Search in sources :

Example 1 with U2FException

use of com.google.u2f.U2FException in project OpenUnison by TremoloSecurity.

the class Registration method doFilter.

@Override
public void doFilter(HttpFilterRequest request, HttpFilterResponse response, HttpFilterChain chain) throws Exception {
    if (request.getMethod().equalsIgnoreCase("GET")) {
        // TODO switch this off
        AuthInfo userData = ((AuthController) request.getSession().getAttribute(ProxyConstants.AUTH_CTL)).getAuthInfo();
        String accountName = userData.getAttribs().get(this.uidAttributeName).getValues().get(0);
        List<SecurityKeyData> keys = U2fUtil.loadUserKeys(userData, challengeStoreAttribute, encyrptionKeyName);
        Set<String> origins = new HashSet<String>();
        String appID = U2fUtil.getApplicationId(request.getServletRequest());
        origins.add(appID);
        U2FServer u2f = new U2FServerUnison(this.challengeGen, new UnisonDataStore(UUID.randomUUID().toString(), keys, (this.requireAttestation ? this.attestationCerts : new HashSet<X509Certificate>())), new BouncyCastleCrypto(), origins, this.requireAttestation);
        RegistrationRequest regRequest = u2f.getRegistrationRequest(accountName, appID);
        request.getSession().setAttribute(Registration.REGISTRATION_REQUEST_JSON, gson.toJson(regRequest));
        request.getSession().setAttribute(Registration.REGISTRATION_REQUEST, regRequest);
        request.getSession().setAttribute(Registration.SERVER, u2f);
        request.setAttribute(REGISTRATION_URI, request.getRequestURL().toString());
        request.getRequestDispatcher(this.challengeURI).forward(request.getServletRequest(), response.getServletResponse());
    } else if (request.getMethod().equalsIgnoreCase("POST")) {
        U2FServer u2f = (U2FServer) request.getSession().getAttribute(SERVER);
        if (logger.isDebugEnabled()) {
            logger.debug("response : '" + request.getParameter("tokenResponse").getValues().get(0) + "'");
        }
        RegistrationResponseHolder rrh = gson.fromJson(request.getParameter("tokenResponse").getValues().get(0), RegistrationResponseHolder.class);
        RegistrationResponse rr = new RegistrationResponse(rrh.getRegistrationData(), rrh.getClientData(), rrh.getClientData());
        try {
            u2f.processRegistrationResponse(rr, System.currentTimeMillis());
        } catch (U2FException e) {
            logger.error("Could not register", e);
            request.setAttribute("register.result", false);
            request.getRequestDispatcher(this.registrationCompleteURI).forward(request.getServletRequest(), response.getServletResponse());
            return;
        }
        AuthInfo userData = ((AuthController) request.getSession().getAttribute(ProxyConstants.AUTH_CTL)).getAuthInfo();
        String encrypted = U2fUtil.encode(u2f.getAllSecurityKeys("doesntmatter"), encyrptionKeyName);
        WFCall wc = new WFCall();
        wc.setName(this.workflowName);
        wc.setUidAttributeName(this.uidAttributeName);
        TremoloUser tu = new TremoloUser();
        tu.setUid(userData.getAttribs().get(this.uidAttributeName).getValues().get(0));
        tu.getAttributes().add(new Attribute(this.uidAttributeName, userData.getAttribs().get(this.uidAttributeName).getValues().get(0)));
        tu.getAttributes().add(new Attribute(this.challengeStoreAttribute, encrypted));
        wc.setUser(tu);
        Map<String, Object> req = new HashMap<String, Object>();
        req.put(ProvisioningParams.UNISON_EXEC_TYPE, ProvisioningParams.UNISON_EXEC_SYNC);
        wc.setRequestParams(req);
        GlobalEntries.getGlobalEntries().getConfigManager().getProvisioningEngine().getWorkFlow(this.workflowName).executeWorkflow(wc);
        request.setAttribute("register.result", true);
        request.getRequestDispatcher(this.registrationCompleteURI).forward(request.getServletRequest(), response.getServletResponse());
    }
}
Also used : AuthInfo(com.tremolosecurity.proxy.auth.AuthInfo) U2FServer(com.google.u2f.server.U2FServer) WFCall(com.tremolosecurity.provisioning.service.util.WFCall) BouncyCastleCrypto(com.google.u2f.server.impl.BouncyCastleCrypto) Attribute(com.tremolosecurity.saml.Attribute) AuthController(com.tremolosecurity.proxy.auth.AuthController) RegistrationRequest(com.google.u2f.server.messages.RegistrationRequest) SecurityKeyData(com.google.u2f.server.data.SecurityKeyData) TremoloUser(com.tremolosecurity.provisioning.service.util.TremoloUser) U2FException(com.google.u2f.U2FException) RegistrationResponse(com.google.u2f.server.messages.RegistrationResponse) HashMap(java.util.HashMap) Map(java.util.Map) HashSet(java.util.HashSet)

Example 2 with U2FException

use of com.google.u2f.U2FException in project OpenUnison by TremoloSecurity.

the class U2FServerUnison method processRegistrationResponse.

@Override
public SecurityKeyData processRegistrationResponse(RegistrationResponse registrationResponse, long currentTimeInMillis) throws U2FException {
    log.debug(">> processRegistrationResponse");
    String sessionId = registrationResponse.getSessionId();
    String clientDataBase64 = registrationResponse.getClientData();
    String rawRegistrationDataBase64 = registrationResponse.getRegistrationData();
    log.debug(">> rawRegistrationDataBase64: " + rawRegistrationDataBase64);
    EnrollSessionData sessionData = dataStore.getEnrollSessionData(sessionId);
    if (sessionData == null) {
        throw new U2FException("Unknown session_id");
    }
    String appId = sessionData.getAppId();
    String clientData = new String(Base64.decodeBase64(clientDataBase64));
    byte[] rawRegistrationData = Base64.decodeBase64(rawRegistrationDataBase64);
    if (log.isDebugEnabled()) {
        log.debug("-- Input --");
        log.debug("  sessionId: " + sessionId);
        log.debug("  challenge: " + Hex.encodeHexString(sessionData.getChallenge()));
        log.debug("  accountName: " + sessionData.getAccountName());
        log.debug("  clientData: " + clientData);
        log.debug("  rawRegistrationData: " + Hex.encodeHexString(rawRegistrationData));
    }
    RegisterResponse registerResponse = RawMessageCodec.decodeRegisterResponse(rawRegistrationData);
    byte[] userPublicKey = registerResponse.getUserPublicKey();
    byte[] keyHandle = registerResponse.getKeyHandle();
    X509Certificate attestationCertificate = registerResponse.getAttestationCertificate();
    byte[] signature = registerResponse.getSignature();
    List<Transports> transports = null;
    try {
        transports = U2fAttestation.Parse(attestationCertificate).getTransports();
    } catch (CertificateParsingException e) {
        log.warn("Could not parse transports extension " + e.getMessage());
    }
    if (log.isDebugEnabled()) {
        log.debug("-- Parsed rawRegistrationResponse --");
        log.debug("  userPublicKey: " + Hex.encodeHexString(userPublicKey));
        log.debug("  keyHandle: " + Hex.encodeHexString(keyHandle));
        log.debug("  attestationCertificate: " + attestationCertificate.toString());
        log.debug("  transports: " + transports);
        try {
            log.debug("  attestationCertificate bytes: " + Hex.encodeHexString(attestationCertificate.getEncoded()));
        } catch (CertificateEncodingException e) {
            throw new U2FException("Cannot encode certificate", e);
        }
        log.debug("  signature: " + Hex.encodeHexString(signature));
    }
    byte[] appIdSha256 = crypto.computeSha256(appId.getBytes());
    byte[] clientDataSha256 = crypto.computeSha256(clientData.getBytes());
    byte[] signedBytes = RawMessageCodec.encodeRegistrationSignedBytes(appIdSha256, clientDataSha256, keyHandle, userPublicKey);
    Set<X509Certificate> trustedCertificates = dataStore.getTrustedCertificates();
    boolean found = false;
    for (X509Certificate trusted : trustedCertificates) {
        try {
            attestationCertificate.verify(trusted.getPublicKey());
            found = true;
        } catch (InvalidKeyException | CertificateException | NoSuchAlgorithmException | NoSuchProviderException | SignatureException e) {
        }
    }
    if (!found) {
        if (!this.requireAttestation) {
            log.warn("attestion cert is not trusted");
        } else {
            throw new U2FException("Attestation certificate is not trusted");
        }
    }
    verifyBrowserData(new JsonParser().parse(clientData), "navigator.id.finishEnrollment", sessionData);
    if (log.isDebugEnabled()) {
        log.debug("Verifying signature of bytes " + Hex.encodeHexString(signedBytes));
    }
    if (!crypto.verifySignature(attestationCertificate, signedBytes, signature)) {
        throw new U2FException("Signature is invalid");
    }
    // The first time we create the SecurityKeyData, we set the counter value to 0.
    // We don't actually know what the counter value of the real device is - but it will
    // be something bigger (or equal) to 0, so subsequent signatures will check out ok.
    SecurityKeyData securityKeyData = new SecurityKeyData(currentTimeInMillis, transports, keyHandle, userPublicKey, attestationCertificate, /* initial counter value */
    0);
    dataStore.addSecurityKeyData(sessionData.getAccountName(), securityKeyData);
    if (log.isDebugEnabled()) {
        log.debug("<< processRegistrationResponse");
    }
    return securityKeyData;
}
Also used : EnrollSessionData(com.google.u2f.server.data.EnrollSessionData) CertificateParsingException(java.security.cert.CertificateParsingException) Transports(com.google.u2f.server.data.SecurityKeyData.Transports) CertificateEncodingException(java.security.cert.CertificateEncodingException) CertificateException(java.security.cert.CertificateException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) SignatureException(java.security.SignatureException) InvalidKeyException(java.security.InvalidKeyException) X509Certificate(java.security.cert.X509Certificate) RegisterResponse(com.google.u2f.key.messages.RegisterResponse) SecurityKeyData(com.google.u2f.server.data.SecurityKeyData) U2FException(com.google.u2f.U2FException) NoSuchProviderException(java.security.NoSuchProviderException) JsonParser(com.google.gson.JsonParser)

Example 3 with U2FException

use of com.google.u2f.U2FException in project OpenUnison by TremoloSecurity.

the class U2fAuth method doGet.

@Override
public void doGet(HttpServletRequest request, HttpServletResponse response, AuthStep as) throws IOException, ServletException {
    if (request.getParameter("signResponse") == null) {
        startAuthentication(request, response, as);
    } else {
        SignResponseHolder srh = gson.fromJson(request.getParameter("signResponse"), SignResponseHolder.class);
        AuthInfo userData = ((AuthController) request.getSession().getAttribute(ProxyConstants.AUTH_CTL)).getAuthInfo();
        // SharedSession.getSharedSession().getSession(req.getSession().getId());
        HttpSession session = ((HttpServletRequest) request).getSession();
        UrlHolder holder = (UrlHolder) request.getAttribute(ProxyConstants.AUTOIDM_CFG);
        RequestHolder reqHolder = ((AuthController) request.getSession().getAttribute(ProxyConstants.AUTH_CTL)).getHolder();
        String urlChain = holder.getUrl().getAuthChain();
        AuthChainType act = holder.getConfig().getAuthChains().get(reqHolder.getAuthChainName());
        AuthMechType amt = act.getAuthMech().get(as.getId());
        HashMap<String, Attribute> authParams = (HashMap<String, Attribute>) session.getAttribute(ProxyConstants.AUTH_MECH_PARAMS);
        String challengeStoreAttribute = authParams.get("attribute").getValues().get(0);
        String encyrptionKeyName = authParams.get("encryptionKeyName").getValues().get(0);
        String uidAttributeName = authParams.get("uidAttributeName").getValues().get(0);
        String workflowName = authParams.get("workflowName").getValues().get(0);
        if (srh.getErrorCode() > 0) {
            logger.warn("Browser could not validate u2f token for user '" + userData.getUserDN() + "' : " + srh.getErrorCode());
            if (amt.getRequired().equals("required")) {
                as.setSuccess(false);
            }
            holder.getConfig().getAuthManager().nextAuth(request, response, session, false);
            return;
        }
        U2FServer u2f = (U2FServer) request.getSession().getAttribute(SERVER);
        SignResponse sigResp = new SignResponse(srh.getKeyHandle(), srh.getSignatureData(), srh.getClientData(), srh.getSessionId());
        try {
            u2f.processSignResponse(sigResp);
        } catch (U2FException e) {
            logger.warn("Could not authenticate user : '" + e.getMessage() + "'");
            if (amt.getRequired().equals("required")) {
                as.setSuccess(false);
            }
            holder.getConfig().getAuthManager().nextAuth(request, response, session, false);
            return;
        }
        String encrypted;
        try {
            encrypted = U2fUtil.encode(u2f.getAllSecurityKeys("doesntmatter"), encyrptionKeyName);
        } catch (Exception e) {
            throw new ServletException("Could not encrypt keys");
        }
        WFCall wc = new WFCall();
        wc.setName(workflowName);
        wc.setUidAttributeName(uidAttributeName);
        TremoloUser tu = new TremoloUser();
        tu.setUid(userData.getAttribs().get(uidAttributeName).getValues().get(0));
        tu.getAttributes().add(new Attribute(uidAttributeName, userData.getAttribs().get(uidAttributeName).getValues().get(0)));
        tu.getAttributes().add(new Attribute(challengeStoreAttribute, encrypted));
        wc.setUser(tu);
        Map<String, Object> req = new HashMap<String, Object>();
        req.put(ProvisioningParams.UNISON_EXEC_TYPE, ProvisioningParams.UNISON_EXEC_SYNC);
        wc.setRequestParams(req);
        try {
            GlobalEntries.getGlobalEntries().getConfigManager().getProvisioningEngine().getWorkFlow(workflowName).executeWorkflow(wc);
        } catch (ProvisioningException e) {
            throw new ServletException("Could not save keys", e);
        }
        as.setSuccess(true);
        holder.getConfig().getAuthManager().nextAuth(request, response, session, false);
    }
}
Also used : AuthInfo(com.tremolosecurity.proxy.auth.AuthInfo) U2FServer(com.google.u2f.server.U2FServer) WFCall(com.tremolosecurity.provisioning.service.util.WFCall) Attribute(com.tremolosecurity.saml.Attribute) HashMap(java.util.HashMap) HttpSession(javax.servlet.http.HttpSession) AuthMechType(com.tremolosecurity.config.xml.AuthMechType) RequestHolder(com.tremolosecurity.proxy.auth.RequestHolder) AuthController(com.tremolosecurity.proxy.auth.AuthController) ServletException(javax.servlet.ServletException) U2FException(com.google.u2f.U2FException) MalformedURLException(java.net.MalformedURLException) ProvisioningException(com.tremolosecurity.provisioning.core.ProvisioningException) IOException(java.io.IOException) HttpServletRequest(javax.servlet.http.HttpServletRequest) UrlHolder(com.tremolosecurity.config.util.UrlHolder) ServletException(javax.servlet.ServletException) SignResponse(com.google.u2f.server.messages.SignResponse) TremoloUser(com.tremolosecurity.provisioning.service.util.TremoloUser) ProvisioningException(com.tremolosecurity.provisioning.core.ProvisioningException) U2FException(com.google.u2f.U2FException) AuthChainType(com.tremolosecurity.config.xml.AuthChainType)

Example 4 with U2FException

use of com.google.u2f.U2FException in project OpenUnison by TremoloSecurity.

the class BouncyCastleCrypto method decodePublicKey.

@Override
public PublicKey decodePublicKey(byte[] encodedPublicKey) throws U2FException {
    try {
        X9ECParameters curve = SECNamedCurves.getByName("secp256r1");
        ECPoint point;
        try {
            point = curve.getCurve().decodePoint(encodedPublicKey);
        } catch (RuntimeException e) {
            throw new U2FException("Couldn't parse user public key", e);
        }
        return KeyFactory.getInstance("ECDSA").generatePublic(new ECPublicKeySpec(point, new ECParameterSpec(curve.getCurve(), curve.getG(), curve.getN(), curve.getH())));
    } catch (InvalidKeySpecException e) {
        throw new U2FException("Error when decoding public key", e);
    } catch (NoSuchAlgorithmException e) {
        throw new U2FException("Error when decoding public key", e);
    }
}
Also used : X9ECParameters(org.bouncycastle.asn1.x9.X9ECParameters) ECParameterSpec(org.bouncycastle.jce.spec.ECParameterSpec) U2FException(com.google.u2f.U2FException) InvalidKeySpecException(java.security.spec.InvalidKeySpecException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) ECPoint(org.bouncycastle.math.ec.ECPoint) ECPublicKeySpec(org.bouncycastle.jce.spec.ECPublicKeySpec)

Example 5 with U2FException

use of com.google.u2f.U2FException in project OpenUnison by TremoloSecurity.

the class U2FServerReferenceImpl method processSignResponse.

@Override
public SecurityKeyData processSignResponse(SignResponse signResponse) throws U2FException {
    Log.info(">> processSignResponse");
    String sessionId = signResponse.getSessionId();
    String browserDataBase64 = signResponse.getClientData();
    String rawSignDataBase64 = signResponse.getSignatureData();
    SignSessionData sessionData = dataStore.getSignSessionData(sessionId);
    if (sessionData == null) {
        throw new U2FException("Unknown session_id");
    }
    String appId = sessionData.getAppId();
    SecurityKeyData securityKeyData = null;
    for (SecurityKeyData temp : dataStore.getSecurityKeyData(sessionData.getAccountName())) {
        if (Arrays.equals(sessionData.getPublicKey(), temp.getPublicKey())) {
            securityKeyData = temp;
            break;
        }
    }
    if (securityKeyData == null) {
        throw new U2FException("No security keys registered for this user");
    }
    String browserData = new String(Base64.decodeBase64(browserDataBase64));
    byte[] rawSignData = Base64.decodeBase64(rawSignDataBase64);
    Log.info("-- Input --");
    Log.info("  sessionId: " + sessionId);
    Log.info("  publicKey: " + Hex.encodeHexString(securityKeyData.getPublicKey()));
    Log.info("  challenge: " + Hex.encodeHexString(sessionData.getChallenge()));
    Log.info("  accountName: " + sessionData.getAccountName());
    Log.info("  browserData: " + browserData);
    Log.info("  rawSignData: " + Hex.encodeHexString(rawSignData));
    verifyBrowserData(new JsonParser().parse(browserData), "navigator.id.getAssertion", sessionData);
    AuthenticateResponse authenticateResponse = RawMessageCodec.decodeAuthenticateResponse(rawSignData);
    byte userPresence = authenticateResponse.getUserPresence();
    int counter = authenticateResponse.getCounter();
    byte[] signature = authenticateResponse.getSignature();
    Log.info("-- Parsed rawSignData --");
    Log.info("  userPresence: " + Integer.toHexString(userPresence & 0xFF));
    Log.info("  counter: " + counter);
    Log.info("  signature: " + Hex.encodeHexString(signature));
    if ((userPresence & UserPresenceVerifier.USER_PRESENT_FLAG) == 0) {
        throw new U2FException("User presence invalid during authentication");
    }
    if (counter <= securityKeyData.getCounter()) {
        throw new U2FException("Counter value smaller than expected!");
    }
    byte[] appIdSha256 = crypto.computeSha256(appId.getBytes());
    byte[] browserDataSha256 = crypto.computeSha256(browserData.getBytes());
    byte[] signedBytes = RawMessageCodec.encodeAuthenticateSignedBytes(appIdSha256, userPresence, counter, browserDataSha256);
    Log.info("Verifying signature of bytes " + Hex.encodeHexString(signedBytes));
    if (!crypto.verifySignature(crypto.decodePublicKey(securityKeyData.getPublicKey()), signedBytes, signature)) {
        throw new U2FException("Signature is invalid");
    }
    dataStore.updateSecurityKeyCounter(sessionData.getAccountName(), securityKeyData.getPublicKey(), counter);
    Log.info("<< processSignResponse");
    return securityKeyData;
}
Also used : SignSessionData(com.google.u2f.server.data.SignSessionData) AuthenticateResponse(com.google.u2f.key.messages.AuthenticateResponse) SecurityKeyData(com.google.u2f.server.data.SecurityKeyData) U2FException(com.google.u2f.U2FException) JsonParser(com.google.gson.JsonParser)

Aggregations

U2FException (com.google.u2f.U2FException)21 SecurityKeyData (com.google.u2f.server.data.SecurityKeyData)6 IOException (java.io.IOException)6 DataInputStream (java.io.DataInputStream)5 JsonParser (com.google.gson.JsonParser)4 RegisterResponse (com.google.u2f.key.messages.RegisterResponse)4 ByteArrayInputStream (java.io.ByteArrayInputStream)4 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)4 X509Certificate (java.security.cert.X509Certificate)4 AuthenticateResponse (com.google.u2f.key.messages.AuthenticateResponse)3 U2FServer (com.google.u2f.server.U2FServer)3 AuthController (com.tremolosecurity.proxy.auth.AuthController)3 AuthInfo (com.tremolosecurity.proxy.auth.AuthInfo)3 Attribute (com.tremolosecurity.saml.Attribute)3 InvalidKeyException (java.security.InvalidKeyException)3 SignatureException (java.security.SignatureException)3 CertificateEncodingException (java.security.cert.CertificateEncodingException)3 HashMap (java.util.HashMap)3 JsonObject (com.google.gson.JsonObject)2 EnrollSessionData (com.google.u2f.server.data.EnrollSessionData)2