diff options
Diffstat (limited to 'packages/server/src')
5 files changed, 43 insertions, 23 deletions
diff --git a/packages/server/src/attestation/verifications/tpm/verifyTPM.ts b/packages/server/src/attestation/verifications/tpm/verifyTPM.ts index 2f86e1c..e2fb772 100644 --- a/packages/server/src/attestation/verifications/tpm/verifyTPM.ts +++ b/packages/server/src/attestation/verifications/tpm/verifyTPM.ts @@ -14,6 +14,7 @@ import decodeCredentialPublicKey from '../../../helpers/decodeCredentialPublicKe import { COSEKEYS, COSEALGHASH } from '../../../helpers/convertCOSEtoPKCS'; import toHash from '../../../helpers/toHash'; import convertCertBufferToPEM from '../../../helpers/convertCertBufferToPEM'; +import validateCertificatePath from '../../../helpers/validateCertificatePath'; import getCertificateInfo from '../../../helpers/getCertificateInfo'; import verifySignature from '../../../helpers/verifySignature'; import MetadataService from '../../../services/metadataService'; @@ -24,7 +25,8 @@ import parseCertInfo from './parseCertInfo'; import parsePubArea from './parsePubArea'; export default async function verifyTPM(options: AttestationFormatVerifierOpts): Promise<boolean> { - const { aaguid, attStmt, authData, credentialPublicKey, clientDataHash } = options; + const { aaguid, attStmt, authData, credentialPublicKey, clientDataHash, rootCertificates } = + options; const { ver, sig, alg, x5c, pubArea, certInfo } = attStmt; /** @@ -263,6 +265,13 @@ export default async function verifyTPM(options: AttestationFormatVerifierOpts): } catch (err) { throw new Error(`${err.message} (TPM)`); } + } else { + try { + // Try validating the certificate path using the root certificates set via SettingsService + await validateCertificatePath(x5c.map(convertCertBufferToPEM), rootCertificates); + } catch (err) { + throw new Error(`${err.message} (TPM)`); + } } // Verify signature over certInfo with the public key extracted from AIK certificate. diff --git a/packages/server/src/attestation/verifications/verifyAndroidKey.ts b/packages/server/src/attestation/verifications/verifyAndroidKey.ts index 460e97f..29d184e 100644 --- a/packages/server/src/attestation/verifications/verifyAndroidKey.ts +++ b/packages/server/src/attestation/verifications/verifyAndroidKey.ts @@ -5,6 +5,7 @@ import { KeyDescription, id_ce_keyDescription } from '@peculiar/asn1-android'; import type { AttestationFormatVerifierOpts } from '../verifyAttestationResponse'; import convertCertBufferToPEM from '../../helpers/convertCertBufferToPEM'; +import validateCertificatePath from '../../helpers/validateCertificatePath'; import verifySignature from '../../helpers/verifySignature'; import convertCOSEtoPKCS, { COSEALGHASH } from '../../helpers/convertCOSEtoPKCS'; import MetadataService from '../../services/metadataService'; @@ -16,7 +17,8 @@ import verifyAttestationWithMetadata from '../../metadata/verifyAttestationWithM export default async function verifyAttestationAndroidKey( options: AttestationFormatVerifierOpts, ): Promise<boolean> { - const { authData, clientDataHash, attStmt, credentialPublicKey, aaguid } = options; + const { authData, clientDataHash, attStmt, credentialPublicKey, aaguid, rootCertificates } = + options; const { x5c, sig, alg } = attStmt; if (!x5c) { @@ -73,14 +75,6 @@ export default async function verifyAttestationAndroidKey( throw new Error('teeEnforced contained "allApplications [600]" tag (AndroidKey)'); } - // TODO: Confirm that the root certificate is an expected certificate - // const rootCertPEM = convertBufferToPEM(x5c[x5c.length - 1]); - // console.log(rootCertPEM); - - // if (rootCertPEM !== expectedRootCert) { - // throw new Error('Root certificate was not expected certificate (AndroidKey)'); - // } - const statement = await MetadataService.getStatement(aaguid); if (statement) { try { @@ -88,6 +82,13 @@ export default async function verifyAttestationAndroidKey( } catch (err) { throw new Error(`${err.message} (AndroidKey)`); } + } else { + try { + // Try validating the certificate path using the root certificates set via SettingsService + await validateCertificatePath(x5c.map(convertCertBufferToPEM), rootCertificates); + } catch (err) { + throw new Error(`${err.message} (AndroidKey)`); + } } const signatureBase = Buffer.concat([authData, clientDataHash]); @@ -96,13 +97,3 @@ export default async function verifyAttestationAndroidKey( return verifySignature(sig, signatureBase, leafCertPEM, hashAlg); } - -type KeyStoreExtensionDescription = { - attestationVersion: number; - attestationChallenge: Buffer; - softwareEnforced: string[]; - teeEnforced: string[]; -}; - -// TODO: Find the most up-to-date expected root cert, the one from Yuriy's article doesn't match -const expectedRootCert = ``; diff --git a/packages/server/src/attestation/verifications/verifyFIDOU2F.ts b/packages/server/src/attestation/verifications/verifyFIDOU2F.ts index bf45472..a2bfd53 100644 --- a/packages/server/src/attestation/verifications/verifyFIDOU2F.ts +++ b/packages/server/src/attestation/verifications/verifyFIDOU2F.ts @@ -2,12 +2,15 @@ import type { AttestationFormatVerifierOpts } from '../verifyAttestationResponse import convertCOSEtoPKCS from '../../helpers/convertCOSEtoPKCS'; import convertCertBufferToPEM from '../../helpers/convertCertBufferToPEM'; +import validateCertificatePath from '../../helpers/validateCertificatePath'; import verifySignature from '../../helpers/verifySignature'; /** * Verify an attestation response with fmt 'fido-u2f' */ -export default function verifyAttestationFIDOU2F(options: AttestationFormatVerifierOpts): boolean { +export default async function verifyAttestationFIDOU2F( + options: AttestationFormatVerifierOpts, +): Promise<boolean> { const { attStmt, clientDataHash, @@ -15,6 +18,7 @@ export default function verifyAttestationFIDOU2F(options: AttestationFormatVerif credentialID, credentialPublicKey, aaguid = '', + rootCertificates, } = options; const reservedByte = Buffer.from([0x00]); @@ -44,6 +48,13 @@ export default function verifyAttestationFIDOU2F(options: AttestationFormatVerif throw new Error(`AAGUID "${aaguidToHex}" was not expected value`); } + try { + // Try validating the certificate path using the root certificates set via SettingsService + await validateCertificatePath(x5c.map(convertCertBufferToPEM), rootCertificates); + } catch (err) { + throw new Error(`${err.message} (FIDOU2F)`); + } + const leafCertPEM = convertCertBufferToPEM(x5c[0]); return verifySignature(sig, signatureBase, leafCertPEM); diff --git a/packages/server/src/attestation/verifications/verifyPacked.ts b/packages/server/src/attestation/verifications/verifyPacked.ts index 9d4a0c2..dd876c2 100644 --- a/packages/server/src/attestation/verifications/verifyPacked.ts +++ b/packages/server/src/attestation/verifications/verifyPacked.ts @@ -13,6 +13,7 @@ import convertCOSEtoPKCS, { import { FIDO_METADATA_ATTESTATION_TYPES } from '../../helpers/constants'; import toHash from '../../helpers/toHash'; import convertCertBufferToPEM from '../../helpers/convertCertBufferToPEM'; +import validateCertificatePath from '../../helpers/validateCertificatePath'; import getCertificateInfo from '../../helpers/getCertificateInfo'; import verifySignature from '../../helpers/verifySignature'; import decodeCredentialPublicKey from '../../helpers/decodeCredentialPublicKey'; @@ -25,7 +26,8 @@ import verifyAttestationWithMetadata from '../../metadata/verifyAttestationWithM export default async function verifyAttestationPacked( options: AttestationFormatVerifierOpts, ): Promise<boolean> { - const { attStmt, clientDataHash, authData, credentialPublicKey, aaguid } = options; + const { attStmt, clientDataHash, authData, credentialPublicKey, aaguid, rootCertificates } = + options; const { sig, x5c, alg } = attStmt; @@ -104,6 +106,13 @@ export default async function verifyAttestationPacked( } catch (err) { throw new Error(`${err.message} (Packed|Full)`); } + } else { + try { + // Try validating the certificate path using the root certificates set via SettingsService + await validateCertificatePath(x5c.map(convertCertBufferToPEM), rootCertificates); + } catch (err) { + throw new Error(`${err.message} (Packed|Full)`); + } } verified = verifySignature(sig, signatureBase, leafCert); diff --git a/packages/server/src/attestation/verifyAttestationResponse.ts b/packages/server/src/attestation/verifyAttestationResponse.ts index ac2bd5a..726acec 100644 --- a/packages/server/src/attestation/verifyAttestationResponse.ts +++ b/packages/server/src/attestation/verifyAttestationResponse.ts @@ -197,7 +197,7 @@ export default async function verifyAttestationResponse( */ let verified = false; if (fmt === 'fido-u2f') { - verified = verifyFIDOU2F(verifierOpts); + verified = await verifyFIDOU2F(verifierOpts); } else if (fmt === 'packed') { verified = await verifyPacked(verifierOpts); } else if (fmt === 'android-safetynet') { |