summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--packages/server/src/authentication/verifyAuthenticationResponse.test.ts27
-rw-r--r--packages/server/src/authentication/verifyAuthenticationResponse.ts8
-rw-r--r--packages/server/src/helpers/__mocks__/generateChallenge.ts4
-rw-r--r--packages/server/src/helpers/getCertificateInfo.ts2
-rw-r--r--packages/server/src/helpers/isCertRevoked.ts5
-rw-r--r--packages/server/src/registration/verifications/tpm/parseCertInfo.ts56
-rw-r--r--packages/server/src/registration/verifications/tpm/parsePubArea.ts78
-rw-r--r--packages/server/src/registration/verifications/tpm/verifyAttestationTPM.ts12
-rw-r--r--packages/server/src/registration/verifications/verifyAttestationAndroidKey.ts4
-rw-r--r--packages/server/src/registration/verifications/verifyAttestationApple.ts6
-rw-r--r--packages/server/src/registration/verifications/verifyAttestationFIDOU2F.ts4
-rw-r--r--packages/server/src/registration/verifications/verifyAttestationPacked.ts2
-rw-r--r--packages/server/src/registration/verifyRegistrationResponse.ts4
13 files changed, 122 insertions, 90 deletions
diff --git a/packages/server/src/authentication/verifyAuthenticationResponse.test.ts b/packages/server/src/authentication/verifyAuthenticationResponse.test.ts
index 3b8e7b6..66163dc 100644
--- a/packages/server/src/authentication/verifyAuthenticationResponse.test.ts
+++ b/packages/server/src/authentication/verifyAuthenticationResponse.test.ts
@@ -1,4 +1,3 @@
-import base64url from 'base64url';
import { verifyAuthenticationResponse } from './verifyAuthenticationResponse';
import * as esmDecodeClientDataJSON from '../helpers/decodeClientDataJSON';
@@ -8,6 +7,8 @@ import {
AuthenticatorDevice,
AuthenticationCredentialJSON,
} from '@simplewebauthn/typescript-types';
+import * as uint8Array from '../helpers/uint8array';
+import * as base64url from '../helpers/base64url';
let mockDecodeClientData: jest.SpyInstance;
let mockParseAuthData: jest.SpyInstance;
@@ -183,7 +184,7 @@ test('should throw an error if user verification is required but user was not ve
// TODO: Get a real TPM authentication response in here
test.skip('should verify TPM assertion', async () => {
const expectedChallenge = 'dG90YWxseVVuaXF1ZVZhbHVlRXZlcnlBc3NlcnRpb24';
- jest.spyOn(base64url, 'encode').mockReturnValueOnce(expectedChallenge);
+ jest.spyOn(base64url, 'toString').mockReturnValueOnce(expectedChallenge);
const verification = await verifyAuthenticationResponse({
credential: {
id: 'YJ8FMM-AmcUt73XPX341WXWd7ypBMylGjjhu0g3VzME',
@@ -279,7 +280,7 @@ test('should pass verification if custom challenge verifier returns true', async
},
expectedChallenge: (challenge: string) => {
const parsedChallenge: { actualChallenge: string; arbitraryData: string } = JSON.parse(
- base64url.decode(challenge),
+ base64url.toString(challenge),
);
return parsedChallenge.actualChallenge === 'K3QxOjnVJLiGlnVEp5va5QJeMVWNf_7PYgutgbAtAUA';
},
@@ -318,7 +319,7 @@ test('should return authenticator extension output', async () => {
clientDataJSON:
'eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiaVpzVkN6dHJEVzdEMlVfR0hDSWxZS0x3VjJiQ3NCVFJxVlFVbkpYbjlUayIsIm9yaWdpbiI6ImFuZHJvaWQ6YXBrLWtleS1oYXNoOmd4N3NxX3B4aHhocklRZEx5ZkcwcHhLd2lKN2hPazJESlE0eHZLZDQzOFEiLCJhbmRyb2lkUGFja2FnZU5hbWUiOiJjb20uZmlkby5leGFtcGxlLmZpZG8yYXBpZXhhbXBsZSJ9',
authenticatorData:
- 'DXX8xWP9p3nbLjQ-6kiYiHWLeFSdSTpP2-oc2WqjHMSFAAAAAKFvZGV2aWNlUHVibGljS2V5pWNkcGtYTaUBAgMmIAEhWCCZGqvtneQnGp7erYgG-dyW1tzNDEdiU6VRBInsg3m-WyJYIKCXPP3tu3nif-9O50gWc_szElBN3KVDTP0jQx1q0p7aY3NpZ1hHMEUCIElSbNKK72tOYhp9WTbStQSVL8CuIxOk8DV6r_-uqWR0AiEAnVE6yu-wsyx2Wq5v66jClGhe_2P_HL8R7PIQevT-uPhlbm9uY2VAZXNjb3BlQQBmYWFndWlkULk_2WHy5kYvsSKCACJH3ng=',
+ 'DXX8xWP9p3nbLjQ-6kiYiHWLeFSdSTpP2-oc2WqjHMSFAAAAAKFsZGV2aWNlUHViS2V5pWNkcGtYTaUBAgMmIAEhWCCZGqvtneQnGp7erYgG-dyW1tzNDEdiU6VRBInsg3m-WyJYIKCXPP3tu3nif-9O50gWc_szElBN3KVDTP0jQx1q0p7aY3NpZ1hHMEUCIElSbNKK72tOYhp9WTbStQSVL8CuIxOk8DV6r_-uqWR0AiEAnVE6yu-wsyx2Wq5v66jClGhe_2P_HL8R7PIQevT-uPhlbm9uY2VAZXNjb3BlQQBmYWFndWlkULk_2WHy5kYvsSKCACJH3ng',
signature:
'MEYCIQDlRuxY7cYre0sb3T6TovQdfYIUb72cRZYOQv_zS9wN_wIhAOvN-fwjtyIhWRceqJV4SX74-z6oALERbC7ohk8EdVPO',
userHandle: 'b2FPajFxcmM4MWo3QkFFel9RN2lEakh5RVNlU2RLNDF0Sl92eHpQYWV5UQ==',
@@ -343,18 +344,16 @@ test('should return authenticator extension output', async () => {
});
expect(verification.authenticationInfo?.authenticatorExtensionResults).toMatchObject({
- devicePublicKey: {
- dpk: Buffer.from(
+ devicePubKey: {
+ dpk: uint8Array.fromHex(
'A5010203262001215820991AABED9DE4271A9EDEAD8806F9DC96D6DCCD0C476253A5510489EC8379BE5B225820A0973CFDEDBB79E27FEF4EE7481673FB3312504DDCA5434CFD23431D6AD29EDA',
- 'hex',
),
- sig: Buffer.from(
+ sig: uint8Array.fromHex(
'3045022049526CD28AEF6B4E621A7D5936D2B504952FC0AE2313A4F0357AAFFFAEA964740221009D513ACAEFB0B32C765AAE6FEBA8C294685EFF63FF1CBF11ECF2107AF4FEB8F8',
- 'hex',
),
- nonce: Buffer.from('', 'hex'),
- scope: Buffer.from('00', 'hex'),
- aaguid: Buffer.from('B93FD961F2E6462FB12282002247DE78', 'hex'),
+ nonce: uint8Array.fromHex(''),
+ scope: uint8Array.fromHex('00'),
+ aaguid: uint8Array.fromHex('B93FD961F2E6462FB12282002247DE78'),
},
});
});
@@ -392,7 +391,7 @@ const assertionResponse: AuthenticationCredentialJSON = {
clientExtensionResults: {},
type: 'public-key',
};
-const assertionChallenge = base64url.encode('totallyUniqueValueEveryTime');
+const assertionChallenge = base64url.fromString('totallyUniqueValueEveryTime');
const assertionOrigin = 'https://dev.dontneeda.pw';
const authenticator: AuthenticatorDevice = {
@@ -421,7 +420,7 @@ const assertionFirstTimeUsedResponse: AuthenticationCredentialJSON = {
type: 'public-key',
clientExtensionResults: {},
};
-const assertionFirstTimeUsedChallenge = base64url.encode('totallyUniqueValueEveryAssertion');
+const assertionFirstTimeUsedChallenge = base64url.fromString('totallyUniqueValueEveryAssertion');
const assertionFirstTimeUsedOrigin = 'https://dev.dontneeda.pw';
const authenticatorFirstTimeUsed: AuthenticatorDevice = {
credentialPublicKey: base64url.toBuffer(
diff --git a/packages/server/src/authentication/verifyAuthenticationResponse.ts b/packages/server/src/authentication/verifyAuthenticationResponse.ts
index c89d39b..9f52d70 100644
--- a/packages/server/src/authentication/verifyAuthenticationResponse.ts
+++ b/packages/server/src/authentication/verifyAuthenticationResponse.ts
@@ -149,14 +149,14 @@ export async function verifyAuthenticationResponse(
// Make sure the response's RP ID is ours
if (typeof expectedRPID === 'string') {
- const expectedRPIDHash = toHash(Buffer.from(expectedRPID, 'ascii'));
+ const expectedRPIDHash = toHash(uint8Array.fromASCIIString(expectedRPID));
if (!uint8Array.areEqual(rpIdHash, expectedRPIDHash)) {
throw new Error(`Unexpected RP ID hash`);
}
} else {
// Go through each expected RP ID and try to find one that matches
const foundMatch = expectedRPID.some(expected => {
- const expectedRPIDHash = toHash(Buffer.from(expected, 'ascii'));
+ const expectedRPIDHash = toHash(uint8Array.fromASCIIString(expected));
return uint8Array.areEqual(rpIdHash, expectedRPIDHash);
});
@@ -195,7 +195,7 @@ export async function verifyAuthenticationResponse(
}
const clientDataHash = toHash(base64url.toBuffer(response.clientDataJSON));
- const signatureBase = Buffer.concat([authDataBuffer, clientDataHash]);
+ const signatureBase = uint8Array.concat([authDataBuffer, clientDataHash]);
const signature = base64url.toBuffer(response.signature);
@@ -251,7 +251,7 @@ export async function verifyAuthenticationResponse(
export type VerifiedAuthenticationResponse = {
verified: boolean;
authenticationInfo: {
- credentialID: Buffer;
+ credentialID: Uint8Array;
newCounter: number;
userVerified: boolean;
credentialDeviceType: CredentialDeviceType;
diff --git a/packages/server/src/helpers/__mocks__/generateChallenge.ts b/packages/server/src/helpers/__mocks__/generateChallenge.ts
index a339e56..d9d866e 100644
--- a/packages/server/src/helpers/__mocks__/generateChallenge.ts
+++ b/packages/server/src/helpers/__mocks__/generateChallenge.ts
@@ -1,3 +1,3 @@
-export function generateChallenge(): Buffer {
- return Buffer.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
+export function generateChallenge(): Uint8Array {
+ return Uint8Array.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
}
diff --git a/packages/server/src/helpers/getCertificateInfo.ts b/packages/server/src/helpers/getCertificateInfo.ts
index 02183c5..e503f70 100644
--- a/packages/server/src/helpers/getCertificateInfo.ts
+++ b/packages/server/src/helpers/getCertificateInfo.ts
@@ -36,7 +36,7 @@ const issuerSubjectIDKey: { [key: string]: 'C' | 'O' | 'OU' | 'CN' } = {
*
* @param pemCertificate Result from call to `convertASN1toPEM(x5c[0])`
*/
-export function getCertificateInfo(leafCertBuffer: Buffer): CertificateInfo {
+export function getCertificateInfo(leafCertBuffer: Uint8Array): CertificateInfo {
const asnx509 = AsnParser.parse(leafCertBuffer, Certificate);
const parsedCert = asnx509.tbsCertificate;
diff --git a/packages/server/src/helpers/isCertRevoked.ts b/packages/server/src/helpers/isCertRevoked.ts
index cc8c3f1..4ea3dda 100644
--- a/packages/server/src/helpers/isCertRevoked.ts
+++ b/packages/server/src/helpers/isCertRevoked.ts
@@ -4,6 +4,7 @@ import { AsnParser } from '@peculiar/asn1-schema';
import { CertificateList } from '@peculiar/asn1-x509';
import { convertCertBufferToPEM } from './convertCertBufferToPEM';
+import * as uint8Array from './uint8Array';
/**
* A cache of revoked cert serial numbers by Authority Key ID
@@ -68,7 +69,7 @@ export async function isCertRevoked(cert: X509): Promise<boolean> {
return false;
}
- const data = AsnParser.parse(Buffer.from(crlCert.hex, 'hex'), CertificateList);
+ const data = AsnParser.parse(uint8Array.fromHex(crlCert.hex), CertificateList);
const newCached: CAAuthorityInfo = {
revokedCerts: [],
@@ -85,7 +86,7 @@ export async function isCertRevoked(cert: X509): Promise<boolean> {
if (revokedCerts) {
for (const cert of revokedCerts) {
- const revokedHex = Buffer.from(cert.userCertificate).toString('hex');
+ const revokedHex = uint8Array.toHex(new Uint8Array(cert.userCertificate));
newCached.revokedCerts.push(revokedHex);
}
diff --git a/packages/server/src/registration/verifications/tpm/parseCertInfo.ts b/packages/server/src/registration/verifications/tpm/parseCertInfo.ts
index 6e3d4c3..c590794 100644
--- a/packages/server/src/registration/verifications/tpm/parseCertInfo.ts
+++ b/packages/server/src/registration/verifications/tpm/parseCertInfo.ts
@@ -1,48 +1,58 @@
import { TPM_ST, TPM_ALG } from './constants';
+import * as uint8Array from '../../../helpers/uint8Array';
/**
* Cut up a TPM attestation's certInfo into intelligible chunks
*/
-export function parseCertInfo(certInfo: Buffer): ParsedCertInfo {
+export function parseCertInfo(certInfo: Uint8Array): ParsedCertInfo {
let pointer = 0;
+ const dataView = uint8Array.toDataView(certInfo);
// Get a magic constant
- const magic = certInfo.slice(pointer, (pointer += 4)).readUInt32BE(0);
+ const magic = dataView.getUint32(pointer);
+ pointer += 4;
// Determine the algorithm used for attestation
- const typeBuffer = certInfo.slice(pointer, (pointer += 2));
- const type = TPM_ST[typeBuffer.readUInt16BE(0)];
+ const typeBuffer = dataView.getUint16(pointer);
+ pointer += 2;
+ const type = TPM_ST[typeBuffer];
// The name of a parent entity, can be ignored
- const qualifiedSignerLength = certInfo.slice(pointer, (pointer += 2)).readUInt16BE(0);
+ const qualifiedSignerLength = dataView.getUint16(pointer);
+ pointer += 2;
const qualifiedSigner = certInfo.slice(pointer, (pointer += qualifiedSignerLength));
// Get the expected hash of `attsToBeSigned`
- const extraDataLength = certInfo.slice(pointer, (pointer += 2)).readUInt16BE(0);
+ const extraDataLength = dataView.getUint16(pointer);
+ pointer += 2;
const extraData = certInfo.slice(pointer, (pointer += extraDataLength));
// Information about the TPM device's internal clock, can be ignored
- const clockInfoBuffer = certInfo.slice(pointer, (pointer += 17));
- const clockInfo = {
- clock: clockInfoBuffer.slice(0, 8),
- resetCount: clockInfoBuffer.slice(8, 12).readUInt32BE(0),
- restartCount: clockInfoBuffer.slice(12, 16).readUInt32BE(0),
- safe: !!clockInfoBuffer[16],
- };
+ const clock = certInfo.slice(pointer, pointer += 8);
+ const resetCount = dataView.getUint32(pointer);
+ pointer += 4;
+ const restartCount = dataView.getUint32(pointer);
+ pointer += 4;
+ const safe = !!certInfo.slice(pointer, pointer += 1);
+
+ const clockInfo = { clock, resetCount, restartCount, safe };
// TPM device firmware version
const firmwareVersion = certInfo.slice(pointer, (pointer += 8));
// Attested Name
- const attestedNameLength = certInfo.slice(pointer, (pointer += 2)).readUInt16BE(0);
+ const attestedNameLength = dataView.getUint16(pointer);
+ pointer += 2;
const attestedName = certInfo.slice(pointer, (pointer += attestedNameLength));
+ const attestedNameDataView = uint8Array.toDataView(attestedName);
// Attested qualified name, can be ignored
- const qualifiedNameLength = certInfo.slice(pointer, (pointer += 2)).readUInt16BE(0);
+ const qualifiedNameLength = dataView.getUint16(pointer);
+ pointer += 2;
const qualifiedName = certInfo.slice(pointer, (pointer += qualifiedNameLength));
const attested = {
- nameAlg: TPM_ALG[attestedName.slice(0, 2).readUInt16BE(0)],
+ nameAlg: TPM_ALG[attestedNameDataView.getUint16(0)],
nameAlgBuffer: attestedName.slice(0, 2),
name: attestedName,
qualifiedName,
@@ -62,19 +72,19 @@ export function parseCertInfo(certInfo: Buffer): ParsedCertInfo {
type ParsedCertInfo = {
magic: number;
type: string;
- qualifiedSigner: Buffer;
- extraData: Buffer;
+ qualifiedSigner: Uint8Array;
+ extraData: Uint8Array;
clockInfo: {
- clock: Buffer;
+ clock: Uint8Array;
resetCount: number;
restartCount: number;
safe: boolean;
};
- firmwareVersion: Buffer;
+ firmwareVersion: Uint8Array;
attested: {
nameAlg: string;
- nameAlgBuffer: Buffer;
- name: Buffer;
- qualifiedName: Buffer;
+ nameAlgBuffer: Uint8Array;
+ name: Uint8Array;
+ qualifiedName: Uint8Array;
};
};
diff --git a/packages/server/src/registration/verifications/tpm/parsePubArea.ts b/packages/server/src/registration/verifications/tpm/parsePubArea.ts
index ca61ddc..1476ea4 100644
--- a/packages/server/src/registration/verifications/tpm/parsePubArea.ts
+++ b/packages/server/src/registration/verifications/tpm/parsePubArea.ts
@@ -1,4 +1,5 @@
import { TPM_ALG, TPM_ECC_CURVE } from './constants';
+import * as uint8Array from '../../../helpers/uint8Array';
/**
* Break apart a TPM attestation's pubArea buffer
@@ -6,17 +7,20 @@ import { TPM_ALG, TPM_ECC_CURVE } from './constants';
* See 12.2.4 TPMT_PUBLIC here:
* https://trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-2-Structures-00.96-130315.pdf
*/
-export function parsePubArea(pubArea: Buffer): ParsedPubArea {
+export function parsePubArea(pubArea: Uint8Array): ParsedPubArea {
let pointer = 0;
+ const dataView = uint8Array.toDataView(pubArea);
- const typeBuffer = pubArea.slice(pointer, (pointer += 2));
- const type = TPM_ALG[typeBuffer.readUInt16BE(0)];
+ const type = TPM_ALG[dataView.getUint16(pointer)];
+ pointer += 2;
- const nameAlgBuffer = pubArea.slice(pointer, (pointer += 2));
- const nameAlg = TPM_ALG[nameAlgBuffer.readUInt16BE(0)];
+ const nameAlg = TPM_ALG[dataView.getUint16(pointer)];
+ pointer += 2;
// Get some authenticator attributes(?)
- const objectAttributesInt = pubArea.slice(pointer, (pointer += 4)).readUInt32BE(0);
+ // const objectAttributesInt = pubArea.slice(pointer, (pointer += 4)).readUInt32BE(0);
+ const objectAttributesInt = dataView.getUint32(pointer);
+ pointer += 4;
const objectAttributes = {
fixedTPM: !!(objectAttributesInt & 1),
stClear: !!(objectAttributesInt & 2),
@@ -32,52 +36,70 @@ export function parsePubArea(pubArea: Buffer): ParsedPubArea {
};
// Slice out the authPolicy of dynamic length
- const authPolicyLength = pubArea.slice(pointer, (pointer += 2)).readUInt16BE(0);
+ const authPolicyLength = dataView.getUint16(pointer);
+ pointer += 2;
const authPolicy = pubArea.slice(pointer, (pointer += authPolicyLength));
// Extract additional curve params according to type
const parameters: { rsa?: RSAParameters; ecc?: ECCParameters } = {};
- let unique = Buffer.from([]);
+ let unique = Uint8Array.from([]);
if (type === 'TPM_ALG_RSA') {
- const rsaBuffer = pubArea.slice(pointer, (pointer += 10));
+ const symmetric = TPM_ALG[dataView.getUint16(pointer)];
+ pointer += 2;
- parameters.rsa = {
- symmetric: TPM_ALG[rsaBuffer.slice(0, 2).readUInt16BE(0)],
- scheme: TPM_ALG[rsaBuffer.slice(2, 4).readUInt16BE(0)],
- keyBits: rsaBuffer.slice(4, 6).readUInt16BE(0),
- exponent: rsaBuffer.slice(6, 10).readUInt32BE(0),
- };
+ const scheme = TPM_ALG[dataView.getUint16(pointer)];
+ pointer += 2;
+
+ const keyBits = dataView.getUint16(pointer);
+ pointer += 2;
+
+ const exponent = dataView.getUint32(pointer);
+ pointer += 4;
+
+ parameters.rsa = { symmetric, scheme, keyBits, exponent };
/**
* See 11.2.4.5 TPM2B_PUBLIC_KEY_RSA here:
* https://trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-2-Structures-00.96-130315.pdf
*/
- const uniqueLength = pubArea.slice(pointer, (pointer += 2)).readUInt16BE(0);
+ // const uniqueLength = pubArea.slice(pointer, (pointer += 2)).readUInt16BE(0);
+ const uniqueLength = dataView.getUint16(pointer);
+ pointer += 2;
unique = pubArea.slice(pointer, (pointer += uniqueLength));
} else if (type === 'TPM_ALG_ECC') {
- const eccBuffer = pubArea.slice(pointer, (pointer += 8));
+ const symmetric = TPM_ALG[dataView.getUint16(pointer)];
+ pointer += 2;
+
+ const scheme = TPM_ALG[dataView.getUint16(pointer)];
+ pointer += 2;
+
+ const curveID = TPM_ECC_CURVE[dataView.getUint16(pointer)];
+ pointer += 2;
- parameters.ecc = {
- symmetric: TPM_ALG[eccBuffer.slice(0, 2).readUInt16BE(0)],
- scheme: TPM_ALG[eccBuffer.slice(2, 4).readUInt16BE(0)],
- curveID: TPM_ECC_CURVE[eccBuffer.slice(4, 6).readUInt16BE(0)],
- kdf: TPM_ALG[eccBuffer.slice(6, 8).readUInt16BE(0)],
- };
+ const kdf = TPM_ALG[dataView.getUint16(pointer)];
+ pointer += 2;
+
+ parameters.ecc = { symmetric, scheme, curveID, kdf };
/**
* See 11.2.5.1 TPM2B_ECC_PARAMETER here:
* https://trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-2-Structures-00.96-130315.pdf
*/
// Retrieve X
- const uniqueXLength = pubArea.slice(pointer, (pointer += 2)).readUInt16BE(0);
+ const uniqueXLength = dataView.getUint16(pointer);
+ pointer += 2;
+
const uniqueX = pubArea.slice(pointer, (pointer += uniqueXLength));
+
// Retrieve Y
- const uniqueYLength = pubArea.slice(pointer, (pointer += 2)).readUInt16BE(0);
+ const uniqueYLength = dataView.getUint16(pointer);
+ pointer += 2;
+
const uniqueY = pubArea.slice(pointer, (pointer += uniqueYLength));
- unique = Buffer.concat([uniqueX, uniqueY]);
+ unique = uint8Array.concat([uniqueX, uniqueY]);
} else {
throw new Error(`Unexpected type "${type}" (TPM)`);
}
@@ -108,12 +130,12 @@ type ParsedPubArea = {
decrypt: boolean;
signOrEncrypt: boolean;
};
- authPolicy: Buffer;
+ authPolicy: Uint8Array;
parameters: {
rsa?: RSAParameters;
ecc?: ECCParameters;
};
- unique: Buffer;
+ unique: Uint8Array;
};
type RSAParameters = {
diff --git a/packages/server/src/registration/verifications/tpm/verifyAttestationTPM.ts b/packages/server/src/registration/verifications/tpm/verifyAttestationTPM.ts
index 910e8f3..c1c4306 100644
--- a/packages/server/src/registration/verifications/tpm/verifyAttestationTPM.ts
+++ b/packages/server/src/registration/verifications/tpm/verifyAttestationTPM.ts
@@ -74,7 +74,7 @@ export async function verifyAttestationTPM(options: AttestationFormatVerifierOpt
throw new Error('COSE public key missing e (TPM|RSA)');
}
- if (!unique.equals(n as Buffer)) {
+ if (!uint8Array.areEqual(unique, (n as Buffer))) {
throw new Error('PubArea unique is not same as credentialPublicKey (TPM|RSA)');
}
@@ -107,7 +107,7 @@ export async function verifyAttestationTPM(options: AttestationFormatVerifierOpt
throw new Error('COSE public key missing y (TPM|ECC)');
}
- if (!unique.equals(Buffer.concat([x as Buffer, y as Buffer]))) {
+ if (!uint8Array.areEqual(unique, uint8Array.concat([x as Uint8Array, y as Uint8Array]))) {
throw new Error('PubArea unique is not same as public key x and y (TPM|ECC)');
}
@@ -141,22 +141,22 @@ export async function verifyAttestationTPM(options: AttestationFormatVerifierOpt
const pubAreaHash = toHash(pubArea, attested.nameAlg.replace('TPM_ALG_', ''));
// Concatenate attested.nameAlg and pubAreaHash to create attestedName.
- const attestedName = Buffer.concat([attested.nameAlgBuffer, pubAreaHash]);
+ const attestedName = uint8Array.concat([attested.nameAlgBuffer, pubAreaHash]);
// Check that certInfo.attested.name is equals to attestedName.
- if (!attested.name.equals(attestedName)) {
+ if (!uint8Array.areEqual(attested.name, attestedName)) {
throw new Error(`Attested name comparison failed (TPM)`);
}
// Concatenate authData with clientDataHash to create attToBeSigned
- const attToBeSigned = Buffer.concat([authData, clientDataHash]);
+ const attToBeSigned = uint8Array.concat([authData, clientDataHash]);
// Hash attToBeSigned using the algorithm specified in attStmt.alg to create attToBeSignedHash
const hashAlg: string = COSEALGHASH[alg as number];
const attToBeSignedHash = toHash(attToBeSigned, hashAlg);
// Check that certInfo.extraData is equals to attToBeSignedHash.
- if (!extraData.equals(attToBeSignedHash)) {
+ if (!uint8Array.areEqual(extraData, attToBeSignedHash)) {
throw new Error('CertInfo extra data did not equal hashed attestation (TPM)');
}
diff --git a/packages/server/src/registration/verifications/verifyAttestationAndroidKey.ts b/packages/server/src/registration/verifications/verifyAttestationAndroidKey.ts
index ed0bb61..27bef78 100644
--- a/packages/server/src/registration/verifications/verifyAttestationAndroidKey.ts
+++ b/packages/server/src/registration/verifications/verifyAttestationAndroidKey.ts
@@ -62,7 +62,7 @@ export async function verifyAttestationAndroidKey(
// Verify extKeyStore values
const { attestationChallenge, teeEnforced, softwareEnforced } = parsedExtKeyStore;
- if (!Buffer.from(attestationChallenge.buffer).equals(clientDataHash)) {
+ if (!uint8Array.areEqual(new Uint8Array(attestationChallenge.buffer), clientDataHash)) {
throw new Error('Attestation challenge was not equal to client data hash (AndroidKey)');
}
@@ -99,7 +99,7 @@ export async function verifyAttestationAndroidKey(
}
}
- const signatureBase = Buffer.concat([authData, clientDataHash]);
+ const signatureBase = uint8Array.concat([authData, clientDataHash]);
const hashAlg = COSEALGHASH[alg as number];
return verifySignature({
diff --git a/packages/server/src/registration/verifications/verifyAttestationApple.ts b/packages/server/src/registration/verifications/verifyAttestationApple.ts
index a54c465..928f6c6 100644
--- a/packages/server/src/registration/verifications/verifyAttestationApple.ts
+++ b/packages/server/src/registration/verifications/verifyAttestationApple.ts
@@ -45,7 +45,7 @@ export async function verifyAttestationApple(
throw new Error('credCert missing "1.2.840.113635.100.8.2" extension (Apple)');
}
- const nonceToHash = Buffer.concat([authData, clientDataHash]);
+ const nonceToHash = uint8Array.concat([authData, clientDataHash]);
const nonce = toHash(nonceToHash, 'SHA256');
/**
* Ignore the first six ASN.1 structure bytes that define the nonce as an OCTET STRING. Should
@@ -54,7 +54,7 @@ export async function verifyAttestationApple(
* TODO: Try and get @peculiar (GitHub) to add a schema for "1.2.840.113635.100.8.2" when we
* find out where it's defined (doesn't seem to be publicly documented at the moment...)
*/
- const extNonce = Buffer.from(extCertNonce.extnValue.buffer).slice(6);
+ const extNonce = new Uint8Array(extCertNonce.extnValue.buffer).slice(6);
if (!uint8Array.areEqual(nonce, extNonce)) {
throw new Error(`credCert nonce was not expected value (Apple)`);
@@ -64,7 +64,7 @@ export async function verifyAttestationApple(
* Verify credential public key matches the Subject Public Key of credCert
*/
const credPubKeyPKCS = convertCOSEtoPKCS(credentialPublicKey);
- const credCertSubjectPublicKey = Buffer.from(subjectPublicKeyInfo.subjectPublicKey);
+ const credCertSubjectPublicKey = new Uint8Array(subjectPublicKeyInfo.subjectPublicKey);
if (!uint8Array.areEqual(credPubKeyPKCS, credCertSubjectPublicKey)) {
throw new Error('Credential public key does not equal credCert public key (Apple)');
diff --git a/packages/server/src/registration/verifications/verifyAttestationFIDOU2F.ts b/packages/server/src/registration/verifications/verifyAttestationFIDOU2F.ts
index ea705d0..591149f 100644
--- a/packages/server/src/registration/verifications/verifyAttestationFIDOU2F.ts
+++ b/packages/server/src/registration/verifications/verifyAttestationFIDOU2F.ts
@@ -22,10 +22,10 @@ export async function verifyAttestationFIDOU2F(
rootCertificates,
} = options;
- const reservedByte = Buffer.from([0x00]);
+ const reservedByte = Uint8Array.from([0x00]);
const publicKey = convertCOSEtoPKCS(credentialPublicKey);
- const signatureBase = Buffer.concat([
+ const signatureBase = uint8Array.concat([
reservedByte,
rpIdHash,
clientDataHash,
diff --git a/packages/server/src/registration/verifications/verifyAttestationPacked.ts b/packages/server/src/registration/verifications/verifyAttestationPacked.ts
index 02beebc..aa2d4b9 100644
--- a/packages/server/src/registration/verifications/verifyAttestationPacked.ts
+++ b/packages/server/src/registration/verifications/verifyAttestationPacked.ts
@@ -27,7 +27,7 @@ export async function verifyAttestationPacked(
throw new Error(`Attestation Statement alg "${alg}" is not a number (Packed)`);
}
- const signatureBase = Buffer.concat([authData, clientDataHash]);
+ const signatureBase = uint8Array.concat([authData, clientDataHash]);
let verified = false;
diff --git a/packages/server/src/registration/verifyRegistrationResponse.ts b/packages/server/src/registration/verifyRegistrationResponse.ts
index 87deb85..1711108 100644
--- a/packages/server/src/registration/verifyRegistrationResponse.ts
+++ b/packages/server/src/registration/verifyRegistrationResponse.ts
@@ -141,14 +141,14 @@ export async function verifyRegistrationResponse(
// Make sure the response's RP ID is ours
if (expectedRPID) {
if (typeof expectedRPID === 'string') {
- const expectedRPIDHash = toHash(Buffer.from(expectedRPID, 'ascii'));
+ const expectedRPIDHash = toHash(uint8Array.fromASCIIString(expectedRPID));
if (!uint8Array.areEqual(rpIdHash, expectedRPIDHash)) {
throw new Error(`Unexpected RP ID hash`);
}
} else {
// Go through each expected RP ID and try to find one that matches
const foundMatch = expectedRPID.some(expected => {
- const expectedRPIDHash = toHash(Buffer.from(expected, 'ascii'));
+ const expectedRPIDHash = toHash(uint8Array.fromASCIIString(expected));
return uint8Array.areEqual(rpIdHash, expectedRPIDHash);
});