@blamejs/pki 0.6.14 → 0.6.16
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 +27 -1
- package/lib/acme.js +59 -815
- package/lib/asn1-der.js +7 -245
- package/lib/attrcert-sign.js +12 -260
- package/lib/attrcert-verify.js +1 -7
- package/lib/byte-reader.js +0 -8
- package/lib/byte-writer.js +0 -11
- package/lib/cbor-det.js +0 -54
- package/lib/cmc-build.js +15 -357
- package/lib/cmc-verify.js +6 -239
- package/lib/cmp-build.js +41 -317
- package/lib/cmp-session.js +73 -760
- package/lib/cmp-verify.js +32 -488
- package/lib/cms-compress.js +3 -32
- package/lib/cms-decrypt.js +29 -294
- package/lib/cms-encrypt.js +14 -234
- package/lib/cms-sign.js +29 -324
- package/lib/cms-verify.js +9 -500
- package/lib/composite-kem.js +2 -102
- package/lib/composite-sig.js +1 -77
- package/lib/constants.js +0 -249
- package/lib/crl-sign.js +9 -237
- package/lib/crl-verify.js +1 -10
- package/lib/crmf-sign.js +19 -198
- package/lib/crmf-verify.js +1 -12
- package/lib/csr-sign.js +3 -34
- package/lib/csr-verify.js +1 -12
- package/lib/ct.js +28 -253
- package/lib/edwards-point.js +10 -44
- package/lib/est.js +28 -764
- package/lib/framework-error.js +4 -182
- package/lib/guard-all.js +1 -58
- package/lib/guard-async.js +1 -36
- package/lib/guard-bytes.js +6 -650
- package/lib/guard-compress.js +5 -102
- package/lib/guard-crypto.js +1 -40
- package/lib/guard-der.js +2 -93
- package/lib/guard-encoding.js +2 -60
- package/lib/guard-header.js +1 -36
- package/lib/guard-identifier.js +7 -531
- package/lib/guard-intrinsic.js +1 -150
- package/lib/guard-json.js +10 -73
- package/lib/guard-limits.js +1 -77
- package/lib/guard-list.js +1 -49
- package/lib/guard-name.js +3 -209
- package/lib/guard-parsed.js +7 -335
- package/lib/guard-range.js +1 -71
- package/lib/guard-secret.js +1 -102
- package/lib/guard-text.js +1 -64
- package/lib/guard-time.js +1 -97
- package/lib/hpke.js +3 -105
- package/lib/http-digest.js +14 -142
- package/lib/http-retry-after.js +1 -47
- package/lib/http-transport.js +21 -131
- package/lib/inspect.js +30 -284
- package/lib/ip-utils.js +6 -47
- package/lib/jose.js +7 -142
- package/lib/key.js +2 -67
- package/lib/lint.js +9 -194
- package/lib/merkle.js +1 -27
- package/lib/mime.js +9 -82
- package/lib/ocsp-request-verify.js +1 -14
- package/lib/ocsp-verify.js +1 -82
- package/lib/ocsp.js +11 -169
- package/lib/oid.js +5 -337
- package/lib/path-validate.js +103 -1492
- package/lib/pbes2.js +2 -89
- package/lib/pkcs12-build.js +31 -379
- package/lib/pki-build.js +64 -290
- package/lib/rc2.js +2 -18
- package/lib/rfc3339.js +4 -27
- package/lib/scep.js +140 -286
- package/lib/schema-all.js +0 -122
- package/lib/schema-attrcert.js +4 -146
- package/lib/schema-c509.js +153 -802
- package/lib/schema-cmc.js +5 -220
- package/lib/schema-cmp.js +2 -223
- package/lib/schema-cms.js +13 -427
- package/lib/schema-crl.js +5 -68
- package/lib/schema-crmf.js +6 -167
- package/lib/schema-csr.js +1 -54
- package/lib/schema-csrattrs.js +2 -87
- package/lib/schema-engine.js +0 -152
- package/lib/schema-ocsp.js +0 -117
- package/lib/schema-pkcs12.js +2 -93
- package/lib/schema-pkcs8.js +3 -35
- package/lib/schema-pkix.js +24 -655
- package/lib/schema-smime.js +0 -54
- package/lib/schema-tsp.js +3 -99
- package/lib/schema-x509.js +4 -63
- package/lib/shbs.js +11 -95
- package/lib/sign-scheme.js +2 -97
- package/lib/sigstore.js +9 -169
- package/lib/sleep.js +2 -8
- package/lib/smime.js +15 -408
- package/lib/tls-cert-compress.js +0 -62
- package/lib/trust.js +19 -185
- package/lib/tsp-sign.js +16 -270
- package/lib/validator-all.js +1 -30
- package/lib/validator-attcert.js +2 -46
- package/lib/validator-cose.js +2 -153
- package/lib/validator-keydesc.js +1 -37
- package/lib/validator-sig.js +1 -46
- package/lib/validator-tls.js +1 -88
- package/lib/validator-tpm.js +19 -122
- package/lib/verify-seam.js +1 -24
- package/lib/webauthn-mds.js +3 -400
- package/lib/webauthn.js +12 -833
- package/lib/webcrypto.js +5 -485
- package/lib/x509-sign.js +4 -108
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
package/lib/constants.js
CHANGED
|
@@ -32,8 +32,6 @@ var frameworkError = require("./framework-error");
|
|
|
32
32
|
|
|
33
33
|
var ConstantsError = frameworkError.ConstantsError;
|
|
34
34
|
|
|
35
|
-
// _positive(n, who) is the shared guard every scale helper runs. Config-
|
|
36
|
-
// time tier: a bad scale argument is an authoring bug, so it throws.
|
|
37
35
|
function _positive(n, who) {
|
|
38
36
|
if (typeof n !== "number" || !isFinite(n) || n < 0) {
|
|
39
37
|
throw new ConstantsError(
|
|
@@ -44,11 +42,6 @@ function _positive(n, who) {
|
|
|
44
42
|
return n;
|
|
45
43
|
}
|
|
46
44
|
|
|
47
|
-
// _scale(n, who, factor) validates the argument and the product. A finite
|
|
48
|
-
// operand can still overflow the multiplication (days(1e304) -> Infinity),
|
|
49
|
-
// and an Infinity handed onward silently disables any bound compared
|
|
50
|
-
// against it (`len > Infinity` is always false), so a product outside the
|
|
51
|
-
// safe-integer range throws instead of returning.
|
|
52
45
|
function _scale(n, who, factor) {
|
|
53
46
|
var out = Math.round(_positive(n, who) * factor);
|
|
54
47
|
if (!Number.isSafeInteger(out)) {
|
|
@@ -115,265 +108,61 @@ var BYTES = {
|
|
|
115
108
|
gib: function (n) { return _scale(n, "C.BYTES.gib", BYTES_PER_KIB * BYTES_PER_KIB * BYTES_PER_KIB); },
|
|
116
109
|
};
|
|
117
110
|
|
|
118
|
-
// LIMITS -- shared codec ceilings. A DER document larger than this, or
|
|
119
|
-
// nested deeper than this, is refused before the parser walks it: an
|
|
120
|
-
// unbounded length prefix or a pathologically-nested SEQUENCE is a
|
|
121
|
-
// classic decoder-DoS, so the bound is a fail-closed default rather
|
|
122
|
-
// than a tunable an operator must remember to set.
|
|
123
|
-
//
|
|
124
|
-
// DER_MAX_INTEGER_BYTES and OID_MAX_SUBIDENTIFIER_BYTES are per-value
|
|
125
|
-
// ceilings the whole-document cap can't provide: a single INTEGER or OID
|
|
126
|
-
// sub-identifier under the 16 MiB limit can still carry hundreds of KiB,
|
|
127
|
-
// so a value reader that scales super-linearly in its content length is a
|
|
128
|
-
// decoder-DoS the document cap does not stop. 16 KiB covers any real key
|
|
129
|
-
// material (an RSA-131072 modulus), and 32 bytes covers any real OID arc:
|
|
130
|
-
// the largest standard sub-identifier is a 128-bit UUID-based arc (X.667,
|
|
131
|
-
// e.g. 2.25.<uuid>), which is 19 base-128 bytes -- so the cap must exceed
|
|
132
|
-
// that, not sit at 16. Anything larger than 32 bytes is refused as hostile.
|
|
133
111
|
var LIMITS = {
|
|
134
112
|
DER_MAX_BYTES: BYTES.mib(16),
|
|
135
113
|
DER_MAX_DEPTH: 64,
|
|
136
|
-
// Total decoded-node ceiling: the DER decoder builds an eager node tree, so a
|
|
137
|
-
// dense run of tiny TLVs (a 2-byte NULL is a node) fans a small input into a
|
|
138
|
-
// huge tree -- ~350 B/node, so a 16 MiB input of NULLs is ~8M nodes ~= 2.8 GiB.
|
|
139
|
-
// 4M sits well above the largest realistic structure (a full 16 MiB CRL carries
|
|
140
|
-
// ~500k revoked entries ~= 2.5M nodes) and below the dense-bomb count; the
|
|
141
|
-
// operator may override via opts.maxItems. (The CBOR sibling caps at 1M, too
|
|
142
|
-
// low for DER's legitimate large CRLs.)
|
|
143
114
|
DER_MAX_ITEMS: 4000000,
|
|
144
|
-
// Hard stack-safe ceiling on the recursion depth of the DER / CBOR
|
|
145
|
-
// decoders, independent of the (operator-tunable) maxDepth. Both decoders
|
|
146
|
-
// are recursive descent; a maxDepth raised above the engine's native call-
|
|
147
|
-
// stack limit would let deeply nested input overflow the C stack with a raw
|
|
148
|
-
// RangeError instead of the typed too-deep verdict, defeating the fail-closed
|
|
149
|
-
// contract. A maxDepth above this ceiling is refused at config time. 256 is
|
|
150
|
-
// four times the default cap and far deeper than any real PKI / CBOR nesting
|
|
151
|
-
// (a certificate is ~6 levels; the deepest bounded re-decode is 16), while
|
|
152
|
-
// staying well below the overflow threshold on any supported platform.
|
|
153
115
|
MAX_DECODE_DEPTH_CEILING: 256,
|
|
154
116
|
PEM_MAX_BYTES: BYTES.mib(16),
|
|
155
117
|
DER_MAX_INTEGER_BYTES: BYTES.kib(16),
|
|
156
118
|
OID_MAX_SUBIDENTIFIER_BYTES: 32,
|
|
157
|
-
// Network transport response ceiling (pki.transport / the EST client). A remote
|
|
158
|
-
// server's HTTP response body is bounded WHILE it streams -- the accumulator
|
|
159
|
-
// aborts the socket the instant the running total crosses this cap, before the
|
|
160
|
-
// body reaches a decoder, so a malicious length field cannot drive unbounded
|
|
161
|
-
// allocation (RFC 7030 sec. 6). Sized above a base64-inflated DER_MAX_BYTES
|
|
162
|
-
// document plus multipart/header overhead (16 MiB * 4/3 ~= 21.3 MiB); 24 MiB
|
|
163
|
-
// clears it. An operator may only tighten it DOWNWARD via opts.maxResponseBytes.
|
|
164
119
|
HTTP_MAX_RESPONSE_BYTES: BYTES.mib(24),
|
|
165
|
-
// A single untrusted WWW-Authenticate challenge header, bounded BEFORE the string
|
|
166
|
-
// is copied/tokenized so a hostile server cannot drive unbounded work parsing it
|
|
167
|
-
// (CWE-770). 8 KiB clears any realistic multi-scheme Digest challenge.
|
|
168
120
|
HTTP_AUTH_HEADER_MAX_BYTES: BYTES.kib(8),
|
|
169
|
-
// Deterministic-CBOR codec ceilings (RFC 8949), the DER neighbors' siblings:
|
|
170
|
-
// a whole-document cap refused before the walk, a nesting cap, and a per-value
|
|
171
|
-
// bignum ceiling the document cap can't provide. Unlike DER_MAX_INTEGER_BYTES,
|
|
172
|
-
// the bignum cap carries NO +1 sign octet -- a CBOR tag-2/3 bignum body is pure
|
|
173
|
-
// unsigned big-endian magnitude (RFC 8949 sec. 3.4.3), so 16 KiB is the exact
|
|
174
|
-
// byte ceiling (covers an RSA-131072 modulus).
|
|
175
121
|
CBOR_MAX_BYTES: BYTES.mib(16),
|
|
176
122
|
CBOR_MAX_DEPTH: 64,
|
|
177
123
|
CBOR_MAX_BIGUINT_BYTES: BYTES.kib(16),
|
|
178
|
-
// Total decoded-item ceiling. A definite-length array or map can declare a
|
|
179
|
-
// huge element count that stays under the byte cap yet allocates one node per
|
|
180
|
-
// element -- e.g. a 16 MiB input of `9a00fffffb` followed by ~16 million
|
|
181
|
-
// one-byte items would build ~16 million nodes and exhaust memory before a
|
|
182
|
-
// typed verdict. The decoder counts every item it builds and refuses past this
|
|
183
|
-
// cap, so a high-fanout bomb fails closed with cbor/too-many-items instead of
|
|
184
|
-
// OOM-ing. 1,000,000 is far above any real CBOR-encoded PKI structure (a C509
|
|
185
|
-
// certificate or COSE message is hundreds of items) while bounding the tree.
|
|
186
124
|
CBOR_MAX_ITEMS: 1000000,
|
|
187
|
-
// Certificate Transparency SCT-list bounds (RFC 6962 sec. 3.3). The outer sct_list
|
|
188
|
-
// vector carries a 2-byte length prefix, so a well-formed list body is at most
|
|
189
|
-
// 2^16-1 = 65535 bytes and the full TLS blob (prefix + body) is at most 65537.
|
|
190
|
-
// The byte cap sits at that structural maximum, so the largest conforming list
|
|
191
|
-
// is accepted while an oversized inner OCTET STRING (up to the DER document cap)
|
|
192
|
-
// is refused BEFORE the list is walked. The per-list count cap is asserted per
|
|
193
|
-
// element DURING the walk (an element count is unknowable before walking
|
|
194
|
-
// variable-length elements), bounding total work at SCT_MAX_COUNT+1 elements
|
|
195
|
-
// regardless of a hostile length prefix (the CVE-2022-0778 class: crafted bytes
|
|
196
|
-
// inside a certificate extension pinning a validator). A real chain carries
|
|
197
|
-
// 2-5 SCTs; 256 is far above policy.
|
|
198
125
|
SCT_MAX_BYTES: BYTES.kib(64) + 1,
|
|
199
126
|
SCT_MAX_COUNT: 256,
|
|
200
|
-
// Merkle-proof node-count ceiling (RFC 6962 / RFC 9162). A DoS backstop that
|
|
201
|
-
// rejects a pathologically long proof array BEFORE the O(log n) fold does any
|
|
202
|
-
// digest work. 65 is the exact structural maximum: a tree size is a uint64, so
|
|
203
|
-
// an audit (inclusion) path is at most ceil(log2(2^64)) = 64 nodes, but a
|
|
204
|
-
// consistency proof is at most ceil(log2(newSize)) + 1 = 65 nodes (the extra
|
|
205
|
-
// node is the SUBPROOF terminal for a non-power-of-two old size near 2^64). Real
|
|
206
|
-
// CT logs are 2^30-2^40 (30-40-node proofs), so 65 is generous headroom while
|
|
207
|
-
// still bounding hostile work. The PRECISE per-proof guard is the geometry
|
|
208
|
-
// check in each verify (the node count must equal what the coordinates require);
|
|
209
|
-
// this is the coarse cap. A node count, not a byte size.
|
|
210
127
|
MERKLE_MAX_PROOF_NODES: 65,
|
|
211
|
-
// Certification-path length ceiling: bounds the per-cert asymmetric verify
|
|
212
|
-
// work on an untrusted certificate bundle (a real chain is well under this;
|
|
213
|
-
// the operator may override via opts.maxPathCerts).
|
|
214
128
|
PATH_MAX_CERTS: 100,
|
|
215
|
-
// Valid-policy-tree node ceiling: bounds the RFC 5280 6.1.3(d) tree a
|
|
216
|
-
// policy-rich hostile chain can grow (the CVE-2023-0464 class). A real
|
|
217
|
-
// chain's tree holds a handful of nodes; the operator may override via
|
|
218
|
-
// opts.maxPolicyNodes.
|
|
219
129
|
PATH_MAX_POLICY_NODES: 4096,
|
|
220
|
-
// Certification-path BUILDING bounds (pki.path.build). The pool of candidate
|
|
221
|
-
// issuers is untrusted, so a cross-certificate cycle or Bridge-CA fan-out can
|
|
222
|
-
// grow the number and length of candidate paths without bound (RFC 4158 sec.
|
|
223
|
-
// 8.1). PATH_BUILD_MAX_DEPTH caps the chain length explored from the leaf --
|
|
224
|
-
// well under PATH_MAX_CERTS so a built path clears the validator's own bound
|
|
225
|
-
// on hand-off; a real hierarchy is a handful of hops. PATH_BUILD_MAX_CANDIDATES
|
|
226
|
-
// is the total-work ceiling: the builder ticks it once per candidate-issuer
|
|
227
|
-
// expansion, so a hostile mesh terminates deterministically. Both are operator
|
|
228
|
-
// overridable (opts.maxDepth / opts.maxCandidatesConsidered).
|
|
229
130
|
PATH_BUILD_MAX_DEPTH: 20,
|
|
230
131
|
PATH_BUILD_MAX_CANDIDATES: 1000,
|
|
231
|
-
// AIA caIssuers network-fetch bounds (pki.path.build with opts.fetchAia). Fetching an issuer over the
|
|
232
|
-
// network from an untrusted certificate's authorityInfoAccess opens an SSRF / amplification surface (a
|
|
233
|
-
// hostile mesh where each fetched cert advertises a fresh caIssuers URL). PATH_AIA_MAX_FETCHES is the
|
|
234
|
-
// TOTAL network GET budget across a whole build() call (a breach throws path/aia-fetch-limit);
|
|
235
|
-
// PATH_AIA_MAX_PER_CERT caps how many caIssuers URIs are tried for a single certificate (an AIA MAY carry
|
|
236
|
-
// many). Both are small by default and operator-overridable (opts.maxAiaFetches / opts.maxAiaPerCert).
|
|
237
132
|
PATH_AIA_MAX_FETCHES: 10,
|
|
238
133
|
PATH_AIA_MAX_PER_CERT: 3,
|
|
239
|
-
// A caIssuers response is one certificate or a short chain -- never a 24 MiB bundle. Bounding the AIA
|
|
240
|
-
// fetch below the general HTTP ceiling (and capping the certificate COUNT a single response contributes)
|
|
241
|
-
// stops a hostile-but-TLS-trusted AIA endpoint from forcing tens of thousands of certificate parses per
|
|
242
|
-
// fetch (parse work bounded by COUNT, not only by bytes). Both operator-overridable (opts.maxResponseBytes
|
|
243
|
-
// tightens downward only; the count cap is a fixed defense).
|
|
244
134
|
PATH_AIA_MAX_RESPONSE_BYTES: BYTES.mib(1),
|
|
245
135
|
PATH_AIA_MAX_CERTS_PER_RESPONSE: 16,
|
|
246
|
-
// PKCS#12 container ceilings. A PFX carries lists at three altitudes
|
|
247
|
-
// (ContentInfos per AuthenticatedSafe, SafeBags per SafeContents,
|
|
248
|
-
// attributes per bag) and can chain fresh DER blobs inside OCTET STRINGs,
|
|
249
|
-
// where every re-decode would otherwise restart the depth cap from zero.
|
|
250
|
-
// A real keystore holds a handful of keys and certificates; thousands of
|
|
251
|
-
// elements or dozens of chained re-decodes is hostile input, not a store.
|
|
252
136
|
PKCS12_MAX_ELEMENTS: 1024,
|
|
253
137
|
PKCS12_MAX_REDECODES: 64,
|
|
254
138
|
PKCS12_MAX_BAG_DEPTH: 16,
|
|
255
|
-
// BER constructed-string reassembly copies each nesting level's payload, so
|
|
256
|
-
// nesting multiplies transient memory. Real producers segment one level
|
|
257
|
-
// deep; nesting past this cap is amplification, not a store.
|
|
258
139
|
BER_MAX_STRING_NESTING: 8,
|
|
259
|
-
// A single attribute's value SET -- no deployed attribute carries more than
|
|
260
|
-
// a handful of values; a list at this scale is amplification.
|
|
261
140
|
ATTRIBUTE_MAX_VALUES: 256,
|
|
262
|
-
// JSON message bounds for the JOSE / ACME layer (RFC 8555). Directories and
|
|
263
|
-
// resource objects are small (certificates travel as PEM, not JSON); 1 MiB is
|
|
264
|
-
// generous headroom. Depth 32 clears the deepest real nesting (a problem
|
|
265
|
-
// document's subproblems nest one level) with margin below any stack risk;
|
|
266
|
-
// enforced BEFORE parsing so a hostile document is refused up front.
|
|
267
141
|
JSON_MAX_BYTES: BYTES.mib(1),
|
|
268
142
|
JSON_MAX_DEPTH: 32,
|
|
269
|
-
// The CT log-list JSON ceiling -- the full "all logs" variant (with historical logs) exceeds the
|
|
270
|
-
// 1 MiB JSON_MAX_BYTES used for small ACME resource objects; 4 MiB gives headroom while staying bounded.
|
|
271
143
|
CT_LOG_LIST_MAX_BYTES: BYTES.mib(4),
|
|
272
|
-
// PBKDF2 iteration ceiling on the DECRYPT side (RFC 8018 pwri / PBES2). An attacker-supplied
|
|
273
|
-
// iterationCount is attacker-controlled work; a message above this is refused before any
|
|
274
|
-
// derivation (typed cms/iteration-limit), and a caller may cap it lower via opts.maxIterations.
|
|
275
|
-
// 10M clears the authoring default (600k) with generous headroom for high-security policies.
|
|
276
144
|
PBKDF2_MAX_ITERATIONS: 10000000,
|
|
277
145
|
PBKDF2_MAX_SALT: 1024,
|
|
278
|
-
// A MIME entity / S/MIME message size ceiling -- bounds the header + body decode before a copy.
|
|
279
146
|
MIME_MAX_BYTES: BYTES.mib(16),
|
|
280
|
-
// RFC 5322 sec. 2.1.1: a header line MUST be <= 998 octets excluding the CRLF. A composer that emits a
|
|
281
|
-
// longer unfolded field line risks a relay re-folding or rejecting the message -- for multipart/signed
|
|
282
|
-
// that re-fold changes the signed bytes and breaks verification -- so an emitted field line is capped here.
|
|
283
147
|
HEADER_LINE_MAX_OCTETS: 998,
|
|
284
|
-
// The decompressed-output ceiling for CMS CompressedData (RFC 3274) -- bounds the inflate BEFORE the
|
|
285
|
-
// output is materialized (a decompression-bomb / resource-exhaustion defense, CWE-409); a caller may
|
|
286
|
-
// tighten it DOWNWARD via opts.maxOutputBytes, never loosen it.
|
|
287
148
|
COMPRESS_MAX_BYTES: BYTES.mib(16),
|
|
288
|
-
// The largest TLS handshake message body. RFC 8446 sec. 4 frames every Handshake with a uint24
|
|
289
|
-
// length, so a Certificate message cannot exceed 2^24-1 bytes -- the ceiling RFC 8879 sec. 5
|
|
290
|
-
// requires a CompressedCertificate to respect ("they MUST apply the same limit as if no
|
|
291
|
-
// compression were used"). That section spells the number 16777216, which is one MORE than any
|
|
292
|
-
// uint24 can express; the field width governs, so this is deliberately not mib(16).
|
|
293
149
|
TLS_CERT_MSG_MAX_BYTES: BYTES.mib(16) - 1,
|
|
294
|
-
// The most CertificateEntry elements a TLS Certificate message may carry. The byte ceiling
|
|
295
|
-
// alone does not bound this: the smallest legal entry is 6 bytes (a uint24 length, one payload
|
|
296
|
-
// octet, an empty uint16 extensions vector), so a message inside the framing limit can declare
|
|
297
|
-
// millions of them and each costs far more heap than wire -- an allocation DoS (CWE-770) that
|
|
298
|
-
// terminates but exhausts memory. This matches PATH_MAX_CERTS: a chain longer than the path
|
|
299
|
-
// validator will ever accept has nothing to offer, so refusing it at the decoder is free.
|
|
300
150
|
TLS_CERT_MAX_ENTRIES: 100,
|
|
301
|
-
// A FIDO Metadata Service BLOB is a JWS whose payload carries every registered authenticator's
|
|
302
|
-
// metadata; the live one runs about 10 MB across ~500 entries. The byte cap bounds the decode
|
|
303
|
-
// before the payload is materialized, and the entry and anchor caps bound the per-entry work
|
|
304
|
-
// (each anchor is a DER certificate parse), since a byte ceiling alone does not bound how many
|
|
305
|
-
// items are declared inside it (CWE-770).
|
|
306
151
|
MDS_BLOB_MAX_BYTES: BYTES.mib(32),
|
|
307
|
-
// The BLOB's JWS protected header is read BEFORE the signature is checked, so it carries its own,
|
|
308
|
-
// far smaller ceiling: a header is a few hundred bytes plus the x5c chain, and the envelope cap
|
|
309
|
-
// would otherwise let unauthenticated input buy heap ahead of every authentication step.
|
|
310
152
|
MDS_BLOB_HEADER_MAX_BYTES: BYTES.kib(256),
|
|
311
|
-
// The JWS signature, likewise read before anything is authenticated. Every algorithm this reader
|
|
312
|
-
// supports has a tightly bounded signature: 64/96/132 bytes for ECDSA P-256/384/521, 64 and 114
|
|
313
|
-
// for Ed25519 and Ed448, the modulus size for RSA, and 2420 / 3309 / 4627 for ML-DSA-44/65/87
|
|
314
|
-
// (FIPS 204). The bound has to clear the LARGEST of those -- an accepted algorithm whose ordinary
|
|
315
|
-
// signature the ceiling refuses is a row that can never verify -- so 8 KiB, which covers ML-DSA-87
|
|
316
|
-
// and an RSA-16384 key with room to spare while still refusing a segment whose only purpose is to
|
|
317
|
-
// make the verifier allocate.
|
|
318
153
|
MDS_BLOB_SIG_MAX_BYTES: BYTES.kib(8),
|
|
319
154
|
MDS_MAX_ENTRIES: 4096,
|
|
320
|
-
// A model's certification history: bounded like the other repeated per-entry structures, because
|
|
321
|
-
// the status gate walks the whole array on every verification.
|
|
322
155
|
MDS_MAX_STATUS_REPORTS_PER_ENTRY: 256,
|
|
323
156
|
MDS_MAX_ANCHORS_PER_ENTRY: 16,
|
|
324
|
-
// A U2F authenticator carries no AAGUID, so its entry is keyed by the key identifiers of its
|
|
325
|
-
// attestation certificates instead -- a batch-attested product line legitimately registers dozens.
|
|
326
157
|
MDS_MAX_KEY_IDS_PER_ENTRY: 64,
|
|
327
|
-
// The most nested statements a WebAuthn compound attestation (sec. 8.9) may carry. The syntax
|
|
328
|
-
// says "2*" -- unbounded -- so this is a resource bound this toolkit chooses, NOT a spec MUST.
|
|
329
|
-
// The CBOR parse caps bound the decode; they do not bound the crypto, and each element costs a
|
|
330
|
-
// signature verification plus, for some formats, a full certificate-path validation. Seven
|
|
331
|
-
// non-compound formats are registered, so a conforming statement carrying one of each is 7.
|
|
332
158
|
WEBAUTHN_COMPOUND_MAX_STATEMENTS: 16,
|
|
333
|
-
// The most certificates a WebAuthn attestation chain may carry, in an attStmt x5c array or a JWS
|
|
334
|
-
// x5c header. A real attestation chain is one to four; the byte ceiling on a single entry does
|
|
335
|
-
// not bound the COUNT, so an array of thousands of small certificates is an unbounded parse and
|
|
336
|
-
// signature-check fanout (CWE-770) that terminates but costs far more CPU than wire. This is a
|
|
337
|
-
// resource bound this toolkit chooses -- no specification states it -- and it is far tighter than
|
|
338
|
-
// PATH_MAX_CERTS because an attestation chain is not a general PKI path.
|
|
339
159
|
WEBAUTHN_X5C_MAX_CERTS: 10,
|
|
340
|
-
// A WebAuthn android-safetynet attestation statement carries the SafetyNet response as a JWS
|
|
341
|
-
// compact serialization: two small JSON objects plus a signature, with the certificate chain
|
|
342
|
-
// inline in the header. Real ones run a few kilobytes. The cap bounds the text decode before the
|
|
343
|
-
// string is materialized, so an oversized statement is refused rather than allocated (CWE-770).
|
|
344
160
|
SAFETYNET_JWS_MAX_BYTES: BYTES.kib(64),
|
|
345
|
-
// One x5c entry is a single DER certificate; PATH_MAX_CERT_BYTES is the ceiling the path
|
|
346
|
-
// validator already applies to any certificate it will accept, and an entry above it could not
|
|
347
|
-
// chain even if it decoded.
|
|
348
161
|
SAFETYNET_CERT_MAX_BYTES: BYTES.kib(64),
|
|
349
|
-
// ACME challenge token entropy floor (RFC 8555 sec. 8, errata 6950): >= 128
|
|
350
|
-
// bits of base64url is >= 22 characters. A shorter token is refused before use.
|
|
351
162
|
ACME_TOKEN_MIN_CHARS: 22,
|
|
352
|
-
// SCEP transactionID length ceiling (RFC 8894 sec. 3.2.1.1). The RFC sets no
|
|
353
|
-
// length; a real transaction id is a short hash or key fingerprint, so the
|
|
354
|
-
// builder caps the caller-supplied PrintableString here rather than emitting
|
|
355
|
-
// an unbounded attribute.
|
|
356
163
|
SCEP_TRANSACTION_ID_MAX: 255,
|
|
357
|
-
// OCSP embedded-certificate ceiling. A BasicOCSPResponse (or an OCSP request
|
|
358
|
-
// Signature) carries the responder / requestor certificate plus at most a short
|
|
359
|
-
// chain; the delegated-responder authorization loop verifies each candidate
|
|
360
|
-
// BEFORE the response signature is checked, so an attacker-crafted stapled /
|
|
361
|
-
// relayed response with a huge certs list would drive unbounded pre-auth
|
|
362
|
-
// signature verifies. 32 is generous headroom over a real chain.
|
|
363
164
|
OCSP_MAX_CERTS: 32,
|
|
364
|
-
// HSS hierarchy depth (RFC 8554 sec. 6.1: L is 1..8). The HSS verifier caps
|
|
365
|
-
// its per-level parse loop at this from the registry, never at the blob's own
|
|
366
|
-
// Nspk, so a hostile signature cannot drive an unbounded level walk.
|
|
367
165
|
HSS_MAX_LEVELS: 8,
|
|
368
|
-
// Trust-store ingestion ceilings (Mozilla/NSS certdata.txt + CCADB CSV).
|
|
369
|
-
// Every cap is refused BEFORE the offending allocation with a typed trust/*
|
|
370
|
-
// error -- never a silent truncate. A live certdata.txt is a few MiB and a
|
|
371
|
-
// CCADB all-records export a few MiB more, so 16 MiB whole-input headroom
|
|
372
|
-
// matches the codec siblings. A root certificate (or a CCADB PEM cell) is a
|
|
373
|
-
// few KiB; a MULTILINE_OCTAL blob or CSV field past 64 KiB is amplification,
|
|
374
|
-
// not a root. The real store is ~150 roots x 2 object blocks (and one CCADB
|
|
375
|
-
// row per root), so 10000 objects / rows is generous headroom while bounding
|
|
376
|
-
// a block/row bomb.
|
|
377
166
|
TRUST_MAX_BYTES: BYTES.mib(16),
|
|
378
167
|
TRUST_MAX_OCTAL_BYTES: BYTES.kib(64),
|
|
379
168
|
TRUST_MAX_OBJECTS: 10000,
|
|
@@ -381,19 +170,7 @@ var LIMITS = {
|
|
|
381
170
|
TRUST_MAX_CSV_FIELD_BYTES: BYTES.kib(64),
|
|
382
171
|
};
|
|
383
172
|
|
|
384
|
-
// NAMES -- display-naming conventions shared by the human-readable renderers
|
|
385
|
-
// (pki.inspect today; a future lint / CLI report tomorrow). Centralized so every
|
|
386
|
-
// consumer speaks ONE convention -- the OpenSSL-familiar labels an operator expects
|
|
387
|
-
// -- rather than each renderer copying a table that silently drifts. These are
|
|
388
|
-
// DISPLAY strings, not wire identifiers (those resolve through pki.oid): a value here
|
|
389
|
-
// never affects parse or verify, only how a decoded field is titled in a report.
|
|
390
173
|
var NAMES = {
|
|
391
|
-
// ==== Distinguished-name attribute short names (RFC 4514 sec. 3 + RFC 4519 / CABF) ==
|
|
392
|
-
// The single source of truth: this table was previously copied in both
|
|
393
|
-
// lib/inspect.js and lib/schema-pkix.js and had already drifted (STREET vs street,
|
|
394
|
-
// SERIALNUMBER vs serialNumber). An entry whose type the OID registry does not yet
|
|
395
|
-
// resolve is simply never hit -- forward entries (jurisdiction*, organizationIdentifier)
|
|
396
|
-
// are harmless until their arc is registered.
|
|
397
174
|
DN_SHORT: {
|
|
398
175
|
commonName: "CN", surname: "SN", serialNumber: "SERIALNUMBER", countryName: "C",
|
|
399
176
|
localityName: "L", stateOrProvinceName: "ST", streetAddress: "STREET",
|
|
@@ -404,8 +181,6 @@ var NAMES = {
|
|
|
404
181
|
jurisdictionCountryName: "jurisdictionC", jurisdictionStateOrProvinceName: "jurisdictionST",
|
|
405
182
|
jurisdictionLocalityName: "jurisdictionL", organizationIdentifier: "organizationIdentifier",
|
|
406
183
|
},
|
|
407
|
-
// ==== X.509v3 extension section titles (OpenSSL-familiar); an extension absent
|
|
408
|
-
// here is titled from the OID registry name / dotted OID ====
|
|
409
184
|
EXTENSION: {
|
|
410
185
|
basicConstraints: "X509v3 Basic Constraints", keyUsage: "X509v3 Key Usage",
|
|
411
186
|
extKeyUsage: "X509v3 Extended Key Usage", subjectAltName: "X509v3 Subject Alternative Name",
|
|
@@ -420,43 +195,29 @@ var NAMES = {
|
|
|
420
195
|
invalidityDate: "Invalidity Date", certificateIssuer: "X509v3 Certificate Issuer",
|
|
421
196
|
signedCertificateTimestampList: "CT Precertificate SCTs", precertificatePoison: "CT Precertificate Poison",
|
|
422
197
|
},
|
|
423
|
-
// ==== KeyUsage bits (RFC 5280 sec. 4.2.1.3, bit order) ====
|
|
424
198
|
KEY_USAGE: {
|
|
425
199
|
digitalSignature: "Digital Signature", nonRepudiation: "Non Repudiation", keyEncipherment: "Key Encipherment",
|
|
426
200
|
dataEncipherment: "Data Encipherment", keyAgreement: "Key Agreement", keyCertSign: "Certificate Sign",
|
|
427
201
|
cRLSign: "CRL Sign", encipherOnly: "Encipher Only", decipherOnly: "Decipher Only",
|
|
428
202
|
},
|
|
429
|
-
// ==== ExtendedKeyUsage purposes (RFC 5280 sec. 4.2.1.12 + common); an unlisted
|
|
430
|
-
// purpose shows its registry name / OID ====
|
|
431
203
|
EXT_KEY_USAGE: {
|
|
432
204
|
anyExtendedKeyUsage: "Any Extended Key Usage", serverAuth: "TLS Web Server Authentication",
|
|
433
205
|
clientAuth: "TLS Web Client Authentication", codeSigning: "Code Signing",
|
|
434
206
|
emailProtection: "E-mail Protection", timeStamping: "Time Stamping", ocspSigning: "OCSP Signing",
|
|
435
207
|
},
|
|
436
|
-
// ==== GeneralName CHOICE labels, by context tag number (RFC 5280 sec. 4.2.1.6) ====
|
|
437
208
|
GENERAL_NAME: { 0: "othername", 1: "email", 2: "DNS", 3: "X400Name", 4: "DirName", 5: "EdiPartyName", 6: "URI", 7: "IP Address", 8: "Registered ID" },
|
|
438
|
-
// ==== Named-curve -> NIST alias, for the EC key line ====
|
|
439
209
|
NIST_CURVE: { prime256v1: "P-256", secp384r1: "P-384", secp521r1: "P-521" },
|
|
440
|
-
// ==== ReasonFlags BIT STRING bit -> name (RFC 5280 sec. 4.2.1.13, a CRL
|
|
441
|
-
// distribution point's revocation scope; bit 0 is "unused"). Distinct from the
|
|
442
|
-
// CRLReason ENUMERATED below -- a BIT STRING of scopes, not a single code. ====
|
|
443
210
|
REASON_FLAGS: {
|
|
444
211
|
1: "Key Compromise", 2: "CA Compromise", 3: "Affiliation Changed", 4: "Superseded",
|
|
445
212
|
5: "Cessation Of Operation", 6: "Certificate Hold", 7: "Privilege Withdrawn", 8: "AA Compromise",
|
|
446
213
|
},
|
|
447
|
-
// ==== CRLReason ENUMERATED value names (RFC 5280 sec. 5.3.1; value 7 is unused) ====
|
|
448
214
|
CRL_REASON: {
|
|
449
215
|
"0": "unspecified", "1": "keyCompromise", "2": "cACompromise", "3": "affiliationChanged",
|
|
450
216
|
"4": "superseded", "5": "cessationOfOperation", "6": "certificateHold",
|
|
451
217
|
"8": "removeFromCRL", "9": "privilegeWithdrawn", "10": "aACompromise",
|
|
452
218
|
},
|
|
453
|
-
// ==== OCSPResponseStatus value names (RFC 6960 sec. 4.2.1; value 4 is unassigned) ====
|
|
454
219
|
OCSP_STATUS: { "0": "successful", "1": "malformedRequest", "2": "internalError", "3": "tryLater", "5": "sigRequired", "6": "unauthorized" },
|
|
455
|
-
// ==== Attribute-cert objectDigestInfo digested-object types (RFC 5755 sec. 4.4.2) ====
|
|
456
220
|
OBJECT_DIGEST_TYPE: { "0": "publicKey", "1": "publicKeyCert", "2": "otherObjectTypes" },
|
|
457
|
-
// ==== Public-key / signature algorithm display names, classical + PQC. Forward-
|
|
458
|
-
// looking: the toolkit is PQC-first, so the FIPS 203/204/205 names render as-is;
|
|
459
|
-
// a consumer that finds no entry shows the OID registry name / dotted OID ====
|
|
460
221
|
ALGORITHM: {
|
|
461
222
|
rsaEncryption: "rsaEncryption", rsassaPss: "rsassaPss", rsaesOaep: "rsaesOaep", ecPublicKey: "id-ecPublicKey",
|
|
462
223
|
ed25519: "ED25519", ed448: "ED448", x25519: "X25519", x448: "X448",
|
|
@@ -467,19 +228,9 @@ var NAMES = {
|
|
|
467
228
|
},
|
|
468
229
|
};
|
|
469
230
|
|
|
470
|
-
// NAMES is BOTH a display table (pki.inspect) and the strict parsers' legal-value
|
|
471
|
-
// allow-list: the CRL reasonCode, OCSP response-status, and attribute-cert object-
|
|
472
|
-
// digest decoders check membership against CRL_REASON / OCSP_STATUS / OBJECT_DIGEST_TYPE
|
|
473
|
-
// to fail closed on an RFC-reserved / undefined value. Deep-freeze it so a caller can
|
|
474
|
-
// NEVER widen what those decoders accept by mutating the "display-only" table (e.g.
|
|
475
|
-
// adding CRLReason 7, RFC-reserved, which would otherwise make the decoders fail open).
|
|
476
231
|
Object.keys(NAMES).forEach(function (k) { Object.freeze(NAMES[k]); });
|
|
477
232
|
Object.freeze(NAMES);
|
|
478
233
|
|
|
479
|
-
// Single-sourced from the package manifest so the reported version can
|
|
480
|
-
// never drift from the published package (package.json is always present
|
|
481
|
-
// in the installed tarball). A hand-maintained literal here silently
|
|
482
|
-
// shipped 0.1.0 on a 0.1.1 release.
|
|
483
234
|
var VERSION = require("../package.json").version;
|
|
484
235
|
|
|
485
236
|
module.exports = {
|