@blamejs/pki 0.1.21 → 0.1.23

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/ct.js CHANGED
@@ -14,26 +14,26 @@
14
14
  * OCSP response) carries in the SCT extension into its individual signed
15
15
  * certificate timestamps.
16
16
  *
17
- * The SCT payload is encoded in the TLS presentation language (RFC 8446 §3 /
18
- * RFC 5246 §4 conventions) positional, tag-less, fixed-width big-endian
19
- * integers and length-prefixed opaque vectors NOT ASN.1/DER. So this module
17
+ * The SCT payload is encoded in the TLS presentation language (RFC 8446 sec. 3 /
18
+ * RFC 5246 sec. 4 conventions) -- positional, tag-less, fixed-width big-endian
19
+ * integers and length-prefixed opaque vectors -- NOT ASN.1/DER. So this module
20
20
  * owns a bounded big-endian TLS-struct reader rather than composing the DER
21
- * schema engine; the only ASN.1 surface is the §3.3 double wrap (the
21
+ * schema engine; the only ASN.1 surface is the sec. 3.3 double wrap (the
22
22
  * extension value is a DER OCTET STRING whose content is another DER OCTET
23
- * STRING whose content is the TLS list the certificate/OCSP layer peels the
23
+ * STRING whose content is the TLS list -- the certificate/OCSP layer peels the
24
24
  * outer, this module peels the inner).
25
25
  *
26
26
  * Structure is decoded, crypto is surfaced RAW: each SCT surfaces its `logId`
27
- * (32 raw bytes SHA-256 of the log's SPKI, never recomputed), the exact
27
+ * (32 raw bytes -- SHA-256 of the log's SPKI, never recomputed), the exact
28
28
  * `timestamp` as a BigInt, the raw `extensions`, the named-but-not-interpreted
29
29
  * `hashAlg`/`sigAlg` code points, and the raw `signature`. The parser NEVER
30
- * verifies a signature, recomputes a LogID, or trusts a log a verifier
30
+ * verifies a signature, recomputes a LogID, or trusts a log -- a verifier
31
31
  * composes `webcrypto` over `reconstructSignedData(...)`, the exact
32
32
  * `digitally-signed` preimage. DER-only carrier, fail-closed.
33
33
  *
34
34
  * @card
35
35
  * Parse RFC 6962 Certificate Transparency SCT lists from a certificate or OCSP
36
- * extension per-SCT logId / timestamp (BigInt) / algorithm / raw signature,
36
+ * extension -- per-SCT logId / timestamp (BigInt) / algorithm / raw signature,
37
37
  * the signed-preimage reconstruction surfaced for external verification,
38
38
  * bounded TLS-struct decode, fail-closed.
39
39
  */
@@ -45,8 +45,8 @@ var frameworkError = require("./framework-error.js");
45
45
  var CtError = frameworkError.CtError;
46
46
  var C = constants;
47
47
 
48
- // RFC 5246 §7.4.1.4.1 code points 1-byte, NOT OIDs. Surfaced named; an
49
- // unknown code surfaces as its numeric byte with a null name (never rejected
48
+ // RFC 5246 sec. 7.4.1.4.1 code points -- 1-byte, NOT OIDs. Surfaced named; an
49
+ // unknown code surfaces as its numeric byte with a null name (never rejected --
50
50
  // off-profile-pair rejection is a verifier-tier log-conformance concern).
51
51
  var HASH_ALGORITHMS = {
52
52
  0: "none", 1: "md5", 2: "sha1", 3: "sha224", 4: "sha256", 5: "sha384", 6: "sha512",
@@ -59,7 +59,7 @@ var SCT_MIN_BODY = 47;
59
59
  var LOGID_BYTES = 32;
60
60
  var MAX_SAFE = 9007199254740991n; // 2^53 - 1; above this a Number loses precision
61
61
 
62
- // ---- TlsReader the one net-new primitive (an ENCODING layer, not a schema
62
+ // ---- TlsReader -- the one net-new primitive (an ENCODING layer, not a schema
63
63
  // combinator): a bounded big-endian TLS-vector cursor with a hard [pos, end).
64
64
  // A lying inner length can overrun only the current sub-reader's `end`, never
65
65
  // the parent buffer, so bounds-before-slice is structural.
@@ -81,7 +81,7 @@ TlsReader.prototype.fixed = function (n, code) {
81
81
  this._need(n, code);
82
82
  var s = this.buf.subarray(this.pos, this.pos + n); this.pos += n; return s;
83
83
  };
84
- // opaque<min..max> a length-prefixed vector (lenWidth-byte big-endian prefix).
84
+ // opaque<min..max> -- a length-prefixed vector (lenWidth-byte big-endian prefix).
85
85
  // The length prefix itself is a plain read (a truncation there is ct/truncated);
86
86
  // only a LYING length whose body overruns the bound carries the field's own code.
87
87
  TlsReader.prototype.vector = function (lenWidth, min, max, code) {
@@ -98,16 +98,16 @@ TlsReader.prototype.subReader = function (len, code) {
98
98
  TlsReader.prototype.remaining = function () { return this.end - this.pos; };
99
99
  TlsReader.prototype.atEnd = function () { return this.pos === this.end; };
100
100
 
101
- // Peel the RFC 6962 §3.3 inner DER OCTET STRING (the certificate/OCSP layer
101
+ // Peel the RFC 6962 sec. 3.3 inner DER OCTET STRING (the certificate/OCSP layer
102
102
  // already peeled the outer extnValue OCTET STRING). Rides the strict codec, so
103
103
  // an indefinite length / constructed OCTET STRING / trailing bytes / single
104
104
  // wrap all fail closed here; the asn1/* fault attaches as `.cause`.
105
105
  function _peelInner(extValue) {
106
106
  var node;
107
107
  try { node = asn1.decode(extValue); }
108
- catch (e) { throw new CtError("ct/bad-der", "the SCT-list extension value is not valid DER (RFC 6962 §3.3)", e); }
108
+ catch (e) { throw new CtError("ct/bad-der", "the SCT-list extension value is not valid DER (RFC 6962 sec. 3.3)", e); }
109
109
  try { return asn1.read.octetString(node); }
110
- catch (e) { throw new CtError("ct/bad-der", "the SCT-list extension value must be a DER OCTET STRING wrapping the TLS list (RFC 6962 §3.3)", e); }
110
+ catch (e) { throw new CtError("ct/bad-der", "the SCT-list extension value must be a DER OCTET STRING wrapping the TLS list (RFC 6962 sec. 3.3)", e); }
111
111
  }
112
112
 
113
113
  function _toBuffer(v, field) {
@@ -119,9 +119,9 @@ function _toBuffer(v, field) {
119
119
  // Parse one SerializedSCT body inside a sub-reader bounded to the element (so a
120
120
  // lying extensions/signature length overruns the element, never the list). A
121
121
  // version this parser does not define is preserved OPAQUE, not rejected: RFC 6962
122
- // §3.3 gives every SerializedSCT its own length prefix precisely so a client "can
122
+ // sec. 3.3 gives every SerializedSCT its own length prefix precisely so a client "can
123
123
  // still parse old SCTs while skipping over new SCTs whose versions they don't
124
- // understand" so an unknown version yields { unknown, version, rawSct } and the
124
+ // understand" -- so an unknown version yields { unknown, version, rawSct } and the
125
125
  // v1-specific field decode (and the 47-byte floor) is skipped.
126
126
  function _parseSct(r, sctLen) {
127
127
  var bodyStart = r.pos;
@@ -130,7 +130,7 @@ function _parseSct(r, sctLen) {
130
130
  return { unknown: true, version: version, rawSct: r.buf.subarray(bodyStart, r.end) };
131
131
  }
132
132
  if (sctLen < SCT_MIN_BODY) {
133
- throw new CtError("ct/sct-too-short", "a v1 SCT body is at least " + SCT_MIN_BODY + " bytes, got " + sctLen + " (RFC 6962 §3.2)");
133
+ throw new CtError("ct/sct-too-short", "a v1 SCT body is at least " + SCT_MIN_BODY + " bytes, got " + sctLen + " (RFC 6962 sec. 3.2)");
134
134
  }
135
135
  var logId = r.fixed(LOGID_BYTES);
136
136
  var timestamp = r.u64();
@@ -139,7 +139,7 @@ function _parseSct(r, sctLen) {
139
139
  var sigAlg = r.u8();
140
140
  var signature = r.vector(2, 0, null, "ct/sig-overrun");
141
141
  if (!r.atEnd()) {
142
- throw new CtError("ct/sct-trailing-bytes", (r.end - r.pos) + " byte(s) left in a SerializedSCT after the signature (RFC 6962 §3.3)");
142
+ throw new CtError("ct/sct-trailing-bytes", (r.end - r.pos) + " byte(s) left in a SerializedSCT after the signature (RFC 6962 sec. 3.3)");
143
143
  }
144
144
  var timestampMs = timestamp <= MAX_SAFE ? Number(timestamp) : null;
145
145
  return {
@@ -176,13 +176,13 @@ function _parseSct(r, sctLen) {
176
176
  * `signatureAlgorithm`, the raw `signature` Buffer, and `rawSct` (the full
177
177
  * SerializedSCT body). A SerializedSCT whose version this parser does not define
178
178
  * is preserved OPAQUE in `unknownScts` as `{ version, rawSct }` rather than
179
- * failing the list RFC 6962 §3.3 frames each SerializedSCT with its own length
179
+ * failing the list -- RFC 6962 sec. 3.3 frames each SerializedSCT with its own length
180
180
  * so unknown versions are skippable (forward compatibility).
181
181
  *
182
182
  * The extension value is a DER `OCTET STRING` wrapping the TLS-encoded list
183
- * (RFC 6962 §3.3 double wrap); everything below that peel is TLS presentation
183
+ * (RFC 6962 sec. 3.3 double wrap); everything below that peel is TLS presentation
184
184
  * language, decoded with a bounded cursor. Structure is decoded, crypto is
185
- * surfaced RAW the signature is never verified and the LogID never recomputed.
185
+ * surfaced RAW -- the signature is never verified and the LogID never recomputed.
186
186
  *
187
187
  * Throws `CtError` with a stable `ct/*` code on any malformed input (a bad inner
188
188
  * DER wrap is `ct/bad-der` with the `asn1/*` fault as `.cause`), never a raw
@@ -209,22 +209,22 @@ function parseSctList(extValue) {
209
209
  var outer = new TlsReader(blob, 0, blob.length);
210
210
  var listLen = outer.u16("ct/bad-list");
211
211
  if (listLen + 2 !== blob.length) {
212
- throw new CtError("ct/bad-list", "the SCT list declared length " + listLen + " does not match the " + (blob.length - 2) + " byte(s) present (RFC 6962 §3.3)");
212
+ throw new CtError("ct/bad-list", "the SCT list declared length " + listLen + " does not match the " + (blob.length - 2) + " byte(s) present (RFC 6962 sec. 3.3)");
213
213
  }
214
214
  if (listLen < 1) {
215
- throw new CtError("ct/empty-list", "an SCT list must contain at least one SCT (RFC 6962 §3.3)");
215
+ throw new CtError("ct/empty-list", "an SCT list must contain at least one SCT (RFC 6962 sec. 3.3)");
216
216
  }
217
217
  var scts = [], unknownScts = [];
218
218
  while (!outer.atEnd()) {
219
219
  if (outer.remaining() < 2) {
220
- throw new CtError("ct/list-trailing-bytes", "a dangling partial element after the last complete SCT (RFC 6962 §3.3)");
220
+ throw new CtError("ct/list-trailing-bytes", "a dangling partial element after the last complete SCT (RFC 6962 sec. 3.3)");
221
221
  }
222
222
  var sctLen = outer.u16("ct/list-trailing-bytes");
223
223
  if (sctLen < 1) {
224
- throw new CtError("ct/sct-empty", "a SerializedSCT must be non-empty (RFC 6962 §3.3)");
224
+ throw new CtError("ct/sct-empty", "a SerializedSCT must be non-empty (RFC 6962 sec. 3.3)");
225
225
  }
226
226
  if (outer.remaining() < sctLen) {
227
- throw new CtError("ct/list-trailing-bytes", "a SerializedSCT length " + sctLen + " overruns the list (RFC 6962 §3.3)");
227
+ throw new CtError("ct/list-trailing-bytes", "a SerializedSCT length " + sctLen + " overruns the list (RFC 6962 sec. 3.3)");
228
228
  }
229
229
  var one = _parseSct(outer.subReader(sctLen, "ct/list-trailing-bytes"), sctLen);
230
230
  if (one.unknown) unknownScts.push({ version: one.version, rawSct: one.rawSct });
@@ -240,7 +240,7 @@ function parseSctList(extValue) {
240
240
 
241
241
  function _u24Bytes(n) {
242
242
  if (n < 1 || n > 0xffffff) {
243
- throw new CtError("ct/bad-tbs-length", "a certificate / TBSCertificate length must be in 1..2^24-1, got " + n + " (RFC 6962 §3.1)");
243
+ throw new CtError("ct/bad-tbs-length", "a certificate / TBSCertificate length must be in 1..2^24-1, got " + n + " (RFC 6962 sec. 3.1)");
244
244
  }
245
245
  return Buffer.from([(n >> 16) & 0xff, (n >> 8) & 0xff, n & 0xff]);
246
246
  }
@@ -254,20 +254,22 @@ function _u24Bytes(n) {
254
254
  * @related pki.ct.parseSctList
255
255
  *
256
256
  * Rebuild the exact `digitally-signed` preimage bytes an external verifier
257
- * hashes to check an SCT's signature (RFC 6962 §3.2), for a parsed `sct`.
257
+ * hashes to check an SCT's signature (RFC 6962 sec. 3.2), for a parsed `sct`.
258
258
  * `entry` selects the log-entry arm:
259
- * - `{ entryType: 0, leafCert: <DER Buffer> }` an SCT delivered over TLS /
259
+ * - `{ entryType: 0, leafCert: <DER Buffer> }` -- an SCT delivered over TLS /
260
260
  * OCSP, signed over `x509_entry(0)` with the leaf certificate.
261
- * - `{ entryType: 1, tbsCertificate: <DER Buffer>, issuerKeyHash: <32B> }`
261
+ * - `{ entryType: 1, tbsCertificate: <DER Buffer>, issuerKeyHash: <32B> }` --
262
262
  * an SCT EMBEDDED in a certificate, signed over `precert_entry(1)` with the
263
263
  * issuer key hash + the precertificate TBS (the TBS with only the SCT
264
264
  * extension removed). `issuerKeyHash` is SHA-256 of the issuer's SPKI DER.
265
265
  *
266
266
  * The preimage reuses the parsed SCT's raw `extensions` byte-for-byte and
267
- * re-emits the fixed-width scalars canonically. This never verifies anything
267
+ * re-emits the fixed-width scalars canonically. This never verifies anything --
268
268
  * a verifier hashes the returned bytes and checks the signature with the log's
269
269
  * public key (compose `webcrypto`). Throws `CtError` (`ct/bad-entry-type`,
270
- * `ct/bad-issuer-key-hash`, `ct/bad-tbs-length`) on a malformed entry.
270
+ * `ct/bad-issuer-key-hash`, `ct/bad-tbs-length`) on a malformed entry, and
271
+ * `ct/bad-input` / `ct/bad-extensions` on an `sct` whose timestamp or
272
+ * extensions exceed their RFC 6962 3.2 wire ranges (uint64 / opaque<0..2^16-1>).
271
273
  *
272
274
  * @example
273
275
  * var sct = pki.ct.parseSctList(sctExtValue).scts[0];
@@ -278,17 +280,23 @@ function reconstructSignedData(entry, sct) {
278
280
  entry = entry || {};
279
281
  var entryType = entry.entryType;
280
282
  if (entryType !== 0 && entryType !== 1) {
281
- throw new CtError("ct/bad-entry-type", "entryType must be x509_entry(0) or precert_entry(1), got " + entryType + " (RFC 6962 §3.1)");
283
+ throw new CtError("ct/bad-entry-type", "entryType must be x509_entry(0) or precert_entry(1), got " + entryType + " (RFC 6962 sec. 3.1)");
282
284
  }
283
- // A fully decoded v1 SCT (from parseSctList().scts[]) not an opaque
285
+ // A fully decoded v1 SCT (from parseSctList().scts[]) -- not an opaque
284
286
  // unknownScts entry, whose body layout is undefined and cannot be signed over.
285
287
  if (!sct || typeof sct.timestamp !== "bigint" || sct.version !== 0) {
286
288
  throw new CtError("ct/bad-input", "reconstructSignedData expects a decoded v1 SCT from parseSctList().scts[]");
287
289
  }
290
+ // RFC 6962 3.2: the timestamp is a uint64. A hand-built value outside
291
+ // 0..2^64-1 cannot fill the fixed 8-byte field -- refused typed here rather
292
+ // than escaping as a raw RangeError from the Buffer write.
293
+ if (sct.timestamp < 0n || sct.timestamp > 0xffffffffffffffffn) {
294
+ throw new CtError("ct/bad-input", "sct.timestamp must be a uint64 (0..2^64-1), got " + sct.timestamp.toString() + " (RFC 6962 3.2)");
295
+ }
288
296
  var parts = [];
289
- parts.push(Buffer.from([sct.version & 0xff])); // Version v1(0)
290
- parts.push(Buffer.from([0])); // SignatureType certificate_timestamp(0)
291
- var ts = Buffer.alloc(8); ts.writeBigUInt64BE(BigInt(sct.timestamp)); parts.push(ts); // uint64 timestamp
297
+ parts.push(Buffer.from([sct.version & 0xff])); // Version -- v1(0)
298
+ parts.push(Buffer.from([0])); // SignatureType -- certificate_timestamp(0)
299
+ var ts = Buffer.alloc(8); ts.writeBigUInt64BE(sct.timestamp); parts.push(ts); // uint64 timestamp
292
300
  parts.push(Buffer.from([(entryType >> 8) & 0xff, entryType & 0xff])); // LogEntryType (2 bytes BE)
293
301
  if (entryType === 0) {
294
302
  var cert = _toBuffer(entry.leafCert, "leafCert");
@@ -296,13 +304,20 @@ function reconstructSignedData(entry, sct) {
296
304
  } else {
297
305
  var ikh = _toBuffer(entry.issuerKeyHash, "issuerKeyHash");
298
306
  if (ikh.length !== 32) {
299
- throw new CtError("ct/bad-issuer-key-hash", "issuer_key_hash must be exactly 32 bytes (SHA-256 of the issuer SPKI), got " + ikh.length + " (RFC 6962 §3.2)");
307
+ throw new CtError("ct/bad-issuer-key-hash", "issuer_key_hash must be exactly 32 bytes (SHA-256 of the issuer SPKI), got " + ikh.length + " (RFC 6962 sec. 3.2)");
300
308
  }
301
309
  var tbs = _toBuffer(entry.tbsCertificate, "tbsCertificate");
302
310
  parts.push(ikh);
303
311
  parts.push(_u24Bytes(tbs.length)); parts.push(tbs); // PreCert.tbs_certificate<1..2^24-1>
304
312
  }
305
313
  var ext = _toBuffer(sct.extensions, "sct.extensions"); // reuse the parsed raw bytes, never re-encode
314
+ // RFC 6962 3.2: CtExtensions is opaque<0..2^16-1>. A longer value is
315
+ // unrepresentable -- its 2-byte prefix would silently truncate mod 65536,
316
+ // an internally inconsistent preimage -- so it is refused, matching the
317
+ // range check the u24 certificate lengths get.
318
+ if (ext.length > 0xffff) {
319
+ throw new CtError("ct/bad-extensions", "CtExtensions must be 0..65535 bytes, got " + ext.length + " (RFC 6962 3.2)");
320
+ }
306
321
  parts.push(Buffer.from([(ext.length >> 8) & 0xff, ext.length & 0xff])); parts.push(ext); // CtExtensions
307
322
  return Buffer.concat(parts);
308
323
  }
@@ -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
@@ -27,6 +27,10 @@
27
27
  * classes the toolkit throws.
28
28
  */
29
29
 
30
+ // The frozen shape of every error code: a `domain/reason` string of
31
+ // lowercase alphanumerics and dashes.
32
+ var CODE_SHAPE = /^[a-z0-9-]+\/[a-z0-9-]+$/;
33
+
30
34
  /**
31
35
  * @primitive pki.errors.PkiError
32
36
  * @signature new PkiError(message, code)
@@ -36,6 +40,11 @@
36
40
  *
37
41
  * Base class every toolkit error extends. Provides the unified
38
42
  * `instanceof` check plus the `{ name, code, isPkiError }` shape.
43
+ * A supplied `code` must be a `domain/reason` string (lowercase
44
+ * alphanumerics and dashes) -- the construction throws a `TypeError`
45
+ * otherwise, which catches an argument-order swap with the
46
+ * `defineClass` subclasses' `(code, message)` convention at the call
47
+ * site instead of shipping prose into a code-switching consumer.
39
48
  *
40
49
  * @example
41
50
  * try { pki.asn1.decode(bytes); }
@@ -47,7 +56,14 @@ class PkiError extends Error {
47
56
  constructor(message, code) {
48
57
  super(message);
49
58
  this.name = "PkiError";
50
- this.code = code || "pki/invalid";
59
+ var c = code || "pki/invalid";
60
+ if (typeof c !== "string" || !CODE_SHAPE.test(c)) {
61
+ throw new TypeError(
62
+ "PkiError code must be a domain/reason string, got " + String(c) +
63
+ " (PkiError takes (message, code); defineClass subclasses take (code, message))"
64
+ );
65
+ }
66
+ this.code = c;
51
67
  this.isPkiError = true;
52
68
  this.permanent = true;
53
69
  }
@@ -60,13 +76,16 @@ class PkiError extends Error {
60
76
  * @status stable
61
77
  * @spec internal (design: error-class factory)
62
78
  *
63
- * Factory that produces a `PkiError` subclass with the standard shape
79
+ * Factory that produces a `PkiError` subclass with the standard shape --
64
80
  * eliminating the per-domain boilerplate. The returned constructor takes
65
81
  * `(code, message)`, stamps `name`, sets an `is<Name>` flag, and exposes
66
82
  * a `.factory` static for the common `var _err = XxxError.factory` shape.
83
+ * The `code` must be a `domain/reason` string (the base-class contract);
84
+ * without `withCause`, a third constructor argument throws a `TypeError`
85
+ * rather than silently discarding a cause the caller meant to thread.
67
86
  *
68
87
  * @opts
69
- * withCause: boolean, // default: false constructor becomes (code, message, cause)
88
+ * withCause: boolean, // default: false -- constructor becomes (code, message, cause)
70
89
  *
71
90
  * @example
72
91
  * var MyError = pki.errors.defineClass("MyError");
@@ -85,7 +104,11 @@ function defineClass(name, opts) {
85
104
  super(message, code);
86
105
  this.name = name;
87
106
  this[flagKey] = true;
88
- if (withCause && arg3 !== undefined) this.cause = arg3;
107
+ if (withCause) {
108
+ if (arg3 !== undefined) this.cause = arg3;
109
+ } else if (arg3 !== undefined) {
110
+ throw new TypeError(name + " takes (code, message); to thread a cause, define the class with { withCause: true }");
111
+ }
89
112
  }
90
113
  };
91
114
  Object.defineProperty(GeneratedError, "name", { value: name, configurable: true });
@@ -97,93 +120,101 @@ function defineClass(name, opts) {
97
120
 
98
121
  // ---- Per-domain error classes ----
99
122
 
100
- // ConstantsError a bad scale argument to C.TIME.* / C.BYTES.* (an
123
+ // ConstantsError -- a bad scale argument to C.TIME.* / C.BYTES.* (an
101
124
  // authoring bug caught at config time).
102
125
  var ConstantsError = defineClass("ConstantsError");
103
126
 
104
- // Asn1Error malformed / non-canonical DER: truncated TLV, indefinite
127
+ // Asn1Error -- malformed / non-canonical DER: truncated TLV, indefinite
105
128
  // length, non-minimal length or integer, leftover trailing bytes, depth
106
129
  // or size cap exceeded. DER is a canonical encoding, so anything the
107
130
  // decoder rejects is permanently invalid.
108
131
  var Asn1Error = defineClass("Asn1Error");
109
132
 
110
- // OidError a malformed object-identifier: fewer than two arcs, a first
133
+ // OidError -- a malformed object-identifier: fewer than two arcs, a first
111
134
  // arc outside 0..2, a second arc >= 40 under arcs 0/1, or a non-minimal
112
135
  // base-128 sub-identifier.
113
136
  var OidError = defineClass("OidError");
114
137
 
115
- // PemError a malformed PEM envelope: missing / mismatched BEGIN/END
138
+ // PemError -- a malformed PEM envelope: missing / mismatched BEGIN/END
116
139
  // markers, a bad label, or non-base64 body.
117
140
  var PemError = defineClass("PemError");
118
141
 
119
- // CertificateError a byte sequence that is not a well-formed X.509
142
+ // CertificateError -- a byte sequence that is not a well-formed X.509
120
143
  // certificate (wrong outer structure, unparseable field, unsupported
121
144
  // version).
122
145
  var CertificateError = defineClass("CertificateError", { withCause: true });
123
146
 
124
- // CrlError a byte sequence that is not a well-formed X.509 CRL
125
- // (CertificateList / TBSCertList RFC 5280 §5).
147
+ // CrlError -- a byte sequence that is not a well-formed X.509 CRL
148
+ // (CertificateList / TBSCertList -- RFC 5280 sec. 5).
126
149
  var CrlError = defineClass("CrlError", { withCause: true });
127
150
 
128
- // SchemaError the schema-family orchestrator's own errors (input that matches
151
+ // SchemaError -- the schema-family orchestrator's own errors (input that matches
129
152
  // no registered format / does not decode). (code, message) shape like the rest.
130
153
  var SchemaError = defineClass("SchemaError", { withCause: true });
131
154
 
132
- // CsrError a byte sequence that is not a well-formed PKCS#10 CertificationRequest
155
+ // CsrError -- a byte sequence that is not a well-formed PKCS#10 CertificationRequest
133
156
  // (RFC 2986).
134
157
  var CsrError = defineClass("CsrError", { withCause: true });
135
158
 
136
- // Pkcs8Error a byte sequence that is not a well-formed PKCS#8 PrivateKeyInfo /
137
- // OneAsymmetricKey or EncryptedPrivateKeyInfo (RFC 5208 §5, RFC 5958 §23).
159
+ // Pkcs8Error -- a byte sequence that is not a well-formed PKCS#8 PrivateKeyInfo /
160
+ // OneAsymmetricKey or EncryptedPrivateKeyInfo (RFC 5208 sec. 5, RFC 5958 sec. 2/sec. 3).
138
161
  var Pkcs8Error = defineClass("Pkcs8Error", { withCause: true });
139
162
 
140
- // CmsError a byte sequence that is not a well-formed CMS ContentInfo /
163
+ // CmsError -- a byte sequence that is not a well-formed CMS ContentInfo /
141
164
  // SignedData (RFC 5652). Carries the underlying leaf fault as `.cause`.
142
165
  var CmsError = defineClass("CmsError", { withCause: true });
143
166
 
144
- // OcspError a byte sequence that is not a well-formed OCSP request or response
145
- // (OCSPRequest / OCSPResponse RFC 6960 §4). Carries the leaf fault as `.cause`.
167
+ // OcspError -- a byte sequence that is not a well-formed OCSP request or response
168
+ // (OCSPRequest / OCSPResponse -- RFC 6960 sec. 4). Carries the leaf fault as `.cause`.
146
169
  var OcspError = defineClass("OcspError", { withCause: true });
147
170
 
148
- // TspError a byte sequence that is not a well-formed RFC 3161 timestamp token,
171
+ // TspError -- a byte sequence that is not a well-formed RFC 3161 timestamp token,
149
172
  // TSTInfo, or TimeStampResp. Carries the underlying leaf fault as `.cause`.
150
173
  var TspError = defineClass("TspError", { withCause: true });
151
174
 
152
- // AttrCertError a byte sequence that is not a well-formed X.509 Attribute
153
- // Certificate (AttributeCertificate / AttributeCertificateInfo RFC 5755 §4),
175
+ // AttrCertError -- a byte sequence that is not a well-formed X.509 Attribute
176
+ // Certificate (AttributeCertificate / AttributeCertificateInfo -- RFC 5755 sec. 4),
154
177
  // or a recognized-and-deferred legacy AttributeCertificateV1. Carries the
155
178
  // underlying leaf fault as `.cause`.
156
179
  var AttrCertError = defineClass("AttrCertError", { withCause: true });
157
180
 
158
- // CrmfError a byte sequence that is not a well-formed RFC 4211 CertReqMessages
181
+ // CrmfError -- a byte sequence that is not a well-formed RFC 4211 CertReqMessages
159
182
  // / CertReqMsg / CertRequest / CertTemplate. Carries the underlying leaf fault as
160
183
  // `.cause`.
161
184
  var CrmfError = defineClass("CrmfError", { withCause: true });
162
185
 
163
- // Pkcs12Error a byte sequence that is not a well-formed RFC 7292 PFX
164
- // (AuthenticatedSafe / SafeContents / SafeBag), or a PFX violating a §4
186
+ // Pkcs12Error -- a byte sequence that is not a well-formed RFC 7292 PFX
187
+ // (AuthenticatedSafe / SafeContents / SafeBag), or a PFX violating a sec. 4
165
188
  // coherence rule (version, integrity mode, bag dispatch, MacData). Carries
166
189
  // the underlying leaf fault as `.cause`.
167
190
  var Pkcs12Error = defineClass("Pkcs12Error", { withCause: true });
168
191
 
169
- // CmpError a byte sequence that is not a well-formed RFC 9810 PKIMessage
170
- // (PKIHeader / PKIBody / protection / extraCerts), or one violating a §5
171
- // coherence rule (protectionprotectionAlg, certConf-hashAlgpvno). Carries
192
+ // CmpError -- a byte sequence that is not a well-formed RFC 9810 PKIMessage
193
+ // (PKIHeader / PKIBody / protection / extraCerts), or one violating a sec. 5
194
+ // coherence rule (protection<=>protectionAlg, certConf-hashAlg<=>pvno). Carries
172
195
  // the underlying leaf fault as `.cause`.
173
196
  var CmpError = defineClass("CmpError", { withCause: true });
174
197
 
175
- // PathError a certification path that fails RFC 5280 §6 validation, or a
198
+ // PathError -- a certification path that fails RFC 5280 sec. 6 validation, or a
176
199
  // malformed input handed to the validator (an extension value that does not
177
200
  // decode, an empty path, an unsupported signature algorithm). Carries the
178
201
  // per-check reason in `.code` (`path/*`) and the underlying leaf fault as
179
202
  // `.cause`.
180
203
  var PathError = defineClass("PathError", { withCause: true });
181
204
 
182
- // CtError a byte sequence that is not a well-formed RFC 6962 Certificate
205
+ // SmimeError -- a byte sequence that is not a well-formed RFC 5035 ESS
206
+ // signing-certificate attribute (SigningCertificate / SigningCertificateV2 /
207
+ // ESSCertID(v2) / IssuerSerial) or RFC 8551 SMIMECapabilities, or a CMS
208
+ // attribute violating a sec. 2.5 coherence rule (single-AttributeValue, certs
209
+ // non-empty, non-canonical DEFAULT hashAlgorithm). Carries the underlying leaf
210
+ // fault (e.g. the inner asn1/* decode error) as `.cause`.
211
+ var SmimeError = defineClass("SmimeError", { withCause: true });
212
+
213
+ // CtError -- a byte sequence that is not a well-formed RFC 6962 Certificate
183
214
  // Transparency SCT list: a malformed inner DER OCTET-STRING wrap, or a TLS
184
215
  // presentation-language framing violation (a lying vector length, a field read
185
216
  // past its bound, a truncated element). An SCT whose version this parser does
186
- // not define is NOT an error RFC 6962 §3.3 makes unknown versions skippable,
217
+ // not define is NOT an error -- RFC 6962 sec. 3.3 makes unknown versions skippable,
187
218
  // so they are preserved opaque. Carries the underlying leaf fault (e.g. the
188
219
  // inner `asn1/*` decode error) as `.cause`.
189
220
  var CtError = defineClass("CtError", { withCause: true });
@@ -209,4 +240,5 @@ module.exports = {
209
240
  CmpError: CmpError,
210
241
  PathError: PathError,
211
242
  CtError: CtError,
243
+ SmimeError: SmimeError,
212
244
  };