@blamejs/pki 0.6.40 → 0.6.42
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 +25 -0
- package/README.md +1 -1
- package/lib/acme.js +24 -13
- package/lib/asn1-der.js +5 -5
- package/lib/attrcert-sign.js +14 -14
- package/lib/cbor-det.js +2 -2
- package/lib/cmc-build.js +16 -16
- package/lib/cmc-verify.js +5 -5
- package/lib/cmp-build.js +29 -19
- package/lib/cmp-session.js +21 -16
- package/lib/cmp-verify.js +4 -4
- package/lib/cms-decrypt.js +8 -8
- package/lib/cms-encrypt.js +22 -22
- package/lib/cms-sign.js +17 -17
- package/lib/cms-verify.js +6 -6
- package/lib/composite-kem.js +1 -1
- package/lib/composite-sig.js +4 -4
- package/lib/constants.js +13 -9
- package/lib/crl-sign.js +17 -17
- package/lib/crmf-sign.js +11 -11
- package/lib/csr-sign.js +2 -2
- package/lib/ct.js +19 -11
- package/lib/edwards-point.js +2 -2
- package/lib/est.js +74 -43
- package/lib/guard-async.js +17 -1
- package/lib/guard-bytes.js +2 -2
- package/lib/guard-compress.js +5 -5
- package/lib/guard-identifier.js +45 -1
- package/lib/guard-name.js +272 -1
- package/lib/guard-time.js +3 -1
- package/lib/hpke.js +10 -10
- package/lib/http-digest.js +2 -2
- package/lib/http-transport.js +3 -3
- package/lib/inspect.js +9 -9
- package/lib/jose.js +14 -14
- package/lib/key.js +7 -7
- package/lib/lint.js +6 -4
- package/lib/merkle.js +2 -2
- package/lib/mime.js +2 -2
- package/lib/ocsp-verify.js +1 -1
- package/lib/ocsp.js +5 -5
- package/lib/oid.js +3 -3
- package/lib/path-validate.js +50 -120
- package/lib/pbes2.js +2 -2
- package/lib/pkcs12-build.js +15 -15
- package/lib/pki-build.js +2 -2
- package/lib/scep.js +47 -16
- package/lib/schema-all.js +1 -1
- package/lib/schema-attrcert.js +4 -3
- package/lib/schema-c509.js +23 -23
- package/lib/schema-cmc.js +6 -6
- package/lib/schema-cmp.js +3 -3
- package/lib/schema-cms.js +15 -8
- package/lib/schema-crmf.js +1 -1
- package/lib/schema-csr.js +1 -1
- package/lib/schema-engine.js +2 -1
- package/lib/schema-pkcs12.js +1 -1
- package/lib/schema-pkix.js +3 -0
- package/lib/schema-tsp.js +2 -2
- package/lib/shbs.js +2 -2
- package/lib/sign-scheme.js +9 -9
- package/lib/sigstore.js +9 -8
- package/lib/smime.js +12 -12
- package/lib/tls-cert-compress.js +6 -6
- package/lib/trust.js +179 -10
- package/lib/tsp-sign.js +11 -11
- package/lib/validator-attcert.js +2 -2
- package/lib/validator-cose.js +5 -5
- package/lib/validator-sig.js +3 -3
- package/lib/validator-tpm.js +5 -4
- package/lib/webauthn.js +12 -12
- package/lib/webcrypto.js +22 -14
- package/lib/x509-sign.js +8 -8
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
package/lib/jose.js
CHANGED
|
@@ -129,7 +129,7 @@ function parseJson(input) {
|
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
|
|
132
|
-
var SIG_ALGS = {
|
|
132
|
+
var SIG_ALGS = intrinsic.assign(intrinsic.create(null), {
|
|
133
133
|
ES256: { kty: "EC", crv: "P-256", hash: "SHA-256", subtle: "ECDSA", sigBytes: 64 },
|
|
134
134
|
ES384: { kty: "EC", crv: "P-384", hash: "SHA-384", subtle: "ECDSA", sigBytes: 96 },
|
|
135
135
|
ES512: { kty: "EC", crv: "P-521", hash: "SHA-512", subtle: "ECDSA", sigBytes: 132 },
|
|
@@ -139,26 +139,26 @@ var SIG_ALGS = {
|
|
|
139
139
|
PS256: { kty: "RSA", hash: "SHA-256", subtle: "RSA-PSS", saltLength: 32 },
|
|
140
140
|
PS384: { kty: "RSA", hash: "SHA-384", subtle: "RSA-PSS", saltLength: 48 },
|
|
141
141
|
PS512: { kty: "RSA", hash: "SHA-512", subtle: "RSA-PSS", saltLength: 64 },
|
|
142
|
-
EdDSA: { kty: "OKP", subtle: "EdDSA", sigBytesByCrv: { Ed25519: 64, Ed448: 114 } },
|
|
142
|
+
EdDSA: { kty: "OKP", subtle: "EdDSA", sigBytesByCrv: intrinsic.assign(intrinsic.create(null), { Ed25519: 64, Ed448: 114 }) },
|
|
143
143
|
"ML-DSA-44": { kty: "AKP", subtle: "ML-DSA-44", sigBytes: 2420 },
|
|
144
144
|
"ML-DSA-65": { kty: "AKP", subtle: "ML-DSA-65", sigBytes: 3309 },
|
|
145
145
|
"ML-DSA-87": { kty: "AKP", subtle: "ML-DSA-87", sigBytes: 4627 },
|
|
146
|
-
};
|
|
146
|
+
});
|
|
147
147
|
|
|
148
|
-
var MAC_ALGS = {
|
|
148
|
+
var MAC_ALGS = intrinsic.assign(intrinsic.create(null), {
|
|
149
149
|
HS256: { kty: "oct", hash: "SHA-256", sigBytes: 32 },
|
|
150
150
|
HS384: { kty: "oct", hash: "SHA-384", sigBytes: 48 },
|
|
151
151
|
HS512: { kty: "oct", hash: "SHA-512", sigBytes: 64 },
|
|
152
|
-
};
|
|
152
|
+
});
|
|
153
153
|
|
|
154
|
-
var UNDERSTOOD_HEADER = { alg: 1, nonce: 1, url: 1, jwk: 1, kid: 1, crit: 1 };
|
|
154
|
+
var UNDERSTOOD_HEADER = intrinsic.assign(intrinsic.create(null), { alg: 1, nonce: 1, url: 1, jwk: 1, kid: 1, crit: 1 });
|
|
155
155
|
|
|
156
156
|
|
|
157
|
-
var PROFILES = {
|
|
157
|
+
var PROFILES = intrinsic.assign(intrinsic.create(null), {
|
|
158
158
|
"acme-outer": { algs: SIG_ALGS, nonce: "required", keyId: "one-of", requireUrl: true },
|
|
159
159
|
"eab-inner": { algs: MAC_ALGS, nonce: "forbidden", keyId: "kid", requireUrl: true },
|
|
160
160
|
"keychange-inner": { algs: SIG_ALGS, nonce: "forbidden", keyId: "jwk", requireUrl: true },
|
|
161
|
-
};
|
|
161
|
+
});
|
|
162
162
|
|
|
163
163
|
function _checkHeader(header, profileName) {
|
|
164
164
|
var profile = PROFILES[profileName];
|
|
@@ -192,7 +192,7 @@ function _checkHeader(header, profileName) {
|
|
|
192
192
|
if (_hasOwn(header, "crit")) {
|
|
193
193
|
var crit = header.crit;
|
|
194
194
|
if (!_isArray(crit) || crit.length === 0) throw E("jose/bad-crit", "crit must be a non-empty array");
|
|
195
|
-
var seen =
|
|
195
|
+
var seen = intrinsic.create(null);
|
|
196
196
|
for (var c = 0; c < crit.length; c++) {
|
|
197
197
|
var name = crit[c];
|
|
198
198
|
if (typeof name !== "string") throw E("jose/bad-crit", "crit entries must be strings");
|
|
@@ -315,7 +315,7 @@ function assertPublicJwk(jwk) {
|
|
|
315
315
|
* var v = await pki.jose.verify(jws, { profile: "acme-outer", key: accountJwk });
|
|
316
316
|
* v.header.alg; // -> "ES256"
|
|
317
317
|
*/
|
|
318
|
-
var _VERIFY_KEYS = { key: 1, profile: 1 };
|
|
318
|
+
var _VERIFY_KEYS = intrinsic.assign(intrinsic.create(null), { key: 1, profile: 1 });
|
|
319
319
|
async function verify(jws, opts) {
|
|
320
320
|
opts = opts || {};
|
|
321
321
|
guard.identifier.assertKnownKeys(opts, _VERIFY_KEYS, E, "jose/bad-input", "unknown pki.jose.verify option ");
|
|
@@ -395,8 +395,8 @@ async function verify(jws, opts) {
|
|
|
395
395
|
* nonce: "oFvnlFP1wIhRlYS2jTaXbA", url: "https://ca.example/acme/new-acct" };
|
|
396
396
|
* var jws = await pki.jose.sign({ protected: hdr, payload: Buffer.from("{}"), key: priv });
|
|
397
397
|
*/
|
|
398
|
-
var _SIGN_KEYS = { protected: 1, payload: 1, key: 1, jwk: 1, profile: 1 };
|
|
399
|
-
var _SIGN_KEYS_EMBEDDED_JWK = { protected: 1, payload: 1, key: 1, profile: 1 };
|
|
398
|
+
var _SIGN_KEYS = intrinsic.assign(intrinsic.create(null), { protected: 1, payload: 1, key: 1, jwk: 1, profile: 1 });
|
|
399
|
+
var _SIGN_KEYS_EMBEDDED_JWK = intrinsic.assign(intrinsic.create(null), { protected: 1, payload: 1, key: 1, profile: 1 });
|
|
400
400
|
async function sign(opts) {
|
|
401
401
|
opts = opts || {};
|
|
402
402
|
guard.identifier.assertKnownKeys(opts, _SIGN_KEYS, E, "jose/bad-input", "unknown pki.jose.sign option ");
|
|
@@ -442,13 +442,13 @@ async function sign(opts) {
|
|
|
442
442
|
}
|
|
443
443
|
|
|
444
444
|
|
|
445
|
-
var THUMBPRINT_MEMBERS = {
|
|
445
|
+
var THUMBPRINT_MEMBERS = intrinsic.assign(intrinsic.create(null), {
|
|
446
446
|
EC: ["crv", "kty", "x", "y"],
|
|
447
447
|
RSA: ["e", "kty", "n"],
|
|
448
448
|
oct: ["k", "kty"],
|
|
449
449
|
OKP: ["crv", "kty", "x"],
|
|
450
450
|
AKP: ["alg", "kty", "pub"],
|
|
451
|
-
};
|
|
451
|
+
});
|
|
452
452
|
|
|
453
453
|
/**
|
|
454
454
|
* @primitive pki.jose.thumbprint
|
package/lib/key.js
CHANGED
|
@@ -38,7 +38,7 @@ function _err(code, msg, cause) { return new KeyError(code, msg, cause); }
|
|
|
38
38
|
|
|
39
39
|
var CIPHER_NAME = Object.assign(Object.create(null), { "aes-128-cbc": "aes128-CBC", "aes-192-cbc": "aes192-CBC", "aes-256-cbc": "aes256-CBC" });
|
|
40
40
|
|
|
41
|
-
var INFER_ALG =
|
|
41
|
+
var INFER_ALG = Object.create(null);
|
|
42
42
|
["Ed25519", "Ed448", "X25519", "X448"].forEach(function (n) { INFER_ALG[O(n)] = { name: n }; });
|
|
43
43
|
[["id-ml-dsa-44", "ML-DSA-44"], ["id-ml-dsa-65", "ML-DSA-65"], ["id-ml-dsa-87", "ML-DSA-87"],
|
|
44
44
|
["id-ml-kem-512", "ML-KEM-512"], ["id-ml-kem-768", "ML-KEM-768"], ["id-ml-kem-1024", "ML-KEM-1024"]
|
|
@@ -88,7 +88,7 @@ async function _toPrivateKeyDer(input) {
|
|
|
88
88
|
* var enc = await pki.key.encrypt(der, "s3cr3t", { pem: true });
|
|
89
89
|
* var back = await pki.key.decrypt(enc, "s3cr3t");
|
|
90
90
|
*/
|
|
91
|
-
var _ENCRYPT_OPTS = { cipher: 1, iterations: 1, pem: 1, prf: 1, salt: 1 };
|
|
91
|
+
var _ENCRYPT_OPTS = Object.assign(Object.create(null), { cipher: 1, iterations: 1, pem: 1, prf: 1, salt: 1 });
|
|
92
92
|
|
|
93
93
|
async function encrypt(privateKey, password, opts) {
|
|
94
94
|
opts = guard.identifier.optionsObject(opts, _err, "key/bad-input", "pki.key.encrypt options");
|
|
@@ -147,7 +147,7 @@ async function encrypt(privateKey, password, opts) {
|
|
|
147
147
|
* var enc = await pki.key.encrypt(await pki.key.export(pair.privateKey), "s3cr3t", { pem: true });
|
|
148
148
|
* var der = await pki.key.decrypt(enc, "s3cr3t");
|
|
149
149
|
*/
|
|
150
|
-
var _DECRYPT_OPTS = { maxIterations: 1, pem: 1 };
|
|
150
|
+
var _DECRYPT_OPTS = Object.assign(Object.create(null), { maxIterations: 1, pem: 1 });
|
|
151
151
|
|
|
152
152
|
async function decrypt(encrypted, password, opts) {
|
|
153
153
|
opts = guard.identifier.optionsObject(opts, _err, "key/bad-input", "pki.key.decrypt options");
|
|
@@ -203,7 +203,7 @@ function _decryptPbes2(encAlg, ciphertext, password, opts) {
|
|
|
203
203
|
* var pair = await pki.key.generate("Ed25519");
|
|
204
204
|
* var spkiPem = await pki.key.export(pair.publicKey, { format: "pem" });
|
|
205
205
|
*/
|
|
206
|
-
var _EXPORT_OPTS = { format: 1, label: 1 };
|
|
206
|
+
var _EXPORT_OPTS = Object.assign(Object.create(null), { format: 1, label: 1 });
|
|
207
207
|
|
|
208
208
|
async function export_(key, opts) {
|
|
209
209
|
opts = guard.identifier.optionsObject(opts, _err, "key/bad-input", "pki.key.export options");
|
|
@@ -246,7 +246,7 @@ async function export_(key, opts) {
|
|
|
246
246
|
* var spki = await pki.key.export(pair.publicKey);
|
|
247
247
|
* var pub = await pki.key.import(spki); // Ed25519 -- algorithm inferred
|
|
248
248
|
*/
|
|
249
|
-
var _IMPORT_OPTS = { algorithm: 1, extractable: 1, password: 1, usages: 1 };
|
|
249
|
+
var _IMPORT_OPTS = Object.assign(Object.create(null), { algorithm: 1, extractable: 1, password: 1, usages: 1 });
|
|
250
250
|
|
|
251
251
|
async function import_(input, opts) {
|
|
252
252
|
opts = guard.identifier.optionsObject(opts, _err, "key/bad-input", "pki.key.import options");
|
|
@@ -290,7 +290,7 @@ async function import_(input, opts) {
|
|
|
290
290
|
* var pair = await pki.key.generate("Ed25519");
|
|
291
291
|
* var pkcs8 = await pki.key.export(pair.privateKey);
|
|
292
292
|
*/
|
|
293
|
-
var _GENERATE_OPTS = { extractable: 1, usages: 1 };
|
|
293
|
+
var _GENERATE_OPTS = Object.assign(Object.create(null), { extractable: 1, usages: 1 });
|
|
294
294
|
|
|
295
295
|
async function generate(algorithm, opts) {
|
|
296
296
|
opts = guard.identifier.optionsObject(opts, _err, "key/bad-input", "pki.key.generate options");
|
|
@@ -325,7 +325,7 @@ async function generate(algorithm, opts) {
|
|
|
325
325
|
* var pair = await pki.key.generate("Ed25519");
|
|
326
326
|
* var spki = await pki.key.publicFromPrivate(await pki.key.export(pair.privateKey));
|
|
327
327
|
*/
|
|
328
|
-
var _PUBLIC_FROM_PRIVATE_OPTS = { pem: 1 };
|
|
328
|
+
var _PUBLIC_FROM_PRIVATE_OPTS = Object.assign(Object.create(null), { pem: 1 });
|
|
329
329
|
|
|
330
330
|
async function publicFromPrivate(privateKey, opts) {
|
|
331
331
|
opts = guard.identifier.optionsObject(opts, _err, "key/bad-input", "pki.key.publicFromPrivate options");
|
package/lib/lint.js
CHANGED
|
@@ -129,7 +129,8 @@ function _effective(rule, cert) {
|
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
function _runLints(rules, cert, ctx) {
|
|
132
|
-
var findings = [],
|
|
132
|
+
var findings = [], ran = [];
|
|
133
|
+
var counts = Object.assign(Object.create(null), { fatal: 0, error: 0, warn: 0, notice: 0, pass: 0, na: 0, ne: 0 });
|
|
133
134
|
rules.forEach(function (rule) {
|
|
134
135
|
if (rule.appliesTo && !rule.appliesTo(cert, ctx)) { counts.na++; return; }
|
|
135
136
|
if (!_effective(rule, cert)) { counts.ne++; return; }
|
|
@@ -172,7 +173,7 @@ function _subjectCNs(cert) {
|
|
|
172
173
|
return out;
|
|
173
174
|
}
|
|
174
175
|
|
|
175
|
-
var _CRITICAL_LEGIT =
|
|
176
|
+
var _CRITICAL_LEGIT = Object.create(null);
|
|
176
177
|
_CRITICAL_LEGIT[oid.byName("precertificatePoison")] = true;
|
|
177
178
|
function _isUnknownExtension(extOid) {
|
|
178
179
|
if (path.PROCESSED_EXTENSIONS[extOid] !== true) return _CRITICAL_LEGIT[extOid] !== true;
|
|
@@ -560,7 +561,7 @@ function _applyThreshold(report, severity) {
|
|
|
560
561
|
* report.worst; // "notice" | "error" | ...
|
|
561
562
|
* report.findings.map(function (f) { return f.id; });
|
|
562
563
|
*/
|
|
563
|
-
var _CERTIFICATE_OPTS = { profile: 1, severity: 1 };
|
|
564
|
+
var _CERTIFICATE_OPTS = Object.assign(Object.create(null), { profile: 1, severity: 1 });
|
|
564
565
|
|
|
565
566
|
function certificate(input, opts) {
|
|
566
567
|
opts = guard.identifier.optionsObject(opts, _cfg, "lint/bad-input", "pki.lint options");
|
|
@@ -573,7 +574,8 @@ function certificate(input, opts) {
|
|
|
573
574
|
var ingested = _ingest(input);
|
|
574
575
|
var report;
|
|
575
576
|
if (ingested.fatal) {
|
|
576
|
-
report = { findings: [ingested.fatal],
|
|
577
|
+
report = { findings: [ingested.fatal], ran: [],
|
|
578
|
+
counts: Object.assign(Object.create(null), { fatal: 1, error: 0, warn: 0, notice: 0, pass: 0, na: 0, ne: 0 }) };
|
|
577
579
|
} else {
|
|
578
580
|
var ctx = _makeCtx(ingested.cert, opts.profile);
|
|
579
581
|
report = _runLints(rules, ingested.cert, ctx);
|
package/lib/merkle.js
CHANGED
|
@@ -180,7 +180,7 @@ function emptyRootHash() {
|
|
|
180
180
|
* var lh = pki.merkle.leafHash(Buffer.from([0]));
|
|
181
181
|
* pki.merkle.verifyInclusion({ leafIndex: 0, treeSize: 1, leafHash: lh, proof: [], rootHash: lh }); // -> true
|
|
182
182
|
*/
|
|
183
|
-
var _INCLUSION_KEYS = { leafIndex: 1, treeSize: 1, leafHash: 1, rootHash: 1, proof: 1 };
|
|
183
|
+
var _INCLUSION_KEYS = Object.assign(Object.create(null), { leafIndex: 1, treeSize: 1, leafHash: 1, rootHash: 1, proof: 1 });
|
|
184
184
|
function verifyInclusion(opts) {
|
|
185
185
|
opts = opts || {};
|
|
186
186
|
guard.identifier.assertKnownKeys(opts, _INCLUSION_KEYS, function (c, m) { return new MerkleError(c, m); },
|
|
@@ -252,7 +252,7 @@ function verifyInclusion(opts) {
|
|
|
252
252
|
* var r = pki.merkle.leafHash(Buffer.from([0]));
|
|
253
253
|
* pki.merkle.verifyConsistency({ oldSize: 1, newSize: 1, oldRoot: r, newRoot: r, proof: [] }); // -> true
|
|
254
254
|
*/
|
|
255
|
-
var _CONSISTENCY_KEYS = { oldSize: 1, newSize: 1, oldRoot: 1, newRoot: 1, proof: 1 };
|
|
255
|
+
var _CONSISTENCY_KEYS = Object.assign(Object.create(null), { oldSize: 1, newSize: 1, oldRoot: 1, newRoot: 1, proof: 1 });
|
|
256
256
|
function verifyConsistency(opts) {
|
|
257
257
|
opts = opts || {};
|
|
258
258
|
guard.identifier.assertKnownKeys(opts, _CONSISTENCY_KEYS, function (c, m) { return new MerkleError(c, m); },
|
package/lib/mime.js
CHANGED
|
@@ -68,7 +68,7 @@ function _unfoldHeaders(headerText) {
|
|
|
68
68
|
function _parseStructured(headerValue) {
|
|
69
69
|
var parts = _splitSemicolons(headerValue);
|
|
70
70
|
var type = _stripComments(parts[0]).trim().toLowerCase();
|
|
71
|
-
var params =
|
|
71
|
+
var params = Object.create(null);
|
|
72
72
|
for (var i = 1; i < parts.length; i++) {
|
|
73
73
|
var p = _stripComments(parts[i]);
|
|
74
74
|
var eq = p.indexOf("=");
|
|
@@ -131,7 +131,7 @@ function parse(input, E, code) {
|
|
|
131
131
|
var cte = (header("content-transfer-encoding") || "").trim().toLowerCase() || "7bit";
|
|
132
132
|
return {
|
|
133
133
|
headers: headers, header: header,
|
|
134
|
-
contentType: ctv != null ? _parseStructured(ctv) : { value: "text/plain", type: "text/plain", params:
|
|
134
|
+
contentType: ctv != null ? _parseStructured(ctv) : { value: "text/plain", type: "text/plain", params: Object.create(null) },
|
|
135
135
|
cte: cte,
|
|
136
136
|
headerBytes: headerBytes, bodyBytes: bodyBytes, body: bodyBytes, bytes: bytes,
|
|
137
137
|
};
|
package/lib/ocsp-verify.js
CHANGED
|
@@ -12,7 +12,7 @@ var compositeSig = require("./composite-sig");
|
|
|
12
12
|
var webcrypto = require("./webcrypto");
|
|
13
13
|
var subtle = webcrypto.webcrypto.subtle;
|
|
14
14
|
|
|
15
|
-
var OCSP_CERTID_HASHES =
|
|
15
|
+
var OCSP_CERTID_HASHES = intrinsic.create(null);
|
|
16
16
|
OCSP_CERTID_HASHES[oid.byName("sha1")] = "SHA-1";
|
|
17
17
|
OCSP_CERTID_HASHES[oid.byName("sha256")] = "SHA-256";
|
|
18
18
|
OCSP_CERTID_HASHES[oid.byName("sha384")] = "SHA-384";
|
package/lib/ocsp.js
CHANGED
|
@@ -139,9 +139,9 @@ function buildRequest(query, opts) {
|
|
|
139
139
|
], _buildRequest);
|
|
140
140
|
}
|
|
141
141
|
|
|
142
|
-
var _BUILD_REQUEST_OPTS = {
|
|
142
|
+
var _BUILD_REQUEST_OPTS = Object.assign(Object.create(null), {
|
|
143
143
|
hashAlgorithm: 1, nonce: 1, pem: 1, profile: 1, requestorName: 1, signer: 1
|
|
144
|
-
};
|
|
144
|
+
});
|
|
145
145
|
|
|
146
146
|
function _buildRequest(query, opts) {
|
|
147
147
|
opts = guard.identifier.optionsObject(opts, _err, "ocsp/bad-input", "pki.ocsp.buildRequest options");
|
|
@@ -250,7 +250,7 @@ function sign(responseData, responder, opts) {
|
|
|
250
250
|
], _sign);
|
|
251
251
|
}
|
|
252
252
|
|
|
253
|
-
var _SIGN_OPTS = { embedCert: 1, extendedRevoke: 1, nonce: 1, pem: 1 };
|
|
253
|
+
var _SIGN_OPTS = Object.assign(Object.create(null), { embedCert: 1, extendedRevoke: 1, nonce: 1, pem: 1 });
|
|
254
254
|
|
|
255
255
|
function _sign(responseData, responder, opts) {
|
|
256
256
|
opts = guard.identifier.optionsObject(opts, _err, "ocsp/bad-input", "pki.ocsp.sign options");
|
|
@@ -425,7 +425,7 @@ function buildErrorResponse(status) {
|
|
|
425
425
|
* var res = await pki.ocsp.verify(responseDer, { cert: leafDer, issuer: caDer });
|
|
426
426
|
* res.status; // "good" | "revoked" | "unknown"
|
|
427
427
|
*/
|
|
428
|
-
var _VERIFY_OPTS = { cert: 1, historicalMode: 1, issuer: 1, requestNonce: 1, time: 1 };
|
|
428
|
+
var _VERIFY_OPTS = Object.assign(Object.create(null), { cert: 1, historicalMode: 1, issuer: 1, requestNonce: 1, time: 1 });
|
|
429
429
|
|
|
430
430
|
function verify(response, opts) {
|
|
431
431
|
try {
|
|
@@ -465,7 +465,7 @@ function _responseNonce(parsed) {
|
|
|
465
465
|
return null;
|
|
466
466
|
}
|
|
467
467
|
|
|
468
|
-
var _VERIFY_REQUEST_OPTS = { certs: 1 };
|
|
468
|
+
var _VERIFY_REQUEST_OPTS = Object.assign(Object.create(null), { certs: 1 });
|
|
469
469
|
function _requestFromBytes(request) {
|
|
470
470
|
if (guard.bytes.isByteSource(request)) request = guard.bytes.snapshotSource(request, OcspError, "ocsp/bad-input", "the OCSP request");
|
|
471
471
|
return ocspSchema.parseRequest(request);
|
package/lib/oid.js
CHANGED
|
@@ -42,7 +42,7 @@ var OidError = frameworkError.OidError;
|
|
|
42
42
|
|
|
43
43
|
function _oidError(c, m) { return new OidError(c, m); }
|
|
44
44
|
|
|
45
|
-
var FAMILIES = {
|
|
45
|
+
var FAMILIES = Object.assign(Object.create(null), {
|
|
46
46
|
attributeType: { base: [2, 5, 4], of: {
|
|
47
47
|
commonName: 3, surname: 4, serialNumber: 5, countryName: 6,
|
|
48
48
|
localityName: 7, stateOrProvinceName: 8, streetAddress: 9,
|
|
@@ -335,7 +335,7 @@ var FAMILIES = {
|
|
|
335
335
|
scepMessageType: 2, scepPkiStatus: 3, scepFailInfo: 4,
|
|
336
336
|
scepSenderNonce: 5, scepRecipientNonce: 6, scepTransactionId: 7 } },
|
|
337
337
|
scep: { base: [1, 3, 6, 1, 5, 5, 7, 24], of: { scepFailInfoText: 1 } },
|
|
338
|
-
};
|
|
338
|
+
});
|
|
339
339
|
|
|
340
340
|
var _byOid = new Map();
|
|
341
341
|
var _byName = new Map();
|
|
@@ -483,7 +483,7 @@ function registerFamily(base, members) {
|
|
|
483
483
|
}
|
|
484
484
|
|
|
485
485
|
function all() {
|
|
486
|
-
var out =
|
|
486
|
+
var out = Object.create(null);
|
|
487
487
|
_byOid.forEach(function (v, k) { out[k] = v; });
|
|
488
488
|
return out;
|
|
489
489
|
}
|
package/lib/path-validate.js
CHANGED
|
@@ -80,7 +80,7 @@ var ANCHOR_SPKI_SCHEMA = pkix.spki(NS);
|
|
|
80
80
|
|
|
81
81
|
var subtle = webcrypto.webcrypto.subtle;
|
|
82
82
|
|
|
83
|
-
var OID = {
|
|
83
|
+
var OID = intrinsic.assign(intrinsic.create(null), {
|
|
84
84
|
basicConstraints: oid.byName("basicConstraints"),
|
|
85
85
|
keyUsage: oid.byName("keyUsage"),
|
|
86
86
|
nameConstraints: oid.byName("nameConstraints"),
|
|
@@ -98,9 +98,9 @@ var OID = {
|
|
|
98
98
|
authorityKeyIdentifier: oid.byName("authorityKeyIdentifier"),
|
|
99
99
|
authorityInfoAccess: oid.byName("authorityInfoAccess"),
|
|
100
100
|
caIssuers: oid.byName("caIssuers"),
|
|
101
|
-
};
|
|
101
|
+
});
|
|
102
102
|
|
|
103
|
-
var PROCESSED_EXTENSIONS =
|
|
103
|
+
var PROCESSED_EXTENSIONS = intrinsic.create(null);
|
|
104
104
|
[OID.basicConstraints, OID.keyUsage, OID.nameConstraints, OID.certificatePolicies,
|
|
105
105
|
OID.policyMappings, OID.policyConstraints, OID.inhibitAnyPolicy, OID.subjectAltName,
|
|
106
106
|
OID.extKeyUsage, OID.cRLDistributionPoints].
|
|
@@ -137,7 +137,7 @@ _sig("id-ml-dsa-87", { name: "ML-DSA-87" }, { name: "ML-DSA-87" }, "absent", fal
|
|
|
137
137
|
|
|
138
138
|
var OID_RSA_PSS = oid.byName("rsassaPss");
|
|
139
139
|
var OID_MGF1 = oid.byName("mgf1");
|
|
140
|
-
var HASH_BY_OID =
|
|
140
|
+
var HASH_BY_OID = intrinsic.create(null);
|
|
141
141
|
HASH_BY_OID[oid.byName("sha256")] = "SHA-256";
|
|
142
142
|
HASH_BY_OID[oid.byName("sha384")] = "SHA-384";
|
|
143
143
|
HASH_BY_OID[oid.byName("sha512")] = "SHA-512";
|
|
@@ -244,7 +244,7 @@ function compositeKeyUsageCheck(cert) {
|
|
|
244
244
|
return { ok: true };
|
|
245
245
|
}
|
|
246
246
|
|
|
247
|
-
var ML_KEM_OIDS =
|
|
247
|
+
var ML_KEM_OIDS = intrinsic.create(null);
|
|
248
248
|
["id-ml-kem-512", "id-ml-kem-768", "id-ml-kem-1024"].forEach(function (n) { ML_KEM_OIDS[oid.byName(n)] = true; });
|
|
249
249
|
|
|
250
250
|
function kemKeyUsageCheck(cert) {
|
|
@@ -323,12 +323,7 @@ function requireCriticalExt(ext, name, checks) {
|
|
|
323
323
|
}
|
|
324
324
|
|
|
325
325
|
|
|
326
|
-
|
|
327
|
-
var first = addr.indexOf("@");
|
|
328
|
-
if (first === -1) return null;
|
|
329
|
-
if (first !== addr.lastIndexOf("@")) return "ambiguous";
|
|
330
|
-
return [addr.slice(0, first), addr.slice(first + 1)];
|
|
331
|
-
}
|
|
326
|
+
var splitMailbox = guard.name.splitMailbox;
|
|
332
327
|
|
|
333
328
|
function emailMatch(constraint, mailbox) {
|
|
334
329
|
var mb = splitMailbox(mailbox);
|
|
@@ -346,7 +341,7 @@ function emailMatch(constraint, mailbox) {
|
|
|
346
341
|
return host === c;
|
|
347
342
|
}
|
|
348
343
|
|
|
349
|
-
|
|
344
|
+
var stripTrailingDot = guard.name.stripTrailingDot;
|
|
350
345
|
|
|
351
346
|
function hostConstraintMatch(constraint, host) {
|
|
352
347
|
var c = stripTrailingDot(constraint.toLowerCase()), h = stripTrailingDot(host.toLowerCase());
|
|
@@ -356,13 +351,6 @@ function hostConstraintMatch(constraint, host) {
|
|
|
356
351
|
}
|
|
357
352
|
|
|
358
353
|
function _charTable(chars) { var t = []; for (var i = 0; i < chars.length; i++) t[_charCodeAt(chars, i)] = true; return t; }
|
|
359
|
-
var _FQDN_TABLE = _charTable("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-");
|
|
360
|
-
var _DIGDOT_TABLE = _charTable("0123456789.");
|
|
361
|
-
function _allCharsIn(s, table) {
|
|
362
|
-
if (s.length === 0) return false;
|
|
363
|
-
for (var i = 0; i < s.length; i++) if (!table[_charCodeAt(s, i)]) return false;
|
|
364
|
-
return true;
|
|
365
|
-
}
|
|
366
354
|
function _startsWithDigit(s) { if (s.length === 0) return false; var c = _charCodeAt(s, 0); return c >= 48 && c <= 57; }
|
|
367
355
|
|
|
368
356
|
var _SCHEME_TABLE = _charTable("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+.-");
|
|
@@ -389,13 +377,7 @@ function _stripBrackets(s) {
|
|
|
389
377
|
return (n >= 2 && _charCodeAt(s, 0) === 91 && _charCodeAt(s, n - 1) === 93) ? s.slice(1, n - 1) : s;
|
|
390
378
|
}
|
|
391
379
|
|
|
392
|
-
|
|
393
|
-
var h = stripTrailingDot(host);
|
|
394
|
-
if (h === "" || h.indexOf(".") === -1) return false;
|
|
395
|
-
if (!_allCharsIn(h, _FQDN_TABLE)) return false;
|
|
396
|
-
if (_allCharsIn(h, _DIGDOT_TABLE)) return false;
|
|
397
|
-
return true;
|
|
398
|
-
}
|
|
380
|
+
var isFqdnHost = guard.name.isFqdnHost;
|
|
399
381
|
|
|
400
382
|
function uriMatch(constraint, uri) {
|
|
401
383
|
var host = uriHost(uri);
|
|
@@ -544,7 +526,7 @@ function treeIsEmpty(tree) { return tree.children.length === 0; }
|
|
|
544
526
|
|
|
545
527
|
function isSubtreeBaseValid(tag, base) {
|
|
546
528
|
switch (tag) {
|
|
547
|
-
case 1: case 2: case 6: return
|
|
529
|
+
case 1: case 2: case 6: return guard.name.constraintBaseRefusal(tag, base) === null;
|
|
548
530
|
case 7: return Buffer.isBuffer(base) && (base.length === 8 || base.length === 32);
|
|
549
531
|
case 4: return base !== null && typeof base === "object" && !!base.rdns && intrinsic.isArray(base.rdns);
|
|
550
532
|
default: return base !== undefined;
|
|
@@ -806,7 +788,7 @@ function prepareNext(state, cert, i, checks) {
|
|
|
806
788
|
function applyPolicyMappings(state, mappings, i) {
|
|
807
789
|
var depth = i;
|
|
808
790
|
if (state.policyMapping > 0) {
|
|
809
|
-
var mappedFrom =
|
|
791
|
+
var mappedFrom = intrinsic.create(null);
|
|
810
792
|
mappings.forEach(function (m) { guard.list.append(mappedFrom[m.issuerDomainPolicy] = mappedFrom[m.issuerDomainPolicy] || [], m.subjectDomainPolicy); });
|
|
811
793
|
var depthI = leavesAt(state.validPolicyTree, depth);
|
|
812
794
|
var anyNodes = depthI.filter(function (nd) { return nd.validPolicy === OID.anyPolicy; });
|
|
@@ -821,7 +803,7 @@ function applyPolicyMappings(state, mappings, i) {
|
|
|
821
803
|
}
|
|
822
804
|
});
|
|
823
805
|
} else {
|
|
824
|
-
var mappedSet =
|
|
806
|
+
var mappedSet = intrinsic.create(null);
|
|
825
807
|
mappings.forEach(function (m) { mappedSet[m.issuerDomainPolicy] = true; });
|
|
826
808
|
if (!state.validPolicyTree) return;
|
|
827
809
|
leavesAt(state.validPolicyTree, depth).forEach(function (node) {
|
|
@@ -835,7 +817,7 @@ function applyPolicyMappings(state, mappings, i) {
|
|
|
835
817
|
}
|
|
836
818
|
}
|
|
837
819
|
|
|
838
|
-
var TARGET_UNPROCESSED_IF_CRITICAL =
|
|
820
|
+
var TARGET_UNPROCESSED_IF_CRITICAL = intrinsic.create(null);
|
|
839
821
|
TARGET_UNPROCESSED_IF_CRITICAL[OID.policyMappings] = true;
|
|
840
822
|
Object.freeze(TARGET_UNPROCESSED_IF_CRITICAL);
|
|
841
823
|
|
|
@@ -923,7 +905,13 @@ function validateCriticalExtensionStructure(cert) {
|
|
|
923
905
|
* intermediate's own `nameConstraints` extension intersects with them and a leaf
|
|
924
906
|
* must satisfy both. They are a separate generation from
|
|
925
907
|
* `opts.initialPermittedSubtrees`, so those two intersect as well. A mis-shaped
|
|
926
|
-
* subtree is refused with `path/bad-input` rather than left inert
|
|
908
|
+
* subtree is refused with `path/bad-input` rather than left inert, and so is one
|
|
909
|
+
* whose base is outside the form its tag names: a host name for tags 2 and 6, a
|
|
910
|
+
* mailbox or host name for tag 1, at least one relative name with object
|
|
911
|
+
* identifier types and string values for tag 4, and 8 or 32 bytes for tag 7. An
|
|
912
|
+
* anchor whose `nameConstraints` names no subtree at all is refused the same way.
|
|
913
|
+
* A certificate's own `nameConstraints` extension is compared as the certificate
|
|
914
|
+
* wrote it; this rule is on the subtrees a caller supplies.
|
|
927
915
|
*
|
|
928
916
|
* @example
|
|
929
917
|
* var pair = await pki.key.generate("Ed25519");
|
|
@@ -939,13 +927,13 @@ function validateCriticalExtensionStructure(cert) {
|
|
|
939
927
|
* });
|
|
940
928
|
* res.valid; // boolean; res.results[0].checks carries the per-check codes
|
|
941
929
|
*/
|
|
942
|
-
var _VALIDATE_OPTS = {
|
|
930
|
+
var _VALIDATE_OPTS = intrinsic.assign(intrinsic.create(null), {
|
|
943
931
|
checkPurpose: 1, ctLogList: 1, ctPolicy: 1, historicalMode: 1, initialAnyPolicyInhibit: 1,
|
|
944
932
|
initialExcludedSubtrees: 1, initialExplicitPolicy: 1, initialPermittedSubtrees: 1,
|
|
945
933
|
initialPolicyMappingInhibit: 1, maxPathCerts: 1, maxPolicyNodes: 1, requireRevocation: 1,
|
|
946
934
|
requiredEku: 1, revocationChecker: 1, softFail: 1, time: 1, trustAnchors: 1,
|
|
947
935
|
userInitialPolicySet: 1, verifier: 1
|
|
948
|
-
};
|
|
936
|
+
});
|
|
949
937
|
|
|
950
938
|
var OID_SCT_LIST = oid.byName("signedCertificateTimestampList");
|
|
951
939
|
async function ctGateCheck(leaf, certs, anchor, ctLogList, ctPolicy, n, at) {
|
|
@@ -1015,7 +1003,7 @@ async function validate(path, opts) {
|
|
|
1015
1003
|
var exclRawOnce = opts.initialExcludedSubtrees;
|
|
1016
1004
|
var singleOpts = function (a) {
|
|
1017
1005
|
var keys = intrinsic.ownKeys(opts);
|
|
1018
|
-
var o =
|
|
1006
|
+
var o = intrinsic.create(null);
|
|
1019
1007
|
for (var ki = 0; ki < keys.length; ki++) { o[keys[ki]] = opts[keys[ki]]; }
|
|
1020
1008
|
o.trustAnchors = a;
|
|
1021
1009
|
if (permRawOnce != null) o.initialPermittedSubtrees = callerPermitted;
|
|
@@ -1248,12 +1236,12 @@ function userConstrainedPolicies(state, n) {
|
|
|
1248
1236
|
var uips = state.userInitialPolicySet;
|
|
1249
1237
|
var anyUser = contains(uips, OID.anyPolicy);
|
|
1250
1238
|
var leaves = leavesAt(state.validPolicyTree, n);
|
|
1251
|
-
var explicit =
|
|
1239
|
+
var explicit = intrinsic.create(null), hasAnyLeaf = false;
|
|
1252
1240
|
leaves.forEach(function (node) {
|
|
1253
1241
|
if (node.validPolicy === OID.anyPolicy) hasAnyLeaf = true;
|
|
1254
1242
|
else explicit[node.validPolicy] = true;
|
|
1255
1243
|
});
|
|
1256
|
-
var set =
|
|
1244
|
+
var set = intrinsic.create(null);
|
|
1257
1245
|
Object.keys(explicit).forEach(function (p) { if (anyUser || contains(uips, p)) set[p] = true; });
|
|
1258
1246
|
if (hasAnyLeaf) {
|
|
1259
1247
|
if (anyUser) set[OID.anyPolicy] = true;
|
|
@@ -1941,7 +1929,7 @@ function resolvePurposeOpts(opts) {
|
|
|
1941
1929
|
}
|
|
1942
1930
|
|
|
1943
1931
|
function _snapshotConstraintMap(m, E, code, who) {
|
|
1944
|
-
var out =
|
|
1932
|
+
var out = intrinsic.create(null);
|
|
1945
1933
|
var proto = intrinsic.getPrototypeOf(m);
|
|
1946
1934
|
if (proto !== null && proto !== intrinsic.ObjectProto) throw E(code, who + ": a trustAnchor constraint map must be a plain object (its own entries only), not one with a custom or cross-realm prototype");
|
|
1947
1935
|
var keys = intrinsic.getOwnPropertyNames(m);
|
|
@@ -1996,82 +1984,8 @@ var _ATV_KEYS = ["type", "value", "name"];
|
|
|
1996
1984
|
* and nothing deeper, so exactly those levels are walked and a self-referencing array is refused
|
|
1997
1985
|
* rather than followed.
|
|
1998
1986
|
*/
|
|
1999
|
-
function _copyDnRdns(rdns, who) {
|
|
2000
|
-
_assertPlainDnRdns(rdns, who);
|
|
2001
|
-
var out = [];
|
|
2002
|
-
for (var i = 0; i < rdns.length; i++) {
|
|
2003
|
-
var rd = intrinsic.getOwnPropertyDescriptor(rdns, i);
|
|
2004
|
-
if (rd === undefined) throw E("path/bad-input", who + " index " + i + " is a hole or is inherited; every entry must be its own");
|
|
2005
|
-
var rdn = rd.value;
|
|
2006
|
-
if (!intrinsic.isArray(rdn)) throw E("path/bad-input", who + "[" + i + "] must be an array of attributes");
|
|
2007
|
-
var rdnOut = [];
|
|
2008
|
-
for (var j = 0; j < rdn.length; j++) {
|
|
2009
|
-
var ad = intrinsic.getOwnPropertyDescriptor(rdn, j);
|
|
2010
|
-
if (ad === undefined) throw E("path/bad-input", who + "[" + i + "] index " + j + " is a hole or is inherited; every entry must be its own");
|
|
2011
|
-
var atv = ad.value;
|
|
2012
|
-
if (atv === null || typeof atv !== "object") throw E("path/bad-input", who + "[" + i + "][" + j + "] must be an attribute object carrying a type and a value");
|
|
2013
|
-
var atvOut = {};
|
|
2014
|
-
for (var k = 0; k < _ATV_KEYS.length; k++) {
|
|
2015
|
-
var fd = intrinsic.getOwnPropertyDescriptor(atv, _ATV_KEYS[k]);
|
|
2016
|
-
if (fd === undefined) continue;
|
|
2017
|
-
intrinsic.defineProperty(atvOut, _ATV_KEYS[k], { value: fd.value, enumerable: true, configurable: true, writable: true });
|
|
2018
|
-
}
|
|
2019
|
-
if (!intrinsic.hasOwn(atvOut, "type") || !intrinsic.hasOwn(atvOut, "value")) {
|
|
2020
|
-
throw E("path/bad-input", who + "[" + i + "][" + j + "] must carry its type and value as own data properties");
|
|
2021
|
-
}
|
|
2022
|
-
guard.list.append(rdnOut, atvOut);
|
|
2023
|
-
}
|
|
2024
|
-
guard.list.append(out, rdnOut);
|
|
2025
|
-
}
|
|
2026
|
-
return out;
|
|
2027
|
-
}
|
|
2028
|
-
/**
|
|
2029
|
-
* @internal The shape check the copy above relies on: a Proxy answers its own reads and an accessor
|
|
2030
|
-
* runs caller code, so either one at any level of the directoryName is refused before it is copied.
|
|
2031
|
-
*/
|
|
2032
|
-
function _assertPlainDnRdns(rdns, who) {
|
|
2033
|
-
if (intrinsic.types.isProxy(rdns)) throw E("path/bad-input", who + " must be a plain array, not a Proxy");
|
|
2034
|
-
for (var i = 0; i < rdns.length; i++) {
|
|
2035
|
-
var rd = intrinsic.getOwnPropertyDescriptor(rdns, i);
|
|
2036
|
-
if (rd === undefined) continue;
|
|
2037
|
-
if (!intrinsic.hasOwn(rd, "value")) throw E("path/bad-input", who + " entry " + i + " must be a data property, not an accessor");
|
|
2038
|
-
var rdn = rd.value;
|
|
2039
|
-
if (!intrinsic.isArray(rdn)) continue;
|
|
2040
|
-
if (intrinsic.types.isProxy(rdn)) throw E("path/bad-input", who + "[" + i + "] must be a plain array, not a Proxy");
|
|
2041
|
-
for (var j = 0; j < rdn.length; j++) {
|
|
2042
|
-
var ad = intrinsic.getOwnPropertyDescriptor(rdn, j);
|
|
2043
|
-
if (ad === undefined) continue;
|
|
2044
|
-
if (!intrinsic.hasOwn(ad, "value")) throw E("path/bad-input", who + "[" + i + "] entry " + j + " must be a data property, not an accessor");
|
|
2045
|
-
var atv = ad.value;
|
|
2046
|
-
if (atv === null || typeof atv !== "object") continue;
|
|
2047
|
-
if (intrinsic.types.isProxy(atv)) throw E("path/bad-input", who + "[" + i + "][" + j + "] must not be a Proxy");
|
|
2048
|
-
if (intrinsic.isArray(atv)) throw E("path/bad-input", who + "[" + i + "][" + j + "] must be an attribute object, not an array");
|
|
2049
|
-
for (var k = 0; k < _ATV_KEYS.length; k++) {
|
|
2050
|
-
var fd = intrinsic.getOwnPropertyDescriptor(atv, _ATV_KEYS[k]);
|
|
2051
|
-
if (fd !== undefined && !intrinsic.hasOwn(fd, "value")) {
|
|
2052
|
-
throw E("path/bad-input", who + "[" + i + "][" + j + "]." + _ATV_KEYS[k] + " must be a data property, not an accessor");
|
|
2053
|
-
}
|
|
2054
|
-
}
|
|
2055
|
-
}
|
|
2056
|
-
}
|
|
2057
|
-
}
|
|
2058
1987
|
function _capturedRdns(base, who) {
|
|
2059
|
-
|
|
2060
|
-
/** @internal An inherited Proxy answers `in` through its has trap, which is caller code running
|
|
2061
|
-
* inside what is meant to be a getter-free read. */
|
|
2062
|
-
var baseProto = intrinsic.getPrototypeOf(base);
|
|
2063
|
-
while (baseProto !== null) {
|
|
2064
|
-
if (intrinsic.types.isProxy(baseProto)) throw E("path/bad-input", who + ": a trustAnchor nameConstraints directoryName base must not inherit from a Proxy");
|
|
2065
|
-
baseProto = intrinsic.getPrototypeOf(baseProto);
|
|
2066
|
-
}
|
|
2067
|
-
var d = intrinsic.getOwnPropertyDescriptor(base, "rdns");
|
|
2068
|
-
if (d === undefined) {
|
|
2069
|
-
if ("rdns" in base) throw E("path/bad-input", who + ": a trustAnchor nameConstraints directoryName rdns must be an own data property, not inherited");
|
|
2070
|
-
return undefined;
|
|
2071
|
-
}
|
|
2072
|
-
if (!intrinsic.hasOwn(d, "value")) throw E("path/bad-input", who + ": a trustAnchor nameConstraints directoryName rdns must be a data property, not an accessor");
|
|
2073
|
-
if (!intrinsic.isArray(d.value)) return undefined;
|
|
2074
|
-
return _copyDnRdns(d.value, who + ": a trustAnchor nameConstraints directoryName rdns");
|
|
1988
|
+
return guard.name.capturedRdns(base, E, "path/bad-input", who + ": a trustAnchor nameConstraints directoryName base");
|
|
2075
1989
|
}
|
|
2076
1990
|
var _NC_SUBTREE_KEYS = ["tag", "base"];
|
|
2077
1991
|
var _NC_LIST_KEYS = ["permitted", "excluded"];
|
|
@@ -2168,6 +2082,12 @@ function _copyAnchorNameConstraints(nc, who) {
|
|
|
2168
2082
|
var checkedList = checkedSubtreeSeeds(copiedList, "trustAnchors[].nameConstraints." + key);
|
|
2169
2083
|
intrinsic.defineProperty(out, key, { value: checkedList, enumerable: true, configurable: true, writable: true });
|
|
2170
2084
|
}
|
|
2085
|
+
/** @internal An anchor carrying the option but naming no subtree restricts nothing, and reads to
|
|
2086
|
+
* whoever built it as a namespace that has been applied. */
|
|
2087
|
+
if ((out.permitted === undefined || out.permitted.length === 0) &&
|
|
2088
|
+
(out.excluded === undefined || out.excluded.length === 0)) {
|
|
2089
|
+
throw E("path/bad-input", who + ": a trustAnchor nameConstraints must name at least one permitted or excluded subtree");
|
|
2090
|
+
}
|
|
2171
2091
|
return out;
|
|
2172
2092
|
}
|
|
2173
2093
|
|
|
@@ -2468,7 +2388,9 @@ function _aiaParseBody(body, contentType, maxCerts) {
|
|
|
2468
2388
|
}
|
|
2469
2389
|
|
|
2470
2390
|
async function _aiaFetchOne(uri, aia) {
|
|
2471
|
-
var res = await
|
|
2391
|
+
var res = await guard.async.invoked(aia.transport,
|
|
2392
|
+
[{ method: "GET", url: uri, tls: aia.tls, timeout: aia.timeout, maxResponseBytes: aia.maxResponseBytes, blockPrivateAddresses: true }],
|
|
2393
|
+
E, "path/bad-input", "opts.transport");
|
|
2472
2394
|
res = res || {};
|
|
2473
2395
|
if (res.status !== 200) throw E("path/aia-status", "an AIA fetch returned HTTP " + res.status + " (only 200 is a cert source; no redirect following)");
|
|
2474
2396
|
var body = guard.bytes.isByteSource(res.body)
|
|
@@ -2476,7 +2398,7 @@ async function _aiaFetchOne(uri, aia) {
|
|
|
2476
2398
|
: Buffer.from(res.body == null ? "" : String(res.body), "latin1");
|
|
2477
2399
|
if (body.length === 0) throw E("path/aia-empty", "an AIA fetch returned an empty body");
|
|
2478
2400
|
if (body.length > aia.maxResponseBytes) throw E("path/aia-too-large", "an AIA response exceeds the " + aia.maxResponseBytes + "-byte cap");
|
|
2479
|
-
var headers =
|
|
2401
|
+
var headers = intrinsic.create(null);
|
|
2480
2402
|
Object.keys(res.headers || {}).forEach(function (k) { headers[k.toLowerCase()] = res.headers[k]; });
|
|
2481
2403
|
return _aiaParseBody(body, headers["content-type"], aia.maxCertsPerResponse);
|
|
2482
2404
|
}
|
|
@@ -2509,6 +2431,11 @@ async function _fetchAiaIssuers(current, aia) {
|
|
|
2509
2431
|
intrinsic.setAdd(aia.fetchedUrls, uris[k]);
|
|
2510
2432
|
aia.fetches += 1;
|
|
2511
2433
|
var certs;
|
|
2434
|
+
/** @internal Every failure of a fetch is skipped and the next URL tried, because AIA is a
|
|
2435
|
+
* best-effort source of issuers and one unreachable host must not fail a build that another URL
|
|
2436
|
+
* can complete. A transport that throws where a rejecting one would only reject is the same
|
|
2437
|
+
* failure reported a different way, so the two are treated alike rather than one of them ending
|
|
2438
|
+
* the build. */
|
|
2512
2439
|
try { certs = await _aiaFetchOne(uris[k], aia); }
|
|
2513
2440
|
catch (_e2) { continue; }
|
|
2514
2441
|
for (var c = 0; c < certs.length; c++) {
|
|
@@ -2591,11 +2518,11 @@ async function _fetchAiaIssuers(current, aia) {
|
|
|
2591
2518
|
* result.valid; // true when a path to a trust anchor was found and validated
|
|
2592
2519
|
*/
|
|
2593
2520
|
var _BUILD_OPTS = (function () {
|
|
2594
|
-
var o = {
|
|
2521
|
+
var o = intrinsic.assign(intrinsic.create(null), {
|
|
2595
2522
|
aiaTimeout: 1, candidates: 1, direction: 1, fetchAia: 1, intermediates: 1, maxAiaFetches: 1,
|
|
2596
2523
|
maxAiaPerCert: 1, maxCandidatesConsidered: 1, maxDepth: 1, maxPathCerts: 1,
|
|
2597
2524
|
maxResponseBytes: 1, time: 1, tls: 1, transport: 1, trustAnchors: 1, validate: 1
|
|
2598
|
-
};
|
|
2525
|
+
});
|
|
2599
2526
|
Object.keys(_VALIDATE_OPTS).forEach(function (k) { o[k] = 1; });
|
|
2600
2527
|
return o;
|
|
2601
2528
|
})();
|
|
@@ -2604,6 +2531,12 @@ async function build(leaf, opts) {
|
|
|
2604
2531
|
opts = guard.identifier.optionsObject(opts, E, "path/bad-input", "build: opts");
|
|
2605
2532
|
guard.identifier.assertKnownKeys(opts, _BUILD_OPTS, E, "path/bad-input",
|
|
2606
2533
|
"pki.path.build has an unknown option (the anchor option is `trustAnchors`). The unknown option was: ");
|
|
2534
|
+
/** @internal Checked at the door, before any certificate is parsed, and whether or not AIA
|
|
2535
|
+
* fetching is on: supplying a transport that cannot be called is a wiring fault at the moment it
|
|
2536
|
+
* is written. The checked value is the one used below, since reading the option again would ask a
|
|
2537
|
+
* second time and an accessor can answer differently on each read. */
|
|
2538
|
+
var checkedTransport = guard.identifier.assertCallableOption(opts, "transport", E, "path/bad-input",
|
|
2539
|
+
"build: opts.transport", "(request) -> Promise<{ status, headers, body }>");
|
|
2607
2540
|
var leafCert;
|
|
2608
2541
|
try { leafCert = coerceCert(leaf); }
|
|
2609
2542
|
catch (e) { throw E("path/bad-input", "build: the leaf certificate did not parse", e); }
|
|
@@ -2652,13 +2585,10 @@ async function build(leaf, opts) {
|
|
|
2652
2585
|
|
|
2653
2586
|
var aiaCtx = null;
|
|
2654
2587
|
if (opts.fetchAia === true) {
|
|
2655
|
-
if (opts.transport !== undefined && typeof opts.transport !== "function") {
|
|
2656
|
-
throw E("path/bad-input", "build: opts.transport must be a transport function (request) -> Promise<{ status, headers, body }>");
|
|
2657
|
-
}
|
|
2658
2588
|
if (opts.aiaTimeout !== undefined) {
|
|
2659
2589
|
guard.limits.cap(opts.aiaTimeout, "build: opts.aiaTimeout", 1, { E: E, code: "path/bad-input", min: 1, max: httpTransport.MAX_TIMEOUT });
|
|
2660
2590
|
}
|
|
2661
|
-
var aiaTransport =
|
|
2591
|
+
var aiaTransport = checkedTransport || httpTransport.https({ E: E, errPrefix: "path" });
|
|
2662
2592
|
aiaCtx = {
|
|
2663
2593
|
transport: aiaTransport,
|
|
2664
2594
|
transportGuardsAddresses: aiaTransport.blocksPrivateAddresses === true,
|