use of com.webauthn4j.validator.exception.BadAttestationStatementException in project webauthn4j by webauthn4j.
the class FidoMdsMetadataValidator method validate.
@Override
public void validate(RegistrationObject registrationObject) {
AssertUtil.notNull(registrationObject.getAttestationObject().getAuthenticatorData(), "authenticatorData must not be null");
AssertUtil.notNull(registrationObject.getAttestationObject().getAuthenticatorData().getAttestedCredentialData(), "attestedCredentialData must not be null");
AAGUID aaguid = registrationObject.getAttestationObject().getAuthenticatorData().getAttestedCredentialData().getAaguid();
AttestationStatement attestationStatement = registrationObject.getAttestationObject().getAttestationStatement();
Set<MetadataItem> metadataItems = metadataItemsResolver.resolve(aaguid);
List<AuthenticatorAttestationType> authenticatorAttestationTypes = metadataItems.stream().flatMap(item -> item.getMetadataStatement().getAttestationTypes().stream()).collect(Collectors.toList());
boolean isSurrogate = !authenticatorAttestationTypes.isEmpty() && authenticatorAttestationTypes.stream().allMatch(type -> type.equals(AuthenticatorAttestationType.BASIC_SURROGATE));
if (isSurrogate && attestationStatement instanceof CertificateBaseAttestationStatement) {
CertificateBaseAttestationStatement certificateBaseAttestationStatement = (CertificateBaseAttestationStatement) attestationStatement;
if (certificateBaseAttestationStatement.getX5c() != null) {
throw new BadAttestationStatementException("Although AAGUID is registered for surrogate attestation in metadata, x5c contains certificates.");
}
}
for (MetadataItem metadataItem : metadataItems) {
doAdditionalValidationForFidoMdsMetadataItem(metadataItem);
}
}
use of com.webauthn4j.validator.exception.BadAttestationStatementException in project webauthn4j by webauthn4j.
the class AppleAppAttestAttestationStatementValidator method validatePublicKey.
private void validatePublicKey(CoreRegistrationObject registrationObject) {
byte[] publicKey = ECUtil.createUncompressedPublicKey((ECPublicKey) getAttestationStatement(registrationObject).getX5c().getEndEntityAttestationCertificate().getCertificate().getPublicKey());
DCRegistrationObject dcRegistrationObject = (DCRegistrationObject) registrationObject;
byte[] keyId = dcRegistrationObject.getKeyId();
// there is no need to prevent timing attack and it is OK to use `Arrays.equals` instead of `MessageDigest.isEqual` here.
if (!Arrays.equals(MessageDigestUtil.createSHA256().digest(publicKey), keyId)) {
throw new BadAttestationStatementException("key identifier doesn't match SHA-256 of the publickey");
}
}
use of com.webauthn4j.validator.exception.BadAttestationStatementException in project webauthn4j by webauthn4j.
the class AppleAppAttestAttestationStatementValidator method validateNonce.
private void validateNonce(CoreRegistrationObject registrationObject) {
AppleAppAttestAttestationStatement attestationStatement = getAttestationStatement(registrationObject);
X509Certificate attestationCertificate = attestationStatement.getX5c().getEndEntityAttestationCertificate().getCertificate();
byte[] actualNonce = extractNonce(attestationCertificate);
byte[] clientDataHash = registrationObject.getClientDataHash();
byte[] authenticatorData = registrationObject.getAuthenticatorDataBytes();
byte[] composite = ByteBuffer.allocate(authenticatorData.length + clientDataHash.length).put(authenticatorData).put(clientDataHash).array();
byte[] expectedNonce = MessageDigestUtil.createSHA256().digest(composite);
// As nonce is known data to client side(potential attacker), there is no risk of timing attack and it is OK to use `Arrays.equals` instead of `MessageDigest.isEqual`
if (!Arrays.equals(actualNonce, expectedNonce)) {
throw new BadAttestationStatementException("App Attest nonce doesn't match.");
}
}
use of com.webauthn4j.validator.exception.BadAttestationStatementException in project webauthn4j by webauthn4j.
the class TPMAttestationStatementValidator method validatePublicKeyEquality.
private void validatePublicKeyEquality(TPMTPublic pubArea, AuthenticatorData<RegistrationExtensionAuthenticatorOutput> authenticatorData) {
// noinspection ConstantConditions as null check is already done in caller
PublicKey publicKeyInAuthData = authenticatorData.getAttestedCredentialData().getCOSEKey().getPublicKey();
TPMUPublicId publicKeyInPubArea = pubArea.getUnique();
if (pubArea.getType() == TPMIAlgPublic.TPM_ALG_RSA && publicKeyInPubArea instanceof RSAUnique) {
RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKeyInAuthData;
TPMSRSAParms parms = (TPMSRSAParms) pubArea.getParameters();
RSAUnique rsaUnique = (RSAUnique) publicKeyInPubArea;
long exponent = UnsignedNumberUtil.getUnsignedInt(parms.getExponent());
if (exponent == 0) {
// 2^16 + 1
exponent = 65537;
}
// noinspection ConstantConditions as null check is already done in caller
if (rsaPublicKey.getModulus().equals(new BigInteger(1, rsaUnique.getN())) && rsaPublicKey.getPublicExponent().equals(BigInteger.valueOf(exponent))) {
return;
}
} else if (pubArea.getType() == TPMIAlgPublic.TPM_ALG_ECDSA && publicKeyInPubArea instanceof ECCUnique) {
ECPublicKey ecPublicKey = (ECPublicKey) publicKeyInAuthData;
TPMSECCParms parms = (TPMSECCParms) pubArea.getParameters();
EllipticCurve curveInParms = parms.getCurveId().getEllipticCurve();
ECCUnique eccUnique = (ECCUnique) publicKeyInPubArea;
// noinspection ConstantConditions as null check is already done in caller
if (ecPublicKey.getParams().getCurve().equals(curveInParms) && ecPublicKey.getW().getAffineX().equals(new BigInteger(1, eccUnique.getX())) && ecPublicKey.getW().getAffineY().equals(new BigInteger(1, eccUnique.getY()))) {
return;
}
}
throw new BadAttestationStatementException("publicKey in authData and publicKey in unique pubArea doesn't match");
}
use of com.webauthn4j.validator.exception.BadAttestationStatementException in project webauthn4j by webauthn4j.
the class TPMAttestationStatementValidator method validateSubjectAlternativeName.
private void validateSubjectAlternativeName(X509Certificate certificate) throws CertificateParsingException {
try {
for (List<?> entry : certificate.getSubjectAlternativeNames()) {
if (entry.get(0).equals(4)) {
TPMDeviceProperty tpmDeviceProperty = parseTPMDeviceProperty((String) entry.get(1));
tpmDevicePropertyValidator.validate(tpmDeviceProperty);
return;
}
}
} catch (IOException | RuntimeException e) {
throw new BadAttestationStatementException("The Subject Alternative Name extension of attestation certificate does not contain a TPM device property", e);
}
throw new BadAttestationStatementException("The Subject Alternative Name extension of attestation certificate does not contain a TPM device property");
}
Aggregations