@blamejs/pki 0.6.38 → 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 +37 -0
- package/lib/attrcert-sign.js +2 -2
- package/lib/cmc-verify.js +10 -4
- package/lib/cmp-session.js +11 -12
- package/lib/cmp-verify.js +4 -8
- package/lib/cms-verify.js +45 -35
- package/lib/composite-sig.js +1 -1
- package/lib/crl-sign.js +8 -8
- package/lib/crmf-sign.js +6 -3
- package/lib/csr-sign.js +2 -2
- package/lib/ct.js +14 -14
- package/lib/guard-all.js +2 -0
- 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 +47 -0
- package/lib/ip-utils.js +1 -1
- package/lib/ocsp-verify.js +20 -6
- package/lib/ocsp.js +21 -12
- package/lib/path-validate.js +105 -103
- package/lib/pkcs12-build.js +11 -9
- package/lib/sigstore.js +16 -7
- package/lib/smime.js +6 -6
- 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/guard-list.js
CHANGED
|
@@ -4,6 +4,21 @@
|
|
|
4
4
|
// @internal
|
|
5
5
|
|
|
6
6
|
var _freeze = require("./guard-intrinsic").freeze;
|
|
7
|
+
var _defineProperty = require("./guard-intrinsic").defineProperty;
|
|
8
|
+
var _isArray = require("./guard-intrinsic").isArray;
|
|
9
|
+
|
|
10
|
+
var MAX_ARRAY_LENGTH = 4294967295;
|
|
11
|
+
|
|
12
|
+
// @enforced-by guard-shape-reinlined
|
|
13
|
+
// @guard-shape defineProperty\(\s*\w+\s*,\s*\w+\.length\s*,\s*\{\s*value:
|
|
14
|
+
// @guard-via guard\.list\.append\(
|
|
15
|
+
function append(list, value) {
|
|
16
|
+
if (!_isArray(list)) throw new TypeError("guard.list.append: the receiver must be an array");
|
|
17
|
+
var n = list.length;
|
|
18
|
+
if (n >= MAX_ARRAY_LENGTH) throw new RangeError("guard.list.append: the array is at its maximum length");
|
|
19
|
+
_defineProperty(list, n, { value: value, writable: true, enumerable: true, configurable: true });
|
|
20
|
+
return list;
|
|
21
|
+
}
|
|
7
22
|
|
|
8
23
|
// @enforced-by behavioral -- `.indexOf(x) !== -1` has no rename-proof form that separates a
|
|
9
24
|
function contains(list, value) {
|
|
@@ -34,6 +49,7 @@ function allMatch(list, predicate) {
|
|
|
34
49
|
}
|
|
35
50
|
|
|
36
51
|
module.exports = _freeze({
|
|
52
|
+
append: append,
|
|
37
53
|
contains: contains,
|
|
38
54
|
containsAll: containsAll,
|
|
39
55
|
anyMatches: anyMatches,
|
package/lib/guard-parsed.js
CHANGED
|
@@ -20,7 +20,7 @@ var _weakSet = require("./guard-intrinsic").weakSet;
|
|
|
20
20
|
var _weakHas = require("./guard-intrinsic").weakHas;
|
|
21
21
|
var _WeakMap = require("./guard-intrinsic").WeakMap;
|
|
22
22
|
var _defineProperty = require("./guard-intrinsic").defineProperty;
|
|
23
|
-
|
|
23
|
+
var _append = require("./guard-list").append;
|
|
24
24
|
|
|
25
25
|
function _isBytes(x) {
|
|
26
26
|
return bytes.isByteSource(x);
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (c) blamejs contributors
|
|
3
|
+
"use strict";
|
|
4
|
+
// @internal
|
|
5
|
+
|
|
6
|
+
var _freeze = require("./guard-intrinsic").freeze;
|
|
7
|
+
var _keys = require("./guard-intrinsic").keys;
|
|
8
|
+
var _defineProperty = require("./guard-intrinsic").defineProperty;
|
|
9
|
+
var _getOwnPropertyDescriptor = require("./guard-intrinsic").getOwnPropertyDescriptor;
|
|
10
|
+
var _hasOwn = require("./guard-intrinsic").hasOwn;
|
|
11
|
+
var _Object = require("./guard-intrinsic").Object;
|
|
12
|
+
|
|
13
|
+
function _copyOwn(out, src) {
|
|
14
|
+
var keys = _keys(src);
|
|
15
|
+
for (var i = 0; i < keys.length; i++) {
|
|
16
|
+
var d = _getOwnPropertyDescriptor(src, keys[i]);
|
|
17
|
+
if (!d) continue;
|
|
18
|
+
var value = _hasOwn(d, "value") ? d.value : src[keys[i]];
|
|
19
|
+
_defineProperty(out, keys[i], { value: value, enumerable: true, configurable: true, writable: true });
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// @enforced-by behavioral -- the defect is the ABSENCE of this call at a construction site, not a
|
|
24
|
+
function of(src, extras) {
|
|
25
|
+
var out = {};
|
|
26
|
+
_copyOwn(out, src);
|
|
27
|
+
if (extras != null) _copyOwn(out, extras);
|
|
28
|
+
/** @internal Resolving a promise reads `then` off the value, so an inherited accessor would run
|
|
29
|
+
* with the verdict as its receiver and could rewrite a field or hand the caller a different
|
|
30
|
+
* object. An own `then` ends that lookup, and is non-enumerable so keys, JSON, a spread and a
|
|
31
|
+
* deep-equality comparison do not see it. */
|
|
32
|
+
_defineProperty(out, "then", { value: undefined, enumerable: false, configurable: true, writable: true });
|
|
33
|
+
return out;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// @enforced-by behavioral -- Object.hasOwn and hasOwnProperty are replaceable at any time, and a
|
|
37
|
+
function carries(obj, key) {
|
|
38
|
+
return obj != null && _hasOwn(_Object(obj), key);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// @enforced-by behavioral -- for a target that cannot be rebuilt, an Error carrying a field a
|
|
42
|
+
function set(target, key, value) {
|
|
43
|
+
_defineProperty(target, key, { value: value, enumerable: true, configurable: true, writable: true });
|
|
44
|
+
return target;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
module.exports = _freeze({ of: of, carries: carries, set: set });
|
package/lib/ip-utils.js
CHANGED
|
@@ -15,7 +15,7 @@ var _bufferFrom = intrinsic.bufferFrom;
|
|
|
15
15
|
var _bufferAlloc = intrinsic.bufferAlloc;
|
|
16
16
|
var _defineProperty = intrinsic.defineProperty;
|
|
17
17
|
var _Number = intrinsic.Number;
|
|
18
|
-
|
|
18
|
+
var _push = require("./guard-list").append;
|
|
19
19
|
function _splitOn(str, sep) {
|
|
20
20
|
var out = [], from = 0, at;
|
|
21
21
|
while ((at = _indexOf(str, sep, from)) !== -1) { _push(out, _slice(str, from, at)); from = at + sep.length; }
|
package/lib/ocsp-verify.js
CHANGED
|
@@ -121,19 +121,33 @@ function makeOcspVerify(deps) {
|
|
|
121
121
|
|
|
122
122
|
function isOctetAligned(bitString) { return !!bitString && bitString.unusedBits === 0; }
|
|
123
123
|
|
|
124
|
+
/**
|
|
125
|
+
* @internal Every field the callers decide on is present on every return, so a field an early
|
|
126
|
+
* return would have left absent is read from the response that was evaluated rather than from
|
|
127
|
+
* whatever a polluted Object.prototype answers: a rejected response would otherwise be able to
|
|
128
|
+
* report `sawGood`, and a certificate with no authoritative response would read as good.
|
|
129
|
+
*/
|
|
130
|
+
function _evaluation(extras) {
|
|
131
|
+
return guard.verdict.of({
|
|
132
|
+
applicable: false, matched: false, responderAuthorized: false, signatureValid: false,
|
|
133
|
+
revoked: null, sawGood: false, sawUnknownStatus: false,
|
|
134
|
+
thisUpdate: null, nextUpdate: null, reason: "",
|
|
135
|
+
}, extras);
|
|
136
|
+
}
|
|
137
|
+
|
|
124
138
|
async function evaluateResponse(resp, cert, issuer, issuerKeyBits, issuerNameCandidates, time, historical) {
|
|
125
|
-
if (resp.responseStatus.code !== 0) return {
|
|
139
|
+
if (resp.responseStatus.code !== 0) return _evaluation({ reason: "non-successful OCSP responseStatus (" + resp.responseStatus.code + ")" });
|
|
126
140
|
var br = resp.basicResponse;
|
|
127
|
-
if (!br) return {
|
|
141
|
+
if (!br) return _evaluation({ reason: "successful OCSP response carries no BasicOCSPResponse" });
|
|
128
142
|
var signerSpki = await ocspAuthorizeResponder(br, cert, issuer, issuerKeyBits, time);
|
|
129
|
-
if (!signerSpki) return { applicable: true,
|
|
143
|
+
if (!signerSpki) return _evaluation({ applicable: true, reason: "no authorized OCSP responder signs this response (RFC 6960 sec. 4.2.2.2)" });
|
|
130
144
|
if (!(await verifyWithSpki(br.signatureAlgorithm, br.signature, signerSpki, br.tbsResponseDataBytes))) {
|
|
131
|
-
return { applicable: true,
|
|
145
|
+
return _evaluation({ applicable: true, responderAuthorized: true, reason: "the OCSP response signature does not verify over tbsResponseData" });
|
|
132
146
|
}
|
|
133
147
|
if (ocspHasCriticalExtension(br.responseExtensions)) {
|
|
134
|
-
return { applicable: true,
|
|
148
|
+
return _evaluation({ applicable: true, responderAuthorized: true, signatureValid: true, reason: "the OCSP response carries an unrecognized critical extension" });
|
|
135
149
|
}
|
|
136
|
-
var out = { applicable: true,
|
|
150
|
+
var out = _evaluation({ applicable: true, responderAuthorized: true, signatureValid: true, reason: "no current SingleResponse names this certificate" });
|
|
137
151
|
for (var s = 0; s < br.responses.length; s++) {
|
|
138
152
|
var sr = br.responses[s];
|
|
139
153
|
if (!(await ocspCertIdMatches(sr.certID, cert, issuerNameCandidates, issuerKeyBits))) continue;
|
package/lib/ocsp.js
CHANGED
|
@@ -374,7 +374,7 @@ function buildErrorResponse(status) {
|
|
|
374
374
|
|
|
375
375
|
/**
|
|
376
376
|
* @primitive pki.ocsp.verify
|
|
377
|
-
* @signature pki.ocsp.verify(response, opts) -> Promise<{ status, responderAuthorized, signatureValid, matched, thisUpdate, nextUpdate, revocationReason?, revocationTime?, nonceMatched?, reason }>
|
|
377
|
+
* @signature pki.ocsp.verify(response, opts) -> Promise<{ valid, status, responderAuthorized, signatureValid, matched, thisUpdate, nextUpdate, revocationReason?, revocationTime?, nonceMatched?, reason }>
|
|
378
378
|
* @since 0.2.22
|
|
379
379
|
* @status stable
|
|
380
380
|
* @spec RFC 6960, RFC 9654, RFC 5019
|
|
@@ -389,6 +389,11 @@ function buildErrorResponse(status) {
|
|
|
389
389
|
* unauthorized, stale, or CertID-mismatched response is a `"unknown"` verdict (never a silent
|
|
390
390
|
* accept); a malformed response's parse fault surfaces as the parser's `ocsp/*` / `asn1/*`.
|
|
391
391
|
*
|
|
392
|
+
* `valid` is the toolkit-wide verdict alias the other verify verbs carry, and it is true only when
|
|
393
|
+
* `status` is `"good"`. Because every failure this verb detects already collapses to `"unknown"`,
|
|
394
|
+
* `valid` states exactly what `status === "good"` does and hides no unrun check. A revoked
|
|
395
|
+
* certificate is `valid: false`; which of the two it was stays in `status`.
|
|
396
|
+
*
|
|
392
397
|
* The request-nonce check is reported, and downgrades `good` alone. Every verdict carries
|
|
393
398
|
* `nonceMatched` (true / false / null when the client sent no nonce). An unmatched nonce turns a
|
|
394
399
|
* `good` into `"unknown"`, because a response that is not an answer to this request cannot be relied
|
|
@@ -437,16 +442,20 @@ function verify(response, opts) {
|
|
|
437
442
|
time = opts.time == null ? new Date() : _asDate(opts.time);
|
|
438
443
|
} catch (e) { return Promise.reject(e); }
|
|
439
444
|
return pathValidate.verifyOcspResponse(parsed, cert, issuerCert, time, { historicalMode: opts.historicalMode === true }).then(function (verdict) {
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
445
|
+
var out;
|
|
446
|
+
if (opts.requestNonce == null) {
|
|
447
|
+
out = guard.verdict.of(verdict, { nonceMatched: null });
|
|
448
|
+
} else {
|
|
449
|
+
var respNonce = _responseNonce(parsed);
|
|
450
|
+
var reqNonce = guard.bytes.isByteSource(opts.requestNonce)
|
|
451
|
+
? guard.bytes.snapshotSource(opts.requestNonce, OcspError, "ocsp/bad-input", "opts.requestNonce") : null;
|
|
452
|
+
var matched = respNonce != null && reqNonce != null && guard.crypto.constantTimeEqual(respNonce, reqNonce);
|
|
453
|
+
out = guard.verdict.of(verdict, { nonceMatched: matched });
|
|
454
|
+
if (!matched && out.status === "good") {
|
|
455
|
+
out = guard.verdict.of(out, { status: "unknown", reason: "the OCSP response nonce does not echo the request nonce (RFC 9654)" });
|
|
456
|
+
}
|
|
448
457
|
}
|
|
449
|
-
return out;
|
|
458
|
+
return guard.verdict.of(out, { valid: out.status === "good" });
|
|
450
459
|
});
|
|
451
460
|
}
|
|
452
461
|
function _responseNonce(parsed) {
|
|
@@ -462,7 +471,7 @@ function _requestFromBytes(request) {
|
|
|
462
471
|
return ocspSchema.parseRequest(request);
|
|
463
472
|
}
|
|
464
473
|
function _reqVerdict(parsed, extra) {
|
|
465
|
-
return {
|
|
474
|
+
return guard.verdict.of({
|
|
466
475
|
valid: extra.signed === true && extra.signatureValid === true,
|
|
467
476
|
signed: extra.signed, signatureValid: extra.signatureValid,
|
|
468
477
|
signerCert: extra.signerCert != null ? extra.signerCert : null,
|
|
@@ -472,7 +481,7 @@ function _reqVerdict(parsed, extra) {
|
|
|
472
481
|
requestorName: parsed.requestorName, requestList: parsed.requestList,
|
|
473
482
|
requestExtensions: parsed.requestExtensions, version: parsed.version,
|
|
474
483
|
reason: extra.reason != null ? extra.reason : null,
|
|
475
|
-
};
|
|
484
|
+
});
|
|
476
485
|
}
|
|
477
486
|
async function _findRequestSigners(candidates, strict, parsed, sig, sigBits) {
|
|
478
487
|
var parsedList = [];
|