@blamejs/pki 0.6.13 → 0.6.15

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 (114) hide show
  1. package/CHANGELOG.md +22 -1
  2. package/README.md +1 -1
  3. package/index.js +1 -1
  4. package/lib/acme.js +59 -815
  5. package/lib/asn1-der.js +7 -245
  6. package/lib/attrcert-sign.js +12 -260
  7. package/lib/attrcert-verify.js +1 -7
  8. package/lib/byte-reader.js +0 -8
  9. package/lib/byte-writer.js +0 -11
  10. package/lib/cbor-det.js +0 -54
  11. package/lib/cmc-build.js +15 -357
  12. package/lib/cmc-verify.js +6 -239
  13. package/lib/cmp-build.js +41 -317
  14. package/lib/cmp-session.js +73 -760
  15. package/lib/cmp-verify.js +32 -488
  16. package/lib/cms-compress.js +3 -32
  17. package/lib/cms-decrypt.js +29 -294
  18. package/lib/cms-encrypt.js +14 -234
  19. package/lib/cms-sign.js +29 -324
  20. package/lib/cms-verify.js +9 -500
  21. package/lib/composite-kem.js +2 -102
  22. package/lib/composite-sig.js +1 -77
  23. package/lib/constants.js +0 -249
  24. package/lib/crl-sign.js +9 -237
  25. package/lib/crl-verify.js +1 -10
  26. package/lib/crmf-sign.js +19 -198
  27. package/lib/crmf-verify.js +1 -12
  28. package/lib/csr-sign.js +3 -34
  29. package/lib/csr-verify.js +1 -12
  30. package/lib/ct.js +28 -253
  31. package/lib/edwards-point.js +10 -44
  32. package/lib/est.js +28 -764
  33. package/lib/framework-error.js +4 -182
  34. package/lib/guard-all.js +1 -58
  35. package/lib/guard-async.js +1 -36
  36. package/lib/guard-bytes.js +6 -650
  37. package/lib/guard-compress.js +5 -102
  38. package/lib/guard-crypto.js +1 -40
  39. package/lib/guard-der.js +2 -93
  40. package/lib/guard-encoding.js +2 -60
  41. package/lib/guard-header.js +1 -36
  42. package/lib/guard-identifier.js +7 -531
  43. package/lib/guard-intrinsic.js +1 -150
  44. package/lib/guard-json.js +10 -73
  45. package/lib/guard-limits.js +1 -77
  46. package/lib/guard-list.js +1 -49
  47. package/lib/guard-name.js +3 -209
  48. package/lib/guard-parsed.js +7 -335
  49. package/lib/guard-range.js +1 -71
  50. package/lib/guard-secret.js +1 -102
  51. package/lib/guard-text.js +1 -64
  52. package/lib/guard-time.js +1 -97
  53. package/lib/hpke.js +3 -105
  54. package/lib/http-digest.js +14 -142
  55. package/lib/http-retry-after.js +1 -47
  56. package/lib/http-transport.js +21 -131
  57. package/lib/inspect.js +30 -284
  58. package/lib/ip-utils.js +6 -47
  59. package/lib/jose.js +7 -142
  60. package/lib/key.js +2 -67
  61. package/lib/lint.js +9 -194
  62. package/lib/merkle.js +1 -27
  63. package/lib/mime.js +9 -82
  64. package/lib/ocsp-request-verify.js +1 -14
  65. package/lib/ocsp-verify.js +1 -82
  66. package/lib/ocsp.js +11 -169
  67. package/lib/oid.js +5 -337
  68. package/lib/path-validate.js +103 -1492
  69. package/lib/pbes2.js +2 -89
  70. package/lib/pkcs12-build.js +31 -379
  71. package/lib/pki-build.js +64 -290
  72. package/lib/rc2.js +2 -18
  73. package/lib/rfc3339.js +4 -27
  74. package/lib/scep.js +59 -233
  75. package/lib/schema-all.js +0 -122
  76. package/lib/schema-attrcert.js +4 -146
  77. package/lib/schema-c509.js +153 -802
  78. package/lib/schema-cmc.js +5 -220
  79. package/lib/schema-cmp.js +2 -223
  80. package/lib/schema-cms.js +13 -427
  81. package/lib/schema-crl.js +5 -68
  82. package/lib/schema-crmf.js +6 -167
  83. package/lib/schema-csr.js +1 -54
  84. package/lib/schema-csrattrs.js +2 -87
  85. package/lib/schema-engine.js +0 -152
  86. package/lib/schema-ocsp.js +0 -117
  87. package/lib/schema-pkcs12.js +2 -93
  88. package/lib/schema-pkcs8.js +3 -35
  89. package/lib/schema-pkix.js +24 -655
  90. package/lib/schema-smime.js +0 -54
  91. package/lib/schema-tsp.js +3 -99
  92. package/lib/schema-x509.js +4 -63
  93. package/lib/shbs.js +11 -95
  94. package/lib/sign-scheme.js +2 -97
  95. package/lib/sigstore.js +9 -169
  96. package/lib/sleep.js +2 -8
  97. package/lib/smime.js +15 -408
  98. package/lib/tls-cert-compress.js +0 -62
  99. package/lib/trust.js +19 -185
  100. package/lib/tsp-sign.js +16 -270
  101. package/lib/validator-all.js +1 -30
  102. package/lib/validator-attcert.js +2 -46
  103. package/lib/validator-cose.js +2 -153
  104. package/lib/validator-keydesc.js +1 -37
  105. package/lib/validator-sig.js +1 -46
  106. package/lib/validator-tls.js +1 -88
  107. package/lib/validator-tpm.js +19 -122
  108. package/lib/verify-seam.js +1 -24
  109. package/lib/webauthn-mds.js +3 -400
  110. package/lib/webauthn.js +12 -833
  111. package/lib/webcrypto.js +5 -485
  112. package/lib/x509-sign.js +4 -108
  113. package/package.json +1 -1
  114. package/sbom.cdx.json +6 -6
package/lib/schema-all.js CHANGED
@@ -46,200 +46,89 @@ var crmf = require("./schema-crmf");
46
46
  var cmp = require("./schema-cmp");
47
47
  var csrattrs = require("./schema-csrattrs");
48
48
  var attrcert = require("./schema-attrcert");
49
- // smime is a companion decoder for CMS signed-attribute values and not a top-level
50
- // format: it has no self-describing DER root (an ESS attribute value is a bare
51
- // SEQUENCE) so it is deliberately absent from FORMATS / the detect-and-route
52
- // `parse`; it is reached only by explicit OID dispatch on a CMS attribute.
53
49
  var smime = require("./schema-smime");
54
- // cmc is likewise a COMPANION decoder, for the same reason arrived at from the
55
- // other direction: a CMC message's outer DER root IS a CMS ContentInfo, which
56
- // `cms.matches` already claims below. A `cmc` FORMATS row would either shadow CMS
57
- // or be shadowed by it, and there is no structurally disjoint root to detect --
58
- // the discriminator is the encapsulated content type, one layer in. So it is
59
- // reached by explicit call, or by dispatching on
60
- // `pki.schema.cms.parse(der).encapContentInfo.eContentType`, and exports no
61
- // `matches` for nobody to call.
62
50
  var cmc = require("./schema-cmc");
63
51
  var frameworkError = require("./framework-error");
64
52
 
65
53
  var SchemaError = frameworkError.SchemaError;
66
54
  var PemError = frameworkError.PemError;
67
55
 
68
- // The shared parse-entry opts for the orchestrator: label-agnostic PEM unwrap
69
- // (any block type routes), the schema/* error family. Detection needs a decoded
70
- // root, so the coerced bytes are what gets routed to the matched format. The
71
- // ber mode lets a BER-encoded PFX (the dominant real-world .p12 shape) decode
72
- // far enough to detect; a BER input matching a strict-DER-only format still
73
- // fails typed inside that format's own parse.
74
56
  var ENTRY = { pemLabel: null, PemError: PemError, ErrorClass: SchemaError, prefix: "schema", what: "input", ber: true };
75
57
 
76
- // REGISTRY -- each format is declarative data: a name, a `detect(root)` that
77
- // recognizes the decoded DER root as this format's outer structure, and the
78
- // member's own `parse`. Adding a format is a table entry, not new dispatch
79
- // logic. Order matters: the most specific detector wins, so a new member is
80
- // inserted ahead of any more-permissive one.
81
58
  var FORMATS = [
82
59
  {
83
- // CMS ContentInfo (RFC 5652 sec. 3) -- the only registered root that leads with an
84
- // OBJECT IDENTIFIER child (a SEQUENCE of exactly 2: contentType OID + a
85
- // context [0] EXPLICIT content wrapper). Disjoint from the INTEGER-first pkcs8
86
- // and the tbs-SEQUENCE-first signed-envelope trio, so it detects unambiguously.
87
- // A non-SignedData content type routes here and gets a precise
88
- // cms/unsupported-content-type instead of schema/unknown-format.
89
60
  name: "cms",
90
61
  module: cms,
91
62
  detect: cms.matches,
92
63
  parse: function (input) { return cms.parse(input); },
93
64
  },
94
65
  {
95
- // TimeStampResp ::= SEQUENCE { status PKIStatusInfo, timeStampToken OPTIONAL } --
96
- // a SEQUENCE of 1-2 whose first child is a PKIStatusInfo SEQUENCE whose own first
97
- // child is an INTEGER status. This detector is a strict REFINEMENT of the
98
- // ocsp-request one (both are SEQUENCE-of-1-2 with a SEQUENCE first child), so it
99
- // MUST be checked first: a tokenless TimeStampResp (a bare PKIStatusInfo) would
100
- // otherwise be shadowed by ocsp-request, whereas an OCSPRequest's tbsRequest never
101
- // leads with a universal INTEGER and so never matches here (RFC 3161 sec. 2.4.2). A
102
- // bare timestamp token is a CMS ContentInfo and routes to cms; a bare TSTInfo is
103
- // an internal payload (reached via pki.schema.tsp.parseTstInfo).
104
66
  name: "tsp",
105
67
  module: tsp,
106
68
  detect: tsp.matches,
107
69
  parse: function (input) { return tsp.parse(input); },
108
70
  },
109
71
  {
110
- // CertReqMessages ::= SEQUENCE SIZE(1..MAX) OF CertReqMsg (RFC 4211 sec. 3): a
111
- // SEQUENCE whose first CertReqMsg's CertRequest leads with a universal INTEGER
112
- // (certReqId) then a universal SEQUENCE (certTemplate). Leads with a SEQUENCE
113
- // like the signed-envelope trio and the ocsp-request, but the INTEGER-then-
114
- // SEQUENCE pair at that depth is disjoint from both. Registered AHEAD of
115
- // ocsp-request: a single-message CertReqMessages is the only remaining overlap
116
- // with the ocsp-request detector, and crmf's deeper probe is the more specific.
117
72
  name: "crmf",
118
73
  module: crmf,
119
74
  detect: crmf.matches,
120
75
  parse: function (input) { return crmf.parse(input); },
121
76
  },
122
77
  {
123
- // PKIMessage ::= SEQUENCE { header PKIHeader, body PKIBody [0..26],
124
- // protection [0]?, extraCerts [1]? } (RFC 9810 sec. 5.1): a SEQUENCE of 2-4
125
- // whose first child is a >=3-child SEQUENCE leading with a bare INTEGER
126
- // (pvno) and whose second child is context-constructed [0..26]. Order is
127
- // load-bearing here: a 2-child PKIMessage whose body is ir [0] also
128
- // satisfies the shallow ocsp-request probe below (k[0] SEQUENCE +
129
- // k[1] context-[0]), while no OCSPRequest satisfies this detector (its
130
- // tbsRequest never leads with a bare INTEGER), so cmp MUST sit ahead of
131
- // ocsp-request for the pair to dispatch deterministically.
132
78
  name: "cmp",
133
79
  module: cmp,
134
80
  detect: cmp.matches,
135
81
  parse: function (input) { return cmp.parse(input); },
136
82
  },
137
83
  {
138
- // CsrAttrs ::= SEQUENCE SIZE (0..MAX) OF AttrOrOID (RFC 8951 sec. 3.5): a
139
- // SEQUENCE whose every child is a bare universal OID or an Attribute (a
140
- // universal SEQUENCE of exactly 2: OID + SET). A 1-2-element all-Attribute
141
- // CsrAttrs satisfies the permissive ocsp-request probe below (SEQUENCE +
142
- // constructed first child), and the empty 30 00 is a CsrAttrs no other root
143
- // accepts -- so csrattrs is the strict refinement and MUST sit ahead of
144
- // ocsp-request, the same resolution tsp / cmp use. Disjoint from cmp (whose
145
- // body child is context-[0..26], never a universal OID/Attribute).
146
84
  name: "csrattrs",
147
85
  module: csrattrs,
148
86
  detect: csrattrs.matches,
149
87
  parse: function (input) { return csrattrs.parse(input); },
150
88
  },
151
89
  {
152
- // OCSPRequest ::= SEQUENCE { tbsRequest SEQUENCE, optionalSignature [0] EXPLICIT
153
- // OPTIONAL }: a SEQUENCE of 1-2 whose first child is the tbsRequest SEQUENCE.
154
- // Leads with a SEQUENCE like the signed-envelope trio, but is excluded by arity
155
- // (the trio is exactly 3 children; an OCSPRequest is 1-2). Checked after tsp,
156
- // whose detector is a strict refinement (RFC 6960 sec. 4.1.1), and after cmp,
157
- // whose 2-child ir-body shape this probe would otherwise shadow.
158
90
  name: "ocsp-request",
159
91
  module: ocsp,
160
92
  detect: ocsp.matchesRequest,
161
93
  parse: function (input) { return ocsp.parseRequest(input); },
162
94
  },
163
95
  {
164
- // OCSPResponse ::= SEQUENCE { responseStatus ENUMERATED, responseBytes [0]
165
- // EXPLICIT OPTIONAL }: the only registered root that leads with an ENUMERATED
166
- // child, so it is disjoint from every other format (RFC 6960 sec. 4.2.1).
167
96
  name: "ocsp-response",
168
97
  module: ocsp,
169
98
  detect: ocsp.matchesResponse,
170
99
  parse: function (input) { return ocsp.parseResponse(input); },
171
100
  },
172
101
  {
173
- // PKCS#12 PFX ::= SEQUENCE { version INTEGER, authSafe ContentInfo, macData
174
- // OPTIONAL }: INTEGER-first like pkcs8, so the discriminators are deeper.
175
- // children[1] is a ContentInfo (SEQUENCE of exactly 2: OID + [0] constructed,
176
- // a shape a PrivateKeyInfo's AlgorithmIdentifier never presents) and
177
- // children[2] is a MacData SEQUENCE or absent (pkcs8 requires an OCTET STRING
178
- // there). Shape-disjoint from pkcs8, and registered ahead of it as the more
179
- // specific probe (RFC 7292 sec. 4). A BER-encoded PFX detects through the
180
- // orchestrator's BER decode fallback and routes here.
181
102
  name: "pkcs12",
182
103
  module: pkcs12,
183
104
  detect: pkcs12.matches,
184
105
  parse: function (input) { return pkcs12.parse(input); },
185
106
  },
186
107
  {
187
- // PKCS#8 PrivateKeyInfo / OneAsymmetricKey: a SEQUENCE whose first child is an
188
- // INTEGER (version) and third an OCTET STRING (privateKey); disjoint from the
189
- // signed-envelope trio. (EncryptedPrivateKeyInfo is deliberately not
190
- // auto-routed: its SEQUENCE{SEQUENCE, OCTET STRING} shape is ambiguous, since a
191
- // PKCS#1 DigestInfo is identical, so structural detection cannot classify it
192
- // without a validated encryption-algorithm discriminator, which arrives with
193
- // the PBES layer. It is reached explicitly via pki.schema.pkcs8.parseEncrypted.)
194
108
  name: "pkcs8",
195
109
  module: pkcs8,
196
110
  detect: pkcs8.matches,
197
111
  parse: function (input) { return pkcs8.parse(input); },
198
112
  },
199
113
  {
200
- // CertificationRequest ::= SEQUENCE { certificationRequestInfo,
201
- // signatureAlgorithm, signature }: the same outer 3-element shape,
202
- // distinguished by a CertificationRequestInfo of exactly four children
203
- // ending in the IMPLICIT [0] attributes element. Checked first because that
204
- // detector is the most specific and mutually exclusive with the others.
205
114
  name: "csr",
206
115
  module: csr,
207
116
  detect: csr.matches,
208
117
  parse: function (input) { return csr.parse(input); },
209
118
  },
210
119
  {
211
- // AttributeCertificate ::= SEQUENCE { acinfo, signatureAlgorithm, signatureValue }
212
- // -- the signed-envelope trio, recognized by an acinfo that LEADS WITH a bare
213
- // INTEGER version and carries a 2-GeneralizedTime attrCertValidityPeriod at
214
- // children[5] (RFC 5755, section 4.1). Order-independent versus crl / x509 / csr:
215
- // a v2 acinfo puts the AlgorithmIdentifier at the position where their probes
216
- // require a bare Time / a 2-Time Validity / a 4-child CRI, and none of their tbs
217
- // shapes carry the 2-GeneralizedTime marker at children[5].
218
120
  name: "attrcert",
219
121
  module: attrcert,
220
122
  detect: attrcert.matches,
221
123
  parse: function (input) { return attrcert.parse(input); },
222
124
  },
223
125
  {
224
- // AttributeCertificateV1 (X.509-1997, RFC 5652, section 10.2) -- the obsolete
225
- // predecessor whose acInfo LEADS WITH the subject CHOICE (context [0]/[1]).
226
- // Recognized and deferred with a precise attrcert/legacy-v1-not-supported rather
227
- // than routed to a wrong format. ORDER IS LOAD-BEARING against x509: a [0]-subject
228
- // v1 AC ALSO satisfies x509.matches (the [0] child reads as the certificate's
229
- // EXPLICIT version marker, putting the 2-GeneralizedTime attrCertValidityPeriod at
230
- // the Validity probe offset), so this entry MUST sit ahead of x509 for first-match
231
- // dispatch to defer it here. children[1] == SEQUENCE keeps a v3 certificate (whose
232
- // [0] version is followed by an INTEGER serialNumber) from matching in the other
233
- // direction.
234
126
  name: "attrcert-v1",
235
127
  module: attrcert,
236
128
  detect: attrcert.matchesV1,
237
129
  parse: function (input) { return attrcert.parseV1(input); },
238
130
  },
239
131
  {
240
- // CertificateList ::= SEQUENCE { tbsCertList, signatureAlgorithm,
241
- // signatureValue }: the same outer shape as a certificate, distinguished
242
- // by its tbsCertList (a bare Time at the certificate's Validity position).
243
132
  name: "crl",
244
133
  module: crl,
245
134
  detect: crl.matches,
@@ -248,9 +137,6 @@ var FORMATS = [
248
137
  {
249
138
  name: "x509",
250
139
  module: x509,
251
- // Certificate, identified by a Validity (SEQUENCE of two Times) inside the
252
- // tbs, so a CSR or other 3-element signed envelope is not misclassified as a
253
- // certificate (it falls through to schema/unknown-format).
254
140
  detect: x509.matches,
255
141
  parse: function (input) { return x509.parse(input); },
256
142
  },
@@ -293,9 +179,6 @@ function all() { return FORMATS.map(function (f) { return f.name; }); }
293
179
  * var parsed = pki.schema.parse(der); // cert -> the pki.schema.x509 shape
294
180
  */
295
181
  function parse(input) {
296
- // Coerce + decode via the shared parse-entry, then route the COERCED DER (a
297
- // PEM string/Buffer is already unwrapped, so the matched format parses DER
298
- // directly and never re-treats the armor as DER).
299
182
  var der = pkix.coerceToDer(input, ENTRY);
300
183
  var root = pkix.decodeRoot(der, ENTRY);
301
184
  for (var i = 0; i < FORMATS.length; i++) {
@@ -336,14 +219,9 @@ function detectFormat(input) {
336
219
  return null;
337
220
  }
338
221
 
339
- // Curated public surface: each format exposes only its operator primitives. The
340
- // `matches` detector is internal dispatch infrastructure (used by FORMATS above),
341
- // not an operator API, so it is NOT re-exported here.
342
222
  module.exports = {
343
223
  engine: engine,
344
224
  x509: { parse: x509.parse, pemDecode: x509.pemDecode, pemEncode: x509.pemEncode },
345
- // C509 is CBOR, not DER: an explicit-call surface only, NOT added to FORMATS / the detect-and-route
346
- // parse() below (which detect DER shapes). No pemDecode/pemEncode -- C509 is binary CBOR.
347
225
  c509: { parse: c509.parse, encode: c509.encode },
348
226
  crl: { parse: crl.parse, pemDecode: crl.pemDecode, pemEncode: crl.pemEncode },
349
227
  csr: { parse: csr.parse, pemDecode: csr.pemDecode, pemEncode: csr.pemEncode },
@@ -40,8 +40,6 @@ var pkix = require("./schema-pkix");
40
40
  var oid = require("./oid");
41
41
  var guard = require("./guard-all");
42
42
  var intrinsic = require("./guard-intrinsic");
43
- // Own-key membership through an operation taken at load. Written out, the question reads two
44
- // replaceable properties to answer one thing, and here it decides which object-digest types resolve.
45
43
  var _hasOwn = intrinsic.hasOwn;
46
44
  var frameworkError = require("./framework-error");
47
45
 
@@ -55,20 +53,11 @@ var TAGS = asn1.TAGS;
55
53
  var ALGORITHM_IDENTIFIER = pkix.algorithmIdentifier(NS);
56
54
  var EXTENSIONS = pkix.extensions(NS);
57
55
 
58
- // AttCertVersion ::= INTEGER { v2(1) }, a bare mandatory INTEGER (not the x509
59
- // [0] EXPLICIT DEFAULT shape). The only legal value is v2, surfaced as 2.
60
56
  var VERSION = pkix.versionReader(NS, { "1": 2 });
61
57
 
62
- // ---- shared leaves ---------------------------------------------------
63
58
 
64
- // AttCertValidityPeriod times are GeneralizedTime (RFC 5755 sec. 4.2.6) -- a UTCTime is
65
- // rejected. Non-fractional YYYYMMDDHHMMSSZ is enforced by the codec.
66
59
  var GENERALIZED_TIME = pkix.generalizedTime(NS, { code: "attrcert/bad-time", message: "AttCertValidityPeriod times must be GeneralizedTime (RFC 5755 sec. 4.2.6)" });
67
60
 
68
- // digestedObjectType ::= ENUMERATED { publicKey(0), publicKeyCert(1),
69
- // otherObjectTypes(2) } (RFC 5755 sec. 4.1). An undefined value is rejected; a
70
- // non-ENUMERATED tag fails at the codec (asn1/*).
71
- // objectDigestInfo digested-object-type names -- single source pki.C.NAMES.OBJECT_DIGEST_TYPE.
72
61
  var ODT_NAMES = constants.NAMES.OBJECT_DIGEST_TYPE;
73
62
  var DIGESTED_OBJECT_TYPE = schema.decode(function (n, ctx) {
74
63
  var v = asn1.read.enumerated(n);
@@ -76,22 +65,13 @@ var DIGESTED_OBJECT_TYPE = schema.decode(function (n, ctx) {
76
65
  if (!_hasOwn(ODT_NAMES, k)) {
77
66
  throw ctx.E("attrcert/bad-digested-object-type", "digestedObjectType " + k + " is not a defined value (RFC 5755 sec. 4.1)");
78
67
  }
79
- // RFC 5755 sec. 7.3 -- a conformant AC MUST NOT use otherObjectTypes(2); the digested
80
- // object is limited to a public key or a public-key certificate, so reject it
81
- // fail-closed instead of parsing a digest whose object type is unidentifiable.
82
68
  if (k === "2") {
83
69
  throw ctx.E("attrcert/bad-digested-object-type", "otherObjectTypes(2) MUST NOT be used (RFC 5755 sec. 7.3)");
84
70
  }
85
71
  return { code: Number(v), name: ODT_NAMES[k] };
86
72
  });
87
73
 
88
- // ---- IssuerSerial / ObjectDigestInfo ---------------------------------
89
74
 
90
- // IssuerSerial ::= SEQUENCE { issuer GeneralNames, serial CertificateSerialNumber,
91
- // issuerUID UniqueIdentifier OPTIONAL } (RFC 5755 sec. 4.1). Reached as an IMPLICIT
92
- // [n] node (Holder [0] / V2Form [0]) whose tag replaces the SEQUENCE tag, so the
93
- // shape assertion is "constructed" (the tag is pinned by the enclosing trailing);
94
- // a context [n] PRIMITIVE node has no children and fails closed here.
95
75
  var ISSUER_SERIAL = schema.seq([
96
76
  schema.field("issuer", pkix.generalNames(NS, { code: "attrcert/bad-issuer-serial" })),
97
77
  schema.field("serial", schema.integerLeaf()),
@@ -108,9 +88,6 @@ var ISSUER_SERIAL = schema.seq([
108
88
  },
109
89
  });
110
90
 
111
- // ObjectDigestInfo ::= SEQUENCE { digestedObjectType ENUMERATED, otherObjectTypeID
112
- // OBJECT IDENTIFIER OPTIONAL, digestAlgorithm AlgorithmIdentifier, objectDigest BIT
113
- // STRING } (RFC 5755 sec. 4.1). otherObjectTypeID is present only for otherObjectTypes(2).
114
91
  var OBJECT_DIGEST_INFO = schema.seq([
115
92
  schema.field("digestedObjectType", DIGESTED_OBJECT_TYPE),
116
93
  schema.optional("otherObjectTypeID", schema.oidLeaf(), { whenUniversal: [TAGS.OBJECT_IDENTIFIER] }),
@@ -120,15 +97,9 @@ var OBJECT_DIGEST_INFO = schema.seq([
120
97
  assert: "constructed", code: "attrcert/bad-object-digest-info", what: "ObjectDigestInfo",
121
98
  build: function (m, ctx) {
122
99
  var t = m.fields.digestedObjectType.value;
123
- // otherObjectTypeID identifies a non-certificate object type, meaningful only with
124
- // otherObjectTypes(2) -- which RFC 5755 sec. 7.3 forbids (rejected at the leaf above) --
125
- // so a present otherObjectTypeID is never valid here and is rejected fail-closed.
126
100
  if (m.fields.otherObjectTypeID.present) {
127
101
  throw ctx.E("attrcert/bad-object-digest-info", "otherObjectTypeID is only valid with otherObjectTypes(2), which RFC 5755 sec. 7.3 forbids");
128
102
  }
129
- // The objectDigest is a whole-octet digest over the identified object; a
130
- // non-octet-aligned BIT STRING is malformed (RFC 5755 sec. 4.1) and has no
131
- // in-tree verify layer to catch it later, so reject it at parse.
132
103
  guard.crypto.assertOctetAligned(m.fields.objectDigest.value, ctx.E, "attrcert/bad-object-digest-info", "objectDigest");
133
104
  return {
134
105
  digestedObjectType: t,
@@ -139,13 +110,7 @@ var OBJECT_DIGEST_INFO = schema.seq([
139
110
  },
140
111
  });
141
112
 
142
- // ---- Holder / AttCertIssuer / V2Form ---------------------------------
143
113
 
144
- // Holder ::= SEQUENCE { baseCertificateID [0] IMPLICIT IssuerSerial OPTIONAL,
145
- // entityName [1] IMPLICIT GeneralNames OPTIONAL, objectDigestInfo [2] IMPLICIT
146
- // ObjectDigestInfo OPTIONAL } (RFC 5755 sec. 4.1). All three are IMPLICIT + OPTIONAL;
147
- // the profile RECOMMENDS exactly one, but the parser surfaces all three (null when
148
- // absent) and does not enforce the cardinality.
149
114
  var HOLDER = schema.seq([
150
115
  schema.trailing([
151
116
  { tag: 0, name: "baseCertificateID", schema: ISSUER_SERIAL },
@@ -163,13 +128,6 @@ var HOLDER = schema.seq([
163
128
  },
164
129
  });
165
130
 
166
- // V2Form ::= SEQUENCE { issuerName GeneralNames OPTIONAL, baseCertificateID [0]
167
- // IMPLICIT IssuerSerial OPTIONAL, objectDigestInfo [1] IMPLICIT ObjectDigestInfo
168
- // OPTIONAL } (RFC 5755 sec. 4.1). Reached via the AttCertIssuer CHOICE on a context [0]
169
- // node, so the shape is "constructed". The build enforces the sec. 4.2.3 issuer
170
- // profile MUSTs: every field is syntactically OPTIONAL, but a conformant AC's
171
- // issuerName is present with one and only one GeneralName (a non-empty
172
- // directoryName) and baseCertificateID / objectDigestInfo are absent.
173
131
  var V2_FORM = schema.seq([
174
132
  schema.optional("issuerName", pkix.generalNames(NS, { code: "attrcert/bad-issuer-name" }), { whenUniversal: [TAGS.SEQUENCE] }),
175
133
  schema.trailing([
@@ -189,9 +147,6 @@ var V2_FORM = schema.seq([
189
147
  if (issuerName.names[0].tagNumber !== 4) {
190
148
  throw ctx.E("attrcert/bad-issuer-name", "the issuerName GeneralName must be a directoryName [4] (RFC 5755 sec. 4.2.3)");
191
149
  }
192
- // directoryName [4] EXPLICIT wraps exactly one Name (the shared GeneralName
193
- // grammar validated that); a zero-RDN Name is an empty DN identifying no
194
- // issuer, which sec. 4.2.3 forbids.
195
150
  var dirName = asn1.decode(issuerName.names[0].bytes).children[0];
196
151
  if (!dirName.children || dirName.children.length < 1) {
197
152
  throw ctx.E("attrcert/bad-issuer-name", "the issuerName directoryName must be a non-empty distinguished name (RFC 5755 sec. 4.2.3)");
@@ -203,10 +158,6 @@ var V2_FORM = schema.seq([
203
158
  },
204
159
  });
205
160
 
206
- // AttCertIssuer ::= CHOICE { v1Form GeneralNames, v2Form [0] IMPLICIT V2Form } (RFC
207
- // 5755 sec. 4.1). A universal SEQUENCE is the (obsolete but structurally recognizable)
208
- // v1Form, which a conformant AC MUST NOT use (sec. 4.2.3). The arm is recognized and
209
- // rejected with a precise verdict instead of mis-dispatched; a context [0] is v2Form.
210
161
  var ATT_CERT_ISSUER = schema.choice([
211
162
  { when: { tagClass: "universal", tagNumber: TAGS.SEQUENCE },
212
163
  schema: schema.decode(function (n, ctx) {
@@ -215,10 +166,7 @@ var ATT_CERT_ISSUER = schema.choice([
215
166
  { when: { tagClass: "context", tagNumber: 0 }, schema: V2_FORM },
216
167
  ], { code: "attrcert/bad-issuer" });
217
168
 
218
- // ---- validity + attributes -------------------------------------------
219
169
 
220
- // AttCertValidityPeriod ::= SEQUENCE { notBeforeTime GeneralizedTime, notAfterTime
221
- // GeneralizedTime } (RFC 5755 sec. 4.2.6).
222
170
  var VALIDITY = schema.seq([
223
171
  schema.field("notBeforeTime", GENERALIZED_TIME),
224
172
  schema.field("notAfterTime", GENERALIZED_TIME),
@@ -227,20 +175,13 @@ var VALIDITY = schema.seq([
227
175
  build: function (m) { return { notBeforeTime: m.fields.notBeforeTime.value, notAfterTime: m.fields.notAfterTime.value }; },
228
176
  });
229
177
 
230
- // attributes ::= SEQUENCE OF Attribute (RFC 5755 sec. 4.2.7), which MUST be non-empty and
231
- // each AttributeType OID unique. Order-preserving (SEQUENCE OF, not SET OF).
232
178
  var ATTRIBUTES = schema.seqOf(pkix.attribute(NS), {
233
179
  assert: "sequence", min: 1, code: "attrcert/bad-attributes", what: "attributes",
234
180
  unique: function (it) { return it.value.result.type; }, dupCode: "attrcert/duplicate-attribute",
235
181
  build: function (m) { return m.items.map(function (it) { return it.value.result; }); },
236
182
  });
237
183
 
238
- // ---- AttributeCertificateInfo / AttributeCertificate -----------------
239
184
 
240
- // AttributeCertificateInfo ::= SEQUENCE { version, holder, issuer, signature
241
- // AlgorithmIdentifier, serialNumber, attrCertValidityPeriod, attributes,
242
- // issuerUniqueID OPTIONAL, extensions OPTIONAL } (RFC 5755 sec. 4.1). The tbs body the
243
- // signed envelope wraps; the cross-field invariants live in the envelope build.
244
185
  var ACINFO = schema.seq([
245
186
  schema.field("version", VERSION),
246
187
  schema.field("holder", HOLDER),
@@ -253,24 +194,15 @@ var ACINFO = schema.seq([
253
194
  schema.optional("extensions", EXTENSIONS, { whenUniversal: [TAGS.SEQUENCE] }),
254
195
  ], { assert: "sequence", code: "attrcert/bad-acinfo", what: "AttributeCertificateInfo" });
255
196
 
256
- // AttributeCertificate ::= SEQUENCE { acinfo, signatureAlgorithm, signatureValue
257
- // BIT STRING }, the shared SIGNED envelope (RFC 5755 sec. 4.1). The AC-specific
258
- // invariants (sec. 4.2.4 sig-alg agreement, sec. 4.2.5 positive-and-<=20-octet serialNumber)
259
- // run in the build; the envelope owns the SEQUENCE-of-3 shape + signature extraction.
260
197
  var ATTRIBUTE_CERTIFICATE = pkix.signedEnvelope(NS, ACINFO, {
261
198
  code: "attrcert/not-an-attribute-certificate", what: "AttributeCertificate",
262
199
  build: function (e, ctx) {
263
200
  var acinfo = e.tbsMatch;
264
201
 
265
- // RFC 5755 sec. 4.2.4 -- the outer signatureAlgorithm MUST equal acinfo.signature.
266
202
  if (!e.outerSignatureAlgorithmBytes.equals(acinfo.fields.signature.node.bytes)) {
267
203
  throw ctx.E("attrcert/bad-signature-algorithm", "signatureAlgorithm must match AttributeCertificateInfo.signature (RFC 5755 sec. 4.2.4)");
268
204
  }
269
205
 
270
- // RFC 5755 sec. 4.2.5 -- serialNumber MUST be a positive INTEGER of at most 20 content
271
- // octets. Positive excludes both a negative (DER sign bit set) and zero (a minimal
272
- // INTEGER 0 is a single 0x00 octet, and the codec already rejected any non-minimal
273
- // zero). Surface it lossless (BigInt) + as hex.
274
206
  var serialNode = acinfo.fields.serialNumber.node;
275
207
  var sc = serialNode.content;
276
208
  if (sc.length === 0 || (sc[0] & 0x80) !== 0 || (sc.length === 1 && sc[0] === 0)) {
@@ -280,22 +212,14 @@ var ATTRIBUTE_CERTIFICATE = pkix.signedEnvelope(NS, ACINFO, {
280
212
  throw ctx.E("attrcert/bad-serial-number", "serialNumber must not exceed 20 content octets (RFC 5755 sec. 4.2.5)");
281
213
  }
282
214
 
283
- // AttCertIssuer is a CHOICE whose v1Form arm rejects at the leaf (sec. 4.2.3), so
284
- // the surviving arm is always v2Form. The { form, v2Form, v1Form } shape is
285
- // kept stable for consumers keying off `form`.
286
215
  var issuer = { form: "v2Form", v2Form: acinfo.fields.issuer.value.result, v1Form: null };
287
216
 
288
- // RFC 5755 sec. 4.4 -- decode each attribute's value(s) additively: a recognized attribute type
289
- // gains `decoded` (parallel to `values`); an unrecognized type falls back to { opaque, bytes } so
290
- // the parse never fails on an unknown attribute, and a recognized-but-malformed value fails closed.
291
217
  var attributes = acinfo.fields.attributes.value.result;
292
218
  attributes.forEach(function (a) {
293
219
  var dec = _ATTR_VALUE_DECODERS[a.type];
294
220
  a.decoded = a.values.map(function (v) { return dec ? dec(v) : { opaque: true, bytes: v }; });
295
221
  });
296
222
 
297
- // RFC 5755 sec. 4.3 -- decode each AC extension additively (extensions[i].decoded), same opaque
298
- // fallback + fail-closed-on-malformed contract as the attributes above.
299
223
  var extField = acinfo.fields.extensions;
300
224
  var extensions = (extField && extField.present) ? extField.value.result : [];
301
225
  extensions.forEach(function (x) {
@@ -304,7 +228,7 @@ var ATTRIBUTE_CERTIFICATE = pkix.signedEnvelope(NS, ACINFO, {
304
228
  });
305
229
 
306
230
  return {
307
- version: acinfo.fields.version.value, // 2
231
+ version: acinfo.fields.version.value,
308
232
  holder: acinfo.fields.holder.value.result,
309
233
  issuer: issuer,
310
234
  signatureAlgorithm: e.signatureAlgorithm,
@@ -321,7 +245,6 @@ var ATTRIBUTE_CERTIFICATE = pkix.signedEnvelope(NS, ACINFO, {
321
245
  },
322
246
  });
323
247
 
324
- // ---- parse -----------------------------------------------------------
325
248
 
326
249
  /**
327
250
  * @primitive pki.schema.attrcert.parse
@@ -365,23 +288,13 @@ function _legacyV1Error() {
365
288
 
366
289
  function _parseAc(input) {
367
290
  var root = pkix.decodeRoot(pkix.coerceToDer(input, PARSE_OPTS), PARSE_OPTS);
368
- // A well-formed legacy AttributeCertificateV1 gets the advertised, stable
369
- // attrcert/legacy-v1-not-supported on the DIRECT path too -- not a low-level asn1/*
370
- // tag error from attempting the v2 walk -- so a direct caller of this entry sees the
371
- // same error family for the recognized-but-deferred form as the orchestrator does.
372
291
  if (matchesV1(root)) throw _legacyV1Error();
373
292
  return schema.walk(ATTRIBUTE_CERTIFICATE, root, NS).result;
374
293
  }
375
294
 
376
- // Recording, because pki.attrcert.verify reaches a verdict from this result: the signed byte range,
377
- // the holder the privileges attach to and the attributes themselves are separate properties here,
378
- // so the record is what binds them to one another.
379
295
  var parse = guard.parsed.recordingParser("attributeCertificate", _parseAc,
380
296
  AttrCertError, "attrcert/bad-input", "an attribute certificate");
381
297
 
382
- // The obsolete X.509-1997 AttributeCertificateV1 (RFC 5652 sec. 10.2) is recognized and
383
- // deferred: decode the envelope (so a malformed input still fails as bad DER), then
384
- // throw the precise diagnostic rather than routing it to a wrong format.
385
298
  function parseV1(input) {
386
299
  pkix.decodeRoot(pkix.coerceToDer(input, PARSE_OPTS), PARSE_OPTS);
387
300
  throw _legacyV1Error();
@@ -440,11 +353,6 @@ function pemDecode(text, label) { return pkix.pemDecode(text, label === null ? n
440
353
  */
441
354
  function pemEncode(der, label) { return pkix.pemEncode(der, label || "ATTRIBUTE CERTIFICATE", PemError); }
442
355
 
443
- // matches(root): a v2 AttributeCertificate is the signed-envelope trio whose acinfo
444
- // LEADS WITH a bare universal INTEGER version (== v2 = 1, NOT the x509 [0] EXPLICIT
445
- // wrapper) and whose attrCertValidityPeriod at children[5] is a SEQUENCE of exactly
446
- // two GeneralizedTime (RFC 5755 sec. 4.2.6 forbids UTCTime) -- a marker no cert / CRL /
447
- // CSR presents at that position. Disjoint from matchesV1 by the children[0] tag class.
448
356
  function matches(root) {
449
357
  var acinfo = pkix.signedEnvelopeTbs(root);
450
358
  if (!acinfo) return false;
@@ -457,11 +365,6 @@ function matches(root) {
457
365
  return v.children.every(function (t) { return schema.isUniversal(t, TAGS.GENERALIZED_TIME); });
458
366
  }
459
367
 
460
- // matchesV1(root): the obsolete AttributeCertificateV1 -- its acInfo (version DEFAULT
461
- // v1 OMITTED) LEADS WITH the subject CHOICE (a context [0]/[1]), and its children[1]
462
- // is the issuer GeneralNames (a universal SEQUENCE). The children[1] == SEQUENCE test
463
- // keeps it disjoint from a v3 certificate (whose [0] EXPLICIT version is followed by
464
- // an INTEGER serialNumber), so v1-vs-cert dispatch is order-independent.
465
368
  function matchesV1(root) {
466
369
  var acinfo = pkix.signedEnvelopeTbs(root);
467
370
  if (!acinfo) return false;
@@ -471,12 +374,6 @@ function matchesV1(root) {
471
374
  return schema.isUniversal(k[1], TAGS.SEQUENCE);
472
375
  }
473
376
 
474
- // ---- RFC 5755 sec. 4.4 attribute-value decoders ----------------------
475
- // A per-attribute-type decoder table (mirroring pkix.certExtensionDecoders): each takes the raw
476
- // AttributeValue TLV Buffer and returns a structured value, throwing a typed attrcert/bad-* error on
477
- // any non-conformant shape. Composes pkix's shared imperative helpers + generalName/generalNames.
478
- // A single GeneralName decodes as the walk OBJECT itself (gn.tagNumber / gn.value); generalNames
479
- // (plural) returns { names:[...] } on .result.
480
377
  var _AV = pkix._decodeHelpers(NS);
481
378
  var _decodeTop = _AV.decodeTop, _seqChildren = _AV.seqChildren, _readInt = _AV.readInt, _Oav = _AV.O;
482
379
  var _GN = pkix.generalName(NS, { decodeValue: true, code: "attrcert/bad-general-name" });
@@ -492,19 +389,11 @@ function _oneGN(node, code) {
492
389
  return { tagNumber: gn.tagNumber, value: gn.value };
493
390
  }
494
391
 
495
- // readGeneralName(der) -> { tagNumber, value }, the shape every GeneralName in a parsed attribute
496
- // certificate is surfaced in.
497
- //
498
- // @internal -- exported so a verifier comparing a caller's GeneralName against one this module
499
- // decoded puts BOTH sides through this one decoder. A second decoder would be a second set of
500
- // per-form conventions, and a comparison whose two halves were produced by different rules is a
501
- // comparison of the rules rather than of the names.
392
+ // @internal
502
393
  function readGeneralName(der, code) {
503
394
  return _oneGN(asn1.decode(der), code || "attrcert/bad-input");
504
395
  }
505
396
 
506
- // SvceAuthInfo ::= SEQUENCE { service GeneralName, ident GeneralName, authInfo OCTET STRING OPTIONAL }
507
- // -- authenticationInfo (sec. 4.4.1) allows authInfo; accessIdentity (sec. 4.4.2) MUST omit it.
508
397
  function _svceAuthInfo(authInfoAllowed, code) {
509
398
  return function (buf) {
510
399
  var kids = _seqChildren(buf, code, "SvceAuthInfo");
@@ -521,8 +410,6 @@ function _svceAuthInfo(authInfoAllowed, code) {
521
410
  };
522
411
  }
523
412
 
524
- // IetfAttrSyntax ::= SEQUENCE { policyAuthority [0] IMPLICIT GeneralNames OPTIONAL,
525
- // values SEQUENCE OF CHOICE { octets OCTET STRING, oid OBJECT IDENTIFIER, string UTF8String } }
526
413
  function _ietfAttrSyntax(buf) {
527
414
  var C = "attrcert/bad-ietf-attr";
528
415
  var kids = _seqChildren(buf, C, "IetfAttrSyntax");
@@ -544,7 +431,6 @@ function _ietfAttrSyntax(buf) {
544
431
  return { policyAuthority: policyAuthority, values: values, homogeneous: Object.keys(kinds).length === 1 };
545
432
  }
546
433
 
547
- // RoleSyntax ::= SEQUENCE { roleAuthority [0] IMPLICIT GeneralNames OPTIONAL, roleName [1] EXPLICIT GeneralName }
548
434
  function _role(buf) {
549
435
  var C = "attrcert/bad-role";
550
436
  var kids = _seqChildren(buf, C, "RoleSyntax");
@@ -557,9 +443,6 @@ function _role(buf) {
557
443
  return { roleAuthority: roleAuthority, roleName: _oneGN(rn.children[0], C) };
558
444
  }
559
445
 
560
- // Clearance ::= SEQUENCE { policyId OBJECT IDENTIFIER, classList ClassList DEFAULT {unclassified},
561
- // securityCategories SET OF SecurityCategory OPTIONAL }.
562
- // ClassList ::= BIT STRING { unmarked(0), unclassified(1), restricted(2), confidential(3), secret(4), topSecret(5) }.
563
446
  var _CLASSLIST_NAMES = ["unmarked", "unclassified", "restricted", "confidential", "secret", "topSecret"];
564
447
  function _decodeClassList(node, C) {
565
448
  var bs;
@@ -574,7 +457,6 @@ function _decodeClassList(node, C) {
574
457
  }
575
458
  return { names: names, flags: flags, reservedBits: reserved };
576
459
  }
577
- // SecurityCategory ::= SEQUENCE { type [0] IMPLICIT OBJECT IDENTIFIER, value [1] EXPLICIT ANY }.
578
460
  function _securityCategory(node, C) {
579
461
  if (!_isU(node, TAGS.SEQUENCE) || !node.children || node.children.length !== 2) throw NS.E(C, "a SecurityCategory must be a SEQUENCE of a type and a value");
580
462
  var typeNode = node.children[0], valueNode = node.children[1];
@@ -589,7 +471,7 @@ function _clearance(buf) {
589
471
  if (!kids.length || kids.length > 3) throw NS.E(C, "Clearance must be a SEQUENCE { policyId, classList?, securityCategories? }");
590
472
  if (!_isU(kids[0], TAGS.OBJECT_IDENTIFIER)) throw NS.E(C, "Clearance policyId must be an OBJECT IDENTIFIER");
591
473
  var policyId; try { policyId = asn1.read.oid(kids[0]); } catch (e) { throw NS.E(C, "Clearance policyId must be an OBJECT IDENTIFIER", e); }
592
- var classList = { names: ["unclassified"], flags: { unclassified: true }, reservedBits: [] }, i = 1; // DEFAULT {unclassified}
474
+ var classList = { names: ["unclassified"], flags: { unclassified: true }, reservedBits: [] }, i = 1;
593
475
  if (kids[i] && _isU(kids[i], TAGS.BIT_STRING)) {
594
476
  classList = _decodeClassList(kids[i], C);
595
477
  if (classList.names.length === 1 && classList.flags.unclassified && !classList.reservedBits.length) {
@@ -611,21 +493,13 @@ function _clearance(buf) {
611
493
  var _ATTR_VALUE_DECODERS = {};
612
494
  _ATTR_VALUE_DECODERS[_Oav("role")] = _role;
613
495
  _ATTR_VALUE_DECODERS[_Oav("clearance")] = _clearance;
614
- // RFC 5755 sec. 4.4.6 requires decoding the legacy RFC 3281 id-at-clearance too (the X.501
615
- // selected-attribute-types arc, an alias of "clearance" -- built from arcs, never a dotted literal).
616
496
  _ATTR_VALUE_DECODERS[oid.fromArcs([2, 5, 1, 5, 55])] = _clearance;
617
497
  _ATTR_VALUE_DECODERS[_Oav("authenticationInfo")] = _svceAuthInfo(true, "attrcert/bad-svce-auth-info");
618
498
  _ATTR_VALUE_DECODERS[_Oav("accessIdentity")] = _svceAuthInfo(false, "attrcert/bad-access-identity");
619
499
  _ATTR_VALUE_DECODERS[_Oav("chargingIdentity")] = _ietfAttrSyntax;
620
500
  _ATTR_VALUE_DECODERS[_Oav("group")] = _ietfAttrSyntax;
621
501
 
622
- // ---- RFC 5755 sec. 4.3 AC-extension decoders -------------------------
623
- // A per-extension-OID decoder table for the AC-specific extensions (kept in the AC domain, not the
624
- // shared cert-extension table, because Targets/TargetCert reuse the local IssuerSerial). Each takes
625
- // the raw extnValue content Buffer and returns a structured value, fail-closed with a typed error.
626
502
 
627
- // AuditIdentity ::= OCTET STRING (sec. 4.3.1) -- an opaque audit tag, unconstrained (no SIZE), so an
628
- // empty OCTET STRING (04 00) is valid; only the OCTET STRING type is enforced.
629
503
  function _acAuditIdentity(buf) {
630
504
  var C = "attrcert/bad-audit-identity";
631
505
  var n = _decodeTop(buf, C, "AuditIdentity");
@@ -633,8 +507,6 @@ function _acAuditIdentity(buf) {
633
507
  return Buffer.concat([asn1.read.octetString(n)]);
634
508
  }
635
509
 
636
- // NoRevAvail syntax is NULL (sec. 4.3.6: '0500'H is the DER encoding) -- the extnValue OCTET STRING
637
- // contains a DER NULL. An empty or any-other-shape value is malformed and fails closed.
638
510
  function _noRevAvail(buf) {
639
511
  var C = "attrcert/bad-no-rev-avail";
640
512
  var n = _decodeTop(buf, C, "NoRevAvail");
@@ -642,8 +514,6 @@ function _noRevAvail(buf) {
642
514
  return { noRevAvail: true };
643
515
  }
644
516
 
645
- // Target ::= CHOICE { targetName [0] GeneralName, targetGroup [1] GeneralName, targetCert [2] TargetCert }.
646
- // [0]/[1] wrap a GeneralName CHOICE (EXPLICIT); [2] is an IMPLICIT TargetCert SEQUENCE.
647
517
  function _acTargetCert(node, C) {
648
518
  if (!node.children || !node.children.length) throw NS.E(C, "a targetCert [2] must be a non-empty TargetCert SEQUENCE");
649
519
  var out = { kind: "targetCert", targetCertificate: null, targetName: null, certDigestInfo: null }, i = 0;
@@ -664,14 +534,10 @@ function _acTarget(node, C, allowTargetCert) {
664
534
  }
665
535
  throw NS.E(C, "a Target must be [0] targetName, [1] targetGroup, or [2] targetCert");
666
536
  }
667
- // Targets ::= SEQUENCE OF Target -- decode a Targets SEQUENCE node into an array of Target.
668
537
  function _acDecodeTargets(node, C, allowTargetCert) {
669
538
  if (!_isU(node, TAGS.SEQUENCE) || !node.children || !node.children.length) throw NS.E(C, "Targets must be a non-empty SEQUENCE OF Target");
670
539
  return node.children.map(function (t) { return _acTarget(t, C, allowTargetCert); });
671
540
  }
672
- // Both targetInformation (sec. 4.3.2) and ProxyInfo (sec. 7.4) are SEQUENCE OF Targets -- an outer
673
- // SEQUENCE whose every element is itself a Targets (SEQUENCE OF Target). A conforming issuer emits one
674
- // Targets, but users MUST accept several. proxying additionally forbids the targetCert [2] alternative.
675
541
  function _seqOfTargets(buf, C, allowTargetCert) {
676
542
  var kids = _seqChildren(buf, C, "SEQUENCE OF Targets");
677
543
  if (!kids.length) throw NS.E(C, "a SEQUENCE OF Targets must be non-empty");
@@ -680,9 +546,6 @@ function _seqOfTargets(buf, C, allowTargetCert) {
680
546
  function _targetInformation(buf) { return _seqOfTargets(buf, "attrcert/bad-targets", true); }
681
547
  function _acProxying(buf) { return _seqOfTargets(buf, "attrcert/bad-proxy-info", false); }
682
548
 
683
- // AAControls ::= SEQUENCE { pathLenConstraint INTEGER (0..MAX) OPTIONAL, permittedAttrs [0] AttrSpec
684
- // OPTIONAL, excludedAttrs [1] AttrSpec OPTIONAL, permitUnSpecified BOOLEAN DEFAULT TRUE }.
685
- // AttrSpec ::= SEQUENCE OF OBJECT IDENTIFIER (the [0]/[1] IMPLICIT tag replaces the SEQUENCE tag).
686
549
  function _acAttrSpec(node, C) {
687
550
  if (!node.children) throw NS.E(C, "an AttrSpec must be a SEQUENCE OF OBJECT IDENTIFIER");
688
551
  return node.children.map(function (o) {
@@ -714,12 +577,7 @@ _AC_EXT_DECODERS[_Oav("noRevAvail")] = _noRevAvail;
714
577
  _AC_EXT_DECODERS[_Oav("aaControls")] = _aaControls;
715
578
  _AC_EXT_DECODERS[_Oav("acProxying")] = _acProxying;
716
579
 
717
- // @internal -- validate a pre-encoded AC attribute value / AC extension value against the SAME decoder
718
- // the parser runs, so the attrcert-sign escape hatches (a caller's pre-encoded Attribute / Extension DER)
719
- // cannot embed a structurally-malformed recognized value the strict parser would then reject. `type` /
720
- // `extnOid` are dotted-OID strings; `valueDer` / `extnValueDer` are the raw AttributeValue / extnValue
721
- // content Buffers (exactly what the parse loop passes). An unrecognized type returns null (stays opaque,
722
- // no validation); a recognized-but-malformed value throws the frozen attrcert/bad-* code.
580
+ // @internal
723
581
  function validateAttributeValue(type, valueDer) {
724
582
  var dec = _ATTR_VALUE_DECODERS[type];
725
583
  return dec ? dec(valueDer) : null;