Search in sources :

Example 1 with RegisterResponse

use of com.google.u2f.key.messages.RegisterResponse 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 2 with RegisterResponse

use of com.google.u2f.key.messages.RegisterResponse in project OpenUnison by TremoloSecurity.

the class RawMessageCodec method decodeRegisterResponse.

public static RegisterResponse decodeRegisterResponse(byte[] data) throws U2FException {
    try {
        DataInputStream inputStream = new DataInputStream(new ByteArrayInputStream(data));
        byte reservedByte = inputStream.readByte();
        byte[] userPublicKey = new byte[65];
        inputStream.readFully(userPublicKey);
        byte[] keyHandle = new byte[inputStream.readUnsignedByte()];
        inputStream.readFully(keyHandle);
        X509Certificate attestationCertificate = (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(inputStream);
        byte[] signature = new byte[inputStream.available()];
        inputStream.readFully(signature);
        if (inputStream.available() != 0) {
            throw new U2FException("Message ends with unexpected data");
        }
        if (reservedByte != REGISTRATION_RESERVED_BYTE_VALUE) {
            throw new U2FException(String.format("Incorrect value of reserved byte. Expected: %d. Was: %d", REGISTRATION_RESERVED_BYTE_VALUE, reservedByte));
        }
        return new RegisterResponse(userPublicKey, keyHandle, attestationCertificate, signature);
    } catch (IOException e) {
        throw new U2FException("Error when parsing raw RegisterResponse", e);
    } catch (CertificateException e) {
        throw new U2FException("Error when parsing attestation certificate", e);
    }
}
Also used : RegisterResponse(com.google.u2f.key.messages.RegisterResponse) ByteArrayInputStream(java.io.ByteArrayInputStream) CertificateException(java.security.cert.CertificateException) U2FException(com.google.u2f.U2FException) IOException(java.io.IOException) DataInputStream(java.io.DataInputStream) X509Certificate(java.security.cert.X509Certificate)

Example 3 with RegisterResponse

use of com.google.u2f.key.messages.RegisterResponse in project OpenUnison by TremoloSecurity.

the class U2FKeyReferenceImpl method register.

@Override
public RegisterResponse register(RegisterRequest registerRequest) throws U2FException {
    Log.info(">> register");
    byte[] applicationSha256 = registerRequest.getApplicationSha256();
    byte[] challengeSha256 = registerRequest.getChallengeSha256();
    Log.info(" -- Inputs --");
    Log.info("  applicationSha256: " + Hex.encodeHexString(applicationSha256));
    Log.info("  challengeSha256: " + Hex.encodeHexString(challengeSha256));
    byte userPresent = userPresenceVerifier.verifyUserPresence();
    if ((userPresent & UserPresenceVerifier.USER_PRESENT_FLAG) == 0) {
        throw new U2FException("Cannot verify user presence");
    }
    KeyPair keyPair = keyPairGenerator.generateKeyPair(applicationSha256, challengeSha256);
    byte[] keyHandle = keyHandleGenerator.generateKeyHandle(applicationSha256, keyPair);
    dataStore.storeKeyPair(keyHandle, keyPair);
    byte[] userPublicKey = keyPairGenerator.encodePublicKey(keyPair.getPublic());
    byte[] signedData = RawMessageCodec.encodeRegistrationSignedBytes(applicationSha256, challengeSha256, keyHandle, userPublicKey);
    Log.info("Signing bytes " + Hex.encodeHexString(signedData));
    byte[] signature = crypto.sign(signedData, certificatePrivateKey);
    Log.info(" -- Outputs --");
    Log.info("  userPublicKey: " + Hex.encodeHexString(userPublicKey));
    Log.info("  keyHandle: " + Hex.encodeHexString(keyHandle));
    Log.info("  vendorCertificate: " + vendorCertificate);
    Log.info("  signature: " + Hex.encodeHexString(signature));
    Log.info("<< register");
    return new RegisterResponse(userPublicKey, keyHandle, vendorCertificate, signature);
}
Also used : KeyPair(java.security.KeyPair) RegisterResponse(com.google.u2f.key.messages.RegisterResponse) U2FException(com.google.u2f.U2FException)

Example 4 with RegisterResponse

use of com.google.u2f.key.messages.RegisterResponse 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

U2FException (com.google.u2f.U2FException)4 RegisterResponse (com.google.u2f.key.messages.RegisterResponse)4 X509Certificate (java.security.cert.X509Certificate)3 JsonParser (com.google.gson.JsonParser)2 EnrollSessionData (com.google.u2f.server.data.EnrollSessionData)2 SecurityKeyData (com.google.u2f.server.data.SecurityKeyData)2 Transports (com.google.u2f.server.data.SecurityKeyData.Transports)2 CertificateEncodingException (java.security.cert.CertificateEncodingException)2 CertificateException (java.security.cert.CertificateException)2 CertificateParsingException (java.security.cert.CertificateParsingException)2 ByteArrayInputStream (java.io.ByteArrayInputStream)1 DataInputStream (java.io.DataInputStream)1 IOException (java.io.IOException)1 InvalidKeyException (java.security.InvalidKeyException)1 KeyPair (java.security.KeyPair)1 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)1 NoSuchProviderException (java.security.NoSuchProviderException)1 SignatureException (java.security.SignatureException)1