Skip to content

Commit

Permalink
Passed FIDO Conformance Tool 1.7.10 !
Browse files Browse the repository at this point in the history
  • Loading branch information
dqj1998 committed Mar 21, 2023
1 parent c19214c commit e8b6f4f
Show file tree
Hide file tree
Showing 24 changed files with 262 additions and 158 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ Body is JSON with MNG_TOKEN:
* For security, you can deny external access to /mng on your firewall.

# FIDO Conformance test
We passed the test of FIDO Conformance Tools v1.7.9 || FIDO2 Server - MDS3
We passed the test of FIDO Conformance Tools v1.7.10 || FIDO2 Server - MDS3

## Preperations
1. Download Metadata by clicking DOWNLOAD TEST METADATA on FIDO conformance tools
Expand Down
29 changes: 29 additions & 0 deletions fido-mds3/cert/MDS3ROOT.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
!!!!!DO NOT DYNAMICALLY FETCH THIS CERTIFICATE!!!!!
!!!!!ADD THIS CERTIFICATE DIRECTLY TO YOUR CERTIFICATE STORAGE OR SOURCE CODE!!!!!

FIDO Alliance Certification TEST Metadata Service Root Certificate
Expected page status: Valid
CN=FAKE Root FAKE
OU=FAKE Metadata 3 BLOB Signing FAKE
O=FIDO Alliance
C=US
Serial number=04 5A 1C 22 66 A1 4F 3F 1F 4D 29 55 12 23 15
Valid from=01 February 2017
Valid to=31 January 2045

Base64
-----BEGIN CERTIFICATE-----
MIICaDCCAe6gAwIBAgIPBCqih0DiJLW7+UHXx/o1MAoGCCqGSM49BAMDMGcxCzAJ
BgNVBAYTAlVTMRYwFAYDVQQKDA1GSURPIEFsbGlhbmNlMScwJQYDVQQLDB5GQUtF
IE1ldGFkYXRhIDMgQkxPQiBST09UIEZBS0UxFzAVBgNVBAMMDkZBS0UgUm9vdCBG
QUtFMB4XDTE3MDIwMTAwMDAwMFoXDTQ1MDEzMTIzNTk1OVowZzELMAkGA1UEBhMC
VVMxFjAUBgNVBAoMDUZJRE8gQWxsaWFuY2UxJzAlBgNVBAsMHkZBS0UgTWV0YWRh
dGEgMyBCTE9CIFJPT1QgRkFLRTEXMBUGA1UEAwwORkFLRSBSb290IEZBS0UwdjAQ
BgcqhkjOPQIBBgUrgQQAIgNiAASKYiz3YltC6+lmxhPKwA1WFZlIqnX8yL5RybSL
TKFAPEQeTD9O6mOz+tg8wcSdnVxHzwnXiQKJwhrav70rKc2ierQi/4QUrdsPes8T
EirZOkCVJurpDFbXZOgs++pa4XmjYDBeMAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8E
BTADAQH/MB0GA1UdDgQWBBQGcfeCs0Y8D+lh6U5B2xSrR74eHTAfBgNVHSMEGDAW
gBQGcfeCs0Y8D+lh6U5B2xSrR74eHTAKBggqhkjOPQQDAwNoADBlAjEA/xFsgri0
xubSa3y3v5ormpPqCwfqn9s0MLBAtzCIgxQ/zkzPKctkiwoPtDzI51KnAjAmeMyg
X2S5Ht8+e+EQnezLJBJXtnkRWY+Zt491wgt/AwSs5PHHMv5QgjELOuMxQBc=
-----END CERTIFICATE-----
Binary file added fido-mds3/cert/fido-conformance.crt
Binary file not shown.
15 changes: 15 additions & 0 deletions fido-mds3/cert/fido-conformance.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
-----BEGIN CERTIFICATE-----
MIICaDCCAe6gAwIBAgIPBCqih0DiJLW7+UHXx/o1MAoGCCqGSM49BAMDMGcxCzAJ
BgNVBAYTAlVTMRYwFAYDVQQKDA1GSURPIEFsbGlhbmNlMScwJQYDVQQLDB5GQUtF
IE1ldGFkYXRhIDMgQkxPQiBST09UIEZBS0UxFzAVBgNVBAMMDkZBS0UgUm9vdCBG
QUtFMB4XDTE3MDIwMTAwMDAwMFoXDTQ1MDEzMTIzNTk1OVowZzELMAkGA1UEBhMC
VVMxFjAUBgNVBAoMDUZJRE8gQWxsaWFuY2UxJzAlBgNVBAsMHkZBS0UgTWV0YWRh
dGEgMyBCTE9CIFJPT1QgRkFLRTEXMBUGA1UEAwwORkFLRSBSb290IEZBS0UwdjAQ
BgcqhkjOPQIBBgUrgQQAIgNiAASKYiz3YltC6+lmxhPKwA1WFZlIqnX8yL5RybSL
TKFAPEQeTD9O6mOz+tg8wcSdnVxHzwnXiQKJwhrav70rKc2ierQi/4QUrdsPes8T
EirZOkCVJurpDFbXZOgs++pa4XmjYDBeMAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8E
BTADAQH/MB0GA1UdDgQWBBQGcfeCs0Y8D+lh6U5B2xSrR74eHTAfBgNVHSMEGDAW
gBQGcfeCs0Y8D+lh6U5B2xSrR74eHTAKBggqhkjOPQQDAwNoADBlAjEA/xFsgri0
xubSa3y3v5ormpPqCwfqn9s0MLBAtzCIgxQ/zkzPKctkiwoPtDzI51KnAjAmeMyg
X2S5Ht8+e+EQnezLJBJXtnkRWY+Zt491wgt/AwSs5PHHMv5QgjELOuMxQBc=
-----END CERTIFICATE-----
23 changes: 23 additions & 0 deletions fido-mds3/config/config-fido-conformance.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* This file's comment is removed before JSON parse.
*
* How to create fido-conformance.crt file:
* 1. Download MDS3ROOT.crt by click 'MDS3 TEST SERVER' button of conformance tool
* 2. Copy BEGIN to END part of MDS3ROOT.crt to create fido-conformance.pem file
* 3. Run openssl command: openssl x509 -outform der -in fido-conformance.pem -out fido-conformance.crt
*/
{
"mds": {
"url": "https://mds3.fido.tools/execute/634c6ced49448057778bbd088f9d2cec6a266b7a6d443525be85c0b3630ed406", /* MDS3 BLOB download url is one of endpoints from 'MDS3 TEST SERVER' button of conformance tool . */
"file": "../data/blob-fido-conformance.jwt", /* MDS3 BLOB file path. */
"access": "url" /* How to access MDS3. */
},
"payload": {
"file": "../data/payload-fido-conformance.json" /* MDS3 BLOB payload file path. */
},
"root": {
"url": "https://mds3.fido.tools", /* fake url */
"file": "../cert/fido-conformance.crt",
"access": "file"
}
}
1 change: 1 addition & 0 deletions fido-mds3/data/payload-fido-conformance.json

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions fido-mds3/main/accessor.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ var Accessor = /** @class */ (function () {
var buf, pem, certificate;
return __generator(this, function (_a) {
buf = fs_1.default.readFileSync(filePath);
/*const txt = buf.toString();
if(!txt.startsWith("----BEGIN CERTIFICATE-----")){
pem = Accessor.createPem(buf, 'CERTIFICATE');
} else pem = txt */
pem = Accessor.createPem(buf, 'CERTIFICATE');
certificate = new jsrsasign_1.default.X509(pem);
Accessor.rootCert = certificate;
Expand Down
8 changes: 7 additions & 1 deletion fido-mds3/main/builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,13 @@ var Builder = /** @class */ (function () {
* @param config
*/
function Builder(config) {
var configJson = fs_1.default.readFileSync(path_1.default.resolve(__dirname, '../config/config.json'), 'utf-8');
var configJson
if(process.env.FIDO_CONFORMANCE_TEST){
configJson = fs_1.default.readFileSync(path_1.default.resolve(__dirname, '../config/config-fido-conformance.json'), 'utf-8');
} else {
configJson = fs_1.default.readFileSync(path_1.default.resolve(__dirname, '../config/config.json'), 'utf-8');
}

var defaultConfig = (0, comment_json_1.parse)(configJson);
if (config && !config.accessMds) {
if (config.mdsUrl && !config.mdsFile && !config.mdsJwt) {
Expand Down
22 changes: 17 additions & 5 deletions fido2-node-lib/attestations/androidSafetyNet.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
//import { ab2str, appendBuffer, coerceToBase64, tools } from "../utils.js";
const { ab2str, appendBuffer, coerceToBase64, tools } = require("../utils.js")

//import { Certificate } from "../certUtils.js";
const Certificate = require("../certUtils.js")
const { Certificate } = require("../certUtils.js")

function androidSafetyNetParseFn(attStmt) {
const ret = new Map();

// console.log("android-safetynet", attStmt);
//console.log("android-safetynet", attStmt);

ret.set("ver", attStmt.ver);

const response = ab2str(attStmt.response);
ret.set("response", response);

// console.log("returning", ret);
//console.log("returning", ret);
return ret;
}

Expand All @@ -24,6 +22,11 @@ function androidSafetyNetParseFn(attStmt) {
async function androidSafetyNetValidateFn() {
const response = this.authnrData.get("response");

const ver = this.authnrData.get("ver");
if(!ver){
throw new Error("android-safetynet attestation ver field is empty");
}

// parse JWS
const protectedHeader = await tools.decodeProtectedHeader(response);
const publicKey = await tools.getEmbeddedJwk(protectedHeader);
Expand All @@ -32,6 +35,15 @@ async function androidSafetyNetValidateFn() {
await tools.importJWK(publicKey),
);

const timestampMs = parsedJws.payload.timestampMs;
if(timestampMs){
if(Date.now() < timestampMs){
throw new Error("android-safetynet attestation timestampMs field is future");
} else if((60*1000) < (Date.now() - timestampMs)){
throw new Error("android-safetynet attestation timestampMs field is older than 1 minute");
}
}

// Append now verified header to jws
parsedJws.header = protectedHeader;

Expand Down
5 changes: 1 addition & 4 deletions fido2-node-lib/attestations/apple.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
//import { Certificate } from "../certUtils.js";
const Certificate = require("../certUtils.js")
const { Certificate } = require("../certUtils.js")

//import { PublicKey } from "../keyUtils.js";
const PublicKey = require("../keyUtils.js")

//import { coerceToArrayBuffer, coerceToBase64, appendBuffer, tools, arrayBufferEquals } from "../utils.js";
const { coerceToArrayBuffer, coerceToBase64, appendBuffer, tools, arrayBufferEquals } = require("../utils.js")

// https://www.w3.org/TR/webauthn-2/#sctn-apple-anonymous-attestation
Expand Down
27 changes: 24 additions & 3 deletions fido2-node-lib/attestations/fidoU2F.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
//import { abToBuf, abToPem, coerceToArrayBuffer, coerceToBase64, tools } from "../utils.js";
const { abToBuf, abToPem, coerceToArrayBuffer, coerceToBase64, tools } = require("../utils.js")

//import { Certificate, CertManager } from "../certUtils.js";
const { Certificate, CertManager } = require("../certUtils.js")

//import { u2fRootCerts as rootCertList } from "./u2fRootCerts.js";
const rootCertList = require("./u2fRootCerts.js")

function fidoU2fParseFn(attStmt) {
Expand Down Expand Up @@ -36,10 +33,34 @@ function fidoU2fParseFn(attStmt) {
return ret;
}

function arrayBufferEquals(b1, b2) {
if (
!(b1 instanceof ArrayBuffer) ||
!(b2 instanceof ArrayBuffer)
) {
return false;
}

if (b1.byteLength !== b2.byteLength) {
return false;
}
b1 = new Uint8Array(b1);
b2 = new Uint8Array(b2);
for (let i = 0; i < b1.byteLength; i++) {
if (b1[i] !== b2[i]) return false;
}
return true;
}

async function fidoU2fValidateFn() {
const x5c = this.authnrData.get("x5c");
const parsedAttCert = this.authnrData.get("attCert");

const aaguid = this.authnrData.get("aaguid");
if(aaguid && !arrayBufferEquals(new ArrayBuffer(16), aaguid)){
throw new Error("authData.AAGUID is not 0x00 for fido-u2f attestation.");
}

// validate cert chain
if (x5c.length > 0) {
throw new Error("cert chain not validated");
Expand Down
54 changes: 28 additions & 26 deletions fido2-node-lib/attestations/packed.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
//import { arrayBufferEquals, abToPem, appendBuffer, coerceToArrayBuffer, coerceToBase64, tools } from "../utils.js";
const { arrayBufferEquals, abToPem, appendBuffer, coerceToArrayBuffer, coerceToBase64, tools } = require("../utils.js")

//import { Certificate, CertManager } from "../certUtils.js";
const { Certificate, CertManager } = require("../certUtils.js")

//import { u2fRootCerts as rootCertList } from "./u2fRootCerts.js";
const rootCertList = require("./u2fRootCerts.js")

const mds3 = require("../../mds3.js")
Expand Down Expand Up @@ -32,6 +29,9 @@ const algMap = new Map([
}],
]);

const authenticator_dangerous_status=["USER_VERIFICATION_BYPASS", "ATTESTATION_KEY_COMPROMISE",
"USER_KEY_REMOTE_COMPROMISE", "USER_KEY_PHYSICAL_COMPROMISE"];

function packedParseFn(attStmt) {
const ret = new Map();

Expand Down Expand Up @@ -174,6 +174,21 @@ async function validateCerts(parsedAttCert, aaguid, _x5c, audit) {
}*/
}

var meta_entry
if(aaguid){
//console.log(buf2hex(aaguid)) // for debug
meta_entry = await mds3.mds3_client.findByAAGUID(aaguid)

if(meta_entry.statusReports){
meta_entry.statusReports.forEach((status)=>{
if(authenticator_dangerous_status.includes(status.status)){
throw new Error("Authenticator dangerous status.");
}
}
);
}
}

// decode attestation cert
const attCert = new Certificate(coerceToBase64(parsedAttCert, "parsedAttCert"));

Expand All @@ -192,17 +207,8 @@ async function validateCerts(parsedAttCert, aaguid, _x5c, audit) {
}

let roots = []// Array.from(CertManager.getCerts().values())

if(aaguid){
try{
const aa_entries = await mds3.mds3_client.findByAAGUID(aaguid)
if(aa_entries){
//aa_entries.attestationRootCertificates.forEach((ent) => roots.unshift(new Certificate(ent)));
aa_entries.attestationRootCertificates.forEach((ent) => roots.push(new Certificate(ent)));
}
}catch (e) {
console.log(e.message);
}
if(meta_entry){
meta_entry.attestationRootCertificates.forEach((ent) => roots.push(new Certificate(ent)));
}

try{
Expand All @@ -212,16 +218,12 @@ async function validateCerts(parsedAttCert, aaguid, _x5c, audit) {
}
} else {//Verify one cert
CertManager.removeAll();
if(aaguid){
try{
console.log(buf2hex(aaguid))
const aa_entries = await mds3.mds3_client.findByAAGUID(aaguid)
if(aa_entries){
aa_entries.attestationRootCertificates.forEach((ent) => CertManager.addCert(ent));
}
}catch (e) {
console.log(e.message);
}
if(meta_entry){
if(meta_entry.attestationRootCertificates){
meta_entry.attestationRootCertificates.forEach((ent) => CertManager.addCert(ent));
} else if(meta_entry.metadataStatement && meta_entry.metadataStatement.attestationRootCertificates){
meta_entry.metadataStatement.attestationRootCertificates.forEach((ent) => CertManager.addCert(ent));
}
}

//for debug
Expand Down Expand Up @@ -261,8 +263,8 @@ async function validateCerts(parsedAttCert, aaguid, _x5c, audit) {
attCert.info.forEach((v, k) => audit.info.set(k, v));
attCert.warning.forEach((v, k) => audit.warning.set(k, v));
audit.journal.add("attCert");
// console.log("_cert", attCert._cert);
// console.log("_cert.subject", attCert._cert.subject);
//console.log("_cert", attCert._cert);
//console.log("_cert.subject", attCert._cert.subject);

// from: https://w3c.github.io/webauthn/#packed-attestation
// Version MUST be set to 3 (which is indicated by an ASN.1 INTEGER with value 2).
Expand Down
5 changes: 1 addition & 4 deletions fido2-node-lib/attestations/tpm.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
//import { arrayBufferEquals, abToBuf, abToInt, abToPem, appendBuffer, coerceToArrayBuffer, coerceToBase64, tools } from "../utils.js";
const { arrayBufferEquals, abToBuf, abToInt, abToPem, appendBuffer, coerceToArrayBuffer, coerceToBase64, tools } = require("../utils.js")

//import { Certificate } from "../certUtils.js";
const Certificate = require("../certUtils.js")
const { Certificate } = require("../certUtils.js")

//import { coseAlgToHashStr, coseAlgToStr } from "../keyUtils.js";
const { coseAlgToHashStr, coseAlgToStr } = require("../keyUtils.js")

function tpmParseFn(attStmt) {
Expand Down
17 changes: 4 additions & 13 deletions fido2-node-lib/certUtils.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,6 @@
//import { ab2str, coerceToArrayBuffer, isPem, pemToBase64, tools } from "./utils.js";
const { ab2str, coerceToArrayBuffer, isPem, pemToBase64, tools } = require("./utilsCore.js")
/*const utils = require("./utils.js")
ab2str = utils.ab2str
coerceToArrayBuffer = utils.coerceToArrayBuffer
isPem = utils.isPem
pemToBase64 = utils.pemToBase64
tools = utils.tools*/
const { ab2str, coerceToArrayBuffer, isPem, pemToBase64 } = require("./utilsCore.js")

//const tools = require("./toolbox.js")

//require("./utilsCore.js");
const tools = require("./toolbox.js")

class Certificate {
constructor(cert) {
Expand Down Expand Up @@ -294,8 +285,8 @@ function resolveOid(id, value) {

function decodeValue(valueBlock) {
const blockType = Object.getPrototypeOf(valueBlock).constructor.name;
// console.log("blockType", blockType);
// console.log("valueBlock", valueBlock);
//console.log("blockType", blockType);
//console.log("valueBlock", valueBlock);
switch (blockType) {
case "LocalOctetStringValueBlock":
return valueBlock.valueHex;
Expand Down
8 changes: 3 additions & 5 deletions fido2-node-lib/keyUtils.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
//import { coerceToArrayBuffer, coerceToBase64Url, isPem, pemToBase64, abToPem, tools } from "./utils.js";
//const theUtils = require("./utils.js")
var coerceToArrayBuffer
var coerceToBase64Url
var isPem
Expand Down Expand Up @@ -40,7 +38,7 @@ const coseLabels = {
"-257": "RSASSA-PKCS1-v1_5_w_SHA256",
"-258": "RSASSA-PKCS1-v1_5_w_SHA384",
"-259": "RSASSA-PKCS1-v1_5_w_SHA512",
"-65535": "RSASSA-PKCS1-v1_5_w_SHA1",
"-65535": "RSASSA-PKCS1-v1_5_w_SHA1"
},
},
4: {
Expand Down Expand Up @@ -121,7 +119,7 @@ const algToJWKAlg = {
"RSASSA-PKCS1-v1_5_w_SHA256": "RS256",
"RSASSA-PKCS1-v1_5_w_SHA384": "RS384",
"RSASSA-PKCS1-v1_5_w_SHA512": "RS512",
"RSASSA-PKCS1-v1_5_w_SHA1": "RS256",
"RSASSA-PKCS1-v1_5_w_SHA1": "RS1",
/*
PS256-512 is untested
"RSASSA-PSS_w_SHA-256": "PS256",
Expand Down Expand Up @@ -158,7 +156,7 @@ const algorithmInputMap = {
"RS256": "RSASSA-PKCS1-v1_5",
"RS384": "RSASSA-PKCS1-v1_5",
"RS512": "RSASSA-PKCS1-v1_5",
//"RS1": "RSASSA-PKCS1-v1_5",//dqj
"RS1": "RSASSA-PKCS1-v1_5",
/*"PS256": "RSASSA-PSS",
"PS384": "RSASSA-PSS",
"PS512": "RSASSA-PSS",*/
Expand Down
Loading

0 comments on commit e8b6f4f

Please sign in to comment.