@blamejs/pki 0.5.7 → 0.5.8

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.
Files changed (104) hide show
  1. package/CHANGELOG.md +405 -386
  2. package/MIGRATING.md +43 -0
  3. package/README.md +12 -12
  4. package/lib/acme.js +31 -31
  5. package/lib/asn1-der.js +10 -10
  6. package/lib/attrcert-sign.js +19 -19
  7. package/lib/byte-reader.js +6 -6
  8. package/lib/byte-writer.js +5 -5
  9. package/lib/cbor-det.js +27 -24
  10. package/lib/cmc-build.js +97 -92
  11. package/lib/cmc-verify.js +106 -30
  12. package/lib/cmp-build.js +25 -25
  13. package/lib/cmp-session.js +70 -70
  14. package/lib/cmp-verify.js +71 -57
  15. package/lib/cms-compress.js +7 -7
  16. package/lib/cms-decrypt.js +90 -72
  17. package/lib/cms-encrypt.js +32 -32
  18. package/lib/cms-sign.js +74 -55
  19. package/lib/cms-verify.js +97 -75
  20. package/lib/composite-sig.js +13 -13
  21. package/lib/constants.js +4 -4
  22. package/lib/crl-sign.js +22 -22
  23. package/lib/crl-verify.js +7 -6
  24. package/lib/crmf-sign.js +14 -14
  25. package/lib/csr-sign.js +8 -8
  26. package/lib/ct.js +37 -37
  27. package/lib/edwards-point.js +7 -7
  28. package/lib/est.js +98 -55
  29. package/lib/framework-error.js +5 -5
  30. package/lib/guard-all.js +3 -3
  31. package/lib/guard-async.js +4 -4
  32. package/lib/guard-bytes.js +79 -79
  33. package/lib/guard-compress.js +17 -17
  34. package/lib/guard-crypto.js +1 -1
  35. package/lib/guard-encoding.js +15 -15
  36. package/lib/guard-header.js +3 -3
  37. package/lib/guard-identifier.js +16 -16
  38. package/lib/guard-json.js +15 -15
  39. package/lib/guard-limits.js +7 -7
  40. package/lib/guard-name.js +81 -16
  41. package/lib/guard-parsed.js +80 -80
  42. package/lib/guard-range.js +19 -19
  43. package/lib/guard-secret.js +11 -10
  44. package/lib/guard-text.js +6 -6
  45. package/lib/guard-time.js +10 -10
  46. package/lib/hpke.js +18 -17
  47. package/lib/http-digest.js +35 -35
  48. package/lib/http-retry-after.js +13 -13
  49. package/lib/http-transport.js +20 -19
  50. package/lib/inspect.js +53 -53
  51. package/lib/ip-utils.js +2 -2
  52. package/lib/jose.js +13 -13
  53. package/lib/key.js +16 -16
  54. package/lib/lint.js +51 -51
  55. package/lib/merkle.js +51 -36
  56. package/lib/mime.js +18 -18
  57. package/lib/ocsp-verify.js +10 -10
  58. package/lib/ocsp.js +13 -13
  59. package/lib/oid.js +29 -29
  60. package/lib/path-validate.js +114 -113
  61. package/lib/pbes2.js +16 -16
  62. package/lib/pkcs12-build.js +53 -53
  63. package/lib/pki-build.js +21 -19
  64. package/lib/rc2.js +1 -1
  65. package/lib/rfc3339.js +5 -5
  66. package/lib/schema-all.js +31 -31
  67. package/lib/schema-attrcert.js +12 -12
  68. package/lib/schema-c509.js +144 -142
  69. package/lib/schema-cmc.js +58 -58
  70. package/lib/schema-cmp.js +43 -43
  71. package/lib/schema-cms.js +45 -45
  72. package/lib/schema-crl.js +7 -7
  73. package/lib/schema-crmf.js +28 -28
  74. package/lib/schema-csr.js +12 -12
  75. package/lib/schema-csrattrs.js +16 -16
  76. package/lib/schema-engine.js +18 -18
  77. package/lib/schema-ocsp.js +15 -15
  78. package/lib/schema-pkcs12.js +20 -20
  79. package/lib/schema-pkcs8.js +2 -2
  80. package/lib/schema-pkix.js +131 -126
  81. package/lib/schema-smime.js +19 -19
  82. package/lib/schema-tsp.js +12 -12
  83. package/lib/schema-x509.js +3 -3
  84. package/lib/shbs.js +18 -18
  85. package/lib/sign-scheme.js +13 -13
  86. package/lib/sigstore.js +10 -11
  87. package/lib/sleep.js +1 -1
  88. package/lib/smime.js +308 -96
  89. package/lib/tls-cert-compress.js +18 -18
  90. package/lib/trust.js +27 -27
  91. package/lib/tsp-sign.js +17 -17
  92. package/lib/validator-all.js +1 -1
  93. package/lib/validator-attcert.js +1 -1
  94. package/lib/validator-cose.js +43 -44
  95. package/lib/validator-keydesc.js +3 -3
  96. package/lib/validator-sig.js +13 -13
  97. package/lib/validator-tls.js +11 -11
  98. package/lib/validator-tpm.js +20 -19
  99. package/lib/webauthn-mds.js +66 -66
  100. package/lib/webauthn.js +33 -33
  101. package/lib/webcrypto.js +15 -15
  102. package/lib/x509-sign.js +13 -13
  103. package/package.json +3 -2
  104. package/sbom.cdx.json +6 -6
package/lib/est.js CHANGED
@@ -13,8 +13,8 @@
13
13
  * The network verbs -- `cacerts`, `simpleenroll`, `simplereenroll` -- run the thin
14
14
  * RFC 7030 client: they compose the codecs below over the shared `pki.transport`
15
15
  * (a caller MAY inject `opts.transport`; the default is a fail-closed
16
- * `pki.transport.https`). This module opens no socket itself -- the sole socket
17
- * choke point is `pki.transport` -- so the verbs stay a thin, fail-closed shell:
16
+ * `pki.transport.https`). This module opens no socket itself: the sole socket
17
+ * choke point is `pki.transport`, so the verbs stay a thin, fail-closed shell:
18
18
  * https-only (`est/insecure-url`), an explicit trust anchor required
19
19
  * (`est/no-trust-anchors`), same-origin redirects followed but a downgrade / loop
20
20
  * refused, a 202 Retry-After SURFACED and never slept, HTTP Basic answered only
@@ -22,10 +22,10 @@
22
22
  * by public-key match. Under them sit the transport-agnostic codecs, validators, and
23
23
  * request builders over the shipped CMS / CSR / PKCS#8 / X.509 parsers:
24
24
  * `transferDecode` / `transferEncode` are the RFC 8951
25
- * sec. 3 base64 transfer codec (RFC 4648, and DELIBERATELY blind to any
26
- * Content-Transfer-Encoding header -- errata 5904/5107); `splitMultipartMixed`
25
+ * sec. 3 base64 transfer codec (RFC 4648, and deliberately blind to any
26
+ * Content-Transfer-Encoding header, per errata 5904/5107); `splitMultipartMixed`
27
27
  * is the /serverkeygen `multipart/mixed` splitter; `parseCertsOnly` validates a
28
- * certs-only Simple PKI Response (RFC 5272 sec. 4.1) OVER `cms.parse` output;
28
+ * certs-only Simple PKI Response (RFC 5272 sec. 4.1) over `cms.parse` output;
29
29
  * `parseServerKeygenResponse` dispatches the two-part key + certificate
30
30
  * response with recipient-arm coherence; `classifyResponse` is the HTTP status
31
31
  * / content-type / Retry-After state machine (202 accepted-not-ready surfaces
@@ -35,20 +35,20 @@
35
35
  * out-of-band-key identifiers, SMIMECapabilities, and the RFC 9908
36
36
  * template-priority enroll plan.
37
37
  *
38
- * Altitude MATCHES the toolkit: structural validation, no crypto verdicts.
39
- * Certificates come back RAW and UNORDERED ("Clients MUST NOT assume the
40
- * certificates are in any order", RFC 5272 sec. 4.1) -- `findIssuedCert` picks
38
+ * Altitude matches the toolkit: structural validation, no crypto verdicts.
39
+ * Certificates come back raw and unordered ("Clients MUST NOT assume the
40
+ * certificates are in any order", RFC 5272 sec. 4.1), so `findIssuedCert` picks
41
41
  * the issued certificate by a public-key match, never a positional guess. The
42
42
  * serverkeygen encrypted-key part's EnvelopedData is surfaced structurally
43
- * (ciphertext raw, decryption external). A /fullcmc response is CLASSIFIED:
43
+ * (ciphertext raw, decryption external). A /fullcmc response is classified:
44
44
  * a 200 may carry either arm RFC 7030 sec. 4.3.2 permits (`certs-only` or
45
45
  * `CMC-response`), and a 404 or 501 is the distinct `not-implemented`
46
- * verdict -- this service absent, rather than a transport fault. Reading the
46
+ * verdict, meaning this service is absent, not that the transport faulted. Reading the
47
47
  * CMC message itself is the CMC module's job. DER-only where DER,
48
48
  * fail-closed everywhere.
49
49
  *
50
50
  * @card
51
- * EST (RFC 7030 / 8951 / 9908) client -- the cacerts / simpleenroll / simplereenroll
51
+ * EST (RFC 7030 / 8951 / 9908) client: the cacerts / simpleenroll / simplereenroll
52
52
  * verbs over the shared pki.transport, plus the codecs they compose: base64 transfer,
53
53
  * multipart splitter, certs-only + serverkeygen validators over CMS, the
54
54
  * enroll-attribute builders, and the HTTP response classifier. Fail-closed.
@@ -88,7 +88,7 @@ var OPERATIONS = ["cacerts", "simpleenroll", "simplereenroll", "fullcmc", "serve
88
88
 
89
89
  // ---- the option surface each verb accepts -----------------------------------
90
90
  //
91
- // A misspelled option reads as an omission rather than as a value: nothing is out of range and
91
+ // A misspelled option reads as an omission, never as a value: nothing is out of range and
92
92
  // nothing fails to parse, so the caller who asked for something stricter gets the looser default
93
93
  // and is told nothing. That is worst here, where the options carry the security posture of a
94
94
  // network exchange -- a misspelled `tls` leaves the anchors unset (the no-anchors refusal names
@@ -97,7 +97,7 @@ var OPERATIONS = ["cacerts", "simpleenroll", "simplereenroll", "fullcmc", "serve
97
97
  // server-generated private key, and a misspelled `oldCert` fails the re-enrollment outright.
98
98
  //
99
99
  // Every network verb shares the client surface, because every one of them goes through _client and
100
- // the redirect / authentication plumbing it drives. The per-verb tables extend it rather than
100
+ // the redirect / authentication plumbing it drives. The per-verb tables extend it instead of
101
101
  // restating it, so a key added to the client reaches every verb at once and none of them drifts.
102
102
  var CLIENT_OPTS = {
103
103
  transport: 1, tls: 1, label: 1, timeout: 1, maxResponseBytes: 1, maxRedirects: 1, now: 1,
@@ -114,7 +114,7 @@ function _withClient(extra) {
114
114
  var CACERTS_OPTS = _withClient(null);
115
115
  var SIMPLEENROLL_OPTS = _withClient({ strict: 1 });
116
116
  var SIMPLEREENROLL_OPTS = _withClient({ strict: 1, oldCert: 1 });
117
- // expectedRecipientKind is NOT here: it is derived from the CSR's own advertised attribute, never
117
+ // expectedRecipientKind is deliberately absent: it is derived from the CSR's own advertised attribute, never
118
118
  // taken from the caller, so listing it would offer a pin that nothing reads.
119
119
  var SERVERKEYGEN_OPTS = _withClient({
120
120
  requestedEncryption: 1, expectedRecipientKeyId: 1, expectedRecipientIssuerSerial: 1,
@@ -122,7 +122,7 @@ var SERVERKEYGEN_OPTS = _withClient({
122
122
  var CSRATTRS_OPTS = _withClient(null);
123
123
  var FULLCMC_OPTS = _withClient({
124
124
  transactionId: 1, senderNonce: 1, dataReturn: 1,
125
- responderCerts: 1, responseRecipient: 1, allowUnverifiedResponse: 1,
125
+ responderCerts: 1, responseRecipient: 1, allowUnverifiedResponse: 1, allowUnboundResponse: 1,
126
126
  });
127
127
  // The two verbs that take options without going near the network.
128
128
  var CLASSIFY_OPTS = { op: 1, now: 1 };
@@ -151,8 +151,8 @@ function _knownOpts(opts, known, verb) {
151
151
  *
152
152
  * Decode an EST payload body (a base64 string or Buffer) to DER. CR/LF/space/tab
153
153
  * are stripped anywhere (RFC 8951 sec. 3.1); any other non-alphabet byte fails
154
- * closed with `est/bad-base64`. A Content-Transfer-Encoding header is NEVER read
155
- * (errata 5904/5107). Bounded twice -- the raw length before decode and the
154
+ * closed with `est/bad-base64`. A Content-Transfer-Encoding header is never read
155
+ * (errata 5904/5107). Bounded twice: the raw length before decode and the
156
156
  * decoded DER against `DER_MAX_BYTES` (`est/too-large`).
157
157
  *
158
158
  * @example
@@ -276,8 +276,8 @@ function splitMultipartMixed(body, contentType) {
276
276
  * shipped `cms.parse` output: a SignedData with no eContent and EMPTY
277
277
  * signerInfos, carrying at least one plain X.509 certificate (a context-tagged
278
278
  * CertificateChoices alternative is rejected `est/bad-certificate-choice`). CRLs
279
- * MAY be present. Certificates come back RAW and in AS-RECEIVED order (never
280
- * sorted -- RFC 5272 sec. 4.1). A non-conformant response throws a typed
279
+ * MAY be present. Certificates come back raw and in as-received order (never
280
+ * sorted, per RFC 5272 sec. 4.1). A non-conformant response throws a typed
281
281
  * `EstError` (`est/not-certs-only`, `est/no-certificates`).
282
282
  *
283
283
  * @example
@@ -1135,28 +1135,39 @@ function _certsResult(op, res, opts, csrSpki) {
1135
1135
  * `application/pkcs7-mime; smime-type=CMC-request`, base64 per RFC 8951, over the shared
1136
1136
  * `pki.transport`.
1137
1137
  *
1138
- * A 200 answers with EITHER `smime-type=certs-only` (a Simple PKI Response) or
1139
- * `smime-type=CMC-response` (a Full PKI Response) -- RFC 7030 sec. 4.3.2 names both, and the label
1138
+ * A 200 answers with either `smime-type=certs-only` (a Simple PKI Response) or
1139
+ * `smime-type=CMC-response` (a Full PKI Response). RFC 7030 sec. 4.3.2 names both, and the label
1140
1140
  * must agree with the bytes. Either way the result is the `pki.cmc.verify` verdict shape, so a
1141
1141
  * caller reads one `outcome` (`issued` / `pending` / `confirm-required` / `pop-required` /
1142
- * `rejected`) regardless of which arm the server chose. Pass `transactionId` / `senderNonce` /
1143
- * `dataReturn` to have the exchange bound to the request that was sent.
1142
+ * `rejected`) regardless of which arm the server chose.
1144
1143
  *
1145
- * A 404 **or** a 501 is the distinct `est/not-implemented` verdict -- support for this verb is
1146
- * OPTIONAL on both sides (sec. 4.3). A 202 surfaces its Retry-After rather than sleeping. A
1144
+ * The exchange binding is read out of the request itself, never taken on the caller's word: whatever
1145
+ * Transaction Identifier, Sender Nonce or Data Return the submitted bytes carry is what the response
1146
+ * must echo, and `transactionId` / `senderNonce` / `dataReturn` are a cross-check that is refused if
1147
+ * it disagrees. A request that carries none of the three leaves nothing for the response to echo, so
1148
+ * the answer is refused instead of being accepted as an enrollment result that could be a replay of
1149
+ * any earlier exchange. The code is `cmc/unbound-response` on the `CMC-response` arm, which the CMC
1150
+ * layer interprets, and `est/unbound-response` on the `certs-only` arm, which this verb owns. Build
1151
+ * the request with a `senderNonce` (`pki.cmc.build`) to bind it, or pass `allowUnboundResponse: true` to
1152
+ * accept that it is unbound. The verdict reports which halves ran as `bound` and `boundToRequest`.
1153
+ *
1154
+ * A 404 **or** a 501 is the distinct `est/not-implemented` verdict, since support for this verb is
1155
+ * optional on both sides (sec. 4.3). A 202 surfaces its Retry-After and does not sleep. A
1147
1156
  * rejection carries a CMC response (sec. 4.3.2 makes it a MUST), which is decoded and attached to
1148
- * a typed `est/cmc-failed` as `err.cmc` and `err.httpStatus` -- but a body that cannot be read
1157
+ * a typed `est/cmc-failed` as `err.cmc` and `err.httpStatus`, while a body that cannot be read
1149
1158
  * never masks the HTTP fault it arrived with.
1150
1159
  *
1151
- * On the `certs-only` arm the issued certificates are identified by PUBLIC-KEY MATCH against the
1152
- * requests that were submitted -- the only identification RFC 5272 sec. 4.1 sanctions, since "the
1153
- * certificates are in any order" -- and EVERY certification request in the message must be answered
1154
- * before the exchange reads as `issued` -- a key wanted by N requests needs N certificates, so a
1155
- * bag that answers only some of them, or none, is a refusal rather than a partial success. That arm
1160
+ * On the `certs-only` arm the issued certificates are identified by public-key match against the
1161
+ * requests that were submitted, the only identification RFC 5272 sec. 4.1 sanctions, since "the
1162
+ * certificates are in any order". Every certification request in the message must be answered
1163
+ * before the exchange reads as `issued`: a key wanted by N requests needs N certificates, so a
1164
+ * bag that answers only some of them, or none, is a refusal and not a partial success. That arm
1156
1165
  * carries no controls, so it cannot echo a Transaction Identifier, Sender Nonce or Data Return: a
1157
- * request that sent those asked for replay binding it cannot provide -- the key match is not one,
1158
- * since an old response for the same key still matches -- and it is refused as
1159
- * `est/unbound-response` rather than accepted with silently none of what was asked for. They are
1166
+ * request that sent those asked for replay binding it cannot provide (the key match is not one,
1167
+ * since an old response for the same key still matches), and it is refused as
1168
+ * `est/unbound-response`, never accepted with silently none of what was asked for. A request
1169
+ * that asked for no binding reaches the same refusal on this arm, for the same reason: nothing here
1170
+ * can tie the bag to the exchange, so `allowUnboundResponse: true` is what accepts it. They are
1160
1171
  * surfaced as `issuedCertificates` (with `certificate` the first), distinct from `certificates`,
1161
1172
  * which is the whole returned bag including any chain. Where the requested keys are distinct that
1162
1173
  * list is in request order; where several requests deliberately SHARE one key it is not, and does
@@ -1170,18 +1181,23 @@ function _certsResult(op, res, opts, csrSpki) {
1170
1181
  * response is SURFACED, never acted on (RFC 5272 sec. 6.15 makes accepting one a manual decision).
1171
1182
  *
1172
1183
  * @opts
1173
- * - `transport` / `tls` / `label` / `timeout` / `maxResponseBytes` / `maxRedirects` / `now` -- as pki.est.cacerts.
1174
- * - `transactionId` / `senderNonce` / `dataReturn` -- what the request sent, for the exchange binding.
1175
- * - `responderCerts` -- EXTRA certificates for CMC signer lookup, for a response that does not carry
1184
+ * - `transport` / `tls` / `label` / `timeout` / `maxResponseBytes` / `maxRedirects` / `now`, as in pki.est.cacerts.
1185
+ * - `transactionId` / `senderNonce` / `dataReturn`: what the request sent. The values are read out
1186
+ * of the request itself; supplying them here cross-checks that, and a disagreement is refused.
1187
+ * - `responderCerts`: extra certificates for CMC signer lookup, for a response that does not carry
1176
1188
  * its own signer; the certificates the response carries are searched either way. The carrier's
1177
1189
  * signature MUST be verified (RFC 5272 sec. 3.2.1.3.4), so a `CMC-response` whose signer is found
1178
1190
  * nowhere and which does not name the opt-out below is refused.
1179
1191
  * - `responseRecipient` -- key material for a response carried in AuthenticatedData, in the shape
1180
1192
  * `pki.cms.decrypt` takes. Its MAC is then checked and the verdict reports
1181
- * `signatureVerified: true`, rather than the carrier being reachable only unauthenticated.
1193
+ * `signatureVerified: true`, so the carrier is not reachable only unauthenticated.
1182
1194
  * - `allowUnverifiedResponse` -- accept a `CMC-response` whose signer certificate cannot be found,
1183
1195
  * without checking its signature; the verdict then reports `signatureVerified: false`. For an
1184
1196
  * unauthenticated bootstrap only, and it never excuses a signature that is present and wrong.
1197
+ * - `allowUnboundResponse` -- accept an answer to a request that carried no Transaction Identifier,
1198
+ * Sender Nonce or Data Return, so nothing ties it to this exchange; the verdict then reports
1199
+ * `boundToRequest: false`. A separate question from the one above, because a replayed response
1200
+ * is authentic, so naming one does not name the other.
1185
1201
  * - `username` / `password` / `allowCrossOriginRedirect` -- as pki.est.simpleenroll.
1186
1202
  * @example
1187
1203
  * var pair = await pki.key.generate("Ed25519");
@@ -1417,6 +1433,12 @@ function _cmcSent(opts, der) {
1417
1433
  // would exist one layer down and be unreachable from the one operators call.
1418
1434
  recipient: _copyRecipient(opts.responseRecipient),
1419
1435
  allowUnverified: opts.allowUnverifiedResponse === true,
1436
+ // The binding opt-out travels the same way. Without it the capability would
1437
+ // exist one layer down and be unreachable from the verb operators call: a
1438
+ // request built with no Transaction Identifier, Sender Nonce or Data Return
1439
+ // carries nothing for the response to echo, so pki.cmc.verify would refuse
1440
+ // every answer to it and no option here could say that was intended.
1441
+ allowUnbound: opts.allowUnboundResponse === true,
1420
1442
  };
1421
1443
  }
1422
1444
 
@@ -1681,6 +1703,19 @@ function _fullcmcResult(res, opts, wanted, sent) {
1681
1703
  "the request carried " + unecho.join(" / ") + ", which a certs-only response has no controls to " +
1682
1704
  "echo, so the replay binding it asked for cannot be checked (RFC 5272 sec. 6.6 / 6.4)");
1683
1705
  }
1706
+ // Reaching here means the request asked for no binding, so nothing whatever
1707
+ // ties this bag of certificates to this exchange. The public-key correlation
1708
+ // below is explicitly not a binding, since an old response for the same key
1709
+ // matches just as well. pki.cmc.verify takes this posture on the other arm,
1710
+ // and it is taken here too: one arm quietly accepting what the other refuses
1711
+ // would make which rule applied depend on the smime-type the server chose.
1712
+ if (sent.allowUnbound !== true) {
1713
+ throw E("est/unbound-response",
1714
+ "nothing ties this certs-only response to the request just sent: a certs-only body carries no " +
1715
+ "controls at all, so build the request with a `senderNonce` (pki.cmc.build) and use a server that " +
1716
+ "answers with a CMC-response, or pass `allowUnboundResponse: true` to accept a bag of certificates " +
1717
+ "that could answer any earlier request for the same key (RFC 5272 sec. 6.6)");
1718
+ }
1684
1719
  var certs = parseCertsOnly(der); // throws est/not-certs-only on a Full PKI Response
1685
1720
  // A certs-only body says nothing about WHICH request it answers -- no status,
1686
1721
  // no body-part reference. So the issued certificate is identified the one way
@@ -1699,10 +1734,18 @@ function _fullcmcResult(res, opts, wanted, sent) {
1699
1734
  // depending on which arm the server happened to choose. RFC 7030 secures this
1700
1735
  // arm through the authenticated TLS channel instead, and the certificates stay
1701
1736
  // `trusted: false` for the caller to run through pki.path.validate.
1737
+ // `bound` and `boundToRequest` are stated here for the same reason
1738
+ // `signatureVerified` is: leaving them undefined while the CMC-response arm
1739
+ // sets them would give a caller a different kind of answer depending on which
1740
+ // arm the server chose. Every one is false and cannot be otherwise, because a
1741
+ // certs-only body has no controls to echo. That is what the refusal above
1742
+ // makes the caller acknowledge before reading this verdict at all.
1702
1743
  return { outcome: "issued", certificate: issued, issuedCertificates: issuedCerts,
1703
1744
  certificates: certs.certificates, crls: certs.crls,
1704
1745
  controls: [], statuses: [], publishTrustAnchors: null, trusted: false,
1705
- signatureVerified: false };
1746
+ signatureVerified: false,
1747
+ bound: { transactionId: false, senderNonce: false, dataReturn: false, bodyPartIDs: false },
1748
+ boundToRequest: false };
1706
1749
  }
1707
1750
  // smime-type=cmc-response: the Full PKI Response, interpreted into one verdict.
1708
1751
  // pki.cmc.verify owns the transaction binding and the status reduction; this
@@ -1804,11 +1847,11 @@ function _enroll(op, baseUrl, csrInput, opts) {
1804
1847
  * (`{ certificates, crls }`), or `{ retry: true, retryAfterSeconds }` on a 202 (surfaced,
1805
1848
  * never slept). https-only (`est/insecure-url`); an explicit `opts.tls.anchors` (or an
1806
1849
  * `opts.tls.useSystemStore` opt-in) is required (`est/no-trust-anchors`); the returned CA
1807
- * certificate is NOT auto-trusted -- the caller path-validates it and supplies the accepted
1850
+ * certificate is not auto-trusted: the caller path-validates it and supplies the accepted
1808
1851
  * anchor on the next call.
1809
1852
  *
1810
1853
  * @opts
1811
- * - `transport` -- an injected transport(request) -> {status, headers, body, tls}; default pki.transport.https.
1854
+ * - `transport`: an injected transport(request) -> {status, headers, body, tls}; default pki.transport.https.
1812
1855
  * - `tls` -- { anchors, useSystemStore, cert, key, minVersion, servername, checkServerIdentity }.
1813
1856
  * - `label` -- an OPTIONAL CA label path segment; `timeout` / `maxResponseBytes` / `maxRedirects` -- budgets.
1814
1857
  * - `now` -- receipt time (epoch ms) to render a 202 Retry-After HTTP-date as seconds.
@@ -1849,12 +1892,12 @@ function cacerts(baseUrl, opts) {
1849
1892
  * certificates (`chain`), and the raw set (`certificates`); or `{ retry: true,
1850
1893
  * retryAfterSeconds }` on a 202. No returned certificate matching the CSR key fails closed
1851
1894
  * (`est/issued-cert-not-found`); `opts.strict` requires exactly the issued certificate. A
1852
- * 401 is answered once with HTTP Basic ONLY when `opts.username`/`password` are supplied and
1895
+ * 401 is answered once with HTTP Basic only when `opts.username`/`password` are supplied and
1853
1896
  * the transport already authenticated the server.
1854
1897
  *
1855
1898
  * @opts
1856
- * - `transport` / `tls` / `label` / `timeout` / `maxResponseBytes` / `maxRedirects` / `now` -- as pki.est.cacerts.
1857
- * - `strict` -- reject an enroll response that carries more than the single issued certificate.
1899
+ * - `transport` / `tls` / `label` / `timeout` / `maxResponseBytes` / `maxRedirects` / `now`, as in pki.est.cacerts.
1900
+ * - `strict`: reject an enroll response that carries more than the single issued certificate.
1858
1901
  * - `username` / `password` -- HTTP Basic credentials, answered only after server authorization (empty username allowed).
1859
1902
  * - `allowCrossOriginRedirect` -- opt in to following a cross-origin redirect on this POST.
1860
1903
  * @example
@@ -1884,7 +1927,7 @@ function simpleenroll(baseUrl, csrInput, opts) {
1884
1927
  * `/.well-known/est/simplereenroll` and REQUIRES `opts.oldCert` (the certificate being
1885
1928
  * renewed). Before anything crosses the wire, `reenrollGuard` enforces that the CSR's
1886
1929
  * Subject and SubjectAltName (names and criticality) are byte-identical to `opts.oldCert`
1887
- * (RFC 7030 sec. 4.2.2) -- a mismatch fails closed (`est/reenroll-subject-mismatch` /
1930
+ * (RFC 7030 sec. 4.2.2). A mismatch fails closed (`est/reenroll-subject-mismatch` /
1888
1931
  * `est/reenroll-san-mismatch`) and the transport is never called. A missing `opts.oldCert`
1889
1932
  * is `est/bad-input`.
1890
1933
  *
@@ -2039,14 +2082,14 @@ async function _serverkeygenResult(res, opts, derived) {
2039
2082
  * application/pkcs10`, identical request encoding to `simpleenroll`) to
2040
2083
  * `<baseUrl>/.well-known/est/serverkeygen`. The two-part `multipart/mixed` response is surfaced as
2041
2084
  * `{ certificates, privateKey }` (a cleartext PKCS#8 `PrivateKeyInfo`) or `{ certificates,
2042
- * encryptedKey }` (the CMS `EnvelopedData` the caller decrypts out-of-band with its key-encryption key --
2043
- * the verb NEVER decrypts, so it is not a decryption oracle), or `{ retry, retryAfterSeconds }` on a 202.
2044
- * The certificates are RAW/unordered -- unlike `simpleenroll` no leaf is picked, because the CA generated
2045
- * the key so the issued certificate's public key is the generated one, not the throwaway CSR key. A CLEARTEXT
2085
+ * encryptedKey }` (the CMS `EnvelopedData` the caller decrypts out-of-band with its key-encryption key;
2086
+ * the verb never decrypts, so it is not a decryption oracle), or `{ retry, retryAfterSeconds }` on a 202.
2087
+ * The certificates are raw and unordered: unlike `simpleenroll` no leaf is picked, because the CA generated
2088
+ * the key so the issued certificate's public key is the generated one, not the throwaway CSR key. A cleartext
2046
2089
  * key is bound to its certificate before it resolves: the delivered private key's public half MUST match
2047
- * EXACTLY ONE returned certificate (`est/key-cert-mismatch` on none, `est/ambiguous-issued-cert` on more than
2048
- * one), so a mis-associated key is refused rather than handed back unusable.
2049
- * The encryption requirement + expected recipient are DERIVED from the CSR's own DecryptKeyIdentifier /
2090
+ * exactly one returned certificate (`est/key-cert-mismatch` on none, `est/ambiguous-issued-cert` on more than
2091
+ * one), so a mis-associated key is refused, never handed back unusable.
2092
+ * The encryption requirement + expected recipient are derived from the CSR's own DecryptKeyIdentifier /
2050
2093
  * AsymmetricDecryptKeyIdentifier attribute; an `opts` value that contradicts the CSR is `est/bad-input`
2051
2094
  * (a cleartext-key downgrade cannot slip past). The delivered key's channel is asserted confidentiality-
2052
2095
  * bearing (a NULL / anonymous / EXPORT cipher is `est/weak-cipher`). https-only, explicit-anchor, and the
@@ -2116,10 +2159,10 @@ function _csrattrsResult(res, opts) {
2116
2159
  *
2117
2160
  * Fetch the CA's CSR-attributes policy: GET `<baseUrl>/.well-known/est/csrattrs` (`Accept:
2118
2161
  * application/csrattrs`). A 200 body is base64-decoded, parsed as an RFC 9908 `CsrAttrs`, and returned
2119
- * with a `plan` (`buildEnrollAttributes`) the caller applies to its NEXT CSR -- the verb NEVER auto-applies
2162
+ * with a `plan` (`buildEnrollAttributes`) the caller applies to its next CSR; the verb never auto-applies
2120
2163
  * attributes to a CSR (single responsibility). A 204 or 404 is `{ available: false }` (a valid "no specific
2121
- * attributes"), NOT an error; an empty SEQUENCE (`30 00`) is a COMPLETE empty policy (`attrs.items` empty),
2122
- * distinct from an empty HTTP body (`est/empty-body`). Server auth is NOT required for this policy GET but a
2164
+ * attributes") and not an error; an empty SEQUENCE (`30 00`) is a complete empty policy (`attrs.items` empty),
2165
+ * distinct from an empty HTTP body (`est/empty-body`). Server auth is not required for this policy GET but a
2123
2166
  * 401 is tolerated (the shared auth path stays live). https-only + explicit-anchor as elsewhere.
2124
2167
  *
2125
2168
  * @opts
@@ -16,10 +16,10 @@
16
16
  * `{ name, code, message, permanent, isPkiError: true }`.
17
17
  *
18
18
  * `code` is a stable, greppable `domain/reason` string
19
- * (`asn1/indefinite-length`, `x509/not-a-certificate`) -- safe to switch
19
+ * (`asn1/indefinite-length`, `x509/not-a-certificate`): safe to switch
20
20
  * on and safe to log. Because every failure here is a deterministic
21
21
  * verdict on the bytes in hand (a malformed length, an unknown OID
22
- * shape, a truncated certificate), errors are `permanent: true` -- the
22
+ * shape, a truncated certificate), errors are `permanent: true`. The
23
23
  * same input will never parse on retry.
24
24
  *
25
25
  * @card
@@ -41,7 +41,7 @@ var CODE_SHAPE = /^[a-z0-9-]+\/[a-z0-9-]+$/;
41
41
  * Base class every toolkit error extends. Provides the unified
42
42
  * `instanceof` check plus the `{ name, code, isPkiError }` shape.
43
43
  * A supplied `code` must be a `domain/reason` string (lowercase
44
- * alphanumerics and dashes) -- the construction throws a `TypeError`
44
+ * alphanumerics and dashes); the construction throws a `TypeError`
45
45
  * otherwise, which catches an argument-order swap with the
46
46
  * `defineClass` subclasses' `(code, message)` convention at the call
47
47
  * site instead of shipping prose into a code-switching consumer.
@@ -83,10 +83,10 @@ class PkiError extends Error {
83
83
  * a `.factory` static for the common `var _err = XxxError.factory` shape.
84
84
  * The `code` must be a `domain/reason` string (the base-class contract);
85
85
  * without `withCause`, a third constructor argument throws a `TypeError`
86
- * rather than silently discarding a cause the caller meant to thread.
86
+ * instead of silently discarding a cause the caller meant to thread.
87
87
  *
88
88
  * @opts
89
- * withCause: boolean, // default: false -- constructor becomes (code, message, cause)
89
+ * withCause: boolean, // default false; constructor becomes (code, message, cause)
90
90
  *
91
91
  * @example
92
92
  * // throws: my/bad-input -- raising the new error type IS what this shows
package/lib/guard-all.js CHANGED
@@ -8,11 +8,11 @@
8
8
  // guard-all -- the guard-family orchestrator (schema-all's role for the guard
9
9
  // family). It assembles the per-shape fail-closed guards into one namespaced
10
10
  // surface every input boundary composes, so a boundary depends on the family
11
- // rather than re-implementing a guard inline:
11
+ // itself, with no guard re-implemented inline:
12
12
  //
13
13
  // guard.bytes.view / .source -- untrusted byte-source -> Buffer re-view
14
14
  // (detached-buffer fail-open defence)
15
- // guard.text.decode -- byte-source -> string, cap BEFORE copy
15
+ // guard.text.decode -- byte-source -> string, cap before copy
16
16
  // (parser-DoS string-allocation defence)
17
17
  // guard.limits.cap / .depthCap -- config-time resource-cap validation
18
18
  // (recursion / allocation DoS defence)
@@ -47,7 +47,7 @@
47
47
  //
48
48
  // Each shape is enforced by a codebase-patterns detector: the characteristic
49
49
  // token of a guard (the Buffer.from(x.buffer, byteOffset) re-view, the
50
- // timingSafeEqual call, the MAX_DECODE_DEPTH_CEILING check) must appear ONLY in
50
+ // timingSafeEqual call, the MAX_DECODE_DEPTH_CEILING check) must appear only in
51
51
  // its guard module, so a new boundary cannot re-inline the shape and forget the
52
52
  // defence.
53
53
 
@@ -12,14 +12,14 @@
12
12
  //
13
13
  // pki.acme.newOrder(opts).catch(handleIt);
14
14
  //
15
- // A validation that runs BEFORE the promise is created throws straight past that `.catch`, so a
15
+ // A validation that runs before the promise is created throws straight past that `.catch`, so a
16
16
  // misspelled option or a malformed input becomes an uncaught exception in code that already handles
17
17
  // errors -- and nothing in the shape of the call tells the caller which verbs do that. Eleven verbs
18
18
  // across five modules had it (pki.cms.verify / sign / countersign, pki.ocsp.sign, pki.tsp.sign and
19
19
  // six pki.acme verbs), each having grown the same way: a cheap synchronous check added at the top of
20
20
  // a function that returns a promise further down.
21
21
  //
22
- // What this does NOT change is WHEN the work happens. The body still runs synchronously, because
22
+ // What this does not change is when the work happens. The body still runs synchronously, because
23
23
  // several of these verbs must resolve a caller's mutable options object before any turn passes --
24
24
  // reading a key, a nonce, or a request's bytes a turn later is a different value than the one that
25
25
  // was checked. Only the exit changes: a fault leaves as a rejection instead of a throw.
@@ -27,8 +27,8 @@
27
27
  // @enforced-by behavioral -- the rule has no rename-proof code shape (it is the ABSENCE of a wrapper
28
28
  // around a synchronous prefix, which no lexical pattern can see). The guard is the derived test
29
29
  // test/layer-0-primitives/promise-contract.test.js, which reads every `-> Promise<` @signature out
30
- // of lib/ and calls each verb to prove the refusal arrives as a rejection -- so a new verb is in
31
- // scope the day it is documented, and no list here can go stale.
30
+ // of lib/ and calls each verb to prove the refusal arrives as a rejection. A new verb is in
31
+ // scope the day it is documented, so no list here can go stale.
32
32
  function deferred(body) {
33
33
  try { return Promise.resolve(body()); }
34
34
  catch (e) { return Promise.reject(e); }