@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/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,
@@ -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
- function _append(arr, v) { _defineProperty(arr, arr.length, { value: v, writable: true, enumerable: true, configurable: true }); }
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
- function _push(arr, v) { _defineProperty(arr, arr.length, { value: v, writable: true, enumerable: true, configurable: true }); }
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; }
@@ -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 { applicable: false, matched: false, reason: "non-successful OCSP responseStatus (" + resp.responseStatus.code + ")" };
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 { applicable: false, matched: false, reason: "successful OCSP response carries no BasicOCSPResponse" };
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, matched: false, responderAuthorized: false, reason: "no authorized OCSP responder signs this response (RFC 6960 sec. 4.2.2.2)" };
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, matched: false, responderAuthorized: true, signatureValid: false, reason: "the OCSP response signature does not verify over tbsResponseData" };
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, matched: false, responderAuthorized: true, signatureValid: true, reason: "the OCSP response carries an unrecognized critical extension" };
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, matched: false, responderAuthorized: true, signatureValid: true, revoked: null, sawGood: false, sawUnknownStatus: false, reason: "no current SingleResponse names this certificate" };
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
- if (opts.requestNonce == null) return Object.assign({}, verdict, { nonceMatched: null });
441
- var respNonce = _responseNonce(parsed);
442
- var reqNonce = guard.bytes.isByteSource(opts.requestNonce)
443
- ? guard.bytes.snapshotSource(opts.requestNonce, OcspError, "ocsp/bad-input", "opts.requestNonce") : null;
444
- var matched = respNonce != null && reqNonce != null && guard.crypto.constantTimeEqual(respNonce, reqNonce);
445
- var out = Object.assign({}, verdict, { nonceMatched: matched });
446
- if (!matched && verdict.status === "good") {
447
- return Object.assign(out, { status: "unknown", reason: "the OCSP response nonce does not echo the request nonce (RFC 9654)" });
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 = [];