diff options
author | Matthew Miller <matthew@millerti.me> | 2020-05-18 17:54:26 -0700 |
---|---|---|
committer | Matthew Miller <matthew@millerti.me> | 2020-05-18 17:54:26 -0700 |
commit | bacad393af5fb9d07a5dbdca143065091fc98281 (patch) | |
tree | 8ce9bbf4b325c4b23bdc19b3dd1b2df4cefe5648 /src | |
parent | 6d086ecb8bbe6e382bf3960a3b0757489a38e78a (diff) |
Add verifyFIDOU2F
Diffstat (limited to 'src')
-rw-r--r-- | src/attestation/verifications/verifyFIDOU2F.ts | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/src/attestation/verifications/verifyFIDOU2F.ts b/src/attestation/verifications/verifyFIDOU2F.ts new file mode 100644 index 0000000..3ee6ac1 --- /dev/null +++ b/src/attestation/verifications/verifyFIDOU2F.ts @@ -0,0 +1,76 @@ +import base64url from 'base64url'; + +import { AttestationObject, VerifiedAttestation } from '@types'; +import { U2F_USER_PRESENTED } from '@helpers/constants'; +import toHash from '@helpers/toHash'; +import parseAttestationAuthData from '@helpers/parseAttestationAuthData'; +import convertCOSEECDHAtoPKCS from '@helpers/convertCOSEECDHAtoPKCS'; +import convertASN1toPEM from '@helpers/convertASN1toPEM'; +import verifySignature from '@helpers/verifySignature'; + +export default function verifyAttestationFIDOU2F( + attestationObject: AttestationObject, + base64ClientDataJSON: string, +): VerifiedAttestation { + const { fmt, authData, attStmt } = attestationObject; + + const authDataStruct = parseAttestationAuthData(authData); + const { + flags, + COSEPublicKey, + rpIdHash, + credentialID, + counter, + } = authDataStruct; + + if (!(flags.flagsInt & U2F_USER_PRESENTED)) { + throw new Error('User was NOT present during authentication'); + } + + if (!COSEPublicKey) { + throw new Error('No public key was provided by authenticator'); + } + + if (!credentialID) { + throw new Error('No credential ID was provided by authenticator'); + } + + const clientDataHash = toHash(base64url.toBuffer(base64ClientDataJSON)); + const reservedByte = Buffer.from([0x00]); + const publicKey = convertCOSEECDHAtoPKCS(COSEPublicKey); + + const signatureBase = Buffer.concat([ + reservedByte, + rpIdHash, + clientDataHash, + credentialID, + publicKey, + ]); + + const { sig, x5c } = attStmt; + + if (!x5c) { + throw new Error('No attestation certificate provided in attestation statement'); + } + + if (!sig) { + throw new Error('No attestation signature provided in attestation statement'); + } + + const publicKeyCertPEM = convertASN1toPEM(x5c[0]); + + const toReturn: VerifiedAttestation = { + verified: verifySignature(sig, signatureBase, publicKeyCertPEM), + }; + + if (toReturn.verified) { + toReturn.authenticatorInfo = { + fmt, + counter, + base64PublicKey: base64url.encode(publicKey), + base64CredentialID: base64url.encode(credentialID), + }; + } + + return toReturn; +} |