@blamejs/pki 0.8.9 → 0.8.11

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.
@@ -28,6 +28,8 @@ var _charAt = intrinsic.uncurry(String.prototype.charAt);
28
28
  var _charCodeAt = intrinsic.uncurry(String.prototype.charCodeAt);
29
29
  var _split = intrinsic.uncurry(String.prototype.split);
30
30
  var _create = intrinsic.create;
31
+ var _Number = intrinsic.Number;
32
+ var _append = guard.list.append;
31
33
  var _isUint8Array = intrinsic.types.isUint8Array;
32
34
  var _bigIntToString = intrinsic.bigIntToString;
33
35
  var _weakGet = intrinsic.weakGet;
@@ -911,16 +913,39 @@ var CERT_FIXED_CRITICALITY_ROWS = [
911
913
  ["freshestCRL", false, "RFC 5280 sec. 4.2.1.15"], ["authorityInfoAccess", false, "RFC 5280 sec. 4.2.2.1"],
912
914
  ["subjectInfoAccess", false, "RFC 5280 sec. 4.2.2.2"],
913
915
  ["precertificatePoison", true, "RFC 6962 sec. 3.1"],
916
+ ["ipAddrBlocks", true, "RFC 3779 sec. 2.2.2"], ["autonomousSysIds", true, "RFC 3779 sec. 3.2.2"],
917
+ ["ipAddrBlocksV2", true, "RFC 8360 sec. 4.2.2, RFC 3779 sec. 2.2.2"],
918
+ ["autonomousSysIdsV2", true, "RFC 8360 sec. 4.2.2, RFC 3779 sec. 3.2.2"],
914
919
  ];
915
- /** @internal The table keyed by dotted OID through the registry the caller passes, since this
916
- * module takes its registry as a parameter rather than requiring it. */
917
- function certFixedCriticality(oidRegistry) {
920
+ /** @internal The criticality RFC 5280 sec. 5.2 fixes for a CRL extension. issuerAltName is absent:
921
+ * sec. 5.2.2 states its criticality as a SHOULD, and carrying it in a table of MUSTs would promote
922
+ * the requirement level the clause states. */
923
+ var CRL_FIXED_CRITICALITY_ROWS = [
924
+ ["authorityKeyIdentifier", false, "RFC 5280 sec. 5.2.1"], ["cRLNumber", false, "RFC 5280 sec. 5.2.3"],
925
+ ["deltaCRLIndicator", true, "RFC 5280 sec. 5.2.4"], ["issuingDistributionPoint", true, "RFC 5280 sec. 5.2.5"],
926
+ ["freshestCRL", false, "RFC 5280 sec. 5.2.6"], ["authorityInfoAccess", false, "RFC 5280 sec. 5.2.7"],
927
+ ];
928
+
929
+ /** @internal The criticality RFC 5280 sec. 5.3 fixes for a CRL ENTRY extension. Three consumers read
930
+ * this one table: the CRL signer, the linter, and the OCSP signer, since RFC 6960 sec. 4.4.5
931
+ * carries the same extensions into a SingleResponse. */
932
+ var CRL_ENTRY_FIXED_CRITICALITY_ROWS = [
933
+ ["reasonCode", false, "RFC 5280 sec. 5.3.1"], ["invalidityDate", false, "RFC 5280 sec. 5.3.2"],
934
+ ["certificateIssuer", true, "RFC 5280 sec. 5.3.3"],
935
+ ];
936
+
937
+ /** @internal A criticality table keyed by dotted OID through the registry the caller passes, since
938
+ * this module takes its registry as a parameter rather than requiring it. */
939
+ function _criticalityTable(rows, oidRegistry) {
918
940
  var table = _create(null);
919
- _forEach(CERT_FIXED_CRITICALITY_ROWS, function (r) {
941
+ _forEach(rows, function (r) {
920
942
  table[oidRegistry.byName(r[0])] = { critical: r[1], citation: r[2] };
921
943
  });
922
944
  return table;
923
945
  }
946
+ function certFixedCriticality(oidRegistry) { return _criticalityTable(CERT_FIXED_CRITICALITY_ROWS, oidRegistry); }
947
+ function crlFixedCriticality(oidRegistry) { return _criticalityTable(CRL_FIXED_CRITICALITY_ROWS, oidRegistry); }
948
+ function crlEntryFixedCriticality(oidRegistry) { return _criticalityTable(CRL_ENTRY_FIXED_CRITICALITY_ROWS, oidRegistry); }
924
949
 
925
950
  var GN_CONSTRUCTED = _assign(_create(null), { 0: 1, 3: 1, 4: 1, 5: 1 });
926
951
  var GN_IA5 = _assign(_create(null), { 1: 1, 2: 1, 6: 1 });
@@ -1259,6 +1284,358 @@ function _decodeHelpers(ns) {
1259
1284
  return { decodeTop: decodeTop, seqChildren: seqChildren, readInt: readInt, O: O };
1260
1285
  }
1261
1286
 
1287
+ /** @internal The extensions a CRL profiles, keyed by the scope that profiles them. RFC 5280
1288
+ * sec. 5.2 defines the extensions of the list and sec. 5.3 those of an entry, and the two sets are
1289
+ * disjoint: a `cRLNumber` sitting on an entry and a `reasonCode` sitting on the list are each an
1290
+ * OID nothing profiles THERE, so neither is decoded and neither is a fault. Reading one table at
1291
+ * both scopes is what made `lib/lint.js` apply the CERTIFICATE table at CRL scope.
1292
+ *
1293
+ * A caller that names no scope gets both tables, which is what an OCSP singleExtension needs:
1294
+ * RFC 6960 sec. 4.4.5 carries a CRL-entry extension in a response, where neither scope is the
1295
+ * whole answer. That agnostic reading is the shipped default and is why the tables are returned
1296
+ * separately rather than merged.
1297
+ *
1298
+ * Each decoder takes the extnValue and the parse context and returns the decoded value, throwing a
1299
+ * plain Error whose message the caller wraps in its own typed code, so a module keeps its own
1300
+ * `<prefix>/bad-extension-value` rather than inheriting one from here. */
1301
+ function crlExtensionDecoders(ns) {
1302
+ var _h = _decodeHelpers(ns), O = _h.O;
1303
+ var byScope = _create(null);
1304
+ byScope.crl = _create(null);
1305
+ byScope.entry = _create(null);
1306
+
1307
+ /** @internal RFC 5280 sec. 5.2.4 defines BaseCRLNumber AS a CRLNumber, so the two read alike and
1308
+ * the sec. 5.2.3 type's `INTEGER (0..MAX)` binds both. The width ceiling that section also
1309
+ * states is a PROFILE rule rather than a shape rule and stays with the linter, which could not
1310
+ * report on a CRL a parse had already refused. */
1311
+ function crlNumberValue(what) {
1312
+ return function (buf, ctx) {
1313
+ var v = asn1.read.integer(decodeNested(buf, ctx, "a " + what + " extension value"));
1314
+ if (v < 0n) throw new Error(what + " must be non-negative (INTEGER 0..MAX)");
1315
+ return v;
1316
+ };
1317
+ }
1318
+ byScope.crl[O("cRLNumber")] = crlNumberValue("cRLNumber");
1319
+ byScope.entry[O("reasonCode")] = function (buf, ctx) {
1320
+ var reason = asn1.read.enumerated(decodeNested(buf, ctx, "a reasonCode extension value"));
1321
+ /** @internal The decoded value is a BigInt and the table is keyed by its decimal text, so the
1322
+ * conversion is the captured one: a replaced `BigInt.prototype.toString` would otherwise
1323
+ * decide which reason codes this reader calls defined. */
1324
+ var key = _bigIntToString(reason);
1325
+ if (!_hasOwn(CRL_REASON_NAMES, key)) throw new Error("undefined CRLReason " + key);
1326
+ return _Number(reason);
1327
+ };
1328
+ byScope.entry[O("invalidityDate")] = function (buf, ctx) {
1329
+ var n = decodeNested(buf, ctx, "an invalidityDate extension value");
1330
+ if (n.tagClass !== "universal" || n.tagNumber !== asn1.TAGS.GENERALIZED_TIME) {
1331
+ throw new Error("invalidityDate must be a GeneralizedTime");
1332
+ }
1333
+ return asn1.read.time(n);
1334
+ };
1335
+
1336
+ /** @internal The decoder for one OID at one scope, or null. `scope` of `undefined` means both,
1337
+ * in the order the list is read before its entries, which is the order the shipped agnostic
1338
+ * reading already resolved them in. */
1339
+ function at(extOid, scope) {
1340
+ if (scope !== "entry" && _hasOwn(byScope.crl, extOid)) return byScope.crl[extOid];
1341
+ if (scope !== "crl" && _hasOwn(byScope.entry, extOid)) return byScope.entry[extOid];
1342
+ return null;
1343
+ }
1344
+
1345
+ /** @internal The wider tables the extension door reads: every extension RFC 5280 sec. 5.2 and
1346
+ * sec. 5.3 profile, including the ones whose syntax is a certificate extension's. They are NOT
1347
+ * `byScope`, because `byScope` is what the parse decodes in place and the linter can only report
1348
+ * a malformed extension the parse left opaque. */
1349
+ var doorScope = _create(null);
1350
+ doorScope.crl = _assign(_create(null), byScope.crl);
1351
+ doorScope.entry = _assign(_create(null), byScope.entry);
1352
+ _forEach(["authorityKeyIdentifier", "issuerAltName", "authorityInfoAccess", "freshestCRL"], function (n) {
1353
+ doorScope.crl[O(n)] = scopedCertDecoder(ns, n);
1354
+ });
1355
+ doorScope.entry[O("certificateIssuer")] = _generalNamesDecoder(ns);
1356
+ /** @internal RFC 5280 sec. 5.2.4 defines BaseCRLNumber AS a CRLNumber, so the sec. 5.2.3 type
1357
+ * binds it and the non-negative rule is the same one. It is registered for the door and NOT in
1358
+ * `byScope`, because a parse that decoded it could no longer open a CRL whose delta indicator is
1359
+ * malformed, which is the object the linter's value-syntax rule exists to report on. */
1360
+ doorScope.crl[O("deltaCRLIndicator")] = crlNumberValue("baseCRLNumber");
1361
+ doorScope.crl[O("issuingDistributionPoint")] = _issuingDistributionPointDecoder(ns);
1362
+
1363
+ return { byScope: byScope, at: at, doorScope: doorScope };
1364
+ }
1365
+
1366
+ /** @internal The door's reading of an IssuingDistributionPoint. The shared structural read reports a
1367
+ * fault rather than throwing, because path validation and linting both survey hostile input; the
1368
+ * door needs a decoder, so this is the throwing form over the same read. */
1369
+ function _issuingDistributionPointDecoder(ns) {
1370
+ var code = ns.prefix + "/bad-extension-value";
1371
+ return function (buf, ctx) {
1372
+ var read = decodeIssuingDistributionPointValue(ctx || ns, buf, code);
1373
+ if (read.malformed) {
1374
+ throw new Error("value is not a well-formed IssuingDistributionPoint (RFC 5280 sec. 5.2.5)");
1375
+ }
1376
+ return {
1377
+ distributionPoint: read.distributionPoint,
1378
+ onlyContainsUserCerts: read.onlyUser,
1379
+ onlyContainsCACerts: read.onlyCa,
1380
+ onlySomeReasons: read.onlySomeReasonsPresent ? read.onlySomeReasonsValue : null,
1381
+ indirectCRL: read.indirect,
1382
+ onlyContainsAttributeCerts: read.onlyAttr,
1383
+ };
1384
+ };
1385
+ }
1386
+
1387
+ /** @internal A certificate extension's decoder, reached from another format's table. The
1388
+ * certificate decoders close over the namespace they were built with, so a call that named caps
1389
+ * gets its own table and every decode below reads the caller's figure. A caller outside a parse
1390
+ * passes no context and reuses the module's table. */
1391
+ function scopedCertDecoder(ns, name) {
1392
+ var key = ns.oid.byName(name);
1393
+ var fixed = null;
1394
+ return function (buf, ctx) {
1395
+ if (ctx && (ctx.caps != null || ctx.budget != null)) {
1396
+ return certExtensionDecoders(schema.withResources(ns, ctx)).byOid[key](buf);
1397
+ }
1398
+ if (fixed === null) fixed = certExtensionDecoders(ns).byOid;
1399
+ return fixed[key](buf);
1400
+ };
1401
+ }
1402
+
1403
+ /** @internal certificateIssuer is a GeneralNames, which the CRL profile leaves raw at parse time
1404
+ * and the door reads. */
1405
+ function _generalNamesDecoder(ns) {
1406
+ var NAMES = generalNames(ns, { code: ns.prefix + "/bad-extension-value" });
1407
+ return function (buf, ctx) {
1408
+ return schema.walk(NAMES, decodeNested(buf, ctx || ns, "a certificateIssuer extension value"), ctx || ns).result;
1409
+ };
1410
+ }
1411
+
1412
+ /** @internal One decoded extension, as the public door hands it back. Eleven own properties, every
1413
+ * one always present, so a caller reads the same shape whatever happened to the value.
1414
+ *
1415
+ * `state` is the discriminator and is read first: `"decoded"` when the decoder produced a value,
1416
+ * `"unrecognized"` when no decoder is registered for that OID at that scope, `"undecodable"` when
1417
+ * one is and the value did not read as the structure its identifier names. `decoded` carries the
1418
+ * value only in the first arm and is `null` in the other two, and nothing may test `decoded` for
1419
+ * truthiness to tell them apart: `ocspNoCheck` decodes VALIDLY to null.
1420
+ *
1421
+ * `value` is the raw extnValue octets in every arm, byte-identical to the certificate's, because a
1422
+ * caller that has to recompute a hash or compare an encoding needs the bytes and not a rendering
1423
+ * of them. `code` is the typed error the decoder threw in the undecodable arm and `null`
1424
+ * otherwise. `profile` carries the criticality the scope's RFC fixes for that OID, with the clause
1425
+ * that fixes it and whether the encoded flag deviates, and is `null` for an extension whose
1426
+ * criticality the issuer chooses.
1427
+ *
1428
+ * `index` is the position in the SEQUENCE the row came from and `containerIndex` the position of
1429
+ * that SEQUENCE's container within the object: the revoked-certificate entry at `crl-entry` scope,
1430
+ * the `extensionRequest` attribute at `csr-requested` scope, and `null` for a list the object
1431
+ * carries directly. `scope` names which of the two it is, so one field serves both. */
1432
+ function _extensionRow(ext, opts, index, state, decoded, code, profile) {
1433
+ var row = _create(null);
1434
+ row.oid = ext.oid;
1435
+ row.name = ext.name === undefined ? null : ext.name;
1436
+ row.critical = ext.critical === true;
1437
+ row.value = ext.value;
1438
+ row.scope = opts.scope;
1439
+ row.index = index;
1440
+ row.containerIndex = opts.containerIndex === undefined ? null : opts.containerIndex;
1441
+ row.state = state;
1442
+ row.decoded = decoded;
1443
+ row.code = code;
1444
+ row.profile = profile;
1445
+ return row;
1446
+ }
1447
+
1448
+ /** @internal The door itself, parameterized by the scope it reads at and the table that scope
1449
+ * profiles, so each format module wires its own rather than this file reaching into theirs. The
1450
+ * attribute-certificate table lives in `schema-attrcert.js`, and a registry here that reached for
1451
+ * it would invert the dependency.
1452
+ *
1453
+ * `opts.decoders` is the OID-keyed table, `opts.scope` the key each row carries, `opts.criticality`
1454
+ * the fixed-criticality table or null, and `opts.strict` turns the undecodable arm into a throw.
1455
+ * An unrecognized OID is never a throw, in any mode, at any scope: refusing one would make it
1456
+ * impossible to READ a certificate carrying a private critical extension, which is what
1457
+ * `pki.inspect` and `pki.lint` are for. RFC 5280 sec. 4.2's reject-on-critical rule is the
1458
+ * caller's to apply, and the two facts it needs, `critical` and `state`, are on the row. */
1459
+ function decodeExtensionList(list, opts) {
1460
+ var out = [];
1461
+ for (var i = 0; i < list.length; i++) _append(out, decodeOneExtension(list[i], i, opts));
1462
+ return out;
1463
+ }
1464
+
1465
+ /** @internal One row, so the single-extension verb and the table verb answer from one reader. */
1466
+ function decodeOneExtension(ext, index, opts) {
1467
+ var decoders = opts.decoders || _create(null);
1468
+ var criticality = opts.criticality || null;
1469
+ var profile = null;
1470
+ if (criticality !== null && _hasOwn(criticality, ext.oid)) {
1471
+ var fixed = criticality[ext.oid];
1472
+ profile = _create(null);
1473
+ profile.criticalExpected = fixed.critical;
1474
+ profile.citation = fixed.citation;
1475
+ profile.deviates = (ext.critical === true) !== fixed.critical;
1476
+ }
1477
+ if (!_hasOwn(decoders, ext.oid)) {
1478
+ return _extensionRow(ext, opts, index, "unrecognized", null, null, profile);
1479
+ }
1480
+ /** @internal `failed` rather than a test on the caught value: a decoder that threw something
1481
+ * falsy would otherwise read as a decode that produced `undefined`, and the row would say
1482
+ * `decoded` for a value nothing decoded. */
1483
+ var decoded, thrown = null, failed = false;
1484
+ try { decoded = decoders[ext.oid](ext.value, opts.ctx); }
1485
+ catch (e) { thrown = e; failed = true; }
1486
+ if (failed) {
1487
+ /** @internal A table's decoders do not all throw typed errors: the ones a parse composes throw
1488
+ * a plain Error so the parse can wrap them in its own code. The row carries a code in every
1489
+ * arm, so an untyped throw becomes the format's own `bad-extension-value` here. */
1490
+ var carriesCode = thrown !== null && thrown !== undefined && typeof thrown.code === "string";
1491
+ var typed = carriesCode ? thrown : opts.wrap(ext, thrown);
1492
+ if (opts.strict === true) throw typed;
1493
+ return _extensionRow(ext, opts, index, "undecodable", null, typed.code, profile);
1494
+ }
1495
+ return _extensionRow(ext, opts, index, "decoded", decoded, null, profile);
1496
+ }
1497
+
1498
+ /** @internal The caps a caller may tighten on an extension door, and the two flags it takes
1499
+ * besides. `groups` is offered only by the door that has more than one list to group. */
1500
+ var EXTENSION_DOOR_OPTS = _assign(_create(null), { maxBytes: 1, maxDepth: 1, maxItems: 1, strict: 1 });
1501
+ var EXTENSION_DOOR_GROUP_OPTS = _assign(_create(null), _assign(_create(null), EXTENSION_DOOR_OPTS), { groups: 1 });
1502
+ var EXTENSION_CAP_KEYS = ["maxBytes", "maxDepth", "maxItems"];
1503
+
1504
+ /** @internal The public door onto one object's decoded extensions, built once here and wired by each
1505
+ * format module with its own scopes, so the option handling, the caps, the budget latch and the row
1506
+ * shape are stated in one place and no format can answer differently from another.
1507
+ *
1508
+ * `spec.scopes` maps each scope key this format reads to `{ decoders, criticality }`.
1509
+ * The attribute-certificate table lives in `schema-attrcert.js` and is passed in rather than
1510
+ * reached for, or the dependency inverts. `spec.segments(parsed, read)` names the lists to read and
1511
+ * the scope and container index of each; `spec.defaultScope` is the scope the single-extension verb
1512
+ * reads at, and a format with more than one scope leaves it out and requires `opts.scope`.
1513
+ *
1514
+ * Caps bound the decoding THIS call performs. Handed bytes the door parses under them; handed a
1515
+ * parse result it reads that result, whose own caps the caller chose when they parsed. */
1516
+ function extensionDoor(spec) {
1517
+ var ns = spec.ns;
1518
+ var prefix = ns.prefix;
1519
+ var badInput = prefix + "/bad-input";
1520
+ var knownOpts = spec.groups === true ? EXTENSION_DOOR_GROUP_OPTS : EXTENSION_DOOR_OPTS;
1521
+ var capOpts = parseOpts({ ErrorClass: spec.ErrorClass, prefix: prefix, what: spec.what });
1522
+ var scopeNames = intrinsic.keys(spec.scopes);
1523
+ function E(code, message, cause) { return new spec.ErrorClass(code, message, cause); }
1524
+
1525
+ function readOpts(callerOpts, verb, wantsScope) {
1526
+ var checked = guard.identifier.optionsObject(callerOpts, E, badInput, verb + ": opts");
1527
+ var known = wantsScope ? _assign(_create(null), _assign(_create(null), knownOpts), { scope: 1 }) : knownOpts;
1528
+ guard.identifier.assertKnownKeys(checked, known, E, badInput,
1529
+ "pki.schema." + spec.key + "." + verb + " does not take the option ");
1530
+ var asked = _create(null);
1531
+ for (var i = 0; i < EXTENSION_CAP_KEYS.length; i++) {
1532
+ var k = EXTENSION_CAP_KEYS[i];
1533
+ if (checked[k] !== undefined) asked[k] = checked[k];
1534
+ }
1535
+ var read = _create(null);
1536
+ read.caps = parseCaps(asked, capOpts);
1537
+ read.strict = checked.strict === true;
1538
+ read.groups = checked.groups === true;
1539
+ read.scope = checked.scope;
1540
+ read.tables = _create(null);
1541
+ return read;
1542
+ }
1543
+
1544
+ /** @internal The scope's tables plus this call's walk context, as one options object the row
1545
+ * reader takes. A fresh context per call, so one call's budget cannot latch another's.
1546
+ *
1547
+ * `table.decoders` is a FUNCTION of the call's namespace rather than a table, because a decoder
1548
+ * built against the module's namespace carries the module's caps: the certificate decoders take
1549
+ * the value alone and reach their bounds through the namespace they were built with, so a table
1550
+ * held at module load would decode a caller's value under the built-in ceilings whatever caps
1551
+ * that caller named. Built once per call and reused across every segment, so a CRL's entries do
1552
+ * not rebuild it per entry. */
1553
+ function scopeOpts(key, read, containerIndex) {
1554
+ var table = spec.scopes[key];
1555
+ var out = _create(null);
1556
+ if (!_hasOwn(read.tables, key)) read.tables[key] = table.decoders(read.ctx.ns);
1557
+ out.decoders = read.tables[key];
1558
+ out.criticality = table.criticality === undefined ? null : table.criticality;
1559
+ out.scope = key;
1560
+ out.containerIndex = containerIndex;
1561
+ out.strict = read.strict;
1562
+ out.ctx = read.ctx.ns;
1563
+ out.wrap = wrapValueFault;
1564
+ return out;
1565
+ }
1566
+
1567
+ var badValueCode = prefix + "/bad-extension-value";
1568
+ function wrapValueFault(ext, thrown) {
1569
+ return E(badValueCode, "malformed " + (ext.name || ext.oid) + " extension value: " +
1570
+ guard.text.describeThrown(thrown), thrown);
1571
+ }
1572
+
1573
+ function decodeExtensions(input, callerOpts) {
1574
+ var read = readOpts(callerOpts, "decodeExtensions", false);
1575
+ /** @internal A parse result is re-derived from the bytes it recorded, to prove it is the
1576
+ * unmodified output of this format's parser. That re-derivation is not work this call asked
1577
+ * for, so the caps do not bound it: they bound the decoding, and a caller naming a cap smaller
1578
+ * than the whole object would otherwise be refused an extension value that fits inside it.
1579
+ * Caps DO bound the parse of bytes the caller handed in, which is work this call performs. */
1580
+ var fromBytes = typeof input === "string" || guard.bytes.isByteSource(input);
1581
+ var parsed = guard.parsed.acceptDerived(input, spec.kind, function (bytes) {
1582
+ return fromBytes ? spec.parse(bytes, read.caps) : spec.parse(bytes);
1583
+ }, E, badInput, spec.what);
1584
+ read.ctx = nestedContext(ns, read.caps);
1585
+ var segments = spec.segments(parsed, read);
1586
+ var out = [];
1587
+ for (var s = 0; s < segments.length; s++) {
1588
+ var seg = segments[s];
1589
+ var rows = decodeExtensionList(seg.list, scopeOpts(seg.scope, read, seg.containerIndex));
1590
+ for (var r = 0; r < rows.length; r++) _append(out, rows[r]);
1591
+ }
1592
+ if (read.ctx.budget.exhausted()) {
1593
+ throw E(prefix + "/too-large", spec.what + " exceeds the decode budget for this call");
1594
+ }
1595
+ return read.groups ? spec.group(out, segments) : out;
1596
+ }
1597
+
1598
+ function decodeExtension(ext, callerOpts) {
1599
+ var read = readOpts(callerOpts, "decodeExtension", spec.defaultScope === undefined);
1600
+ var key = read.scope === undefined ? spec.defaultScope : read.scope;
1601
+ if (typeof key !== "string" || !_hasOwn(spec.scopes, key)) {
1602
+ throw E(badInput, "pki.schema." + spec.key + ".decodeExtension needs opts.scope naming which " +
1603
+ "scope to read at, one of " + _join(scopeNames, ", ") + "; got " + _String(key));
1604
+ }
1605
+ var record = _acceptExtensionRecord(ext, E, badInput, spec.key);
1606
+ read.ctx = nestedContext(ns, read.caps);
1607
+ var row = decodeOneExtension(record, 0, scopeOpts(key, read, undefined));
1608
+ if (read.ctx.budget.exhausted()) {
1609
+ throw E(prefix + "/too-large", "the extension value exceeds the decode budget for this call");
1610
+ }
1611
+ return row;
1612
+ }
1613
+
1614
+ return { decodeExtensions: decodeExtensions, decodeExtension: decodeExtension };
1615
+ }
1616
+
1617
+ /** @internal The single-extension verbs take the record `parse` puts in an object's extension list.
1618
+ * The three fields the row is built from are read off a snapshot, so a caller object cannot answer
1619
+ * one value to the check and another to the decode. */
1620
+ function _acceptExtensionRecord(ext, E, code, key) {
1621
+ var checked = guard.identifier.optionsObject(ext, E, code,
1622
+ "pki.schema." + key + ".decodeExtension: the extension");
1623
+ if (typeof checked.oid !== "string" || checked.oid.length === 0) {
1624
+ throw E(code, "pki.schema." + key + ".decodeExtension takes one extension record from a parse " +
1625
+ "result, as { oid, name, critical, value }; its oid must be a dotted string");
1626
+ }
1627
+ if (!guard.bytes.isByteSource(checked.value)) {
1628
+ throw E(code, "pki.schema." + key + ".decodeExtension: the extension's value must be the raw " +
1629
+ "extnValue octets");
1630
+ }
1631
+ var record = _create(null);
1632
+ record.oid = checked.oid;
1633
+ record.name = typeof checked.name === "string" ? checked.name : null;
1634
+ record.critical = checked.critical === true;
1635
+ record.value = guard.bytes.snapshot(checked.value, E, code, "the extension value");
1636
+ return record;
1637
+ }
1638
+
1262
1639
  function certExtensionDecoders(ns) {
1263
1640
  var GN_SUBTREE = generalName(ns, { decodeValue: true, subtreeBase: true, code: ns.prefix + "/bad-name-constraints" });
1264
1641
  var _h = _decodeHelpers(ns), decodeTop = _h.decodeTop, seqChildren = _h.seqChildren, readInt = _h.readInt, O = _h.O;
@@ -1686,7 +2063,114 @@ function certExtensionDecoders(ns) {
1686
2063
  return hash;
1687
2064
  }
1688
2065
 
2066
+ /** @internal RFC 7633 sec. 4: Features ::= SEQUENCE OF INTEGER, each an entry of the TLS
2067
+ * ExtensionType registry. The type carries no range, so a feature is read as the INTEGER it is
2068
+ * and a number outside the registry's 16-bit width is the caller's to judge. */
2069
+ function tlsFeature(buf) {
2070
+ var C = ns.prefix + "/bad-tls-feature";
2071
+ var kids = seqChildren(buf, C, "Features");
2072
+ return { features: _map(kids, function (n) {
2073
+ if (n.tagClass !== "universal" || n.tagNumber !== _T.INTEGER) throw ns.E(C, "a Features element must be an INTEGER (RFC 7633 sec. 4)");
2074
+ return readInt(n, C, "a feature");
2075
+ }) };
2076
+ }
2077
+
2078
+ /** @internal RFC 3779 sec. 2.2.3. An IPAddress is a BIT STRING whose bits are the leading bits of
2079
+ * the address, so a prefix is its length in bits and a range is a pair of them. The address
2080
+ * family is the two-octet IANA AFI, with an optional third octet naming the SAFI. */
2081
+ function _ipAddress(n, C, what) {
2082
+ if (n.tagClass !== "universal" || n.tagNumber !== _T.BIT_STRING) throw ns.E(C, what + " must be a BIT STRING (RFC 3779 sec. 2.1.1)");
2083
+ var bs;
2084
+ try { bs = asn1.read.bitString(n); }
2085
+ catch (e) { throw ns.E(C, what + " must be a well-formed BIT STRING", e); }
2086
+ return { unusedBits: bs.unusedBits, bytes: bs.bytes, prefixLength: bs.bytes.length * 8 - bs.unusedBits };
2087
+ }
2088
+ function ipAddrBlocks(buf) {
2089
+ var C = ns.prefix + "/bad-ip-addr-blocks";
2090
+ var families = seqChildren(buf, C, "IPAddrBlocks");
2091
+ return { families: _map(families, function (f) {
2092
+ if (f.tagClass !== "universal" || f.tagNumber !== _T.SEQUENCE || !f.children || f.children.length !== 2) {
2093
+ throw ns.E(C, "an IPAddressFamily must be a SEQUENCE { addressFamily, ipAddressChoice } (RFC 3779 sec. 2.2.3)");
2094
+ }
2095
+ var afi;
2096
+ try { afi = _bufferConcat([asn1.read.octetString(f.children[0])]); }
2097
+ catch (e) { throw ns.E(C, "an IPAddressFamily addressFamily must be an OCTET STRING", e); }
2098
+ if (afi.length < 2 || afi.length > 3) throw ns.E(C, "an IPAddressFamily addressFamily must be 2 or 3 octets (RFC 3779 sec. 2.2.3.3)");
2099
+ var choice = f.children[1];
2100
+ var inherit = choice.tagClass === "universal" && choice.tagNumber === _T.NULL;
2101
+ if (inherit) {
2102
+ try { asn1.read.nullValue(choice); }
2103
+ catch (e) { throw ns.E(C, "an inherit IPAddressChoice must be a NULL carrying no content", e); }
2104
+ } else if (choice.tagClass !== "universal" || choice.tagNumber !== _T.SEQUENCE || !choice.children) {
2105
+ throw ns.E(C, "an IPAddressChoice must be an inherit NULL or a SEQUENCE OF IPAddressOrRange (RFC 3779 sec. 2.2.3.7)");
2106
+ }
2107
+ return {
2108
+ addressFamily: afi, afi: (afi[0] << 8) | afi[1], safi: afi.length === 3 ? afi[2] : null,
2109
+ inherit: inherit,
2110
+ addressesOrRanges: inherit ? null : _map(choice.children, function (r) {
2111
+ if (r.tagClass === "universal" && r.tagNumber === _T.BIT_STRING) {
2112
+ return { kind: "addressPrefix", addressPrefix: _ipAddress(r, C, "an addressPrefix") };
2113
+ }
2114
+ if (r.tagClass !== "universal" || r.tagNumber !== _T.SEQUENCE || !r.children || r.children.length !== 2) {
2115
+ throw ns.E(C, "an IPAddressOrRange must be an addressPrefix BIT STRING or an addressRange SEQUENCE { min, max } (RFC 3779 sec. 2.2.3.7)");
2116
+ }
2117
+ return { kind: "addressRange", min: _ipAddress(r.children[0], C, "an addressRange min"),
2118
+ max: _ipAddress(r.children[1], C, "an addressRange max") };
2119
+ }),
2120
+ };
2121
+ }) };
2122
+ }
2123
+
2124
+ /** @internal RFC 3779 sec. 3.2.3. `ASId ::= INTEGER` carries no range, so an AS number is read as
2125
+ * the INTEGER it is and one outside the 32 bits RFC 6793 sec. 2 gives the registry is the
2126
+ * caller's to judge. Both arms of the SEQUENCE are EXPLICIT because ASIdentifierChoice is a
2127
+ * CHOICE. */
2128
+ function _asIdChoice(wrap, C, what) {
2129
+ if (!wrap.children || wrap.children.length !== 1) throw ns.E(C, "an " + what + " [n] must wrap exactly one ASIdentifierChoice (RFC 3779 sec. 3.2.3)");
2130
+ var n = wrap.children[0];
2131
+ if (n.tagClass === "universal" && n.tagNumber === _T.NULL) {
2132
+ try { asn1.read.nullValue(n); }
2133
+ catch (e) { throw ns.E(C, "an inherit ASIdentifierChoice must be a NULL carrying no content", e); }
2134
+ return { inherit: true, asIdsOrRanges: null };
2135
+ }
2136
+ if (n.tagClass !== "universal" || n.tagNumber !== _T.SEQUENCE || !n.children) {
2137
+ throw ns.E(C, "an ASIdentifierChoice must be an inherit NULL or a SEQUENCE OF ASIdOrRange (RFC 3779 sec. 3.2.3)");
2138
+ }
2139
+ function asId(node, label) {
2140
+ if (node.tagClass !== "universal" || node.tagNumber !== _T.INTEGER) throw ns.E(C, label + " must be an INTEGER (RFC 3779 sec. 3.2.3)");
2141
+ return readInt(node, C, label);
2142
+ }
2143
+ return { inherit: false, asIdsOrRanges: _map(n.children, function (r) {
2144
+ if (r.tagClass === "universal" && r.tagNumber === _T.INTEGER) return { kind: "id", id: asId(r, "an ASId") };
2145
+ if (r.tagClass !== "universal" || r.tagNumber !== _T.SEQUENCE || !r.children || r.children.length !== 2) {
2146
+ throw ns.E(C, "an ASIdOrRange must be an ASId INTEGER or an ASRange SEQUENCE { min, max } (RFC 3779 sec. 3.2.3)");
2147
+ }
2148
+ return { kind: "range", min: asId(r.children[0], "an ASRange min"), max: asId(r.children[1], "an ASRange max") };
2149
+ }) };
2150
+ }
2151
+ function autonomousSysIds(buf) {
2152
+ var C = ns.prefix + "/bad-autonomous-sys-ids";
2153
+ var kids = seqChildren(buf, C, "ASIdentifiers");
2154
+ var asnum = null, rdi = null, seen = -1;
2155
+ for (var i = 0; i < kids.length; i++) {
2156
+ var k = kids[i];
2157
+ if (k.tagClass !== "context" || (k.tagNumber !== 0 && k.tagNumber !== 1)) {
2158
+ throw ns.E(C, "ASIdentifiers carries only asnum [0] and rdi [1] (RFC 3779 sec. 3.2.3)");
2159
+ }
2160
+ if (k.tagNumber <= seen) throw ns.E(C, "ASIdentifiers components must appear in tag order and at most once (RFC 3779 sec. 3.2.3)");
2161
+ seen = k.tagNumber;
2162
+ if (k.tagNumber === 0) asnum = _asIdChoice(k, C, "asnum");
2163
+ else rdi = _asIdChoice(k, C, "rdi");
2164
+ }
2165
+ return { asnum: asnum, rdi: rdi };
2166
+ }
2167
+
1689
2168
  var byOid = _create(null);
2169
+ byOid[O("tlsFeature")] = tlsFeature;
2170
+ byOid[O("ipAddrBlocks")] = ipAddrBlocks;
2171
+ byOid[O("ipAddrBlocksV2")] = ipAddrBlocks;
2172
+ byOid[O("autonomousSysIds")] = autonomousSysIds;
2173
+ byOid[O("autonomousSysIdsV2")] = autonomousSysIds;
1690
2174
  byOid[O("qcStatements")] = qcStatements;
1691
2175
  byOid[O("basicConstraints")] = basicConstraints;
1692
2176
  byOid[O("keyUsage")] = keyUsage;
@@ -1919,7 +2403,13 @@ module.exports = {
1919
2403
  rawNonEmptySequence: rawNonEmptySequence,
1920
2404
  CRL_REASON_NAMES: CRL_REASON_NAMES,
1921
2405
  certFixedCriticality: certFixedCriticality,
2406
+ crlFixedCriticality: crlFixedCriticality,
2407
+ crlEntryFixedCriticality: crlEntryFixedCriticality,
1922
2408
  certExtensionDecoders: certExtensionDecoders,
2409
+ scopedCertDecoder: scopedCertDecoder,
2410
+ crlExtensionDecoders: crlExtensionDecoders,
2411
+ decodeExtensionList: decodeExtensionList,
2412
+ extensionDoor: extensionDoor,
1923
2413
  _decodeHelpers: _decodeHelpers,
1924
2414
  attribute: attribute,
1925
2415
  extension: extension,