diff options
5 files changed, 27 insertions, 5 deletions
diff --git a/packages/server/src/attestation/verifications/verifyAndroidSafetyNet.test.ts b/packages/server/src/attestation/verifications/verifyAndroidSafetyNet.test.ts index ea16b1d..b910cd0 100644 --- a/packages/server/src/attestation/verifications/verifyAndroidSafetyNet.test.ts +++ b/packages/server/src/attestation/verifications/verifyAndroidSafetyNet.test.ts @@ -7,6 +7,11 @@ import decodeAttestationObject, { } from '../../helpers/decodeAttestationObject'; import parseAuthenticatorData from '../../helpers/parseAuthenticatorData'; import toHash from '../../helpers/toHash'; +import settingsService from '../../services/settingsService'; + +const rootCertificate = settingsService.getRootCertificate({ + attestationFormat: 'android-safetynet', +}); let authData: Buffer; let attStmt: AttestationStatement; @@ -36,6 +41,7 @@ test('should verify Android SafetyNet attestation', async () => { clientDataHash, verifyTimestampMS: false, aaguid, + rootCertificate, }); expect(verified).toEqual(true); @@ -48,6 +54,7 @@ test('should throw error when timestamp is not within one minute of now', async authData, clientDataHash, aaguid, + rootCertificate, }), ).rejects.toThrow(/has expired/i); }); diff --git a/packages/server/src/attestation/verifications/verifyAndroidSafetyNet.ts b/packages/server/src/attestation/verifications/verifyAndroidSafetyNet.ts index 3c4522c..0ab7524 100644 --- a/packages/server/src/attestation/verifications/verifyAndroidSafetyNet.ts +++ b/packages/server/src/attestation/verifications/verifyAndroidSafetyNet.ts @@ -15,6 +15,7 @@ type Options = { clientDataHash: Buffer; authData: Buffer; aaguid: Buffer; + rootCertificate: string; verifyTimestampMS?: boolean; }; @@ -24,7 +25,14 @@ type Options = { export default async function verifyAttestationAndroidSafetyNet( options: Options, ): Promise<boolean> { - const { attStmt, clientDataHash, authData, aaguid, verifyTimestampMS = true } = options; + const { + attStmt, + clientDataHash, + authData, + aaguid, + rootCertificate, + verifyTimestampMS = true, + } = options; const { response, ver } = attStmt; if (!ver) { @@ -103,7 +111,8 @@ export default async function verifyAttestationAndroidSafetyNet( } } else { // Validate certificate path using a fixed global root cert - const path = HEADER.x5c.concat([GlobalSignRootCAR2]).map(convertCertBufferToPEM); + const path = HEADER.x5c.map(convertCertBufferToPEM); + path.push(rootCertificate); try { await validateCertificatePath(path); diff --git a/packages/server/src/attestation/verifications/verifyApple.test.ts b/packages/server/src/attestation/verifications/verifyApple.test.ts index 79ac6c6..6ba0a5e 100644 --- a/packages/server/src/attestation/verifications/verifyApple.test.ts +++ b/packages/server/src/attestation/verifications/verifyApple.test.ts @@ -1,6 +1,7 @@ -import verifyAttestationResponse from '../verifyAttestationResponse'; import base64url from 'base64url'; +import verifyAttestationResponse from '../verifyAttestationResponse'; + test('should verify Apple attestation', async () => { const expectedChallenge = 'h5xSyIRMx2IQPr1mQk6GD98XSQOBHgMHVpJIkMV9Nkc'; jest.spyOn(base64url, 'encode').mockReturnValueOnce(expectedChallenge); diff --git a/packages/server/src/attestation/verifications/verifyApple.ts b/packages/server/src/attestation/verifications/verifyApple.ts index 937c3f8..9740449 100644 --- a/packages/server/src/attestation/verifications/verifyApple.ts +++ b/packages/server/src/attestation/verifications/verifyApple.ts @@ -12,10 +12,11 @@ type Options = { authData: Buffer; clientDataHash: Buffer; credentialPublicKey: Buffer; + rootCertificate: string; }; export default async function verifyApple(options: Options): Promise<boolean> { - const { attStmt, authData, clientDataHash, credentialPublicKey } = options; + const { attStmt, authData, clientDataHash, credentialPublicKey, rootCertificate } = options; const { x5c } = attStmt; if (!x5c) { @@ -26,7 +27,7 @@ export default async function verifyApple(options: Options): Promise<boolean> { * Verify certificate path */ const certPath = x5c.map(convertCertBufferToPEM); - certPath.push(AppleWebAuthnRootCertificate); + certPath.push(rootCertificate); try { await validateCertificatePath(certPath); diff --git a/packages/server/src/attestation/verifyAttestationResponse.ts b/packages/server/src/attestation/verifyAttestationResponse.ts index 5e6a203..f7e67f5 100644 --- a/packages/server/src/attestation/verifyAttestationResponse.ts +++ b/packages/server/src/attestation/verifyAttestationResponse.ts @@ -11,6 +11,7 @@ import toHash from '../helpers/toHash'; import decodeCredentialPublicKey from '../helpers/decodeCredentialPublicKey'; import { COSEKEYS } from '../helpers/convertCOSEtoPKCS'; import convertAAGUIDToString from '../helpers/convertAAGUIDToString'; +import settingsService from '../services/settingsService'; import { supportedCOSEAlgorithmIdentifiers } from './generateAttestationOptions'; import verifyFIDOU2F from './verifications/verifyFIDOU2F'; @@ -174,6 +175,7 @@ export default async function verifyAttestationResponse( } const clientDataHash = toHash(base64url.toBuffer(response.clientDataJSON)); + const rootCertificate = settingsService.getRootCertificate({ attestationFormat: fmt }); /** * Verification can only be performed when attestation = 'direct' @@ -202,6 +204,7 @@ export default async function verifyAttestationResponse( authData, clientDataHash, aaguid, + rootCertificate, }); } else if (fmt === 'android-key') { verified = await verifyAndroidKey({ @@ -225,6 +228,7 @@ export default async function verifyAttestationResponse( authData, clientDataHash, credentialPublicKey, + rootCertificate, }); } else if (fmt === 'none') { if (Object.keys(attStmt).length > 0) { |