Search in sources :

Example 6 with SecurityKeyData

use of com.google.u2f.server.data.SecurityKeyData in project OpenUnison by TremoloSecurity.

the class U2fUtil method loadUserKeys.

public static List<SecurityKeyData> loadUserKeys(AuthInfo userData, String challengeStoreAttribute, String encyrptionKeyName) throws Exception, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
    Attribute challengeAttr = userData.getAttribs().get(challengeStoreAttribute);
    Type t = new TypeToken<List<KeyHolder>>() {
    }.getType();
    ArrayList<SecurityKeyData> devices = new ArrayList<SecurityKeyData>();
    if (challengeAttr != null) {
        SecretKey key = GlobalEntries.getGlobalEntries().getConfigManager().getSecretKey(encyrptionKeyName);
        if (key == null) {
            throw new Exception("Queue message encryption key not found");
        }
        EncryptedMessage msg = gson.fromJson(inflate(challengeAttr.getValues().get(0)), EncryptedMessage.class);
        IvParameterSpec spec = new IvParameterSpec(msg.getIv());
        Cipher cipher;
        cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, key, spec);
        byte[] bytes = cipher.doFinal(msg.getMsg());
        String json = new String(bytes);
        java.util.List<KeyHolder> fromJSON = gson.fromJson(json, t);
        for (KeyHolder kh : fromJSON) {
            devices.add(new SecurityKeyData(kh.getEnrollmentTime(), kh.getKeyHandle(), kh.getPublicKey(), null, kh.getCounter()));
        }
    }
    return devices;
}
Also used : Attribute(com.tremolosecurity.saml.Attribute) ArrayList(java.util.ArrayList) KeyHolder(com.tremolosecurity.unison.google.u2f.KeyHolder) InvalidAlgorithmParameterException(java.security.InvalidAlgorithmParameterException) NoSuchPaddingException(javax.crypto.NoSuchPaddingException) MalformedURLException(java.net.MalformedURLException) IllegalBlockSizeException(javax.crypto.IllegalBlockSizeException) IOException(java.io.IOException) BadPaddingException(javax.crypto.BadPaddingException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) InvalidKeyException(java.security.InvalidKeyException) Type(java.lang.reflect.Type) SecretKey(javax.crypto.SecretKey) SecurityKeyData(com.google.u2f.server.data.SecurityKeyData) EncryptedMessage(com.tremolosecurity.provisioning.util.EncryptedMessage) ArrayList(java.util.ArrayList) List(java.util.List) IvParameterSpec(javax.crypto.spec.IvParameterSpec) Cipher(javax.crypto.Cipher)

Example 7 with SecurityKeyData

use of com.google.u2f.server.data.SecurityKeyData in project OpenUnison by TremoloSecurity.

the class U2fUtil method encode.

public static String encode(List<SecurityKeyData> devices, String encyrptionKeyName) throws Exception {
    ArrayList<KeyHolder> keys = new ArrayList<KeyHolder>();
    for (SecurityKeyData dr : devices) {
        KeyHolder kh = new KeyHolder();
        kh.setCounter(dr.getCounter());
        kh.setEnrollmentTime(dr.getEnrollmentTime());
        kh.setKeyHandle(dr.getKeyHandle());
        kh.setPublicKey(dr.getPublicKey());
        kh.setTransports(dr.getTransports());
        keys.add(kh);
    }
    String json = gson.toJson(keys);
    EncryptedMessage msg = new EncryptedMessage();
    SecretKey key = GlobalEntries.getGlobalEntries().getConfigManager().getSecretKey(encyrptionKeyName);
    if (key == null) {
        throw new Exception("Queue message encryption key not found");
    }
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipher.init(Cipher.ENCRYPT_MODE, key);
    msg.setMsg(cipher.doFinal(json.getBytes("UTF-8")));
    msg.setIv(cipher.getIV());
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    DeflaterOutputStream compressor = new DeflaterOutputStream(baos, new Deflater(Deflater.BEST_COMPRESSION, true));
    compressor.write(gson.toJson(msg).getBytes("UTF-8"));
    compressor.flush();
    compressor.close();
    String b64 = new String(Base64.encodeBase64(baos.toByteArray()));
    return b64;
}
Also used : SecretKey(javax.crypto.SecretKey) SecurityKeyData(com.google.u2f.server.data.SecurityKeyData) Deflater(java.util.zip.Deflater) ArrayList(java.util.ArrayList) EncryptedMessage(com.tremolosecurity.provisioning.util.EncryptedMessage) DeflaterOutputStream(java.util.zip.DeflaterOutputStream) KeyHolder(com.tremolosecurity.unison.google.u2f.KeyHolder) Cipher(javax.crypto.Cipher) ByteArrayOutputStream(java.io.ByteArrayOutputStream) InvalidAlgorithmParameterException(java.security.InvalidAlgorithmParameterException) NoSuchPaddingException(javax.crypto.NoSuchPaddingException) MalformedURLException(java.net.MalformedURLException) IllegalBlockSizeException(javax.crypto.IllegalBlockSizeException) IOException(java.io.IOException) BadPaddingException(javax.crypto.BadPaddingException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) InvalidKeyException(java.security.InvalidKeyException)

Example 8 with SecurityKeyData

use of com.google.u2f.server.data.SecurityKeyData in project OpenUnison by TremoloSecurity.

the class U2FServerUnison method processSignResponse.

@Override
public SecurityKeyData processSignResponse(SignResponse signResponse) throws U2FException {
    if (log.isDebugEnabled()) {
        log.debug(">> 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);
    if (log.isDebugEnabled()) {
        log.debug("-- Input --");
        log.debug("  sessionId: " + sessionId);
        log.debug("  publicKey: " + Hex.encodeHexString(securityKeyData.getPublicKey()));
        log.debug("  challenge: " + Hex.encodeHexString(sessionData.getChallenge()));
        log.debug("  accountName: " + sessionData.getAccountName());
        log.debug("  browserData: " + browserData);
        log.debug("  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();
    if (log.isDebugEnabled()) {
        log.debug("-- Parsed rawSignData --");
        log.debug("  userPresence: " + Integer.toHexString(userPresence & 0xFF));
        log.debug("  counter: " + counter);
        log.debug("  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);
    if (log.isDebugEnabled()) {
        log.debug("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);
    if (log.isDebugEnabled()) {
        log.debug("<< 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)

Example 9 with SecurityKeyData

use of com.google.u2f.server.data.SecurityKeyData in project OpenUnison by TremoloSecurity.

the class U2fAuth method startAuthentication.

private void startAuthentication(HttpServletRequest request, HttpServletResponse response, AuthStep as) throws ServletException, MalformedURLException, IOException {
    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 formURI = authParams.get("formURI").getValues().get(0);
    List<SecurityKeyData> keys;
    try {
        keys = U2fUtil.loadUserKeys(userData, challengeStoreAttribute, encyrptionKeyName);
    } catch (Exception e1) {
        throw new ServletException("Could not loak keys", e1);
    }
    Set<String> origins = new HashSet<String>();
    String appID = U2fUtil.getApplicationId(request);
    origins.add(appID);
    U2FServer u2f = new U2FServerUnison(this.challengeGen, new UnisonDataStore(UUID.randomUUID().toString(), keys), new BouncyCastleCrypto(), origins);
    String uid = userData.getAttribs().get(uidAttributeName).getValues().get(0);
    if (keys == null || keys.size() == 0) {
        if (amt.getRequired().equals("required")) {
            as.setSuccess(false);
        }
        holder.getConfig().getAuthManager().nextAuth(request, response, session, false);
        return;
    }
    U2fSignRequest sigReq = null;
    try {
        sigReq = u2f.getSignRequest(uid, appID);
    } catch (U2FException e) {
        logger.error("Could not start authentication", e);
        if (amt.getRequired().equals("required")) {
            as.setSuccess(false);
        }
        holder.getConfig().getAuthManager().nextAuth(request, response, session, false);
        return;
    }
    Gson gson = new Gson();
    request.getSession().setAttribute(AUTH_SIGN_REQ, sigReq);
    request.getSession().setAttribute(AUTH_SIGN_REQ_JSON, gson.toJson(sigReq));
    request.getSession().setAttribute(SERVER, u2f);
    response.sendRedirect(formURI);
}
Also used : U2FServer(com.google.u2f.server.U2FServer) BouncyCastleCrypto(com.google.u2f.server.impl.BouncyCastleCrypto) Attribute(com.tremolosecurity.saml.Attribute) HashMap(java.util.HashMap) Gson(com.google.gson.Gson) RequestHolder(com.tremolosecurity.proxy.auth.RequestHolder) HttpServletRequest(javax.servlet.http.HttpServletRequest) UrlHolder(com.tremolosecurity.config.util.UrlHolder) ServletException(javax.servlet.ServletException) U2fSignRequest(com.google.u2f.server.messages.U2fSignRequest) SecurityKeyData(com.google.u2f.server.data.SecurityKeyData) U2FException(com.google.u2f.U2FException) AuthChainType(com.tremolosecurity.config.xml.AuthChainType) HashSet(java.util.HashSet) AuthInfo(com.tremolosecurity.proxy.auth.AuthInfo) HttpSession(javax.servlet.http.HttpSession) AuthMechType(com.tremolosecurity.config.xml.AuthMechType) 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)

Example 10 with SecurityKeyData

use of com.google.u2f.server.data.SecurityKeyData in project OpenUnison by TremoloSecurity.

the class U2FServerReferenceImpl method processRegistrationResponse.

@Override
public SecurityKeyData processRegistrationResponse(RegistrationResponse registrationResponse, long currentTimeInMillis) throws U2FException {
    Log.info(">> processRegistrationResponse");
    String sessionId = registrationResponse.getSessionId();
    String clientDataBase64 = registrationResponse.getClientData();
    String rawRegistrationDataBase64 = registrationResponse.getRegistrationData();
    Log.info(">> 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);
    Log.info("-- Input --");
    Log.info("  sessionId: " + sessionId);
    Log.info("  challenge: " + Hex.encodeHexString(sessionData.getChallenge()));
    Log.info("  accountName: " + sessionData.getAccountName());
    Log.info("  clientData: " + clientData);
    Log.info("  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.warning("Could not parse transports extension " + e.getMessage());
    }
    Log.info("-- Parsed rawRegistrationResponse --");
    Log.info("  userPublicKey: " + Hex.encodeHexString(userPublicKey));
    Log.info("  keyHandle: " + Hex.encodeHexString(keyHandle));
    Log.info("  attestationCertificate: " + attestationCertificate.toString());
    Log.info("  transports: " + transports);
    try {
        Log.info("  attestationCertificate bytes: " + Hex.encodeHexString(attestationCertificate.getEncoded()));
    } catch (CertificateEncodingException e) {
        throw new U2FException("Cannot encode certificate", e);
    }
    Log.info("  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();
    if (!trustedCertificates.contains(attestationCertificate)) {
        Log.warning("attestion cert is not trusted");
    }
    verifyBrowserData(new JsonParser().parse(clientData), "navigator.id.finishEnrollment", sessionData);
    Log.info("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);
    Log.info("<< 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) X509Certificate(java.security.cert.X509Certificate) RegisterResponse(com.google.u2f.key.messages.RegisterResponse) SecurityKeyData(com.google.u2f.server.data.SecurityKeyData) U2FException(com.google.u2f.U2FException) JsonParser(com.google.gson.JsonParser)

Aggregations

SecurityKeyData (com.google.u2f.server.data.SecurityKeyData)10 U2FException (com.google.u2f.U2FException)6 JsonParser (com.google.gson.JsonParser)4 Transports (com.google.u2f.server.data.SecurityKeyData.Transports)4 SignSessionData (com.google.u2f.server.data.SignSessionData)4 U2fSignRequest (com.google.u2f.server.messages.U2fSignRequest)3 Attribute (com.tremolosecurity.saml.Attribute)3 IOException (java.io.IOException)3 MalformedURLException (java.net.MalformedURLException)3 InvalidKeyException (java.security.InvalidKeyException)3 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)3 ImmutableList (com.google.common.collect.ImmutableList)2 AuthenticateResponse (com.google.u2f.key.messages.AuthenticateResponse)2 RegisterResponse (com.google.u2f.key.messages.RegisterResponse)2 U2FServer (com.google.u2f.server.U2FServer)2 EnrollSessionData (com.google.u2f.server.data.EnrollSessionData)2 BouncyCastleCrypto (com.google.u2f.server.impl.BouncyCastleCrypto)2 RegisteredKey (com.google.u2f.server.messages.RegisteredKey)2 EncryptedMessage (com.tremolosecurity.provisioning.util.EncryptedMessage)2 AuthController (com.tremolosecurity.proxy.auth.AuthController)2