@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.
Files changed (112) hide show
  1. package/CHANGELOG.md +27 -1
  2. package/lib/acme.js +59 -815
  3. package/lib/asn1-der.js +7 -245
  4. package/lib/attrcert-sign.js +12 -260
  5. package/lib/attrcert-verify.js +1 -7
  6. package/lib/byte-reader.js +0 -8
  7. package/lib/byte-writer.js +0 -11
  8. package/lib/cbor-det.js +0 -54
  9. package/lib/cmc-build.js +15 -357
  10. package/lib/cmc-verify.js +6 -239
  11. package/lib/cmp-build.js +41 -317
  12. package/lib/cmp-session.js +73 -760
  13. package/lib/cmp-verify.js +32 -488
  14. package/lib/cms-compress.js +3 -32
  15. package/lib/cms-decrypt.js +29 -294
  16. package/lib/cms-encrypt.js +14 -234
  17. package/lib/cms-sign.js +29 -324
  18. package/lib/cms-verify.js +9 -500
  19. package/lib/composite-kem.js +2 -102
  20. package/lib/composite-sig.js +1 -77
  21. package/lib/constants.js +0 -249
  22. package/lib/crl-sign.js +9 -237
  23. package/lib/crl-verify.js +1 -10
  24. package/lib/crmf-sign.js +19 -198
  25. package/lib/crmf-verify.js +1 -12
  26. package/lib/csr-sign.js +3 -34
  27. package/lib/csr-verify.js +1 -12
  28. package/lib/ct.js +28 -253
  29. package/lib/edwards-point.js +10 -44
  30. package/lib/est.js +28 -764
  31. package/lib/framework-error.js +4 -182
  32. package/lib/guard-all.js +1 -58
  33. package/lib/guard-async.js +1 -36
  34. package/lib/guard-bytes.js +6 -650
  35. package/lib/guard-compress.js +5 -102
  36. package/lib/guard-crypto.js +1 -40
  37. package/lib/guard-der.js +2 -93
  38. package/lib/guard-encoding.js +2 -60
  39. package/lib/guard-header.js +1 -36
  40. package/lib/guard-identifier.js +7 -531
  41. package/lib/guard-intrinsic.js +1 -150
  42. package/lib/guard-json.js +10 -73
  43. package/lib/guard-limits.js +1 -77
  44. package/lib/guard-list.js +1 -49
  45. package/lib/guard-name.js +3 -209
  46. package/lib/guard-parsed.js +7 -335
  47. package/lib/guard-range.js +1 -71
  48. package/lib/guard-secret.js +1 -102
  49. package/lib/guard-text.js +1 -64
  50. package/lib/guard-time.js +1 -97
  51. package/lib/hpke.js +3 -105
  52. package/lib/http-digest.js +14 -142
  53. package/lib/http-retry-after.js +1 -47
  54. package/lib/http-transport.js +21 -131
  55. package/lib/inspect.js +30 -284
  56. package/lib/ip-utils.js +6 -47
  57. package/lib/jose.js +7 -142
  58. package/lib/key.js +2 -67
  59. package/lib/lint.js +9 -194
  60. package/lib/merkle.js +1 -27
  61. package/lib/mime.js +9 -82
  62. package/lib/ocsp-request-verify.js +1 -14
  63. package/lib/ocsp-verify.js +1 -82
  64. package/lib/ocsp.js +11 -169
  65. package/lib/oid.js +5 -337
  66. package/lib/path-validate.js +103 -1492
  67. package/lib/pbes2.js +2 -89
  68. package/lib/pkcs12-build.js +31 -379
  69. package/lib/pki-build.js +64 -290
  70. package/lib/rc2.js +2 -18
  71. package/lib/rfc3339.js +4 -27
  72. package/lib/scep.js +140 -286
  73. package/lib/schema-all.js +0 -122
  74. package/lib/schema-attrcert.js +4 -146
  75. package/lib/schema-c509.js +153 -802
  76. package/lib/schema-cmc.js +5 -220
  77. package/lib/schema-cmp.js +2 -223
  78. package/lib/schema-cms.js +13 -427
  79. package/lib/schema-crl.js +5 -68
  80. package/lib/schema-crmf.js +6 -167
  81. package/lib/schema-csr.js +1 -54
  82. package/lib/schema-csrattrs.js +2 -87
  83. package/lib/schema-engine.js +0 -152
  84. package/lib/schema-ocsp.js +0 -117
  85. package/lib/schema-pkcs12.js +2 -93
  86. package/lib/schema-pkcs8.js +3 -35
  87. package/lib/schema-pkix.js +24 -655
  88. package/lib/schema-smime.js +0 -54
  89. package/lib/schema-tsp.js +3 -99
  90. package/lib/schema-x509.js +4 -63
  91. package/lib/shbs.js +11 -95
  92. package/lib/sign-scheme.js +2 -97
  93. package/lib/sigstore.js +9 -169
  94. package/lib/sleep.js +2 -8
  95. package/lib/smime.js +15 -408
  96. package/lib/tls-cert-compress.js +0 -62
  97. package/lib/trust.js +19 -185
  98. package/lib/tsp-sign.js +16 -270
  99. package/lib/validator-all.js +1 -30
  100. package/lib/validator-attcert.js +2 -46
  101. package/lib/validator-cose.js +2 -153
  102. package/lib/validator-keydesc.js +1 -37
  103. package/lib/validator-sig.js +1 -46
  104. package/lib/validator-tls.js +1 -88
  105. package/lib/validator-tpm.js +19 -122
  106. package/lib/verify-seam.js +1 -24
  107. package/lib/webauthn-mds.js +3 -400
  108. package/lib/webauthn.js +12 -833
  109. package/lib/webcrypto.js +5 -485
  110. package/lib/x509-sign.js +4 -108
  111. package/package.json +1 -1
  112. package/sbom.cdx.json +6 -6
package/lib/cmc-build.js CHANGED
@@ -1,44 +1,22 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  // Copyright (c) blamejs contributors
3
3
  "use strict";
4
- //
5
- // @internal -- the pki.cmc.build implementation. So the pki.cmc namespace has one @module home,
4
+ // @internal
6
5
  // the operator-facing @module pki.cmc + the @primitive pki.cmc.build documentation block live in
7
- // cmc-verify.js, which re-exports this build function.
8
- //
9
- /**
10
- * RFC 5272 Full PKI Request production -- the producing half of `pki.cmc`.
11
- *
12
- * `build(spec, signer, opts)` assembles a PKIData (all four sequences, each
13
- * possibly empty), allocates a unique body part identifier for every element,
14
- * attaches controls through an OID-keyed encoder registry that enforces the RFC
15
- * 6402 placement rules, computes the Identity Proof / POP Link witnesses over the
16
- * bytes it is about to EMIT, and signs the result through `pki.cms.sign` with
17
- * `eContentType: id-cct-PKIData`.
18
- *
19
- * The witness rule is the load-bearing one. RFC 5272 sec. 6.2.1 step 1 says the
20
- * value to be validated is "The PKIData reqSequence field (encoded exactly as it
21
- * appears in the Full PKI Request including the sequence type and length)". So
22
- * the reqSequence TLV is built once and both the message and the witness are
23
- * derived from that single buffer; computing the witness over a second
24
- * serialization would agree with itself while disagreeing with the wire the
25
- * moment any encoding detail differed.
26
- */
6
+
27
7
 
28
8
  var nodeCrypto = require("node:crypto");
29
9
  var asn1 = require("./asn1-der");
30
- var pkiBuild = require("./pki-build"); // reqDenseArray: reject a sparse/nullish caller array as a typed cmc/bad-input
31
- var csr = require("./schema-csr"); // to read the Subject Key Identifier a tcr request declares
32
- require("./path-validate"); // side-effect: path-validate injects its signature engine into csr-verify at load
33
- var csrVerify = require("./csr-verify"); // verify an embedded tcr request's proof-of-possession before signing it
34
- var crmf = require("./schema-crmf"); // ... and the one a crm request declares
35
- var cmcFmt = require("./schema-cmc"); // to read the assembled message back before signing it
10
+ var pkiBuild = require("./pki-build");
11
+ var csr = require("./schema-csr");
12
+ require("./path-validate");
13
+ var csrVerify = require("./csr-verify");
14
+ var crmf = require("./schema-crmf");
15
+ var cmcFmt = require("./schema-cmc");
36
16
  var oid = require("./oid");
37
17
  var cmsSign = require("./cms-sign");
38
18
  var guard = require("./guard-all");
39
19
  var intrinsic = require("./guard-intrinsic");
40
- // Own-key membership through an operation taken at load. Written out, the question reads two
41
- // replaceable properties to answer one thing, and here it decides which controls a request carries.
42
20
  var _hasOwn = intrinsic.hasOwn;
43
21
  var frameworkError = require("./framework-error");
44
22
 
@@ -53,44 +31,18 @@ var OID_IDENTIFICATION = O("id-cmc-identification");
53
31
  var OID_SHA256 = O("sha256");
54
32
  var OID_HMAC_SHA256 = O("hmacWithSHA256");
55
33
 
56
- // The identity-bearing controls a renewal must not carry: RFC 5272 sec. 3.2 (a),
57
- // "The Identification and Identity Proof controls are absent."
58
- //
59
- // "Identity Proof" covers both versions: the original id-cmc-identityProof (sec.
60
- // 6.2.2) and identityProofV2 (sec. 6.2.1). Listing only V2 would leave a renewal
61
- // able to carry the v1 control, which is the same nonconformance the rule names.
62
34
  var RENEWAL_FORBIDDEN = {};
63
35
  RENEWAL_FORBIDDEN[OID_IDENTIFICATION] = "Identification";
64
36
  RENEWAL_FORBIDDEN[O("id-cmc-identityProof")] = "Identity Proof";
65
37
  RENEWAL_FORBIDDEN[OID_IDENTITY_PROOF_V2] = "Identity Proof V2";
66
38
 
67
- // RFC 6402 sec. 2.6: responseBody appears only in a PKIResponse. Enforced at
68
- // build time as well as at parse, so a caller cannot emit a message its own
69
- // decoder would refuse.
70
39
  var OID_RESPONSE_BODY = O("id-cmc-responseBody");
71
40
 
72
- // RFC 5272 sec. 6.2.1 says "Implementations MUST be able to support tokens at
73
- // least 16 characters long", a requirement on what an implementation must be
74
- // able to accept, not a floor every token has to clear. Reading it as a minimum
75
- // inverts it, and would refuse a shorter secret a CA legitimately provisioned.
76
- // The shared secret's strength is the deploying CA's policy; what this layer can
77
- // say is that an empty string is not a credential at all.
78
- // PL1: R "SHOULD be at least 512 bits in length".
79
41
  var POP_LINK_RANDOM_BYTES = 64;
80
42
 
81
- // The spec fields pki.cmc.build understands. Anything else is a caller mistake
82
- // caught at the entry point, never silently dropped from the message.
83
43
  var KNOWN_SPEC_KEYS = {
84
44
  requests: 1, controls: 1, cmsSequence: 1, otherMsgSequence: 1,
85
- // `identification` is deliberately absent: the Identification control is attached through
86
- // identityProof.identity, which is what emits it. Listing a key nothing reads
87
- // would recreate the very hole this table closes, accepted at the door and
88
- // silently absent from the message.
89
45
  identityProof: 1, popLink: 1, renewal: 1,
90
- // The exchange binding (RFC 5272 sec. 6.6 / 6.4). First-class here because
91
- // pki.cmc.verify names these same three when checking the response: a builder
92
- // that made the caller hand-encode them while the verifier took them by name is
93
- // the asymmetry that lets a request ship with no replay defense.
94
46
  transactionId: 1, senderNonce: 1, dataReturn: 1,
95
47
  };
96
48
 
@@ -98,22 +50,11 @@ var OID_TRANSACTION_ID = O("id-cmc-transactionId");
98
50
  var OID_SENDER_NONCE = O("id-cmc-senderNonce");
99
51
  var OID_DATA_RETURN = O("id-cmc-dataReturn");
100
52
 
101
- // AlgorithmIdentifier { OID } with no parameters: the form the MAC / hash
102
- // algorithm identifiers in these two controls take.
103
53
  function algId(o) { return b.sequence([b.oid(o)]); }
104
54
 
105
- // ---- body part identity ---------------------------------------------
106
55
 
107
- // RFC 5272 sec. 3.2.2: identifiers are unique across the whole message and 0 is
108
- // reserved for the reference to the current PKIData. The allocator therefore
109
- // starts at 1, and a caller-supplied value is validated, never adjusted;
110
- // silently renumbering would break any control that already references it.
111
56
  function makeIdAllocator() {
112
57
  var used = Object.create(null);
113
- // Reserved ahead of allocation and not yet consumed by the element that owns
114
- // it. Kept distinct from `used` so an element re-claiming its own reservation
115
- // is a no-op, while a second element asking for the same value is still the
116
- // duplicate the rule forbids.
117
58
  var pending = Object.create(null);
118
59
  var next = 1;
119
60
  function assertValid(requested, what) {
@@ -143,7 +84,7 @@ function makeIdAllocator() {
143
84
  return next;
144
85
  }
145
86
  assertValid(requested, what);
146
- if (pending[requested]) { delete pending[requested]; return requested; } // consume our own reservation
87
+ if (pending[requested]) { delete pending[requested]; return requested; }
147
88
  if (used[requested]) {
148
89
  throw E("cmc/bad-input",
149
90
  "bodyPartID " + requested + " is used more than once; identifiers MUST be unique within a single PKIData (RFC 5272 sec. 3.2.2)");
@@ -154,28 +95,8 @@ function makeIdAllocator() {
154
95
  };
155
96
  }
156
97
 
157
- // ---- requests --------------------------------------------------------
158
-
159
- // TaggedRequest ::= CHOICE { tcr [0], crm [1], orm [2] }, IMPLICIT tags. For the
160
- // crm arm the identity is the CertReqMsg's own certReqId (sec. 3.2.2), so it is
161
- // read back out of the supplied message and never allocated; allocating one
162
- // would put a second, contradictory identifier on the wire.
163
- // The identifier a request fixes, or null when it leaves the choice to us. Read
164
- // in a pre-pass so every caller-determined value is reserved before a single
165
- // generated one is handed out; otherwise acceptance depends on the order the
166
- // caller happened to write the list in, which is not a property of the message.
167
- // The fields a request descriptor understands -- the same door KNOWN_SPEC_KEYS
168
- // closes on the spec, on the objects nested inside it. A misspelled `bodyPartID`
169
- // is not a harmless extra: the request would be auto-allocated a DIFFERENT
170
- // identifier while a control the caller wrote still references the intended one,
171
- // and the builder would sign a message whose halves point at different requests.
98
+
172
99
  var KNOWN_REQUEST_KEYS = { tcr: 1, crm: 1, orm: 1, bodyPartID: 1 };
173
- // The same door on the other descriptors nested in a spec. A control's identifier
174
- // is always allocated, so a `bodyPartID` written on one is ignored outright; and a
175
- // misspelled `identity` does not merely go missing: the Identification control
176
- // it would have emitted is what tells the server to derive the Identity Proof key
177
- // from the secret and the identity, so the message would carry a witness no
178
- // conforming server can reproduce.
179
100
  var KNOWN_CONTROL_KEYS = { type: 1, value: 1 };
180
101
  var KNOWN_IDENTITY_PROOF_KEYS = { identity: 1, secret: 1 };
181
102
  var KNOWN_POP_LINK_KEYS = { secret: 1 };
@@ -192,12 +113,6 @@ function fixedRequestId(req, index) {
192
113
  "each request names exactly one of tcr / crm / orm, got " + (arms.length ? arms.join(" + ") : "none") +
193
114
  " (request " + index + ")");
194
115
  }
195
- // A crm arm's identity is its CertReqMsg's own certReqId, so it is always fixed:
196
- // there is nothing to allocate and nothing that may displace it. A caller who
197
- // also writes bodyPartID is stating an identity, and the only reason to state one
198
- // is that something already references it; taking the certReqId silently would
199
- // sign a message whose control points at no request in it. Equal is accepted,
200
- // since the caller is agreeing with the message, not overriding it.
201
116
  if (req.crm != null) {
202
117
  var crmId = _certReqIdOf(_asCertReqMsg(_der(req.crm, "a crm CertReqMsg")));
203
118
  if (req.bodyPartID != null && _asBigInt(req.bodyPartID, "a crm request bodyPartID") !== BigInt(crmId)) {
@@ -210,23 +125,12 @@ function fixedRequestId(req, index) {
210
125
  return req.bodyPartID == null ? null : req.bodyPartID;
211
126
  }
212
127
 
213
- // Verify each embedded PKCS#10 (tcr) request's proof-of-possession before the message is signed. A CSR
214
- // whose self-signature does not verify under its own subjectPKInfo is one the CA will reject (RFC 5272
215
- // sec. 4.1), so refusing it here -- through the shared inbound-PoP seam pki.csr.verify uses -- keeps the
216
- // producer from signing a request that cannot be acted on, the same "do not sign what the recipient
217
- // refuses" discipline the assembled-message readback already applies. The crm / orm arms carry their own
218
- // POP structures (CRMF POPOSigningKey etc.), validated by their own parse; only tcr is a bare CSR.
219
- // `await`, not `.then`: the PoP verdict is read through the native promise job, not the replaceable
220
- // Promise.prototype.then a co-resident could swap to force `ok` true and slip an unverified request past.
221
128
  async function _assertTcrPops(requests) {
222
129
  for (var i = 0; i < requests.length; i++) {
223
130
  if (requests[i] && requests[i].tcr != null) await _assertOneTcrPop(requests[i].tcr, i);
224
131
  }
225
132
  }
226
133
  async function _assertOneTcrPop(tcr, i) {
227
- // encodeRequest already validated this tcr's structure synchronously (it runs before this async pass),
228
- // so the re-parse here only recovers the parse the PoP check verifies over; on the shipped path it
229
- // cannot fail, and a sync throw surfaces as a rejection through build's async boundary regardless.
230
134
  var parsed = csr.parse(_der(tcr, "a tcr certificationRequest"));
231
135
  if (!(await csrVerify.verifyCsrSignature(parsed))) {
232
136
  throw E("cmc/bad-popo", "a tcr request [" + i + "] failed its proof-of-possession: the PKCS#10 signature does not verify under the request's own subject public key (RFC 5272 sec. 6.3), so a CA would reject it -- refusing it here rather than signing it");
@@ -235,11 +139,6 @@ async function _assertOneTcrPop(tcr, i) {
235
139
 
236
140
  function encodeRequest(req, ids, index) {
237
141
  if (req.tcr != null) {
238
- // A tcr arm is a PKCS#10 CertificationRequest, so it is parsed and never
239
- // taken on the tag: the readback of the assembled message checks the CMC
240
- // structure around it, and would pass an empty SEQUENCE here as happily as a
241
- // real request. Signing a request body that is not one produces an enrollment
242
- // no CA can act on, and the producer is where that is cheap to catch.
243
142
  try { csr.parse(_der(req.tcr, "a tcr certificationRequest")); }
244
143
  catch (e) {
245
144
  throw E("cmc/bad-input", "a tcr request must be a PKCS#10 CertificationRequest: " +
@@ -250,23 +149,12 @@ function encodeRequest(req, ids, index) {
250
149
  }
251
150
  if (req.crm != null) {
252
151
  var msg = _asCertReqMsg(_der(req.crm, "a crm CertReqMsg"));
253
- // Parsed as the CertReqMsg it is, the same way a tcr is parsed as a
254
- // CertificationRequest: the readback checks the CMC structure around the
255
- // request, and would pass a SEQUENCE that merely starts like one.
256
152
  try { crmf.parse(b.sequence([msg])); }
257
153
  catch (e) {
258
154
  throw E("cmc/bad-input", "a crm request must be an RFC 4211 CertReqMsg: " +
259
155
  (e && e.message ? e.message : "it did not parse as one"), e);
260
156
  }
261
- // CLAIM, not just read. The certReqId was reserved in the pre-pass with every
262
- // other caller-determined identifier; leaving the reservation outstanding lets
263
- // a later cmsSequence or otherMsg element asking for the same number be taken
264
- // for its owner, and the message would then carry the identifier twice: a
265
- // PKIData this toolkit's own parser refuses. The tcr and orm arms already
266
- // claim; this arm is the same rule.
267
157
  var certReqId = ids.claim(_certReqIdOf(msg), "a crm request");
268
- // IMPLICIT [1]: the tag replaces the CertReqMsg SEQUENCE tag, so the content
269
- // is re-headered, not nested.
270
158
  var node = asn1.decode(msg);
271
159
  var headerLen = node.header.end - node.header.start;
272
160
  return { bodyPartID: certReqId, der: b.contextConstructed(1, node.bytes.subarray(headerLen)) };
@@ -283,18 +171,6 @@ function encodeRequest(req, ids, index) {
283
171
  };
284
172
  }
285
173
 
286
- // A TaggedRequest's crm arm carries one CertReqMsg, but `pki.crmf.build` returns
287
- // a CertReqMessages (SEQUENCE SIZE(1..MAX) OF CertReqMsg), which is what a
288
- // caller naturally has in hand. Both are accepted, told apart structurally:
289
- //
290
- // CertReqMsg ::= SEQUENCE { certReq CertRequest, ... } first child is a
291
- // SEQUENCE whose own first child is an INTEGER (certReqId)
292
- // CertReqMessages ::= SEQUENCE OF CertReqMsg first child is a
293
- // CertReqMsg, whose own first child is a SEQUENCE
294
- //
295
- // A CertReqMessages carrying more than one message is refused, never reduced to
296
- // its first: each CertReqMsg is its own TaggedRequest with its own identity,
297
- // so silently dropping the rest would emit a request the caller did not ask for.
298
174
  function _asCertReqMsg(der) {
299
175
  var node = asn1.decode(der);
300
176
  var first = node.children && node.children[0];
@@ -302,7 +178,7 @@ function _asCertReqMsg(der) {
302
178
  throw E("cmc/bad-input", "a crm arm must be a CertReqMsg or a CertReqMessages carrying one");
303
179
  }
304
180
  var grand = first.children[0];
305
- if (grand.tagClass === "universal" && grand.tagNumber === asn1.TAGS.INTEGER) return der; // already a CertReqMsg
181
+ if (grand.tagClass === "universal" && grand.tagNumber === asn1.TAGS.INTEGER) return der;
306
182
  if (node.children.length !== 1) {
307
183
  throw E("cmc/bad-input",
308
184
  "a crm arm carries exactly one CertReqMsg; this CertReqMessages holds " + node.children.length +
@@ -311,8 +187,6 @@ function _asCertReqMsg(der) {
311
187
  return first.bytes;
312
188
  }
313
189
 
314
- // A CertReqMsg's identity: CertReqMsg ::= SEQUENCE { certReq CertRequest, ... },
315
- // CertRequest ::= SEQUENCE { certReqId INTEGER, ... }.
316
190
  function _certReqIdOf(msg) {
317
191
  var node = asn1.decode(msg);
318
192
  var certReq = node.children && node.children[0];
@@ -323,10 +197,6 @@ function _certReqIdOf(msg) {
323
197
  return guard.range.int(v, 0n, 4294967295n, E, "cmc/bad-input", "a crm certReqId");
324
198
  }
325
199
 
326
- // A pre-encoded TaggedContentInfo / OtherMsg supplied by the caller. Only its
327
- // leading bodyPartID is read (the payload is the caller's and stays untouched),
328
- // so the identifier joins the same allocation space every other element draws
329
- // from and a collision is refused here, never discovered later by the parser.
330
200
  function _claimRawElement(el, ids, what) {
331
201
  var der = _der(el, what);
332
202
  var node = asn1.decode(der);
@@ -339,24 +209,11 @@ function _claimRawElement(el, ids, what) {
339
209
  return der;
340
210
  }
341
211
 
342
- // The binding controls have a named spec field and can also be hand-encoded into
343
- // spec.controls. Emitting both would put two of the same control in one message,
344
- // and duplicates of these three are what decide what the response must echo: two
345
- // values means no value. Also refuses two hand-encoded copies, since the same
346
- // ambiguity arrives that way.
347
212
  var BINDING_BY_OID = {};
348
213
  BINDING_BY_OID[O("id-cmc-transactionId")] = "transactionId";
349
214
  BINDING_BY_OID[O("id-cmc-senderNonce")] = "senderNonce";
350
215
  BINDING_BY_OID[O("id-cmc-dataReturn")] = "dataReturn";
351
216
 
352
- // ... and the type each one carries. The CMC parser keeps every control value raw,
353
- // so nothing downstream of the builder objects to a Transaction Identifier encoded
354
- // as an OCTET STRING. But these three are read, not carried: pki.cmc.verify
355
- // compares them against the response, and pki.est.fullcmc reads them back out of
356
- // the request before it goes out. A hand-encoded value of the wrong type therefore
357
- // signs a request that this toolkit's own client will refuse to send. The type is
358
- // checked by READING the value, so a wrong tag and a malformed encoding of the
359
- // right one are refused alike.
360
217
  var BINDING_READER = {
361
218
  transactionId: function (node) { return asn1.read.integer(node); },
362
219
  senderNonce: function (node) { return asn1.read.octetString(node); },
@@ -390,8 +247,6 @@ function _assertNoDuplicateBinding(callerControls, spec) {
390
247
  });
391
248
  }
392
249
 
393
- // A Transaction Identifier is an unbounded INTEGER on the wire; the shared authoring
394
- // guard normalizes the number-or-bigint a caller naturally has.
395
250
  function _asBigInt(v, what) { return guard.range.authoredInteger(v, E, "cmc/bad-input", what); }
396
251
 
397
252
  function _der(v, what) {
@@ -403,20 +258,7 @@ function _oidOf(v) {
403
258
  return oid.isDottedDecimal(v) ? v : O(v);
404
259
  }
405
260
 
406
- // ---- controls --------------------------------------------------------
407
-
408
- // TaggedAttribute ::= SEQUENCE { bodyPartID, attrType, attrValues SET OF ANY }.
409
- // Controls this builder will not put in a Full PKI Request. A row per control with
410
- // the reason it does not belong in this direction: id-cmc-responseBody by an
411
- // explicit RFC 6402 sec. 2.6 MUST NOT, the two status controls because RFC 5272
412
- // sec. 6.1 makes them what a server emits and a client processes in a PKI Response.
413
- // a request has no verdict of its own to report, so one written here is a fabricated
414
- // answer to a question nobody asked.
415
- //
416
- // Only the BUILDER refuses these. pki.schema.cmc keeps decoding them wherever they
417
- // appear, because the spec states a placement MUST for id-cmc-responseBody alone --
418
- // refusing the rest on the wire would reject a message the ASN.1 permits, and this
419
- // decoder's job is to surface what arrived, not to judge who should have sent it.
261
+
420
262
  var REQUEST_FORBIDDEN_CONTROL = {};
421
263
  REQUEST_FORBIDDEN_CONTROL[OID_RESPONSE_BODY] =
422
264
  "id-cmc-responseBody may appear only in the control sequence of a PKIResponse (RFC 6402 sec. 2.6)";
@@ -435,14 +277,8 @@ function encodeControl(attrType, values, ids) {
435
277
  return b.sequence([b.integer(BigInt(id)), b.oid(attrType), b.set(values)]);
436
278
  }
437
279
 
438
- // ---- the witnesses ---------------------------------------------------
439
280
 
440
281
  function _assertSecret(secret, what) {
441
- // An entry-tier argument check: this tests the TYPE and whether the string is empty, and
442
- // compares no secret-dependent content. The length of a caller's own argument is already
443
- // known to that caller, so there is no secret for a timing-safe compare to protect. The
444
- // MAC comparisons this rule exists for route through guard.crypto.constantTimeEqual.
445
- // nosemgrep: pki-non-constant-time-secret-compare
446
282
  if (typeof secret !== "string" || secret.length === 0) {
447
283
  throw E("cmc/bad-input",
448
284
  what + " requires the shared secret as a non-empty string; got " +
@@ -450,13 +286,6 @@ function _assertSecret(secret, what) {
450
286
  }
451
287
  }
452
288
 
453
- // IdentifyProofV2 ::= SEQUENCE { hashAlgID, macAlgID, witness OCTET STRING }.
454
- // key = hash(shared-secret as a UTF8 string); witness = MAC(reqSequenceBytes, key).
455
- // `reqSequenceBytes` is the buffer that becomes the message's reqSequence, never
456
- // a re-encode of it (RFC 5272 sec. 6.2.1 step 1).
457
- // Tracks a buffer this module allocated that carries secret material, so the caller clears it
458
- // on every exit. The shared secret arrives as a JS string, which is immutable and cannot be
459
- // cleared; what this closes is every copy the toolkit itself makes of it.
460
289
  function _ownSecret(buf, owned) {
461
290
  owned.push(buf);
462
291
  return buf;
@@ -464,18 +293,6 @@ function _ownSecret(buf, owned) {
464
293
 
465
294
  function identityProofV2(secret, reqSequenceBytes, identity) {
466
295
  _assertSecret(secret, "an Identity Proof V2 control");
467
- // RFC 5272 sec. 6.2.3: the Identification control is OPTIONAL ("servers MAY
468
- // require" it), but when it is present the key derivation changes: "the
469
- // hash of the concatenation of the shared-secret and the UTF8 identity value
470
- // (without the type and length bytes) are hashed rather than just the
471
- // shared-secret". Same controls on the wire, different key: a producer that
472
- // emits the Identification control while hashing the secret alone computes a
473
- // witness every conforming server rejects.
474
- // Every allocation that carries the shared secret is cleared, not only the derived key.
475
- // The derivation input holds the secret in the clear, and with an identity present the
476
- // concatenation leaves two more copies of it behind: the operand and the joined buffer.
477
- // Wiping the key while those survive clears the cheapest copy and keeps the rest. The
478
- // derivation runs inside the try so a throw partway still reaches the clear.
479
296
  var owned = [];
480
297
  var key = null;
481
298
  try {
@@ -497,10 +314,6 @@ function identityProofV2(secret, reqSequenceBytes, identity) {
497
314
  }
498
315
  }
499
316
 
500
- // PopLinkWitnessV2 ::= SEQUENCE { keyGenAlgorithm, macAlgorithm, witness }.
501
- // key = keyGen(shared-secret); witness = MAC(R, key), with R carried alongside in
502
- // the POP Link Random control -- PL1 makes that control mandatory in the same
503
- // request, which is why the two are produced together and never separately.
504
317
  function popLinkWitnessV2(secret, R) {
505
318
  _assertSecret(secret, "a POP Link Witness V2 control");
506
319
  var key = nodeCrypto.createHash("sha256").update(secret, "utf8").digest();
@@ -515,10 +328,6 @@ function popLinkWitnessV2(secret, R) {
515
328
  // The operator-facing @primitive block for this function lives beside its
516
329
  // re-export in cmc-verify.js, the pki.cmc @module home.
517
330
  function build(spec, signer, opts) {
518
- // Every caller-owned argument copied at entry and released when the call settles; see the note
519
- // on the same call in x509-sign. It matters most here: the Identity Proof and POP Link witnesses
520
- // are computed over the bytes this builder is about to emit, so a spec that changed in between
521
- // would witness a different request than the one that goes out.
522
331
  return guard.bytes.fixedCall(CmcError, "cmc/bad-input", [
523
332
  [spec, "the CMC request spec"], [signer, "the signer"], [opts, "pki.cmc.build options"],
524
333
  ], _build);
@@ -530,14 +339,7 @@ async function _build(spec, signer, opts) {
530
339
  throw E("cmc/bad-input", "the CMC request spec must be an object");
531
340
  }
532
341
  if (typeof opts !== "object" || Buffer.isBuffer(opts)) throw E("cmc/bad-input", "pki.cmc.build options must be an object");
533
- // A misspelled or unsupported spec field fails open in the quietest way there is:
534
- // the message builds, is signed, and simply does not carry what was asked for.
535
- // That is worst for the exchange-binding fields below: a request built without
536
- // them has no replay defense, and pki.cmc.verify cannot enforce a binding the
537
- // client never sent, so the omission is invisible from both ends.
538
342
  guard.identifier.assertKnownKeys(spec, KNOWN_SPEC_KEYS, E, "cmc/bad-input", "unknown spec field ");
539
- // Density up front: requests is iterated by both the forEach below and the map that encodes it, and a
540
- // hole would survive either (map/forEach skip it) to reach b.sequence as a native error.
541
343
  var requests = spec.requests != null ? pkiBuild.reqDenseArray(spec.requests, "requests", E, "cmc/bad-input") : [];
542
344
  if (!Array.isArray(requests)) throw E("cmc/bad-input", "spec.requests must be an array");
543
345
  var callerControls = spec.controls || [];
@@ -545,17 +347,6 @@ async function _build(spec, signer, opts) {
545
347
 
546
348
  var ids = makeIdAllocator();
547
349
 
548
- // Every identifier the caller determines is reserved before a single generated
549
- // one is handed out. There are four sources, and reserving only some of them
550
- // makes acceptance depend on the order the caller wrote things in, not on
551
- // the message:
552
- // 1. a request's explicit bodyPartID
553
- // 2. a crm arm's certReqId, which is fixed by the CertReqMsg itself
554
- // 3. a cmsSequence element's bodyPartID
555
- // 4. an otherMsgSequence element's bodyPartID
556
- // Auto-allocation walks upward from 1, so anything minted before these were
557
- // claimed could take a value the caller already spent, and the caller's own
558
- // element would then be rejected as a duplicate of whatever displaced it.
559
350
  requests.forEach(function (r, i) {
560
351
  var fixed = fixedRequestId(r, i);
561
352
  if (fixed != null) ids.reserve(fixed, "request " + i);
@@ -567,15 +358,9 @@ async function _build(spec, signer, opts) {
567
358
  return _claimRawElement(el, ids, "an otherMsgSequence element (index " + i + ")");
568
359
  });
569
360
 
570
- // Now the requests: a fixed identifier is re-claimed as a no-op against the
571
- // reservation above, and only the ones that omitted it are allocated. The
572
- // reqSequence bytes this produces are what the Identity Proof witness covers.
573
361
  var encodedRequests = requests.map(function (r, i) { return encodeRequest(r, ids, i); });
574
362
  var reqSequenceBytes = b.sequence(encodedRequests.map(function (r) { return r.der; }));
575
363
 
576
- // A renewal carries neither identity control. Refusing the combination is the
577
- // point: dropping the control silently would emit a message that looks like a
578
- // renewal to us and an identity-proofed request to nobody.
579
364
  if (spec.renewal) {
580
365
  if (spec.identityProof) {
581
366
  throw E("cmc/bad-input",
@@ -588,13 +373,6 @@ async function _build(spec, signer, opts) {
588
373
  "a renewal request carries no " + forbidden + " control (RFC 5272 sec. 3.2 (a))");
589
374
  }
590
375
  }
591
- // A renewal is authenticated by the certificate being renewed: sec. 6.3.3 says
592
- // "the outermost signature layer is created using the current signing
593
- // certificate, which allows the original identity to be associated with the
594
- // certification request". That identity is the whole mechanism: it is what
595
- // replaces the Identity Proof this mode just refused. A key-only signer has no
596
- // certificate and so carries no prior identity, leaving a message with nothing
597
- // for the CA to authenticate the renewal against.
598
376
  var renewalSigners = Array.isArray(signer) ? signer : [signer];
599
377
  for (var si = 0; si < renewalSigners.length; si++) {
600
378
  var rs = renewalSigners[si];
@@ -618,15 +396,6 @@ async function _build(spec, signer, opts) {
618
396
  controls.push(encodeControl(_oidOf(c.type), [_der(c.value, "a control value")], ids));
619
397
  });
620
398
 
621
- // The exchange binding (RFC 5272 sec. 6.6 Transaction Identifier / Sender Nonce,
622
- // sec. 6.4 Data Return). These are what pki.cmc.verify checks the response
623
- // against, and a request that omits them has no replay defense, so they are
624
- // named fields here and not something the caller hand-encodes into
625
- // spec.controls and can silently get wrong.
626
- // A named field and a hand-encoded control of the same type would emit the
627
- // control twice, and a message carrying two of them has no single value the
628
- // response can be bound to; this toolkit's own /fullcmc refuses exactly that.
629
- // Refuse it at the source, before signing something no one can bind to.
630
399
  _assertNoDuplicateBinding(callerControls, spec);
631
400
  if (spec.transactionId != null) {
632
401
  controls.push(encodeControl(OID_TRANSACTION_ID,
@@ -648,10 +417,6 @@ async function _build(spec, signer, opts) {
648
417
  if (identity != null && typeof identity !== "string") {
649
418
  throw E("cmc/bad-input", "identityProof.identity is the UTF8String the Identification control carries");
650
419
  }
651
- // The pair is emitted together when an identity is given, because the two are
652
- // coupled: the Identification control tells the server which shared secret to
653
- // look up, and its presence is what changes how the key is derived. Letting a
654
- // caller supply one without the other would put that coupling out of reach.
655
420
  if (identity != null) controls.push(encodeControl(OID_IDENTIFICATION, [b.utf8(identity)], ids));
656
421
  controls.push(encodeControl(OID_IDENTITY_PROOF_V2,
657
422
  [identityProofV2(spec.identityProof.secret, reqSequenceBytes, identity)], ids));
@@ -665,18 +430,11 @@ async function _build(spec, signer, opts) {
665
430
  throw E("cmc/bad-input", "popLinkRandomBytes must be a positive integer");
666
431
  }
667
432
  var R = nodeCrypto.randomBytes(rBytes);
668
- // Both are emitted together: PL1 makes the Random control mandatory whenever
669
- // the witness is present, so producing one without the other is not an option
670
- // the API offers.
671
433
  controls.push(encodeControl(OID_POP_LINK_RANDOM, [b.octetString(R)], ids));
672
434
  controls.push(encodeControl(O("id-cmc-popLinkWitnessV2"),
673
435
  [popLinkWitnessV2(spec.popLink.secret, R)], ids));
674
436
  }
675
437
 
676
- // PKIData ::= SEQUENCE { controlSequence, reqSequence, cmsSequence,
677
- // otherMsgSequence }: all four emitted, the unused ones empty (sec. 3.2.1).
678
- // reqSequenceBytes is spliced in as the same buffer the witness was computed
679
- // over, which is the whole of IP1.
680
438
  var pkiData = b.sequence([
681
439
  b.sequence(controls),
682
440
  b.raw(reqSequenceBytes),
@@ -684,14 +442,6 @@ async function _build(spec, signer, opts) {
684
442
  b.sequence(otherMsgSequence),
685
443
  ]);
686
444
 
687
- // Read the assembled message back through the shipped parser before signing it.
688
- // Every arm here splices caller-supplied DER (a tcr's CertificationRequest, a
689
- // cmsSequence TaggedContentInfo, an otherMsg's value), and checking each shape
690
- // by hand would restate the parser's rules in a second place, where they would
691
- // drift and where a newly added arm would silently miss them. One round-trip
692
- // covers them all, including arms not yet written: whatever the parser refuses,
693
- // this refuses at build time, so no message goes out whose recipient (this
694
- // toolkit's own decoder included) cannot read it.
695
445
  try {
696
446
  cmcFmt.parsePkiData(pkiData);
697
447
  } catch (e) {
@@ -702,28 +452,12 @@ async function _build(spec, signer, opts) {
702
452
 
703
453
  _assertKeyOnlySigner(signer, requests);
704
454
 
705
- // The signer is copied for the same reason the message was assembled at the
706
- // call: cms.sign reads `key` inside its own promise chain, so a caller who
707
- // swaps signer.key on the next line would have the request signed by the
708
- // replacement while the original certificate stays embedded: a message whose
709
- // signature does not belong to the certificate beside it.
710
- //
711
- // cms.sign resolves eContentType through oid.byName, so it takes the registry
712
- // name; handing it the dotted value resolves to undefined.
713
- // Copying a private key makes a second copy of a secret, so it is cleared once signing has
714
- // settled and never left for the collector, the same discipline the MAC keys above follow.
715
- // The clear covers the rejecting path too: a wrong or malformed key is the case a caller can
716
- // reach, and a success-only wipe would keep the secret exactly when it matters.
717
455
  var ownedKeyBytes = [];
718
456
  var copiedSigner = _copySigners(signer, ownedKeyBytes);
719
457
  function _wipeOwnedKeys() {
720
458
  if (ownedKeyBytes.length) guard.secret.zeroizeAll(ownedKeyBytes, CmcError, "cmc/bad-input", "the signer key copy");
721
459
  ownedKeyBytes.length = 0;
722
460
  }
723
- // Verify every embedded tcr proof-of-possession BEFORE signing: do not sign a request the CA will
724
- // reject. `await`, not a `.then` chain, so the PoP gate and the sign are sequenced through native
725
- // promise jobs a co-resident cannot swap; the finally clears the signer key copy on every path,
726
- // the rejecting one included.
727
461
  try {
728
462
  await _assertTcrPops(requests);
729
463
  return await cmsSign.sign(pkiData, copiedSigner, { eContentType: "id-cct-PKIData", pem: opts.pem });
@@ -732,15 +466,6 @@ async function _build(spec, signer, opts) {
732
466
  }
733
467
  }
734
468
 
735
- // Each signer descriptor, and every byte value in it. cms.sign reads these inside
736
- // its own promise chain, so both levels matter: re-pointing signer.key is one way
737
- // to change who signs, and rewriting the PKCS#8 buffer it already points at is
738
- // the other. A CryptoKey handle is passed through as-is: it is an opaque
739
- // reference the caller is meant to share, and there is nothing to copy.
740
- // `owned` collects the buffers this function allocated that hold private key material, so the
741
- // caller can clear them once signing has settled. Only the key is listed: the other copied
742
- // values are certificates and identifiers, which are public and outlive the call by design.
743
- // The caller's own key is never written to; only our copy of it is.
744
469
  function _copySigners(signer, owned) {
745
470
  function one(s) {
746
471
  if (!s || typeof s !== "object") return s;
@@ -751,25 +476,13 @@ function _copySigners(signer, owned) {
751
476
  }
752
477
  return out;
753
478
  }
754
- // One level further for a composite key, which is an object of component keys
755
- // ({ mldsa, trad }) and not a buffer. Copying only the top level would leave
756
- // those components, the actual PKCS#8 bytes that sign, the caller's to
757
- // replace or zeroize while cms.sign reads them in a later turn. A CryptoKey is
758
- // an opaque handle and is passed through as-is.
759
479
  function copyValue(v, isSecret) {
760
480
  if (!isSecret) {
761
- // A public signer field (cert / spki / keyIdentifier DER): any BufferSource is
762
- // snapshotted to a private Buffer so a caller cannot mutate it in a later turn;
763
- // an ArrayBuffer or DataView is accepted, not silently turned into an empty object.
764
- // A non-byte descriptor or scalar (a parsed certificate, a CryptoKey handle) passes
765
- // through untouched.
766
481
  if (guard.bytes.isByteSource(v)) return guard.bytes.snapshotSource(v, CmcError, "cmc/bad-input", "a signer field");
767
482
  return v;
768
483
  }
769
- // The private key stays on the ownership contract: a Buffer is copied, a Uint8Array is
770
- // copied, and every copy is collected so it can be zeroized once signing settles.
771
484
  if (Buffer.isBuffer(v) || v instanceof Uint8Array) return _own(Buffer.from(v), true); // allow:byte-source-narrow -- private key bytes (Buffer borrowed / Uint8Array copied+wiped)
772
- if (!v || typeof v !== "object" || typeof v.type === "string") return v; // CryptoKey / scalar
485
+ if (!v || typeof v !== "object" || typeof v.type === "string") return v;
773
486
  var c = {}, ck;
774
487
  for (ck in v) {
775
488
  if (!_hasOwn(v, ck)) continue;
@@ -778,8 +491,6 @@ function _copySigners(signer, owned) {
778
491
  }
779
492
  return c;
780
493
  }
781
- // A composite key's components are listed too: each is PKCS#8 bytes that actually sign, so
782
- // leaving them out would wipe the wrapper and keep the secrets it was wrapping.
783
494
  function _own(buf, isSecret) {
784
495
  if (isSecret && owned) owned.push(buf);
785
496
  return buf;
@@ -787,38 +498,11 @@ function _copySigners(signer, owned) {
787
498
  return Array.isArray(signer) ? signer.map(one) : one(signer);
788
499
  }
789
500
 
790
- /**
791
- * RFC 5272 sec. 3.2, the three rules that apply when the signature is made with
792
- * the private key of a certification request the message carries, and not with
793
- * an already-certified key:
794
- *
795
- * a. that request MUST include a Subject Key Identifier extension;
796
- * b. the subjectKeyIdentifier form of SignerIdentifier MUST be used;
797
- * c. its value MUST be the Subject Key Identifier that request specifies.
798
- *
799
- * (b) is structural and pki.cms.sign already emits only that form for a key-only
800
- * signer. (a) and (c) are about agreement between the signer and the requests
801
- * beside it, which is checked here: an identifier the requests never declare
802
- * leaves the CA unable to tie the signature to the key being enrolled, so the
803
- * request is signed but unusable, and it is the producer's job to catch that,
804
- * not the CA's to guess.
805
- *
806
- * This lives here, not in pki.cms.sign, because it is a CMC rule: only this
807
- * layer knows the content is a PKIData and which requests are in it. Teaching the
808
- * generic CMS signer to parse CMC content would put the protocol's rules in the
809
- * wrong module.
810
- *
811
- * A signer that carries a certificate is untouched: it identifies itself by that
812
- * certificate, and the clause does not reach it.
813
- */
501
+
814
502
  function _assertKeyOnlySigner(signer, requests) {
815
503
  var all = Array.isArray(signer) ? signer : [signer];
816
504
  var keyOnly = all.filter(function (x) { return x && x.cert == null && x.spki != null; });
817
505
  if (!keyOnly.length) return;
818
- // Sec. 3.2's fourth rule: "If the request key is used for signing, there MUST be
819
- // only one SignerInfo in the SignedData." A request key has no certificate and
820
- // so no independent identity; letting it sign alongside others would produce a
821
- // message whose signer set the CA cannot reason about.
822
506
  if (all.length !== 1) {
823
507
  throw E("cmc/bad-signer",
824
508
  "a Full PKI Request signed with a certification request's own key MUST carry exactly one SignerInfo, " +
@@ -827,7 +511,6 @@ function _assertKeyOnlySigner(signer, requests) {
827
511
  keyOnly.forEach(function (so) { _assertKeyOnlySignerBinding(so, requests); });
828
512
  }
829
513
 
830
- // The sec. 3.2a/3.2c binding for a single key-only signer.
831
514
  function _assertKeyOnlySignerBinding(so, requests) {
832
515
  var id = so.keyIdentifier;
833
516
  if (!guard.bytes.isByteSource(id)) {
@@ -842,24 +525,14 @@ function _assertKeyOnlySignerBinding(so, requests) {
842
525
  var declaredSki = false, sawRequest = false;
843
526
  for (var i = 0; i < requests.length; i++) {
844
527
  var req = requests[i];
845
- // Both key-bearing arms: sec. 3.2 says the signing key may belong to a request
846
- // "included in the TaggedRequest tcr or crm fields", so reading only PKCS#10
847
- // would reject every conforming CRMF enrollment of a brand-new key.
848
528
  var declaredBy;
849
529
  try {
850
530
  declaredBy = req && req.tcr != null ? _csrKeyIdentity(req.tcr)
851
531
  : (req && req.crm != null ? _crmKeyIdentity(req.crm) : null);
852
- } catch (_e) { declaredBy = null; } // a request this layer cannot read declares nothing
532
+ } catch (_e) { declaredBy = null; }
853
533
  if (req && (req.tcr != null || req.crm != null)) sawRequest = true;
854
534
  if (!declaredBy || !declaredBy.ski) continue;
855
535
  declaredSki = true;
856
- // The identifier and the key together. Matching the identifier alone would accept a
857
- // signer holding key A while the request it points at asks to certify key B:
858
- // the SKI is caller-chosen, so the two can be made to agree while the keys do
859
- // not, and a CA resolving the SID to the requested key could then not verify
860
- // the carrier at all. The identifier says which request; the key is what makes
861
- // the claim true. The comparison runs through the toolkit's shared byte
862
- // equality; neither value here is secret, but there is one way to compare.
863
536
  if (guard.crypto.constantTimeEqual(declaredBy.ski, idBytes) &&
864
537
  declaredBy.spki && guard.crypto.constantTimeEqual(declaredBy.spki, signerSpki)) {
865
538
  return;
@@ -880,14 +553,8 @@ function _assertKeyOnlySignerBinding(so, requests) {
880
553
  "to be the one asking for this very public key (RFC 5272 sec. 3.2)");
881
554
  }
882
555
 
883
- // { ski, spki } for a CRMF certification request: the identifier it declares and
884
- // the key it asks to have certified. The CertTemplate carries extensions directly,
885
- // so there is no attribute wrapper to unwrap; the extnValue is the same DER
886
- // SubjectKeyIdentifier OCTET STRING.
887
556
  function _crmKeyIdentity(crmDer) {
888
557
  var msg = _asCertReqMsg(_der(crmDer, "a crm CertReqMsg"));
889
- // pki.schema.crmf reads CertReqMessages (SEQUENCE OF CertReqMsg); one message is
890
- // wrapped here and decoded there, so the CRMF rules stay in the CRMF parser.
891
558
  var msgs = crmf.parse(b.sequence([msg])).messages;
892
559
  var tmpl = msgs && msgs[0] && msgs[0].certReq && msgs[0].certReq.certTemplate;
893
560
  var found = null;
@@ -895,19 +562,12 @@ function _crmKeyIdentity(crmDer) {
895
562
  if (e.name !== "subjectKeyIdentifier" || found) return;
896
563
  found = asn1.read.octetString(asn1.decode(e.value));
897
564
  });
898
- // RFC 4211 sec. 4.1: the requested key may live in the signature POP's
899
- // POPOSigningKeyInput instead of the CertTemplate, and the CRMF parser surfaces
900
- // it there. Reading only the template would refuse a key-only signer whose
901
- // request is perfectly conforming.
902
565
  var msg0 = msgs && msgs[0];
903
566
  var pk = (tmpl && tmpl.publicKey) ||
904
567
  (msg0 && msg0.popo && msg0.popo.poposkInput && msg0.popo.poposkInput.publicKey);
905
568
  return { ski: found, spki: Buffer.isBuffer(pk) ? pk : (pk && pk.bytes) || null };
906
569
  }
907
570
 
908
- // { ski, spki } for a PKCS#10 certification request. Read through the shipped CSR
909
- // parser and the extensionRequest attribute it already decodes, so the extension
910
- // rules are not restated here.
911
571
  function _csrKeyIdentity(csrDer) {
912
572
  var parsed = csr.parse(_der(csrDer, "a tcr certificationRequest"));
913
573
  var found = null;
@@ -915,8 +575,6 @@ function _csrKeyIdentity(csrDer) {
915
575
  if (a.name !== "extensionRequest") return;
916
576
  (a.extensions || []).forEach(function (e) {
917
577
  if (e.name !== "subjectKeyIdentifier" || found) return;
918
- // extnValue holds a DER SubjectKeyIdentifier ::= OCTET STRING; the identifier
919
- // is its contents, not the TLV.
920
578
  found = asn1.read.octetString(asn1.decode(e.value));
921
579
  });
922
580
  });