@blamejs/pki 0.8.59 → 0.8.60

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 (63) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/lib/acme.js +15 -7
  3. package/lib/alt-sig.js +3 -1
  4. package/lib/asn1-der.js +82 -34
  5. package/lib/attrcert-sign.js +19 -16
  6. package/lib/byte-writer.js +63 -13
  7. package/lib/cbor-det.js +9 -3
  8. package/lib/cmc-build.js +12 -9
  9. package/lib/cmp-build.js +35 -33
  10. package/lib/cmp-session.js +19 -9
  11. package/lib/cms-decrypt.js +22 -8
  12. package/lib/cms-encrypt.js +23 -17
  13. package/lib/cms-sign.js +65 -43
  14. package/lib/cms-verify.js +8 -4
  15. package/lib/crl-sign.js +24 -17
  16. package/lib/csr-sign.js +5 -2
  17. package/lib/ct.js +27 -16
  18. package/lib/est.js +12 -9
  19. package/lib/guard-bytes.js +5 -1
  20. package/lib/guard-der.js +6 -1
  21. package/lib/guard-intrinsic.js +12 -4
  22. package/lib/guard-list.js +64 -0
  23. package/lib/guard-name.js +1 -1
  24. package/lib/hpke.js +10 -3
  25. package/lib/http-transport.js +12 -3
  26. package/lib/inspect.js +10 -2
  27. package/lib/jose.js +3 -1
  28. package/lib/lint.js +236 -152
  29. package/lib/mime.js +9 -5
  30. package/lib/ocsp.js +25 -22
  31. package/lib/path-validate.js +43 -13
  32. package/lib/pbes2.js +6 -2
  33. package/lib/pkcs11-uri.js +3 -1
  34. package/lib/pkcs12-build.js +14 -11
  35. package/lib/pki-build.js +14 -10
  36. package/lib/possession.js +3 -1
  37. package/lib/rc2.js +6 -2
  38. package/lib/revocation-fetch.js +78 -19
  39. package/lib/scep.js +14 -6
  40. package/lib/schema-attrcert.js +4 -2
  41. package/lib/schema-c509.js +94 -78
  42. package/lib/schema-cmc.js +5 -2
  43. package/lib/schema-cmp.js +6 -3
  44. package/lib/schema-cms.js +7 -4
  45. package/lib/schema-crl.js +1 -1
  46. package/lib/schema-crmf.js +1 -1
  47. package/lib/schema-csr.js +3 -3
  48. package/lib/schema-engine.js +36 -18
  49. package/lib/schema-pkcs1.js +7 -3
  50. package/lib/schema-pkcs12.js +9 -6
  51. package/lib/schema-pkix.js +19 -3
  52. package/lib/schema-sec1.js +4 -1
  53. package/lib/schema-tsp.js +4 -1
  54. package/lib/shbs.js +7 -3
  55. package/lib/smime.js +18 -14
  56. package/lib/tlog.js +17 -11
  57. package/lib/tuf.js +3 -1
  58. package/lib/validator-keydesc.js +4 -1
  59. package/lib/validator-tls.js +7 -2
  60. package/lib/webcrypto.js +9 -3
  61. package/lib/x509-sign.js +20 -15
  62. package/package.json +1 -1
  63. package/sbom.cdx.json +6 -6
package/lib/cmc-build.js CHANGED
@@ -22,6 +22,9 @@ var key = require("./key");
22
22
  var _createPublicKey = nodeCrypto.createPublicKey;
23
23
  var guard = require("./guard-all");
24
24
  var intrinsic = require("./guard-intrinsic");
25
+ /** @internal The append every list here is built with: `push` stores at the index and a store
26
+ * consults a setter inherited there, and these lists become the controls a request carries. */
27
+ var _push = intrinsic.append;
25
28
  var _hasOwn = intrinsic.hasOwn;
26
29
  var _isArray = intrinsic.isArray;
27
30
  var _isBuffer = intrinsic.isBuffer;
@@ -449,7 +452,7 @@ function _assertSecret(secret, what) {
449
452
  }
450
453
 
451
454
  function _ownSecret(buf, owned) {
452
- owned.push(buf);
455
+ _push(owned,buf);
453
456
  return buf;
454
457
  }
455
458
 
@@ -804,15 +807,15 @@ async function _build(spec, signer, opts) {
804
807
 
805
808
  _assertNoDuplicateBinding(callerControls, spec);
806
809
  if (spec.transactionId != null) {
807
- controls.push(encodeControl(OID_TRANSACTION_ID,
810
+ _push(controls,encodeControl(OID_TRANSACTION_ID,
808
811
  [b.integer(_asBigInt(spec.transactionId, "spec.transactionId"))], ids));
809
812
  }
810
813
  if (spec.senderNonce != null) {
811
- controls.push(encodeControl(OID_SENDER_NONCE,
814
+ _push(controls,encodeControl(OID_SENDER_NONCE,
812
815
  [b.octetString(_der(spec.senderNonce, "spec.senderNonce"))], ids));
813
816
  }
814
817
  if (spec.dataReturn != null) {
815
- controls.push(encodeControl(OID_DATA_RETURN,
818
+ _push(controls,encodeControl(OID_DATA_RETURN,
816
819
  [b.octetString(_der(spec.dataReturn, "spec.dataReturn"))], ids));
817
820
  }
818
821
 
@@ -839,8 +842,8 @@ async function _build(spec, signer, opts) {
839
842
  if (identity != null && typeof identity !== "string") {
840
843
  throw E("cmc/bad-input", "identityProof.identity is the UTF8String the Identification control carries");
841
844
  }
842
- if (identity != null) controls.push(encodeControl(OID_IDENTIFICATION, [b.utf8(identity)], ids));
843
- controls.push(encodeControl(OID_IDENTITY_PROOF_V2,
845
+ if (identity != null) _push(controls,encodeControl(OID_IDENTIFICATION, [b.utf8(identity)], ids));
846
+ _push(controls,encodeControl(OID_IDENTITY_PROOF_V2,
844
847
  [identityProofV2(spec.identityProof.secret, reqSequenceBytes, carriedIdentity)], ids));
845
848
  }
846
849
 
@@ -933,8 +936,8 @@ async function _build(spec, signer, opts) {
933
936
  throw E("cmc/bad-input", "popLinkRandomBytes must be a positive integer");
934
937
  }
935
938
  var R = nodeCrypto.randomBytes(rBytes);
936
- controls.push(encodeControl(OID_POP_LINK_RANDOM, [b.octetString(R)], ids));
937
- controls.push(encodeControl(O("id-cmc-popLinkWitnessV2"),
939
+ _push(controls,encodeControl(OID_POP_LINK_RANDOM, [b.octetString(R)], ids));
940
+ _push(controls,encodeControl(O("id-cmc-popLinkWitnessV2"),
938
941
  [popLinkWitnessV2(spec.popLink.secret, R)], ids));
939
942
  }
940
943
 
@@ -1016,7 +1019,7 @@ function _copySigners(signer, owned) {
1016
1019
  return c;
1017
1020
  }
1018
1021
  function _own(buf, isSecret) {
1019
- if (isSecret && owned) owned.push(buf);
1022
+ if (isSecret && owned) _push(owned,buf);
1020
1023
  return buf;
1021
1024
  }
1022
1025
  return Array.isArray(signer) ? guard.list.copyMap(signer, one) : one(signer);
package/lib/cmp-build.js CHANGED
@@ -56,7 +56,9 @@ var _bufferConcat = intrinsic.bufferConcat;
56
56
  var _map = intrinsic.map;
57
57
  var _keys = intrinsic.keys;
58
58
  var _forEach = intrinsic.forEach;
59
- var _push = intrinsic.push;
59
+ /** @internal `append`, not a captured `push`: a store at an index walks the prototype chain for a
60
+ * setter, so an accessor there takes the element being appended. `append` defines it. */
61
+ var _push = intrinsic.append;
60
62
  var _stringify = intrinsic.stringify;
61
63
  var _bigInt = intrinsic.BigInt;
62
64
  var _Date = intrinsic.Date;
@@ -167,7 +169,7 @@ function _encodeInfoTypeAndValue(itav) {
167
169
  if (typeof itav.infoType !== "string" || O(itav.infoType) == null) throw _err("cmp/bad-name", "unknown infoType " + guard.text.showValue(itav.infoType));
168
170
  var children = [b.oid(O(itav.infoType))];
169
171
  var val = _encodeInfoValue(itav);
170
- if (val != null) children.push(val);
172
+ if (val != null) _push(children,val);
171
173
  return b.sequence(children);
172
174
  }
173
175
 
@@ -238,16 +240,16 @@ function _encodeHeader(headerSpec, protectionAlgDer, pvno) {
238
240
  ];
239
241
  if (headerSpec.messageTime != null) {
240
242
  guard.time.assertEncodable(headerSpec.messageTime, _err, "cmp/bad-input", "header.messageTime");
241
- children.push(b.explicit(0, b.generalizedTime(headerSpec.messageTime)));
243
+ _push(children,b.explicit(0, b.generalizedTime(headerSpec.messageTime)));
242
244
  }
243
- if (protectionAlgDer != null) children.push(b.explicit(1, b.raw(protectionAlgDer)));
244
- if (headerSpec.senderKID != null) children.push(b.explicit(2, _reqOctets(headerSpec.senderKID, "header.senderKID")));
245
- if (headerSpec.recipKID != null) children.push(b.explicit(3, _reqOctets(headerSpec.recipKID, "header.recipKID")));
246
- if (headerSpec.transactionID != null) children.push(b.explicit(4, _reqOctets(headerSpec.transactionID, "header.transactionID")));
247
- if (headerSpec.senderNonce != null) children.push(b.explicit(5, _reqOctets(headerSpec.senderNonce, "header.senderNonce")));
248
- if (headerSpec.recipNonce != null) children.push(b.explicit(6, _reqOctets(headerSpec.recipNonce, "header.recipNonce")));
249
- if (headerSpec.freeText != null) children.push(b.explicit(7, _encodePkiFreeText(headerSpec.freeText, "cmp/bad-freetext", "header.freeText")));
250
- if (headerSpec.generalInfo != null) children.push(b.explicit(8, _encodeGeneralInfo(headerSpec.generalInfo, "cmp/bad-general-info", "header.generalInfo")));
245
+ if (protectionAlgDer != null) _push(children,b.explicit(1, b.raw(protectionAlgDer)));
246
+ if (headerSpec.senderKID != null) _push(children,b.explicit(2, _reqOctets(headerSpec.senderKID, "header.senderKID")));
247
+ if (headerSpec.recipKID != null) _push(children,b.explicit(3, _reqOctets(headerSpec.recipKID, "header.recipKID")));
248
+ if (headerSpec.transactionID != null) _push(children,b.explicit(4, _reqOctets(headerSpec.transactionID, "header.transactionID")));
249
+ if (headerSpec.senderNonce != null) _push(children,b.explicit(5, _reqOctets(headerSpec.senderNonce, "header.senderNonce")));
250
+ if (headerSpec.recipNonce != null) _push(children,b.explicit(6, _reqOctets(headerSpec.recipNonce, "header.recipNonce")));
251
+ if (headerSpec.freeText != null) _push(children,b.explicit(7, _encodePkiFreeText(headerSpec.freeText, "cmp/bad-freetext", "header.freeText")));
252
+ if (headerSpec.generalInfo != null) _push(children,b.explicit(8, _encodeGeneralInfo(headerSpec.generalInfo, "cmp/bad-general-info", "header.generalInfo")));
251
253
  return b.sequence(children);
252
254
  }
253
255
 
@@ -267,8 +269,8 @@ function _encodePkiStatusInfo(si, code) {
267
269
  if (!si || typeof si !== "object" || Buffer.isBuffer(si)) throw _err(code, "a PKIStatusInfo must be an object { status, statusString?, failInfo? }");
268
270
  if (typeof si.status !== "number" || !Number.isInteger(si.status) || si.status < 0 || si.status > 6) throw _err(code, "statusInfo.status must be a PKIStatus 0..6 (RFC 9810 sec. 5.2.3)");
269
271
  var children = [b.integer(BigInt(si.status))];
270
- if (si.statusString != null) children.push(_encodePkiFreeText(si.statusString, code, "statusInfo.statusString"));
271
- if (si.failInfo != null) children.push(_encodeFailInfo(si.failInfo, code));
272
+ if (si.statusString != null) _push(children,_encodePkiFreeText(si.statusString, code, "statusInfo.statusString"));
273
+ if (si.failInfo != null) _push(children,_encodeFailInfo(si.failInfo, code));
272
274
  return b.sequence(children);
273
275
  }
274
276
 
@@ -278,10 +280,10 @@ function _encodeCertStatus(cs, state) {
278
280
  _reqOctets(cs.certHash, "certConf certHash"),
279
281
  b.integer(_reqIdInt(cs.certReqId, "cmp/bad-cert-status", "CertStatus certReqId")),
280
282
  ];
281
- if (cs.statusInfo != null) children.push(_encodePkiStatusInfo(cs.statusInfo, "cmp/bad-cert-status"));
283
+ if (cs.statusInfo != null) _push(children,_encodePkiStatusInfo(cs.statusInfo, "cmp/bad-cert-status"));
282
284
  if (cs.hashAlg != null) {
283
285
  if (typeof cs.hashAlg !== "string" || !CERT_CONF_HASH_ALGS[cs.hashAlg]) throw _err("cmp/bad-name", "certConf hashAlg must be a hash algorithm (sha256 / sha384 / sha512 / sha3-256 / sha3-512 / sha1); got " + guard.text.showValue(cs.hashAlg));
284
- children.push(b.explicit(0, _algIdNoParams(cs.hashAlg)));
286
+ _push(children,b.explicit(0, _algIdNoParams(cs.hashAlg)));
285
287
  state.usesCmp2021 = true;
286
288
  }
287
289
  return b.sequence(children);
@@ -317,7 +319,7 @@ function _encodeRevDetails(rd) {
317
319
  certDetails = b.raw(crmf.buildCertTemplate(rd.certDetails));
318
320
  }
319
321
  var children = [certDetails];
320
- if (rd.crlEntryDetails != null) children.push(b.raw(_encodeCrlEntryDetails(rd.crlEntryDetails)));
322
+ if (rd.crlEntryDetails != null) _push(children,b.raw(_encodeCrlEntryDetails(rd.crlEntryDetails)));
321
323
  return b.sequence(children);
322
324
  }
323
325
 
@@ -419,12 +421,12 @@ function _encodeCertifiedKeyPair(ckp, state) {
419
421
  var children = [_encodeCertOrEncCert(ckp, state)];
420
422
  if (ckp.privateKey != null) {
421
423
  var pk = _b.reqDer(ckp.privateKey, "certifiedKeyPair.privateKey (a pre-encoded EncryptedKey DER)");
422
- children.push(b.explicit(0, b.raw(pk)));
424
+ _push(children,b.explicit(0, b.raw(pk)));
423
425
  var pkNode;
424
426
  try { pkNode = asn1.decode(pk); } catch (e) { throw _err("cmp/bad-cert-response", "certifiedKeyPair.privateKey is not valid DER", e); }
425
427
  if (pkNode.tagClass === "context" && pkNode.tagNumber === 0) state.usesCmp2021 = true;
426
428
  }
427
- if (ckp.publicationInfo != null) children.push(b.explicit(1, b.raw(_b.reqDer(ckp.publicationInfo, "certifiedKeyPair.publicationInfo (a pre-encoded DER)"))));
429
+ if (ckp.publicationInfo != null) _push(children,b.explicit(1, b.raw(_b.reqDer(ckp.publicationInfo, "certifiedKeyPair.publicationInfo (a pre-encoded DER)"))));
428
430
  return b.sequence(children);
429
431
  }
430
432
 
@@ -435,8 +437,8 @@ function _encodeCertResponse(cr, state) {
435
437
  if (hasCkp && cr.status.failInfo != null) throw _err("cmp/bad-cert-response", "a CertResponse must not carry both failInfo and certifiedKeyPair");
436
438
  if (hasCkp && cr.status.status !== 0 && cr.status.status !== 1) throw _err("cmp/bad-cert-response", "a CertResponse certifiedKeyPair is allowed only under a granting status (accepted / grantedWithMods)");
437
439
  var children = [b.integer(_reqIdInt(cr.certReqId, "cmp/bad-cert-response", "CertResponse certReqId")), _encodePkiStatusInfo(cr.status, "cmp/bad-cert-response")];
438
- if (hasCkp) children.push(_encodeCertifiedKeyPair(cr.certifiedKeyPair, state));
439
- if (cr.rspInfo != null) children.push(_reqOctets(cr.rspInfo, "CertResponse.rspInfo"));
440
+ if (hasCkp) _push(children,_encodeCertifiedKeyPair(cr.certifiedKeyPair, state));
441
+ if (cr.rspInfo != null) _push(children,_reqOctets(cr.rspInfo, "CertResponse.rspInfo"));
440
442
  return b.sequence(children);
441
443
  }
442
444
 
@@ -446,9 +448,9 @@ function _encodeCertRepMessage(spec, state, arm) {
446
448
  var children = [];
447
449
  if (spec.caPubs != null) {
448
450
  if (!Array.isArray(spec.caPubs) || !spec.caPubs.length) throw _err("cmp/bad-cert-rep", arm + ".caPubs must be a non-empty array of certificate DERs");
449
- children.push(b.explicit(1, b.sequence(spec.caPubs.map(function (c) { return _certRaw(c, "cmp/bad-cert-rep", "a caPubs entry"); }))));
451
+ _push(children,b.explicit(1, b.sequence(spec.caPubs.map(function (c) { return _certRaw(c, "cmp/bad-cert-rep", "a caPubs entry"); }))));
450
452
  }
451
- children.push(b.sequence(spec.response.map(function (cr) { return _encodeCertResponse(cr, state); })));
453
+ _push(children,b.sequence(spec.response.map(function (cr) { return _encodeCertResponse(cr, state); })));
452
454
  return b.sequence(children);
453
455
  }
454
456
 
@@ -468,11 +470,11 @@ function _encodeRevRepContent(spec) {
468
470
  var children = [b.sequence(spec.status.map(function (si) { return _encodePkiStatusInfo(si, "cmp/bad-rev-rep"); }))];
469
471
  if (spec.revCerts != null) {
470
472
  if (!Array.isArray(spec.revCerts) || !spec.revCerts.length) throw _err("cmp/bad-rev-rep", "rp.revCerts must be a non-empty array of CertId");
471
- children.push(b.explicit(0, b.sequence(spec.revCerts.map(_encodeCertIdRr))));
473
+ _push(children,b.explicit(0, b.sequence(spec.revCerts.map(_encodeCertIdRr))));
472
474
  }
473
475
  if (spec.crls != null) {
474
476
  if (!Array.isArray(spec.crls) || !spec.crls.length) throw _err("cmp/bad-rev-rep", "rp.crls must be a non-empty array of CertificateList DERs");
475
- children.push(b.explicit(1, b.sequence(spec.crls.map(function (c) {
477
+ _push(children,b.explicit(1, b.sequence(spec.crls.map(function (c) {
476
478
  var der = _b.reqDerSequence(c, "crls entry (a CertificateList DER)");
477
479
  try { crl.parse(der); }
478
480
  catch (e) { if (e instanceof CmpError) throw e; throw _err("cmp/bad-rev-rep", "a crls entry is not a valid CRL (CertificateList)", e); }
@@ -486,8 +488,8 @@ function _encodeErrorMsgContent(spec) {
486
488
  if (!spec || typeof spec !== "object" || Buffer.isBuffer(spec)) throw _err("cmp/bad-error", "error must be an object { pKIStatusInfo, errorCode?, errorDetails? }");
487
489
  if (spec.pKIStatusInfo == null) throw _err("cmp/bad-error", "error.pKIStatusInfo is required");
488
490
  var children = [_encodePkiStatusInfo(spec.pKIStatusInfo, "cmp/bad-error")];
489
- if (spec.errorCode != null) children.push(b.integer(_reqIdInt(spec.errorCode, "cmp/bad-error", "error.errorCode")));
490
- if (spec.errorDetails != null) children.push(_encodePkiFreeText(spec.errorDetails, "cmp/bad-error", "error.errorDetails"));
491
+ if (spec.errorCode != null) _push(children,b.integer(_reqIdInt(spec.errorCode, "cmp/bad-error", "error.errorCode")));
492
+ if (spec.errorDetails != null) _push(children,_encodePkiFreeText(spec.errorDetails, "cmp/bad-error", "error.errorDetails"));
491
493
  return b.sequence(children);
492
494
  }
493
495
 
@@ -497,7 +499,7 @@ function _encodePollRepContent(list) {
497
499
  if (!pr || typeof pr !== "object" || Buffer.isBuffer(pr)) throw _err("cmp/bad-poll-rep", "each pollRep entry must be an object");
498
500
  if (typeof pr.checkAfter !== "number" || !Number.isInteger(pr.checkAfter) || pr.checkAfter < 0 || pr.checkAfter > 0x7fffffff) throw _err("cmp/bad-poll-rep", "pollRep checkAfter must be a non-negative uint31 delay in seconds (RFC 9810 sec. 5.3.22)");
499
501
  var kids = [b.integer(_reqIdInt(pr.certReqId, "cmp/bad-poll-rep", "pollRep certReqId")), b.integer(BigInt(pr.checkAfter))];
500
- if (pr.reason != null) kids.push(_encodePkiFreeText(pr.reason, "cmp/bad-poll-rep", "pollRep reason"));
502
+ if (pr.reason != null) _push(kids,_encodePkiFreeText(pr.reason, "cmp/bad-poll-rep", "pollRep reason"));
501
503
  return b.sequence(kids);
502
504
  }));
503
505
  }
@@ -506,14 +508,14 @@ function _encodeKeyRecRepContent(spec, state) {
506
508
  if (!spec || typeof spec !== "object" || Buffer.isBuffer(spec)) throw _err("cmp/bad-key-rec-rep", "krp must be an object { status, newSigCert?, caCerts?, keyPairHist? }");
507
509
  if (spec.status == null) throw _err("cmp/bad-key-rec-rep", "krp.status is required");
508
510
  var children = [_encodePkiStatusInfo(spec.status, "cmp/bad-key-rec-rep")];
509
- if (spec.newSigCert != null) children.push(b.explicit(0, _certRaw(spec.newSigCert, "cmp/bad-key-rec-rep", "krp.newSigCert")));
511
+ if (spec.newSigCert != null) _push(children,b.explicit(0, _certRaw(spec.newSigCert, "cmp/bad-key-rec-rep", "krp.newSigCert")));
510
512
  if (spec.caCerts != null) {
511
513
  if (!Array.isArray(spec.caCerts) || !spec.caCerts.length) throw _err("cmp/bad-key-rec-rep", "krp.caCerts must be a non-empty array of certificate DERs");
512
- children.push(b.explicit(1, b.sequence(spec.caCerts.map(function (c) { return _certRaw(c, "cmp/bad-key-rec-rep", "a krp.caCerts entry"); }))));
514
+ _push(children,b.explicit(1, b.sequence(spec.caCerts.map(function (c) { return _certRaw(c, "cmp/bad-key-rec-rep", "a krp.caCerts entry"); }))));
513
515
  }
514
516
  if (spec.keyPairHist != null) {
515
517
  if (!Array.isArray(spec.keyPairHist) || !spec.keyPairHist.length) throw _err("cmp/bad-key-rec-rep", "krp.keyPairHist must be a non-empty array of CertifiedKeyPair");
516
- children.push(b.explicit(2, b.sequence(spec.keyPairHist.map(function (ckp) { return _encodeCertifiedKeyPair(ckp, state); }))));
518
+ _push(children,b.explicit(2, b.sequence(spec.keyPairHist.map(function (ckp) { return _encodeCertifiedKeyPair(ckp, state); }))));
517
519
  }
518
520
  return b.sequence(children);
519
521
  }
@@ -891,7 +893,7 @@ async function _build(message, opts) {
891
893
  var protectionBits = await prot.computeBits(protectedPartDer);
892
894
  var msgChildren = [headerTLV, bodyTLV, b.explicit(0, protectionBits)];
893
895
  var extraCertsDers = _collectExtraCerts(opts, prot.certDer);
894
- if (extraCertsDers.length) msgChildren.push(b.explicit(1, b.sequence(extraCertsDers)));
896
+ if (extraCertsDers.length) _push(msgChildren,b.explicit(1, b.sequence(extraCertsDers)));
895
897
  var der = b.sequence(msgChildren);
896
898
 
897
899
  cmp.parse(der);
@@ -905,14 +907,14 @@ async function _build(message, opts) {
905
907
 
906
908
  function _collectExtraCerts(opts, protCertDer) {
907
909
  var out = [];
908
- if (protCertDer != null) out.push(b.raw(protCertDer));
910
+ if (protCertDer != null) _push(out,b.raw(protCertDer));
909
911
  if (opts.extraCerts != null) {
910
912
  if (!Array.isArray(opts.extraCerts)) throw _err("cmp/bad-extra-certs", "opts.extraCerts must be an array of certificate DERs");
911
913
  opts.extraCerts.forEach(function (c) {
912
914
  var der = _b.reqDerSequence(c, "extraCerts entry (a Certificate DER)");
913
915
  try { x509.parse(der); }
914
916
  catch (e) { if (e instanceof CmpError) throw e; throw _err("cmp/bad-extra-certs", "an extraCerts entry is not a valid X.509 certificate", e); }
915
- out.push(b.raw(der));
917
+ _push(out,b.raw(der));
916
918
  });
917
919
  }
918
920
  return out;
@@ -15,6 +15,10 @@ var crmfSign = require("./crmf-sign");
15
15
  var cmpBuild = require("./cmp-build");
16
16
  var csr = require("./schema-csr");
17
17
  var guard = require("./guard-all");
18
+ /** @internal The append every list here is built with: `push` stores at the index and a store
19
+ * consults a setter inherited there, and one of these lists is the accumulated CA certificates a
20
+ * later leg is authenticated against. */
21
+ var _push = guard.list.append;
18
22
  var compositeSig = require("./composite-sig");
19
23
  var constants = require("./constants");
20
24
  var webcrypto = require("./webcrypto");
@@ -34,7 +38,7 @@ function setEngine(engine) { _engine = engine; }
34
38
  var HASHLESS_SIG_OIDS = Object.create(null);
35
39
  (function () {
36
40
  var names = ["Ed25519", "Ed448", "id-ml-dsa-44", "id-ml-dsa-65", "id-ml-dsa-87"];
37
- ["sha2", "shake"].forEach(function (h) { ["128s", "128f", "192s", "192f", "256s", "256f"].forEach(function (s) { names.push("id-slh-dsa-" + h + "-" + s); }); });
41
+ ["sha2", "shake"].forEach(function (h) { ["128s", "128f", "192s", "192f", "256s", "256f"].forEach(function (s) { _push(names,"id-slh-dsa-" + h + "-" + s); }); });
38
42
  names.forEach(function (n) { var o = oid.byName(n); if (o) HASHLESS_SIG_OIDS[o] = 1; });
39
43
  })();
40
44
  var SIG_OID_TO_HASH = Object.create(null);
@@ -136,11 +140,11 @@ function _asCertList(v) { return v == null ? [] : (Array.isArray(v) ? guard.list
136
140
  function _boundedPool(base, added) {
137
141
  var ceiling = constants.LIMITS.PATH_BUILD_MAX_CANDIDATES;
138
142
  var seen = Object.create(null), distinctBase = [];
139
- base.forEach(function (c) { var k = _certIdentity(c); if (k == null) { distinctBase.push(c); return; } if (!seen[k]) { seen[k] = 1; distinctBase.push(c); } });
143
+ base.forEach(function (c) { var k = _certIdentity(c); if (k == null) { _push(distinctBase,c); return; } if (!seen[k]) { seen[k] = 1; _push(distinctBase,c); } });
140
144
  var room = ceiling - distinctBase.length;
141
145
  if (room <= 0) return distinctBase;
142
146
  var useful = [];
143
- added.forEach(function (c) { var k = _certIdentity(c); if (k != null && seen[k]) return; if (k != null) seen[k] = 1; useful.push(c); });
147
+ added.forEach(function (c) { var k = _certIdentity(c); if (k != null && seen[k]) return; if (k != null) seen[k] = 1; _push(useful,c); });
144
148
  return distinctBase.concat(useful.slice(0, room));
145
149
  }
146
150
  function _certIdentity(cert) {
@@ -228,7 +232,7 @@ function _responseExtraCerts(responseBytes) {
228
232
  seen[key] = true;
229
233
  try { x509.parse(c); }
230
234
  catch (_e) { continue; }
231
- out.push(Buffer.from(c));
235
+ _push(out,Buffer.from(c));
232
236
  }
233
237
  return out;
234
238
  }
@@ -682,7 +686,13 @@ function session(opts) {
682
686
  if (!Buffer.isBuffer(c)) return;
683
687
  var k = c.toString("base64");
684
688
  if (caPubsSeen[k]) {
685
- if (isGrantLeg) { for (var pi = 0; pi < caPubsAccum.length; pi++) { if (caPubsAccum[pi].toString("base64") === k) { guard.list.append(caPubsAccum, caPubsAccum.splice(pi, 1)[0]); if (pi < caPubsWaitingCount) caPubsWaitingCount--; break; } } }
689
+ /** @internal The entry is read, removed and appended as three steps rather than through
690
+ * `splice`. `splice` RETURNS what it removed, so it builds that result through
691
+ * `ArraySpeciesCreate`, which reads the receiver's `constructor` and then its
692
+ * `Symbol.species`: a getter installed on `Array.prototype.constructor` is handed this
693
+ * accumulator as its `this` while the move is in progress, and the list holds the CA
694
+ * certificates a later leg is authenticated against. */
695
+ if (isGrantLeg) { for (var pi = 0; pi < caPubsAccum.length; pi++) { if (caPubsAccum[pi].toString("base64") === k) { var moved = caPubsAccum[pi]; guard.list.removeAt(caPubsAccum, pi); guard.list.append(caPubsAccum, moved); if (pi < caPubsWaitingCount) caPubsWaitingCount--; break; } } }
686
696
  return;
687
697
  }
688
698
  try { x509.parse(c); } catch (e) { throw _err("cmp/bad-cert-response", "an authenticated caPubs entry is not a valid X.509 certificate", e); }
@@ -963,10 +973,10 @@ function session(opts) {
963
973
  async function _validateLeaf(leaf, caPubs) {
964
974
  if (_engine == null || opts.trustAnchors == null) return;
965
975
  var caPubsList = [];
966
- if (Array.isArray(caPubs)) caPubs.forEach(function (c) { if (Buffer.isBuffer(c)) caPubsList.push(c); });
976
+ if (Array.isArray(caPubs)) caPubs.forEach(function (c) { if (Buffer.isBuffer(c)) _push(caPubsList,c); });
967
977
  var added = _asCertList(opts.intermediates);
968
- if (Buffer.isBuffer(cachedSignerCert)) added.push(cachedSignerCert);
969
- cachedChain.forEach(function (c) { if (Buffer.isBuffer(c)) added.push(c); });
978
+ if (Buffer.isBuffer(cachedSignerCert)) _push(added,cachedSignerCert);
979
+ cachedChain.forEach(function (c) { if (Buffer.isBuffer(c)) _push(added,c); });
970
980
  var pool = _boundedPool(caPubsList, added);
971
981
  var res;
972
982
  try { res = await _engine.build(leaf, { trustAnchors: _asCertList(opts.trustAnchors), intermediates: pool, validate: true, time: opts.time != null ? opts.time : new Date() }); }
@@ -1395,7 +1405,7 @@ function session(opts) {
1395
1405
  if (limit.total !== null && total > limit.total) {
1396
1406
  throw _err("cmp/bad-input", "the resumeToken " + name + " exceeds the " + limit.total + "-byte pool a transaction holds");
1397
1407
  }
1398
- out.push(der);
1408
+ _push(out,der);
1399
1409
  }
1400
1410
  return out;
1401
1411
  }
@@ -121,10 +121,10 @@ function _selectCandidates(recips, km, opts) {
121
121
  for (var k = 0; k < recips.length; k++) {
122
122
  var r = recips[k];
123
123
  if (want === "asym" && (r.type === "ktri" || r.type === "kari" || r.type === "ori")) {
124
- if (cert && _ridMatches(r, cert)) out.push({ ri: r, index: k });
125
- } else if (want === "pwri" && r.type === "pwri") { out.push({ ri: r, index: k }); }
124
+ if (cert && _ridMatches(r, cert)) intrinsic.append(out, { ri: r, index: k });
125
+ } else if (want === "pwri" && r.type === "pwri") { intrinsic.append(out, { ri: r, index: k }); }
126
126
  else if (want === "kekri" && r.type === "kekri") {
127
- if (km.kekId == null || _kekIdMatches(r, km.kekId)) out.push({ ri: r, index: k });
127
+ if (km.kekId == null || _kekIdMatches(r, km.kekId)) intrinsic.append(out, { ri: r, index: k });
128
128
  }
129
129
  }
130
130
  if (!out.length) throw _err("cms/no-matching-recipient", "no recipient matches the supplied key material");
@@ -563,19 +563,23 @@ async function _aesKwUnwrap(kek, wrapped) {
563
563
  guard.secret.zeroize(new Uint8Array(rawAb), CmsError, "cms/bad-input", "the unwrapped content key");
564
564
  }
565
565
  }
566
+ /** @internal Both KDF-input structures APPEND by defining the index. A store at an index the list
567
+ * has no own property at consults a setter inherited from the array prototype, so an accessor there
568
+ * would decide the SharedInfo these bytes become and derive a different KEK from the same shared
569
+ * secret. */
566
570
  function _eccSharedInfo(wrapName, ukm, kekBytes) {
567
571
  var kids = [b.sequence([b.oid(O(wrapName))])];
568
- if (ukm) kids.push(b.explicit(0, b.octetString(ukm)));
572
+ if (ukm) intrinsic.append(kids, b.explicit(0, b.octetString(ukm)));
569
573
  /** @internal The SuppPubInfo key length is written with the capture, for the same reason the
570
574
  * encrypt side does it: this is KDF input, and a replaced write derives a different KEK from the
571
575
  * same shared secret. */
572
576
  var supp = Buffer.alloc(4); intrinsic.writeUInt32BE(supp, kekBytes * 8, 0);
573
- kids.push(b.explicit(2, b.octetString(supp)));
577
+ intrinsic.append(kids, b.explicit(2, b.octetString(supp)));
574
578
  return b.sequence(kids);
575
579
  }
576
580
  function _kemOtherInfo(wrapName, kekBytes, ukm) {
577
581
  var kids = [b.sequence([b.oid(O(wrapName))]), b.integer(BigInt(kekBytes))];
578
- if (ukm) kids.push(b.explicit(0, b.octetString(ukm)));
582
+ if (ukm) intrinsic.append(kids, b.explicit(0, b.octetString(ukm)));
579
583
  return b.sequence(kids);
580
584
  }
581
585
  function _pwriUnwrap(kek, wrapped, iv, keyBits) {
@@ -648,7 +652,7 @@ function _originatorSpki(originator) {
648
652
  if (!originator || originator.form !== "originatorKey") throw _err("cms/unsupported-algorithm", "kari requires an originatorKey (ephemeral-static ECDH)");
649
653
  var v = originator.value;
650
654
  var algKids = [b.oid(v.algorithm.oid)];
651
- if (v.algorithm.parameters != null) algKids.push(b.raw(v.algorithm.parameters));
655
+ if (v.algorithm.parameters != null) intrinsic.append(algKids, b.raw(v.algorithm.parameters));
652
656
  return b.sequence([b.sequence(algKids), b.bitString(v.publicKey.bytes, v.publicKey.unusedBits)]);
653
657
  }
654
658
  var MONT = intrinsic.create(null); MONT[O("X25519")] = { name: "X25519", hkdf: "SHA-256" }; MONT[O("X448")] = { name: "X448", hkdf: "SHA-512" };
@@ -710,7 +714,17 @@ async function _verifyAuthenticatedData(parsed, km, opts, requireProtection) {
710
714
  guard.der.assertParams(parsed.digestAlgorithm.parameters, "absentOrNull", _err,
711
715
  "cms/unsupported-algorithm", parsed.digestAlgorithm.name + " digestAlgorithm (RFC 5754 sec. 2)");
712
716
  preimage = _explicitSetOf(parsed.authAttrsBytes);
713
- var mdAttr = (parsed.authAttrs || []).filter(function (a) { return a.type === O("messageDigest"); })[0];
717
+ /** @internal The selection returns the first matching attribute or null. `filter(...)[0]` indexes
718
+ * a result that is EMPTY when the attribute is absent, and index 0 of an empty array answers
719
+ * from the array prototype, so a value installed there would supply the digest this comparison
720
+ * is made against. The refusal restates an invariant the parse already holds: an
721
+ * AuthenticatedData with authAttrs is walked through the content-binding check, which requires
722
+ * the message-digest attribute (`cms/missing-message-digest`), so this is not reachable from a
723
+ * message and is here so the read below cannot be made on something that is not an attribute. */
724
+ var mdAttr = guard.list.firstMatch(parsed.authAttrs || [], function (a) { return a.type === O("messageDigest"); });
725
+ if (!mdAttr || mdAttr.values.length !== 1) {
726
+ throw _err("cms/bad-auth-attrs", "authenticated attributes must carry exactly one message-digest attribute (RFC 5652 sec. 9.2)");
727
+ }
714
728
  mdCheck = { hash: dHash, declared: asn1.read.octetString(asn1.decode(mdAttr.values[0])) };
715
729
  /** @internal RFC 6211 sec. 3.2 on this content type: the two comparisons are what make the
716
730
  * outer `digestAlgorithm` and `macAlgorithm` fields mean anything, since the MAC input is the
@@ -14,6 +14,10 @@ var webcrypto = require("./webcrypto");
14
14
  var frameworkError = require("./framework-error");
15
15
  var guard = require("./guard-all");
16
16
  var intrinsic = require("./guard-intrinsic");
17
+ /** @internal The append every list here is built with: `push` stores at the index and a store
18
+ * consults a setter inherited there. These lists become a recipient info and the key-derivation
19
+ * input beside it. */
20
+ var _push = intrinsic.append;
17
21
  var pbes2 = require("./pbes2");
18
22
  var compositeKem = require("./composite-kem");
19
23
  var b = asn1.build;
@@ -66,7 +70,7 @@ function _wrapOidForKek(keyBytes) {
66
70
 
67
71
  function _gcmParams(nonce, icvLen) {
68
72
  var kids = [b.octetString(nonce)];
69
- if (icvLen !== 12) kids.push(b.integer(BigInt(icvLen)));
73
+ if (icvLen !== 12) _push(kids,b.integer(BigInt(icvLen)));
70
74
  return b.sequence(kids);
71
75
  }
72
76
 
@@ -124,12 +128,12 @@ MONT_KA[O("X448")] = { name: "X448", hkdf: "SHA-512", scheme: "dhSinglePass-stdD
124
128
 
125
129
  function _eccSharedInfo(wrapName, ukm, kekBytes) {
126
130
  var kids = [_algId(wrapName, "absent")];
127
- if (ukm) kids.push(b.explicit(0, b.octetString(ukm)));
131
+ if (ukm) _push(kids,b.explicit(0, b.octetString(ukm)));
128
132
  /** @internal The SuppPubInfo key length is written with the capture. It is KDF input, so it is part
129
133
  * of what the key-encryption key derives from, and a replaced write derives a different KEK from
130
134
  * the same shared secret. */
131
135
  var supp = Buffer.alloc(4); intrinsic.writeUInt32BE(supp, kekBytes * 8, 0);
132
- kids.push(b.explicit(2, b.octetString(supp)));
136
+ _push(kids,b.explicit(2, b.octetString(supp)));
133
137
  return b.sequence(kids);
134
138
  }
135
139
  async function _buildKari(cek, cert, opts) {
@@ -179,8 +183,9 @@ async function _buildKari(cek, cert, opts) {
179
183
  var rek = b.sequence([b.sequence([ridNode, b.octetString(encryptedKey)])]);
180
184
  var kekAlg = b.sequence([b.oid(O(origKeyAlgId.scheme)), _algId(wrapName, "absent")]);
181
185
  var kariKids = [b.integer(3n), b.explicit(0, originatorKey)];
182
- if (ukm) kariKids.push(b.explicit(1, b.octetString(ukm)));
183
- kariKids.push(kekAlg, rek);
186
+ if (ukm) _push(kariKids,b.explicit(1, b.octetString(ukm)));
187
+ _push(kariKids,kekAlg);
188
+ _push(kariKids,rek);
184
189
  return { tag: 1, node: b.sequence(kariKids) };
185
190
  } finally {
186
191
  guard.secret.zeroizeAll([z, mz, kek], CmsError, "cms/bad-input", "the key-agreement shared secret");
@@ -227,7 +232,7 @@ var KEM_WC = intrinsic.create(null); KEM_WC[O("id-ml-kem-512")] = "ML-KEM-512";
227
232
 
228
233
  function _kemOtherInfo(wrapName, kekBytes, ukm) {
229
234
  var kids = [_algId(wrapName, "absent"), b.integer(BigInt(kekBytes))];
230
- if (ukm) kids.push(b.explicit(0, b.octetString(ukm)));
235
+ if (ukm) _push(kids,b.explicit(0, b.octetString(ukm)));
231
236
  return b.sequence(kids);
232
237
  }
233
238
  async function _kemEncapsulate(keyOid, cert) {
@@ -258,8 +263,9 @@ async function _buildKemri(cek, cert, opts) {
258
263
  var encryptedKey = await _aesKwWrap(kek, cek);
259
264
  var rid = _rid(cert, opts.keyIdentifier);
260
265
  var kemriKids = [b.integer(0n), rid.node, _algId(oid.name(keyOid), "absent"), b.octetString(kemct), _algId("hkdfWithSha256", "absent"), b.integer(BigInt(kekBytes))];
261
- if (ukm) kemriKids.push(b.explicit(0, b.octetString(ukm)));
262
- kemriKids.push(_algId(wrapName, "absent"), b.octetString(encryptedKey));
266
+ if (ukm) _push(kemriKids,b.explicit(0, b.octetString(ukm)));
267
+ _push(kemriKids,_algId(wrapName, "absent"));
268
+ _push(kemriKids,b.octetString(encryptedKey));
263
269
  var kemri = b.sequence(kemriKids);
264
270
  return { tag: 4, node: b.sequence([b.oid(O("kem")), kemri]) };
265
271
  } finally {
@@ -446,7 +452,7 @@ async function _encryptImpl(content, recipients, opts) {
446
452
  if (!recipients.length) throw _err("cms/bad-input", "at least one recipient is required (RFC 5652 sec. 6.1)");
447
453
  var recips = [];
448
454
  var consumed = intrinsic.create(null);
449
- for (var i = 0; i < recipients.length; i++) recips.push(await _buildRecipient(cek, recipients[i], opts, consumed));
455
+ for (var i = 0; i < recipients.length; i++) _push(recips,await _buildRecipient(cek, recipients[i], opts, consumed));
450
456
  _assertDefaultsConsumed(opts, consumed);
451
457
  var riNodes = recips.map(_taggedRecipient);
452
458
 
@@ -535,8 +541,8 @@ async function _authEnvelopedData(contentBytes, contentStream, cek, ca, contentT
535
541
  }
536
542
  var eci = b.sequence([b.oid(O(contentType)), b.sequence([b.oid(O(ca.oid)), _gcmParams(nonce, 16)]), b.contextPrimitive(0, g.ct)]);
537
543
  var kids = [b.integer(0n), b.setOf(riNodes), eci];
538
- if (authAttrsDer) kids.push(authAttrsDer);
539
- kids.push(b.octetString(g.tag));
544
+ if (authAttrsDer) _push(kids,authAttrsDer);
545
+ _push(kids,b.octetString(g.tag));
540
546
  void recips;
541
547
  return b.sequence(kids);
542
548
  }
@@ -680,7 +686,7 @@ async function _authenticateImpl(content, recipients, opts) {
680
686
  try {
681
687
  var recips = [];
682
688
  var consumedAuth = {};
683
- for (var i = 0; i < recipients.length; i++) recips.push(await _buildRecipient(macKey, recipients[i], opts, consumedAuth));
689
+ for (var i = 0; i < recipients.length; i++) _push(recips,await _buildRecipient(macKey, recipients[i], opts, consumedAuth));
684
690
  _assertDefaultsConsumed(opts, consumedAuth);
685
691
  var riNodes = recips.map(_taggedRecipient);
686
692
 
@@ -705,7 +711,7 @@ async function _authenticateImpl(content, recipients, opts) {
705
711
  * MAC algorithm substitution attack, which is difficult because the attacker does not know
706
712
  * the authentication key". Built from the same values the two outer fields are built from. */
707
713
  if (protectionOid) {
708
- intrinsic.push(pairs, b.sequence([
714
+ intrinsic.append(pairs, b.sequence([
709
715
  b.oid(protectionOid),
710
716
  b.setOf([b.sequence([_algId(digestName), b.implicit(2, _algId(mac.oid))])]),
711
717
  ]));
@@ -732,10 +738,10 @@ async function _authenticateImpl(content, recipients, opts) {
732
738
 
733
739
  var eci = b.sequence([b.oid(O(contentType)), b.explicit(0, b.octetString(contentBytes))]);
734
740
  var kids = [b.integer(0n), b.setOf(riNodes), _algId(mac.oid)];
735
- if (digestAlgTagged) kids.push(digestAlgTagged);
736
- kids.push(eci);
737
- if (authAttrsDer) kids.push(authAttrsDer);
738
- kids.push(b.octetString(macValue));
741
+ if (digestAlgTagged) _push(kids,digestAlgTagged);
742
+ _push(kids,eci);
743
+ if (authAttrsDer) _push(kids,authAttrsDer);
744
+ _push(kids,b.octetString(macValue));
739
745
  var ci = b.sequence([b.oid(O("authData")), b.explicit(0, b.sequence(kids))]);
740
746
  try { schemaCms.parse(ci); } catch (e) { throw (e instanceof CmsError) ? e : _err("cms/bad-input", "the supplied authenticated attributes produced an invalid AuthenticatedData", e); }
741
747
  return opts.pem ? schemaCms.pemEncode(ci, "CMS") : ci;