use of io.jans.fido2.model.entry.Fido2RegistrationData in project jans by JanssenProject.
the class AppleAssertionFormatProcessor method process.
@Override
public void process(String base64AuthenticatorData, String signature, String clientDataJson, Fido2RegistrationData registration, Fido2AuthenticationData authenticationEntity) {
AuthData authData = authenticatorDataParser.parseAssertionData(base64AuthenticatorData);
commonVerifiers.verifyRpIdHash(authData, registration.getDomain());
log.info("User verification option {}", authenticationEntity.getUserVerificationOption());
userVerificationVerifier.verifyUserVerificationOption(authenticationEntity.getUserVerificationOption(), authData);
byte[] clientDataHash = DigestUtils.getSha256Digest().digest(base64Service.urlDecode(clientDataJson));
try {
int counter = authenticatorDataParser.parseCounter(authData.getCounters());
commonVerifiers.verifyCounter(registration.getCounter(), counter);
registration.setCounter(counter);
JsonNode uncompressedECPointNode = dataMapperService.cborReadTree(base64Service.urlDecode(registration.getUncompressedECPoint()));
PublicKey publicKey = coseService.createUncompressedPointFromCOSEPublicKey(uncompressedECPointNode);
log.info("Uncompressed ECpoint node {}", uncompressedECPointNode.toString());
log.info("EC Public key hex {}", Hex.encodeHexString(publicKey.getEncoded()));
log.info("Signature algorithm: " + registration.getSignatureAlgorithm());
// Note : The signature counter is not implemented and therefore it is always
// zero. Secure Enclave is used to prevent the credential private key from
// leaking instead of a software safeguard.
log.info("Key type / Algorithm : " + authData.getKeyType());
// authData.getKeyType());
authenticatorDataVerifier.verifyAssertionSignature(authData, clientDataHash, signature, publicKey, -7);
} catch (Fido2CompromisedDevice ex) {
throw ex;
} catch (Exception ex) {
throw new Fido2RuntimeException("Failed to check packet assertion", ex);
}
}
use of io.jans.fido2.model.entry.Fido2RegistrationData in project jans by JanssenProject.
the class PackedAssertionFormatProcessor method process.
@Override
public void process(String base64AuthenticatorData, String signature, String clientDataJson, Fido2RegistrationData registration, Fido2AuthenticationData authenticationEntity) {
AuthData authData = authenticatorDataParser.parseAssertionData(base64AuthenticatorData);
commonVerifiers.verifyRpIdHash(authData, registration.getDomain());
log.debug("User verification option {}", authenticationEntity.getUserVerificationOption());
userVerificationVerifier.verifyUserVerificationOption(authenticationEntity.getUserVerificationOption(), authData);
byte[] clientDataHash = DigestUtils.getSha256Digest().digest(base64Service.urlDecode(clientDataJson));
try {
int counter = authenticatorDataParser.parseCounter(authData.getCounters());
commonVerifiers.verifyCounter(registration.getCounter(), counter);
registration.setCounter(counter);
JsonNode uncompressedECPointNode = dataMapperService.cborReadTree(base64Service.urlDecode(registration.getUncompressedECPoint()));
PublicKey publicKey = coseService.createUncompressedPointFromCOSEPublicKey(uncompressedECPointNode);
log.debug("Uncompressed ECpoint node {}", uncompressedECPointNode.toString());
log.debug("EC Public key hex {}", Hex.encodeHexString(publicKey.getEncoded()));
// apple algorithm = -7
// windows hello algorithm is -257
log.debug("registration.getSignatureAlgorithm(): " + registration.getSignatureAlgorithm());
log.debug("Platform authenticator: " + String.valueOf(registration.getAttenstationRequest().contains(AuthenticatorAttachment.PLATFORM.getAttachment()) ? -7 : registration.getSignatureAlgorithm()));
authenticatorDataVerifier.verifyAssertionSignature(authData, clientDataHash, signature, publicKey, registration.getAttenstationRequest().contains(AuthenticatorAttachment.PLATFORM.getAttachment()) ? -7 : registration.getSignatureAlgorithm());
} catch (Fido2CompromisedDevice ex) {
throw ex;
} catch (Exception ex) {
throw new Fido2RuntimeException("Failed to check packet assertion", ex);
}
}
use of io.jans.fido2.model.entry.Fido2RegistrationData in project jans by JanssenProject.
the class AppleAttestationProcessor method process.
// @Override
public void process(JsonNode attStmt, AuthData authData, Fido2RegistrationData credential, byte[] clientDataHash, CredAndCounterData credIdAndCounters) {
log.info("AttStmt: " + attStmt.asText());
// Check attStmt and it contains “x5c” then its a FULL attestation.
if (attStmt.hasNonNull("x5c")) {
// 1. Verify |x5c| is a valid certificate chain starting from the |credCert|
// (the first certificate in x5c) to
// the Apple WebAuthn root certificate.
Iterator<JsonNode> i = attStmt.get("x5c").elements();
List<X509Certificate> certificates = new ArrayList<X509Certificate>();
while (i.hasNext()) {
String c = i.next().asText();
X509Certificate cert = certificateService.getCertificate(c);
certificates.add(cert);
}
// the first certificate in x5c
X509Certificate credCert = certificates.get(0);
List<X509Certificate> trustAnchorCertificates = new ArrayList<X509Certificate>();
trustAnchorCertificates.addAll(certificateService.getCertificates(APPLE_WEBAUTHN_ROOT_CA));
try {
log.debug("APPLE_WEBAUTHN_ROOT_CA root certificate" + trustAnchorCertificates.size());
X509Certificate verifiedCert = certificateVerifier.verifyAttestationCertificates(certificates, trustAnchorCertificates);
log.info("Step 1 completed ");
} catch (Fido2MissingAttestationCertException ex) {
X509Certificate certificate = certificates.get(0);
String issuerDN = certificate.getIssuerDN().getName();
log.warn("Failed to find attestation validation signature public certificate with DN: '{}'", issuerDN);
}
// 2. Concatenate |authenticatorData| and |clientDataHash| to form
// |nonceToHash|.
byte[] authDataInBytes = authData.getAuthDataDecoded();
// byte[] nonceToHash = new byte[authDataInBytes.length +
// clientDataHash.length];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
baos.write(authDataInBytes);
baos.write(clientDataHash);
} catch (IOException e) {
throw new AttestationException("Concatenate |authenticatorData| and |clientDataHash| to form |nonceToHash|." + e.getMessage());
}
byte[] nonceToHash = baos.toByteArray();
log.info("Step 2 completed");
// 3. Perform SHA-256 hash of |nonceToHash| to produce |nonce|.
byte[] nonce = DigestUtils.getSha256Digest().digest(nonceToHash);
log.info("Step 3 completed");
// 4. Verify |nonce| matches the value of the extension with OID (
// 1.2.840.113635.100.8.2 ) in |credCert|.
byte[] attestationChallenge = getExtension(credCert);
if (!Arrays.equals(nonce, attestationChallenge)) {
throw new AttestationException("Certificate 1.2.840.113635.100.8.2 extension does not match nonce");
} else
log.info("Step 4 completed");
// 5. Verify credential public key matches the Subject Public Key of
// |credCert|.
PublicKey publicKeyAuthData = coseService.getPublicKeyFromUncompressedECPoint(authData.getCosePublicKey());
PublicKey publicKeyCredCert = credCert.getPublicKey();
if (!publicKeyAuthData.equals(publicKeyCredCert)) {
throw new AttestationException("The public key in the first certificate in x5c doesn't matches the credentialPublicKey in the attestedCredentialData in authenticatorData.");
} else {
log.info("Step 5 completed");
}
// this is Gluu implementation specific where setUncompressedEcPoint is saved in
// LDAP registrationData and read during assertion
credIdAndCounters.setAttestationType(getAttestationFormat().getFmt());
credIdAndCounters.setCredId(base64Service.urlEncodeToString(authData.getCredId()));
credIdAndCounters.setUncompressedEcPoint(base64Service.urlEncodeToString(authData.getCosePublicKey()));
// log.info("attStmt.get(\"alg\")"+attStmt.get("alg"));
// commonVerifiers.verifyAlgorithm(attStmt.get("alg"), authData.getKeyType());
int alg = -7;
credIdAndCounters.setSignatureAlgorithm(alg);
}
}
use of io.jans.fido2.model.entry.Fido2RegistrationData in project jans by JanssenProject.
the class AssertionVerifier method verifyAuthenticatorAssertionResponse.
public void verifyAuthenticatorAssertionResponse(JsonNode response, Fido2RegistrationData registration, Fido2AuthenticationData authenticationEntity) {
if (!(response.hasNonNull("authenticatorData") && response.hasNonNull("clientDataJSON") && response.hasNonNull("signature"))) {
throw new Fido2RuntimeException("Authenticator data is invalid");
}
String base64AuthenticatorData = response.get("authenticatorData").asText();
String clientDataJson = response.get("clientDataJSON").asText();
String signature = response.get("signature").asText();
log.debug("Authenticator data {}", base64AuthenticatorData);
AssertionFormatProcessor assertionProcessor = assertionProcessorFactory.getCommandProcessor(registration.getAttestationType());
assertionProcessor.process(base64AuthenticatorData, signature, clientDataJson, registration, authenticationEntity);
}
use of io.jans.fido2.model.entry.Fido2RegistrationData in project jans by JanssenProject.
the class TPMProcessor method process.
@Override
public void process(JsonNode attStmt, AuthData authData, Fido2RegistrationData credential, byte[] clientDataHash, CredAndCounterData credIdAndCounters) {
JsonNode cborPublicKey;
try {
cborPublicKey = dataMapperService.cborReadTree(authData.getCosePublicKey());
} catch (IOException e) {
throw new Fido2RuntimeException("Problem with TPM attestation");
}
byte[] hashedBuffer = getHashedBuffer(cborPublicKey.get("3").asInt(), authData.getAttestationBuffer(), clientDataHash);
byte[] keyBufferFromAuthData = base64Service.decode(cborPublicKey.get("-1").asText());
Iterator<JsonNode> i = attStmt.get("x5c").elements();
String pubArea = attStmt.get("pubArea").asText();
String certInfo = attStmt.get("certInfo").asText();
if (i.hasNext()) {
ArrayList<String> aikCertificatePath = new ArrayList<String>();
aikCertificatePath.add(i.next().asText());
ArrayList<String> certificatePath = new ArrayList<String>();
while (i.hasNext()) {
certificatePath.add(i.next().asText());
}
List<X509Certificate> certificates = certificateService.getCertificates(certificatePath);
List<X509Certificate> aikCertificates = certificateService.getCertificates(aikCertificatePath);
List<X509Certificate> trustAnchorCertificates = attestationCertificateService.getAttestationRootCertificates(authData, aikCertificates);
X509Certificate verifiedCert = certificateVerifier.verifyAttestationCertificates(certificates, trustAnchorCertificates);
X509Certificate aikCertificate = aikCertificates.get(0);
verifyTPMCertificateExtenstion(aikCertificate, authData);
verifyAIKCertificate(aikCertificate, verifiedCert);
String signature = commonVerifiers.verifyBase64String(attStmt.get("sig"));
byte[] certInfoBuffer = base64Service.decode(certInfo);
byte[] signatureBytes = base64Service.decode(signature.getBytes());
signatureVerifier.verifySignature(signatureBytes, certInfoBuffer, aikCertificate, authData.getKeyType());
byte[] pubAreaBuffer = base64Service.decode(pubArea);
TPMT_PUBLIC tpmtPublic = TPMT_PUBLIC.fromTpm(pubAreaBuffer);
TPMS_ATTEST tpmsAttest = TPMS_ATTEST.fromTpm(certInfoBuffer);
verifyMagicInTpms(tpmsAttest);
verifyTPMSCertificateName(tpmtPublic, tpmsAttest, pubAreaBuffer);
verifyTPMSExtraData(hashedBuffer, tpmsAttest.extraData);
verifyThatKeysAreSame(tpmtPublic, keyBufferFromAuthData);
} else {
throw new Fido2RuntimeException("Problem with TPM attestation. Unsupported");
}
}
Aggregations