@blamejs/pki 0.8.3 → 0.8.5

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.
@@ -413,16 +413,16 @@ function _generalNameToDer(intVal, valueNode, ipMode, isNative) {
413
413
  if (intVal === 0 || intVal === -1 || intVal === -2 || intVal === -3) return _otherNameToDer(valueNode, intVal);
414
414
  throw _err("c509/bad-extensions", "GeneralName int " + intVal + " has no C509 sec. 8.13 registry row");
415
415
  }
416
- function _generalNameFromDer(gn, ipMode) {
416
+ function _generalNameFromDer(gn, ipMode, ctx) {
417
417
  var t = gn.tagNumber;
418
418
  if (t === 1 || t === 2 || t === 6) return [cbor.build.int(BigInt(t)), cbor.build.textString(gn.value)];
419
- if (t === 4) { var nm = _dirNameToCbor(gn.bytes); return nm == null ? null : [cbor.build.int(4n), nm]; }
419
+ if (t === 4) { var nm = _dirNameToCbor(gn.bytes, ctx); return nm == null ? null : [cbor.build.int(4n), nm]; }
420
420
  if (t === 7) {
421
421
  if (!ipMode) return [cbor.build.int(7n), cbor.build.byteString(gn.value)];
422
422
  var ip = _ncIpFromDer(gn.value); return ip == null ? null : [cbor.build.int(7n), cbor.build.byteString(ip)];
423
423
  }
424
424
  if (t === 8) return [cbor.build.int(8n), _oidCbor(gn.value)];
425
- if (t === 0) return _otherNameFromDer(gn.value);
425
+ if (t === 0) return _otherNameFromDer(gn.value, ctx);
426
426
  return null;
427
427
  }
428
428
 
@@ -434,10 +434,10 @@ function _generalNamesToDer(node, isNative) {
434
434
  for (var i = 0; i + 1 < kids.length; i += 2) out.push(_generalNameToDer(Number(_cborIntVal(kids[i], "a GeneralName type")), kids[i + 1], false, isNative));
435
435
  return out;
436
436
  }
437
- function _generalNamesFromDer(gnNodes) {
437
+ function _generalNamesFromDer(gnNodes, ctx) {
438
438
  var out = [];
439
439
  for (var i = 0; i < gnNodes.length; i++) {
440
- var pair = _generalNameFromDer(schema.walk(GN_LEAF, gnNodes[i], NS), false);
440
+ var pair = _generalNameFromDer(schema.walk(GN_LEAF, gnNodes[i], schema.withResources(NS, ctx)), false, ctx);
441
441
  if (pair == null) return null;
442
442
  out.push(pair[0]); out.push(pair[1]);
443
443
  }
@@ -470,11 +470,11 @@ function _otherNameToDer(node, intVal) {
470
470
  }
471
471
  return b.contextConstructed(0, Buffer.concat([b.oid(typeId), b.explicit(0, inner)]));
472
472
  }
473
- function _otherNameFromDer(v) {
473
+ function _otherNameFromDer(v, ctx) {
474
474
  var onInt = ON_INT_BY_OID[v.typeId];
475
475
  if (onInt === undefined) return [cbor.build.int(0n), cbor.build.array([_oidCbor(v.typeId), cbor.build.byteString(v.valueBytes)])];
476
476
  var inner;
477
- try { inner = asn1.decode(v.valueBytes); } catch (_e) { return null; } // allow:swallow-unverified -- a malformed otherName value yields null, so the extension does not compact and is carried in C509 general form (raw bytes)
477
+ try { inner = pkix.decodeNested(v.valueBytes, ctx, "an otherName value"); } catch (_e) { return null; } // allow:swallow-unverified -- a malformed otherName value yields null, so the extension does not compact and is carried in C509 general form (raw bytes)
478
478
  if (onInt === -1) {
479
479
  if (inner.tagClass !== "universal" || inner.tagNumber !== asn1.TAGS.SEQUENCE || !inner.children || inner.children.length !== 2) return null;
480
480
  var hwType, hwSerial;
@@ -492,11 +492,11 @@ function _otherNameFromDer(v) {
492
492
  return [cbor.build.int(-3n), cbor.build.byteString(mac)];
493
493
  }
494
494
 
495
- function _dirNameToCbor(gnBytes) {
496
- var node = asn1.decode(gnBytes);
495
+ function _dirNameToCbor(gnBytes, ctx) {
496
+ var node = pkix.decodeNested(gnBytes, ctx, "a directoryName value");
497
497
  if (!node.children || node.children.length !== 1) return null;
498
498
  var name;
499
- try { name = _c509NameFromDer(node.children[0].bytes); } catch (_e) { return null; } // allow:swallow-unverified -- a malformed directoryName yields null, so the extension is carried in C509 general form instead
499
+ try { name = _c509NameFromDer(node.children[0].bytes, ctx); } catch (_e) { return null; } // allow:swallow-unverified -- a malformed directoryName yields null, so the extension is carried in C509 general form instead
500
500
  try { return _encName(name, true); } catch (_e2) { return null; } // allow:swallow-unverified -- a directoryName that does not re-encode yields null, so the extension is carried in C509 general form instead
501
501
  }
502
502
 
@@ -745,13 +745,13 @@ function _subtreesToDer(node, isNative) {
745
745
  for (var i = 0; i + 1 < kids.length; i += 2) out.push(b.sequence([_generalNameToDer(Number(_cborIntVal(kids[i], "a GeneralSubtree base type")), kids[i + 1], true, isNative)]));
746
746
  return Buffer.concat(out);
747
747
  }
748
- function _subtreesFromDer(subtreeNodes) {
748
+ function _subtreesFromDer(subtreeNodes, ctx) {
749
749
  if (!subtreeNodes.length) return null;
750
750
  var out = [];
751
751
  for (var i = 0; i < subtreeNodes.length; i++) {
752
752
  var st = subtreeNodes[i];
753
753
  if (st.tagClass !== "universal" || st.tagNumber !== asn1.TAGS.SEQUENCE || !st.children || st.children.length !== 1) return null;
754
- var pair = _generalNameFromDer(schema.walk(GN_LEAF_SUBTREE, st.children[0], NS), true);
754
+ var pair = _generalNameFromDer(schema.walk(GN_LEAF_SUBTREE, st.children[0], schema.withResources(NS, ctx)), true, ctx);
755
755
  if (pair == null) return null;
756
756
  out.push(pair[0]); out.push(pair[1]);
757
757
  }
@@ -836,7 +836,7 @@ function _dpToDer(dpNode, isNative) {
836
836
  if (!_isCborNull(crlIssuer)) fields.push(b.contextConstructed(2, b.explicit(4, _reconName(_name509(crlIssuer, true, isNative)))));
837
837
  return b.sequence(fields);
838
838
  }
839
- function _dpFromDer(dp) {
839
+ function _dpFromDer(dp, ctx) {
840
840
  if (dp.tagClass !== "universal" || dp.tagNumber !== asn1.TAGS.SEQUENCE || !dp.children) return null;
841
841
  var fullNameUris = null, reasonsVal = null, crlIssuerCbor = null, lastTag = -1;
842
842
  for (var i = 0; i < dp.children.length; i++) {
@@ -862,7 +862,7 @@ function _dpFromDer(dp) {
862
862
  if (!f.children || f.children.length !== 1) return null;
863
863
  var ci = f.children[0];
864
864
  if (ci.tagClass !== "context" || ci.tagNumber !== 4 || !ci.children || ci.children.length !== 1) return null;
865
- try { crlIssuerCbor = _encName(_c509NameFromDer(ci.children[0].bytes), true); } catch (_e2) { return null; } // allow:swallow-unverified -- a malformed CRL-issuer name yields null, so the distributionPoint is carried in C509 general form instead
865
+ try { crlIssuerCbor = _encName(_c509NameFromDer(ci.children[0].bytes, ctx), true); } catch (_e2) { return null; } // allow:swallow-unverified -- a malformed CRL-issuer name yields null, so the distributionPoint is carried in C509 general form instead
866
866
  } else return null;
867
867
  }
868
868
  if (fullNameUris == null) return null;
@@ -1054,15 +1054,15 @@ function _extValueToDer(name, node, isNative) {
1054
1054
  }
1055
1055
  }
1056
1056
 
1057
- function _extValueFromDer(name, der) {
1057
+ function _extValueFromDer(name, der, ctx) {
1058
1058
  var node;
1059
1059
  try {
1060
- node = asn1.decode(der);
1060
+ node = pkix.decodeNested(der, ctx, "an extension value");
1061
1061
  switch (name) {
1062
1062
  case "subjectKeyIdentifier":
1063
1063
  return cbor.build.byteString(asn1.read.octetString(node));
1064
1064
  case "keyUsage": {
1065
- var bits = _keyUsageBitsFromDer(der);
1065
+ var bits = _keyUsageBitsFromDer(der, ctx);
1066
1066
  return bits == null ? null : cbor.build.uint(BigInt(bits));
1067
1067
  }
1068
1068
  case "basicConstraints": {
@@ -1081,7 +1081,7 @@ function _extValueFromDer(name, der) {
1081
1081
  if (akids.length === 3 && akids[0].tagClass === "context" && akids[0].tagNumber === 0 &&
1082
1082
  akids[1].tagClass === "context" && akids[1].tagNumber === 1 && akids[1].children &&
1083
1083
  akids[2].tagClass === "context" && akids[2].tagNumber === 2) {
1084
- var akiIssuer = _generalNamesFromDer(akids[1].children);
1084
+ var akiIssuer = _generalNamesFromDer(akids[1].children, ctx);
1085
1085
  if (akiIssuer == null) return null;
1086
1086
  var akiSerial = asn1.read.integerImplicit(akids[2], 2);
1087
1087
  if (akiSerial < 0n) return null;
@@ -1112,7 +1112,7 @@ function _extValueFromDer(name, der) {
1112
1112
  if (sanMembers.length === 1 && sanMembers[0].tagClass === "context" && sanMembers[0].tagNumber === 2) {
1113
1113
  return cbor.build.textString(schema.walk(GN_LEAF, sanMembers[0], NS).value);
1114
1114
  }
1115
- var sanItems = _generalNamesFromDer(sanMembers);
1115
+ var sanItems = _generalNamesFromDer(sanMembers, ctx);
1116
1116
  return sanItems == null ? null : cbor.build.array(sanItems);
1117
1117
  }
1118
1118
  case "nameConstraints": {
@@ -1122,7 +1122,7 @@ function _extValueFromDer(name, der) {
1122
1122
  var ncf = node.children[nci];
1123
1123
  if (ncf.tagClass !== "context" || ncf.tagNumber <= ncLast) return null;
1124
1124
  ncLast = ncf.tagNumber;
1125
- var subItems = _subtreesFromDer(ncf.children || []);
1125
+ var subItems = _subtreesFromDer(ncf.children || [], ctx);
1126
1126
  if (subItems == null) return null;
1127
1127
  if (ncf.tagNumber === 0) { permCbor = cbor.build.array(subItems); sawNc = true; }
1128
1128
  else if (ncf.tagNumber === 1) { exclCbor = cbor.build.array(subItems); sawNc = true; }
@@ -1151,7 +1151,7 @@ function _extValueFromDer(name, der) {
1151
1151
  var dps = node.children || [];
1152
1152
  if (node.tagClass !== "universal" || node.tagNumber !== asn1.TAGS.SEQUENCE || dps.length < 1) return null;
1153
1153
  var dpResults = [];
1154
- for (var dpi = 0; dpi < dps.length; dpi++) { var dpr = _dpFromDer(dps[dpi]); if (dpr == null) return null; dpResults.push(dpr); }
1154
+ for (var dpi = 0; dpi < dps.length; dpi++) { var dpr = _dpFromDer(dps[dpi], ctx); if (dpr == null) return null; dpResults.push(dpr); }
1155
1155
  if (dpResults.length === 1 && dpResults[0].oneUri != null && dpResults[0].noReasons && dpResults[0].noIssuer) return cbor.build.textString(dpResults[0].oneUri);
1156
1156
  return cbor.build.array(dpResults.map(function (r) { return r.triple; }));
1157
1157
  }
@@ -1377,14 +1377,14 @@ function _sdaFromDer(node) {
1377
1377
  * the codec represents it, and one without a codec always, since its int form carries the same
1378
1378
  * bytes. An extension the codec cannot represent keeps the generic form on every certificate type.
1379
1379
  */
1380
- function _assertSpecificExtension(dotted, valContent, isNative) {
1380
+ function _assertSpecificExtension(dotted, valContent, isNative, ctx) {
1381
1381
  var canon = EXT_NAME_BY_OID[dotted];
1382
1382
  if (!isNative || canon === undefined) return;
1383
- if (EXT_COMPACT[canon] && (!Buffer.isBuffer(valContent) || _tryCompactExtValue(canon, valContent, isNative) == null)) return;
1383
+ if (EXT_COMPACT[canon] && (!Buffer.isBuffer(valContent) || _tryCompactExtValue(canon, valContent, isNative, ctx) == null)) return;
1384
1384
  throw _err("c509/non-specific-encoding", "extension " + canon + " has a C509 registry id that carries this value, and a natively signed certificate uses only the specific CBOR encoding (draft sec. 3.7)");
1385
1385
  }
1386
- function _tryCompactExtValue(name, der, isNative) {
1387
- var compact = _extValueFromDer(name, der);
1386
+ function _tryCompactExtValue(name, der, isNative, ctx) {
1387
+ var compact = _extValueFromDer(name, der, ctx);
1388
1388
  if (compact == null) return null;
1389
1389
  var recon;
1390
1390
  try {
@@ -1395,7 +1395,7 @@ function _tryCompactExtValue(name, der, isNative) {
1395
1395
  return recon.equals(der) ? compact : null;
1396
1396
  }
1397
1397
 
1398
- function _extensions(node, isNative) {
1398
+ function _extensions(node, isNative, ctx) {
1399
1399
  if (node.majorType === 0 || node.majorType === 1) {
1400
1400
  var iv = Number(cbor.read.int(node));
1401
1401
  return [{ name: "keyUsage", oid: oid.byName("keyUsage"), critical: iv < 0, keyUsageBits: Math.abs(iv) }];
@@ -1437,7 +1437,7 @@ function _extensions(node, isNative) {
1437
1437
  if (valNode.majorType !== 2) throw _err("c509/bad-extensions", "a non-critical ~oid extension value must be a byte string");
1438
1438
  valContent = valNode.content;
1439
1439
  }
1440
- _assertSpecificExtension(extOid, valContent, isNative);
1440
+ _assertSpecificExtension(extOid, valContent, isNative, ctx);
1441
1441
  }
1442
1442
  out.push({ name: name, oid: extOid, critical: critical, value: valContent || null });
1443
1443
  }
@@ -1637,21 +1637,49 @@ function parse(input, callerOpts) {
1637
1637
  if (f[8].majorType !== 2) throw _err("c509/bad-spki", "subjectPublicKey must be a CBOR byte string");
1638
1638
  subjectPublicKey = f[8].content;
1639
1639
  }
1640
- var extensions = _extensions(f[9], type === 2);
1640
+ /** @internal A native certificate's extension values are opaque DER inside the CBOR, so reading
1641
+ * one is a second decode that restarts depth and item counting and takes the caps this door
1642
+ * was given. The latch is re-read before the result is returned. */
1643
+ var nested = pkix.nestedContext(NS, caps);
1644
+ var result;
1645
+ try {
1646
+ result = _finishParse(f, root, nested, {
1647
+ type: type, serial: serial, sHex: sHex, sigAlg: sigAlg, issuer: issuer,
1648
+ notBefore: notBefore, notAfter: notAfter, subject: subject, spkAlg: spkAlg,
1649
+ subjectPublicKey: subjectPublicKey, rsaKey: rsaKey,
1650
+ });
1651
+ } catch (e) {
1652
+ if (nested.budget.exhausted() && !(e && e.code === "c509/too-large")) throw _budgetRefusal(e);
1653
+ throw e;
1654
+ }
1655
+ if (nested.budget.exhausted()) throw _budgetRefusal(null);
1656
+ return result;
1657
+ }
1658
+
1659
+ /** @internal The refusal a cap produces, as distinct from a statement about the bytes. It is read
1660
+ * off the latch rather than off a throw, because the probe that reads an extension value absorbs
1661
+ * a failure by returning null. */
1662
+ function _budgetRefusal(cause) {
1663
+ return _err("c509/too-large", "the C509 certificate exceeds the decode budget for this parse", cause || undefined);
1664
+ }
1665
+
1666
+ function _finishParse(f, root, nested, fields) {
1667
+ var type = fields.type;
1668
+ var extensions = _extensions(f[9], type === 2, nested.ns);
1641
1669
  if (f[10].majorType !== 2) throw _err("c509/bad-signature", "issuerSignatureValue must be a CBOR byte string");
1642
1670
  var signatureValue = f[10].content;
1643
1671
 
1644
1672
  var result = {
1645
1673
  certificateType: type,
1646
- serialNumber: serial,
1647
- serialNumberHex: sHex,
1648
- signatureAlgorithm: sigAlg,
1649
- issuer: issuer,
1650
- validity: { notBefore: notBefore, notAfter: notAfter },
1651
- subject: subject,
1652
- subjectPublicKeyAlgorithm: spkAlg,
1653
- subjectPublicKey: subjectPublicKey,
1654
- rsaPublicKey: rsaKey,
1674
+ serialNumber: fields.serial,
1675
+ serialNumberHex: fields.sHex,
1676
+ signatureAlgorithm: fields.sigAlg,
1677
+ issuer: fields.issuer,
1678
+ validity: { notBefore: fields.notBefore, notAfter: fields.notAfter },
1679
+ subject: fields.subject,
1680
+ subjectPublicKeyAlgorithm: fields.spkAlg,
1681
+ subjectPublicKey: fields.subjectPublicKey,
1682
+ rsaPublicKey: fields.rsaKey,
1655
1683
  extensions: extensions,
1656
1684
  signatureValue: signatureValue,
1657
1685
  };
@@ -1660,7 +1688,6 @@ function parse(input, callerOpts) {
1660
1688
  if (type === 2) result.signedData = result._fieldBytes;
1661
1689
 
1662
1690
  if (type === 3) result.reconstructedDer = _reconstructDer(result, f[10]);
1663
-
1664
1691
  return result;
1665
1692
  }
1666
1693
 
@@ -1883,8 +1910,8 @@ function _euiFromCn(value) {
1883
1910
  if (bytes[3] === 0xff && bytes[4] === 0xfe) return Buffer.concat([bytes.subarray(0, 3), bytes.subarray(5)]);
1884
1911
  return bytes;
1885
1912
  }
1886
- function _c509NameFromDer(nameBytes) {
1887
- var node = asn1.decode(nameBytes);
1913
+ function _c509NameFromDer(nameBytes, ctx) {
1914
+ var node = pkix.decodeNested(nameBytes, ctx, "a Name value");
1888
1915
  var rdns = [];
1889
1916
  (node.children || []).forEach(function (rdnSet) {
1890
1917
  if (!rdnSet.children || rdnSet.children.length !== 1) throw _err("c509/non-invertible", "a C509 Name requires single-attribute RDNs");
@@ -1905,10 +1932,10 @@ function _c509NameFromDer(nameBytes) {
1905
1932
  });
1906
1933
  return { rdns: rdns };
1907
1934
  }
1908
- function _keyUsageBitsFromDer(extnValue) {
1935
+ function _keyUsageBitsFromDer(extnValue, ctx) {
1909
1936
  var bs;
1910
1937
  try {
1911
- bs = asn1.read.bitString(asn1.decode(extnValue));
1938
+ bs = asn1.read.bitString(pkix.decodeNested(extnValue, ctx, "a keyUsage extension value"));
1912
1939
  } catch (_e) {
1913
1940
  return null;
1914
1941
  }
@@ -1925,6 +1952,7 @@ function _magBytes(intNode) {
1925
1952
  }
1926
1953
  function _sigMagWidth(derSig) {
1927
1954
  var n;
1955
+ // allow:bare-decode on the DER -> C509 conversion, below the X.509 parse door that caps the input.
1928
1956
  try { n = asn1.decode(derSig); } catch (e) { throw _err("c509/bad-signature", "the ECDSA issuer signature is not valid DER", e); }
1929
1957
  if (n.tagNumber !== asn1.TAGS.SEQUENCE || n.tagClass !== "universal" || !n.children || n.children.length !== 2) throw _err("c509/bad-signature", "the ECDSA issuer signature must be a SEQUENCE of two INTEGERs");
1930
1958
  for (var i = 0; i < 2; i++) {
@@ -1969,12 +1997,14 @@ _derToType3 = function (input, opts) {
1969
1997
  var sigAlgName = sigCanon === undefined ? c.signatureAlgorithm.name : sigCanon;
1970
1998
  if (String(sigAlgName || "").toLowerCase().indexOf("ecdsa") !== 0) throw _err("c509/non-invertible", "type-3 C509 encoding covers only ECDSA-signed certificates; got " + (sigAlgName || "an unregistered algorithm"));
1971
1999
  if (c.subjectPublicKeyInfo.algorithm.oid !== oid.byName("ecPublicKey")) throw _err("c509/non-invertible", "type-3 C509 encoding covers only EC (ecPublicKey) certificates in v1; got " + (c.subjectPublicKeyInfo.algorithm.name || "an unregistered algorithm"));
2000
+ // allow:bare-decode on the DER -> C509 conversion, below the X.509 parse door that caps the input.
1972
2001
  var curveOid = asn1.read.oid(asn1.decode(c.subjectPublicKeyInfo.algorithm.parameters));
1973
2002
  var curveCanon = EC_CURVE_BY_OID[curveOid];
1974
2003
  var curve = curveCanon === undefined ? oid.name(curveOid) : curveCanon;
1975
2004
  var coordLen = EC_FIELD_BYTES[curve];
1976
2005
  if (!coordLen) throw _err("c509/non-invertible", "unsupported EC subject curve " + (curve || curveOid));
1977
2006
  var sigCurve = _resolveIssuerSigCurve(c, opts, sigAlgName);
2007
+ // allow:bare-decode on the DER -> C509 conversion, below the X.509 parse door that caps the input.
1978
2008
  var spkiNode = asn1.decode(c.subjectPublicKeyInfo.bytes);
1979
2009
  return {
1980
2010
  certificateType: 3,
package/lib/schema-cmc.js CHANGED
@@ -195,8 +195,8 @@ function readExtendedFailInfo(children, what) {
195
195
  return { failInfoOID: asn1.read.oid(children[0]), failInfoValueBytes: children[1].bytes };
196
196
  }
197
197
 
198
- function parseStatusInfo(valueDer, version, bodyPartID) {
199
- var root = asn1.decode(valueDer);
198
+ function parseStatusInfo(valueDer, version, bodyPartID, ctx) {
199
+ var root = pkix.decodeNested(valueDer, ctx, "a CMCStatusInfo value");
200
200
  if (root.tagClass !== "universal" || root.tagNumber !== TAGS.SEQUENCE || !root.constructed) {
201
201
  throw E("cmc/bad-status-info", "a CMCStatusInfo value must be a SEQUENCE");
202
202
  }
@@ -447,14 +447,15 @@ var PKI_RESPONSE = schema.seq([
447
447
  * that is not one could never be checked against anything. This is asked of a CHALLENGED request only.
448
448
  * A request body carries what its sender sent, and judging it is the enrollment's business, not the
449
449
  * decoder's. */
450
- function _assertAnswerableRequest(request) {
450
+ function _assertAnswerableRequest(request, ctx) {
451
451
  if (request.arm !== "tcr" && request.arm !== "crm") return;
452
452
  /** @internal A CertReqMessages of one, which is the shape the CRMF parser takes; built outside the
453
453
  * catch below so only the parse it wraps can be what fails. */
454
454
  var payload = request.arm === "tcr" ? request.certificationRequestBytes
455
455
  : asn1.build.sequence([asn1.build.raw(request.certReqMsgBytes)]);
456
456
  try {
457
- if (request.arm === "tcr") { csr.parse(payload); } else { crmf.parse(payload); }
457
+ var caps = ctx ? ctx.caps : undefined;
458
+ if (request.arm === "tcr") { csr.parse(payload, caps); } else { crmf.parse(payload, caps); }
458
459
  } catch (e) {
459
460
  throw E("cmc/bad-pop-challenge",
460
461
  "the request an EncryptedPOP quotes is not a " +
@@ -464,13 +465,13 @@ function _assertAnswerableRequest(request) {
464
465
  }
465
466
  }
466
467
 
467
- function parseEncryptedPop(node) {
468
+ function parseEncryptedPop(node, ctx) {
468
469
  if (node.tagClass !== "universal" || node.tagNumber !== TAGS.SEQUENCE || !node.constructed ||
469
470
  node.children.length !== 5) {
470
471
  throw E("cmc/bad-pop-challenge",
471
472
  "an EncryptedPOP is SEQUENCE { request, cms, thePOPAlgID, witnessAlgID, witness } (RFC 5272 sec. 6.7)");
472
473
  }
473
- var envelope = _assertEnvelopedChallenge(node.children[1]);
474
+ var envelope = _assertEnvelopedChallenge(node.children[1], ctx);
474
475
  var request;
475
476
  try { request = parseTaggedRequest(node.children[0]); }
476
477
  catch (e) {
@@ -478,7 +479,7 @@ function parseEncryptedPop(node) {
478
479
  "an EncryptedPOP quotes the request it challenges as a TaggedRequest: " +
479
480
  ((e && e.message) || "malformed") + " (RFC 5272 sec. 6.7)", e);
480
481
  }
481
- _assertAnswerableRequest(request);
482
+ _assertAnswerableRequest(request, ctx);
482
483
  return {
483
484
  request: request,
484
485
  /** @internal The TaggedRequest exactly as it arrived. A proof of possession is a MAC over these
@@ -526,7 +527,7 @@ function parseDecryptedPop(node) {
526
527
  * on unopened because opening them needs key material this parser does not hold. Unopened is not
527
528
  * unchecked: a field that is not a ContentInfo carrying an EnvelopedData cannot be a challenge, and
528
529
  * saying so here is what keeps a control that could never be answered from reading as one. */
529
- function _assertEnvelopedChallenge(node) {
530
+ function _assertEnvelopedChallenge(node, ctx) {
530
531
  var kids = pkix.rootSequenceChildren(node, 2, 2);
531
532
  if (!kids) {
532
533
  throw E("cmc/bad-pop-challenge",
@@ -557,7 +558,7 @@ function _assertEnvelopedChallenge(node) {
557
558
  * a challenge addressed only that way is refused here, and `pki.cms.decrypt` could not open it
558
559
  * either, so it is refused where the reason can be named rather than after a failed answer. */
559
560
  var enveloped;
560
- try { enveloped = cms.walkEnvelopedData(content.children[0]); }
561
+ try { enveloped = cms.walkEnvelopedData(content.children[0], ctx); }
561
562
  catch (e) {
562
563
  throw E("cmc/bad-pop-challenge",
563
564
  "an EncryptedPOP's ContentInfo does not carry an EnvelopedData a recipient could open: " +
@@ -594,26 +595,26 @@ function _popAlgorithm(node, what) {
594
595
  }
595
596
 
596
597
  /** @internal One AttributeValue, which is what a control carrying a single structure holds. */
597
- function _onlyValue(c, what) {
598
+ function _onlyValue(c, what, ctx) {
598
599
  if (c.values.length !== 1) {
599
600
  throw E("cmc/bad-pop-challenge",
600
601
  "a " + what + " control carries exactly one AttributeValue, got " + c.values.length);
601
602
  }
602
- return asn1.decode(c.values[0]);
603
+ return pkix.decodeNested(c.values[0], ctx, what + " control value");
603
604
  }
604
605
 
605
- function _decodePopChallenges(controls) {
606
+ function _decodePopChallenges(controls, ctx) {
606
607
  for (var i = 0; i < controls.length; i++) {
607
608
  var c = controls[i];
608
609
  if (c.attrType === OID_ENCRYPTED_POP) {
609
- c.encryptedPOP = parseEncryptedPop(_onlyValue(c, "an Encrypted POP"));
610
+ c.encryptedPOP = parseEncryptedPop(_onlyValue(c, "an Encrypted POP", ctx), ctx);
610
611
  } else if (c.attrType === OID_DECRYPTED_POP) {
611
- c.decryptedPOP = parseDecryptedPop(_onlyValue(c, "a Decrypted POP"));
612
+ c.decryptedPOP = parseDecryptedPop(_onlyValue(c, "a Decrypted POP", ctx));
612
613
  }
613
614
  }
614
615
  }
615
616
 
616
- function _collectStatuses(controls) {
617
+ function _collectStatuses(controls, ctx) {
617
618
  var out = [];
618
619
  for (var i = 0; i < controls.length; i++) {
619
620
  var c = controls[i];
@@ -622,15 +623,15 @@ function _collectStatuses(controls) {
622
623
  if (c.values.length !== 1) {
623
624
  throw E("cmc/bad-status-info", "a CMC status control carries exactly one AttributeValue, got " + c.values.length);
624
625
  }
625
- out.push(parseStatusInfo(c.values[0], version, c.bodyPartID));
626
+ out.push(parseStatusInfo(c.values[0], version, c.bodyPartID, ctx));
626
627
  }
627
628
  return out;
628
629
  }
629
630
 
630
- function _finishBody(body, where) {
631
+ function _finishBody(body, where, ctx) {
631
632
  for (var i = 0; i < body.controls.length; i++) assertControlPlacement(body.controls[i], where);
632
- _decodePopChallenges(body.controls);
633
- body.statuses = _collectStatuses(body.controls);
633
+ _decodePopChallenges(body.controls, ctx);
634
+ body.statuses = _collectStatuses(body.controls, ctx);
634
635
  body.unhandled = body.controls.filter(function (c) {
635
636
  return c.attrType !== OID_STATUS_INFO && c.attrType !== OID_STATUS_INFO_V2 && c.attrName === null;
636
637
  });
@@ -674,7 +675,7 @@ function parsePkiData(input, callerOpts) {
674
675
  return pkix.runParseWith(input, _BODY_PARSE_OPTS, callerOpts, function (root, ns) {
675
676
  var body = schema.walk(PKI_DATA, root, ns).result;
676
677
  body.bytes = root.bytes;
677
- return _finishBody(body, "pkiData");
678
+ return _finishBody(body, "pkiData", ns);
678
679
  });
679
680
  }
680
681
 
@@ -706,7 +707,7 @@ function parsePkiResponse(input, callerOpts) {
706
707
  return pkix.runParseWith(input, _BODY_PARSE_OPTS, callerOpts, function (root, ns) {
707
708
  var body = schema.walk(PKI_RESPONSE, root, ns).result;
708
709
  body.bytes = root.bytes;
709
- return _finishBody(body, "pkiResponse");
710
+ return _finishBody(body, "pkiResponse", ns);
710
711
  });
711
712
  }
712
713
 
@@ -793,7 +794,9 @@ function parse(input, callerOpts) {
793
794
  throw E("cmc/no-content",
794
795
  "a Full PKI Request / Response carries its body as the encapsulated content; this SignedData is detached (RFC 5272 sec. 3.2)");
795
796
  }
796
- var body = eContentType === OID_PKI_DATA ? parsePkiData(encap.eContent) : parsePkiResponse(encap.eContent);
797
+ var body = eContentType === OID_PKI_DATA
798
+ ? parsePkiData(encap.eContent, caps)
799
+ : parsePkiResponse(encap.eContent, caps);
797
800
  body.cms = parsedCms;
798
801
  body.eContentType = eContentType;
799
802
  return body;
package/lib/schema-cmp.js CHANGED
@@ -283,7 +283,7 @@ var GEN_MSG_CONTENT = schema.seqOf(INFO_TYPE_AND_VALUE, {
283
283
  build: function (m) { return m.items.map(function (it) { return it.value.result; }); },
284
284
  });
285
285
 
286
- var CERT_TEMPLATE_LEAF = schema.decode(function (n) { return crmf.walkCertTemplate(n); });
286
+ var CERT_TEMPLATE_LEAF = schema.decode(function (n, ctx) { return crmf.walkCertTemplate(n, ctx); });
287
287
  var REV_DETAILS = schema.seq([
288
288
  schema.field("certDetails", CERT_TEMPLATE_LEAF),
289
289
  schema.optional("crlEntryDetails", EXTENSIONS, { whenUniversal: [TAGS.SEQUENCE] }),
@@ -348,7 +348,7 @@ var ENCRYPTED_KEY = schema.choice([
348
348
  { when: { tagClass: "context", tagNumber: 0 },
349
349
  schema: schema.decode(function (n, ctx) {
350
350
  var env;
351
- try { env = cms.walkEnvelopedData(asn1.decode(asn1.sequenceTlv(n))); }
351
+ try { env = cms.walkEnvelopedData(pkix.decodeNested(asn1.sequenceTlv(n), ctx, "an EncryptedKey envelopedData"), ctx); }
352
352
  catch (e) {
353
353
  throw ctx.E("cmp/bad-cert-response", "envelopedData [0] must be a well-formed IMPLICIT EnvelopedData (RFC 9810 sec. 5.2.2)", e);
354
354
  }
@@ -521,7 +521,7 @@ var BODY = schema.decode(function (n, ctx) {
521
521
  var out = { arm: BODY_ARMS[n.tagNumber], tag: n.tagNumber, bytes: inner.bytes };
522
522
  if (CRMF_ARMS[n.tagNumber]) {
523
523
  var isCcr = n.tagNumber === 13;
524
- out.decoded = crmf.walkCertReqMessages(inner, { allowSigningAlg: isCcr, allowV1Version: isCcr });
524
+ out.decoded = crmf.walkCertReqMessages(inner, { allowSigningAlg: isCcr, allowV1Version: isCcr }, ctx);
525
525
  } else if (DECODED_ARMS[n.tagNumber]) {
526
526
  var match = schema.walk(DECODED_ARMS[n.tagNumber], inner, ctx);
527
527
  out.decoded = match.result;
@@ -612,7 +612,7 @@ var PKI_MESSAGE = schema.seq([
612
612
  for (var cn = 0; cn < controls.length; cn++) {
613
613
  if (controls[cn].type !== OID_PKI_ARCHIVE_OPTIONS) continue;
614
614
  var arch;
615
- try { arch = asn1.decode(controls[cn].value); }
615
+ try { arch = pkix.decodeNested(controls[cn].value, ctx, "a pkiArchiveOptions control value"); }
616
616
  catch (e) { throw ctx.E("cmp/bad-body", "a ccr pkiArchiveOptions control did not decode (RFC 9810 sec. 5.3.11)", e); }
617
617
  if (arch.tagClass === "context" && arch.tagNumber === 0) {
618
618
  throw ctx.E("cmp/bad-body", "a cross-certification request (ccr) must not send the private key -- a pkiArchiveOptions encryptedPrivKey control is forbidden (RFC 9810 sec. 5.3.11, sec. 5.2.8.3.1)");
@@ -631,7 +631,7 @@ var PKI_MESSAGE = schema.seq([
631
631
  if (archCtrls && header.pvno !== 3) {
632
632
  for (var ac = 0; ac < archCtrls.length; ac++) {
633
633
  if (archCtrls[ac].type !== OID_PKI_ARCHIVE_OPTIONS) continue;
634
- var opt = asn1.decode(archCtrls[ac].value);
634
+ var opt = pkix.decodeNested(archCtrls[ac].value, ctx, "a pkiArchiveOptions control value");
635
635
  if (opt.tagClass === "context" && opt.tagNumber === 0 && opt.children && opt.children.length >= 1 &&
636
636
  opt.children[0].tagClass === "context" && opt.children[0].tagNumber === 0) {
637
637
  throw ctx.E("cmp/bad-version", "a pkiArchiveOptions encryptedPrivKey using the EnvelopedData form requires CMP version cmp2021(3) (RFC 9810 sec. 5.2.8.3.1, sec. 7)");
@@ -643,7 +643,7 @@ var PKI_MESSAGE = schema.seq([
643
643
  if (header.generalInfo) {
644
644
  for (var gi = 0; gi < header.generalInfo.length; gi++) {
645
645
  if (header.generalInfo[gi].type !== OID_CERT_PROFILE) continue;
646
- var profileCount = asn1.decode(header.generalInfo[gi].value).children.length;
646
+ var profileCount = pkix.decodeNested(header.generalInfo[gi].value, ctx, "a certProfile infoValue").children.length;
647
647
  var bodyCount = null;
648
648
  if (body.arm === "p10cr") bodyCount = 1;
649
649
  else if (body.decoded && body.decoded.messages) bodyCount = body.decoded.messages.length;
@@ -654,13 +654,13 @@ var PKI_MESSAGE = schema.seq([
654
654
  }
655
655
  }
656
656
  if (body.arm === "ckuann" && header.pvno !== 3) {
657
- var caKeyUpd = asn1.decode(body.bytes);
657
+ var caKeyUpd = pkix.decodeNested(body.bytes, ctx, "a ckuann body");
658
658
  if (caKeyUpd.tagClass === "context" && caKeyUpd.tagNumber === 0) {
659
659
  throw ctx.E("cmp/bad-version", "a ckuann using the cAKeyUpdAnnV3 [0] RootCaKeyUpdateContent form requires CMP version cmp2021(3) (RFC 9810 sec. 5.3.13, sec. 7)");
660
660
  }
661
661
  }
662
662
  if (body.arm === "popdecc" && header.pvno !== 3) {
663
- var challenges = asn1.decode(body.bytes);
663
+ var challenges = pkix.decodeNested(body.bytes, ctx, "a popdecc body");
664
664
  if (challenges.tagClass === "universal" && challenges.tagNumber === TAGS.SEQUENCE && challenges.children) {
665
665
  for (var chi = 0; chi < challenges.children.length; chi++) {
666
666
  var chKids = challenges.children[chi].children;