@blamejs/pki 0.6.39 → 0.6.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/lib/attrcert-sign.js +2 -2
- package/lib/cmp-session.js +4 -4
- package/lib/cmp-verify.js +4 -8
- package/lib/cms-verify.js +7 -7
- package/lib/crl-sign.js +8 -8
- package/lib/csr-sign.js +2 -2
- package/lib/ct.js +14 -14
- package/lib/guard-bytes.js +1 -1
- package/lib/guard-identifier.js +1 -1
- package/lib/guard-json.js +1 -1
- package/lib/guard-list.js +16 -0
- package/lib/guard-parsed.js +1 -1
- package/lib/guard-verdict.js +7 -1
- package/lib/ip-utils.js +1 -1
- package/lib/path-validate.js +95 -95
- package/lib/pkcs12-build.js +11 -9
- package/lib/sigstore.js +16 -7
- package/lib/smime.js +4 -4
- package/lib/tsp-sign.js +19 -19
- package/lib/webauthn.js +46 -42
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
package/lib/path-validate.js
CHANGED
|
@@ -316,7 +316,7 @@ function decodeExt(cert, extOid) {
|
|
|
316
316
|
|
|
317
317
|
function requireCriticalExt(ext, name, checks) {
|
|
318
318
|
if (ext && ext.critical !== true) {
|
|
319
|
-
|
|
319
|
+
guard.list.append(checks,{ name: name, ok: false, code: "path/extension-not-critical" });
|
|
320
320
|
return E("path/extension-not-critical", name + " extension must be marked critical (RFC 5280 4.2.1)");
|
|
321
321
|
}
|
|
322
322
|
return null;
|
|
@@ -454,17 +454,17 @@ function certNameForms(cert) {
|
|
|
454
454
|
if (san) {
|
|
455
455
|
san.value.names.forEach(function (nm) {
|
|
456
456
|
if (nm.tagNumber === 1) hasRfc822San = true;
|
|
457
|
-
|
|
457
|
+
guard.list.append(forms, { tag: nm.tagNumber, value: nm.value === undefined ? null : nm.value });
|
|
458
458
|
});
|
|
459
459
|
}
|
|
460
460
|
if (!hasRfc822San) {
|
|
461
461
|
cert.subject.rdns.forEach(function (rdn) {
|
|
462
462
|
rdn.forEach(function (atv) {
|
|
463
|
-
if (atv.type === OID.emailAddress && typeof atv.value === "string")
|
|
463
|
+
if (atv.type === OID.emailAddress && typeof atv.value === "string") guard.list.append(forms, { tag: 1, value: atv.value });
|
|
464
464
|
});
|
|
465
465
|
});
|
|
466
466
|
}
|
|
467
|
-
if (cert.subject.rdns.length > 0)
|
|
467
|
+
if (cert.subject.rdns.length > 0) guard.list.append(forms, { tag: 4, value: cert.subject });
|
|
468
468
|
return forms;
|
|
469
469
|
}
|
|
470
470
|
|
|
@@ -497,12 +497,12 @@ function checkNameConstraints(state, cert) {
|
|
|
497
497
|
|
|
498
498
|
function absorbNameConstraints(state, decoded) {
|
|
499
499
|
if (decoded.permittedSubtrees.length) {
|
|
500
|
-
state.permittedGenerations
|
|
500
|
+
guard.list.append(state.permittedGenerations, decoded.permittedSubtrees.map(function (st) {
|
|
501
501
|
return { tag: st.base.tagNumber, base: st.base.value };
|
|
502
502
|
}));
|
|
503
503
|
}
|
|
504
504
|
decoded.excludedSubtrees.forEach(function (st) {
|
|
505
|
-
state.excludedSubtrees
|
|
505
|
+
guard.list.append(state.excludedSubtrees, { tag: st.base.tagNumber, base: st.base.value });
|
|
506
506
|
});
|
|
507
507
|
}
|
|
508
508
|
|
|
@@ -524,7 +524,7 @@ function leavesAt(tree, depth) {
|
|
|
524
524
|
var out = [];
|
|
525
525
|
if (!tree) return out;
|
|
526
526
|
(function walk(node) {
|
|
527
|
-
if (node.depth === depth) {
|
|
527
|
+
if (node.depth === depth) { guard.list.append(out, node); return; }
|
|
528
528
|
node.children.forEach(walk);
|
|
529
529
|
})(tree);
|
|
530
530
|
return out;
|
|
@@ -563,7 +563,7 @@ function checkedSubtreeSeeds(list, optName) {
|
|
|
563
563
|
* array's constructor and Symbol.species, which is more caller code running mid-copy. */
|
|
564
564
|
var seedsOut = [];
|
|
565
565
|
for (var si = 0; si < list.length; si++) {
|
|
566
|
-
|
|
566
|
+
guard.list.append(seedsOut, (function (st) {
|
|
567
567
|
var shapeMsg = "validate: opts." + optName + " entries must be { tag: <GeneralName tag number 0..8>, base: <that form's constraint value> }";
|
|
568
568
|
if (!st || typeof st !== "object" || intrinsic.types.isProxy(st)) throw E("path/bad-input", shapeMsg);
|
|
569
569
|
/** @internal Read tag and base once each, from their own data properties: an accessor could
|
|
@@ -639,7 +639,7 @@ function selfIssued(cert) {
|
|
|
639
639
|
function processPolicies(state, cert, i, checks) {
|
|
640
640
|
var cp;
|
|
641
641
|
try { cp = decodeExt(cert, OID.certificatePolicies); }
|
|
642
|
-
catch (e) {
|
|
642
|
+
catch (e) { guard.list.append(checks,{ name: "policies", ok: false, code: "path/bad-policy" }); return { fatal: true, error: e }; }
|
|
643
643
|
|
|
644
644
|
if (cp && state.validPolicyTree) {
|
|
645
645
|
var policies = cp.value;
|
|
@@ -678,7 +678,7 @@ function processPolicies(state, cert, i, checks) {
|
|
|
678
678
|
}
|
|
679
679
|
|
|
680
680
|
if (!(state.explicitPolicy > 0 || state.validPolicyTree !== null)) {
|
|
681
|
-
|
|
681
|
+
guard.list.append(checks,{ name: "policy", ok: false, code: "path/policy-required" });
|
|
682
682
|
return { fatal: true, error: E("path/policy-required", "explicit policy required but the valid-policy tree is empty") };
|
|
683
683
|
}
|
|
684
684
|
return { fatal: false };
|
|
@@ -687,7 +687,7 @@ function processPolicies(state, cert, i, checks) {
|
|
|
687
687
|
function addChild(state, parent, validPolicy, qualifiers, expectedPolicySet, checks) {
|
|
688
688
|
if (state.policyNodeCount >= state.maxPolicyNodes) { state._capHit = true; return; }
|
|
689
689
|
var node = { depth: parent.depth + 1, validPolicy: validPolicy, qualifierSet: qualifiers ? [qualifiers] : [], expectedPolicySet: expectedPolicySet, children: [], parent: parent };
|
|
690
|
-
parent.children
|
|
690
|
+
guard.list.append(parent.children, node);
|
|
691
691
|
state.policyNodeCount++;
|
|
692
692
|
void checks;
|
|
693
693
|
}
|
|
@@ -722,11 +722,11 @@ function ekuPurposeFails(cert, requiredEku, checks) {
|
|
|
722
722
|
var eku;
|
|
723
723
|
try { eku = decodeExt(cert, OID.extKeyUsage); }
|
|
724
724
|
// allow:fail-open-verify -- ekuPurposeFails returns true to mean the EKU purpose FAILS (a rejecting verdict); a bad extension is recorded in checks and the purpose is treated as failed, which is fail-closed
|
|
725
|
-
catch (e) {
|
|
725
|
+
catch (e) { guard.list.append(checks,{ name: "extendedKeyUsage", ok: false, code: pathCode(e, "path/bad-extension-value") }); return true; }
|
|
726
726
|
if (!eku) return false;
|
|
727
727
|
var purposes = eku.value;
|
|
728
728
|
var ok = contains(purposes, OID.anyExtendedKeyUsage) || containsAll(purposes, requiredEku);
|
|
729
|
-
|
|
729
|
+
guard.list.append(checks,{ name: "extendedKeyUsage", ok: ok, code: ok ? undefined : "path/eku-not-permitted" });
|
|
730
730
|
return !ok;
|
|
731
731
|
}
|
|
732
732
|
|
|
@@ -739,10 +739,10 @@ function prepareNext(state, cert, i, checks) {
|
|
|
739
739
|
|
|
740
740
|
var pm;
|
|
741
741
|
try { pm = decodeExt(cert, OID.policyMappings); }
|
|
742
|
-
catch (e) {
|
|
742
|
+
catch (e) { guard.list.append(checks,{ name: "policyMappings", ok: false, code: "path/bad-policy" }); return { fatal: true, error: e }; }
|
|
743
743
|
if (pm) {
|
|
744
744
|
var badAny = mapsAnyPolicy(pm.value);
|
|
745
|
-
if (badAny) {
|
|
745
|
+
if (badAny) { guard.list.append(checks,{ name: "policyMappings", ok: false, code: "path/bad-policy" }); return { fatal: true, error: E("path/bad-policy", "policyMappings must not map to or from anyPolicy (RFC 5280 6.1.4(a))") }; }
|
|
746
746
|
if (state.validPolicyTree) applyPolicyMappings(state, pm.value, i);
|
|
747
747
|
}
|
|
748
748
|
|
|
@@ -751,7 +751,7 @@ function prepareNext(state, cert, i, checks) {
|
|
|
751
751
|
|
|
752
752
|
var nc;
|
|
753
753
|
try { nc = decodeExt(cert, OID.nameConstraints); }
|
|
754
|
-
catch (e) {
|
|
754
|
+
catch (e) { guard.list.append(checks,{ name: "nameConstraints", ok: false, code: pathCode(e, "path/bad-name-constraints") }); return { fatal: true, error: e }; }
|
|
755
755
|
var ncCritErr = requireCriticalExt(nc, "nameConstraints", checks);
|
|
756
756
|
if (ncCritErr) return { fatal: true, error: ncCritErr };
|
|
757
757
|
if (nc) absorbNameConstraints(state, nc.value);
|
|
@@ -764,7 +764,7 @@ function prepareNext(state, cert, i, checks) {
|
|
|
764
764
|
|
|
765
765
|
var pc;
|
|
766
766
|
try { pc = decodeExt(cert, OID.policyConstraints); }
|
|
767
|
-
catch (e) {
|
|
767
|
+
catch (e) { guard.list.append(checks,{ name: "policyConstraints", ok: false, code: "path/bad-policy" }); return { fatal: true, error: e }; }
|
|
768
768
|
var pcCritErr = requireCriticalExt(pc, "policyConstraints", checks);
|
|
769
769
|
if (pcCritErr) return { fatal: true, error: pcCritErr };
|
|
770
770
|
if (pc) {
|
|
@@ -773,31 +773,31 @@ function prepareNext(state, cert, i, checks) {
|
|
|
773
773
|
}
|
|
774
774
|
var iap;
|
|
775
775
|
try { iap = decodeExt(cert, OID.inhibitAnyPolicy); }
|
|
776
|
-
catch (e) {
|
|
776
|
+
catch (e) { guard.list.append(checks,{ name: "inhibitAnyPolicy", ok: false, code: "path/bad-policy" }); return { fatal: true, error: e }; }
|
|
777
777
|
var iapCritErr = requireCriticalExt(iap, "inhibitAnyPolicy", checks);
|
|
778
778
|
if (iapCritErr) return { fatal: true, error: iapCritErr };
|
|
779
779
|
if (iap && iap.value < state.inhibitAnyPolicy) state.inhibitAnyPolicy = iap.value;
|
|
780
780
|
|
|
781
781
|
var bc;
|
|
782
782
|
try { bc = decodeExt(cert, OID.basicConstraints); }
|
|
783
|
-
catch (e) {
|
|
783
|
+
catch (e) { guard.list.append(checks,{ name: "basicConstraints", ok: false, code: "path/bad-basic-constraints" }); return { fatal: true, error: e }; }
|
|
784
784
|
if (!bc || bc.value.cA !== true) {
|
|
785
|
-
|
|
785
|
+
guard.list.append(checks,{ name: "basicConstraints", ok: false, code: "path/not-a-ca" });
|
|
786
786
|
return { fatal: true, error: E("path/not-a-ca", "intermediate certificate is not a CA (basicConstraints cA is not TRUE, RFC 5280 6.1.4(k))") };
|
|
787
787
|
}
|
|
788
788
|
var bcCritErr = requireCriticalExt(bc, "basicConstraints", checks);
|
|
789
789
|
if (bcCritErr) return { fatal: true, error: bcCritErr };
|
|
790
790
|
if (!isSelfIssued) {
|
|
791
|
-
if (state.maxPathLength <= 0) {
|
|
791
|
+
if (state.maxPathLength <= 0) { guard.list.append(checks,{ name: "pathLength", ok: false, code: "path/path-length-exceeded" }); return { fatal: true, error: E("path/path-length-exceeded", "certification path is longer than the CA path-length constraint allows") }; }
|
|
792
792
|
state.maxPathLength--;
|
|
793
793
|
}
|
|
794
794
|
if (bc.value.pathLenConstraint !== null && bc.value.pathLenConstraint < state.maxPathLength) state.maxPathLength = bc.value.pathLenConstraint;
|
|
795
795
|
|
|
796
796
|
var ku;
|
|
797
797
|
try { ku = decodeExt(cert, OID.keyUsage); }
|
|
798
|
-
catch (e) {
|
|
798
|
+
catch (e) { guard.list.append(checks,{ name: "keyUsage", ok: false, code: "path/bad-key-usage" }); return { fatal: true, error: e }; }
|
|
799
799
|
if (ku && ku.value.keyCertSign !== true) {
|
|
800
|
-
|
|
800
|
+
guard.list.append(checks,{ name: "keyUsage", ok: false, code: "path/missing-key-cert-sign" });
|
|
801
801
|
return { fatal: true, error: E("path/missing-key-cert-sign", "CA certificate keyUsage does not assert keyCertSign (RFC 5280 6.1.4(n))") };
|
|
802
802
|
}
|
|
803
803
|
return { fatal: false };
|
|
@@ -807,7 +807,7 @@ function applyPolicyMappings(state, mappings, i) {
|
|
|
807
807
|
var depth = i;
|
|
808
808
|
if (state.policyMapping > 0) {
|
|
809
809
|
var mappedFrom = {};
|
|
810
|
-
mappings.forEach(function (m) { (mappedFrom[m.issuerDomainPolicy] = mappedFrom[m.issuerDomainPolicy] || []
|
|
810
|
+
mappings.forEach(function (m) { guard.list.append(mappedFrom[m.issuerDomainPolicy] = mappedFrom[m.issuerDomainPolicy] || [], m.subjectDomainPolicy); });
|
|
811
811
|
var depthI = leavesAt(state.validPolicyTree, depth);
|
|
812
812
|
var anyNodes = depthI.filter(function (nd) { return nd.validPolicy === OID.anyPolicy; });
|
|
813
813
|
Object.keys(mappedFrom).forEach(function (idp) {
|
|
@@ -953,14 +953,14 @@ async function ctGateCheck(leaf, certs, anchor, ctLogList, ctPolicy, n, at) {
|
|
|
953
953
|
for (var i = 0; i < exts.length; i++) {
|
|
954
954
|
if (exts[i] && (exts[i].oid === OID_SCT_LIST || exts[i].name === "signedCertificateTimestampList")) { sctExt = exts[i]; break; }
|
|
955
955
|
}
|
|
956
|
-
if (sctExt == null) return { name: "ct", ok: false, code: "path/ct-required" };
|
|
956
|
+
if (sctExt == null) return guard.verdict.of({ name: "ct", ok: false, code: "path/ct-required" });
|
|
957
957
|
var issuer = n >= 2 ? certs[n - 2] : { subjectPublicKeyInfo: { bytes: anchor.publicKey } };
|
|
958
958
|
var entry, list;
|
|
959
959
|
try {
|
|
960
960
|
entry = ct.x509CertEntry(leaf, issuer);
|
|
961
961
|
list = ct.parseSctList(sctExt.value);
|
|
962
962
|
} catch (e) {
|
|
963
|
-
return { name: "ct", ok: false, code: pathCode(e, "path/ct-required") };
|
|
963
|
+
return guard.verdict.of({ name: "ct", ok: false, code: pathCode(e, "path/ct-required") });
|
|
964
964
|
}
|
|
965
965
|
var verdict;
|
|
966
966
|
try {
|
|
@@ -970,7 +970,7 @@ async function ctGateCheck(leaf, certs, anchor, ctLogList, ctPolicy, n, at) {
|
|
|
970
970
|
if (e && e.isPkiError) throw E("path/bad-input", "validate: the CT policy or log-list is invalid (" + (e.code || "ct/bad-input") + "): " + e.message);
|
|
971
971
|
throw e;
|
|
972
972
|
}
|
|
973
|
-
return { name: "ct", ok: verdict.policyOk === true, code: verdict.policyOk ? undefined : "path/ct-policy-not-met" };
|
|
973
|
+
return guard.verdict.of({ name: "ct", ok: verdict.policyOk === true, code: verdict.policyOk ? undefined : "path/ct-policy-not-met" });
|
|
974
974
|
}
|
|
975
975
|
|
|
976
976
|
async function validate(path, opts) {
|
|
@@ -1080,18 +1080,18 @@ async function validate(path, opts) {
|
|
|
1080
1080
|
} else {
|
|
1081
1081
|
sigRes = await builtinVerify(state, cert);
|
|
1082
1082
|
}
|
|
1083
|
-
|
|
1083
|
+
guard.list.append(checks, { name: "signature", ok: sigRes.ok, code: sigRes.ok ? undefined : (sigRes.code || "path/bad-signature") });
|
|
1084
1084
|
if (!sigRes.ok) failed = true;
|
|
1085
1085
|
|
|
1086
1086
|
if (compositeSig.COMPOSITE_ALGS[cert.subjectPublicKeyInfo.algorithm.oid]) {
|
|
1087
1087
|
var cku = compositeKeyUsageCheck(cert);
|
|
1088
|
-
|
|
1088
|
+
guard.list.append(checks,{ name: "compositeKeyUsage", ok: cku.ok, code: cku.ok ? undefined : cku.code });
|
|
1089
1089
|
if (!cku.ok) failed = true;
|
|
1090
1090
|
}
|
|
1091
1091
|
|
|
1092
1092
|
if (ML_KEM_OIDS[cert.subjectPublicKeyInfo.algorithm.oid]) {
|
|
1093
1093
|
var kku = kemKeyUsageCheck(cert);
|
|
1094
|
-
|
|
1094
|
+
guard.list.append(checks,{ name: "kemKeyUsage", ok: kku.ok, code: kku.ok ? undefined : kku.code });
|
|
1095
1095
|
if (!kku.ok) failed = true;
|
|
1096
1096
|
}
|
|
1097
1097
|
|
|
@@ -1099,20 +1099,20 @@ async function validate(path, opts) {
|
|
|
1099
1099
|
var vOk = true, vCode;
|
|
1100
1100
|
if (t < guard.time.instantOf(cert.validity.notBefore)) { vOk = false; vCode = "path/not-yet-valid"; }
|
|
1101
1101
|
else if (t > guard.time.instantOf(cert.validity.notAfter)) { vOk = false; vCode = "path/expired"; }
|
|
1102
|
-
|
|
1102
|
+
guard.list.append(checks,{ name: "validity", ok: vOk, code: vCode });
|
|
1103
1103
|
if (!vOk) failed = true;
|
|
1104
1104
|
|
|
1105
1105
|
var chainOk;
|
|
1106
1106
|
try { chainOk = dnEqual(cert.issuer.rdns, state.workingIssuerName.rdns); }
|
|
1107
1107
|
catch (_e) { chainOk = false; }
|
|
1108
|
-
|
|
1108
|
+
guard.list.append(checks,{ name: "nameChaining", ok: chainOk === true, code: chainOk === true ? undefined : "path/name-chaining" });
|
|
1109
1109
|
if (chainOk !== true) failed = true;
|
|
1110
1110
|
|
|
1111
1111
|
if (!(selfIssued(cert) && i !== n)) {
|
|
1112
1112
|
var ncRes;
|
|
1113
1113
|
try { ncRes = checkNameConstraints(state, cert); }
|
|
1114
1114
|
catch (e) { ncRes = { ok: false, code: pathCode(e, "path/bad-name-constraints") }; }
|
|
1115
|
-
|
|
1115
|
+
guard.list.append(checks,{ name: "nameConstraints", ok: ncRes.ok, code: ncRes.ok ? undefined : ncRes.code });
|
|
1116
1116
|
if (!ncRes.ok) failed = true;
|
|
1117
1117
|
}
|
|
1118
1118
|
|
|
@@ -1122,33 +1122,33 @@ async function validate(path, opts) {
|
|
|
1122
1122
|
try { rv = await revocationChecker.check(cert, { workingIssuerName: state.workingIssuerName, workingPublicKey: state.workingPublicKey, workingPublicKeyAlgorithm: state.workingPublicKeyAlgorithm, issuerCert: issuerCert }, { time: opts.time, historicalMode: opts.historicalMode === true }); }
|
|
1123
1123
|
catch (e) { rv = { status: "error" }; rvError = e; }
|
|
1124
1124
|
var rvStatus = (rv && typeof rv.status === "string") ? rv.status : "unknown";
|
|
1125
|
-
if (rv && rv.status === "good") {
|
|
1126
|
-
else if (rv && rv.status === "revoked") {
|
|
1125
|
+
if (rv && rv.status === "good") { guard.list.append(checks,{ name: "revocation", ok: true, status: "good" }); }
|
|
1126
|
+
else if (rv && rv.status === "revoked") { guard.list.append(checks,{ name: "revocation", ok: false, status: "revoked", code: "path/revoked" }); failed = true; }
|
|
1127
1127
|
else if (rvError) {
|
|
1128
|
-
|
|
1128
|
+
guard.list.append(checks,{ name: "revocation", ok: false, status: "error", code: "path/revocation-checker-error", error: rvError });
|
|
1129
1129
|
revocationUndetermined = true;
|
|
1130
1130
|
failed = true;
|
|
1131
1131
|
}
|
|
1132
1132
|
else if (softFail) {
|
|
1133
|
-
|
|
1133
|
+
guard.list.append(checks,{ name: "revocation", ok: true, status: rvStatus, waived: true });
|
|
1134
1134
|
revocationWaived = true;
|
|
1135
1135
|
} else {
|
|
1136
|
-
|
|
1136
|
+
guard.list.append(checks,{ name: "revocation", ok: false, status: rvStatus, code: "path/revocation-undetermined" });
|
|
1137
1137
|
revocationUndetermined = true;
|
|
1138
1138
|
failed = true;
|
|
1139
1139
|
}
|
|
1140
1140
|
revocationRan = true;
|
|
1141
1141
|
} else if (requireRevocation) {
|
|
1142
|
-
|
|
1142
|
+
guard.list.append(checks,{ name: "revocation", ok: false, code: "path/revocation-undetermined" }); failed = true;
|
|
1143
1143
|
}
|
|
1144
1144
|
|
|
1145
1145
|
var polRes = processPolicies(state, cert, i, checks);
|
|
1146
|
-
if (state._capHit) {
|
|
1146
|
+
if (state._capHit) { guard.list.append(checks,{ name: "policyTree", ok: false, code: "path/policy-tree-cap" }); failed = true; }
|
|
1147
1147
|
else if (polRes.fatal) failed = true;
|
|
1148
1148
|
|
|
1149
1149
|
if (cert.subject.rdns.length === 0) {
|
|
1150
1150
|
var san = findExt(cert, OID.subjectAltName);
|
|
1151
|
-
if (!san || !san.critical) {
|
|
1151
|
+
if (!san || !san.critical) { guard.list.append(checks,{ name: "emptySubject", ok: false, code: "path/empty-subject-no-critical-san" }); failed = true; }
|
|
1152
1152
|
}
|
|
1153
1153
|
|
|
1154
1154
|
if (i !== n) {
|
|
@@ -1160,22 +1160,22 @@ async function validate(path, opts) {
|
|
|
1160
1160
|
if (state.explicitPolicy > 0) state.explicitPolicy--;
|
|
1161
1161
|
var lpc;
|
|
1162
1162
|
try { lpc = decodeExt(cert, OID.policyConstraints); }
|
|
1163
|
-
catch (_e) { lpc = null;
|
|
1163
|
+
catch (_e) { lpc = null; guard.list.append(checks,{ name: "policyConstraints", ok: false, code: "path/bad-policy" }); failed = true; }
|
|
1164
1164
|
if (requireCriticalExt(lpc, "policyConstraints", checks)) failed = true;
|
|
1165
1165
|
if (lpc && lpc.value.requireExplicitPolicy === 0) state.explicitPolicy = 0;
|
|
1166
1166
|
var lpm;
|
|
1167
1167
|
try { lpm = decodeExt(cert, OID.policyMappings); }
|
|
1168
|
-
catch (_e) { lpm = null;
|
|
1168
|
+
catch (_e) { lpm = null; guard.list.append(checks,{ name: "policyMappings", ok: false, code: "path/bad-policy" }); failed = true; }
|
|
1169
1169
|
if (lpm && mapsAnyPolicy(lpm.value)) {
|
|
1170
|
-
|
|
1170
|
+
guard.list.append(checks,{ name: "policyMappings", ok: false, code: "path/bad-policy" }); failed = true;
|
|
1171
1171
|
}
|
|
1172
1172
|
var lnc;
|
|
1173
1173
|
try { lnc = decodeExt(cert, OID.nameConstraints); }
|
|
1174
|
-
catch (e) { lnc = null;
|
|
1174
|
+
catch (e) { lnc = null; guard.list.append(checks,{ name: "nameConstraints", ok: false, code: pathCode(e, "path/bad-name-constraints") }); failed = true; }
|
|
1175
1175
|
if (requireCriticalExt(lnc, "nameConstraints", checks)) failed = true;
|
|
1176
1176
|
var liap;
|
|
1177
1177
|
try { liap = decodeExt(cert, OID.inhibitAnyPolicy); }
|
|
1178
|
-
catch (e) { liap = null;
|
|
1178
|
+
catch (e) { liap = null; guard.list.append(checks,{ name: "inhibitAnyPolicy", ok: false, code: pathCode(e, "path/bad-policy") }); failed = true; }
|
|
1179
1179
|
if (requireCriticalExt(liap, "inhibitAnyPolicy", checks)) failed = true;
|
|
1180
1180
|
if (requiredEku && ekuPurposeFails(cert, requiredEku, checks)) failed = true;
|
|
1181
1181
|
var ta = anchor;
|
|
@@ -1183,25 +1183,25 @@ async function validate(path, opts) {
|
|
|
1183
1183
|
if (distrustDate != null) {
|
|
1184
1184
|
anchorDistrustApplied = true;
|
|
1185
1185
|
if (guard.time.instantOf(cert.validity.notBefore) > guard.time.instantOf(distrustDate)) {
|
|
1186
|
-
|
|
1186
|
+
guard.list.append(checks,{ name: "distrustAfter", ok: false, code: "path/distrusted-after" }); failed = true;
|
|
1187
1187
|
}
|
|
1188
1188
|
}
|
|
1189
1189
|
if (checkPurpose && ta.purposes) {
|
|
1190
1190
|
anchorPurposeApplied = true;
|
|
1191
1191
|
if (!intrinsic.hasOwn(ta.purposes, checkPurpose) || ta.purposes[checkPurpose] !== true) {
|
|
1192
|
-
|
|
1192
|
+
guard.list.append(checks,{ name: "purposeTrust", ok: false, code: "path/purpose-not-trusted" }); failed = true;
|
|
1193
1193
|
}
|
|
1194
1194
|
}
|
|
1195
1195
|
updateWorkingKey(state, cert);
|
|
1196
1196
|
}
|
|
1197
1197
|
|
|
1198
1198
|
var unk = unrecognizedCriticalExtension(cert, i === n);
|
|
1199
|
-
if (unk) {
|
|
1199
|
+
if (unk) { guard.list.append(checks,{ name: "criticalExtensions", ok: false, code: "path/unrecognized-critical-extension" }); failed = true; }
|
|
1200
1200
|
|
|
1201
1201
|
var crit = validateCriticalExtensionStructure(cert);
|
|
1202
|
-
if (crit) {
|
|
1202
|
+
if (crit) { guard.list.append(checks,{ name: "criticalExtensionValue", ok: false, code: crit }); failed = true; }
|
|
1203
1203
|
|
|
1204
|
-
state.results
|
|
1204
|
+
guard.list.append(state.results, { index: idx, checks: checks });
|
|
1205
1205
|
}
|
|
1206
1206
|
|
|
1207
1207
|
var ucps = userConstrainedPolicies(state, n);
|
|
@@ -1209,7 +1209,7 @@ async function validate(path, opts) {
|
|
|
1209
1209
|
if (!policyOk) {
|
|
1210
1210
|
var last = state.results[state.results.length - 1];
|
|
1211
1211
|
if (!guard.list.anyMatches(last.checks, function (c) { return c.code === "path/policy-required"; })) {
|
|
1212
|
-
last.checks
|
|
1212
|
+
guard.list.append(last.checks, { name: "policy", ok: false, code: "path/policy-required" });
|
|
1213
1213
|
}
|
|
1214
1214
|
failed = true;
|
|
1215
1215
|
}
|
|
@@ -1218,11 +1218,11 @@ async function validate(path, opts) {
|
|
|
1218
1218
|
var ctCheck = await ctGateCheck(certs[n - 1], certs, anchor, opts.ctLogList, opts.ctPolicy || {}, n, opts.time);
|
|
1219
1219
|
var target = null;
|
|
1220
1220
|
for (var tr = 0; tr < state.results.length; tr++) { if (state.results[tr].index === n - 1) { target = state.results[tr]; break; } }
|
|
1221
|
-
if (target)
|
|
1221
|
+
if (target) guard.list.append(target.checks, ctCheck);
|
|
1222
1222
|
if (!ctCheck.ok) failed = true;
|
|
1223
1223
|
}
|
|
1224
1224
|
|
|
1225
|
-
return {
|
|
1225
|
+
return guard.verdict.of({
|
|
1226
1226
|
valid: !failed,
|
|
1227
1227
|
revocationChecked: !revocationRan ? false
|
|
1228
1228
|
: revocationUndetermined ? "undetermined"
|
|
@@ -1240,7 +1240,7 @@ async function validate(path, opts) {
|
|
|
1240
1240
|
workingPublicKeyParameters: state.workingPublicKeyParameters,
|
|
1241
1241
|
validPolicyTree: treeWithoutParent(state.validPolicyTree),
|
|
1242
1242
|
userConstrainedPolicySet: ucps,
|
|
1243
|
-
};
|
|
1243
|
+
});
|
|
1244
1244
|
}
|
|
1245
1245
|
|
|
1246
1246
|
function userConstrainedPolicies(state, n) {
|
|
@@ -1379,13 +1379,13 @@ function classifyCrls(parsed) {
|
|
|
1379
1379
|
baseCrlNumber: null,
|
|
1380
1380
|
mergeable: false,
|
|
1381
1381
|
};
|
|
1382
|
-
if (deltaRaw === null) {
|
|
1382
|
+
if (deltaRaw === null) { guard.list.append(completes, rec); continue; }
|
|
1383
1383
|
try {
|
|
1384
1384
|
var n = asn1.read.integer(asn1.decode(deltaRaw));
|
|
1385
1385
|
if (crlNumberWithinBound(n) && deltaCritical) { rec.baseCrlNumber = n; rec.mergeable = true; }
|
|
1386
1386
|
} catch (_e) {
|
|
1387
1387
|
}
|
|
1388
|
-
|
|
1388
|
+
guard.list.append(deltas, rec);
|
|
1389
1389
|
}
|
|
1390
1390
|
return { completes: completes, deltas: deltas };
|
|
1391
1391
|
}
|
|
@@ -1494,7 +1494,7 @@ function crlChecker(crls, opts) {
|
|
|
1494
1494
|
var iku;
|
|
1495
1495
|
try { iku = decodeExt(issuer.issuerCert, OID.keyUsage); }
|
|
1496
1496
|
catch (e) {
|
|
1497
|
-
return { status: "unknown", reason: "the CRL issuer's keyUsage extension is unreadable (" + pathCode(e, "path/bad-key-usage") + "), so its authorization to sign CRLs cannot be verified" };
|
|
1497
|
+
return guard.verdict.of({ status: "unknown", reason: "the CRL issuer's keyUsage extension is unreadable (" + pathCode(e, "path/bad-key-usage") + "), so its authorization to sign CRLs cannot be verified" });
|
|
1498
1498
|
}
|
|
1499
1499
|
if (iku && iku.value.cRLSign !== true) signerAuthorized = false;
|
|
1500
1500
|
}
|
|
@@ -1600,14 +1600,14 @@ function crlChecker(crls, opts) {
|
|
|
1600
1600
|
if (!deltaMergesWith(cand, rec)) continue;
|
|
1601
1601
|
if (!(await gateCrl(cand))) continue;
|
|
1602
1602
|
cand.accounted = true;
|
|
1603
|
-
|
|
1603
|
+
guard.list.append(candidates, cand);
|
|
1604
1604
|
}
|
|
1605
1605
|
chosenDelta = selectDelta(candidates);
|
|
1606
1606
|
}
|
|
1607
1607
|
|
|
1608
1608
|
var status;
|
|
1609
1609
|
if (chosenDelta) {
|
|
1610
|
-
|
|
1610
|
+
guard.list.append(consumedDeltas, chosenDelta);
|
|
1611
1611
|
status = scanCrl(chosenDelta.crl);
|
|
1612
1612
|
if (status === null) status = scanCrl(rec.crl);
|
|
1613
1613
|
} else {
|
|
@@ -1631,20 +1631,20 @@ function crlChecker(crls, opts) {
|
|
|
1631
1631
|
if (certStatus === null) certStatus = dStatus;
|
|
1632
1632
|
}
|
|
1633
1633
|
|
|
1634
|
-
if (releasedByUnmergedDelta) return { status: "unknown", reason: "a delta CRL released this serial from hold; without merging its base CRL the revocation status is undetermined" };
|
|
1634
|
+
if (releasedByUnmergedDelta) return guard.verdict.of({ status: "unknown", reason: "a delta CRL released this serial from hold; without merging its base CRL the revocation status is undetermined" });
|
|
1635
1635
|
if (certStatus !== null) {
|
|
1636
1636
|
var reasonName = constants.NAMES.CRL_REASON[String(certStatus)] || "unspecified";
|
|
1637
|
-
return { status: "revoked", reasonCode: certStatus, reason: "serial listed in a CRL (" + reasonName + ")" };
|
|
1637
|
+
return guard.verdict.of({ status: "revoked", reasonCode: certStatus, reason: "serial listed in a CRL (" + reasonName + ")" });
|
|
1638
1638
|
}
|
|
1639
|
-
if (sawUnmergedDelta) return { status: "unknown", reason: "a delta CRL cannot be combined with any complete CRL held here, so the revocation picture is incomplete" };
|
|
1640
|
-
if ((reasonsMask & ALL_REASONS) === ALL_REASONS) return { status: "good" };
|
|
1639
|
+
if (sawUnmergedDelta) return guard.verdict.of({ status: "unknown", reason: "a delta CRL cannot be combined with any complete CRL held here, so the revocation picture is incomplete" });
|
|
1640
|
+
if ((reasonsMask & ALL_REASONS) === ALL_REASONS) return guard.verdict.of({ status: "good" });
|
|
1641
1641
|
if (certScopeFault) {
|
|
1642
|
-
return { status: "unknown", reason: "no authoritative in-scope CRL covers this certificate; its basicConstraints extension is unreadable (" + certScopeFault + "), so scope-limited CRLs were skipped" };
|
|
1642
|
+
return guard.verdict.of({ status: "unknown", reason: "no authoritative in-scope CRL covers this certificate; its basicConstraints extension is unreadable (" + certScopeFault + "), so scope-limited CRLs were skipped" });
|
|
1643
1643
|
}
|
|
1644
1644
|
if (reasonsMask !== 0) {
|
|
1645
|
-
return { status: "unknown", reason: "the CRLs available cover only some revocation reasons for this certificate; no combination covers all of them" };
|
|
1645
|
+
return guard.verdict.of({ status: "unknown", reason: "the CRLs available cover only some revocation reasons for this certificate; no combination covers all of them" });
|
|
1646
1646
|
}
|
|
1647
|
-
return { status: "unknown", reason: "no authoritative in-scope CRL covers this certificate" };
|
|
1647
|
+
return guard.verdict.of({ status: "unknown", reason: "no authoritative in-scope CRL covers this certificate" });
|
|
1648
1648
|
},
|
|
1649
1649
|
};
|
|
1650
1650
|
}
|
|
@@ -1736,13 +1736,13 @@ function ocspChecker(responses) {
|
|
|
1736
1736
|
var historical = ctx.historicalMode === true;
|
|
1737
1737
|
var issuerNameCandidates = [cert.issuer.bytes];
|
|
1738
1738
|
function addNameCandidate(nm) {
|
|
1739
|
-
if (nm && nm.bytes && !guard.list.anyMatches(issuerNameCandidates, function (e) { return e.equals(nm.bytes); }))
|
|
1739
|
+
if (nm && nm.bytes && !guard.list.anyMatches(issuerNameCandidates, function (e) { return e.equals(nm.bytes); })) guard.list.append(issuerNameCandidates, nm.bytes);
|
|
1740
1740
|
}
|
|
1741
1741
|
if (issuer.issuerCert) addNameCandidate(issuer.issuerCert.subject);
|
|
1742
1742
|
addNameCandidate(issuer.workingIssuerName);
|
|
1743
1743
|
var issuerKeyBits;
|
|
1744
1744
|
try { issuerKeyBits = ocspVerify.ocspKeyValue(issuer.workingPublicKey); }
|
|
1745
|
-
catch (_e) { return { status: "unknown", reason: "the issuer public key could not be read to recompute the OCSP CertID" }; }
|
|
1745
|
+
catch (_e) { return guard.verdict.of({ status: "unknown", reason: "the issuer public key could not be read to recompute the OCSP CertID" }); }
|
|
1746
1746
|
|
|
1747
1747
|
var revokedResult = null;
|
|
1748
1748
|
var sawGood = false;
|
|
@@ -1751,19 +1751,19 @@ function ocspChecker(responses) {
|
|
|
1751
1751
|
for (var k = 0; k < parsed.length; k++) {
|
|
1752
1752
|
var v = await ocspCore.evaluateResponse(parsed[k], cert, issuer, issuerKeyBits, issuerNameCandidates, time, historical);
|
|
1753
1753
|
if (v.revoked && !revokedResult) {
|
|
1754
|
-
revokedResult = { status: "revoked", revocationReason: v.revoked.revocationReason, revocationTime: v.revoked.revocationTime, reason: v.revoked.reason };
|
|
1754
|
+
revokedResult = guard.verdict.of({ status: "revoked", revocationReason: v.revoked.revocationReason, revocationTime: v.revoked.revocationTime, reason: v.revoked.reason });
|
|
1755
1755
|
}
|
|
1756
1756
|
if (v.sawGood) sawGood = true;
|
|
1757
1757
|
if (v.sawUnknownStatus) sawUnknownStatus = true;
|
|
1758
1758
|
}
|
|
1759
1759
|
if (revokedResult) return revokedResult;
|
|
1760
|
-
if (sawGood) return { status: "good" };
|
|
1761
|
-
return {
|
|
1760
|
+
if (sawGood) return guard.verdict.of({ status: "good" });
|
|
1761
|
+
return guard.verdict.of({
|
|
1762
1762
|
status: "unknown",
|
|
1763
1763
|
reason: sawUnknownStatus
|
|
1764
1764
|
? "the OCSP responder reported certStatus unknown for this certificate"
|
|
1765
1765
|
: "no authoritative, current, in-scope OCSP response covers this certificate",
|
|
1766
|
-
};
|
|
1766
|
+
});
|
|
1767
1767
|
},
|
|
1768
1768
|
};
|
|
1769
1769
|
}
|
|
@@ -1865,7 +1865,7 @@ function _verifyOcspParsed(parsedResponse, cert, issuerCert, time, opts) {
|
|
|
1865
1865
|
if (!sig.ok) return unbound("the target certificate's signature does not verify under the supplied issuer certificate's key");
|
|
1866
1866
|
var issuerCtx = { workingPublicKey: issuerCert.subjectPublicKeyInfo.bytes, workingIssuerName: issuerCert.subject, issuerCert: issuerCert };
|
|
1867
1867
|
var issuerNameCandidates = [cert.issuer.bytes];
|
|
1868
|
-
function add(nm) { if (nm && nm.bytes && !guard.list.anyMatches(issuerNameCandidates, function (e) { return e.equals(nm.bytes); }))
|
|
1868
|
+
function add(nm) { if (nm && nm.bytes && !guard.list.anyMatches(issuerNameCandidates, function (e) { return e.equals(nm.bytes); })) guard.list.append(issuerNameCandidates, nm.bytes); }
|
|
1869
1869
|
add(issuerCert.subject);
|
|
1870
1870
|
var issuerKeyBits;
|
|
1871
1871
|
try { issuerKeyBits = ocspVerify.ocspKeyValue(issuerCert.subjectPublicKeyInfo.bytes); }
|
|
@@ -2019,9 +2019,9 @@ function _copyDnRdns(rdns, who) {
|
|
|
2019
2019
|
if (!intrinsic.hasOwn(atvOut, "type") || !intrinsic.hasOwn(atvOut, "value")) {
|
|
2020
2020
|
throw E("path/bad-input", who + "[" + i + "][" + j + "] must carry its type and value as own data properties");
|
|
2021
2021
|
}
|
|
2022
|
-
|
|
2022
|
+
guard.list.append(rdnOut, atvOut);
|
|
2023
2023
|
}
|
|
2024
|
-
|
|
2024
|
+
guard.list.append(out, rdnOut);
|
|
2025
2025
|
}
|
|
2026
2026
|
return out;
|
|
2027
2027
|
}
|
|
@@ -2107,7 +2107,7 @@ function _copyAnchorSubtreeList(list, key, who) {
|
|
|
2107
2107
|
}
|
|
2108
2108
|
intrinsic.defineProperty(out, field, { value: fv, enumerable: true, configurable: true, writable: true });
|
|
2109
2109
|
}
|
|
2110
|
-
|
|
2110
|
+
guard.list.append(copied, out);
|
|
2111
2111
|
}
|
|
2112
2112
|
return copied;
|
|
2113
2113
|
}
|
|
@@ -2128,7 +2128,7 @@ function _ownAnchorEntries(list, who) {
|
|
|
2128
2128
|
var d = intrinsic.getOwnPropertyDescriptor(list, i);
|
|
2129
2129
|
if (d === undefined) throw E("path/bad-input", who + ": trustAnchors index " + i + " is a hole or is inherited; every entry must be its own");
|
|
2130
2130
|
if (!intrinsic.hasOwn(d, "value")) throw E("path/bad-input", who + ": trustAnchors entry " + i + " must be a data property, not an accessor");
|
|
2131
|
-
|
|
2131
|
+
guard.list.append(out, d.value);
|
|
2132
2132
|
}
|
|
2133
2133
|
return out;
|
|
2134
2134
|
}
|
|
@@ -2141,7 +2141,7 @@ function _precaptureAnchorNameConstraints(list, who) {
|
|
|
2141
2141
|
var raw = _captureConstraintMap(entry, "nameConstraints", E, "path/bad-input", who);
|
|
2142
2142
|
captured = raw == null ? undefined : _copyAnchorNameConstraints(raw, who);
|
|
2143
2143
|
}
|
|
2144
|
-
|
|
2144
|
+
guard.list.append(out, captured);
|
|
2145
2145
|
}
|
|
2146
2146
|
return out;
|
|
2147
2147
|
}
|
|
@@ -2441,7 +2441,7 @@ function _pushCandidates(frame, scored, stack, counter, down) {
|
|
|
2441
2441
|
if (intrinsic.setHas(frame.keys, candKey)) continue;
|
|
2442
2442
|
var childKeys = new Set(frame.keys);
|
|
2443
2443
|
intrinsic.setAdd(childKeys, candKey);
|
|
2444
|
-
|
|
2444
|
+
guard.list.append(stack, down
|
|
2445
2445
|
? { chain: intrinsic.concat(frame.chain, [cand]), hop: frame.hop + 1, keys: childKeys, anchor: frame.anchor }
|
|
2446
2446
|
: { chain: [cand].concat(frame.chain), hop: frame.hop + 1, keys: childKeys });
|
|
2447
2447
|
}
|
|
@@ -2500,7 +2500,7 @@ async function _fetchAiaIssuers(current, aia) {
|
|
|
2500
2500
|
if (intrinsic.setHas(aia.fetchedUrls, u.href) || intrinsic.setHas(seenThisCert, u.href)) continue;
|
|
2501
2501
|
if (seenThisCert.size >= aia.maxPerCert) break;
|
|
2502
2502
|
intrinsic.setAdd(seenThisCert, u.href);
|
|
2503
|
-
|
|
2503
|
+
guard.list.append(uris, u.href);
|
|
2504
2504
|
}
|
|
2505
2505
|
var out = [];
|
|
2506
2506
|
for (var k = 0; k < uris.length; k++) {
|
|
@@ -2515,7 +2515,7 @@ async function _fetchAiaIssuers(current, aia) {
|
|
|
2515
2515
|
var parsed;
|
|
2516
2516
|
try { parsed = coerceCert(certs[c]); }
|
|
2517
2517
|
catch (_e3) { /* allow:swallow-unverified verified-unreachable: every cert here already passed the IDENTICAL x509.parse in _aiaParseBody (single-DER validates `body`; certs-only validates each via parseCertsOnly), so coerceCert re-parsing the same bytes cannot throw -- the guard stays as defense-in-depth */ continue; }
|
|
2518
|
-
|
|
2518
|
+
guard.list.append(out, parsed);
|
|
2519
2519
|
}
|
|
2520
2520
|
}
|
|
2521
2521
|
return out;
|
|
@@ -2632,7 +2632,7 @@ async function build(leaf, opts) {
|
|
|
2632
2632
|
for (var bai = 0; bai < buildEntries.length; bai++) {
|
|
2633
2633
|
var bAnchor = toAnchor(buildEntries[bai], "build");
|
|
2634
2634
|
if (buildPreNc[bai] !== undefined) intrinsic.defineProperty(bAnchor, "nameConstraints", { value: buildPreNc[bai], enumerable: true, configurable: true, writable: true });
|
|
2635
|
-
|
|
2635
|
+
guard.list.append(anchors, bAnchor);
|
|
2636
2636
|
}
|
|
2637
2637
|
|
|
2638
2638
|
guard.time.assertValid(opts.time, E, "path/bad-input", "build: opts.time (the validity-window check date, forwarded to validate)");
|
|
@@ -2704,7 +2704,7 @@ async function build(leaf, opts) {
|
|
|
2704
2704
|
if (uip === OID.anyPolicy) { containsAny = true; break; }
|
|
2705
2705
|
var dupUip = false;
|
|
2706
2706
|
for (var uj = 0; uj < uipsDistinct.length; uj++) { if (uipsDistinct[uj] === uip) { dupUip = true; break; } }
|
|
2707
|
-
if (!dupUip)
|
|
2707
|
+
if (!dupUip) guard.list.append(uipsDistinct, uip);
|
|
2708
2708
|
}
|
|
2709
2709
|
selectByPolicy = !containsAny;
|
|
2710
2710
|
}
|
|
@@ -2713,7 +2713,7 @@ async function build(leaf, opts) {
|
|
|
2713
2713
|
try {
|
|
2714
2714
|
if (direction === "reverse") {
|
|
2715
2715
|
var rstack = [];
|
|
2716
|
-
for (var rsi = 0; rsi < anchors.length; rsi++)
|
|
2716
|
+
for (var rsi = 0; rsi < anchors.length; rsi++) guard.list.append(rstack, { chain: [], hop: 0, keys: new Set([identityKey(leafCert)]), anchor: anchors[rsi] });
|
|
2717
2717
|
while (rstack.length) {
|
|
2718
2718
|
var rframe = rstack.pop();
|
|
2719
2719
|
var frontierCert = rframe.chain.length ? rframe.chain[rframe.chain.length - 1] : null;
|
|
@@ -2727,7 +2727,7 @@ async function build(leaf, opts) {
|
|
|
2727
2727
|
var racc = { valid: true, path: rpath, trustAnchor: rframe.anchor, result: rres };
|
|
2728
2728
|
if (!selectByPolicy) { success = racc; break; }
|
|
2729
2729
|
if (_policyScore(rres, uipsDistinct) >= uipsDistinct.length) { success = racc; break; }
|
|
2730
|
-
|
|
2730
|
+
guard.list.append(accepted, racc);
|
|
2731
2731
|
} else if (!bestFail) bestFail = { path: rpath, trustAnchor: rframe.anchor, result: rres };
|
|
2732
2732
|
}
|
|
2733
2733
|
if (rframe.hop >= maxDepth) continue;
|
|
@@ -2736,7 +2736,7 @@ async function build(leaf, opts) {
|
|
|
2736
2736
|
if (nameMatchSoft(pool[rpi].subject.rdns, rframe.anchor.name.rdns) &&
|
|
2737
2737
|
intrinsic.bufferEquals(pool[rpi].subjectPublicKeyInfo.bytes, rframe.anchor.publicKey)) continue;
|
|
2738
2738
|
if (nameMatchSoft(pool[rpi].issuer.rdns, frontierName)) {
|
|
2739
|
-
|
|
2739
|
+
guard.list.append(rscored, { cand: pool[rpi], score: scoreCandidateReverse(pool[rpi], frontierCert, leafCert, opts.time) });
|
|
2740
2740
|
}
|
|
2741
2741
|
}
|
|
2742
2742
|
considered += _pushCandidates(rframe, rscored, rstack, counter, true);
|
|
@@ -2764,7 +2764,7 @@ async function build(leaf, opts) {
|
|
|
2764
2764
|
var fdk = certDerKey(fetched[fj]);
|
|
2765
2765
|
if (intrinsic.setHas(poolDerKeys, fdk)) continue;
|
|
2766
2766
|
intrinsic.setAdd(poolDerKeys, fdk);
|
|
2767
|
-
if (pool.length < poolCeiling)
|
|
2767
|
+
if (pool.length < poolCeiling) guard.list.append(pool, fetched[fj]);
|
|
2768
2768
|
}
|
|
2769
2769
|
}
|
|
2770
2770
|
fb.fetched = true;
|
|
@@ -2772,7 +2772,7 @@ async function build(leaf, opts) {
|
|
|
2772
2772
|
var fbScored = [];
|
|
2773
2773
|
for (var pj = fb.poolMark; pj < pool.length; pj++) {
|
|
2774
2774
|
if (nameMatchSoft(pool[pj].subject.rdns, fbCur.issuer.rdns)) {
|
|
2775
|
-
|
|
2775
|
+
guard.list.append(fbScored, { cand: pool[pj], score: scoreCandidate(pool[pj], fbAki, anchors, opts.time) });
|
|
2776
2776
|
}
|
|
2777
2777
|
}
|
|
2778
2778
|
fb.poolMark = pool.length;
|
|
@@ -2791,7 +2791,7 @@ async function build(leaf, opts) {
|
|
|
2791
2791
|
var acc = { valid: true, path: frame.chain.slice(), trustAnchor: anchors[ai], result: res };
|
|
2792
2792
|
if (!selectByPolicy) { success = acc; break; }
|
|
2793
2793
|
if (_policyScore(res, uipsDistinct) >= uipsDistinct.length) { success = acc; break; }
|
|
2794
|
-
|
|
2794
|
+
guard.list.append(accepted, acc);
|
|
2795
2795
|
} else if (!bestFail) bestFail = { path: frame.chain.slice(), trustAnchor: anchors[ai], result: res };
|
|
2796
2796
|
}
|
|
2797
2797
|
if (success || frame.hop >= maxDepth) continue;
|
|
@@ -2800,11 +2800,11 @@ async function build(leaf, opts) {
|
|
|
2800
2800
|
var scored = [];
|
|
2801
2801
|
for (var pi = 0; pi < pool.length; pi++) {
|
|
2802
2802
|
if (nameMatchSoft(pool[pi].subject.rdns, current.issuer.rdns)) {
|
|
2803
|
-
|
|
2803
|
+
guard.list.append(scored, { cand: pool[pi], score: scoreCandidate(pool[pi], childAki, anchors, opts.time) });
|
|
2804
2804
|
}
|
|
2805
2805
|
}
|
|
2806
2806
|
if (aiaCtx && frame.hop < maxDepth && aiaCtx.fetches < aiaCtx.maxFetches) {
|
|
2807
|
-
|
|
2807
|
+
guard.list.append(deferredAia, { chain: frame.chain, hop: frame.hop, keys: frame.keys, poolMark: pool.length, seq: deferSeq, fetched: false });
|
|
2808
2808
|
deferSeq += 1;
|
|
2809
2809
|
}
|
|
2810
2810
|
considered += _pushCandidates(frame, scored, stack, counter);
|
|
@@ -2820,11 +2820,11 @@ async function build(leaf, opts) {
|
|
|
2820
2820
|
|
|
2821
2821
|
var aiaFetches = aiaCtx ? aiaCtx.fetches : 0;
|
|
2822
2822
|
if (success) {
|
|
2823
|
-
if (doValidate) return { valid: true, path: success.path, trustAnchor: success.trustAnchor, result: success.result, candidatesConsidered: considered, aiaFetches: aiaFetches };
|
|
2824
|
-
return { path: success.path, trustAnchor: success.trustAnchor, candidatesConsidered: considered, aiaFetches: aiaFetches };
|
|
2823
|
+
if (doValidate) return guard.verdict.of({ valid: true, path: success.path, trustAnchor: success.trustAnchor, result: success.result, candidatesConsidered: considered, aiaFetches: aiaFetches });
|
|
2824
|
+
return guard.verdict.of({ path: success.path, trustAnchor: success.trustAnchor, candidatesConsidered: considered, aiaFetches: aiaFetches });
|
|
2825
2825
|
}
|
|
2826
2826
|
if (anyChainAssembled) {
|
|
2827
|
-
return { valid: false, path: bestFail.path, trustAnchor: bestFail.trustAnchor, result: bestFail.result, candidatesConsidered: considered, aiaFetches: aiaFetches };
|
|
2827
|
+
return guard.verdict.of({ valid: false, path: bestFail.path, trustAnchor: bestFail.trustAnchor, result: bestFail.result, candidatesConsidered: considered, aiaFetches: aiaFetches });
|
|
2828
2828
|
}
|
|
2829
2829
|
throw E("path/no-path", "build: no certification path from the leaf to any configured trust anchor could be assembled");
|
|
2830
2830
|
}
|