@blamejs/blamejs-shop 0.5.19 → 0.5.21
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.
- package/CHANGELOG.md +4 -0
- package/README.md +1 -0
- package/SECURITY.md +17 -0
- package/lib/addresses.js +2 -2
- package/lib/admin.js +49 -45
- package/lib/affiliates.js +7 -23
- package/lib/announcement-bar.js +5 -22
- package/lib/api-keys.js +4 -13
- package/lib/asset-manifest.json +1 -1
- package/lib/banner-ab-tests.js +5 -9
- package/lib/blog-articles.js +8 -26
- package/lib/captcha-gate.js +7 -17
- package/lib/carrier-accounts.js +3 -10
- package/lib/catalog-drafts.js +5 -12
- package/lib/category-navigation.js +4 -20
- package/lib/cms-blocks.js +4 -7
- package/lib/compliance-export.js +4 -11
- package/lib/consent-ledger.js +2 -4
- package/lib/cost-layers.js +56 -21
- package/lib/customer-import.js +2 -2
- package/lib/customer-notes.js +7 -23
- package/lib/customer-roles.js +3 -5
- package/lib/customer-segments.js +17 -14
- package/lib/customer-surveys.js +7 -14
- package/lib/customers.js +2 -4
- package/lib/dispute-resolution.js +5 -13
- package/lib/dropship-forwarding.js +3 -5
- package/lib/dunning.js +2 -7
- package/lib/email-ab-tests.js +4 -8
- package/lib/email-campaigns.js +25 -14
- package/lib/email-warmup.js +2 -7
- package/lib/experiments.js +6 -10
- package/lib/externaldb-d1.js +78 -44
- package/lib/geolocation.js +18 -28
- package/lib/gift-options.js +5 -23
- package/lib/knowledge-base.js +7 -22
- package/lib/line-gift-wrap.js +3 -17
- package/lib/live-chat.js +5 -18
- package/lib/metered-usage.js +3 -8
- package/lib/notifications.js +3 -7
- package/lib/operator-accounts.js +3 -5
- package/lib/operator-approvals.js +6 -8
- package/lib/operator-audit-log.js +2 -7
- package/lib/operator-help-center.js +5 -21
- package/lib/operator-inbox.js +4 -11
- package/lib/operator-roles.js +5 -7
- package/lib/order-escalation.js +2 -2
- package/lib/order-export.js +24 -20
- package/lib/order-notes.js +4 -14
- package/lib/order-ratings.js +4 -10
- package/lib/payment-methods.js +5 -13
- package/lib/payment-retries.js +2 -7
- package/lib/payment.js +103 -58
- package/lib/pixel-events.js +8 -23
- package/lib/plan-changes.js +2 -7
- package/lib/product-qa.js +4 -8
- package/lib/promo-banners.js +7 -15
- package/lib/purchase-orders.js +3 -6
- package/lib/push-notifications.js +7 -32
- package/lib/pwa-manifest.js +6 -11
- package/lib/quotes.js +5 -9
- package/lib/referrals.js +10 -6
- package/lib/reviews.js +4 -10
- package/lib/robots-config.js +6 -14
- package/lib/sales-tax-filings.js +2 -2
- package/lib/search-facets.js +5 -5
- package/lib/search-ranking.js +4 -7
- package/lib/search-synonyms.js +7 -21
- package/lib/security-middleware.js +125 -70
- package/lib/seller-signup.js +10 -26
- package/lib/sidebar-widgets.js +6 -15
- package/lib/site-redirects.js +49 -137
- package/lib/sitemap-generator.js +3 -7
- package/lib/sms-dispatcher.js +7 -23
- package/lib/stock-receipts.js +4 -10
- package/lib/storefront-dashboards.js +2 -10
- package/lib/storefront-forms.js +9 -22
- package/lib/storefront-pages.js +6 -20
- package/lib/storefront.js +21 -23
- package/lib/subscription-billing.js +3 -8
- package/lib/subscription-controls.js +2 -7
- package/lib/suggestion-box.js +9 -26
- package/lib/support-tickets.js +6 -24
- package/lib/tax-remittance.js +2 -2
- package/lib/tenants.js +2 -7
- package/lib/text-guard.js +137 -35
- package/lib/theme-assets.js +4 -16
- package/lib/translations.js +3 -6
- package/lib/trust-badges.js +4 -7
- package/lib/vendor/MANIFEST.json +107 -97
- package/lib/vendor/blamejs/CHANGELOG.md +180 -0
- package/lib/vendor/blamejs/NOTICE +14 -10
- package/lib/vendor/blamejs/README.md +17 -5
- package/lib/vendor/blamejs/index.js +2 -0
- package/lib/vendor/blamejs/lib/acme.js +9 -9
- package/lib/vendor/blamejs/lib/api-snapshot.js +35 -16
- package/lib/vendor/blamejs/lib/app-shutdown.js +1 -1
- package/lib/vendor/blamejs/lib/archive-adapters.js +1 -1
- package/lib/vendor/blamejs/lib/archive.js +13 -24
- package/lib/vendor/blamejs/lib/auth/access-lock.js +2 -1
- package/lib/vendor/blamejs/lib/auth/bot-challenge.js +3 -6
- package/lib/vendor/blamejs/lib/auth/ciba.js +32 -3
- package/lib/vendor/blamejs/lib/auth/oauth.js +65 -8
- package/lib/vendor/blamejs/lib/auth/password.js +1 -1
- package/lib/vendor/blamejs/lib/auth/saml.js +21 -3
- package/lib/vendor/blamejs/lib/auth-bot-challenge.js +3 -3
- package/lib/vendor/blamejs/lib/backup/index.js +5 -5
- package/lib/vendor/blamejs/lib/case-fold-classes.js +491 -0
- package/lib/vendor/blamejs/lib/codepoint-class.js +131 -0
- package/lib/vendor/blamejs/lib/constants.js +79 -0
- package/lib/vendor/blamejs/lib/db-declare-view.js +8 -2
- package/lib/vendor/blamejs/lib/error-page.js +20 -1
- package/lib/vendor/blamejs/lib/external-db.js +5 -1
- package/lib/vendor/blamejs/lib/flag-evaluation-context.js +24 -6
- package/lib/vendor/blamejs/lib/flag.js +28 -2
- package/lib/vendor/blamejs/lib/framework-schema.js +14 -3
- package/lib/vendor/blamejs/lib/guard-regex.js +2345 -89
- package/lib/vendor/blamejs/lib/http-client.js +217 -40
- package/lib/vendor/blamejs/lib/mail-bimi.js +1 -1
- package/lib/vendor/blamejs/lib/mail-crypto-pgp.js +3 -2
- package/lib/vendor/blamejs/lib/mail-dav.js +26 -26
- package/lib/vendor/blamejs/lib/mail-deploy.js +10 -10
- package/lib/vendor/blamejs/lib/mail-scan.js +3 -0
- package/lib/vendor/blamejs/lib/mail-store.js +7 -1
- package/lib/vendor/blamejs/lib/mail.js +5 -1
- package/lib/vendor/blamejs/lib/middleware/age-gate.js +3 -2
- package/lib/vendor/blamejs/lib/middleware/api-encrypt.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/assetlinks.js +2 -1
- package/lib/vendor/blamejs/lib/middleware/asyncapi-serve.js +3 -2
- package/lib/vendor/blamejs/lib/middleware/bearer-auth.js +2 -1
- package/lib/vendor/blamejs/lib/middleware/compression.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/cors.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/csp-report.js +5 -5
- package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +2 -1
- package/lib/vendor/blamejs/lib/middleware/daily-byte-quota.js +2 -2
- package/lib/vendor/blamejs/lib/middleware/deny-response.js +2 -1
- package/lib/vendor/blamejs/lib/middleware/dpop.js +2 -2
- package/lib/vendor/blamejs/lib/middleware/fetch-metadata.js +2 -1
- package/lib/vendor/blamejs/lib/middleware/flag-context.js +17 -0
- package/lib/vendor/blamejs/lib/middleware/idempotency-key.js +10 -8
- package/lib/vendor/blamejs/lib/middleware/openapi-serve.js +3 -2
- package/lib/vendor/blamejs/lib/middleware/require-aal.js +3 -2
- package/lib/vendor/blamejs/lib/middleware/require-auth.js +4 -3
- package/lib/vendor/blamejs/lib/middleware/require-bound-key.js +4 -3
- package/lib/vendor/blamejs/lib/middleware/require-content-type.js +3 -2
- package/lib/vendor/blamejs/lib/middleware/require-methods.js +3 -2
- package/lib/vendor/blamejs/lib/middleware/require-mtls.js +3 -2
- package/lib/vendor/blamejs/lib/middleware/security-txt.js +2 -1
- package/lib/vendor/blamejs/lib/middleware/web-app-manifest.js +2 -1
- package/lib/vendor/blamejs/lib/network-dns-resolver.js +1 -1
- package/lib/vendor/blamejs/lib/network-dns.js +3 -3
- package/lib/vendor/blamejs/lib/network-nts.js +35 -14
- package/lib/vendor/blamejs/lib/network-proxy.js +42 -4
- package/lib/vendor/blamejs/lib/network-smtp-policy.js +1 -1
- package/lib/vendor/blamejs/lib/network-tls.js +341 -11
- package/lib/vendor/blamejs/lib/nist-crosswalk.js +2 -2
- package/lib/vendor/blamejs/lib/ntp-check.js +30 -19
- package/lib/vendor/blamejs/lib/object-store/azure-blob.js +1 -1
- package/lib/vendor/blamejs/lib/object-store/gcs.js +1 -1
- package/lib/vendor/blamejs/lib/object-store/http-put.js +2 -1
- package/lib/vendor/blamejs/lib/object-store/sigv4-bucket-ops.js +5 -5
- package/lib/vendor/blamejs/lib/object-store/sigv4.js +2 -2
- package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +4 -2
- package/lib/vendor/blamejs/lib/openapi.js +1 -1
- package/lib/vendor/blamejs/lib/pqc-agent.js +4 -7
- package/lib/vendor/blamejs/lib/problem-details.js +2 -1
- package/lib/vendor/blamejs/lib/redis-client.js +12 -1
- package/lib/vendor/blamejs/lib/regex-linear.js +1349 -0
- package/lib/vendor/blamejs/lib/render.js +531 -7
- package/lib/vendor/blamejs/lib/request-helpers.js +181 -5
- package/lib/vendor/blamejs/lib/router.js +37 -13
- package/lib/vendor/blamejs/lib/safe-async.js +142 -0
- package/lib/vendor/blamejs/lib/safe-icap.js +3 -0
- package/lib/vendor/blamejs/lib/safe-sql.js +15 -3
- package/lib/vendor/blamejs/lib/self-update.js +2 -2
- package/lib/vendor/blamejs/lib/testing.js +54 -7
- package/lib/vendor/blamejs/lib/validate-opts.js +56 -0
- package/lib/vendor/blamejs/lib/vendor/MANIFEST.json +62 -25
- package/lib/vendor/blamejs/lib/vendor/blamejs-pki.cjs +2004 -142
- package/lib/vendor/blamejs/lib/vendor/browser/noble-ciphers.mjs +727 -0
- package/lib/vendor/blamejs/lib/vendor/browser/noble-hashes.mjs +1070 -0
- package/lib/vendor/blamejs/lib/vendor/browser/noble-post-quantum.mjs +1090 -0
- package/lib/vendor/blamejs/lib/vendor/noble-post-quantum.cjs +510 -227
- package/lib/vendor/blamejs/lib/webhook-hmac.js +19 -2
- package/lib/vendor/blamejs/lib/webhook.js +1 -1
- package/lib/vendor/blamejs/lib/ws-client.js +24 -2
- package/lib/vendor/blamejs/package.json +1 -1
- package/lib/vendor/blamejs/sbom.cdx.json +6 -6
- package/lib/vendor-invoices.js +3 -6
- package/lib/vendors.js +5 -19
- package/lib/webhook-receiver.js +46 -83
- package/lib/webhook-subscriptions.js +3 -13
- package/lib/wishlist-sharing.js +5 -10
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// @blamejs/pki v0.4.
|
|
1
|
+
// @blamejs/pki v0.4.13 — vendored (Apache-2.0). Zero-dep pure CJS.
|
|
2
2
|
// https://github.com/blamejs/pki Exports: x509, crl, pkcs12, key, webcrypto, schema, csr, cms, ...
|
|
3
3
|
// Backs lib/mtls-engine-default.js (PQC-capable CA + PKCS#12 engine).
|
|
4
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -139,7 +139,7 @@ var require_package = __commonJS({
|
|
|
139
139
|
"node_modules/@blamejs/pki/package.json"(exports2, module2) {
|
|
140
140
|
module2.exports = {
|
|
141
141
|
name: "@blamejs/pki",
|
|
142
|
-
version: "0.4.
|
|
142
|
+
version: "0.4.13",
|
|
143
143
|
description: "Pure-JavaScript PKI toolkit that owns its stack \u2014 X.509, ASN.1/DER, CMS, PQC-first.",
|
|
144
144
|
license: "Apache-2.0",
|
|
145
145
|
author: "blamejs contributors",
|
|
@@ -454,6 +454,51 @@ var require_constants = __commonJS({
|
|
|
454
454
|
// terminates but exhausts memory. This matches PATH_MAX_CERTS: a chain longer than the path
|
|
455
455
|
// validator will ever accept has nothing to offer, so refusing it at the decoder is free.
|
|
456
456
|
TLS_CERT_MAX_ENTRIES: 100,
|
|
457
|
+
// A FIDO Metadata Service BLOB is a JWS whose payload carries every registered authenticator's
|
|
458
|
+
// metadata; the live one runs about 10 MB across ~500 entries. The byte cap bounds the decode
|
|
459
|
+
// before the payload is materialized, and the entry and anchor caps bound the per-entry work
|
|
460
|
+
// (each anchor is a DER certificate parse), since a byte ceiling alone does not bound how many
|
|
461
|
+
// items are declared inside it (CWE-770).
|
|
462
|
+
MDS_BLOB_MAX_BYTES: BYTES.mib(32),
|
|
463
|
+
// The BLOB's JWS protected header is read BEFORE the signature is checked, so it carries its own,
|
|
464
|
+
// far smaller ceiling: a header is a few hundred bytes plus the x5c chain, and the envelope cap
|
|
465
|
+
// would otherwise let unauthenticated input buy heap ahead of every authentication step.
|
|
466
|
+
MDS_BLOB_HEADER_MAX_BYTES: BYTES.kib(256),
|
|
467
|
+
// The JWS signature, likewise read before anything is authenticated. Every algorithm this reader
|
|
468
|
+
// supports has a tightly bounded signature: 64/96/132 bytes for ECDSA P-256/384/521, and the
|
|
469
|
+
// modulus size for RSA. 2 KiB covers an RSA-16384 key with room to spare, and refuses a segment
|
|
470
|
+
// whose only purpose is to make the verifier allocate.
|
|
471
|
+
MDS_BLOB_SIG_MAX_BYTES: BYTES.kib(2),
|
|
472
|
+
MDS_MAX_ENTRIES: 4096,
|
|
473
|
+
// A model's certification history: bounded like the other repeated per-entry structures, because
|
|
474
|
+
// the status gate walks the whole array on every verification.
|
|
475
|
+
MDS_MAX_STATUS_REPORTS_PER_ENTRY: 256,
|
|
476
|
+
MDS_MAX_ANCHORS_PER_ENTRY: 16,
|
|
477
|
+
// A U2F authenticator carries no AAGUID, so its entry is keyed by the key identifiers of its
|
|
478
|
+
// attestation certificates instead -- a batch-attested product line legitimately registers dozens.
|
|
479
|
+
MDS_MAX_KEY_IDS_PER_ENTRY: 64,
|
|
480
|
+
// The most nested statements a WebAuthn compound attestation (sec. 8.9) may carry. The syntax
|
|
481
|
+
// says "2*" -- unbounded -- so this is a resource bound this toolkit chooses, NOT a spec MUST.
|
|
482
|
+
// The CBOR parse caps bound the decode; they do not bound the crypto, and each element costs a
|
|
483
|
+
// signature verification plus, for some formats, a full certificate-path validation. Seven
|
|
484
|
+
// non-compound formats are registered, so a conforming statement carrying one of each is 7.
|
|
485
|
+
WEBAUTHN_COMPOUND_MAX_STATEMENTS: 16,
|
|
486
|
+
// The most certificates a WebAuthn attestation chain may carry, in an attStmt x5c array or a JWS
|
|
487
|
+
// x5c header. A real attestation chain is one to four; the byte ceiling on a single entry does
|
|
488
|
+
// not bound the COUNT, so an array of thousands of small certificates is an unbounded parse and
|
|
489
|
+
// signature-check fanout (CWE-770) that terminates but costs far more CPU than wire. This is a
|
|
490
|
+
// resource bound this toolkit chooses -- no specification states it -- and it is far tighter than
|
|
491
|
+
// PATH_MAX_CERTS because an attestation chain is not a general PKI path.
|
|
492
|
+
WEBAUTHN_X5C_MAX_CERTS: 10,
|
|
493
|
+
// A WebAuthn android-safetynet attestation statement carries the SafetyNet response as a JWS
|
|
494
|
+
// compact serialization: two small JSON objects plus a signature, with the certificate chain
|
|
495
|
+
// inline in the header. Real ones run a few kilobytes. The cap bounds the text decode before the
|
|
496
|
+
// string is materialized, so an oversized statement is refused rather than allocated (CWE-770).
|
|
497
|
+
SAFETYNET_JWS_MAX_BYTES: BYTES.kib(64),
|
|
498
|
+
// One x5c entry is a single DER certificate; PATH_MAX_CERT_BYTES is the ceiling the path
|
|
499
|
+
// validator already applies to any certificate it will accept, and an entry above it could not
|
|
500
|
+
// chain even if it decoded.
|
|
501
|
+
SAFETYNET_CERT_MAX_BYTES: BYTES.kib(64),
|
|
457
502
|
// ACME challenge token entropy floor (RFC 8555 sec. 8, errata 6950): >= 128
|
|
458
503
|
// bits of base64url is >= 22 characters. A shorter token is refused before use.
|
|
459
504
|
ACME_TOKEN_MIN_CHARS: 22,
|
|
@@ -1160,7 +1205,15 @@ var require_guard_identifier = __commonJS({
|
|
|
1160
1205
|
if (root < 2n && second > 39n) throw E(bcode, who + " second arc must be 0..39 under roots 0 and 1 (X.660)");
|
|
1161
1206
|
return str;
|
|
1162
1207
|
}
|
|
1163
|
-
|
|
1208
|
+
function assertKnownKeys(obj, known, E, code, message) {
|
|
1209
|
+
var describe = typeof message === "function" ? message : function(k) {
|
|
1210
|
+
return message + JSON.stringify(k);
|
|
1211
|
+
};
|
|
1212
|
+
Object.keys(obj).forEach(function(k) {
|
|
1213
|
+
if (!Object.prototype.hasOwnProperty.call(known, k)) throw E(code, describe(k));
|
|
1214
|
+
});
|
|
1215
|
+
}
|
|
1216
|
+
module2.exports = { assertCanonicalOid, assertKnownKeys };
|
|
1164
1217
|
}
|
|
1165
1218
|
});
|
|
1166
1219
|
|
|
@@ -1271,6 +1324,26 @@ var require_guard_compress = __commonJS({
|
|
|
1271
1324
|
}
|
|
1272
1325
|
});
|
|
1273
1326
|
|
|
1327
|
+
// node_modules/@blamejs/pki/lib/guard-secret.js
|
|
1328
|
+
var require_guard_secret = __commonJS({
|
|
1329
|
+
"node_modules/@blamejs/pki/lib/guard-secret.js"(exports2, module2) {
|
|
1330
|
+
"use strict";
|
|
1331
|
+
var bytes = require_guard_bytes();
|
|
1332
|
+
function zeroize(value, ErrorClass, code, label) {
|
|
1333
|
+
if (value === null || value === void 0) return value;
|
|
1334
|
+
var view = bytes.view(value, ErrorClass, code, label);
|
|
1335
|
+
view.fill(0);
|
|
1336
|
+
return value;
|
|
1337
|
+
}
|
|
1338
|
+
function zeroizeAll(list, ErrorClass, code, label) {
|
|
1339
|
+
if (!list) return list;
|
|
1340
|
+
for (var i = 0; i < list.length; i++) zeroize(list[i], ErrorClass, code, label);
|
|
1341
|
+
return list;
|
|
1342
|
+
}
|
|
1343
|
+
module2.exports = { zeroize, zeroizeAll };
|
|
1344
|
+
}
|
|
1345
|
+
});
|
|
1346
|
+
|
|
1274
1347
|
// node_modules/@blamejs/pki/lib/guard-all.js
|
|
1275
1348
|
var require_guard_all = __commonJS({
|
|
1276
1349
|
"node_modules/@blamejs/pki/lib/guard-all.js"(exports2, module2) {
|
|
@@ -1287,6 +1360,7 @@ var require_guard_all = __commonJS({
|
|
|
1287
1360
|
var identifier = require_guard_identifier();
|
|
1288
1361
|
var header = require_guard_header();
|
|
1289
1362
|
var compress = require_guard_compress();
|
|
1363
|
+
var secret = require_guard_secret();
|
|
1290
1364
|
module2.exports = {
|
|
1291
1365
|
bytes,
|
|
1292
1366
|
text,
|
|
@@ -1299,7 +1373,8 @@ var require_guard_all = __commonJS({
|
|
|
1299
1373
|
json,
|
|
1300
1374
|
identifier,
|
|
1301
1375
|
header,
|
|
1302
|
-
compress
|
|
1376
|
+
compress,
|
|
1377
|
+
secret
|
|
1303
1378
|
};
|
|
1304
1379
|
}
|
|
1305
1380
|
});
|
|
@@ -2612,7 +2687,14 @@ var require_oid = __commonJS({
|
|
|
2612
2687
|
// id-pe-tlsfeature (RFC 7633) -- the TLS Feature (formerly "must-staple") extension.
|
|
2613
2688
|
tlsFeature: 24,
|
|
2614
2689
|
// id-pe-qcStatements (RFC 3739 sec. 3.2.6) -- the qualified-certificate-statements extension.
|
|
2615
|
-
qcStatements: 3
|
|
2690
|
+
qcStatements: 3,
|
|
2691
|
+
// RFC 3779 -- the IP-address and AS-number delegation extensions that carry a resource
|
|
2692
|
+
// certificate's authority (RPKI). Each has an RFC 8360 "v2" twin with identical syntax and
|
|
2693
|
+
// stricter path-validation semantics, so both are registered here.
|
|
2694
|
+
ipAddrBlocks: 7,
|
|
2695
|
+
autonomousSysIds: 8,
|
|
2696
|
+
ipAddrBlocksV2: 28,
|
|
2697
|
+
autonomousSysIdsV2: 29
|
|
2616
2698
|
} },
|
|
2617
2699
|
// RFC 3739 sec. 3.2.6.1 id-qcs -- the PKIX QCStatement statementIds carrying SemanticsInformation.
|
|
2618
2700
|
pkixQcSyntax: { base: [1, 3, 6, 1, 5, 5, 7, 11], of: { qcsPkixQCSyntaxV1: 1, qcsPkixQCSyntaxV2: 2 } },
|
|
@@ -3282,11 +3364,26 @@ var require_oid = __commonJS({
|
|
|
3282
3364
|
function paramsMustBeAbsent(dotted) {
|
|
3283
3365
|
return _PARAMS_ABSENT.has(dotted);
|
|
3284
3366
|
}
|
|
3367
|
+
var KEM_PARAMS = /* @__PURE__ */ Object.create(null);
|
|
3368
|
+
[
|
|
3369
|
+
["id-ml-kem-512", 800, 1632, 768, 32],
|
|
3370
|
+
["id-ml-kem-768", 1184, 2400, 1088, 32],
|
|
3371
|
+
["id-ml-kem-1024", 1568, 3168, 1568, 32]
|
|
3372
|
+
].forEach(function(r) {
|
|
3373
|
+
var row = Object.freeze({ ek: r[1], dk: r[2], ct: r[3], ss: r[4] });
|
|
3374
|
+
KEM_PARAMS[byName(r[0])] = row;
|
|
3375
|
+
KEM_PARAMS[r[0]] = row;
|
|
3376
|
+
});
|
|
3377
|
+
Object.freeze(KEM_PARAMS);
|
|
3378
|
+
function kemParams(oidOrName) {
|
|
3379
|
+
return KEM_PARAMS[oidOrName];
|
|
3380
|
+
}
|
|
3285
3381
|
module2.exports = {
|
|
3286
3382
|
name,
|
|
3287
3383
|
byName,
|
|
3288
3384
|
has,
|
|
3289
3385
|
paramsMustBeAbsent,
|
|
3386
|
+
kemParams,
|
|
3290
3387
|
register,
|
|
3291
3388
|
registerFamily,
|
|
3292
3389
|
all,
|
|
@@ -3415,7 +3512,15 @@ var require_webcrypto = __commonJS({
|
|
|
3415
3512
|
this.usages = usages ? usages.slice() : [];
|
|
3416
3513
|
Object.defineProperty(this, "_handle", { value: handle, enumerable: false });
|
|
3417
3514
|
}
|
|
3515
|
+
function _requireOwnKey(key, who) {
|
|
3516
|
+
if (key instanceof CryptoKey) return;
|
|
3517
|
+
if (isCryptoKeyLike(key)) {
|
|
3518
|
+
throw new WebCryptoError("webcrypto/invalid-access", who + ": the key was created by a different WebCrypto implementation; re-import it through this one");
|
|
3519
|
+
}
|
|
3520
|
+
throw new WebCryptoError("webcrypto/invalid-access", who + ": a CryptoKey is required");
|
|
3521
|
+
}
|
|
3418
3522
|
function _requireUsage(key, usage) {
|
|
3523
|
+
_requireOwnKey(key, usage);
|
|
3419
3524
|
if (key.usages.indexOf(usage) === -1) {
|
|
3420
3525
|
throw new WebCryptoError("webcrypto/invalid-access", "key is not permitted for '" + usage + "' (usages: " + key.usages.join(",") + ")");
|
|
3421
3526
|
}
|
|
@@ -3721,6 +3826,7 @@ var require_webcrypto = __commonJS({
|
|
|
3721
3826
|
var name = alg.name;
|
|
3722
3827
|
if (name === "ECDH" || name === "X25519" || name === "X448") {
|
|
3723
3828
|
_requireAlgMatch(alg, alg.public, name + " public key");
|
|
3829
|
+
_requireOwnKey(alg.public, "deriveBits public key");
|
|
3724
3830
|
var secret = nodeCrypto.diffieHellman({ privateKey: key._handle, publicKey: alg.public._handle });
|
|
3725
3831
|
if (length == null) return _toArrayBuffer(secret);
|
|
3726
3832
|
_requireDeriveLength(length, name);
|
|
@@ -3731,8 +3837,13 @@ var require_webcrypto = __commonJS({
|
|
|
3731
3837
|
}
|
|
3732
3838
|
if (name === "HKDF") {
|
|
3733
3839
|
_requireDeriveLength(length, "HKDF");
|
|
3734
|
-
var
|
|
3735
|
-
|
|
3840
|
+
var ikm = _secretBytes(key);
|
|
3841
|
+
try {
|
|
3842
|
+
var derived = nodeCrypto.hkdfSync(_hashNode(alg.hash, "HKDF"), ikm, _toBuf(alg.salt, "HKDF salt"), _toBuf(alg.info || Buffer.alloc(0), "HKDF info"), length / 8);
|
|
3843
|
+
return derived instanceof ArrayBuffer ? derived : _toArrayBuffer(Buffer.from(derived));
|
|
3844
|
+
} finally {
|
|
3845
|
+
guard.secret.zeroize(ikm, WebCryptoError, "webcrypto/operation", "the HKDF input key material");
|
|
3846
|
+
}
|
|
3736
3847
|
}
|
|
3737
3848
|
if (name === "PBKDF2") {
|
|
3738
3849
|
_requireDeriveLength(length, "PBKDF2");
|
|
@@ -3797,7 +3908,11 @@ var require_webcrypto = __commonJS({
|
|
|
3797
3908
|
} catch (e) {
|
|
3798
3909
|
throw new WebCryptoError("webcrypto/operation", "encapsulateBits: ML-KEM encapsulation failed", e);
|
|
3799
3910
|
}
|
|
3800
|
-
|
|
3911
|
+
try {
|
|
3912
|
+
return { sharedKey: _toArrayBuffer(r.sharedKey), ciphertext: _toArrayBuffer(r.ciphertext) };
|
|
3913
|
+
} finally {
|
|
3914
|
+
guard.secret.zeroize(r.sharedKey, WebCryptoError, "webcrypto/operation", "the KEM shared secret");
|
|
3915
|
+
}
|
|
3801
3916
|
};
|
|
3802
3917
|
SubtleCrypto.prototype.decapsulateBits = async function decapsulateBits(algorithm, decapsulationKey, ciphertext) {
|
|
3803
3918
|
var alg = _normalizeAlg(algorithm, "decapsulateBits");
|
|
@@ -3806,13 +3921,24 @@ var require_webcrypto = __commonJS({
|
|
|
3806
3921
|
_requireAlgMatch(alg, decapsulationKey, "decapsulateBits");
|
|
3807
3922
|
if (decapsulationKey.type !== "private") throw new WebCryptoError("webcrypto/invalid-access", "decapsulateBits requires a private (decapsulation) key, got " + JSON.stringify(decapsulationKey.type));
|
|
3808
3923
|
var ct = _toBuf(ciphertext, "decapsulateBits ciphertext");
|
|
3924
|
+
var kemRow = oid.kemParams("id-" + ML_KEM_NODE[alg.name]);
|
|
3925
|
+
if (kemRow && ct.length !== kemRow.ct) {
|
|
3926
|
+
throw new WebCryptoError(
|
|
3927
|
+
"webcrypto/bad-kem-ciphertext",
|
|
3928
|
+
"decapsulateBits: " + alg.name + " expects a " + kemRow.ct + "-octet ciphertext, got " + ct.length + " (FIPS 203 sec. 7.3)"
|
|
3929
|
+
);
|
|
3930
|
+
}
|
|
3809
3931
|
var ss;
|
|
3810
3932
|
try {
|
|
3811
3933
|
ss = nodeCrypto.decapsulate(decapsulationKey._handle, ct);
|
|
3812
3934
|
} catch (e) {
|
|
3813
3935
|
throw new WebCryptoError("webcrypto/operation", "decapsulateBits: ML-KEM decapsulation failed (malformed or wrong-length ciphertext)", e);
|
|
3814
3936
|
}
|
|
3815
|
-
|
|
3937
|
+
try {
|
|
3938
|
+
return _toArrayBuffer(ss);
|
|
3939
|
+
} finally {
|
|
3940
|
+
guard.secret.zeroize(ss, WebCryptoError, "webcrypto/operation", "the KEM shared secret");
|
|
3941
|
+
}
|
|
3816
3942
|
};
|
|
3817
3943
|
SubtleCrypto.prototype.wrapKey = async function wrapKey(format, key, wrappingKey, wrapAlgorithm) {
|
|
3818
3944
|
var exported = await this.exportKey(format, key);
|
|
@@ -3825,11 +3951,15 @@ var require_webcrypto = __commonJS({
|
|
|
3825
3951
|
if (bytes.length < 16 || bytes.length % 8 !== 0) {
|
|
3826
3952
|
throw new WebCryptoError("webcrypto/operation", "wrapKey: AES-KW requires the serialized key be a multiple of 8 bytes (>= 16); got " + bytes.length + " -- format " + JSON.stringify(format) + " is not AES-KW-wrappable");
|
|
3827
3953
|
}
|
|
3954
|
+
var wkBytes = null;
|
|
3828
3955
|
try {
|
|
3829
|
-
|
|
3956
|
+
wkBytes = _secretBytes(wrappingKey);
|
|
3957
|
+
var c = nodeCrypto.createCipheriv("aes" + wrappingKey.algorithm.length + "-wrap", wkBytes, Buffer.from("A6A6A6A6A6A6A6A6", "hex"));
|
|
3830
3958
|
return _toArrayBuffer(Buffer.concat([c.update(bytes), c.final()]));
|
|
3831
3959
|
} catch (e) {
|
|
3832
3960
|
throw new WebCryptoError("webcrypto/operation", "wrapKey: AES-KW key wrap failed", e);
|
|
3961
|
+
} finally {
|
|
3962
|
+
guard.secret.zeroize(wkBytes, WebCryptoError, "webcrypto/operation", "the AES-KW wrapping key");
|
|
3833
3963
|
}
|
|
3834
3964
|
}
|
|
3835
3965
|
var wrapKeyClone = _cloneWithUsage(wrappingKey, "encrypt");
|
|
@@ -3846,11 +3976,15 @@ var require_webcrypto = __commonJS({
|
|
|
3846
3976
|
if (wrapped.length < 24 || wrapped.length % 8 !== 0) {
|
|
3847
3977
|
throw new WebCryptoError("webcrypto/operation", "unwrapKey: AES-KW wrapped key must be a multiple of 8 bytes (>= 24); got " + wrapped.length);
|
|
3848
3978
|
}
|
|
3979
|
+
var kwBytes = null;
|
|
3849
3980
|
try {
|
|
3850
|
-
|
|
3981
|
+
kwBytes = _secretBytes(unwrappingKey);
|
|
3982
|
+
var d = nodeCrypto.createDecipheriv("aes" + unwrappingKey.algorithm.length + "-wrap", kwBytes, Buffer.from("A6A6A6A6A6A6A6A6", "hex"));
|
|
3851
3983
|
bytes = Buffer.concat([d.update(wrapped), d.final()]);
|
|
3852
3984
|
} catch (e) {
|
|
3853
3985
|
throw new WebCryptoError("webcrypto/operation", "unwrapKey: AES-KW key unwrap failed (integrity or length)", e);
|
|
3986
|
+
} finally {
|
|
3987
|
+
guard.secret.zeroize(kwBytes, WebCryptoError, "webcrypto/operation", "the AES-KW unwrapping key");
|
|
3854
3988
|
}
|
|
3855
3989
|
} else {
|
|
3856
3990
|
var unwrapKeyClone = _cloneWithUsage(unwrappingKey, "decrypt");
|
|
@@ -3871,7 +4005,11 @@ var require_webcrypto = __commonJS({
|
|
|
3871
4005
|
} else {
|
|
3872
4006
|
keyData = bytes;
|
|
3873
4007
|
}
|
|
3874
|
-
|
|
4008
|
+
try {
|
|
4009
|
+
return await this.importKey(format, keyData, unwrappedKeyAlgorithm, extractable, keyUsages);
|
|
4010
|
+
} finally {
|
|
4011
|
+
guard.secret.zeroize(bytes, WebCryptoError, "webcrypto/operation", "the unwrapped key material");
|
|
4012
|
+
}
|
|
3875
4013
|
};
|
|
3876
4014
|
function _cloneWithUsage(key, usage) {
|
|
3877
4015
|
var k = new CryptoKey(key.type, key.extractable, key.algorithm, key.usages.concat([usage]), key._handle);
|
|
@@ -3891,9 +4029,10 @@ var require_webcrypto = __commonJS({
|
|
|
3891
4029
|
}
|
|
3892
4030
|
}
|
|
3893
4031
|
var ML_KEM_INNER = {};
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
4032
|
+
["id-ml-kem-512", "id-ml-kem-768", "id-ml-kem-1024"].forEach(function(n) {
|
|
4033
|
+
var row = oid.kemParams(n);
|
|
4034
|
+
ML_KEM_INNER[oid.byName(n)] = { ek: row.ek, dk: row.dk };
|
|
4035
|
+
});
|
|
3897
4036
|
function _isOctet(node, size) {
|
|
3898
4037
|
return node && node.tagClass === "universal" && node.tagNumber === asn1.TAGS.OCTET_STRING && !node.constructed && node.content && node.content.length === size;
|
|
3899
4038
|
}
|
|
@@ -4056,12 +4195,17 @@ var require_webcrypto = __commonJS({
|
|
|
4056
4195
|
return void 0;
|
|
4057
4196
|
}
|
|
4058
4197
|
SubtleCrypto.prototype.exportKey = async function exportKey(format, key) {
|
|
4198
|
+
_requireOwnKey(key, "exportKey");
|
|
4059
4199
|
if (!key.extractable) throw new WebCryptoError("webcrypto/invalid-access", "key is not extractable");
|
|
4060
4200
|
if (format === "jwk") return key._handle.export({ format: "jwk" });
|
|
4061
4201
|
if (key.type === "secret") {
|
|
4062
4202
|
var raw = key._handle.export();
|
|
4063
|
-
|
|
4064
|
-
|
|
4203
|
+
try {
|
|
4204
|
+
if (format === "raw") return _toArrayBuffer(raw);
|
|
4205
|
+
throw new WebCryptoError("webcrypto/not-supported", "exportKey: secret keys support 'raw' / 'jwk' only");
|
|
4206
|
+
} finally {
|
|
4207
|
+
guard.secret.zeroize(raw, WebCryptoError, "webcrypto/operation", "the exported secret key");
|
|
4208
|
+
}
|
|
4065
4209
|
}
|
|
4066
4210
|
if (format === "spki") return _toArrayBuffer(key._handle.export({ format: "der", type: "spki" }));
|
|
4067
4211
|
if (format === "pkcs8") return _toArrayBuffer(key._handle.export({ format: "der", type: "pkcs8" }));
|
|
@@ -4099,13 +4243,66 @@ var require_webcrypto = __commonJS({
|
|
|
4099
4243
|
throw E(code, "EC point is not on curve " + nodeCurve + " (de-compression failed)", e);
|
|
4100
4244
|
}
|
|
4101
4245
|
}
|
|
4246
|
+
var _crypto = new Crypto();
|
|
4247
|
+
var _EXPORT_FORMAT = Object.assign(/* @__PURE__ */ Object.create(null), { "private": "pkcs8", "public": "spki", "secret": "raw" });
|
|
4248
|
+
function isCryptoKeyLike(x) {
|
|
4249
|
+
return !!x && typeof x === "object" && typeof x.type === "string" && typeof x.extractable === "boolean" && !!x.algorithm && typeof x.algorithm === "object" && typeof x.algorithm.name === "string" && Array.isArray(x.usages);
|
|
4250
|
+
}
|
|
4251
|
+
function exportAnyKey(key, E, code) {
|
|
4252
|
+
var format = _EXPORT_FORMAT[key && key.type];
|
|
4253
|
+
if (!format) throw E(code, "a CryptoKey with a private, public, or secret type is required");
|
|
4254
|
+
if (key instanceof CryptoKey) {
|
|
4255
|
+
return Promise.resolve().then(function() {
|
|
4256
|
+
return _crypto.subtle.exportKey(format, key);
|
|
4257
|
+
}).then(function(b) {
|
|
4258
|
+
return Buffer.from(b);
|
|
4259
|
+
});
|
|
4260
|
+
}
|
|
4261
|
+
if (!key.extractable) {
|
|
4262
|
+
throw E(code, "the CryptoKey comes from a different WebCrypto implementation and is not extractable, so its key material cannot be reached; import it through pki.webcrypto.subtle, or pass the key as DER");
|
|
4263
|
+
}
|
|
4264
|
+
var handle = key._handle;
|
|
4265
|
+
if (handle instanceof nodeCrypto.KeyObject && handle.type === key.type) {
|
|
4266
|
+
return Promise.resolve().then(function() {
|
|
4267
|
+
return format === "raw" ? handle.export() : handle.export({ format: "der", type: format });
|
|
4268
|
+
}).then(function(b) {
|
|
4269
|
+
return Buffer.from(b);
|
|
4270
|
+
}, function(e) {
|
|
4271
|
+
throw E(code, "the CryptoKey comes from a different copy of this WebCrypto engine and its key material could not be read; import it through pki.webcrypto.subtle, or pass the key as DER", e);
|
|
4272
|
+
});
|
|
4273
|
+
}
|
|
4274
|
+
return Promise.resolve().then(function() {
|
|
4275
|
+
return nodeCrypto.webcrypto.subtle.exportKey(format, key);
|
|
4276
|
+
}).then(function(b) {
|
|
4277
|
+
return Buffer.from(b);
|
|
4278
|
+
}, function(e) {
|
|
4279
|
+
throw E(code, "the CryptoKey comes from a different WebCrypto implementation and could not be exported for re-import; import it through pki.webcrypto.subtle, or pass the key as DER", e);
|
|
4280
|
+
});
|
|
4281
|
+
}
|
|
4282
|
+
function adoptKey(key, importParams, usages, E, code) {
|
|
4283
|
+
if (key instanceof CryptoKey) return Promise.resolve(key);
|
|
4284
|
+
if (!Array.isArray(key.usages)) throw E(code, "a CryptoKey carrying its permitted usages is required");
|
|
4285
|
+
for (var i = 0; i < usages.length; i++) {
|
|
4286
|
+
if (key.usages.indexOf(usages[i]) === -1) {
|
|
4287
|
+
throw E(code, "the CryptoKey is not permitted for '" + usages[i] + "' (usages: " + key.usages.join(",") + ")");
|
|
4288
|
+
}
|
|
4289
|
+
}
|
|
4290
|
+
return Promise.resolve().then(function() {
|
|
4291
|
+
return exportAnyKey(key, E, code);
|
|
4292
|
+
}).then(function(der) {
|
|
4293
|
+
return _crypto.subtle.importKey(_EXPORT_FORMAT[key.type], der, importParams || key.algorithm, false, usages);
|
|
4294
|
+
});
|
|
4295
|
+
}
|
|
4102
4296
|
module2.exports = {
|
|
4103
|
-
webcrypto:
|
|
4297
|
+
webcrypto: _crypto,
|
|
4104
4298
|
Crypto,
|
|
4105
4299
|
SubtleCrypto,
|
|
4106
4300
|
CryptoKey,
|
|
4107
4301
|
WebCryptoError,
|
|
4108
|
-
decompressEcPoint
|
|
4302
|
+
decompressEcPoint,
|
|
4303
|
+
isCryptoKeyLike,
|
|
4304
|
+
exportAnyKey,
|
|
4305
|
+
adoptKey
|
|
4109
4306
|
};
|
|
4110
4307
|
}
|
|
4111
4308
|
});
|
|
@@ -5269,6 +5466,7 @@ var require_validator_tpm = __commonJS({
|
|
|
5269
5466
|
"node_modules/@blamejs/pki/lib/validator-tpm.js"(exports2, module2) {
|
|
5270
5467
|
"use strict";
|
|
5271
5468
|
var ByteReader = require_byte_reader();
|
|
5469
|
+
var guard = require_guard_all();
|
|
5272
5470
|
var TPM_GENERATED_VALUE = 4283712327;
|
|
5273
5471
|
var TPM_ST_ATTEST_CERTIFY = 32791;
|
|
5274
5472
|
var TPM_ALG = { RSA: 1, SHA1: 4, SHA256: 11, SHA384: 12, SHA512: 13, NULL: 16, ECC: 35 };
|
|
@@ -5308,12 +5506,43 @@ var require_validator_tpm = __commonJS({
|
|
|
5308
5506
|
r.u16();
|
|
5309
5507
|
}
|
|
5310
5508
|
}
|
|
5509
|
+
var TPMA_OBJECT_BITS = Object.assign(/* @__PURE__ */ Object.create(null), {
|
|
5510
|
+
fixedTPM: 1,
|
|
5511
|
+
stClear: 2,
|
|
5512
|
+
fixedParent: 4,
|
|
5513
|
+
sensitiveDataOrigin: 5,
|
|
5514
|
+
userWithAuth: 6,
|
|
5515
|
+
adminWithPolicy: 7,
|
|
5516
|
+
firmwareLimited: 8,
|
|
5517
|
+
svnLimited: 9,
|
|
5518
|
+
noDA: 10,
|
|
5519
|
+
encryptedDuplication: 11,
|
|
5520
|
+
restricted: 16,
|
|
5521
|
+
decrypt: 17,
|
|
5522
|
+
sign: 18,
|
|
5523
|
+
x509sign: 19
|
|
5524
|
+
});
|
|
5525
|
+
var TPMA_OBJECT_RESERVED = 4293980169;
|
|
5526
|
+
function _decodeAttributes(oa) {
|
|
5527
|
+
var out = {};
|
|
5528
|
+
Object.keys(TPMA_OBJECT_BITS).forEach(function(n) {
|
|
5529
|
+
out[n] = (oa >>> TPMA_OBJECT_BITS[n] & 1) === 1;
|
|
5530
|
+
});
|
|
5531
|
+
return out;
|
|
5532
|
+
}
|
|
5311
5533
|
function parsePubArea(buf, E, code) {
|
|
5312
5534
|
var r = new ByteReader(buf, 0, buf.length, E, code);
|
|
5313
5535
|
var type = r.u16(), nameAlg = r.u16();
|
|
5314
|
-
r.u32();
|
|
5315
|
-
r.vector(2, 0, null);
|
|
5316
|
-
var pub = {
|
|
5536
|
+
var objectAttributes = r.u32();
|
|
5537
|
+
var authPolicy = r.vector(2, 0, null);
|
|
5538
|
+
var pub = {
|
|
5539
|
+
type,
|
|
5540
|
+
nameAlg,
|
|
5541
|
+
nameAlgBytes: buf.subarray(2, 4),
|
|
5542
|
+
objectAttributes: objectAttributes >>> 0,
|
|
5543
|
+
attributes: _decodeAttributes(objectAttributes),
|
|
5544
|
+
authPolicy
|
|
5545
|
+
};
|
|
5317
5546
|
if (type === TPM_ALG.RSA) {
|
|
5318
5547
|
_symDef(r);
|
|
5319
5548
|
_scheme(r);
|
|
@@ -5367,8 +5596,108 @@ var require_validator_tpm = __commonJS({
|
|
|
5367
5596
|
}
|
|
5368
5597
|
throw new E(code, "unsupported TPM pubArea key type");
|
|
5369
5598
|
}
|
|
5599
|
+
var TPM_POLICY_PROFILES = Object.assign(/* @__PURE__ */ Object.create(null), {
|
|
5600
|
+
"hardware-bound": { fixedTPM: true, fixedParent: true, sensitiveDataOrigin: true, sign: true, restricted: false, x509sign: false }
|
|
5601
|
+
});
|
|
5602
|
+
var _TPM_POLICY_KEYS = Object.assign(/* @__PURE__ */ Object.create(null), { profile: 1, objectAttributes: 1, reservedBitsClear: 1, consistency: 1, authPolicy: 1 });
|
|
5603
|
+
var _AUTH_POLICY_KEYS = Object.assign(/* @__PURE__ */ Object.create(null), { present: 1, allow: 1 });
|
|
5604
|
+
function normalizeObjectAttributePolicy(policy, E, code) {
|
|
5605
|
+
if (policy === void 0) return null;
|
|
5606
|
+
if (!policy || typeof policy !== "object" || Array.isArray(policy)) throw new E(code, "opts.tpmPolicy must be an object");
|
|
5607
|
+
guard.identifier.assertKnownKeys(policy, _TPM_POLICY_KEYS, function(c, m) {
|
|
5608
|
+
return new E(c, m);
|
|
5609
|
+
}, code, "opts.tpmPolicy has an unknown key ");
|
|
5610
|
+
var want = {};
|
|
5611
|
+
if (policy.profile !== void 0) {
|
|
5612
|
+
var preset = TPM_POLICY_PROFILES[policy.profile];
|
|
5613
|
+
if (!preset) throw new E(code, "opts.tpmPolicy.profile " + JSON.stringify(policy.profile) + " is not a defined profile");
|
|
5614
|
+
Object.keys(preset).forEach(function(n) {
|
|
5615
|
+
want[n] = preset[n];
|
|
5616
|
+
});
|
|
5617
|
+
}
|
|
5618
|
+
var explicit = policy.objectAttributes;
|
|
5619
|
+
if (explicit !== void 0) {
|
|
5620
|
+
if (!explicit || typeof explicit !== "object" || Array.isArray(explicit)) throw new E(code, "opts.tpmPolicy.objectAttributes must be an object");
|
|
5621
|
+
Object.keys(explicit).forEach(function(n) {
|
|
5622
|
+
if (TPMA_OBJECT_BITS[n] === void 0) throw new E(code, "opts.tpmPolicy.objectAttributes has an unknown attribute " + JSON.stringify(n));
|
|
5623
|
+
if (typeof explicit[n] !== "boolean") throw new E(code, "opts.tpmPolicy.objectAttributes." + n + " must be a boolean");
|
|
5624
|
+
want[n] = explicit[n];
|
|
5625
|
+
});
|
|
5626
|
+
}
|
|
5627
|
+
if (want.sensitiveDataOrigin === true && want.fixedTPM !== true) {
|
|
5628
|
+
throw new E(code, "opts.tpmPolicy requires sensitiveDataOrigin without fixedTPM; on its own it does not establish that the TPM generated the key (TPM 2.0 Part 2 sec. 8.3.3.5)");
|
|
5629
|
+
}
|
|
5630
|
+
["reservedBitsClear", "consistency"].forEach(function(k) {
|
|
5631
|
+
if (policy[k] !== void 0 && typeof policy[k] !== "boolean") throw new E(code, "opts.tpmPolicy." + k + " must be a boolean");
|
|
5632
|
+
});
|
|
5633
|
+
var ap = policy.authPolicy;
|
|
5634
|
+
var allow = null;
|
|
5635
|
+
if (ap !== void 0) {
|
|
5636
|
+
if (!ap || typeof ap !== "object" || Array.isArray(ap)) throw new E(code, "opts.tpmPolicy.authPolicy must be an object");
|
|
5637
|
+
guard.identifier.assertKnownKeys(ap, _AUTH_POLICY_KEYS, function(c, m) {
|
|
5638
|
+
return new E(c, m);
|
|
5639
|
+
}, code, "opts.tpmPolicy.authPolicy has an unknown key ");
|
|
5640
|
+
if (ap.present !== void 0 && typeof ap.present !== "boolean") throw new E(code, "opts.tpmPolicy.authPolicy.present must be a boolean");
|
|
5641
|
+
if (ap.allow !== void 0) {
|
|
5642
|
+
if (!Array.isArray(ap.allow)) throw new E(code, "opts.tpmPolicy.authPolicy.allow must be an array");
|
|
5643
|
+
allow = ap.allow.map(function(entry, i) {
|
|
5644
|
+
if (Buffer.isBuffer(entry)) return entry;
|
|
5645
|
+
if (typeof entry !== "string" || entry.length === 0 || entry.length % 2 !== 0 || !/^[0-9a-fA-F]+$/.test(entry)) {
|
|
5646
|
+
throw new E(code, "opts.tpmPolicy.authPolicy.allow[" + i + "] must be a Buffer or an even-length hex string");
|
|
5647
|
+
}
|
|
5648
|
+
return Buffer.from(entry, "hex");
|
|
5649
|
+
});
|
|
5650
|
+
}
|
|
5651
|
+
}
|
|
5652
|
+
return {
|
|
5653
|
+
objectAttributes: want,
|
|
5654
|
+
reservedBitsClear: policy.reservedBitsClear === true,
|
|
5655
|
+
consistency: policy.consistency === true,
|
|
5656
|
+
authPolicy: ap ? { present: ap.present === true, allow } : null
|
|
5657
|
+
};
|
|
5658
|
+
}
|
|
5659
|
+
function assertObjectAttributePolicy(pub, policy, E, policyCode, structuralCode) {
|
|
5660
|
+
if (!policy) return;
|
|
5661
|
+
var oa = pub.objectAttributes >>> 0;
|
|
5662
|
+
if (policy.reservedBitsClear && (oa & TPMA_OBJECT_RESERVED) >>> 0 !== 0) {
|
|
5663
|
+
throw new E(structuralCode, "the TPMT_PUBLIC objectAttributes sets a reserved bit (TPM 2.0 Part 2 sec. 8.3.2 Table 33: shall be zero)");
|
|
5664
|
+
}
|
|
5665
|
+
if (policy.consistency) {
|
|
5666
|
+
if (pub.attributes.encryptedDuplication && pub.attributes.fixedTPM) {
|
|
5667
|
+
throw new E(structuralCode, "the TPMT_PUBLIC objectAttributes sets encryptedDuplication on an object with fixedTPM SET (TPM 2.0 Part 2 sec. 8.3.3.11)");
|
|
5668
|
+
}
|
|
5669
|
+
if (pub.attributes.sign && pub.attributes.decrypt && pub.attributes.restricted) {
|
|
5670
|
+
throw new E(structuralCode, "the TPMT_PUBLIC objectAttributes sets restricted with both sign and decrypt (TPM 2.0 Part 2 sec. 8.3.3)");
|
|
5671
|
+
}
|
|
5672
|
+
if (pub.authPolicy.length > 64) {
|
|
5673
|
+
throw new E(structuralCode, "the TPMT_PUBLIC authPolicy is " + pub.authPolicy.length + " octets, above the 64-octet TPM2B_DIGEST maximum");
|
|
5674
|
+
}
|
|
5675
|
+
}
|
|
5676
|
+
Object.keys(policy.objectAttributes).forEach(function(name) {
|
|
5677
|
+
var want = policy.objectAttributes[name];
|
|
5678
|
+
if (pub.attributes[name] !== want) {
|
|
5679
|
+
throw new E(policyCode, "the TPM credential key has " + name + " " + (pub.attributes[name] ? "SET" : "CLEAR") + "; opts.tpmPolicy requires it " + (want ? "SET" : "CLEAR"));
|
|
5680
|
+
}
|
|
5681
|
+
});
|
|
5682
|
+
var ap = policy.authPolicy;
|
|
5683
|
+
if (!ap) return;
|
|
5684
|
+
if (ap.present === true && pub.authPolicy.length === 0) {
|
|
5685
|
+
throw new E(policyCode, "the TPM credential key carries the Empty Policy; opts.tpmPolicy.authPolicy.present requires a policy digest");
|
|
5686
|
+
}
|
|
5687
|
+
if (ap.allow) {
|
|
5688
|
+
var got = pub.authPolicy;
|
|
5689
|
+
var ok = ap.allow.some(function(want) {
|
|
5690
|
+
return want.length === got.length && guard.crypto.constantTimeEqual(want, got);
|
|
5691
|
+
});
|
|
5692
|
+
if (!ok) throw new E(policyCode, "the TPM credential key authPolicy is not in opts.tpmPolicy.authPolicy.allow");
|
|
5693
|
+
}
|
|
5694
|
+
}
|
|
5370
5695
|
module2.exports = {
|
|
5371
5696
|
parsePubArea,
|
|
5697
|
+
TPMA_OBJECT_BITS,
|
|
5698
|
+
decodeObjectAttributes: _decodeAttributes,
|
|
5699
|
+
normalizeObjectAttributePolicy,
|
|
5700
|
+
assertObjectAttributePolicy,
|
|
5372
5701
|
parseCertInfo,
|
|
5373
5702
|
pubKeyEqualsCose,
|
|
5374
5703
|
TPM_ALG_HASH
|
|
@@ -5491,7 +5820,22 @@ var require_rfc3339 = __commonJS({
|
|
|
5491
5820
|
if (!isValid(v)) throw E(code, (label || "the value") + " is not a valid RFC 3339 date-time");
|
|
5492
5821
|
return new Date(v);
|
|
5493
5822
|
}
|
|
5494
|
-
|
|
5823
|
+
var FULL_DATE_RE = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
5824
|
+
function isValidDate(v) {
|
|
5825
|
+
if (typeof v !== "string") return false;
|
|
5826
|
+
var m = FULL_DATE_RE.exec(v);
|
|
5827
|
+
if (!m) return false;
|
|
5828
|
+
var year = +m[1], month = +m[2], day = +m[3];
|
|
5829
|
+
if (month < 1 || month > 12) return false;
|
|
5830
|
+
var leap = year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
|
|
5831
|
+
var daysInMonth = [31, leap ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
5832
|
+
return day >= 1 && day <= daysInMonth[month - 1];
|
|
5833
|
+
}
|
|
5834
|
+
function parseDate(v, E, code, label) {
|
|
5835
|
+
if (!isValidDate(v)) throw E(code, (label || "the value") + " is not a valid RFC 3339 full-date (YYYY-MM-DD)");
|
|
5836
|
+
return /* @__PURE__ */ new Date(v + "T00:00:00Z");
|
|
5837
|
+
}
|
|
5838
|
+
module2.exports = { isValid, parse, isValidDate, parseDate };
|
|
5495
5839
|
}
|
|
5496
5840
|
});
|
|
5497
5841
|
|
|
@@ -6439,9 +6783,7 @@ var require_ct = __commonJS({
|
|
|
6439
6783
|
}
|
|
6440
6784
|
async function fetchLogList(opts) {
|
|
6441
6785
|
opts = opts || {};
|
|
6442
|
-
|
|
6443
|
-
if (!KNOWN_FETCH_OPTS[k]) throw _ctErr("ct/bad-input", "unknown opts field " + JSON.stringify(k));
|
|
6444
|
-
});
|
|
6786
|
+
guard.identifier.assertKnownKeys(opts, KNOWN_FETCH_OPTS, _ctErr, "ct/bad-input", "unknown opts field ");
|
|
6445
6787
|
if (opts.signerKey == null) throw _ctErr("ct/bad-input", "opts.signerKey is required -- the caller-pinned CT log-list distributor SPKI (there is no baked-in key)");
|
|
6446
6788
|
if (opts.url == null) throw _ctErr("ct/bad-input", "opts.url is required -- the log_list.json URL (there is no baked-in vendor URL)");
|
|
6447
6789
|
var jsonParsed = _parseHttpsUrl(opts.url, "URL");
|
|
@@ -6934,6 +7276,62 @@ var require_schema_pkix = __commonJS({
|
|
|
6934
7276
|
}
|
|
6935
7277
|
});
|
|
6936
7278
|
}
|
|
7279
|
+
var DISPLAY_TEXT_MAX = 200;
|
|
7280
|
+
function displayTextChars(str) {
|
|
7281
|
+
return Array.from(str).length;
|
|
7282
|
+
}
|
|
7283
|
+
var _DISPLAY_TEXT_TAGS = null;
|
|
7284
|
+
function _isDisplayTextNode(n) {
|
|
7285
|
+
if (!_DISPLAY_TEXT_TAGS) {
|
|
7286
|
+
_DISPLAY_TEXT_TAGS = {};
|
|
7287
|
+
_DISPLAY_TEXT_TAGS[_T.IA5_STRING] = 1;
|
|
7288
|
+
_DISPLAY_TEXT_TAGS[_T.VISIBLE_STRING] = 1;
|
|
7289
|
+
_DISPLAY_TEXT_TAGS[_T.BMP_STRING] = 1;
|
|
7290
|
+
_DISPLAY_TEXT_TAGS[_T.UTF8_STRING] = 1;
|
|
7291
|
+
}
|
|
7292
|
+
return !!n && n.tagClass === "universal" && _DISPLAY_TEXT_TAGS[n.tagNumber] === 1;
|
|
7293
|
+
}
|
|
7294
|
+
function _dtEntry(field, node) {
|
|
7295
|
+
var text;
|
|
7296
|
+
try {
|
|
7297
|
+
text = asn1.read.string(node);
|
|
7298
|
+
} catch (_e) {
|
|
7299
|
+
text = null;
|
|
7300
|
+
}
|
|
7301
|
+
return { field, tagNumber: node.tagNumber, text, chars: text === null ? null : displayTextChars(text) };
|
|
7302
|
+
}
|
|
7303
|
+
function _noticeNumbers(node) {
|
|
7304
|
+
if (!node || node.tagClass !== "universal" || node.tagNumber !== _T.SEQUENCE || !node.children) return null;
|
|
7305
|
+
var nums = [], ok = true;
|
|
7306
|
+
node.children.forEach(function(n) {
|
|
7307
|
+
try {
|
|
7308
|
+
nums.push(String(asn1.read.integer(n)));
|
|
7309
|
+
} catch (_e) {
|
|
7310
|
+
ok = false;
|
|
7311
|
+
}
|
|
7312
|
+
});
|
|
7313
|
+
return ok ? nums : null;
|
|
7314
|
+
}
|
|
7315
|
+
function userNoticeTexts(qualifier) {
|
|
7316
|
+
if (!qualifier || qualifier.tagClass !== "universal" || qualifier.tagNumber !== _T.SEQUENCE || !qualifier.children) return [];
|
|
7317
|
+
var kids = qualifier.children;
|
|
7318
|
+
if (kids.length > 2) return [];
|
|
7319
|
+
var i = 0, out = [];
|
|
7320
|
+
if (i < kids.length && kids[i].tagClass === "universal" && kids[i].tagNumber === _T.SEQUENCE) {
|
|
7321
|
+
var nr = kids[i];
|
|
7322
|
+
if (!nr.children || nr.children.length !== 2 || !_isDisplayTextNode(nr.children[0])) return [];
|
|
7323
|
+
var org = _dtEntry("organization", nr.children[0]);
|
|
7324
|
+
org.noticeNumbers = _noticeNumbers(nr.children[1]);
|
|
7325
|
+
out.push(org);
|
|
7326
|
+
i++;
|
|
7327
|
+
}
|
|
7328
|
+
if (i < kids.length) {
|
|
7329
|
+
if (!_isDisplayTextNode(kids[i])) return [];
|
|
7330
|
+
out.push(_dtEntry("explicitText", kids[i]));
|
|
7331
|
+
i++;
|
|
7332
|
+
}
|
|
7333
|
+
return i === kids.length ? out : [];
|
|
7334
|
+
}
|
|
6937
7335
|
function _decodeHelpers(ns) {
|
|
6938
7336
|
function decodeTop(buf, code, what) {
|
|
6939
7337
|
var n;
|
|
@@ -7655,6 +8053,9 @@ var require_schema_pkix = __commonJS({
|
|
|
7655
8053
|
signedEnvelopeTbs,
|
|
7656
8054
|
rootSequenceChildren,
|
|
7657
8055
|
assertPolicyQualifiers,
|
|
8056
|
+
DISPLAY_TEXT_MAX,
|
|
8057
|
+
displayTextChars,
|
|
8058
|
+
userNoticeTexts,
|
|
7658
8059
|
signedEnvelope,
|
|
7659
8060
|
attrValueToString,
|
|
7660
8061
|
attributeTypeAndValue,
|
|
@@ -7748,6 +8149,12 @@ var require_schema_c509 = __commonJS({
|
|
|
7748
8149
|
29: _name("freshestCRL"),
|
|
7749
8150
|
30: _name("inhibitAnyPolicy"),
|
|
7750
8151
|
31: _name("subjectInfoAccess"),
|
|
8152
|
+
// RFC 3779 resource-delegation extensions, and their RFC 8360 "v2" twins, which the draft
|
|
8153
|
+
// encodes "exactly like" the originals -- same two codecs, four registry rows (sec. 8.8).
|
|
8154
|
+
32: _name("ipAddrBlocks"),
|
|
8155
|
+
33: _name("autonomousSysIds"),
|
|
8156
|
+
34: _name("ipAddrBlocksV2"),
|
|
8157
|
+
35: _name("autonomousSysIdsV2"),
|
|
7751
8158
|
36: _name("ocspNoCheck"),
|
|
7752
8159
|
38: _name("tlsFeature")
|
|
7753
8160
|
};
|
|
@@ -7770,7 +8177,11 @@ var require_schema_c509 = __commonJS({
|
|
|
7770
8177
|
certificatePolicies: 1,
|
|
7771
8178
|
policyMappings: 1,
|
|
7772
8179
|
policyConstraints: 1,
|
|
7773
|
-
subjectDirectoryAttributes: 1
|
|
8180
|
+
subjectDirectoryAttributes: 1,
|
|
8181
|
+
ipAddrBlocks: 1,
|
|
8182
|
+
autonomousSysIds: 1,
|
|
8183
|
+
ipAddrBlocksV2: 1,
|
|
8184
|
+
autonomousSysIdsV2: 1
|
|
7774
8185
|
};
|
|
7775
8186
|
var EKU_BY_INT = {
|
|
7776
8187
|
0: _name("anyExtendedKeyUsage"),
|
|
@@ -7888,6 +8299,7 @@ var require_schema_c509 = __commonJS({
|
|
|
7888
8299
|
if (node.majorType === 4 && node.children && node.children.length === 2) {
|
|
7889
8300
|
var a = _oidName(node.children[0], code, label);
|
|
7890
8301
|
if (node.children[1].majorType !== 2) throw _err(code, label + " algorithm parameters must be a CBOR byte string");
|
|
8302
|
+
if (node.children[1].content.length === 0) throw _err(code, label + " algorithm parameters must not be an empty byte string; omit them with the bare ~oid form (draft sec. 3.1.3)");
|
|
7891
8303
|
return { name: a.name, oid: a.oid, parameters: node.children[1].content };
|
|
7892
8304
|
}
|
|
7893
8305
|
throw _err(code, label + " is not a C509 AlgorithmIdentifier (int / ~oid / [~oid, params])");
|
|
@@ -7905,6 +8317,29 @@ var require_schema_c509 = __commonJS({
|
|
|
7905
8317
|
}
|
|
7906
8318
|
throw _err("c509/bad-name", "an attribute value is not a C509 SpecialText (text / bytes / tag-48)");
|
|
7907
8319
|
}
|
|
8320
|
+
var _HEX_OPTIMIZED = /^(?:[0-9a-f]{2})+$/;
|
|
8321
|
+
var _EUI64_TEXT = /^(?:[0-9A-F]{2}-){7}[0-9A-F]{2}$/;
|
|
8322
|
+
function _assertCanonicalSpecialText(node, isNative, E) {
|
|
8323
|
+
if (isNative) return;
|
|
8324
|
+
if (node.majorType === 3) {
|
|
8325
|
+
var t = cbor.read.textString(node);
|
|
8326
|
+
if (t.length >= 2 && _HEX_OPTIMIZED.test(t)) {
|
|
8327
|
+
throw _err(E, "a text attribute value of even-length hex characters must be encoded as a CBOR byte string (draft sec. 3.1.4)");
|
|
8328
|
+
}
|
|
8329
|
+
if (_EUI64_TEXT.test(t)) {
|
|
8330
|
+
throw _err(E, "a text attribute value in EUI-64 form must be encoded as a CBOR tag-48 MAC address (draft sec. 3.1.4)");
|
|
8331
|
+
}
|
|
8332
|
+
return;
|
|
8333
|
+
}
|
|
8334
|
+
if (node.majorType === 2) {
|
|
8335
|
+
if (node.content.length === 0) throw _err(E, "an empty attribute value must be encoded as a CBOR text string (draft sec. 3.1.4)");
|
|
8336
|
+
return;
|
|
8337
|
+
}
|
|
8338
|
+
var eui = node.children[0].content;
|
|
8339
|
+
if (eui.length === 8 && eui[3] === 255 && eui[4] === 254) {
|
|
8340
|
+
throw _err(E, "an EUI-64 of the form HH-HH-HH-FF-FE-HH-HH-HH must be encoded as a 48-bit MAC address (draft sec. 3.1.4)");
|
|
8341
|
+
}
|
|
8342
|
+
}
|
|
7908
8343
|
function _assertAttrValue(rdn) {
|
|
7909
8344
|
try {
|
|
7910
8345
|
_reconAttrValue(rdn);
|
|
@@ -7917,6 +8352,7 @@ var require_schema_c509 = __commonJS({
|
|
|
7917
8352
|
if (!isSubject && node.majorType === 7 && node.ai === 22) return null;
|
|
7918
8353
|
if (node.majorType === 3 || node.majorType === 2 || node.majorType === 6) {
|
|
7919
8354
|
var sv = _specialText(node);
|
|
8355
|
+
_assertCanonicalSpecialText(node, isNative, "c509/bad-name");
|
|
7920
8356
|
if (sv.eui64) return { rdns: [{ type: "commonName", eui64: sv.eui64 }], eui64: sv.eui64, dn: "CN=" + _macToEui64String(sv.eui64) };
|
|
7921
8357
|
var val = sv.text !== void 0 ? sv.text : sv.hex;
|
|
7922
8358
|
var bareRdn = { type: "commonName", value: val };
|
|
@@ -7936,16 +8372,20 @@ var require_schema_c509 = __commonJS({
|
|
|
7936
8372
|
var tname = ATTR_BY_INT[Math.abs(ti)];
|
|
7937
8373
|
if (tname === void 0) throw _err("c509/bad-name", "attribute type integer " + ti + " has no C509 registry row");
|
|
7938
8374
|
var v = _specialText(kids[i + 1]);
|
|
8375
|
+
_assertCanonicalSpecialText(kids[i + 1], isNative, "c509/bad-name");
|
|
7939
8376
|
var vv = v.text !== void 0 ? v.text : v.hex !== void 0 ? v.hex : _macToEui64String(v.eui64);
|
|
7940
8377
|
var rdn = { type: tname, value: vv, printable: ti < 0 };
|
|
7941
8378
|
_assertAttrValue(rdn);
|
|
7942
8379
|
rdns.push(rdn);
|
|
7943
8380
|
parts.push(_shortName(tname) + "=" + guard.name.escapeDnValue(vv));
|
|
7944
8381
|
}
|
|
7945
|
-
|
|
8382
|
+
if (!isNative && rdns.length === 1 && rdns[0].type === "commonName" && !rdns[0].printable) {
|
|
8383
|
+
throw _err("c509/bad-name", "a Name holding a single +1 commonName must be encoded as a bare SpecialText, not an array (draft sec. 3.1.4)");
|
|
8384
|
+
}
|
|
8385
|
+
return { rdns, dn: parts.join(", ") };
|
|
7946
8386
|
}
|
|
7947
8387
|
function _shortName(n) {
|
|
7948
|
-
return n
|
|
8388
|
+
return n && constants.NAMES.DN_SHORT[n] || n;
|
|
7949
8389
|
}
|
|
7950
8390
|
function _cborUint(node, label) {
|
|
7951
8391
|
if (node.majorType !== 0) throw _err("c509/bad-extensions", "a " + label + " value must be a CBOR unsigned integer");
|
|
@@ -8154,6 +8594,222 @@ var require_schema_c509 = __commonJS({
|
|
|
8154
8594
|
}
|
|
8155
8595
|
return Buffer.concat([buf.subarray(0, addrLen), Buffer.from([prefixLen])]);
|
|
8156
8596
|
}
|
|
8597
|
+
function _isUniversal(n, tagNumber) {
|
|
8598
|
+
return !!n && n.tagClass === "universal" && n.tagNumber === tagNumber;
|
|
8599
|
+
}
|
|
8600
|
+
function _ipSeqToInt(seq) {
|
|
8601
|
+
if (!seq.length || seq[0] > 7) return null;
|
|
8602
|
+
var head = Buffer.from([seq[0] + 1]);
|
|
8603
|
+
return BigInt("0x" + Buffer.concat([head, seq.subarray(1)]).toString("hex"));
|
|
8604
|
+
}
|
|
8605
|
+
function _ipIntToSeq(n) {
|
|
8606
|
+
if (n < 1n) return null;
|
|
8607
|
+
var out = [];
|
|
8608
|
+
for (var v = n; v > 0n; v >>= 8n) out.unshift(Number(v & 0xffn));
|
|
8609
|
+
if (out.length > 9 || out[0] < 1 || out[0] > 8) return null;
|
|
8610
|
+
out[0] -= 1;
|
|
8611
|
+
return Buffer.from(out);
|
|
8612
|
+
}
|
|
8613
|
+
var _IP_WIDTH = { 1: 4, 2: 16 };
|
|
8614
|
+
function _ipLow(seq, width) {
|
|
8615
|
+
var v = Buffer.alloc(width);
|
|
8616
|
+
seq.subarray(1).copy(v);
|
|
8617
|
+
return v;
|
|
8618
|
+
}
|
|
8619
|
+
function _ipHigh(seq, width) {
|
|
8620
|
+
var v = _ipLow(seq, width);
|
|
8621
|
+
var bits = (seq.length - 1) * 8 - seq[0];
|
|
8622
|
+
for (var i = bits; i < width * 8; i++) v[i >> 3] |= 128 >> (i & 7);
|
|
8623
|
+
return v;
|
|
8624
|
+
}
|
|
8625
|
+
function _ipOctCmp(a, b2) {
|
|
8626
|
+
for (var i = 0; i < a.length; i++) {
|
|
8627
|
+
if (a[i] !== b2[i]) return a[i] - b2[i];
|
|
8628
|
+
}
|
|
8629
|
+
return 0;
|
|
8630
|
+
}
|
|
8631
|
+
function _ipIsSuccessor(a, b2) {
|
|
8632
|
+
var carry = 1, inc = Buffer.from(a);
|
|
8633
|
+
for (var i = inc.length - 1; i >= 0 && carry; i--) {
|
|
8634
|
+
var s = inc[i] + carry;
|
|
8635
|
+
inc[i] = s & 255;
|
|
8636
|
+
carry = s >> 8;
|
|
8637
|
+
}
|
|
8638
|
+
if (carry) return false;
|
|
8639
|
+
return _ipOctCmp(inc, b2) === 0;
|
|
8640
|
+
}
|
|
8641
|
+
function _ipRangeIsPrefix(lo, hi) {
|
|
8642
|
+
var bits = lo.length * 8, n = 0;
|
|
8643
|
+
while (n < bits) {
|
|
8644
|
+
var byteAt = n >> 3, mask = 128 >> (n & 7);
|
|
8645
|
+
if ((lo[byteAt] & mask) !== (hi[byteAt] & mask)) break;
|
|
8646
|
+
n++;
|
|
8647
|
+
}
|
|
8648
|
+
for (var i = n; i < bits; i++) {
|
|
8649
|
+
var bt = i >> 3, mk = 128 >> (i & 7);
|
|
8650
|
+
if ((lo[bt] & mk) !== 0) return false;
|
|
8651
|
+
if ((hi[bt] & mk) === 0) return false;
|
|
8652
|
+
}
|
|
8653
|
+
return true;
|
|
8654
|
+
}
|
|
8655
|
+
function _famOctCmp(a, b2) {
|
|
8656
|
+
var n = Math.min(a.length, b2.length);
|
|
8657
|
+
for (var i = 0; i < n; i++) {
|
|
8658
|
+
if (a[i] !== b2[i]) return a[i] - b2[i];
|
|
8659
|
+
}
|
|
8660
|
+
return a.length - b2.length;
|
|
8661
|
+
}
|
|
8662
|
+
function _ipSeqBitsClear(seq) {
|
|
8663
|
+
var unused = seq[0], value = seq.subarray(1);
|
|
8664
|
+
if (!value.length) return unused === 0;
|
|
8665
|
+
if (unused === 0) return true;
|
|
8666
|
+
return (value[value.length - 1] & (1 << unused) - 1) === 0;
|
|
8667
|
+
}
|
|
8668
|
+
function _ipRangesCanonical(bounds) {
|
|
8669
|
+
for (var i = 1; i < bounds.length; i++) {
|
|
8670
|
+
var prev = bounds[i - 1], cur = bounds[i];
|
|
8671
|
+
if (_ipOctCmp(cur.lo, prev.hi) <= 0) return false;
|
|
8672
|
+
if (_ipIsSuccessor(prev.hi, cur.lo)) return false;
|
|
8673
|
+
}
|
|
8674
|
+
return true;
|
|
8675
|
+
}
|
|
8676
|
+
function _ipChoiceToDer(items, afi) {
|
|
8677
|
+
var out = [], prev = null, sawBytes = false, sawInt = false, seqs = [];
|
|
8678
|
+
var width = _IP_WIDTH[afi];
|
|
8679
|
+
if (!width) throw _err("c509/bad-extensions", "address family " + afi + " has no known address width, so its addresses cannot be checked (RFC 3779 sec. 2.2.3.3)");
|
|
8680
|
+
function widthOk(seq) {
|
|
8681
|
+
return seq.length - 1 <= width;
|
|
8682
|
+
}
|
|
8683
|
+
function absolute(node) {
|
|
8684
|
+
var seq;
|
|
8685
|
+
if (node.majorType === 2) {
|
|
8686
|
+
sawBytes = true;
|
|
8687
|
+
if (node.content.length === 0) throw _err("c509/bad-extensions", "an IPAddress byte sequence must be non-empty");
|
|
8688
|
+
if (node.content[0] > 7) throw _err("c509/bad-extensions", "an IPAddress unused-bit count must be 0..7 (DER)");
|
|
8689
|
+
seq = node.content;
|
|
8690
|
+
} else {
|
|
8691
|
+
sawInt = true;
|
|
8692
|
+
var d = _cborIntVal(node, "an IPAddress");
|
|
8693
|
+
var abs = prev === null ? d : prev + d;
|
|
8694
|
+
prev = abs;
|
|
8695
|
+
guard.range.uint64(abs, _err, "c509/bad-extensions", "an IPAddress");
|
|
8696
|
+
seq = _ipIntToSeq(abs);
|
|
8697
|
+
if (!seq) throw _err("c509/bad-extensions", "an IPAddress integer does not encode a DER BIT STRING (sec. 3.3)");
|
|
8698
|
+
}
|
|
8699
|
+
if (!widthOk(seq)) {
|
|
8700
|
+
throw _err("c509/bad-extensions", "an IPAddress is wider than address family " + afi + " permits (RFC 3779 sec. 2.2.3.8)");
|
|
8701
|
+
}
|
|
8702
|
+
if (!_ipSeqBitsClear(seq)) {
|
|
8703
|
+
throw _err("c509/bad-extensions", "an IPAddress must leave its declared unused bits zero (RFC 3779 sec. 2.2.3.8)");
|
|
8704
|
+
}
|
|
8705
|
+
return seq;
|
|
8706
|
+
}
|
|
8707
|
+
var bounds = [];
|
|
8708
|
+
for (var i = 0; i < items.length; i++) {
|
|
8709
|
+
var it = items[i];
|
|
8710
|
+
if (it.majorType === 4) {
|
|
8711
|
+
if (!it.children || it.children.length !== 2) throw _err("c509/bad-extensions", "an IPAddress range must be exactly [min, max]");
|
|
8712
|
+
var lo = absolute(it.children[0]), hi = absolute(it.children[1]);
|
|
8713
|
+
seqs.push(lo);
|
|
8714
|
+
seqs.push(hi);
|
|
8715
|
+
var rlo = _ipLow(lo, width), rhi = _ipHigh(hi, width);
|
|
8716
|
+
{
|
|
8717
|
+
if (_ipRangeIsPrefix(rlo, rhi)) throw _err("c509/bad-extensions", "an address range that is exactly a prefix must use the prefix form (RFC 3779 sec. 2.2.3.7)");
|
|
8718
|
+
bounds.push({ lo: rlo, hi: rhi });
|
|
8719
|
+
}
|
|
8720
|
+
out.push(b.sequence([b.bitString(lo.subarray(1), lo[0]), b.bitString(hi.subarray(1), hi[0])]));
|
|
8721
|
+
} else {
|
|
8722
|
+
var pfx = absolute(it);
|
|
8723
|
+
seqs.push(pfx);
|
|
8724
|
+
bounds.push({ lo: _ipLow(pfx, width), hi: _ipHigh(pfx, width) });
|
|
8725
|
+
out.push(b.bitString(pfx.subarray(1), pfx[0]));
|
|
8726
|
+
}
|
|
8727
|
+
}
|
|
8728
|
+
if (sawBytes && sawInt) throw _err("c509/bad-extensions", "an IPAddressFamily must use one address form throughout (sec. 3.3)");
|
|
8729
|
+
if (sawBytes && !seqs.some(function(s) {
|
|
8730
|
+
return s.length > 8;
|
|
8731
|
+
})) {
|
|
8732
|
+
throw _err("c509/bad-extensions", "an IPAddressFamily whose addresses all fit 8 octets must use the integer form (sec. 3.3)");
|
|
8733
|
+
}
|
|
8734
|
+
for (var r = 0; r < bounds.length; r++) {
|
|
8735
|
+
if (_ipOctCmp(bounds[r].lo, bounds[r].hi) > 0) throw _err("c509/bad-extensions", "an IPAddress range must not end below its start (RFC 3779 sec. 2.2.3.9)");
|
|
8736
|
+
}
|
|
8737
|
+
if (!_ipRangesCanonical(bounds)) {
|
|
8738
|
+
throw _err("c509/bad-extensions", "an IPAddressFamily must be sorted, non-overlapping and maximally merged (RFC 3779 sec. 2.2.3.6)");
|
|
8739
|
+
}
|
|
8740
|
+
return out;
|
|
8741
|
+
}
|
|
8742
|
+
function _ipChoiceFromDer(ch, afi) {
|
|
8743
|
+
if (!_isUniversal(ch, asn1.TAGS.SEQUENCE) || !ch.children || ch.children.length === 0) return null;
|
|
8744
|
+
var groups = [], flat = [];
|
|
8745
|
+
for (var i = 0; i < ch.children.length; i++) {
|
|
8746
|
+
var el = ch.children[i], pair;
|
|
8747
|
+
if (_isUniversal(el, asn1.TAGS.BIT_STRING)) {
|
|
8748
|
+
var bs = asn1.read.bitString(el);
|
|
8749
|
+
pair = [Buffer.concat([Buffer.from([bs.unusedBits]), bs.bytes])];
|
|
8750
|
+
} else if (_isUniversal(el, asn1.TAGS.SEQUENCE) && el.children && el.children.length === 2 && _isUniversal(el.children[0], asn1.TAGS.BIT_STRING) && _isUniversal(el.children[1], asn1.TAGS.BIT_STRING)) {
|
|
8751
|
+
var lo = asn1.read.bitString(el.children[0]), hi = asn1.read.bitString(el.children[1]);
|
|
8752
|
+
pair = [
|
|
8753
|
+
Buffer.concat([Buffer.from([lo.unusedBits]), lo.bytes]),
|
|
8754
|
+
Buffer.concat([Buffer.from([hi.unusedBits]), hi.bytes])
|
|
8755
|
+
];
|
|
8756
|
+
} else return null;
|
|
8757
|
+
groups.push(pair);
|
|
8758
|
+
for (var k = 0; k < pair.length; k++) flat.push(pair[k]);
|
|
8759
|
+
}
|
|
8760
|
+
var width = _IP_WIDTH[afi];
|
|
8761
|
+
if (!width) return null;
|
|
8762
|
+
var bounds = [];
|
|
8763
|
+
for (var g = 0; g < groups.length; g++) {
|
|
8764
|
+
var bg = groups[g];
|
|
8765
|
+
if (bg[0].length - 1 > width || bg[bg.length - 1].length - 1 > width) return null;
|
|
8766
|
+
var blo = _ipLow(bg[0], width), bhi = _ipHigh(bg[bg.length - 1], width);
|
|
8767
|
+
if (bg.length === 2 && _ipRangeIsPrefix(blo, bhi)) return null;
|
|
8768
|
+
bounds.push({ lo: blo, hi: bhi });
|
|
8769
|
+
}
|
|
8770
|
+
for (var r = 0; r < bounds.length; r++) {
|
|
8771
|
+
if (_ipOctCmp(bounds[r].lo, bounds[r].hi) > 0) return null;
|
|
8772
|
+
}
|
|
8773
|
+
if (!_ipRangesCanonical(bounds)) return null;
|
|
8774
|
+
var useBytes = flat.some(function(s) {
|
|
8775
|
+
return s.length > 8;
|
|
8776
|
+
});
|
|
8777
|
+
var out = [];
|
|
8778
|
+
if (useBytes) {
|
|
8779
|
+
groups.forEach(function(p) {
|
|
8780
|
+
out.push(p.length === 1 ? cbor.build.byteString(p[0]) : cbor.build.array([cbor.build.byteString(p[0]), cbor.build.byteString(p[1])]));
|
|
8781
|
+
});
|
|
8782
|
+
return cbor.build.array(out);
|
|
8783
|
+
}
|
|
8784
|
+
var prev = null;
|
|
8785
|
+
function delta(seq) {
|
|
8786
|
+
var n = _ipSeqToInt(seq);
|
|
8787
|
+
if (n === null) return null;
|
|
8788
|
+
var d = prev === null ? n : n - prev;
|
|
8789
|
+
prev = n;
|
|
8790
|
+
return cbor.build.int(d);
|
|
8791
|
+
}
|
|
8792
|
+
for (var gi = 0; gi < groups.length; gi++) {
|
|
8793
|
+
var grp = groups[gi];
|
|
8794
|
+
if (grp.length === 1) {
|
|
8795
|
+
var one = delta(grp[0]);
|
|
8796
|
+
if (!one) return null;
|
|
8797
|
+
out.push(one);
|
|
8798
|
+
} else {
|
|
8799
|
+
var dlo = delta(grp[0]);
|
|
8800
|
+
var dhi = dlo ? delta(grp[1]) : null;
|
|
8801
|
+
if (!dlo || !dhi) return null;
|
|
8802
|
+
out.push(cbor.build.array([dlo, dhi]));
|
|
8803
|
+
}
|
|
8804
|
+
}
|
|
8805
|
+
return cbor.build.array(out);
|
|
8806
|
+
}
|
|
8807
|
+
function _asDelta(node, prev) {
|
|
8808
|
+
var d = _cborIntVal(node, "an ASIdentifier");
|
|
8809
|
+
var abs = prev === null ? d : prev + d;
|
|
8810
|
+
guard.range.int(abs, 0n, 4294967295n, _err, "c509/bad-extensions", "an ASIdentifier");
|
|
8811
|
+
return abs;
|
|
8812
|
+
}
|
|
8157
8813
|
function _subtreesToDer(node, isNative) {
|
|
8158
8814
|
if (node.majorType !== 4 || !node.children) throw _err("c509/bad-extensions", "a GeneralSubtrees value must be a CBOR array");
|
|
8159
8815
|
var kids = node.children;
|
|
@@ -8350,8 +9006,8 @@ var require_schema_c509 = __commonJS({
|
|
|
8350
9006
|
} else {
|
|
8351
9007
|
items = [node];
|
|
8352
9008
|
}
|
|
8353
|
-
return b.sequence(items.map(function(
|
|
8354
|
-
return b.oid(_ekuPurposeOid(
|
|
9009
|
+
return b.sequence(items.map(function(it2) {
|
|
9010
|
+
return b.oid(_ekuPurposeOid(it2));
|
|
8355
9011
|
}));
|
|
8356
9012
|
}
|
|
8357
9013
|
case "inhibitAnyPolicy":
|
|
@@ -8368,6 +9024,9 @@ var require_schema_c509 = __commonJS({
|
|
|
8368
9024
|
case "subjectAltName":
|
|
8369
9025
|
case "issuerAltName":
|
|
8370
9026
|
if (node.majorType === 3) return b.sequence([b.contextPrimitive(2, _ia5Bytes(node, 2))]);
|
|
9027
|
+
if (!isNative && node.majorType === 4 && node.children && node.children.length === 2 && node.children[0].majorType === 0 && Number(cbor.read.int(node.children[0])) === 2 && node.children[1].majorType === 3) {
|
|
9028
|
+
throw _err("c509/bad-extensions", "a " + name + " holding exactly one dNSName must be encoded as a bare CBOR text string, not an array (draft sec. 3.3)");
|
|
9029
|
+
}
|
|
8371
9030
|
return b.sequence(_generalNamesToDer(node, isNative));
|
|
8372
9031
|
case "nameConstraints": {
|
|
8373
9032
|
if (node.majorType !== 4 || !node.children || node.children.length !== 2) throw _err("c509/bad-extensions", "a nameConstraints value must be a 2-element CBOR array [ permitted, excluded ] (sec. 3.3)");
|
|
@@ -8393,6 +9052,71 @@ var require_schema_c509 = __commonJS({
|
|
|
8393
9052
|
return b.sequence(node.children.map(function(dp) {
|
|
8394
9053
|
return _dpToDer(dp, isNative);
|
|
8395
9054
|
}));
|
|
9055
|
+
// IPAddrBlocks (and its RFC 8360 v2 twin): a FLAT array of (AFI, SAFI, choice) triples --
|
|
9056
|
+
// IPAddressFamily is a parenthesized CDDL group, so it splices rather than nesting.
|
|
9057
|
+
case "ipAddrBlocks":
|
|
9058
|
+
case "ipAddrBlocksV2": {
|
|
9059
|
+
if (node.majorType !== 4 || !node.children) throw _err("c509/bad-extensions", "an IPAddrBlocks value must be a CBOR array");
|
|
9060
|
+
var ipKids = node.children;
|
|
9061
|
+
if (ipKids.length === 0 || ipKids.length % 3 !== 0) throw _err("c509/bad-extensions", "an IPAddrBlocks array must be non-empty (AFI, SAFI, addresses) triples (sec. 3.3)");
|
|
9062
|
+
var families = [], prevFam = null;
|
|
9063
|
+
for (var fi = 0; fi + 2 < ipKids.length; fi += 3) {
|
|
9064
|
+
var afi = _cborUint(ipKids[fi], "an IPAddrBlocks AFI");
|
|
9065
|
+
if (afi > 0xffffn) throw _err("c509/bad-extensions", "an IPAddrBlocks AFI must fit two octets (RFC 3779 sec. 2.2.3.3)");
|
|
9066
|
+
var safiNode = ipKids[fi + 1], famBytes = [Number(afi >> 8n) & 255, Number(afi & 0xffn)];
|
|
9067
|
+
if (!_isCborNull(safiNode)) {
|
|
9068
|
+
var safi = _cborUint(safiNode, "an IPAddrBlocks SAFI");
|
|
9069
|
+
if (safi > 0xffn) throw _err("c509/bad-extensions", "an IPAddrBlocks SAFI must fit one octet (RFC 3779 sec. 2.2.3.3)");
|
|
9070
|
+
famBytes.push(Number(safi));
|
|
9071
|
+
}
|
|
9072
|
+
var famOct = Buffer.from(famBytes);
|
|
9073
|
+
if (prevFam !== null && _famOctCmp(prevFam, famOct) >= 0) {
|
|
9074
|
+
throw _err("c509/bad-extensions", "IPAddrBlocks address families must be unique and in ascending addressFamily order (RFC 3779 sec. 2.2.3.3)");
|
|
9075
|
+
}
|
|
9076
|
+
prevFam = famOct;
|
|
9077
|
+
var choice = ipKids[fi + 2], famFields = [b.octetString(famOct)];
|
|
9078
|
+
if (_isCborNull(choice)) {
|
|
9079
|
+
famFields.push(b.nullValue());
|
|
9080
|
+
} else {
|
|
9081
|
+
if (choice.majorType !== 4 || !choice.children || choice.children.length === 0) {
|
|
9082
|
+
throw _err("c509/bad-extensions", "an IPAddrBlocks address choice must be null (inherit) or a non-empty CBOR array");
|
|
9083
|
+
}
|
|
9084
|
+
famFields.push(b.sequence(_ipChoiceToDer(choice.children, Number(afi))));
|
|
9085
|
+
}
|
|
9086
|
+
families.push(b.sequence(famFields));
|
|
9087
|
+
}
|
|
9088
|
+
return b.sequence(families);
|
|
9089
|
+
}
|
|
9090
|
+
// ASIdentifiers (and its v2 twin): null = inherit, else a flat array of uint / [min,max].
|
|
9091
|
+
// Only the asnum field is representable -- a present rdi has no compact form (sec. 3.3), so a
|
|
9092
|
+
// certificate carrying one rides the ~oid byte-string form and never reaches this arm.
|
|
9093
|
+
case "autonomousSysIds":
|
|
9094
|
+
case "autonomousSysIdsV2": {
|
|
9095
|
+
if (_isCborNull(node)) return b.sequence([b.explicit(0, b.nullValue())]);
|
|
9096
|
+
if (node.majorType !== 4 || !node.children || node.children.length === 0) {
|
|
9097
|
+
throw _err("c509/bad-extensions", "an ASIdentifiers value must be null (inherit) or a non-empty CBOR array");
|
|
9098
|
+
}
|
|
9099
|
+
var asKids = node.children, asDers = [], asPrev = null, asPrevHigh = null;
|
|
9100
|
+
for (var asi2 = 0; asi2 < asKids.length; asi2++) {
|
|
9101
|
+
var it = asKids[asi2];
|
|
9102
|
+
if (it.majorType === 4) {
|
|
9103
|
+
if (!it.children || it.children.length !== 2) throw _err("c509/bad-extensions", "an ASIdentifiers range must be exactly [min, max]");
|
|
9104
|
+
var amin = _asDelta(it.children[0], asPrev), amax = _asDelta(it.children[1], amin);
|
|
9105
|
+
if (amax <= amin) throw _err("c509/bad-extensions", "an ASIdentifiers range must be ascending (RFC 3779 sec. 3.2.3.6)");
|
|
9106
|
+
if (asPrevHigh !== null && amin <= asPrevHigh + 1n) throw _err("c509/bad-extensions", "ASIdentifiers must be sorted, non-overlapping and maximally merged (RFC 3779 sec. 3.2.3.4)");
|
|
9107
|
+
asDers.push(b.sequence([b.integer(amin), b.integer(amax)]));
|
|
9108
|
+
asPrev = amax;
|
|
9109
|
+
asPrevHigh = amax;
|
|
9110
|
+
} else {
|
|
9111
|
+
var aid = _asDelta(it, asPrev);
|
|
9112
|
+
if (asPrevHigh !== null && aid <= asPrevHigh + 1n) throw _err("c509/bad-extensions", "ASIdentifiers must be sorted, non-overlapping and maximally merged (RFC 3779 sec. 3.2.3.4)");
|
|
9113
|
+
asDers.push(b.integer(aid));
|
|
9114
|
+
asPrev = aid;
|
|
9115
|
+
asPrevHigh = aid;
|
|
9116
|
+
}
|
|
9117
|
+
}
|
|
9118
|
+
return b.sequence([b.explicit(0, b.sequence(asDers))]);
|
|
9119
|
+
}
|
|
8396
9120
|
case "certificatePolicies": {
|
|
8397
9121
|
if (node.majorType !== 4 || !node.children) throw _err("c509/bad-extensions", "a certificatePolicies value must be a CBOR array");
|
|
8398
9122
|
var cpKids = node.children;
|
|
@@ -8548,6 +9272,70 @@ var require_schema_c509 = __commonJS({
|
|
|
8548
9272
|
return r.triple;
|
|
8549
9273
|
}));
|
|
8550
9274
|
}
|
|
9275
|
+
// IPAddrBlocks -> the flat (AFI, SAFI, choice) array. Any shape the compact form cannot
|
|
9276
|
+
// represent exactly returns null, so the extension rides the ~oid byte-string form intact.
|
|
9277
|
+
case "ipAddrBlocks":
|
|
9278
|
+
case "ipAddrBlocksV2": {
|
|
9279
|
+
if (!_isUniversal(node, asn1.TAGS.SEQUENCE) || !node.children || node.children.length === 0) return null;
|
|
9280
|
+
var ipOut = [], prevFamOct = null;
|
|
9281
|
+
for (var ifi = 0; ifi < node.children.length; ifi++) {
|
|
9282
|
+
var fam = node.children[ifi];
|
|
9283
|
+
if (!_isUniversal(fam, asn1.TAGS.SEQUENCE) || !fam.children || fam.children.length !== 2) return null;
|
|
9284
|
+
var famOct = asn1.read.octetString(fam.children[0]);
|
|
9285
|
+
if (famOct.length !== 2 && famOct.length !== 3) return null;
|
|
9286
|
+
if (prevFamOct !== null && _famOctCmp(prevFamOct, famOct) >= 0) return null;
|
|
9287
|
+
prevFamOct = famOct;
|
|
9288
|
+
var afiVal = famOct[0] << 8 | famOct[1];
|
|
9289
|
+
ipOut.push(cbor.build.uint(BigInt(afiVal)));
|
|
9290
|
+
ipOut.push(famOct.length === 3 ? cbor.build.uint(BigInt(famOct[2])) : cbor.build.nullValue());
|
|
9291
|
+
var ch = fam.children[1];
|
|
9292
|
+
if (_isUniversal(ch, asn1.TAGS.NULL)) {
|
|
9293
|
+
ipOut.push(cbor.build.nullValue());
|
|
9294
|
+
continue;
|
|
9295
|
+
}
|
|
9296
|
+
var chOut = _ipChoiceFromDer(ch, afiVal);
|
|
9297
|
+
if (!chOut) return null;
|
|
9298
|
+
ipOut.push(chOut);
|
|
9299
|
+
}
|
|
9300
|
+
return cbor.build.array(ipOut);
|
|
9301
|
+
}
|
|
9302
|
+
// ASIdentifiers -> null (inherit) or the flat delta array. Only asnum is representable: a
|
|
9303
|
+
// present rdi has no compact form (sec. 3.3), so such a certificate returns null here.
|
|
9304
|
+
case "autonomousSysIds":
|
|
9305
|
+
case "autonomousSysIdsV2": {
|
|
9306
|
+
if (!_isUniversal(node, asn1.TAGS.SEQUENCE) || !node.children || node.children.length !== 1) return null;
|
|
9307
|
+
var asnum = node.children[0];
|
|
9308
|
+
if (asnum.tagClass !== "context" || asnum.tagNumber !== 0 || !asnum.children || asnum.children.length !== 1) return null;
|
|
9309
|
+
var inner = asnum.children[0];
|
|
9310
|
+
if (_isUniversal(inner, asn1.TAGS.NULL)) return cbor.build.nullValue();
|
|
9311
|
+
if (!_isUniversal(inner, asn1.TAGS.SEQUENCE) || !inner.children || inner.children.length === 0) return null;
|
|
9312
|
+
var asOut = [], asPrevOut = null, asPrevHigh = null;
|
|
9313
|
+
for (var aoi = 0; aoi < inner.children.length; aoi++) {
|
|
9314
|
+
var el = inner.children[aoi], elLo, elHi;
|
|
9315
|
+
if (_isUniversal(el, asn1.TAGS.INTEGER)) {
|
|
9316
|
+
elLo = asn1.read.integer(el);
|
|
9317
|
+
elHi = elLo;
|
|
9318
|
+
if (elLo < 0n || elLo > 4294967295n) return null;
|
|
9319
|
+
} else if (_isUniversal(el, asn1.TAGS.SEQUENCE) && el.children && el.children.length === 2) {
|
|
9320
|
+
elLo = asn1.read.integer(el.children[0]);
|
|
9321
|
+
elHi = asn1.read.integer(el.children[1]);
|
|
9322
|
+
if (elLo < 0n || elHi > 4294967295n || elHi <= elLo) return null;
|
|
9323
|
+
} else return null;
|
|
9324
|
+
if (asPrevHigh !== null && elLo <= asPrevHigh + 1n) return null;
|
|
9325
|
+
if (el.tagNumber === asn1.TAGS.INTEGER) {
|
|
9326
|
+
asOut.push(cbor.build.int(asPrevOut === null ? elLo : elLo - asPrevOut));
|
|
9327
|
+
asPrevOut = elLo;
|
|
9328
|
+
} else {
|
|
9329
|
+
asOut.push(cbor.build.array([
|
|
9330
|
+
cbor.build.int(asPrevOut === null ? elLo : elLo - asPrevOut),
|
|
9331
|
+
cbor.build.int(elHi - elLo)
|
|
9332
|
+
]));
|
|
9333
|
+
asPrevOut = elHi;
|
|
9334
|
+
}
|
|
9335
|
+
asPrevHigh = elHi;
|
|
9336
|
+
}
|
|
9337
|
+
return cbor.build.array(asOut);
|
|
9338
|
+
}
|
|
8551
9339
|
case "certificatePolicies": {
|
|
8552
9340
|
if (node.tagClass !== "universal" || node.tagNumber !== asn1.TAGS.SEQUENCE || !node.children || node.children.length < 1) return null;
|
|
8553
9341
|
var cpOut = [];
|
|
@@ -8787,6 +9575,9 @@ var require_schema_c509 = __commonJS({
|
|
|
8787
9575
|
var out = [];
|
|
8788
9576
|
var kids = node.children || [];
|
|
8789
9577
|
if (kids.length % 2 !== 0) throw _err("c509/bad-extensions", "a C509 extensions array must be id/value pairs (dangling extension identifier)");
|
|
9578
|
+
if (!isNative && kids.length === 2 && (kids[0].majorType === 0 || kids[0].majorType === 1) && (kids[1].majorType === 0 || kids[1].majorType === 1) && Math.abs(Number(cbor.read.int(kids[0]))) === 2) {
|
|
9579
|
+
throw _err("c509/bad-extensions", "an extensions field holding only keyUsage must be encoded as a single CBOR int, not an array (draft sec. 3.1.10)");
|
|
9580
|
+
}
|
|
8790
9581
|
for (var i = 0; i + 1 < kids.length; i += 2) {
|
|
8791
9582
|
var idNode = kids[i], valNode = kids[i + 1];
|
|
8792
9583
|
var name, extOid, critical, valContent;
|
|
@@ -8902,15 +9693,20 @@ var require_schema_c509 = __commonJS({
|
|
|
8902
9693
|
}
|
|
8903
9694
|
function _reconstructDer(r, sigNode) {
|
|
8904
9695
|
var sigAlgSeq = _reconAlgId(r.signatureAlgorithm);
|
|
9696
|
+
var subjectName = _reconName(r.subject);
|
|
9697
|
+
var spelledIssuer = r.issuer && r.issuer.rdns ? _reconName(r.issuer) : null;
|
|
9698
|
+
if (spelledIssuer !== null && spelledIssuer.equals(subjectName)) {
|
|
9699
|
+
throw _err("c509/bad-name", "an issuer identical to the subject must be encoded as the CBOR simple value null (draft sec. 3.1.4)");
|
|
9700
|
+
}
|
|
8905
9701
|
var tbsFields = [
|
|
8906
9702
|
b.explicit(0, b.integer(2n)),
|
|
8907
9703
|
// version v3 (type-3 is X.509 v3)
|
|
8908
9704
|
b.integer(r.serialNumber),
|
|
8909
9705
|
sigAlgSeq,
|
|
8910
|
-
|
|
9706
|
+
spelledIssuer === null ? subjectName : spelledIssuer,
|
|
8911
9707
|
// null issuer -> issuer == subject
|
|
8912
9708
|
b.sequence([_reconTime(r.validity.notBefore), _reconTime(r.validity.notAfter)]),
|
|
8913
|
-
|
|
9709
|
+
subjectName,
|
|
8914
9710
|
_reconSpki(r.subjectPublicKeyAlgorithm, r.subjectPublicKey, r.rsaPublicKey)
|
|
8915
9711
|
];
|
|
8916
9712
|
if (r.extensions.length) tbsFields.push(_reconExtensions(r.extensions));
|
|
@@ -9012,7 +9808,9 @@ var require_schema_c509 = __commonJS({
|
|
|
9012
9808
|
}
|
|
9013
9809
|
function _encSpecialText(rdn) {
|
|
9014
9810
|
if (rdn.eui64) return cbor.build.tag(48, cbor.build.byteString(rdn.eui64));
|
|
9015
|
-
|
|
9811
|
+
var v = String(rdn.value);
|
|
9812
|
+
if (v.length >= 2 && _HEX_OPTIMIZED.test(v)) return cbor.build.byteString(Buffer.from(v, "hex"));
|
|
9813
|
+
return cbor.build.textString(v);
|
|
9016
9814
|
}
|
|
9017
9815
|
function _encName(name, isSubject) {
|
|
9018
9816
|
if (name === null || name === void 0) {
|
|
@@ -9197,6 +9995,7 @@ var require_schema_c509 = __commonJS({
|
|
|
9197
9995
|
} catch (e) {
|
|
9198
9996
|
throw _err("c509/bad-input", "the input is not a valid X.509 certificate", e);
|
|
9199
9997
|
}
|
|
9998
|
+
if (c.version !== 3) throw _err("c509/non-invertible", "C509 covers X.509 v3 certificates; got v" + c.version);
|
|
9200
9999
|
if (!/^ecdsa/i.test(c.signatureAlgorithm.name || "")) throw _err("c509/non-invertible", "type-3 C509 encoding covers only ECDSA-signed certificates; got " + (c.signatureAlgorithm.name || "an unregistered algorithm"));
|
|
9201
10000
|
if (c.subjectPublicKeyInfo.algorithm.name !== "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"));
|
|
9202
10001
|
var curveOid = asn1.read.oid(asn1.decode(c.subjectPublicKeyInfo.algorithm.parameters));
|
|
@@ -9210,7 +10009,13 @@ var require_schema_c509 = __commonJS({
|
|
|
9210
10009
|
serialNumber: c.serialNumber,
|
|
9211
10010
|
// no serialNumberHex -> the encoder uses the minimal ~biguint magnitude
|
|
9212
10011
|
signatureAlgorithm: { name: c.signatureAlgorithm.name, oid: c.signatureAlgorithm.oid },
|
|
9213
|
-
|
|
10012
|
+
// sec. 3.1.4: "If the 'issuer' field is identical to the 'subject' field, e.g., in case of
|
|
10013
|
+
// self-signed certificates, then the 'issuer' field MUST be encoded as the CBOR simple value
|
|
10014
|
+
// null." Compared on the RAW DER bytes, not on a canonicalized name: the reconstruction rebuilds
|
|
10015
|
+
// a null issuer FROM the subject, so two names that merely compare equal (a PrintableString
|
|
10016
|
+
// against a UTF8String of the same characters) would rebuild different bytes and break the
|
|
10017
|
+
// signature that covers them. Byte-identical is exactly the condition under which that is safe.
|
|
10018
|
+
issuer: c.issuer.bytes.equals(c.subject.bytes) ? null : _c509NameFromDer(c.issuer.bytes),
|
|
9214
10019
|
validity: { notBefore: c.validity.notBefore, notAfter: c.validity.notAfter.getTime() === _NO_EXPIRY ? null : c.validity.notAfter },
|
|
9215
10020
|
subject: _c509NameFromDer(c.subject.bytes),
|
|
9216
10021
|
subjectPublicKeyAlgorithm: { name: "ecPublicKey", oid: c.subjectPublicKeyInfo.algorithm.oid, curve },
|
|
@@ -9679,9 +10484,9 @@ var require_schema_cms = __commonJS({
|
|
|
9679
10484
|
WRAP_KEK_LENGTHS[oid.byName("aes192-wrap")] = 24;
|
|
9680
10485
|
WRAP_KEK_LENGTHS[oid.byName("aes256-wrap")] = 32;
|
|
9681
10486
|
var KEM_CT_LENGTHS = {};
|
|
9682
|
-
|
|
9683
|
-
|
|
9684
|
-
|
|
10487
|
+
["id-ml-kem-512", "id-ml-kem-768", "id-ml-kem-1024"].forEach(function(n) {
|
|
10488
|
+
KEM_CT_LENGTHS[oid.byName(n)] = oid.kemParams(n).ct;
|
|
10489
|
+
});
|
|
9685
10490
|
var AEAD_GCM_ICVLENS = /* @__PURE__ */ new Set([12, 13, 14, 15, 16]);
|
|
9686
10491
|
var AEAD_CCM_ICVLENS = /* @__PURE__ */ new Set([4, 6, 8, 10, 12, 14, 16]);
|
|
9687
10492
|
var AEAD_ALGS = {};
|
|
@@ -14755,7 +15560,7 @@ var require_sign_scheme = __commonJS({
|
|
|
14755
15560
|
function _importKey(key, imp, E) {
|
|
14756
15561
|
if (key && typeof key === "object" && !Buffer.isBuffer(key) && !(key instanceof Uint8Array) && key.type === "private") {
|
|
14757
15562
|
_assertKeyMatchesScheme(key, imp, E);
|
|
14758
|
-
return
|
|
15563
|
+
return webcrypto.adoptKey(key, imp, ["sign"], E, "bad-input");
|
|
14759
15564
|
}
|
|
14760
15565
|
var der;
|
|
14761
15566
|
if (Buffer.isBuffer(key)) der = key;
|
|
@@ -15005,9 +15810,7 @@ var require_pki_build = __commonJS({
|
|
|
15005
15810
|
if (bc.cA != null && typeof bc.cA !== "boolean") throw E("bad-input", "basicConstraints cA must be a boolean");
|
|
15006
15811
|
if (bc.critical != null && typeof bc.critical !== "boolean") throw E("bad-input", "basicConstraints critical must be a boolean");
|
|
15007
15812
|
if (bc.pathLen != null) pathLen(bc.pathLen);
|
|
15008
|
-
|
|
15009
|
-
if (k !== "cA" && k !== "pathLen" && k !== "critical") throw E("bad-input", "unknown basicConstraints field " + JSON.stringify(k));
|
|
15010
|
-
});
|
|
15813
|
+
guard.identifier.assertKnownKeys(bc, BC_KEYS, E, "bad-input", "unknown basicConstraints field ");
|
|
15011
15814
|
}
|
|
15012
15815
|
function extBasicConstraints(spec) {
|
|
15013
15816
|
var children = [];
|
|
@@ -15103,6 +15906,7 @@ var require_pki_build = __commonJS({
|
|
|
15103
15906
|
var last = n.children[n.children.length - 1];
|
|
15104
15907
|
if (last.tagNumber !== asn1.TAGS.OCTET_STRING || last.tagClass !== "universal") throw E("bad-input", "pre-encoded extension [" + idx + "] extnValue must be an OCTET STRING");
|
|
15105
15908
|
}
|
|
15909
|
+
var BC_KEYS = { cA: 1, pathLen: 1, critical: 1 };
|
|
15106
15910
|
var REQ_EXT_KEYS = {
|
|
15107
15911
|
subjectAltName: 1,
|
|
15108
15912
|
keyUsage: 1,
|
|
@@ -15139,8 +15943,8 @@ var require_pki_build = __commonJS({
|
|
|
15139
15943
|
}));
|
|
15140
15944
|
}
|
|
15141
15945
|
if (!extSpec || typeof extSpec !== "object") throw E("bad-input", "requested extensions must be an object or an array of pre-encoded Extension DER");
|
|
15142
|
-
|
|
15143
|
-
|
|
15946
|
+
guard.identifier.assertKnownKeys(extSpec, REQ_EXT_KEYS, E, "bad-input", function(k) {
|
|
15947
|
+
return "unknown requested extension " + JSON.stringify(k) + "; pass a pre-encoded Extension DER via the array form for a custom extension";
|
|
15144
15948
|
});
|
|
15145
15949
|
var out = [];
|
|
15146
15950
|
if (extSpec.subjectKeyIdentifier != null) {
|
|
@@ -15271,6 +16075,7 @@ var require_crmf_sign = __commonJS({
|
|
|
15271
16075
|
var pkix = require_schema_pkix();
|
|
15272
16076
|
var pkiBuild = require_pki_build();
|
|
15273
16077
|
var frameworkError = require_framework_error();
|
|
16078
|
+
var guard = require_guard_all();
|
|
15274
16079
|
var CrmfError = frameworkError.CrmfError;
|
|
15275
16080
|
var b = asn1.build;
|
|
15276
16081
|
function _err(code, message, cause) {
|
|
@@ -15294,6 +16099,7 @@ var require_crmf_sign = __commonJS({
|
|
|
15294
16099
|
EXT_DECODERS
|
|
15295
16100
|
});
|
|
15296
16101
|
var KNOWN_SPEC_KEYS = { certReqId: 1, certTemplate: 1, controls: 1, regInfo: 1, pop: 1 };
|
|
16102
|
+
var KNOWN_BATCH_KEYS = { messages: 1 };
|
|
15297
16103
|
var KNOWN_TEMPLATE_KEYS = { version: 1, subject: 1, publicKey: 1, validity: 1, extensions: 1, issuer: 1 };
|
|
15298
16104
|
var REVOCATION_TEMPLATE_KEYS = { version: 1, subject: 1, publicKey: 1, validity: 1, extensions: 1, issuer: 1, serialNumber: 1 };
|
|
15299
16105
|
function _ctlUtf8(v) {
|
|
@@ -15321,9 +16127,7 @@ var require_crmf_sign = __commonJS({
|
|
|
15321
16127
|
function _encodeCertTemplate(tpl, opts) {
|
|
15322
16128
|
if (!tpl || typeof tpl !== "object" || Buffer.isBuffer(tpl)) throw _err("crmf/bad-cert-template", "certTemplate must be an object");
|
|
15323
16129
|
var allowed = opts && opts.revocation ? REVOCATION_TEMPLATE_KEYS : KNOWN_TEMPLATE_KEYS;
|
|
15324
|
-
|
|
15325
|
-
if (!allowed[k]) throw _err("crmf/bad-input", "unknown certTemplate field " + JSON.stringify(k));
|
|
15326
|
-
});
|
|
16130
|
+
guard.identifier.assertKnownKeys(tpl, allowed, _err, "crmf/bad-input", "unknown certTemplate field ");
|
|
15327
16131
|
var fields = [];
|
|
15328
16132
|
if (tpl.version != null) {
|
|
15329
16133
|
if (tpl.version !== 2) throw _err("crmf/bad-version", "certTemplate version MUST be 2 (v3) if supplied (RFC 4211 sec. 5)");
|
|
@@ -15368,9 +16172,11 @@ var require_crmf_sign = __commonJS({
|
|
|
15368
16172
|
}
|
|
15369
16173
|
if (!spec || typeof spec !== "object") throw _err("crmf/bad-input", label + " must be an object or an array of pre-encoded AttributeTypeAndValue DER");
|
|
15370
16174
|
var out = [], seen = {};
|
|
16175
|
+
guard.identifier.assertKnownKeys(spec, valueMap, _err, "crmf/bad-input", function(k) {
|
|
16176
|
+
return "unknown " + label + " " + JSON.stringify(k) + "; pass a pre-encoded AttributeTypeAndValue DER via the array form for a " + label + " entry outside " + Object.keys(valueMap).join("/");
|
|
16177
|
+
});
|
|
15371
16178
|
Object.keys(spec).forEach(function(k) {
|
|
15372
16179
|
var enc = valueMap[k];
|
|
15373
|
-
if (!enc) throw _err("crmf/bad-input", "unknown " + label + " " + JSON.stringify(k) + "; pass a pre-encoded AttributeTypeAndValue DER via the array form for a " + label + " entry outside " + Object.keys(valueMap).join("/"));
|
|
15374
16180
|
var typeOid = O(k);
|
|
15375
16181
|
if (seen[typeOid]) throw _err(code, "duplicate " + label + " type " + k);
|
|
15376
16182
|
seen[typeOid] = true;
|
|
@@ -15441,9 +16247,7 @@ var require_crmf_sign = __commonJS({
|
|
|
15441
16247
|
}
|
|
15442
16248
|
function _buildCertReqMsg(spec, key, opts) {
|
|
15443
16249
|
if (!spec || typeof spec !== "object" || Buffer.isBuffer(spec)) throw _err("crmf/bad-input", "each certificate-request-message spec must be an object");
|
|
15444
|
-
|
|
15445
|
-
if (!KNOWN_SPEC_KEYS[k]) throw _err("crmf/bad-input", "unknown spec field " + JSON.stringify(k));
|
|
15446
|
-
});
|
|
16250
|
+
guard.identifier.assertKnownKeys(spec, KNOWN_SPEC_KEYS, _err, "crmf/bad-input", "unknown spec field ");
|
|
15447
16251
|
if (spec.certTemplate == null) throw _err("crmf/bad-input", "spec.certTemplate is required");
|
|
15448
16252
|
var signingKey = key && typeof key === "object" && !Buffer.isBuffer(key) && !(key instanceof Uint8Array) && key.type == null && "key" in key ? key.key : key;
|
|
15449
16253
|
var template = _encodeCertTemplate(spec.certTemplate);
|
|
@@ -15463,8 +16267,8 @@ var require_crmf_sign = __commonJS({
|
|
|
15463
16267
|
var specs;
|
|
15464
16268
|
if (spec.messages != null) {
|
|
15465
16269
|
if (!Array.isArray(spec.messages)) throw _err("crmf/bad-input", "spec.messages must be an array of certificate-request-message specs");
|
|
15466
|
-
|
|
15467
|
-
|
|
16270
|
+
guard.identifier.assertKnownKeys(spec, KNOWN_BATCH_KEYS, _err, "crmf/bad-input", function(k) {
|
|
16271
|
+
return "unknown batch-envelope field " + JSON.stringify(k) + " -- a batch spec carries only 'messages'";
|
|
15468
16272
|
});
|
|
15469
16273
|
specs = spec.messages;
|
|
15470
16274
|
} else {
|
|
@@ -15509,8 +16313,17 @@ var require_pbes2 = __commonJS({
|
|
|
15509
16313
|
PRF_NODE_BY_OID[O(n)] = PRF_NODE_BY_NAME[n];
|
|
15510
16314
|
});
|
|
15511
16315
|
var CONTENT_KEYBITS = {};
|
|
15512
|
-
|
|
16316
|
+
var CONTENT_MODE = {};
|
|
16317
|
+
[
|
|
16318
|
+
["aes128-CBC", 128, "cbc"],
|
|
16319
|
+
["aes192-CBC", 192, "cbc"],
|
|
16320
|
+
["aes256-CBC", 256, "cbc"],
|
|
16321
|
+
["aes128-GCM", 128, "gcm"],
|
|
16322
|
+
["aes192-GCM", 192, "gcm"],
|
|
16323
|
+
["aes256-GCM", 256, "gcm"]
|
|
16324
|
+
].forEach(function(r) {
|
|
15513
16325
|
CONTENT_KEYBITS[O(r[0])] = r[1];
|
|
16326
|
+
CONTENT_MODE[O(r[0])] = r[2];
|
|
15514
16327
|
});
|
|
15515
16328
|
function passwordBytes(p, E, prefix) {
|
|
15516
16329
|
if (Buffer.isBuffer(p)) return p;
|
|
@@ -15663,6 +16476,7 @@ var require_pbes2 = __commonJS({
|
|
|
15663
16476
|
pbes2Encrypt,
|
|
15664
16477
|
pbes2Decrypt,
|
|
15665
16478
|
CONTENT_KEYBITS,
|
|
16479
|
+
CONTENT_MODE,
|
|
15666
16480
|
pbmac1AlgId,
|
|
15667
16481
|
pbmac1
|
|
15668
16482
|
};
|
|
@@ -15769,6 +16583,7 @@ var require_cmp_build = __commonJS({
|
|
|
15769
16583
|
var CRMF_BODY = { ir: 1, cr: 1, kur: 1 };
|
|
15770
16584
|
var CERT_REP_ARM = { ip: 1, cp: 1, kup: 1, ccp: 1 };
|
|
15771
16585
|
var KNOWN_OPTS_KEYS = { key: 1, cert: 1, mac: 1, extraCerts: 1, pem: 1, pss: 1, digestAlgorithm: 1 };
|
|
16586
|
+
var KNOWN_MESSAGE_KEYS = { header: 1, body: 1 };
|
|
15772
16587
|
var KNOWN_MAC_KEYS = { secret: 1, salt: 1, iterationCount: 1, prf: 1, keyLength: 1, algorithm: 1 };
|
|
15773
16588
|
var PBMAC1_DEFAULT_ITER = 1e5;
|
|
15774
16589
|
var PBMAC1_DEFAULT_SALT_BYTES = 16;
|
|
@@ -15858,9 +16673,7 @@ var require_cmp_build = __commonJS({
|
|
|
15858
16673
|
}
|
|
15859
16674
|
function _encodeHeader(headerSpec, protectionAlgDer, pvno) {
|
|
15860
16675
|
if (!headerSpec || typeof headerSpec !== "object" || Buffer.isBuffer(headerSpec)) throw _err("cmp/bad-input", "message.header must be an object");
|
|
15861
|
-
|
|
15862
|
-
if (!KNOWN_HEADER_KEYS[k]) throw _err("cmp/bad-input", "unknown header field " + JSON.stringify(k));
|
|
15863
|
-
});
|
|
16676
|
+
guard.identifier.assertKnownKeys(headerSpec, KNOWN_HEADER_KEYS, _err, "cmp/bad-input", "unknown header field ");
|
|
15864
16677
|
if (headerSpec.sender == null) throw _err("cmp/bad-input", "message.header.sender is required (GeneralName)");
|
|
15865
16678
|
if (headerSpec.recipient == null) throw _err("cmp/bad-input", "message.header.recipient is required (GeneralName)");
|
|
15866
16679
|
var children = [
|
|
@@ -16183,9 +16996,7 @@ var require_cmp_build = __commonJS({
|
|
|
16183
16996
|
}
|
|
16184
16997
|
var m = opts.mac;
|
|
16185
16998
|
if (!m || typeof m !== "object" || Buffer.isBuffer(m)) throw _err("cmp/bad-input", "opts.mac must be an object { secret, salt?, iterationCount?, prf?, keyLength? }");
|
|
16186
|
-
|
|
16187
|
-
if (!KNOWN_MAC_KEYS[k]) throw _err("cmp/bad-input", "unknown opts.mac field " + JSON.stringify(k));
|
|
16188
|
-
});
|
|
16999
|
+
guard.identifier.assertKnownKeys(m, KNOWN_MAC_KEYS, _err, "cmp/bad-input", "unknown opts.mac field ");
|
|
16189
17000
|
if (m.algorithm != null && m.algorithm !== "pbmac1") throw _err("cmp/unsupported-algorithm", "opts.mac.algorithm " + JSON.stringify(m.algorithm) + " is not supported (v1 ships pbmac1; passwordBasedMac is deferred)");
|
|
16190
17001
|
var secret = m.secret;
|
|
16191
17002
|
if (typeof secret !== "string" || !secret) {
|
|
@@ -16224,12 +17035,10 @@ var require_cmp_build = __commonJS({
|
|
|
16224
17035
|
function _build(message, opts) {
|
|
16225
17036
|
opts = opts || {};
|
|
16226
17037
|
if (!message || typeof message !== "object" || Buffer.isBuffer(message)) throw _err("cmp/bad-input", "the PKIMessage spec must be an object { header, body }");
|
|
16227
|
-
|
|
16228
|
-
|
|
16229
|
-
});
|
|
16230
|
-
Object.keys(opts).forEach(function(k) {
|
|
16231
|
-
if (!KNOWN_OPTS_KEYS[k]) throw _err("cmp/bad-input", "unknown opts field " + JSON.stringify(k));
|
|
17038
|
+
guard.identifier.assertKnownKeys(message, KNOWN_MESSAGE_KEYS, _err, "cmp/bad-input", function(k) {
|
|
17039
|
+
return "unknown message field " + JSON.stringify(k) + " (a message carries only header + body)";
|
|
16232
17040
|
});
|
|
17041
|
+
guard.identifier.assertKnownKeys(opts, KNOWN_OPTS_KEYS, _err, "cmp/bad-input", "unknown opts field ");
|
|
16233
17042
|
if (message.header == null) throw _err("cmp/bad-input", "message.header is required");
|
|
16234
17043
|
if (message.body == null) throw _err("cmp/bad-input", "message.body is required");
|
|
16235
17044
|
var prot = _resolveProtection(opts);
|
|
@@ -16338,9 +17147,7 @@ var require_cmp_build = __commonJS({
|
|
|
16338
17147
|
}
|
|
16339
17148
|
function _transfer(url, message, opts) {
|
|
16340
17149
|
opts = opts || {};
|
|
16341
|
-
|
|
16342
|
-
if (!KNOWN_TRANSFER_OPTS[k]) throw _err("cmp/bad-input", "unknown opts field " + JSON.stringify(k));
|
|
16343
|
-
});
|
|
17150
|
+
guard.identifier.assertKnownKeys(opts, KNOWN_TRANSFER_OPTS, _err, "cmp/bad-input", "unknown opts field ");
|
|
16344
17151
|
var der = _cmpMessageDer(message);
|
|
16345
17152
|
var parsedUrl;
|
|
16346
17153
|
try {
|
|
@@ -16387,8 +17194,8 @@ var require_cmp_build = __commonJS({
|
|
|
16387
17194
|
var KNOWN_WELLKNOWN_OPTS = { label: 1, operation: 1 };
|
|
16388
17195
|
function wellKnownUrl(base, opts) {
|
|
16389
17196
|
opts = opts || {};
|
|
16390
|
-
|
|
16391
|
-
|
|
17197
|
+
guard.identifier.assertKnownKeys(opts, KNOWN_WELLKNOWN_OPTS, _err, "cmp/bad-input", function(k) {
|
|
17198
|
+
return "unknown wellKnownUrl option " + JSON.stringify(k) + " (expected label / operation)";
|
|
16392
17199
|
});
|
|
16393
17200
|
var u;
|
|
16394
17201
|
try {
|
|
@@ -16885,9 +17692,7 @@ var require_cmp_verify = __commonJS({
|
|
|
16885
17692
|
async function _verify(message, opts) {
|
|
16886
17693
|
if (opts == null) opts = {};
|
|
16887
17694
|
if (typeof opts !== "object" || Buffer.isBuffer(opts)) throw _err("cmp/bad-input", "opts must be an object");
|
|
16888
|
-
|
|
16889
|
-
if (!KNOWN_VERIFY_OPTS[k]) throw _err("cmp/bad-input", "unknown opts field " + JSON.stringify(k));
|
|
16890
|
-
});
|
|
17695
|
+
guard.identifier.assertKnownKeys(opts, KNOWN_VERIFY_OPTS, _err, "cmp/bad-input", "unknown opts field ");
|
|
16891
17696
|
["transactionID", "expectRecipNonce"].forEach(function(k) {
|
|
16892
17697
|
if (opts[k] != null && !Buffer.isBuffer(opts[k]) && !(opts[k] instanceof Uint8Array)) throw _err("cmp/bad-input", "opts." + k + " must be a Buffer / Uint8Array");
|
|
16893
17698
|
});
|
|
@@ -17271,9 +18076,7 @@ var require_cmp_session = __commonJS({
|
|
|
17271
18076
|
function session(opts) {
|
|
17272
18077
|
if (opts == null) opts = {};
|
|
17273
18078
|
if (typeof opts !== "object" || Buffer.isBuffer(opts)) throw _err("cmp/bad-input", "opts must be an object");
|
|
17274
|
-
|
|
17275
|
-
if (!KNOWN_SESSION_OPTS[k]) throw _err("cmp/bad-input", "unknown session opts field " + JSON.stringify(k));
|
|
17276
|
-
});
|
|
18079
|
+
guard.identifier.assertKnownKeys(opts, KNOWN_SESSION_OPTS, _err, "cmp/bad-input", "unknown session opts field ");
|
|
17277
18080
|
opts = Object.assign({}, opts);
|
|
17278
18081
|
if (typeof opts.url !== "string" || !opts.url) throw _err("cmp/bad-input", "opts.url (the CMP endpoint) is required");
|
|
17279
18082
|
var isSig = opts.key != null || opts.cert != null;
|
|
@@ -20338,15 +21141,26 @@ var require_cms_encrypt = __commonJS({
|
|
|
20338
21141
|
var pub = await subtle.importKey("spki", cert.subjectPublicKeyInfo.bytes, { name: wcName }, false, ["encapsulateBits"]);
|
|
20339
21142
|
var kem = await subtle.encapsulateBits({ name: wcName }, pub);
|
|
20340
21143
|
var ss = Buffer.from(kem.sharedKey), kemct = Buffer.from(kem.ciphertext);
|
|
20341
|
-
var
|
|
20342
|
-
|
|
20343
|
-
|
|
20344
|
-
|
|
20345
|
-
|
|
20346
|
-
|
|
20347
|
-
|
|
20348
|
-
|
|
20349
|
-
|
|
21144
|
+
var kek = null, kekAb = null;
|
|
21145
|
+
try {
|
|
21146
|
+
var ssKey = await subtle.importKey("raw", ss, { name: "HKDF" }, false, ["deriveBits"]);
|
|
21147
|
+
kekAb = await subtle.deriveBits({ name: "HKDF", hash: "SHA-256", salt: Buffer.alloc(0), info: _kemOtherInfo(wrapName, kekBytes, ukm) }, ssKey, kekBytes * 8);
|
|
21148
|
+
kek = Buffer.from(kekAb);
|
|
21149
|
+
var encryptedKey = await _aesKwWrap(kek, cek);
|
|
21150
|
+
var rid = _rid(cert, opts.keyIdentifier);
|
|
21151
|
+
var kemriKids = [b.integer(0n), rid.node, _algId(oid.name(keyOid), "absent"), b.octetString(kemct), _algId("hkdfWithSha256", "absent"), b.integer(BigInt(kekBytes))];
|
|
21152
|
+
if (ukm) kemriKids.push(b.explicit(0, b.octetString(ukm)));
|
|
21153
|
+
kemriKids.push(_algId(wrapName, "absent"), b.octetString(encryptedKey));
|
|
21154
|
+
var kemri = b.sequence(kemriKids);
|
|
21155
|
+
return { tag: 4, node: b.sequence([b.oid(O("kem")), kemri]) };
|
|
21156
|
+
} finally {
|
|
21157
|
+
guard.secret.zeroizeAll(
|
|
21158
|
+
[ss, kek, kem.sharedKey ? new Uint8Array(kem.sharedKey) : null, kekAb ? new Uint8Array(kekAb) : null],
|
|
21159
|
+
CmsError,
|
|
21160
|
+
"cms/bad-input",
|
|
21161
|
+
"the KEM shared secret"
|
|
21162
|
+
);
|
|
21163
|
+
}
|
|
20350
21164
|
}
|
|
20351
21165
|
async function _aesKwWrap(kek, cek) {
|
|
20352
21166
|
var kekKey = await subtle.importKey("raw", kek, { name: "AES-KW" }, false, ["wrapKey"]);
|
|
@@ -20602,6 +21416,7 @@ var require_cms_decrypt = __commonJS({
|
|
|
20602
21416
|
return new CmsError("cms/decrypt-failed", "the CMS content could not be decrypted (uniform by design -- padding / integrity / key-unwrap failures are indistinguishable to defeat oracles)");
|
|
20603
21417
|
}
|
|
20604
21418
|
var CONTENT_KEYBITS = pbes2.CONTENT_KEYBITS;
|
|
21419
|
+
var CONTENT_MODE = pbes2.CONTENT_MODE;
|
|
20605
21420
|
async function decrypt(input, keyMaterial, opts) {
|
|
20606
21421
|
opts = opts || {};
|
|
20607
21422
|
if (keyMaterial == null || typeof keyMaterial !== "object") throw _err("cms/bad-input", "decrypt requires a key-material object");
|
|
@@ -20619,6 +21434,7 @@ var require_cms_decrypt = __commonJS({
|
|
|
20619
21434
|
var recips = parsed.recipientInfos || [];
|
|
20620
21435
|
var candidates = _selectCandidates(recips, keyMaterial, opts);
|
|
20621
21436
|
var eci = parsed.encryptedContentInfo;
|
|
21437
|
+
_assertContentCipherMode(eci, ct);
|
|
20622
21438
|
for (var ci = 0; ci < candidates.length; ci++) {
|
|
20623
21439
|
try {
|
|
20624
21440
|
_assertSupported(candidates[ci].ri, keyMaterial);
|
|
@@ -20814,7 +21630,7 @@ var require_cms_decrypt = __commonJS({
|
|
|
20814
21630
|
var inner = asn1.decode(kea.parameters);
|
|
20815
21631
|
var innerOid = asn1.read.oid(inner.children[0]);
|
|
20816
21632
|
var innerBits = CONTENT_KEYBITS[innerOid];
|
|
20817
|
-
if (!innerBits ||
|
|
21633
|
+
if (!innerBits || CONTENT_MODE[innerOid] !== "cbc") throw _err("cms/unsupported-algorithm", "unsupported pwri inner cipher");
|
|
20818
21634
|
var iv = asn1.read.octetString(inner.children[1]);
|
|
20819
21635
|
var kek = nodeCrypto.pbkdf2Sync(pbes2.passwordBytes(km.password, _err, "cms"), pb.salt, pb.iterations, innerBits / 8, pb.prfNode);
|
|
20820
21636
|
return _pwriUnwrap(kek, ri.encryptedKey, iv, innerBits);
|
|
@@ -20831,10 +21647,30 @@ var require_cms_decrypt = __commonJS({
|
|
|
20831
21647
|
var wrapAlg = k.wrap;
|
|
20832
21648
|
if (WRAP_KEK_LENGTHS[wrapAlg.oid] !== kekBytes) throw _fail();
|
|
20833
21649
|
var priv = await subtle.importKey("pkcs8", _normKeyDer(km.key), { name: wcName }, false, ["decapsulateBits"]);
|
|
20834
|
-
var ss =
|
|
20835
|
-
|
|
20836
|
-
|
|
20837
|
-
|
|
21650
|
+
var ss = null, kek = null, ssAb = null, kekAb = null;
|
|
21651
|
+
try {
|
|
21652
|
+
ssAb = await subtle.decapsulateBits({ name: wcName }, priv, kemct);
|
|
21653
|
+
ss = Buffer.from(ssAb);
|
|
21654
|
+
var ssKey = await subtle.importKey("raw", ss, { name: "HKDF" }, false, ["deriveBits"]);
|
|
21655
|
+
kekAb = await subtle.deriveBits({ name: "HKDF", hash: "SHA-256", salt: Buffer.alloc(0), info: _kemOtherInfo(wrapAlg.name, kekBytes, k.ukm || null) }, ssKey, kekBytes * 8);
|
|
21656
|
+
kek = Buffer.from(kekAb);
|
|
21657
|
+
return await _aesKwUnwrap(kek, k.encryptedKey);
|
|
21658
|
+
} finally {
|
|
21659
|
+
guard.secret.zeroizeAll(
|
|
21660
|
+
[ss, kek, ssAb ? new Uint8Array(ssAb) : null, kekAb ? new Uint8Array(kekAb) : null],
|
|
21661
|
+
CmsError,
|
|
21662
|
+
"cms/bad-input",
|
|
21663
|
+
"the KEM shared secret"
|
|
21664
|
+
);
|
|
21665
|
+
}
|
|
21666
|
+
}
|
|
21667
|
+
function _assertContentCipherMode(eci, ct) {
|
|
21668
|
+
var oidStr = eci.contentEncryptionAlgorithm.oid;
|
|
21669
|
+
if (!CONTENT_MODE[oidStr]) return;
|
|
21670
|
+
var wantMode = ct === "authEnvelopedData" ? "gcm" : "cbc";
|
|
21671
|
+
if (CONTENT_MODE[oidStr] !== wantMode) {
|
|
21672
|
+
throw _err("cms/unsupported-algorithm", "contentEncryptionAlgorithm " + oidStr + " is not a " + wantMode.toUpperCase() + " cipher, which " + ct + " requires (RFC 5083 sec. 2.1 / RFC 5084 sec. 3)");
|
|
21673
|
+
}
|
|
20838
21674
|
}
|
|
20839
21675
|
async function _openContent(parsed, eci, cek, ct) {
|
|
20840
21676
|
var alg = eci.contentEncryptionAlgorithm;
|
|
@@ -20906,7 +21742,15 @@ var require_cms_decrypt = __commonJS({
|
|
|
20906
21742
|
async function _aesKwUnwrap(kek, wrapped) {
|
|
20907
21743
|
var kekKey = await subtle.importKey("raw", kek, { name: "AES-KW" }, false, ["unwrapKey"]);
|
|
20908
21744
|
var raw = await subtle.unwrapKey("raw", wrapped, kekKey, { name: "AES-KW" }, { name: "HMAC", hash: "SHA-256" }, true, ["sign"]);
|
|
20909
|
-
|
|
21745
|
+
var rawAb = await subtle.exportKey("raw", raw);
|
|
21746
|
+
try {
|
|
21747
|
+
var view = new Uint8Array(rawAb);
|
|
21748
|
+
var out = Buffer.alloc(view.length);
|
|
21749
|
+
out.set(view);
|
|
21750
|
+
return out;
|
|
21751
|
+
} finally {
|
|
21752
|
+
guard.secret.zeroize(new Uint8Array(rawAb), CmsError, "cms/bad-input", "the unwrapped content key");
|
|
21753
|
+
}
|
|
20910
21754
|
}
|
|
20911
21755
|
function _eccSharedInfo(wrapName, ukm, kekBytes) {
|
|
20912
21756
|
var kids = [b.sequence([b.oid(O(wrapName))])];
|
|
@@ -23209,8 +24053,8 @@ var require_x509_sign = __commonJS({
|
|
|
23209
24053
|
return arr;
|
|
23210
24054
|
}
|
|
23211
24055
|
if (typeof extSpec !== "object") throw _err("x509/bad-input", "extensions must be an object or an array of pre-encoded Extension DER");
|
|
23212
|
-
|
|
23213
|
-
|
|
24056
|
+
guard.identifier.assertKnownKeys(extSpec, KNOWN_EXT_KEYS, _err, "x509/bad-input", function(k) {
|
|
24057
|
+
return "unknown extension " + JSON.stringify(k) + " in the extensions spec; pass a pre-encoded Extension DER via the array form for a custom extension";
|
|
23214
24058
|
});
|
|
23215
24059
|
var bc = extSpec.basicConstraints;
|
|
23216
24060
|
if (bc != null) _validateBcSpec(bc);
|
|
@@ -23384,7 +24228,9 @@ var require_csr_sign = __commonJS({
|
|
|
23384
24228
|
var pkix = require_schema_pkix();
|
|
23385
24229
|
var pkiBuild = require_pki_build();
|
|
23386
24230
|
var frameworkError = require_framework_error();
|
|
24231
|
+
var guard = require_guard_all();
|
|
23387
24232
|
var CsrError = frameworkError.CsrError;
|
|
24233
|
+
var KNOWN_SPEC_KEYS = { subject: 1, subjectPublicKey: 1, extensionRequest: 1, challengePassword: 1, attributes: 1 };
|
|
23388
24234
|
var b = asn1.build;
|
|
23389
24235
|
function _err(code, message, cause) {
|
|
23390
24236
|
return new CsrError(code, message, cause);
|
|
@@ -23425,9 +24271,7 @@ var require_csr_sign = __commonJS({
|
|
|
23425
24271
|
function _sign(spec, key, opts) {
|
|
23426
24272
|
opts = opts || {};
|
|
23427
24273
|
if (!spec || typeof spec !== "object" || Buffer.isBuffer(spec)) throw _err("csr/bad-input", "the certification-request spec must be an object");
|
|
23428
|
-
|
|
23429
|
-
if (k !== "subject" && k !== "subjectPublicKey" && k !== "extensionRequest" && k !== "challengePassword" && k !== "attributes") throw _err("csr/bad-input", "unknown spec field " + JSON.stringify(k));
|
|
23430
|
-
});
|
|
24274
|
+
guard.identifier.assertKnownKeys(spec, KNOWN_SPEC_KEYS, _err, "csr/bad-input", "unknown spec field ");
|
|
23431
24275
|
var signingKey = key && typeof key === "object" && !Buffer.isBuffer(key) && !(key instanceof Uint8Array) && key.type == null && "key" in key ? key.key : key;
|
|
23432
24276
|
if (signingKey == null) throw _err("csr/bad-input", "a signing key (the subject's private key) is required");
|
|
23433
24277
|
var subjectSpki = _b.reqDer(spec.subjectPublicKey, "spec.subjectPublicKey (the SPKI DER of the requested key)");
|
|
@@ -23595,9 +24439,7 @@ var require_attrcert_sign = __commonJS({
|
|
|
23595
24439
|
}
|
|
23596
24440
|
function _encodeHolder(holder) {
|
|
23597
24441
|
if (!holder || typeof holder !== "object" || Buffer.isBuffer(holder)) throw _err("attrcert/bad-input", "holder must be an object with exactly one form");
|
|
23598
|
-
|
|
23599
|
-
if (!KNOWN_HOLDER_KEYS[k]) throw _err("attrcert/bad-input", "unknown holder form " + JSON.stringify(k));
|
|
23600
|
-
});
|
|
24442
|
+
guard.identifier.assertKnownKeys(holder, KNOWN_HOLDER_KEYS, _err, "attrcert/bad-input", "unknown holder form ");
|
|
23601
24443
|
var forms = Object.keys(holder).filter(function(k) {
|
|
23602
24444
|
return holder[k] != null;
|
|
23603
24445
|
});
|
|
@@ -23814,8 +24656,10 @@ var require_attrcert_sign = __commonJS({
|
|
|
23814
24656
|
return b.sequence(attrs);
|
|
23815
24657
|
}
|
|
23816
24658
|
if (!attrSpec || typeof attrSpec !== "object") throw _err("attrcert/bad-input", "attributes must be an object or an array of pre-encoded Attribute DER");
|
|
24659
|
+
guard.identifier.assertKnownKeys(attrSpec, ATTR_VALUE_ENCODER, _err, "attrcert/bad-input", function(k) {
|
|
24660
|
+
return "unknown attribute " + JSON.stringify(k) + "; pass a pre-encoded Attribute DER via the array form for a custom attribute";
|
|
24661
|
+
});
|
|
23817
24662
|
Object.keys(attrSpec).forEach(function(k) {
|
|
23818
|
-
if (!ATTR_VALUE_ENCODER[k]) throw _err("attrcert/bad-input", "unknown attribute " + JSON.stringify(k) + "; pass a pre-encoded Attribute DER via the array form for a custom attribute");
|
|
23819
24663
|
add(O(ATTR_OID_NAME[k]), ATTR_VALUE_ENCODER[k](attrSpec[k]));
|
|
23820
24664
|
});
|
|
23821
24665
|
if (!attrs.length) throw _err("attrcert/bad-attributes", "attributes must carry at least one Attribute (RFC 5755 sec. 4.2.7)");
|
|
@@ -23850,8 +24694,8 @@ var require_attrcert_sign = __commonJS({
|
|
|
23850
24694
|
return b.sequence(exts);
|
|
23851
24695
|
}
|
|
23852
24696
|
if (typeof extSpec !== "object") throw _err("attrcert/bad-input", "extensions must be an object or an array of pre-encoded Extension DER");
|
|
23853
|
-
|
|
23854
|
-
|
|
24697
|
+
guard.identifier.assertKnownKeys(extSpec, EXT_META, _err, "attrcert/bad-input", function(k) {
|
|
24698
|
+
return "unknown extension " + JSON.stringify(k) + "; pass a pre-encoded Extension DER via the array form for a custom extension";
|
|
23855
24699
|
});
|
|
23856
24700
|
var out = [], seen = {};
|
|
23857
24701
|
Object.keys(extSpec).forEach(function(k) {
|
|
@@ -23872,9 +24716,7 @@ var require_attrcert_sign = __commonJS({
|
|
|
23872
24716
|
function _sign(spec, issuer, opts) {
|
|
23873
24717
|
opts = opts || {};
|
|
23874
24718
|
if (!spec || typeof spec !== "object" || Buffer.isBuffer(spec)) throw _err("attrcert/bad-input", "the attribute-certificate spec must be an object");
|
|
23875
|
-
|
|
23876
|
-
if (!KNOWN_SPEC_KEYS[k]) throw _err("attrcert/bad-input", "unknown spec field " + JSON.stringify(k));
|
|
23877
|
-
});
|
|
24719
|
+
guard.identifier.assertKnownKeys(spec, KNOWN_SPEC_KEYS, _err, "attrcert/bad-input", "unknown spec field ");
|
|
23878
24720
|
issuer = issuer || {};
|
|
23879
24721
|
if (issuer.key == null) throw _err("attrcert/bad-input", "a signing key (issuer.key, the AA's PKCS#8 private key) is required");
|
|
23880
24722
|
var issuerDnSpec, aaSpki;
|
|
@@ -24056,8 +24898,8 @@ var require_crl_sign = __commonJS({
|
|
|
24056
24898
|
}
|
|
24057
24899
|
function _idpValue(idp) {
|
|
24058
24900
|
if (!idp || typeof idp !== "object" || Array.isArray(idp) || Buffer.isBuffer(idp)) throw _err("crl/bad-idp", "issuingDistributionPoint must be an object");
|
|
24059
|
-
|
|
24060
|
-
|
|
24901
|
+
guard.identifier.assertKnownKeys(idp, KNOWN_IDP_KEYS, _err, "crl/bad-idp", function(k) {
|
|
24902
|
+
return "unknown issuingDistributionPoint field " + JSON.stringify(k) + " (pass a pre-encoded Extension DER via the extensions array for an exotic field like onlySomeReasons)";
|
|
24061
24903
|
});
|
|
24062
24904
|
if (idp.onlyContainsAttributeCerts === true) throw _err("crl/bad-idp", "onlyContainsAttributeCerts=TRUE is not permitted for a conforming CRL issuer (RFC 5280 sec. 5.2.5)");
|
|
24063
24905
|
var children = [];
|
|
@@ -24161,8 +25003,8 @@ var require_crl_sign = __commonJS({
|
|
|
24161
25003
|
return { exts: out, isDelta };
|
|
24162
25004
|
}
|
|
24163
25005
|
if (typeof ext !== "object") throw _err("crl/bad-input", "extensions must be an object or an array of pre-encoded Extension DER");
|
|
24164
|
-
|
|
24165
|
-
|
|
25006
|
+
guard.identifier.assertKnownKeys(ext, KNOWN_CRL_EXT_KEYS, _err, "crl/bad-input", function(k) {
|
|
25007
|
+
return "unknown CRL extension " + JSON.stringify(k) + " in the extensions spec; pass a pre-encoded Extension DER via the array form";
|
|
24166
25008
|
});
|
|
24167
25009
|
isDelta = ext.deltaCRLIndicator != null;
|
|
24168
25010
|
if (ext.authorityKeyIdentifier != null) push("authorityKeyIdentifier", false, _extAki(_akiKeyId(ext.authorityKeyIdentifier, ctx)));
|
|
@@ -24394,7 +25236,6 @@ var require_key = __commonJS({
|
|
|
24394
25236
|
var guard = require_guard_all();
|
|
24395
25237
|
var b = asn1.build;
|
|
24396
25238
|
var subtle = webcrypto.webcrypto.subtle;
|
|
24397
|
-
var CryptoKey = webcrypto.CryptoKey;
|
|
24398
25239
|
var KeyError = frameworkError.KeyError;
|
|
24399
25240
|
var PemError = frameworkError.PemError;
|
|
24400
25241
|
function O(n) {
|
|
@@ -24435,7 +25276,7 @@ var require_key = __commonJS({
|
|
|
24435
25276
|
INFER_ALG[O("id-slh-dsa-" + s)] = { name: ("SLH-DSA-" + s).toUpperCase() };
|
|
24436
25277
|
});
|
|
24437
25278
|
function _isCryptoKey(x) {
|
|
24438
|
-
return x
|
|
25279
|
+
return webcrypto.isCryptoKeyLike(x);
|
|
24439
25280
|
}
|
|
24440
25281
|
function _algName(a) {
|
|
24441
25282
|
return typeof a === "string" ? a : a && a.name;
|
|
@@ -24443,7 +25284,7 @@ var require_key = __commonJS({
|
|
|
24443
25284
|
async function _toPrivateKeyDer(input) {
|
|
24444
25285
|
if (_isCryptoKey(input)) {
|
|
24445
25286
|
if (input.type !== "private") throw _err("key/bad-input", "a private CryptoKey is required (got a " + input.type + " key)");
|
|
24446
|
-
return
|
|
25287
|
+
return webcrypto.exportAnyKey(input, _err, "key/bad-input");
|
|
24447
25288
|
}
|
|
24448
25289
|
return pkix.coerceToDer(input, { pemLabel: "PRIVATE KEY", PemError, ErrorClass: KeyError, prefix: "key" });
|
|
24449
25290
|
}
|
|
@@ -24498,15 +25339,11 @@ var require_key = __commonJS({
|
|
|
24498
25339
|
async function export_(key, opts) {
|
|
24499
25340
|
opts = opts || {};
|
|
24500
25341
|
if (!_isCryptoKey(key)) throw _err("key/bad-input", "export expects a WebCrypto CryptoKey");
|
|
24501
|
-
var
|
|
24502
|
-
if (key.type === "private")
|
|
24503
|
-
|
|
24504
|
-
|
|
24505
|
-
|
|
24506
|
-
format = "spki";
|
|
24507
|
-
defaultLabel = "PUBLIC KEY";
|
|
24508
|
-
} else throw _err("key/bad-input", "export supports asymmetric (private / public) CryptoKeys only");
|
|
24509
|
-
var der = Buffer.from(await subtle.exportKey(format, key));
|
|
25342
|
+
var defaultLabel;
|
|
25343
|
+
if (key.type === "private") defaultLabel = "PRIVATE KEY";
|
|
25344
|
+
else if (key.type === "public") defaultLabel = "PUBLIC KEY";
|
|
25345
|
+
else throw _err("key/bad-input", "export supports asymmetric (private / public) CryptoKeys only");
|
|
25346
|
+
var der = await webcrypto.exportAnyKey(key, _err, "key/bad-input");
|
|
24510
25347
|
var fmt = opts.format || "der";
|
|
24511
25348
|
if (fmt === "der") return der;
|
|
24512
25349
|
if (fmt === "pem") return pkix.pemEncode(der, opts.label || defaultLabel, PemError);
|
|
@@ -27751,7 +28588,8 @@ var require_jose = __commonJS({
|
|
|
27751
28588
|
"node_modules/@blamejs/pki/lib/jose.js"(exports2, module2) {
|
|
27752
28589
|
"use strict";
|
|
27753
28590
|
var constants = require_constants();
|
|
27754
|
-
var
|
|
28591
|
+
var wcEngine = require_webcrypto();
|
|
28592
|
+
var webcrypto = wcEngine.webcrypto;
|
|
27755
28593
|
var frameworkError = require_framework_error();
|
|
27756
28594
|
var guard = require_guard_all();
|
|
27757
28595
|
var edwardsPoint = require_edwards_point();
|
|
@@ -27935,7 +28773,7 @@ var require_jose = __commonJS({
|
|
|
27935
28773
|
var payload = opts.payload;
|
|
27936
28774
|
if (!Buffer.isBuffer(payload)) throw E("jose/bad-input", "payload must be a Buffer (empty Buffer for POST-as-GET)");
|
|
27937
28775
|
payload = guard.bytes.view(payload, JoseError, "jose/bad-input", "payload");
|
|
27938
|
-
if (!
|
|
28776
|
+
if (!wcEngine.isCryptoKeyLike(opts.key)) throw E("jose/bad-input", "a private or secret CryptoKey (opts.key) is required");
|
|
27939
28777
|
var checked = _checkHeader(header, opts.profile || "acme-outer");
|
|
27940
28778
|
if ((checked.algRow.kty === "RSA" || checked.algRow.kty === "oct") && (!opts.key.algorithm.hash || opts.key.algorithm.hash.name !== checked.algRow.hash)) {
|
|
27941
28779
|
throw E("jose/bad-key", "the signing key's hash does not match the algorithm " + checked.alg);
|
|
@@ -27948,7 +28786,8 @@ var require_jose = __commonJS({
|
|
|
27948
28786
|
var payloadB64 = payload.length === 0 ? "" : b64uEncode(payload);
|
|
27949
28787
|
var signingInput = Buffer.from(protectedB64 + "." + payloadB64, "ascii");
|
|
27950
28788
|
var jwk = header.jwk || opts.jwk || {};
|
|
27951
|
-
var
|
|
28789
|
+
var signKey = await wcEngine.adoptKey(opts.key, null, ["sign"], E, "jose/bad-input");
|
|
28790
|
+
var sigBuf = Buffer.from(await webcrypto.subtle.sign(_cryptoAlg(checked.algRow, jwk, signKey), signKey, signingInput));
|
|
27952
28791
|
var want = _expectedSigBytes(checked.algRow, jwk, opts.key);
|
|
27953
28792
|
if (want != null && sigBuf.length !== want) throw E("jose/bad-key", "the signing key produced a " + sigBuf.length + "-byte signature but " + checked.alg + " requires " + want + " (the key does not match the algorithm)");
|
|
27954
28793
|
if (header.jwk) {
|
|
@@ -30077,6 +30916,7 @@ var require_inspect = __commonJS({
|
|
|
30077
30916
|
}
|
|
30078
30917
|
var NS = pkix.makeNS("inspect", InspectError, oid);
|
|
30079
30918
|
var EXT_DECODERS = pkix.certExtensionDecoders(NS).byOid;
|
|
30919
|
+
var OID_UNOTICE = oid.byName("unotice");
|
|
30080
30920
|
var HEX = "0123456789abcdef";
|
|
30081
30921
|
function _hexColon(buf, opts) {
|
|
30082
30922
|
opts = opts || {};
|
|
@@ -30187,14 +31027,14 @@ var require_inspect = __commonJS({
|
|
|
30187
31027
|
}
|
|
30188
31028
|
return _hexColon(buf, {});
|
|
30189
31029
|
}
|
|
31030
|
+
function _gnDn(value) {
|
|
31031
|
+
return value && Array.isArray(value.rdns) ? _dnString(value) : value && value.dn || "";
|
|
31032
|
+
}
|
|
30190
31033
|
function _gn(g) {
|
|
30191
31034
|
if (!g || typeof g !== "object") return "";
|
|
30192
31035
|
var t = g.tagNumber;
|
|
30193
31036
|
if (t === 7 && Buffer.isBuffer(g.value)) return "IP Address:" + _ipString(g.value);
|
|
30194
|
-
if (t === 4)
|
|
30195
|
-
var dn = g.value && Array.isArray(g.value.rdns) ? _dnString(g.value) : g.value && g.value.dn || "";
|
|
30196
|
-
return "DirName:" + dn;
|
|
30197
|
-
}
|
|
31037
|
+
if (t === 4) return "DirName:" + _gnDn(g.value);
|
|
30198
31038
|
if (t === 0) return "othername:" + (Buffer.isBuffer(g.bytes) ? _hexColon(g.bytes, {}) : "<unsupported>");
|
|
30199
31039
|
var kind = GN_KIND[t] || "tag" + t;
|
|
30200
31040
|
var v = typeof g.value === "string" ? _clean(g.value) : Buffer.isBuffer(g.value) ? _hexColon(g.value, {}) : Buffer.isBuffer(g.bytes) ? _hexColon(g.bytes, {}) : "";
|
|
@@ -30325,6 +31165,18 @@ var require_inspect = __commonJS({
|
|
|
30325
31165
|
label = oid.name(qid);
|
|
30326
31166
|
} catch (_e) {
|
|
30327
31167
|
}
|
|
31168
|
+
if (qid === OID_UNOTICE) {
|
|
31169
|
+
var texts = pkix.userNoticeTexts(q);
|
|
31170
|
+
if (texts.length && texts.every(function(t) {
|
|
31171
|
+
return t.text !== null && (t.field !== "organization" || t.noticeNumbers !== null);
|
|
31172
|
+
})) {
|
|
31173
|
+
texts.forEach(function(t) {
|
|
31174
|
+
var nums = t.noticeNumbers && t.noticeNumbers.length ? " #" + t.noticeNumbers.join(", ") : "";
|
|
31175
|
+
lines.push(inner + " " + (label || qid) + " " + t.field + ": " + _clean(t.text) + nums);
|
|
31176
|
+
});
|
|
31177
|
+
return;
|
|
31178
|
+
}
|
|
31179
|
+
}
|
|
30328
31180
|
var val = q && !q.constructed && Buffer.isBuffer(q.content) && _printable(q.content) ? _clean(q.content.toString("latin1")) : _hexColon(q && Buffer.isBuffer(q.bytes) ? q.bytes : Buffer.alloc(0), {});
|
|
30329
31181
|
lines.push(inner + " " + (label || qid) + ": " + val);
|
|
30330
31182
|
});
|
|
@@ -30349,6 +31201,7 @@ var require_inspect = __commonJS({
|
|
|
30349
31201
|
else if (loc.tag === 2) lv = "DNS:" + loc.value;
|
|
30350
31202
|
else if (loc.tag === 1) lv = "email:" + loc.value;
|
|
30351
31203
|
else if (loc.tag === 7) lv = "IP:" + _ipString(loc.value);
|
|
31204
|
+
else if (loc.tag === 4) lv = "DirName:" + _gnDn(loc.value);
|
|
30352
31205
|
else lv = typeof loc.value === "string" ? loc.value : "[" + loc.tag + "]";
|
|
30353
31206
|
return inner + (LABEL[m] || m || ad.accessMethod) + " - " + lv;
|
|
30354
31207
|
}).join("\n");
|
|
@@ -30994,14 +31847,53 @@ var require_lint = __commonJS({
|
|
|
30994
31847
|
return null;
|
|
30995
31848
|
}
|
|
30996
31849
|
}
|
|
30997
|
-
|
|
30998
|
-
|
|
30999
|
-
|
|
31000
|
-
|
|
31001
|
-
|
|
31002
|
-
|
|
31003
|
-
|
|
31004
|
-
|
|
31850
|
+
var OID_UNOTICE = oid.byName("unotice");
|
|
31851
|
+
var _T_BMP = asn1.TAGS.BMP_STRING;
|
|
31852
|
+
var _T_VISIBLE = asn1.TAGS.VISIBLE_STRING;
|
|
31853
|
+
var _T_UTF8 = asn1.TAGS.UTF8_STRING;
|
|
31854
|
+
function _hasControlChar(str) {
|
|
31855
|
+
for (var i = 0; i < str.length; i++) {
|
|
31856
|
+
var c = str.charCodeAt(i);
|
|
31857
|
+
if (c <= 31 || c >= 127 && c <= 159) return true;
|
|
31858
|
+
}
|
|
31859
|
+
return false;
|
|
31860
|
+
}
|
|
31861
|
+
function _policyDisplayTexts(ctx) {
|
|
31862
|
+
var d = ctx.decode("certificatePolicies");
|
|
31863
|
+
if (!d || !Array.isArray(d.value)) return [];
|
|
31864
|
+
var out = [];
|
|
31865
|
+
d.value.forEach(function(pi) {
|
|
31866
|
+
if (!pi.qualifiersBytes || !pi.qualifiersBytes.length) return;
|
|
31867
|
+
var quals;
|
|
31868
|
+
try {
|
|
31869
|
+
quals = asn1.decode(pi.qualifiersBytes).children;
|
|
31870
|
+
} catch (_e) {
|
|
31871
|
+
return;
|
|
31872
|
+
}
|
|
31873
|
+
(quals || []).forEach(function(pq) {
|
|
31874
|
+
var qid;
|
|
31875
|
+
try {
|
|
31876
|
+
qid = asn1.read.oid(pq.children[0]);
|
|
31877
|
+
} catch (_e2) {
|
|
31878
|
+
return;
|
|
31879
|
+
}
|
|
31880
|
+
if (qid !== OID_UNOTICE) return;
|
|
31881
|
+
out = out.concat(pkix.userNoticeTexts(pq.children[1]));
|
|
31882
|
+
});
|
|
31883
|
+
});
|
|
31884
|
+
return out;
|
|
31885
|
+
}
|
|
31886
|
+
function _hasPolicyDisplayText(cert, ctx) {
|
|
31887
|
+
return _policyDisplayTexts(ctx).length > 0;
|
|
31888
|
+
}
|
|
31889
|
+
function _criticalityRule(name, id, severity, citation, message) {
|
|
31890
|
+
return {
|
|
31891
|
+
id,
|
|
31892
|
+
severity,
|
|
31893
|
+
source: "rfc5280",
|
|
31894
|
+
citation,
|
|
31895
|
+
message,
|
|
31896
|
+
appliesTo: function(cert, ctx) {
|
|
31005
31897
|
return !!ctx.raw(name);
|
|
31006
31898
|
},
|
|
31007
31899
|
check: function(cert, ctx) {
|
|
@@ -31238,6 +32130,88 @@ var require_lint = __commonJS({
|
|
|
31238
32130
|
check: function(cert, ctx) {
|
|
31239
32131
|
return ctx.raw("subjectKeyIdentifier") ? null : true;
|
|
31240
32132
|
}
|
|
32133
|
+
},
|
|
32134
|
+
// 4.2.1.4 governs the userNotice qualifier's DisplayText with one MUST NOT and three SHOULD-level
|
|
32135
|
+
// rules. None of them can live in the decoder: the section closes by directing certificate users to
|
|
32136
|
+
// "gracefully handle explicitText with more than 200 characters", so a verifier that rejected these
|
|
32137
|
+
// would refuse certificates that are in the wild and otherwise valid. Reporting them is exactly what
|
|
32138
|
+
// a linter is for, so each rule carries the severity its normative word does.
|
|
32139
|
+
{
|
|
32140
|
+
// DisplayText is SIZE (1..200) -- both ends -- but the two ends get SEPARATE ids rather than one
|
|
32141
|
+
// length rule, because the section treats them differently: it tells certificate users to handle a
|
|
32142
|
+
// notice ABOVE 200 gracefully, and says nothing of the sort about an empty one. An operator acting
|
|
32143
|
+
// on that advice suppresses the over-long finding; folding both into a single id would silently
|
|
32144
|
+
// suppress the empty case along with it, which has no such carve-out.
|
|
32145
|
+
id: "lint/rfc5280/explicit-text-too-long",
|
|
32146
|
+
severity: "warn",
|
|
32147
|
+
source: "rfc5280",
|
|
32148
|
+
citation: "RFC 5280 4.2.1.4",
|
|
32149
|
+
message: "a userNotice DisplayText should not exceed 200 characters",
|
|
32150
|
+
appliesTo: _hasPolicyDisplayText,
|
|
32151
|
+
check: function(cert, ctx) {
|
|
32152
|
+
var over = _policyDisplayTexts(ctx).filter(function(d) {
|
|
32153
|
+
return d.text !== null && d.chars > pkix.DISPLAY_TEXT_MAX;
|
|
32154
|
+
});
|
|
32155
|
+
return over.length ? { context: { count: over.length, longest: Math.max.apply(null, over.map(function(d) {
|
|
32156
|
+
return d.chars;
|
|
32157
|
+
})) } } : null;
|
|
32158
|
+
}
|
|
32159
|
+
},
|
|
32160
|
+
{
|
|
32161
|
+
id: "lint/rfc5280/explicit-text-empty",
|
|
32162
|
+
severity: "warn",
|
|
32163
|
+
source: "rfc5280",
|
|
32164
|
+
citation: "RFC 5280 4.2.1.4",
|
|
32165
|
+
message: "a userNotice DisplayText must not be empty (SIZE (1..200))",
|
|
32166
|
+
appliesTo: _hasPolicyDisplayText,
|
|
32167
|
+
check: function(cert, ctx) {
|
|
32168
|
+
var empty = _policyDisplayTexts(ctx).filter(function(d) {
|
|
32169
|
+
return d.text !== null && d.chars < 1;
|
|
32170
|
+
});
|
|
32171
|
+
return empty.length ? { context: { count: empty.length } } : null;
|
|
32172
|
+
}
|
|
32173
|
+
},
|
|
32174
|
+
{
|
|
32175
|
+
id: "lint/rfc5280/explicit-text-bad-encoding",
|
|
32176
|
+
severity: "error",
|
|
32177
|
+
source: "rfc5280",
|
|
32178
|
+
citation: "RFC 5280 4.2.1.4",
|
|
32179
|
+
message: "conforming CAs must not encode explicitText as VisibleString or BMPString",
|
|
32180
|
+
appliesTo: _hasPolicyDisplayText,
|
|
32181
|
+
check: function(cert, ctx) {
|
|
32182
|
+
var bad = _policyDisplayTexts(ctx).filter(function(d) {
|
|
32183
|
+
return d.field === "explicitText" && (d.tagNumber === _T_VISIBLE || d.tagNumber === _T_BMP);
|
|
32184
|
+
});
|
|
32185
|
+
return bad.length ? { context: { count: bad.length, encoding: bad[0].tagNumber === _T_BMP ? "BMPString" : "VisibleString" } } : null;
|
|
32186
|
+
}
|
|
32187
|
+
},
|
|
32188
|
+
{
|
|
32189
|
+
id: "lint/rfc5280/explicit-text-control-chars",
|
|
32190
|
+
severity: "warn",
|
|
32191
|
+
source: "rfc5280",
|
|
32192
|
+
citation: "RFC 5280 4.2.1.4",
|
|
32193
|
+
message: "an explicitText should not include control characters (U+0000 to U+001F, U+007F to U+009F)",
|
|
32194
|
+
appliesTo: _hasPolicyDisplayText,
|
|
32195
|
+
check: function(cert, ctx) {
|
|
32196
|
+
var bad = _policyDisplayTexts(ctx).filter(function(d) {
|
|
32197
|
+
return d.field === "explicitText" && d.text !== null && _hasControlChar(d.text);
|
|
32198
|
+
});
|
|
32199
|
+
return bad.length ? { context: { count: bad.length } } : null;
|
|
32200
|
+
}
|
|
32201
|
+
},
|
|
32202
|
+
{
|
|
32203
|
+
id: "lint/rfc5280/explicit-text-not-nfc",
|
|
32204
|
+
severity: "notice",
|
|
32205
|
+
source: "rfc5280",
|
|
32206
|
+
citation: "RFC 5280 4.2.1.4",
|
|
32207
|
+
message: "a UTF8String explicitText should be normalized to Unicode normalization form C (NFC)",
|
|
32208
|
+
appliesTo: _hasPolicyDisplayText,
|
|
32209
|
+
check: function(cert, ctx) {
|
|
32210
|
+
var bad = _policyDisplayTexts(ctx).filter(function(d) {
|
|
32211
|
+
return d.field === "explicitText" && d.text !== null && d.tagNumber === _T_UTF8 && d.text.normalize("NFC") !== d.text;
|
|
32212
|
+
});
|
|
32213
|
+
return bad.length ? { context: { count: bad.length } } : null;
|
|
32214
|
+
}
|
|
31241
32215
|
}
|
|
31242
32216
|
];
|
|
31243
32217
|
function _isTls(cert, ctx) {
|
|
@@ -31359,8 +32333,8 @@ var require_lint = __commonJS({
|
|
|
31359
32333
|
}
|
|
31360
32334
|
];
|
|
31361
32335
|
var ML_KEM_EK_LEN = {};
|
|
31362
|
-
["id-ml-kem-512", "id-ml-kem-768", "id-ml-kem-1024"].forEach(function(n
|
|
31363
|
-
ML_KEM_EK_LEN[n] =
|
|
32336
|
+
["id-ml-kem-512", "id-ml-kem-768", "id-ml-kem-1024"].forEach(function(n) {
|
|
32337
|
+
ML_KEM_EK_LEN[n] = oid.kemParams(n).ek;
|
|
31364
32338
|
});
|
|
31365
32339
|
function _isMlKem(cert) {
|
|
31366
32340
|
var spki = cert.subjectPublicKeyInfo;
|
|
@@ -31452,6 +32426,573 @@ var require_lint = __commonJS({
|
|
|
31452
32426
|
}
|
|
31453
32427
|
});
|
|
31454
32428
|
|
|
32429
|
+
// node_modules/@blamejs/pki/lib/webauthn-mds.js
|
|
32430
|
+
var require_webauthn_mds = __commonJS({
|
|
32431
|
+
"node_modules/@blamejs/pki/lib/webauthn-mds.js"(exports2, module2) {
|
|
32432
|
+
"use strict";
|
|
32433
|
+
var frameworkError = require_framework_error();
|
|
32434
|
+
var asn1 = require_asn1_der();
|
|
32435
|
+
var x509 = require_schema_x509();
|
|
32436
|
+
var guard = require_guard_all();
|
|
32437
|
+
var jose = require_jose();
|
|
32438
|
+
var rfc3339 = require_rfc3339();
|
|
32439
|
+
var constants = require_constants();
|
|
32440
|
+
var pathValidate = require_path_validate();
|
|
32441
|
+
var webcrypto = require_webcrypto();
|
|
32442
|
+
var nodeCrypto = require("crypto");
|
|
32443
|
+
var WebauthnError = frameworkError.WebauthnError;
|
|
32444
|
+
function _err(code, message, cause) {
|
|
32445
|
+
return new WebauthnError(code, message, cause);
|
|
32446
|
+
}
|
|
32447
|
+
var C = constants.LIMITS;
|
|
32448
|
+
var BLOB_ALGS = Object.assign(/* @__PURE__ */ Object.create(null), {
|
|
32449
|
+
ES256: { family: "EC", hash: "SHA-256", imp: { name: "ECDSA", namedCurve: "P-256" }, ver: { name: "ECDSA", hash: "SHA-256" } },
|
|
32450
|
+
ES384: { family: "EC", hash: "SHA-384", imp: { name: "ECDSA", namedCurve: "P-384" }, ver: { name: "ECDSA", hash: "SHA-384" } },
|
|
32451
|
+
ES512: { family: "EC", hash: "SHA-512", imp: { name: "ECDSA", namedCurve: "P-521" }, ver: { name: "ECDSA", hash: "SHA-512" } },
|
|
32452
|
+
RS256: { family: "RSA", hash: "SHA-256", imp: { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" }, ver: { name: "RSASSA-PKCS1-v1_5" } },
|
|
32453
|
+
RS384: { family: "RSA", hash: "SHA-384", imp: { name: "RSASSA-PKCS1-v1_5", hash: "SHA-384" }, ver: { name: "RSASSA-PKCS1-v1_5" } },
|
|
32454
|
+
RS512: { family: "RSA", hash: "SHA-512", imp: { name: "RSASSA-PKCS1-v1_5", hash: "SHA-512" }, ver: { name: "RSASSA-PKCS1-v1_5" } }
|
|
32455
|
+
});
|
|
32456
|
+
var DISQUALIFYING = Object.assign(/* @__PURE__ */ Object.create(null), {
|
|
32457
|
+
REVOKED: 1,
|
|
32458
|
+
ATTESTATION_KEY_COMPROMISE: 1,
|
|
32459
|
+
USER_KEY_REMOTE_COMPROMISE: 1,
|
|
32460
|
+
USER_KEY_PHYSICAL_COMPROMISE: 1,
|
|
32461
|
+
USER_VERIFICATION_BYPASS: 1
|
|
32462
|
+
});
|
|
32463
|
+
var CERT_SCOPED_STATUS = Object.assign(/* @__PURE__ */ Object.create(null), { ATTESTATION_KEY_COMPROMISE: 1 });
|
|
32464
|
+
var _BLOB_OPTS = Object.assign(/* @__PURE__ */ Object.create(null), {
|
|
32465
|
+
rootCertificates: 1,
|
|
32466
|
+
time: 1,
|
|
32467
|
+
previousNo: 1,
|
|
32468
|
+
requireRollbackCheck: 1,
|
|
32469
|
+
allowStale: 1,
|
|
32470
|
+
statusPolicy: 1,
|
|
32471
|
+
rejectUnknownStatus: 1
|
|
32472
|
+
});
|
|
32473
|
+
function _isPlainObject(v) {
|
|
32474
|
+
return !!v && typeof v === "object" && !Array.isArray(v);
|
|
32475
|
+
}
|
|
32476
|
+
var _verifiedResults = /* @__PURE__ */ new WeakSet();
|
|
32477
|
+
function isVerifiedResult(v) {
|
|
32478
|
+
return _isPlainObject(v) && _verifiedResults.has(v);
|
|
32479
|
+
}
|
|
32480
|
+
function _deepFreeze(v, depth) {
|
|
32481
|
+
if (!v || typeof v !== "object" || Object.isFrozen(v) || ArrayBuffer.isView(v)) return v;
|
|
32482
|
+
if (depth > C.JSON_MAX_DEPTH) return v;
|
|
32483
|
+
Object.freeze(v);
|
|
32484
|
+
Object.keys(v).forEach(function(k) {
|
|
32485
|
+
_deepFreeze(v[k], depth + 1);
|
|
32486
|
+
});
|
|
32487
|
+
return v;
|
|
32488
|
+
}
|
|
32489
|
+
var AAGUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
32490
|
+
var ZERO_AAGUID = "00000000-0000-0000-0000-000000000000";
|
|
32491
|
+
var UNDERSTOOD_HEADER = Object.assign(/* @__PURE__ */ Object.create(null), {
|
|
32492
|
+
alg: 1,
|
|
32493
|
+
typ: 1,
|
|
32494
|
+
cty: 1,
|
|
32495
|
+
crit: 1,
|
|
32496
|
+
jku: 1,
|
|
32497
|
+
jwk: 1,
|
|
32498
|
+
kid: 1,
|
|
32499
|
+
x5u: 1,
|
|
32500
|
+
x5c: 1,
|
|
32501
|
+
x5t: 1,
|
|
32502
|
+
"x5t#S256": 1
|
|
32503
|
+
});
|
|
32504
|
+
function _assertLeafSigns(leaf) {
|
|
32505
|
+
var exts = leaf.extensions || [];
|
|
32506
|
+
for (var i = 0; i < exts.length; i++) {
|
|
32507
|
+
if (exts[i].name !== "keyUsage" || exts[i].value == null) continue;
|
|
32508
|
+
var ku;
|
|
32509
|
+
try {
|
|
32510
|
+
ku = asn1.read.bitString(asn1.decode(exts[i].value));
|
|
32511
|
+
} catch (e) {
|
|
32512
|
+
throw _err("webauthn/bad-att-cert", "the metadata BLOB x5c leaf keyUsage extension is malformed", e);
|
|
32513
|
+
}
|
|
32514
|
+
if (!ku.bytes.length || (ku.bytes[0] & 128) === 0) {
|
|
32515
|
+
throw _err("webauthn/bad-att-cert", "the metadata BLOB x5c leaf keyUsage does not assert digitalSignature, so it may not sign the BLOB (RFC 5280 sec. 4.2.1.3)");
|
|
32516
|
+
}
|
|
32517
|
+
return;
|
|
32518
|
+
}
|
|
32519
|
+
}
|
|
32520
|
+
function _isAnchorItself(cert, anchor) {
|
|
32521
|
+
return guard.name.dnEqual(cert.subject, anchor.subject) && cert.subjectPublicKeyInfo.bytes.equals(anchor.subjectPublicKeyInfo.bytes);
|
|
32522
|
+
}
|
|
32523
|
+
function _asCert(v, label) {
|
|
32524
|
+
if (v && typeof v === "object" && !Buffer.isBuffer(v) && !(v instanceof Uint8Array) && v.subject && v.subjectPublicKeyInfo && Buffer.isBuffer(v.subjectPublicKeyInfo.bytes) && v.signatureAlgorithm && typeof v.signatureAlgorithm.oid === "string" && // `validity` is what separates a certificate from the other signed structures that carry a
|
|
32525
|
+
// subject, a public key and a signature algorithm: a parsed certification request has all
|
|
32526
|
+
// three and would otherwise be installed as a trust anchor.
|
|
32527
|
+
v.validity && v.validity.notBefore !== void 0) {
|
|
32528
|
+
return v;
|
|
32529
|
+
}
|
|
32530
|
+
try {
|
|
32531
|
+
return x509.parse(v);
|
|
32532
|
+
} catch (e) {
|
|
32533
|
+
throw _err("webauthn/bad-input", label + " is not a decodable certificate", e);
|
|
32534
|
+
}
|
|
32535
|
+
}
|
|
32536
|
+
function verifyMetadataBlob(blob, opts) {
|
|
32537
|
+
return Promise.resolve().then(function() {
|
|
32538
|
+
return _verifyMetadataBlob(blob, opts);
|
|
32539
|
+
});
|
|
32540
|
+
}
|
|
32541
|
+
function _verifyMetadataBlob(blob, opts) {
|
|
32542
|
+
opts = opts || {};
|
|
32543
|
+
if (!_isPlainObject(opts)) throw _err("webauthn/bad-input", "opts must be an object");
|
|
32544
|
+
guard.identifier.assertKnownKeys(opts, _BLOB_OPTS, _err, "webauthn/bad-input", "opts has an unknown key ");
|
|
32545
|
+
var roots = opts.rootCertificates;
|
|
32546
|
+
if (!Array.isArray(roots) || roots.length === 0) {
|
|
32547
|
+
throw _err("webauthn/metadata-no-root", "verifying a metadata BLOB requires opts.rootCertificates -- the FIDO root(s) to anchor it to; this library bundles none");
|
|
32548
|
+
}
|
|
32549
|
+
if (opts.time !== void 0) guard.time.assertValid(opts.time, _err, "webauthn/bad-input", "opts.time");
|
|
32550
|
+
var at = opts.time === void 0 ? /* @__PURE__ */ new Date() : opts.time;
|
|
32551
|
+
if (opts.previousNo !== void 0 && (!Number.isSafeInteger(opts.previousNo) || opts.previousNo < 0)) {
|
|
32552
|
+
throw _err("webauthn/bad-input", "opts.previousNo must be a non-negative safe integer");
|
|
32553
|
+
}
|
|
32554
|
+
["requireRollbackCheck", "allowStale", "rejectUnknownStatus"].forEach(function(k) {
|
|
32555
|
+
if (opts[k] !== void 0 && typeof opts[k] !== "boolean") {
|
|
32556
|
+
throw _err("webauthn/bad-input", "opts." + k + " must be a boolean");
|
|
32557
|
+
}
|
|
32558
|
+
});
|
|
32559
|
+
if (opts.statusPolicy !== void 0 && typeof opts.statusPolicy !== "function" && opts.statusPolicy !== "any" && opts.statusPolicy !== "latest-by-date") {
|
|
32560
|
+
throw _err("webauthn/bad-input", 'opts.statusPolicy must be "any", "latest-by-date", or a function');
|
|
32561
|
+
}
|
|
32562
|
+
if (opts.requireRollbackCheck === true && opts.previousNo === void 0) {
|
|
32563
|
+
throw _err("webauthn/metadata-no-baseline", "opts.requireRollbackCheck was set without opts.previousNo, so there is no baseline to compare against");
|
|
32564
|
+
}
|
|
32565
|
+
var anchors = roots.map(function(r, i) {
|
|
32566
|
+
return _asCert(r, "opts.rootCertificates[" + i + "]");
|
|
32567
|
+
});
|
|
32568
|
+
var raw = Buffer.isBuffer(blob) || blob instanceof Uint8Array ? guard.bytes.view(blob, WebauthnError, "webauthn/bad-input", "the metadata BLOB") : null;
|
|
32569
|
+
var declaredLength = raw ? raw.length : typeof blob === "string" ? Buffer.byteLength(blob, "utf8") : null;
|
|
32570
|
+
if (declaredLength !== null && declaredLength > C.MDS_BLOB_MAX_BYTES) {
|
|
32571
|
+
throw _err("webauthn/too-large", "the metadata BLOB is " + declaredLength + " bytes, above the " + C.MDS_BLOB_MAX_BYTES + "-byte ceiling");
|
|
32572
|
+
}
|
|
32573
|
+
if (!raw && typeof blob !== "string") {
|
|
32574
|
+
throw _err("webauthn/bad-input", "the metadata BLOB must be bytes or a string");
|
|
32575
|
+
}
|
|
32576
|
+
var bytes = raw || Buffer.from(blob, "utf8");
|
|
32577
|
+
if (bytes.length > C.MDS_BLOB_MAX_BYTES) {
|
|
32578
|
+
throw _err("webauthn/too-large", "the metadata BLOB is " + bytes.length + " bytes, above the " + C.MDS_BLOB_MAX_BYTES + "-byte ceiling");
|
|
32579
|
+
}
|
|
32580
|
+
var segs = bytes.toString("utf8").split(".");
|
|
32581
|
+
if (segs.length !== 3) throw _err("webauthn/bad-metadata-blob", "the metadata BLOB is not a three-part JWS compact serialization (RFC 7515 sec. 3.1)");
|
|
32582
|
+
if (segs[0].length > Math.ceil(C.MDS_BLOB_HEADER_MAX_BYTES / 3) * 4) {
|
|
32583
|
+
throw _err("webauthn/too-large", "the metadata BLOB protected header is above the " + C.MDS_BLOB_HEADER_MAX_BYTES + "-byte ceiling");
|
|
32584
|
+
}
|
|
32585
|
+
if (segs[2].length > Math.ceil(C.MDS_BLOB_SIG_MAX_BYTES / 3) * 4) {
|
|
32586
|
+
throw _err("webauthn/too-large", "the metadata BLOB signature is above the " + C.MDS_BLOB_SIG_MAX_BYTES + "-byte ceiling");
|
|
32587
|
+
}
|
|
32588
|
+
var header, sig;
|
|
32589
|
+
try {
|
|
32590
|
+
header = guard.json.parse(Buffer.from(jose.base64url.decode(segs[0])), _err, {
|
|
32591
|
+
// The header is read BEFORE anything is authenticated, so its ceiling is the header's own,
|
|
32592
|
+
// not the whole BLOB's: a JWS protected header is a few hundred bytes, and giving this reader
|
|
32593
|
+
// the 32 MiB envelope cap would let unauthenticated bytes buy an unbounded multiple of that
|
|
32594
|
+
// in heap ahead of the signature check. The payload's reader keeps the envelope cap, which is
|
|
32595
|
+
// sound because nothing reaches it until the signature and chain hold.
|
|
32596
|
+
maxBytes: C.MDS_BLOB_HEADER_MAX_BYTES,
|
|
32597
|
+
maxDepth: C.JSON_MAX_DEPTH,
|
|
32598
|
+
tooLarge: "webauthn/too-large",
|
|
32599
|
+
badJson: "webauthn/bad-metadata-blob",
|
|
32600
|
+
// Every code the guard can raise is named. An omitted one falls back to the framework default
|
|
32601
|
+
// and the module's own defences -- duplicate-member smuggling, the depth cap -- surface under
|
|
32602
|
+
// a generic code no webauthn/* consumer can switch on.
|
|
32603
|
+
tooDeep: "webauthn/bad-metadata-blob",
|
|
32604
|
+
duplicateMember: "webauthn/bad-metadata-blob",
|
|
32605
|
+
badInput: "webauthn/bad-metadata-blob",
|
|
32606
|
+
label: "the metadata BLOB header"
|
|
32607
|
+
});
|
|
32608
|
+
sig = Buffer.from(jose.base64url.decode(segs[2]));
|
|
32609
|
+
} catch (e) {
|
|
32610
|
+
if (e instanceof WebauthnError) throw e;
|
|
32611
|
+
throw _err("webauthn/bad-metadata-blob", "the metadata BLOB header or signature is not decodable", e);
|
|
32612
|
+
}
|
|
32613
|
+
if (!_isPlainObject(header)) throw _err("webauthn/bad-metadata-blob", "the metadata BLOB header must be a JSON object");
|
|
32614
|
+
if (header.x5u !== void 0) {
|
|
32615
|
+
throw _err("webauthn/bad-metadata-blob", "the metadata BLOB header carries x5u, which names a chain to fetch; supply a BLOB with an inline x5c instead");
|
|
32616
|
+
}
|
|
32617
|
+
if (Object.prototype.hasOwnProperty.call(header, "crit")) {
|
|
32618
|
+
var crit = header.crit;
|
|
32619
|
+
if (!Array.isArray(crit) || crit.length === 0) {
|
|
32620
|
+
throw _err("webauthn/bad-metadata-blob", "the metadata BLOB header crit must be a non-empty array (RFC 7515 sec. 4.1.11)");
|
|
32621
|
+
}
|
|
32622
|
+
var critSeen = /* @__PURE__ */ Object.create(null);
|
|
32623
|
+
for (var ci = 0; ci < crit.length; ci++) {
|
|
32624
|
+
var critName = crit[ci];
|
|
32625
|
+
if (typeof critName !== "string") throw _err("webauthn/bad-metadata-blob", "the metadata BLOB header crit entries must be strings");
|
|
32626
|
+
if (critSeen[critName]) throw _err("webauthn/bad-metadata-blob", "the metadata BLOB header crit repeats " + JSON.stringify(critName));
|
|
32627
|
+
critSeen[critName] = 1;
|
|
32628
|
+
if (UNDERSTOOD_HEADER[critName]) {
|
|
32629
|
+
throw _err("webauthn/bad-metadata-blob", "the metadata BLOB header crit must not name the standard header parameter " + JSON.stringify(critName) + " (RFC 7515 sec. 4.1.11)");
|
|
32630
|
+
}
|
|
32631
|
+
throw _err("webauthn/bad-metadata-blob", "the metadata BLOB header names critical header parameter " + JSON.stringify(critName) + ", which this reader does not process");
|
|
32632
|
+
}
|
|
32633
|
+
}
|
|
32634
|
+
var algRow = typeof header.alg === "string" ? BLOB_ALGS[header.alg] : void 0;
|
|
32635
|
+
if (!algRow) throw _err("webauthn/unsupported-algorithm", "the metadata BLOB alg " + JSON.stringify(header.alg) + " is not a supported JWS signature algorithm");
|
|
32636
|
+
if (!Array.isArray(header.x5c) || header.x5c.length === 0) {
|
|
32637
|
+
throw _err("webauthn/bad-metadata-blob", "the metadata BLOB header carries no x5c certificate chain (RFC 7515 sec. 4.1.6)");
|
|
32638
|
+
}
|
|
32639
|
+
if (header.x5c.length > C.WEBAUTHN_X5C_MAX_CERTS) {
|
|
32640
|
+
throw _err("webauthn/too-large", "the metadata BLOB x5c carries " + header.x5c.length + " certificates, above the " + C.WEBAUTHN_X5C_MAX_CERTS + " this library will parse");
|
|
32641
|
+
}
|
|
32642
|
+
var chain = header.x5c.map(function(entry, i) {
|
|
32643
|
+
if (typeof entry !== "string") throw _err("webauthn/bad-metadata-blob", "the metadata BLOB x5c entry " + i + " is not a string");
|
|
32644
|
+
var der;
|
|
32645
|
+
try {
|
|
32646
|
+
der = guard.encoding.base64(entry, C.MDS_BLOB_MAX_BYTES, _err, "webauthn/bad-metadata-blob", "a metadata BLOB x5c entry");
|
|
32647
|
+
} catch (e) {
|
|
32648
|
+
throw _err("webauthn/bad-metadata-blob", "the metadata BLOB x5c entry " + i + " is not canonical base64", e);
|
|
32649
|
+
}
|
|
32650
|
+
try {
|
|
32651
|
+
return x509.parse(der);
|
|
32652
|
+
} catch (e) {
|
|
32653
|
+
throw _err("webauthn/bad-att-cert", "the metadata BLOB x5c entry " + i + " is not a decodable certificate", e);
|
|
32654
|
+
}
|
|
32655
|
+
});
|
|
32656
|
+
var leaf = chain[0];
|
|
32657
|
+
_assertLeafSigns(leaf);
|
|
32658
|
+
var leafAlg = (leaf.subjectPublicKeyInfo.algorithm || {}).name;
|
|
32659
|
+
var leafFamily = leafAlg === "ecPublicKey" ? "EC" : leafAlg === "rsaEncryption" ? "RSA" : null;
|
|
32660
|
+
if (leafFamily !== algRow.family) {
|
|
32661
|
+
throw _err("webauthn/unsupported-algorithm", "the metadata BLOB alg " + header.alg + " does not match the x5c leaf key type " + JSON.stringify(leafAlg));
|
|
32662
|
+
}
|
|
32663
|
+
var signingInput = Buffer.from(segs[0] + "." + segs[1], "ascii");
|
|
32664
|
+
return webcrypto.webcrypto.subtle.importKey("spki", leaf.subjectPublicKeyInfo.bytes, algRow.imp, false, ["verify"]).then(
|
|
32665
|
+
function(key) {
|
|
32666
|
+
return webcrypto.webcrypto.subtle.verify(algRow.ver, key, sig, signingInput);
|
|
32667
|
+
},
|
|
32668
|
+
function(e) {
|
|
32669
|
+
throw _err("webauthn/unsupported-algorithm", "the metadata BLOB x5c leaf key could not be imported for " + header.alg, e);
|
|
32670
|
+
}
|
|
32671
|
+
).then(function(ok) {
|
|
32672
|
+
if (!ok) throw _err("webauthn/verify-failed", "the metadata BLOB signature does not verify under its x5c leaf key");
|
|
32673
|
+
return _chainToAnchor(chain, anchors, at);
|
|
32674
|
+
}).then(function() {
|
|
32675
|
+
return _parsePayload(segs[1], at, opts);
|
|
32676
|
+
});
|
|
32677
|
+
}
|
|
32678
|
+
function _chainToAnchor(chain, anchors, at, what) {
|
|
32679
|
+
var subject = what || "metadata BLOB certificate chain";
|
|
32680
|
+
var ordered = chain.slice().reverse();
|
|
32681
|
+
var lastFault = null;
|
|
32682
|
+
return anchors.reduce(function(p, anchor) {
|
|
32683
|
+
return p.then(function(done) {
|
|
32684
|
+
if (done) return true;
|
|
32685
|
+
var path = ordered.slice();
|
|
32686
|
+
var strippedAnchor = false;
|
|
32687
|
+
if (path.length && _isAnchorItself(path[0], anchor)) {
|
|
32688
|
+
path = path.slice(1);
|
|
32689
|
+
strippedAnchor = true;
|
|
32690
|
+
}
|
|
32691
|
+
if (path.length === 0) return strippedAnchor;
|
|
32692
|
+
return pathValidate.validate(path, {
|
|
32693
|
+
time: at,
|
|
32694
|
+
// The anchor tuple names the anchor's own KEY -- its SubjectPublicKeyInfo algorithm and that
|
|
32695
|
+
// algorithm's parameters -- not the algorithm its issuer used to sign it. The validator
|
|
32696
|
+
// carries these forward as the working public key, and a certificate below the anchor may
|
|
32697
|
+
// inherit its key parameters from them (the DSA-style parameter-inheritance case), so
|
|
32698
|
+
// supplying the signature OID leaves such a key unreconstructable and refuses a valid chain.
|
|
32699
|
+
trustAnchor: {
|
|
32700
|
+
name: anchor.subject,
|
|
32701
|
+
publicKey: anchor.subjectPublicKeyInfo.bytes,
|
|
32702
|
+
algorithm: anchor.subjectPublicKeyInfo.algorithm.oid,
|
|
32703
|
+
parameters: anchor.subjectPublicKeyInfo.algorithm.parameters
|
|
32704
|
+
}
|
|
32705
|
+
}).then(function(r) {
|
|
32706
|
+
return !!(r && r.valid);
|
|
32707
|
+
}, function(e) {
|
|
32708
|
+
lastFault = e;
|
|
32709
|
+
return false;
|
|
32710
|
+
});
|
|
32711
|
+
});
|
|
32712
|
+
}, Promise.resolve(false)).then(function(trusted) {
|
|
32713
|
+
if (!trusted) {
|
|
32714
|
+
throw _err("webauthn/metadata-untrusted", "the " + subject + " does not validate to any of the roots it must reach", lastFault);
|
|
32715
|
+
}
|
|
32716
|
+
});
|
|
32717
|
+
}
|
|
32718
|
+
function _staleAfter(nextUpdate) {
|
|
32719
|
+
var d = rfc3339.parseDate(
|
|
32720
|
+
nextUpdate,
|
|
32721
|
+
function(c, m) {
|
|
32722
|
+
return _err("webauthn/bad-metadata-blob", m);
|
|
32723
|
+
},
|
|
32724
|
+
"webauthn/bad-metadata-blob",
|
|
32725
|
+
"the metadata BLOB nextUpdate"
|
|
32726
|
+
);
|
|
32727
|
+
return d.getTime() + constants.TIME.days(1);
|
|
32728
|
+
}
|
|
32729
|
+
function assertFresh(metadata, at, label) {
|
|
32730
|
+
if (!metadata || metadata.allowStale === true || typeof metadata.nextUpdate !== "string") return;
|
|
32731
|
+
var atMs = at instanceof Date ? at.getTime() : NaN;
|
|
32732
|
+
var limit = _staleAfter(metadata.nextUpdate);
|
|
32733
|
+
if (!isFinite(atMs) || !isFinite(limit)) return;
|
|
32734
|
+
if (atMs >= limit) {
|
|
32735
|
+
throw _err("webauthn/metadata-stale", (label || "the metadata") + " expired after " + metadata.nextUpdate + "; re-verify a current BLOB, or pass opts.allowStale when verifying it");
|
|
32736
|
+
}
|
|
32737
|
+
}
|
|
32738
|
+
function _parsePayload(seg, at, opts) {
|
|
32739
|
+
var payload;
|
|
32740
|
+
try {
|
|
32741
|
+
payload = guard.json.parse(Buffer.from(jose.base64url.decode(seg)), _err, {
|
|
32742
|
+
maxBytes: C.MDS_BLOB_MAX_BYTES,
|
|
32743
|
+
maxDepth: C.JSON_MAX_DEPTH,
|
|
32744
|
+
tooLarge: "webauthn/too-large",
|
|
32745
|
+
badJson: "webauthn/bad-metadata-blob",
|
|
32746
|
+
tooDeep: "webauthn/bad-metadata-blob",
|
|
32747
|
+
duplicateMember: "webauthn/bad-metadata-blob",
|
|
32748
|
+
badInput: "webauthn/bad-metadata-blob",
|
|
32749
|
+
label: "the metadata BLOB payload"
|
|
32750
|
+
});
|
|
32751
|
+
} catch (e) {
|
|
32752
|
+
if (e instanceof WebauthnError) throw e;
|
|
32753
|
+
throw _err("webauthn/bad-metadata-blob", "the metadata BLOB payload is not decodable JSON", e);
|
|
32754
|
+
}
|
|
32755
|
+
if (!_isPlainObject(payload)) throw _err("webauthn/bad-metadata-blob", "the metadata BLOB payload must be a JSON object");
|
|
32756
|
+
if (typeof payload.legalHeader !== "string") throw _err("webauthn/bad-metadata-blob", "the metadata BLOB payload must carry a string legalHeader");
|
|
32757
|
+
if (!Number.isSafeInteger(payload.no) || payload.no < 0) throw _err("webauthn/bad-metadata-blob", "the metadata BLOB payload must carry a non-negative integer no");
|
|
32758
|
+
if (opts.previousNo !== void 0 && payload.no <= opts.previousNo) {
|
|
32759
|
+
throw _err("webauthn/metadata-rollback", "the metadata BLOB no " + payload.no + " does not exceed the previously held " + opts.previousNo);
|
|
32760
|
+
}
|
|
32761
|
+
var staleAfter = _staleAfter(payload.nextUpdate);
|
|
32762
|
+
var atMs = at.getTime();
|
|
32763
|
+
if (!isFinite(atMs) || !isFinite(staleAfter)) {
|
|
32764
|
+
throw _err("webauthn/bad-input", "the metadata freshness comparison has no usable instant");
|
|
32765
|
+
}
|
|
32766
|
+
var stale = atMs >= staleAfter;
|
|
32767
|
+
if (stale && opts.allowStale !== true) {
|
|
32768
|
+
throw _err("webauthn/metadata-stale", "the metadata BLOB expired after " + payload.nextUpdate + "; pass opts.allowStale to accept it anyway");
|
|
32769
|
+
}
|
|
32770
|
+
if (!Array.isArray(payload.entries)) throw _err("webauthn/bad-metadata-blob", "the metadata BLOB payload must carry an entries array");
|
|
32771
|
+
if (payload.entries.length > C.MDS_MAX_ENTRIES) {
|
|
32772
|
+
throw _err("webauthn/too-large", "the metadata BLOB declares " + payload.entries.length + " entries, above the " + C.MDS_MAX_ENTRIES + " ceiling");
|
|
32773
|
+
}
|
|
32774
|
+
var byAaguid = /* @__PURE__ */ Object.create(null);
|
|
32775
|
+
var byKeyIdentifier = /* @__PURE__ */ Object.create(null);
|
|
32776
|
+
var entries = payload.entries.map(function(e, i) {
|
|
32777
|
+
if (!_isPlainObject(e)) throw _err("webauthn/bad-metadata-blob", "metadata entry " + i + " is not an object");
|
|
32778
|
+
if (!Array.isArray(e.statusReports) || e.statusReports.length === 0) {
|
|
32779
|
+
throw _err("webauthn/bad-metadata-blob", "metadata entry " + i + " must carry a non-empty statusReports array");
|
|
32780
|
+
}
|
|
32781
|
+
if (e.statusReports.length > C.MDS_MAX_STATUS_REPORTS_PER_ENTRY) {
|
|
32782
|
+
throw _err("webauthn/too-large", "metadata entry " + i + " declares " + e.statusReports.length + " status reports, above the " + C.MDS_MAX_STATUS_REPORTS_PER_ENTRY + " ceiling");
|
|
32783
|
+
}
|
|
32784
|
+
e.statusReports.forEach(function(r, ri) {
|
|
32785
|
+
if (!_isPlainObject(r)) throw _err("webauthn/bad-metadata-blob", "metadata entry " + i + " status report " + ri + " is not an object");
|
|
32786
|
+
if (typeof r.status !== "string" || !r.status) {
|
|
32787
|
+
throw _err("webauthn/bad-metadata-blob", "metadata entry " + i + " status report " + ri + " has no status (MDS v3.0 sec. 3.1.3 requires one)");
|
|
32788
|
+
}
|
|
32789
|
+
});
|
|
32790
|
+
var aaguid = null;
|
|
32791
|
+
if (e.aaguid !== void 0) {
|
|
32792
|
+
if (typeof e.aaguid !== "string" || !AAGUID_RE.test(e.aaguid.toLowerCase())) {
|
|
32793
|
+
throw _err("webauthn/bad-metadata-blob", "metadata entry " + i + " has a malformed aaguid");
|
|
32794
|
+
}
|
|
32795
|
+
aaguid = e.aaguid.toLowerCase();
|
|
32796
|
+
}
|
|
32797
|
+
var st = e.metadataStatement;
|
|
32798
|
+
var keyIds = [];
|
|
32799
|
+
var seenKeyId = /* @__PURE__ */ Object.create(null);
|
|
32800
|
+
[[e.attestationCertificateKeyIdentifiers, "entry"], [st && st.attestationCertificateKeyIdentifiers, "metadataStatement"]].forEach(function(pair) {
|
|
32801
|
+
var list = pair[0];
|
|
32802
|
+
if (list === void 0) return;
|
|
32803
|
+
if (!Array.isArray(list)) {
|
|
32804
|
+
throw _err("webauthn/bad-metadata-blob", "metadata entry " + i + " " + pair[1] + " attestationCertificateKeyIdentifiers is not an array");
|
|
32805
|
+
}
|
|
32806
|
+
if (list.length > C.MDS_MAX_KEY_IDS_PER_ENTRY) {
|
|
32807
|
+
throw _err("webauthn/too-large", "metadata entry " + i + " declares " + list.length + " attestation certificate key identifiers, above the " + C.MDS_MAX_KEY_IDS_PER_ENTRY + " ceiling");
|
|
32808
|
+
}
|
|
32809
|
+
list.forEach(function(k) {
|
|
32810
|
+
if (typeof k !== "string" || !/^[0-9a-fA-F]{40}$/.test(k)) {
|
|
32811
|
+
throw _err("webauthn/bad-metadata-blob", "metadata entry " + i + " has a malformed attestation certificate key identifier");
|
|
32812
|
+
}
|
|
32813
|
+
var lower = k.toLowerCase();
|
|
32814
|
+
if (!seenKeyId[lower]) {
|
|
32815
|
+
seenKeyId[lower] = 1;
|
|
32816
|
+
keyIds.push(lower);
|
|
32817
|
+
}
|
|
32818
|
+
});
|
|
32819
|
+
});
|
|
32820
|
+
var out = {
|
|
32821
|
+
index: i,
|
|
32822
|
+
aaguid,
|
|
32823
|
+
keyIdentifiers: keyIds,
|
|
32824
|
+
statusReports: e.statusReports,
|
|
32825
|
+
metadataStatement: st || null,
|
|
32826
|
+
timeOfLastStatusChange: e.timeOfLastStatusChange || null
|
|
32827
|
+
};
|
|
32828
|
+
if (aaguid) {
|
|
32829
|
+
if (byAaguid[aaguid]) throw _err("webauthn/duplicate-metadata-entry", "two metadata entries claim aaguid " + aaguid);
|
|
32830
|
+
byAaguid[aaguid] = out;
|
|
32831
|
+
}
|
|
32832
|
+
keyIds.forEach(function(k) {
|
|
32833
|
+
if (byKeyIdentifier[k]) throw _err("webauthn/duplicate-metadata-entry", "two metadata entries claim attestation certificate key identifier " + k);
|
|
32834
|
+
byKeyIdentifier[k] = out;
|
|
32835
|
+
});
|
|
32836
|
+
return out;
|
|
32837
|
+
});
|
|
32838
|
+
var result = {
|
|
32839
|
+
no: payload.no,
|
|
32840
|
+
legalHeader: payload.legalHeader,
|
|
32841
|
+
nextUpdate: payload.nextUpdate,
|
|
32842
|
+
stale,
|
|
32843
|
+
allowStale: opts.allowStale === true,
|
|
32844
|
+
entries,
|
|
32845
|
+
byAaguid,
|
|
32846
|
+
byKeyIdentifier,
|
|
32847
|
+
statusPolicy: opts.statusPolicy || "any",
|
|
32848
|
+
rejectUnknownStatus: opts.rejectUnknownStatus === true
|
|
32849
|
+
};
|
|
32850
|
+
_deepFreeze(result, 0);
|
|
32851
|
+
_verifiedResults.add(result);
|
|
32852
|
+
return result;
|
|
32853
|
+
}
|
|
32854
|
+
function metadataFor(metadata, identifier) {
|
|
32855
|
+
if (!isVerifiedResult(metadata)) throw _err("webauthn/bad-input", "metadataFor expects a verifyMetadataBlob result -- an object that merely resembles one, such as a catalogue restored from a cache, has not been through the signature and chain checks");
|
|
32856
|
+
if (typeof identifier !== "string") return null;
|
|
32857
|
+
var key = identifier.toLowerCase();
|
|
32858
|
+
if (AAGUID_RE.test(key)) {
|
|
32859
|
+
if (key === ZERO_AAGUID) return null;
|
|
32860
|
+
return metadata.byAaguid[key] || null;
|
|
32861
|
+
}
|
|
32862
|
+
if (/^[0-9a-f]{40}$/.test(key)) return metadataForKeyIdentifier(metadata, key);
|
|
32863
|
+
return null;
|
|
32864
|
+
}
|
|
32865
|
+
function metadataAnchors(entry) {
|
|
32866
|
+
if (!entry || typeof entry !== "object") throw _err("webauthn/bad-input", "metadataAnchors expects a metadata entry");
|
|
32867
|
+
var st = entry.metadataStatement;
|
|
32868
|
+
var list = st && Array.isArray(st.attestationRootCertificates) ? st.attestationRootCertificates : [];
|
|
32869
|
+
if (list.length > C.MDS_MAX_ANCHORS_PER_ENTRY) {
|
|
32870
|
+
throw _err("webauthn/too-large", "metadata entry " + entry.index + " declares " + list.length + " attestation roots, above the " + C.MDS_MAX_ANCHORS_PER_ENTRY + " ceiling");
|
|
32871
|
+
}
|
|
32872
|
+
return list.map(function(b64, i) {
|
|
32873
|
+
var der;
|
|
32874
|
+
try {
|
|
32875
|
+
der = guard.encoding.base64(b64, C.MDS_BLOB_MAX_BYTES, _err, "webauthn/bad-metadata-entry", "an attestation root certificate");
|
|
32876
|
+
} catch (e) {
|
|
32877
|
+
throw _err("webauthn/bad-metadata-entry", "metadata entry " + entry.index + " attestation root " + i + " is not canonical base64", e);
|
|
32878
|
+
}
|
|
32879
|
+
try {
|
|
32880
|
+
return x509.parse(der);
|
|
32881
|
+
} catch (e) {
|
|
32882
|
+
throw _err("webauthn/bad-metadata-entry", "metadata entry " + entry.index + " attestation root " + i + " is not a decodable certificate", e);
|
|
32883
|
+
}
|
|
32884
|
+
});
|
|
32885
|
+
}
|
|
32886
|
+
function _reportNamesOtherCert(report, leaf) {
|
|
32887
|
+
if (typeof report.certificate !== "string" || !report.certificate) return false;
|
|
32888
|
+
if (!leaf) return false;
|
|
32889
|
+
var named;
|
|
32890
|
+
try {
|
|
32891
|
+
named = x509.parse(guard.encoding.base64(report.certificate, C.MDS_BLOB_MAX_BYTES, _err, "webauthn/bad-metadata-entry", "a status report certificate"));
|
|
32892
|
+
} catch (_e) {
|
|
32893
|
+
return false;
|
|
32894
|
+
}
|
|
32895
|
+
try {
|
|
32896
|
+
return certKeyIdentifier(named) !== certKeyIdentifier(leaf);
|
|
32897
|
+
} catch (_e) {
|
|
32898
|
+
return false;
|
|
32899
|
+
}
|
|
32900
|
+
}
|
|
32901
|
+
function _reportInForceAt(report, atMs) {
|
|
32902
|
+
var d = rfc3339.parseDate(
|
|
32903
|
+
report.effectiveDate,
|
|
32904
|
+
function(c, m) {
|
|
32905
|
+
return _err("webauthn/bad-metadata-blob", m);
|
|
32906
|
+
},
|
|
32907
|
+
"webauthn/bad-metadata-blob",
|
|
32908
|
+
"a status report effectiveDate"
|
|
32909
|
+
);
|
|
32910
|
+
return d.getTime() <= atMs;
|
|
32911
|
+
}
|
|
32912
|
+
function statusDenied(entry, metadata, leaf, at) {
|
|
32913
|
+
var policy = metadata && metadata.statusPolicy || "any";
|
|
32914
|
+
var reports = entry.statusReports || [];
|
|
32915
|
+
if (typeof policy === "function") return policy(reports) === true;
|
|
32916
|
+
reports = reports.filter(function(r) {
|
|
32917
|
+
return !(r && typeof r.status === "string" && CERT_SCOPED_STATUS[r.status] && _reportNamesOtherCert(r, leaf));
|
|
32918
|
+
});
|
|
32919
|
+
var isDated = function(r) {
|
|
32920
|
+
return r && typeof r.effectiveDate === "string" && rfc3339.isValidDate(r.effectiveDate);
|
|
32921
|
+
};
|
|
32922
|
+
var atMs = at instanceof Date && isFinite(at.getTime()) ? at.getTime() : null;
|
|
32923
|
+
if (atMs !== null) {
|
|
32924
|
+
reports = reports.filter(function(r) {
|
|
32925
|
+
return !isDated(r) || _reportInForceAt(r, atMs);
|
|
32926
|
+
});
|
|
32927
|
+
}
|
|
32928
|
+
var considered = reports;
|
|
32929
|
+
if (policy === "latest-by-date") {
|
|
32930
|
+
var dated = reports.filter(isDated);
|
|
32931
|
+
if (dated.length) {
|
|
32932
|
+
var newest = dated.reduce(function(a, b) {
|
|
32933
|
+
return a.effectiveDate >= b.effectiveDate ? a : b;
|
|
32934
|
+
}).effectiveDate;
|
|
32935
|
+
considered = dated.filter(function(r) {
|
|
32936
|
+
return r.effectiveDate === newest;
|
|
32937
|
+
}).concat(reports.filter(function(r) {
|
|
32938
|
+
return !isDated(r);
|
|
32939
|
+
}));
|
|
32940
|
+
}
|
|
32941
|
+
}
|
|
32942
|
+
var rejectUnknown = !!(metadata && metadata.rejectUnknownStatus);
|
|
32943
|
+
return considered.some(function(r) {
|
|
32944
|
+
var s = r && typeof r.status === "string" ? r.status : null;
|
|
32945
|
+
if (s === null) return false;
|
|
32946
|
+
if (DISQUALIFYING[s]) return true;
|
|
32947
|
+
return rejectUnknown && !_KNOWN_STATUS[s];
|
|
32948
|
+
});
|
|
32949
|
+
}
|
|
32950
|
+
var _KNOWN_STATUS = Object.assign(/* @__PURE__ */ Object.create(null), {
|
|
32951
|
+
NOT_FIDO_CERTIFIED: 1,
|
|
32952
|
+
SELF_ASSERTION_SUBMITTED: 1,
|
|
32953
|
+
FIDO_CERTIFIED: 1,
|
|
32954
|
+
FIDO_CERTIFIED_L1: 1,
|
|
32955
|
+
FIDO_CERTIFIED_L1plus: 1,
|
|
32956
|
+
FIDO_CERTIFIED_L2: 1,
|
|
32957
|
+
FIDO_CERTIFIED_L2plus: 1,
|
|
32958
|
+
FIDO_CERTIFIED_L3: 1,
|
|
32959
|
+
FIDO_CERTIFIED_L3plus: 1,
|
|
32960
|
+
UPDATE_AVAILABLE: 1
|
|
32961
|
+
});
|
|
32962
|
+
function aaguidToString(buf) {
|
|
32963
|
+
if (!Buffer.isBuffer(buf) || buf.length !== 16) return null;
|
|
32964
|
+
var h = buf.toString("hex");
|
|
32965
|
+
return h.slice(0, 8) + "-" + h.slice(8, 12) + "-" + h.slice(12, 16) + "-" + h.slice(16, 20) + "-" + h.slice(20);
|
|
32966
|
+
}
|
|
32967
|
+
function certKeyIdentifier(cert) {
|
|
32968
|
+
var pk = cert && cert.subjectPublicKeyInfo && cert.subjectPublicKeyInfo.publicKey;
|
|
32969
|
+
if (!pk || !Buffer.isBuffer(pk.bytes)) {
|
|
32970
|
+
throw _err("webauthn/bad-input", "certKeyIdentifier expects a parsed certificate carrying a subject public key");
|
|
32971
|
+
}
|
|
32972
|
+
return nodeCrypto.createHash("sha1").update(pk.bytes).digest("hex");
|
|
32973
|
+
}
|
|
32974
|
+
function metadataForKeyIdentifier(metadata, keyId) {
|
|
32975
|
+
if (!isVerifiedResult(metadata)) throw _err("webauthn/bad-input", "metadataForKeyIdentifier expects a verifyMetadataBlob result -- an object that merely resembles one has not been through the signature and chain checks");
|
|
32976
|
+
if (typeof keyId !== "string") return null;
|
|
32977
|
+
return metadata.byKeyIdentifier[keyId.toLowerCase()] || null;
|
|
32978
|
+
}
|
|
32979
|
+
module2.exports = {
|
|
32980
|
+
verifyMetadataBlob,
|
|
32981
|
+
metadataFor,
|
|
32982
|
+
metadataForKeyIdentifier,
|
|
32983
|
+
metadataAnchors,
|
|
32984
|
+
chainToAnchor: _chainToAnchor,
|
|
32985
|
+
assertFresh,
|
|
32986
|
+
isVerifiedResult,
|
|
32987
|
+
statusDenied,
|
|
32988
|
+
aaguidToString,
|
|
32989
|
+
ZERO_AAGUID,
|
|
32990
|
+
certKeyIdentifier,
|
|
32991
|
+
DISQUALIFYING
|
|
32992
|
+
};
|
|
32993
|
+
}
|
|
32994
|
+
});
|
|
32995
|
+
|
|
31455
32996
|
// node_modules/@blamejs/pki/lib/webauthn.js
|
|
31456
32997
|
var require_webauthn = __commonJS({
|
|
31457
32998
|
"node_modules/@blamejs/pki/lib/webauthn.js"(exports2, module2) {
|
|
@@ -31466,6 +33007,10 @@ var require_webauthn = __commonJS({
|
|
|
31466
33007
|
var constants = require_constants();
|
|
31467
33008
|
var validator = require_validator_all();
|
|
31468
33009
|
var edwardsPoint = require_edwards_point();
|
|
33010
|
+
var guard = require_guard_all();
|
|
33011
|
+
var jose = require_jose();
|
|
33012
|
+
var pathValidate = require_path_validate();
|
|
33013
|
+
var mds = require_webauthn_mds();
|
|
31469
33014
|
var nodeCrypto = require("crypto");
|
|
31470
33015
|
var WebauthnError = frameworkError.WebauthnError;
|
|
31471
33016
|
function _err(code, message, cause) {
|
|
@@ -31696,7 +33241,11 @@ var require_webauthn = __commonJS({
|
|
|
31696
33241
|
var fmtN = cbor.read.mapGet(root, "fmt"), attStmtN = cbor.read.mapGet(root, "attStmt"), authDataN = cbor.read.mapGet(root, "authData");
|
|
31697
33242
|
if (root.children.length !== 3 || !fmtN || !attStmtN || !authDataN) throw _err("webauthn/bad-attestation-object", "the attestation object must be exactly { fmt, attStmt, authData }");
|
|
31698
33243
|
if (fmtN.majorType !== 3) throw _err("webauthn/bad-attestation-object", "attestation object 'fmt' must be a text string");
|
|
31699
|
-
|
|
33244
|
+
var wantMajor = ATT_STMT_MAJOR[cbor.read.textString(fmtN)];
|
|
33245
|
+
if (wantMajor === void 0) wantMajor = 5;
|
|
33246
|
+
if (attStmtN.majorType !== wantMajor) {
|
|
33247
|
+
throw _err("webauthn/bad-attestation-object", "attestation object 'attStmt' must be a CBOR " + (wantMajor === 4 ? "array" : "map") + " for format " + JSON.stringify(cbor.read.textString(fmtN)));
|
|
33248
|
+
}
|
|
31700
33249
|
if (authDataN.majorType !== 2) throw _err("webauthn/bad-attestation-object", "attestation object 'authData' must be a byte string");
|
|
31701
33250
|
var authDataBytes = cbor.read.byteString(authDataN);
|
|
31702
33251
|
return {
|
|
@@ -31738,9 +33287,28 @@ var require_webauthn = __commonJS({
|
|
|
31738
33287
|
if (!have[k]) throw _err("webauthn/bad-att-stmt", "the attestation statement is missing the '" + k + "' field");
|
|
31739
33288
|
});
|
|
31740
33289
|
}
|
|
33290
|
+
var ATT_STMT_MAJOR = { compound: 4 };
|
|
33291
|
+
var _AAGUID_SIGNED_BY_FMT = Object.assign(/* @__PURE__ */ Object.create(null), { "fido-u2f": false });
|
|
33292
|
+
function _aaguidIsSigned(fmt) {
|
|
33293
|
+
return _AAGUID_SIGNED_BY_FMT[fmt] !== false;
|
|
33294
|
+
}
|
|
33295
|
+
var _VERIFY_OPTS = Object.assign(/* @__PURE__ */ Object.create(null), {
|
|
33296
|
+
time: 1,
|
|
33297
|
+
metadata: 1,
|
|
33298
|
+
tpmPolicy: 1,
|
|
33299
|
+
safetyNetRoots: 1,
|
|
33300
|
+
verifySafetyNetJws: 1,
|
|
33301
|
+
requireCtsProfileMatch: 1
|
|
33302
|
+
});
|
|
33303
|
+
function _requireX5cCount(n) {
|
|
33304
|
+
if (n > constants.LIMITS.WEBAUTHN_X5C_MAX_CERTS) {
|
|
33305
|
+
throw _err("webauthn/bad-att-stmt", "an attestation certificate chain carries " + n + " certificates, above the " + constants.LIMITS.WEBAUTHN_X5C_MAX_CERTS + " this toolkit will parse");
|
|
33306
|
+
}
|
|
33307
|
+
}
|
|
31741
33308
|
function _readX5c(attStmt) {
|
|
31742
33309
|
var x5cN = cbor.read.mapGet(attStmt, "x5c");
|
|
31743
33310
|
if (!x5cN || x5cN.majorType !== 4 || !x5cN.children || !x5cN.children.length) throw _err("webauthn/bad-att-stmt", "x5c must be a non-empty array of certificates");
|
|
33311
|
+
_requireX5cCount(x5cN.children.length);
|
|
31744
33312
|
return x5cN.children.map(function(c) {
|
|
31745
33313
|
var der;
|
|
31746
33314
|
try {
|
|
@@ -31841,7 +33409,8 @@ var require_webauthn = __commonJS({
|
|
|
31841
33409
|
},
|
|
31842
33410
|
// tpm (WebAuthn 8.3): decode certInfo/pubArea, enforce magic/type/extraData/Name,
|
|
31843
33411
|
// bind pubArea to the credential key, and verify sig over certInfo with the AIK.
|
|
31844
|
-
tpm: function(att, clientDataHash) {
|
|
33412
|
+
tpm: function(att, clientDataHash, opts) {
|
|
33413
|
+
var tpmPolicy = validator.tpm.normalizeObjectAttributePolicy((opts || {}).tpmPolicy, WebauthnError, "webauthn/bad-input");
|
|
31845
33414
|
_requireAttShape(att.attStmt, ["ver", "alg", "sig", "certInfo", "pubArea", "x5c"], ["ver", "alg", "sig", "certInfo", "pubArea", "x5c"]);
|
|
31846
33415
|
var verN = cbor.read.mapGet(att.attStmt, "ver");
|
|
31847
33416
|
if (!verN || verN.majorType !== 3 || cbor.read.textString(verN) !== "2.0") throw _err("webauthn/bad-att-stmt", `tpm attestation 'ver' MUST be "2.0" (WebAuthn 8.3)`);
|
|
@@ -31862,7 +33431,150 @@ var require_webauthn = __commonJS({
|
|
|
31862
33431
|
if (!ok) throw _err("webauthn/verify-failed", "the tpm attestation signature does not verify over certInfo under the AIK");
|
|
31863
33432
|
_checkAikCert(aik);
|
|
31864
33433
|
_checkAaguidExt(aik, att.authData.aaguid);
|
|
31865
|
-
|
|
33434
|
+
validator.tpm.assertObjectAttributePolicy(pub, tpmPolicy, WebauthnError, "webauthn/tpm-policy", "webauthn/bad-tpm");
|
|
33435
|
+
var tpmRes = _result("tpm", "AttCA", chain, att);
|
|
33436
|
+
tpmRes.tpm = { objectAttributes: pub.objectAttributes, attributes: pub.attributes, authPolicy: pub.authPolicy };
|
|
33437
|
+
return tpmRes;
|
|
33438
|
+
});
|
|
33439
|
+
},
|
|
33440
|
+
// android-safetynet (WebAuthn 8.5): the attStmt carries a SafetyNet JWS ("response") whose payload
|
|
33441
|
+
// binds a nonce to this registration and whose x5c header chains to a Google root.
|
|
33442
|
+
//
|
|
33443
|
+
// OFF BY DEFAULT, and anchored only by the caller. Google retired the SafetyNet Attestation API, so
|
|
33444
|
+
// nothing mints these any more -- the surviving use is a relying party re-checking attestations it
|
|
33445
|
+
// stored years ago. Enabling a format whose producer is gone, against a root this library chose,
|
|
33446
|
+
// would widen what every caller trusts for no live benefit; so the caller opts in AND supplies the
|
|
33447
|
+
// root. With the opt off the verdict is byte-identical to the one this format had before the arm
|
|
33448
|
+
// existed. There is no bundled root and no trust-on-first-use.
|
|
33449
|
+
"android-safetynet": function(att, clientDataHash, opts) {
|
|
33450
|
+
opts = opts || {};
|
|
33451
|
+
if (opts.verifySafetyNetJws !== true) {
|
|
33452
|
+
if (opts.verifySafetyNetJws !== void 0 && typeof opts.verifySafetyNetJws !== "boolean") {
|
|
33453
|
+
throw _err("webauthn/bad-input", "opts.verifySafetyNetJws must be a boolean");
|
|
33454
|
+
}
|
|
33455
|
+
throw _err("webauthn/unsupported-format", "attestation statement format 'android-safetynet' is not supported");
|
|
33456
|
+
}
|
|
33457
|
+
var roots = opts.safetyNetRoots;
|
|
33458
|
+
if (!Array.isArray(roots) || roots.length === 0) {
|
|
33459
|
+
throw _err("webauthn/safetynet-no-root", "verifying an android-safetynet attestation requires opts.safetyNetRoots -- the Google root(s) to anchor the x5c chain to; this library bundles none (WebAuthn 8.5)");
|
|
33460
|
+
}
|
|
33461
|
+
if (opts.time !== void 0) guard.time.assertValid(opts.time, _err, "webauthn/bad-input", "opts.time");
|
|
33462
|
+
_requireAttShape(att.attStmt, ["ver", "response"], ["ver", "response"]);
|
|
33463
|
+
_attRead(att.attStmt, "ver", cbor.read.textString, "a text string");
|
|
33464
|
+
var responseBytes = _attRead(att.attStmt, "response", cbor.read.byteString, "a byte string");
|
|
33465
|
+
if (!responseBytes.length) throw _err("webauthn/bad-att-stmt", "the android-safetynet response is empty");
|
|
33466
|
+
var segs = guard.text.decode(responseBytes, constants.LIMITS.SAFETYNET_JWS_MAX_BYTES, WebauthnError, "webauthn/bad-att-stmt", "the android-safetynet response").split(".");
|
|
33467
|
+
if (segs.length !== 3) throw _err("webauthn/bad-att-stmt", "the android-safetynet response is not a three-part JWS compact serialization (RFC 7515 sec. 3.1)");
|
|
33468
|
+
var header, payload, sigBytes;
|
|
33469
|
+
try {
|
|
33470
|
+
header = jose.parseJson(jose.base64url.decode(segs[0]));
|
|
33471
|
+
payload = jose.parseJson(jose.base64url.decode(segs[1]));
|
|
33472
|
+
sigBytes = Buffer.from(jose.base64url.decode(segs[2]));
|
|
33473
|
+
} catch (e) {
|
|
33474
|
+
throw _err("webauthn/bad-att-stmt", "the android-safetynet response is not a decodable JWS", e);
|
|
33475
|
+
}
|
|
33476
|
+
if (!_isPlainObject(header) || !_isPlainObject(payload)) {
|
|
33477
|
+
throw _err("webauthn/bad-att-stmt", "the android-safetynet JWS header and payload must each be a JSON object");
|
|
33478
|
+
}
|
|
33479
|
+
if (header.alg !== "RS256") throw _err("webauthn/unsupported-algorithm", "the android-safetynet JWS alg must be RS256, got " + JSON.stringify(header.alg));
|
|
33480
|
+
if (!Array.isArray(header.x5c) || header.x5c.length === 0) {
|
|
33481
|
+
throw _err("webauthn/bad-att-stmt", "the android-safetynet JWS header carries no x5c certificate chain (RFC 7515 sec. 4.1.6)");
|
|
33482
|
+
}
|
|
33483
|
+
_requireX5cCount(header.x5c.length);
|
|
33484
|
+
var chain = header.x5c.map(function(entry, i) {
|
|
33485
|
+
if (typeof entry !== "string") throw _err("webauthn/bad-att-stmt", "the android-safetynet x5c entry " + i + " is not a string");
|
|
33486
|
+
var der;
|
|
33487
|
+
try {
|
|
33488
|
+
der = guard.encoding.base64(entry, constants.LIMITS.SAFETYNET_CERT_MAX_BYTES, WebauthnError, "webauthn/bad-att-stmt", "an android-safetynet x5c entry");
|
|
33489
|
+
} catch (e) {
|
|
33490
|
+
throw _err("webauthn/bad-att-stmt", "the android-safetynet x5c entry " + i + " is not canonical base64", e);
|
|
33491
|
+
}
|
|
33492
|
+
try {
|
|
33493
|
+
return x509.parse(der);
|
|
33494
|
+
} catch (e) {
|
|
33495
|
+
throw _err("webauthn/bad-att-cert", "the android-safetynet x5c entry " + i + " is not a decodable certificate", e);
|
|
33496
|
+
}
|
|
33497
|
+
});
|
|
33498
|
+
var leaf = chain[0];
|
|
33499
|
+
var wantNonce = _sha("sha256", Buffer.concat([att.authDataBytes, clientDataHash])).toString("base64");
|
|
33500
|
+
if (typeof payload.nonce !== "string" || !guard.crypto.constantTimeEqual(Buffer.from(payload.nonce, "utf8"), Buffer.from(wantNonce, "utf8"))) {
|
|
33501
|
+
throw _err("webauthn/safetynet-nonce-mismatch", "the android-safetynet nonce does not bind this authenticatorData and clientDataHash (WebAuthn 8.5)");
|
|
33502
|
+
}
|
|
33503
|
+
if (!_safetyNetHostnameOk(leaf)) {
|
|
33504
|
+
throw _err("webauthn/safetynet-bad-hostname", "the android-safetynet x5c leaf is not issued to attest.android.com (WebAuthn 8.5)");
|
|
33505
|
+
}
|
|
33506
|
+
var chainAt;
|
|
33507
|
+
var signals = {
|
|
33508
|
+
ctsProfileMatch: payload.ctsProfileMatch,
|
|
33509
|
+
basicIntegrity: payload.basicIntegrity,
|
|
33510
|
+
timestampMs: payload.timestampMs,
|
|
33511
|
+
apkPackageName: payload.apkPackageName,
|
|
33512
|
+
apkCertificateDigestSha256: payload.apkCertificateDigestSha256,
|
|
33513
|
+
advice: payload.advice
|
|
33514
|
+
};
|
|
33515
|
+
if (opts.requireCtsProfileMatch === true && signals.ctsProfileMatch !== true) {
|
|
33516
|
+
throw _err("webauthn/safetynet-cts-profile", "the android-safetynet response reports ctsProfileMatch " + JSON.stringify(signals.ctsProfileMatch) + ", and opts.requireCtsProfileMatch demands true");
|
|
33517
|
+
}
|
|
33518
|
+
if (opts.requireCtsProfileMatch !== void 0 && typeof opts.requireCtsProfileMatch !== "boolean") {
|
|
33519
|
+
throw _err("webauthn/bad-input", "opts.requireCtsProfileMatch must be a boolean");
|
|
33520
|
+
}
|
|
33521
|
+
return _verifySig(
|
|
33522
|
+
-257,
|
|
33523
|
+
sigBytes,
|
|
33524
|
+
leaf.subjectPublicKeyInfo.bytes,
|
|
33525
|
+
Buffer.from(segs[0] + "." + segs[1], "ascii"),
|
|
33526
|
+
_err
|
|
33527
|
+
).then(function(ok) {
|
|
33528
|
+
if (!ok) throw _err("webauthn/verify-failed", "the android-safetynet JWS signature does not verify under the x5c leaf key");
|
|
33529
|
+
chainAt = opts.time !== void 0 ? opts.time : typeof payload.timestampMs === "number" && isFinite(payload.timestampMs) && payload.timestampMs > 0 ? new Date(payload.timestampMs) : void 0;
|
|
33530
|
+
return _safetyNetChainTrusted(chain, roots, chainAt);
|
|
33531
|
+
}).then(function() {
|
|
33532
|
+
var res = _result("android-safetynet", "Basic", chain, att);
|
|
33533
|
+
res.safetyNet = signals;
|
|
33534
|
+
if (chainAt !== void 0) res.chainValidatedAt = chainAt;
|
|
33535
|
+
return res;
|
|
33536
|
+
});
|
|
33537
|
+
},
|
|
33538
|
+
// compound (WebAuthn 8.9): the attStmt is an ARRAY of nested attestation statements, each
|
|
33539
|
+
// verified over the SAME authenticatorData and clientDataHash as the outer object. sec. 8.9
|
|
33540
|
+
// leaves the acceptance threshold to relying-party policy ("if validation fails for one or more
|
|
33541
|
+
// subStmt, decide the appropriate result based on RP policy"); this toolkit's policy is
|
|
33542
|
+
// fail-closed -- EVERY element must verify, because accepting a compound whose strong element
|
|
33543
|
+
// failed and whose `none` element passed would let a wrapper launder a failed attestation.
|
|
33544
|
+
compound: function(att, clientDataHash, opts) {
|
|
33545
|
+
var kids = att.attStmt.children || [];
|
|
33546
|
+
if (kids.length < 2) throw _err("webauthn/bad-att-stmt", "a compound attestation statement must carry at least two nested statements (WebAuthn 8.9)");
|
|
33547
|
+
if (kids.length > constants.LIMITS.WEBAUTHN_COMPOUND_MAX_STATEMENTS) {
|
|
33548
|
+
throw _err("webauthn/bad-att-stmt", "a compound attestation statement carries " + kids.length + " nested statements, above the " + constants.LIMITS.WEBAUTHN_COMPOUND_MAX_STATEMENTS + " this toolkit will verify");
|
|
33549
|
+
}
|
|
33550
|
+
var elements = kids.map(function(el, i) {
|
|
33551
|
+
if (!el || el.majorType !== 5) throw _err("webauthn/bad-att-stmt", "compound element " + i + " must be a CBOR map { fmt, attStmt } (WebAuthn 8.9)");
|
|
33552
|
+
var fN = cbor.read.mapGet(el, "fmt"), sN = cbor.read.mapGet(el, "attStmt");
|
|
33553
|
+
if (el.children.length !== 2 || !fN || !sN) throw _err("webauthn/bad-att-stmt", "compound element " + i + " must be exactly { fmt, attStmt } (WebAuthn 8.9)");
|
|
33554
|
+
if (fN.majorType !== 3) throw _err("webauthn/bad-att-stmt", "compound element " + i + " 'fmt' must be a text string");
|
|
33555
|
+
var f = cbor.read.textString(fN);
|
|
33556
|
+
if (f === "compound") throw _err("webauthn/bad-att-stmt", "a compound attestation statement must not nest another compound (WebAuthn 8.9)");
|
|
33557
|
+
var v = VERIFIERS[f];
|
|
33558
|
+
if (!v) throw _err("webauthn/unsupported-format", "compound element " + i + " uses unsupported attestation statement format '" + f + "'");
|
|
33559
|
+
var wantMajor = ATT_STMT_MAJOR[f] === void 0 ? 5 : ATT_STMT_MAJOR[f];
|
|
33560
|
+
if (sN.majorType !== wantMajor) throw _err("webauthn/bad-att-stmt", "compound element " + i + " 'attStmt' has the wrong CBOR shape for format '" + f + "'");
|
|
33561
|
+
return { fmt: f, index: i, att: { fmt: f, attStmt: sN, authData: att.authData, authDataBytes: att.authDataBytes } };
|
|
33562
|
+
});
|
|
33563
|
+
var out = [];
|
|
33564
|
+
return elements.reduce(function(p, e) {
|
|
33565
|
+
return p.then(function() {
|
|
33566
|
+
return Promise.resolve().then(function() {
|
|
33567
|
+
return VERIFIERS[e.fmt](e.att, clientDataHash, opts);
|
|
33568
|
+
}).then(function(r) {
|
|
33569
|
+
out.push(r);
|
|
33570
|
+
}, function(err) {
|
|
33571
|
+
throw _err("webauthn/compound-element-failed", "compound element " + e.index + " (format '" + e.fmt + "') did not verify", err);
|
|
33572
|
+
});
|
|
33573
|
+
});
|
|
33574
|
+
}, Promise.resolve()).then(function() {
|
|
33575
|
+
var res = _result("compound", "Compound", [], att);
|
|
33576
|
+
res.compound = out;
|
|
33577
|
+
return res;
|
|
31866
33578
|
});
|
|
31867
33579
|
},
|
|
31868
33580
|
// none (WebAuthn 8.7): the authenticator provides no attestation. attStmt MUST be
|
|
@@ -31875,6 +33587,69 @@ var require_webauthn = __commonJS({
|
|
|
31875
33587
|
return Promise.resolve(_result("none", "None", [], att));
|
|
31876
33588
|
}
|
|
31877
33589
|
};
|
|
33590
|
+
function _isPlainObject(v) {
|
|
33591
|
+
return !!v && typeof v === "object" && !Array.isArray(v);
|
|
33592
|
+
}
|
|
33593
|
+
function _safetyNetHostnameOk(leaf) {
|
|
33594
|
+
var want = "attest.android.com";
|
|
33595
|
+
var san = _decodeExt(leaf, "subjectAltName");
|
|
33596
|
+
var entries = san && Array.isArray(san.value) ? san.value : [];
|
|
33597
|
+
var dns = entries.filter(function(gn) {
|
|
33598
|
+
return gn && gn.type === "dNSName" && typeof gn.value === "string";
|
|
33599
|
+
});
|
|
33600
|
+
if (dns.length) return dns.some(function(gn) {
|
|
33601
|
+
return gn.value.toLowerCase() === want;
|
|
33602
|
+
});
|
|
33603
|
+
return leaf.subject.rdns.some(function(rdn) {
|
|
33604
|
+
return rdn.some(function(atv) {
|
|
33605
|
+
return atv.name === "commonName" && typeof atv.value === "string" && atv.value.toLowerCase() === want;
|
|
33606
|
+
});
|
|
33607
|
+
});
|
|
33608
|
+
}
|
|
33609
|
+
function _safetyNetChainTrusted(chain, roots, time) {
|
|
33610
|
+
var ordered = chain.slice().reverse();
|
|
33611
|
+
var when = time === void 0 ? /* @__PURE__ */ new Date() : time;
|
|
33612
|
+
var attempts = roots.map(function(root, i) {
|
|
33613
|
+
return function() {
|
|
33614
|
+
var anchorCert;
|
|
33615
|
+
try {
|
|
33616
|
+
anchorCert = Buffer.isBuffer(root) || typeof root === "string" ? x509.parse(root) : root;
|
|
33617
|
+
} catch (e) {
|
|
33618
|
+
throw _err("webauthn/bad-input", "opts.safetyNetRoots[" + i + "] is not a decodable certificate", e);
|
|
33619
|
+
}
|
|
33620
|
+
if (!anchorCert || !anchorCert.subject || !anchorCert.subjectPublicKeyInfo) {
|
|
33621
|
+
throw _err("webauthn/bad-input", "opts.safetyNetRoots[" + i + "] is not a certificate");
|
|
33622
|
+
}
|
|
33623
|
+
var path = ordered.slice();
|
|
33624
|
+
if (path.length > 1 && guard.name.dnEqual(path[0].subject, anchorCert.subject) && guard.name.dnEqual(path[0].issuer, path[0].subject)) {
|
|
33625
|
+
path = path.slice(1);
|
|
33626
|
+
}
|
|
33627
|
+
return pathValidate.validate(path, {
|
|
33628
|
+
time: when,
|
|
33629
|
+
// The anchor's own KEY algorithm and its parameters, not the algorithm its issuer signed it
|
|
33630
|
+
// with: the validator carries these forward as the working public key, and a certificate
|
|
33631
|
+
// below the anchor may inherit its key parameters from them.
|
|
33632
|
+
trustAnchor: {
|
|
33633
|
+
name: anchorCert.subject,
|
|
33634
|
+
publicKey: anchorCert.subjectPublicKeyInfo.bytes,
|
|
33635
|
+
algorithm: anchorCert.subjectPublicKeyInfo.algorithm.oid,
|
|
33636
|
+
parameters: anchorCert.subjectPublicKeyInfo.algorithm.parameters
|
|
33637
|
+
}
|
|
33638
|
+
}).then(function(r) {
|
|
33639
|
+
return !!(r && r.valid);
|
|
33640
|
+
}, function() {
|
|
33641
|
+
return false;
|
|
33642
|
+
});
|
|
33643
|
+
};
|
|
33644
|
+
});
|
|
33645
|
+
return attempts.reduce(function(p, next) {
|
|
33646
|
+
return p.then(function(done) {
|
|
33647
|
+
return done ? true : next();
|
|
33648
|
+
});
|
|
33649
|
+
}, Promise.resolve(false)).then(function(trusted) {
|
|
33650
|
+
if (!trusted) throw _err("webauthn/safetynet-cert-untrusted", "the android-safetynet x5c chain does not validate to any supplied root (opts.safetyNetRoots)");
|
|
33651
|
+
});
|
|
33652
|
+
}
|
|
31878
33653
|
function _result(fmt, attestationType, chain, att) {
|
|
31879
33654
|
return { verified: true, fmt, attestationType, trustPath: (chain || []).slice().reverse(), aaguid: att.authData.aaguid, credentialPublicKey: att.authData.credentialPublicKey };
|
|
31880
33655
|
}
|
|
@@ -31900,6 +33675,13 @@ var require_webauthn = __commonJS({
|
|
|
31900
33675
|
}
|
|
31901
33676
|
function verify(attestationObject, clientDataHash, opts) {
|
|
31902
33677
|
opts = opts || {};
|
|
33678
|
+
try {
|
|
33679
|
+
if (!_isPlainObject(opts)) throw _err("webauthn/bad-input", "opts must be an object");
|
|
33680
|
+
guard.identifier.assertKnownKeys(opts, _VERIFY_OPTS, _err, "webauthn/bad-input", "opts has an unknown key ");
|
|
33681
|
+
if (opts.time !== void 0) guard.time.assertValid(opts.time, _err, "webauthn/bad-input", "opts.time");
|
|
33682
|
+
} catch (e) {
|
|
33683
|
+
return Promise.reject(e);
|
|
33684
|
+
}
|
|
31903
33685
|
if (!Buffer.isBuffer(clientDataHash) || clientDataHash.length !== 32) {
|
|
31904
33686
|
return Promise.reject(_err("webauthn/bad-input", "clientDataHash must be a 32-byte SHA-256 digest"));
|
|
31905
33687
|
}
|
|
@@ -31914,13 +33696,93 @@ var require_webauthn = __commonJS({
|
|
|
31914
33696
|
}
|
|
31915
33697
|
var verifier = VERIFIERS[att.fmt];
|
|
31916
33698
|
if (!verifier) return Promise.reject(_err("webauthn/unsupported-format", "attestation statement format '" + att.fmt + "' is not supported"));
|
|
33699
|
+
if (opts.tpmPolicy !== void 0 && !_formatCanSatisfyTpmPolicy(att)) {
|
|
33700
|
+
return Promise.reject(_err("webauthn/tpm-policy", "opts.tpmPolicy requires a TPM attestation, but this attestation is format '" + att.fmt + "', which carries no TPM public area"));
|
|
33701
|
+
}
|
|
31917
33702
|
return Promise.resolve().then(function() {
|
|
31918
33703
|
return verifier(att, clientDataHash, opts);
|
|
33704
|
+
}).then(function(res) {
|
|
33705
|
+
return opts.metadata === void 0 ? res : _applyMetadata(res, att, opts);
|
|
33706
|
+
});
|
|
33707
|
+
}
|
|
33708
|
+
function _applyMetadata(res, att, opts) {
|
|
33709
|
+
var md = opts.metadata;
|
|
33710
|
+
if (!mds.isVerifiedResult(md)) {
|
|
33711
|
+
throw _err("webauthn/bad-input", "opts.metadata must be a pki.webauthn.verifyMetadataBlob result, not a raw BLOB");
|
|
33712
|
+
}
|
|
33713
|
+
var paths = res.fmt === "compound" && Array.isArray(res.compound) ? res.compound.filter(function(el) {
|
|
33714
|
+
return el.trustPath && el.trustPath.length;
|
|
33715
|
+
}).map(function(el) {
|
|
33716
|
+
return { tp: el.trustPath, fmt: el.fmt, at: el.chainValidatedAt };
|
|
33717
|
+
}) : res.trustPath && res.trustPath.length ? [{ tp: res.trustPath, fmt: res.fmt, at: res.chainValidatedAt }] : [];
|
|
33718
|
+
if (!paths.length) {
|
|
33719
|
+
throw _err("webauthn/metadata-not-applicable", "opts.metadata was supplied, but this attestation carries no trust path to anchor (format '" + res.fmt + "')");
|
|
33720
|
+
}
|
|
33721
|
+
var aaguid = mds.aaguidToString(att.authData.aaguid);
|
|
33722
|
+
var applied = [];
|
|
33723
|
+
function govern(info) {
|
|
33724
|
+
var tp = info.tp;
|
|
33725
|
+
var declared = _aaguidIsSigned(info.fmt) && aaguid && aaguid !== mds.ZERO_AAGUID;
|
|
33726
|
+
var entry, identifier;
|
|
33727
|
+
if (declared) {
|
|
33728
|
+
entry = mds.metadataFor(md, aaguid);
|
|
33729
|
+
identifier = "aaguid " + aaguid;
|
|
33730
|
+
} else {
|
|
33731
|
+
var keyId = mds.certKeyIdentifier(tp[tp.length - 1]);
|
|
33732
|
+
entry = mds.metadataForKeyIdentifier(md, keyId);
|
|
33733
|
+
identifier = "attestation certificate key identifier " + keyId;
|
|
33734
|
+
}
|
|
33735
|
+
if (!entry) throw _err("webauthn/metadata-not-found", "no metadata entry matches this authenticator (" + identifier + ")");
|
|
33736
|
+
if (mds.statusDenied(entry, md, tp[tp.length - 1], at)) {
|
|
33737
|
+
throw _err("webauthn/metadata-status", "the metadata entry for " + identifier + " carries a disqualifying status report");
|
|
33738
|
+
}
|
|
33739
|
+
var anchors = mds.metadataAnchors(entry);
|
|
33740
|
+
if (!anchors.length) throw _err("webauthn/metadata-no-anchor", "the metadata entry for " + identifier + " supplies no attestation root certificate");
|
|
33741
|
+
applied.push({ entry, anchors, identifier });
|
|
33742
|
+
return { anchors, identifier };
|
|
33743
|
+
}
|
|
33744
|
+
var at = opts.time !== void 0 ? opts.time : /* @__PURE__ */ new Date();
|
|
33745
|
+
mds.assertFresh(md, at, "the metadata supplied as opts.metadata");
|
|
33746
|
+
return paths.reduce(function(p, info) {
|
|
33747
|
+
return p.then(function() {
|
|
33748
|
+
var g = govern(info);
|
|
33749
|
+
var pathAt = opts.time !== void 0 ? opts.time : info.at || at;
|
|
33750
|
+
return mds.chainToAnchor(
|
|
33751
|
+
info.tp.slice().reverse(),
|
|
33752
|
+
g.anchors,
|
|
33753
|
+
pathAt,
|
|
33754
|
+
"attestation trust path for " + g.identifier + " (against the roots its metadata entry registers)"
|
|
33755
|
+
);
|
|
33756
|
+
});
|
|
33757
|
+
}, Promise.resolve()).then(function() {
|
|
33758
|
+
var primary = applied[0];
|
|
33759
|
+
res.metadata = {
|
|
33760
|
+
aaguid: primary.entry.aaguid,
|
|
33761
|
+
keyIdentifiers: primary.entry.keyIdentifiers || [],
|
|
33762
|
+
entry: primary.entry,
|
|
33763
|
+
entries: applied.map(function(a) {
|
|
33764
|
+
return a.entry;
|
|
33765
|
+
}),
|
|
33766
|
+
anchors: primary.anchors.length
|
|
33767
|
+
};
|
|
33768
|
+
return res;
|
|
33769
|
+
});
|
|
33770
|
+
}
|
|
33771
|
+
function _formatCanSatisfyTpmPolicy(att) {
|
|
33772
|
+
if (att.fmt === "tpm") return true;
|
|
33773
|
+
if (att.fmt !== "compound") return false;
|
|
33774
|
+
return (att.attStmt.children || []).some(function(el) {
|
|
33775
|
+
if (!el || el.majorType !== 5) return false;
|
|
33776
|
+
var fN = cbor.read.mapGet(el, "fmt");
|
|
33777
|
+
return !!fN && fN.majorType === 3 && cbor.read.textString(fN) === "tpm";
|
|
31919
33778
|
});
|
|
31920
33779
|
}
|
|
31921
33780
|
module2.exports = {
|
|
31922
33781
|
parseAttestationObject,
|
|
31923
|
-
verify
|
|
33782
|
+
verify,
|
|
33783
|
+
verifyMetadataBlob: mds.verifyMetadataBlob,
|
|
33784
|
+
metadataFor: mds.metadataFor,
|
|
33785
|
+
metadataAnchors: mds.metadataAnchors
|
|
31924
33786
|
};
|
|
31925
33787
|
}
|
|
31926
33788
|
});
|