summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorMatthew Miller <matthew@millerti.me>2020-05-18 17:54:26 -0700
committerMatthew Miller <matthew@millerti.me>2020-05-18 17:54:26 -0700
commitbacad393af5fb9d07a5dbdca143065091fc98281 (patch)
tree8ce9bbf4b325c4b23bdc19b3dd1b2df4cefe5648 /src
parent6d086ecb8bbe6e382bf3960a3b0757489a38e78a (diff)
Add verifyFIDOU2F
Diffstat (limited to 'src')
-rw-r--r--src/attestation/verifications/verifyFIDOU2F.ts76
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;
+}