@blamejs/core 0.14.0 → 0.14.2
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/lib/_test/crypto-fixtures.js +3 -3
- package/lib/a2a-tasks.js +18 -18
- package/lib/a2a.js +4 -4
- package/lib/acme.js +3 -3
- package/lib/agent-idempotency.js +1 -1
- package/lib/agent-orchestrator.js +8 -8
- package/lib/agent-posture-chain.js +2 -2
- package/lib/agent-saga.js +1 -1
- package/lib/agent-snapshot.js +1 -1
- package/lib/agent-stream.js +1 -1
- package/lib/agent-tenant.js +1 -1
- package/lib/agent-trace.js +3 -3
- package/lib/ai-capability.js +1 -1
- package/lib/ai-dp.js +4 -4
- package/lib/ai-input.js +3 -3
- package/lib/ai-model-manifest.js +7 -7
- package/lib/ai-pref.js +3 -3
- package/lib/archive-gz.js +2 -2
- package/lib/archive-read.js +25 -25
- package/lib/archive-tar-read.js +2 -2
- package/lib/archive-tar.js +20 -20
- package/lib/archive-wrap.js +10 -10
- package/lib/argon2-builtin.js +1 -1
- package/lib/asn1-der.js +45 -34
- package/lib/atomic-file.js +2 -2
- package/lib/audit-daily-review.js +3 -3
- package/lib/audit-sign.js +5 -5
- package/lib/audit-tools.js +1 -1
- package/lib/audit.js +2 -2
- package/lib/auth/acr-vocabulary.js +2 -2
- package/lib/auth/bot-challenge.js +3 -3
- package/lib/auth/ciba.js +7 -7
- package/lib/auth/dpop.js +3 -3
- package/lib/auth/fido-mds3.js +8 -8
- package/lib/auth/jar.js +11 -0
- package/lib/auth/jwt-external.js +5 -5
- package/lib/auth/oauth.js +7 -9
- package/lib/auth/oid4vci.js +10 -10
- package/lib/auth/oid4vp.js +2 -2
- package/lib/auth/openid-federation.js +2 -2
- package/lib/auth/passkey.js +3 -3
- package/lib/auth/saml.js +29 -25
- package/lib/auth/sd-jwt-vc-disclosure.js +1 -1
- package/lib/auth/sd-jwt-vc.js +4 -4
- package/lib/auth/status-list.js +10 -10
- package/lib/auth/step-up.js +1 -1
- package/lib/auth-bot-challenge.js +1 -1
- package/lib/backup/index.js +7 -7
- package/lib/base32.js +8 -8
- package/lib/budr.js +2 -2
- package/lib/cache-status.js +2 -2
- package/lib/calendar.js +23 -23
- package/lib/cbor.js +12 -12
- package/lib/cdn-cache-control.js +1 -1
- package/lib/cert.js +5 -5
- package/lib/cloud-events.js +5 -5
- package/lib/cms-codec.js +21 -21
- package/lib/codepoint-class.js +12 -12
- package/lib/compliance-sanctions-fuzzy.js +4 -4
- package/lib/compliance-sanctions.js +4 -4
- package/lib/compliance.js +29 -29
- package/lib/content-credentials.js +36 -36
- package/lib/cookies.js +1 -1
- package/lib/cose.js +13 -13
- package/lib/cra-report.js +1 -1
- package/lib/crdt.js +1 -1
- package/lib/crypto-field.js +2 -2
- package/lib/crypto-xwing.js +7 -7
- package/lib/crypto.js +6 -6
- package/lib/csp.js +2 -2
- package/lib/cwt.js +4 -4
- package/lib/dark-patterns.js +2 -2
- package/lib/data-act.js +2 -2
- package/lib/db-file-lifecycle.js +4 -4
- package/lib/db-query.js +1 -1
- package/lib/db.js +6 -6
- package/lib/dbsc.js +13 -13
- package/lib/did.js +17 -17
- package/lib/dora.js +4 -4
- package/lib/dsr.js +1 -1
- package/lib/early-hints.js +2 -2
- package/lib/eat.js +4 -4
- package/lib/external-db-migrate.js +1 -1
- package/lib/external-db.js +1 -1
- package/lib/flag-cache.js +1 -1
- package/lib/flag-evaluation-context.js +2 -2
- package/lib/graphql-federation.js +4 -4
- package/lib/guard-agent-registry.js +5 -5
- package/lib/guard-archive.js +24 -24
- package/lib/guard-cidr.js +33 -33
- package/lib/guard-csv.js +1 -1
- package/lib/guard-domain.js +10 -10
- package/lib/guard-dsn.js +4 -4
- package/lib/guard-email.js +19 -19
- package/lib/guard-event-bus-payload.js +4 -4
- package/lib/guard-event-bus-topic.js +6 -6
- package/lib/guard-filename.js +7 -7
- package/lib/guard-graphql.js +9 -9
- package/lib/guard-html-wcag-tagwalk.js +1 -1
- package/lib/guard-html-wcag.js +4 -4
- package/lib/guard-html.js +7 -7
- package/lib/guard-idempotency-key.js +6 -6
- package/lib/guard-image.js +4 -4
- package/lib/guard-imap-command.js +17 -17
- package/lib/guard-jmap.js +20 -20
- package/lib/guard-json.js +12 -12
- package/lib/guard-jsonpath.js +3 -3
- package/lib/guard-jwt.js +4 -4
- package/lib/guard-list-id.js +7 -7
- package/lib/guard-list-unsubscribe.js +8 -8
- package/lib/guard-mail-compose.js +4 -4
- package/lib/guard-mail-move.js +5 -5
- package/lib/guard-mail-query.js +3 -3
- package/lib/guard-mail-reply.js +3 -3
- package/lib/guard-mail-sieve.js +6 -6
- package/lib/guard-managesieve-command.js +25 -25
- package/lib/guard-markdown.js +31 -31
- package/lib/guard-message-id.js +5 -5
- package/lib/guard-mime.js +1 -1
- package/lib/guard-oauth.js +3 -3
- package/lib/guard-pdf.js +6 -6
- package/lib/guard-pop3-command.js +11 -11
- package/lib/guard-posture-chain.js +5 -5
- package/lib/guard-regex.js +10 -10
- package/lib/guard-saga-config.js +5 -5
- package/lib/guard-smtp-command.js +6 -6
- package/lib/guard-snapshot-envelope.js +3 -3
- package/lib/guard-stream-args.js +4 -4
- package/lib/guard-svg.js +11 -11
- package/lib/guard-tenant-id.js +5 -5
- package/lib/guard-time.js +15 -15
- package/lib/guard-trace-context.js +4 -4
- package/lib/guard-uuid.js +11 -11
- package/lib/guard-xml.js +12 -12
- package/lib/guard-yaml.js +16 -16
- package/lib/honeytoken.js +5 -5
- package/lib/http-client.js +1 -1
- package/lib/http-message-signature.js +2 -2
- package/lib/iab-mspa.js +3 -3
- package/lib/iab-tcf.js +70 -70
- package/lib/inbox.js +4 -4
- package/lib/ip-utils.js +15 -15
- package/lib/jose-jwe-experimental.js +2 -2
- package/lib/json-path.js +3 -3
- package/lib/json-schema.js +1 -1
- package/lib/jsonapi.js +3 -3
- package/lib/jtd.js +2 -2
- package/lib/link-header.js +1 -1
- package/lib/local-db-thin.js +1 -1
- package/lib/log.js +1 -1
- package/lib/lro.js +4 -4
- package/lib/mail-agent.js +1 -1
- package/lib/mail-arc-sign.js +6 -6
- package/lib/mail-auth.js +43 -43
- package/lib/mail-bimi.js +3 -3
- package/lib/mail-crypto-pgp.js +53 -45
- package/lib/mail-crypto-smime.js +5 -5
- package/lib/mail-dav.js +1 -1
- package/lib/mail-deploy.js +39 -39
- package/lib/mail-dkim.js +11 -11
- package/lib/mail-greylist.js +12 -12
- package/lib/mail-helo.js +1 -1
- package/lib/mail-journal.js +8 -8
- package/lib/mail-rbl.js +7 -7
- package/lib/mail-scan.js +7 -7
- package/lib/mail-send-deliver.js +2 -2
- package/lib/mail-server-imap.js +12 -12
- package/lib/mail-server-jmap.js +16 -16
- package/lib/mail-server-managesieve.js +4 -4
- package/lib/mail-server-mx.js +17 -17
- package/lib/mail-server-pop3.js +4 -4
- package/lib/mail-server-rate-limit.js +2 -2
- package/lib/mail-server-submission.js +21 -21
- package/lib/mail-sieve.js +2 -2
- package/lib/mail-spam-score.js +5 -5
- package/lib/mail-srs.js +12 -12
- package/lib/mail-store-fts.js +2 -2
- package/lib/mail-store.js +8 -8
- package/lib/mail-unsubscribe.js +4 -4
- package/lib/mail.js +4 -4
- package/lib/mcp-tool-registry.js +4 -4
- package/lib/mcp.js +8 -8
- package/lib/mdoc.js +2 -2
- package/lib/metrics.js +8 -8
- package/lib/middleware/age-gate.js +1 -1
- package/lib/middleware/api-encrypt.js +7 -7
- package/lib/middleware/assetlinks.js +2 -2
- package/lib/middleware/asyncapi-serve.js +2 -2
- package/lib/middleware/bearer-auth.js +5 -5
- package/lib/middleware/body-parser.js +5 -5
- package/lib/middleware/compose-pipeline.js +15 -15
- package/lib/middleware/csp-report.js +4 -4
- package/lib/middleware/daily-byte-quota.js +1 -1
- package/lib/middleware/dpop.js +1 -1
- package/lib/middleware/headers.js +2 -2
- package/lib/middleware/host-allowlist.js +1 -1
- package/lib/middleware/idempotency-key.js +12 -12
- package/lib/middleware/nel.js +1 -1
- package/lib/middleware/openapi-serve.js +2 -2
- package/lib/middleware/protected-resource-metadata.js +2 -2
- package/lib/middleware/require-aal.js +1 -1
- package/lib/middleware/require-bound-key.js +2 -2
- package/lib/middleware/require-content-type.js +1 -1
- package/lib/middleware/require-methods.js +1 -1
- package/lib/middleware/require-step-up.js +2 -2
- package/lib/middleware/scim-server.js +1 -1
- package/lib/middleware/security-txt.js +3 -3
- package/lib/middleware/tus-upload.js +12 -12
- package/lib/middleware/web-app-manifest.js +2 -2
- package/lib/network-byte-quota.js +1 -1
- package/lib/network-dns-resolver.js +23 -23
- package/lib/network-dns.js +29 -29
- package/lib/network-dnssec.js +33 -33
- package/lib/network-smtp-policy.js +10 -10
- package/lib/network-tls.js +99 -94
- package/lib/network-tsig.js +33 -33
- package/lib/nis2-report.js +1 -1
- package/lib/ntp-check.js +3 -3
- package/lib/observability-otlp-exporter.js +17 -17
- package/lib/observability-tracer.js +6 -6
- package/lib/observability.js +8 -8
- package/lib/openapi-yaml.js +1 -1
- package/lib/openapi.js +1 -1
- package/lib/outbox.js +6 -6
- package/lib/pqc-agent.js +4 -4
- package/lib/pqc-software.js +1 -1
- package/lib/privacy-pass.js +5 -5
- package/lib/problem-details.js +5 -5
- package/lib/promise-pool.js +1 -1
- package/lib/protobuf-encoder.js +9 -1
- package/lib/queue.js +4 -2
- package/lib/redact.js +2 -2
- package/lib/request-helpers.js +1 -1
- package/lib/router.js +10 -10
- package/lib/safe-async.js +2 -2
- package/lib/safe-dns.js +71 -71
- package/lib/safe-ical.js +19 -19
- package/lib/safe-icap.js +24 -24
- package/lib/safe-jsonpath.js +2 -2
- package/lib/safe-mime.js +10 -10
- package/lib/safe-mount-info.js +3 -3
- package/lib/safe-redirect.js +1 -1
- package/lib/safe-sieve.js +23 -23
- package/lib/safe-smtp.js +1 -1
- package/lib/safe-vcard.js +14 -14
- package/lib/sandbox.js +5 -5
- package/lib/sec-cyber.js +1 -1
- package/lib/self-update-standalone-verifier.js +3 -3
- package/lib/self-update.js +3 -3
- package/lib/server-timing.js +3 -3
- package/lib/session-device-binding.js +7 -7
- package/lib/session.js +8 -8
- package/lib/standard-webhooks.js +4 -4
- package/lib/storage.js +2 -2
- package/lib/stream-throttle.js +1 -1
- package/lib/structured-fields.js +15 -15
- package/lib/subject.js +1 -1
- package/lib/tcpa-10dlc.js +1 -1
- package/lib/tenant-quota.js +3 -3
- package/lib/test-harness.js +1 -1
- package/lib/tracing.js +1 -1
- package/lib/tsa.js +5 -5
- package/lib/uri-template.js +5 -5
- package/lib/vault/index.js +2 -2
- package/lib/vault/seal-pem-file.js +4 -4
- package/lib/vc.js +2 -2
- package/lib/vendor-data.js +1 -1
- package/lib/watcher.js +4 -4
- package/lib/web-push-vapid.js +21 -21
- package/lib/webhook.js +2 -2
- package/lib/websocket.js +3 -3
- package/lib/worker-pool.js +3 -3
- package/lib/ws-client.js +24 -24
- package/lib/xml-c14n.js +2 -2
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
package/lib/network-tls.js
CHANGED
|
@@ -821,7 +821,7 @@ function _connectAndCheckOcsp(opts, requireStapled) {
|
|
|
821
821
|
var OID_BASIC_OCSP_RESPONSE = "1.3.6.1.5.5.7.48.1.1";
|
|
822
822
|
// OCSP nonce extension — id-pkix-ocsp-nonce.
|
|
823
823
|
var OID_OCSP_NONCE = "1.3.6.1.5.5.7.48.1.2";
|
|
824
|
-
var OID_SHA1 = "1.3.14.3.2.26"; //
|
|
824
|
+
var OID_SHA1 = "1.3.14.3.2.26"; // SHA-1 algorithm OID arc
|
|
825
825
|
var OID_RSA_SHA256 = "1.2.840.113549.1.1.11";
|
|
826
826
|
var OID_RSA_SHA384 = "1.2.840.113549.1.1.12";
|
|
827
827
|
var OID_RSA_SHA512 = "1.2.840.113549.1.1.13";
|
|
@@ -834,21 +834,21 @@ function _parseTime(node) {
|
|
|
834
834
|
// ("YYYYMMDDhhmmssZ") into ms-since-epoch.
|
|
835
835
|
var s = node.value.toString("ascii");
|
|
836
836
|
var year, month, day, hour, min, sec;
|
|
837
|
-
if (s.length === 13 && s.charAt(12) === "Z") { //
|
|
837
|
+
if (s.length === 13 && s.charAt(12) === "Z") { // UTCTime length per X.690
|
|
838
838
|
// UTCTime YYMMDDhhmmssZ — 50+ → 19xx, else 20xx (RFC 5280 §4.1.2.5).
|
|
839
839
|
year = parseInt(s.slice(0, 2), 10);
|
|
840
|
-
year += year >= 50 ? 1900 : 2000; // allow:raw-
|
|
840
|
+
year += year >= 50 ? 1900 : 2000; // allow:raw-time-literal — RFC 5280 century pivot, calendar years
|
|
841
841
|
month = parseInt(s.slice(2, 4), 10);
|
|
842
842
|
day = parseInt(s.slice(4, 6), 10);
|
|
843
|
-
hour = parseInt(s.slice(6, 8), 10); //
|
|
844
|
-
min = parseInt(s.slice(8, 10), 10); //
|
|
843
|
+
hour = parseInt(s.slice(6, 8), 10); // UTCTime hour-byte offsets
|
|
844
|
+
min = parseInt(s.slice(8, 10), 10); // UTCTime minute-byte offsets
|
|
845
845
|
sec = parseInt(s.slice(10, 12), 10);
|
|
846
|
-
} else if (s.length >= 15 && s.charAt(s.length - 1) === "Z") { //
|
|
846
|
+
} else if (s.length >= 15 && s.charAt(s.length - 1) === "Z") { // GeneralizedTime length per X.690
|
|
847
847
|
// GeneralizedTime YYYYMMDDhhmmssZ.
|
|
848
848
|
year = parseInt(s.slice(0, 4), 10);
|
|
849
849
|
month = parseInt(s.slice(4, 6), 10);
|
|
850
|
-
day = parseInt(s.slice(6, 8), 10); //
|
|
851
|
-
hour = parseInt(s.slice(8, 10), 10); //
|
|
850
|
+
day = parseInt(s.slice(6, 8), 10); // GeneralizedTime day-byte offsets
|
|
851
|
+
hour = parseInt(s.slice(8, 10), 10); // GeneralizedTime hour-byte offsets
|
|
852
852
|
min = parseInt(s.slice(10, 12), 10);
|
|
853
853
|
sec = parseInt(s.slice(12, 14), 10);
|
|
854
854
|
} else {
|
|
@@ -913,7 +913,7 @@ function parseOcspResponse(der) {
|
|
|
913
913
|
"BasicOCSPResponse is not a SEQUENCE");
|
|
914
914
|
}
|
|
915
915
|
var basicChildren = asn1.readSequence(basic.value);
|
|
916
|
-
if (basicChildren.length < 3) { //
|
|
916
|
+
if (basicChildren.length < 3) { // minimum BasicOCSPResponse fields (tbs + alg + sig)
|
|
917
917
|
throw new TlsTrustError("tls/ocsp-bad-shape",
|
|
918
918
|
"BasicOCSPResponse needs tbsResponseData + signatureAlgorithm + signature");
|
|
919
919
|
}
|
|
@@ -994,7 +994,7 @@ function parseOcspResponse(der) {
|
|
|
994
994
|
var responses = [];
|
|
995
995
|
for (var sri = 0; sri < singleResponses.length; sri += 1) {
|
|
996
996
|
var sr = asn1.readSequence(singleResponses[sri].value);
|
|
997
|
-
if (sr.length < 3) continue; //
|
|
997
|
+
if (sr.length < 3) continue; // minimum SingleResponse fields
|
|
998
998
|
// sr[0] = certID SEQUENCE, sr[1] = certStatus CHOICE, sr[2] = thisUpdate.
|
|
999
999
|
var certIdChildren = asn1.readSequence(sr[0].value);
|
|
1000
1000
|
// certID = SEQUENCE { hashAlgorithm, issuerNameHash, issuerKeyHash, serialNumber }
|
|
@@ -1232,12 +1232,12 @@ function _extractIssuerNameDerAndKeyBitString(certDer) {
|
|
|
1232
1232
|
var idx = 0;
|
|
1233
1233
|
if (tbsKids.length > 0 &&
|
|
1234
1234
|
tbsKids[0].tagClass === asn1.TAG_CLASS.CONTEXT_SPECIFIC &&
|
|
1235
|
-
tbsKids[0].tag === 0) { //
|
|
1235
|
+
tbsKids[0].tag === 0) { // X.509 [0] EXPLICIT version tag
|
|
1236
1236
|
idx = 1;
|
|
1237
1237
|
}
|
|
1238
1238
|
// After version: serialNumber, signature, issuer, validity, subject, SPKI.
|
|
1239
|
-
var subjectIdx = idx + 4; //
|
|
1240
|
-
var spkiIdx = idx + 5; //
|
|
1239
|
+
var subjectIdx = idx + 4; // X.509 TBSCertificate field count
|
|
1240
|
+
var spkiIdx = idx + 5; // X.509 TBSCertificate field count
|
|
1241
1241
|
if (spkiIdx >= tbsKids.length) {
|
|
1242
1242
|
throw new TlsTrustError("tls/ocsp-bad-issuer-cert", "issuer cert lacks SPKI field");
|
|
1243
1243
|
}
|
|
@@ -1245,7 +1245,7 @@ function _extractIssuerNameDerAndKeyBitString(certDer) {
|
|
|
1245
1245
|
var spki = tbsKids[spkiIdx];
|
|
1246
1246
|
// Within SPKI: SEQUENCE { algorithm AlgorithmIdentifier, subjectPublicKey BIT STRING }
|
|
1247
1247
|
var spkiKids = asn1.readSequence(spki.value);
|
|
1248
|
-
if (spkiKids.length < 2) { //
|
|
1248
|
+
if (spkiKids.length < 2) { // minimum SPKI fields
|
|
1249
1249
|
throw new TlsTrustError("tls/ocsp-bad-issuer-cert", "SPKI missing subjectPublicKey BIT STRING");
|
|
1250
1250
|
}
|
|
1251
1251
|
var keyBytes = asn1.readBitString(spkiKids[1]);
|
|
@@ -1266,7 +1266,7 @@ function _extractLeafSerial(leafCertDer) {
|
|
|
1266
1266
|
var idx = 0;
|
|
1267
1267
|
if (tbsKids.length > 0 &&
|
|
1268
1268
|
tbsKids[0].tagClass === asn1.TAG_CLASS.CONTEXT_SPECIFIC &&
|
|
1269
|
-
tbsKids[0].tag === 0) { //
|
|
1269
|
+
tbsKids[0].tag === 0) { // X.509 [0] EXPLICIT version tag
|
|
1270
1270
|
idx = 1;
|
|
1271
1271
|
}
|
|
1272
1272
|
// serialNumber is the next field after the optional version.
|
|
@@ -1323,8 +1323,8 @@ function buildOcspRequest(opts) {
|
|
|
1323
1323
|
// talking to a responder that ignores nonces opt out via nonce: false.
|
|
1324
1324
|
var includeNonce = opts.nonce !== false;
|
|
1325
1325
|
if (includeNonce) {
|
|
1326
|
-
var nonceLen = typeof opts.nonceLen === "number" ? opts.nonceLen : 16; //
|
|
1327
|
-
if (nonceLen < 1 || nonceLen > 32) { //
|
|
1326
|
+
var nonceLen = typeof opts.nonceLen === "number" ? opts.nonceLen : 16; // RFC 8954 §2.1 nonce length floor
|
|
1327
|
+
if (nonceLen < 1 || nonceLen > 32) { // RFC 8954 §2.1 nonce length ceiling
|
|
1328
1328
|
throw new TlsTrustError("tls/ocsp-bad-nonce-len",
|
|
1329
1329
|
"nonce length out of RFC 8954 range (1..32)");
|
|
1330
1330
|
}
|
|
@@ -1548,7 +1548,7 @@ function _extractSctExtensionFromCert(certDer) {
|
|
|
1548
1548
|
var extensionsNode = null;
|
|
1549
1549
|
for (var i = 0; i < tbsChildren.length; i += 1) {
|
|
1550
1550
|
var ch = tbsChildren[i];
|
|
1551
|
-
if (ch.tagClass === asn1.TAG_CLASS.CONTEXT_SPECIFIC && ch.tag === 3) { //
|
|
1551
|
+
if (ch.tagClass === asn1.TAG_CLASS.CONTEXT_SPECIFIC && ch.tag === 3) { // X.509 [3] EXPLICIT extensions tag
|
|
1552
1552
|
extensionsNode = asn1.readNode(ch.value, 0);
|
|
1553
1553
|
break;
|
|
1554
1554
|
}
|
|
@@ -1605,7 +1605,7 @@ function _extractTlsFeatureExtensionFromCert(certDer) {
|
|
|
1605
1605
|
var extensionsNode = null;
|
|
1606
1606
|
for (var i = 0; i < tbsChildren.length; i += 1) {
|
|
1607
1607
|
var ch = tbsChildren[i];
|
|
1608
|
-
if (ch.tagClass === asn1.TAG_CLASS.CONTEXT_SPECIFIC && ch.tag === 3) { //
|
|
1608
|
+
if (ch.tagClass === asn1.TAG_CLASS.CONTEXT_SPECIFIC && ch.tag === 3) { // X.509 [3] EXPLICIT extensions tag
|
|
1609
1609
|
extensionsNode = asn1.readNode(ch.value, 0);
|
|
1610
1610
|
break;
|
|
1611
1611
|
}
|
|
@@ -1646,17 +1646,17 @@ function _extractTlsFeatureExtensionFromCert(certDer) {
|
|
|
1646
1646
|
// Format: 2-byte length + concatenation of individual SCTs, each
|
|
1647
1647
|
// itself prefixed by a 2-byte length.
|
|
1648
1648
|
function _parseSctList(sctListRaw) {
|
|
1649
|
-
if (!Buffer.isBuffer(sctListRaw) || sctListRaw.length < 2) { //
|
|
1649
|
+
if (!Buffer.isBuffer(sctListRaw) || sctListRaw.length < 2) { // outer 2-byte length prefix
|
|
1650
1650
|
throw new TlsTrustError("tls/ct-bad-list",
|
|
1651
1651
|
"SCT list shorter than the outer length prefix");
|
|
1652
1652
|
}
|
|
1653
1653
|
var totalLen = sctListRaw.readUInt16BE(0);
|
|
1654
|
-
if (totalLen + 2 !== sctListRaw.length) { //
|
|
1654
|
+
if (totalLen + 2 !== sctListRaw.length) { // outer length prefix
|
|
1655
1655
|
throw new TlsTrustError("tls/ct-bad-list",
|
|
1656
1656
|
"SCT list outer length " + totalLen + " does not match buffer " +
|
|
1657
1657
|
(sctListRaw.length - 2));
|
|
1658
1658
|
}
|
|
1659
|
-
var pos = 2; //
|
|
1659
|
+
var pos = 2; // past the outer prefix
|
|
1660
1660
|
var scts = [];
|
|
1661
1661
|
while (pos < sctListRaw.length) {
|
|
1662
1662
|
var sctLen = sctListRaw.readUInt16BE(pos);
|
|
@@ -1680,7 +1680,7 @@ function _parseSctList(sctListRaw) {
|
|
|
1680
1680
|
// ct_extensions (2-byte len + N) — usually empty
|
|
1681
1681
|
// signature DigitallySigned (hash + sig algo + 2-byte len + N)
|
|
1682
1682
|
function _parseSct(sctBuf) {
|
|
1683
|
-
if (sctBuf.length < 1 + 32 + 8 + 2 + 4) { //
|
|
1683
|
+
if (sctBuf.length < 1 + 32 + 8 + 2 + 4) { // minimum SCT v1 byte total
|
|
1684
1684
|
throw new TlsTrustError("tls/ct-sct-too-short",
|
|
1685
1685
|
"SCT is shorter than the minimum v1 layout (" + sctBuf.length + " bytes)");
|
|
1686
1686
|
}
|
|
@@ -1689,21 +1689,21 @@ function _parseSct(sctBuf) {
|
|
|
1689
1689
|
throw new TlsTrustError("tls/ct-sct-bad-version",
|
|
1690
1690
|
"SCT version is not 0 (v1): got " + version);
|
|
1691
1691
|
}
|
|
1692
|
-
var logId = sctBuf.slice(1, 1 + 32); //
|
|
1693
|
-
var timestamp = Number(sctBuf.readBigUInt64BE(1 + 32)); //
|
|
1694
|
-
var extLen = sctBuf.readUInt16BE(1 + 32 + 8); //
|
|
1695
|
-
var pos = 1 + 32 + 8 + 2; //
|
|
1692
|
+
var logId = sctBuf.slice(1, 1 + 32); // RFC 6962 32-byte LogID
|
|
1693
|
+
var timestamp = Number(sctBuf.readBigUInt64BE(1 + 32)); // past LogID
|
|
1694
|
+
var extLen = sctBuf.readUInt16BE(1 + 32 + 8); // past LogID + timestamp
|
|
1695
|
+
var pos = 1 + 32 + 8 + 2; // past extLen field
|
|
1696
1696
|
var extensions = sctBuf.slice(pos, pos + extLen);
|
|
1697
1697
|
pos += extLen;
|
|
1698
|
-
if (pos + 4 > sctBuf.length) { //
|
|
1698
|
+
if (pos + 4 > sctBuf.length) { // DigitallySigned header (hash + alg + len)
|
|
1699
1699
|
throw new TlsTrustError("tls/ct-sct-truncated",
|
|
1700
1700
|
"SCT truncated before DigitallySigned");
|
|
1701
1701
|
}
|
|
1702
1702
|
var hashAlgo = sctBuf[pos];
|
|
1703
1703
|
var sigAlgo = sctBuf[pos + 1];
|
|
1704
|
-
pos += 2; //
|
|
1704
|
+
pos += 2; // past hash+alg pair
|
|
1705
1705
|
var sigLen = sctBuf.readUInt16BE(pos);
|
|
1706
|
-
pos += 2; //
|
|
1706
|
+
pos += 2; // past sig length
|
|
1707
1707
|
if (pos + sigLen !== sctBuf.length) {
|
|
1708
1708
|
throw new TlsTrustError("tls/ct-sct-truncated",
|
|
1709
1709
|
"SCT signature length " + sigLen + " does not match remaining bytes " +
|
|
@@ -1729,18 +1729,18 @@ function _parseSct(sctBuf) {
|
|
|
1729
1729
|
// signed_entry (3-byte length || ASN.1 cert without SCT extension) ||
|
|
1730
1730
|
// ct_extensions (2-byte length || N)
|
|
1731
1731
|
function _buildSctSignedEntry(certWithoutSctDer, sct) {
|
|
1732
|
-
var head = Buffer.alloc(1 + 1 + 8 + 2); //
|
|
1732
|
+
var head = Buffer.alloc(1 + 1 + 8 + 2); // fixed-shape header bytes
|
|
1733
1733
|
head[0] = sct.version;
|
|
1734
1734
|
head[1] = 0; // signature_type = certificate_timestamp
|
|
1735
|
-
head.writeBigUInt64BE(BigInt(sct.timestamp), 2); //
|
|
1736
|
-
head.writeUInt16BE(0, 10); //
|
|
1735
|
+
head.writeBigUInt64BE(BigInt(sct.timestamp), 2); // past version+sig-type
|
|
1736
|
+
head.writeUInt16BE(0, 10); // entry_type = x509_entry (2 bytes; high byte = 0, low byte = 0)
|
|
1737
1737
|
// signed_entry: 3-byte length prefix + cert DER.
|
|
1738
|
-
var lenBytes = Buffer.alloc(3); //
|
|
1739
|
-
lenBytes[0] = (certWithoutSctDer.length >> 16) & 0xff; //
|
|
1740
|
-
lenBytes[1] = (certWithoutSctDer.length >> 8) & 0xff; //
|
|
1741
|
-
lenBytes[2] = certWithoutSctDer.length & 0xff; //
|
|
1738
|
+
var lenBytes = Buffer.alloc(3); // RFC 6962 24-bit length prefix
|
|
1739
|
+
lenBytes[0] = (certWithoutSctDer.length >> 16) & 0xff; // base-256 length high byte
|
|
1740
|
+
lenBytes[1] = (certWithoutSctDer.length >> 8) & 0xff; // base-256 length mid byte
|
|
1741
|
+
lenBytes[2] = certWithoutSctDer.length & 0xff; // base-256 length low byte
|
|
1742
1742
|
// ct_extensions: 2-byte length + bytes.
|
|
1743
|
-
var extHead = Buffer.alloc(2); //
|
|
1743
|
+
var extHead = Buffer.alloc(2); // RFC 6962 2-byte ct_extensions length prefix
|
|
1744
1744
|
extHead.writeUInt16BE(sct.extensions.length, 0);
|
|
1745
1745
|
return Buffer.concat([head, lenBytes, certWithoutSctDer, extHead, sct.extensions]);
|
|
1746
1746
|
}
|
|
@@ -1781,7 +1781,7 @@ function _stripSctExtensionFromCert(certDer) {
|
|
|
1781
1781
|
var foundExtensions = false;
|
|
1782
1782
|
for (var i = 0; i < tbsChildren.length; i += 1) {
|
|
1783
1783
|
var ch = tbsChildren[i];
|
|
1784
|
-
if (ch.tagClass === asn1.TAG_CLASS.CONTEXT_SPECIFIC && ch.tag === 3) { //
|
|
1784
|
+
if (ch.tagClass === asn1.TAG_CLASS.CONTEXT_SPECIFIC && ch.tag === 3) { // [3] EXPLICIT extensions tag
|
|
1785
1785
|
foundExtensions = true;
|
|
1786
1786
|
// Inner SEQUENCE OF Extensions.
|
|
1787
1787
|
var inner = asn1.readNode(ch.value, 0);
|
|
@@ -1828,22 +1828,22 @@ function _stripSctExtensionFromCert(certDer) {
|
|
|
1828
1828
|
// SCT extension. Tag class is universal for SEQUENCE; constructed
|
|
1829
1829
|
// flag wired explicitly.
|
|
1830
1830
|
function _encodeLength(len) {
|
|
1831
|
-
if (len < 0x80) return Buffer.from([len]); //
|
|
1831
|
+
if (len < 0x80) return Buffer.from([len]); // DER short-form length threshold
|
|
1832
1832
|
var tmp = [];
|
|
1833
1833
|
var n = len;
|
|
1834
1834
|
while (n > 0) {
|
|
1835
|
-
tmp.unshift(n & 0xff); //
|
|
1836
|
-
n = n >>> 8; //
|
|
1835
|
+
tmp.unshift(n & 0xff); // base-256 byte
|
|
1836
|
+
n = n >>> 8; // byte shift
|
|
1837
1837
|
}
|
|
1838
|
-
return Buffer.concat([Buffer.from([0x80 | tmp.length]), Buffer.from(tmp)]); //
|
|
1838
|
+
return Buffer.concat([Buffer.from([0x80 | tmp.length]), Buffer.from(tmp)]); // DER long-form length flag
|
|
1839
1839
|
}
|
|
1840
1840
|
function _encodeAsn1(tag, constructed, value) {
|
|
1841
|
-
var tagByte = (constructed ? 0x20 : 0x00) | tag; //
|
|
1841
|
+
var tagByte = (constructed ? 0x20 : 0x00) | tag; // DER constructed bit + universal tag
|
|
1842
1842
|
return Buffer.concat([Buffer.from([tagByte]), _encodeLength(value.length), value]);
|
|
1843
1843
|
}
|
|
1844
1844
|
function _encodeContextExplicit(num, value) {
|
|
1845
1845
|
// Context-specific class (10) + constructed (20) | tag.
|
|
1846
|
-
var tagByte = 0xa0 | num; //
|
|
1846
|
+
var tagByte = 0xa0 | num; // DER context-specific + constructed
|
|
1847
1847
|
return Buffer.concat([Buffer.from([tagByte]), _encodeLength(value.length), value]);
|
|
1848
1848
|
}
|
|
1849
1849
|
function _encodeAsn1FromNode(node) {
|
|
@@ -1854,10 +1854,10 @@ function _encodeAsn1FromNode(node) {
|
|
|
1854
1854
|
// restored directly. This works for the simple shapes we walk.
|
|
1855
1855
|
var tagByte;
|
|
1856
1856
|
if (node.tagClass === asn1.TAG_CLASS.UNIVERSAL) {
|
|
1857
|
-
tagByte = (node.constructed ? 0x20 : 0x00) | (node.tag & 0x1f); //
|
|
1857
|
+
tagByte = (node.constructed ? 0x20 : 0x00) | (node.tag & 0x1f); // DER constructed bit + universal tag
|
|
1858
1858
|
} else {
|
|
1859
|
-
var classBits = (node.tagClass & 0x03) << 6; //
|
|
1860
|
-
tagByte = classBits | (node.constructed ? 0x20 : 0x00) | (node.tag & 0x1f); //
|
|
1859
|
+
var classBits = (node.tagClass & 0x03) << 6; // DER tag-class bits
|
|
1860
|
+
tagByte = classBits | (node.constructed ? 0x20 : 0x00) | (node.tag & 0x1f); // DER constructed bit + low-tag
|
|
1861
1861
|
}
|
|
1862
1862
|
return Buffer.concat([Buffer.from([tagByte]), _encodeLength(node.value.length), node.value]);
|
|
1863
1863
|
}
|
|
@@ -1874,7 +1874,7 @@ function verifyScts(certDer, opts) {
|
|
|
1874
1874
|
"verifyScts: certDer must be a Buffer");
|
|
1875
1875
|
}
|
|
1876
1876
|
var logKeys = opts.logKeys || {};
|
|
1877
|
-
var minScts = typeof opts.minScts === "number" ? opts.minScts : 2; //
|
|
1877
|
+
var minScts = typeof opts.minScts === "number" ? opts.minScts : 2; // Chrome CT policy min-2-SCTs
|
|
1878
1878
|
var ext = _extractSctExtensionFromCert(certDer);
|
|
1879
1879
|
if (!ext.sctListRaw) {
|
|
1880
1880
|
return { ok: false, reason: "no-sct-extension", scts: [] };
|
|
@@ -1910,9 +1910,9 @@ function verifyScts(certDer, opts) {
|
|
|
1910
1910
|
error: (e && e.message) || String(e) });
|
|
1911
1911
|
continue;
|
|
1912
1912
|
}
|
|
1913
|
-
var nodeAlgo = sct.hashAlgo === 4 ? "sha256" : //
|
|
1914
|
-
sct.hashAlgo === 5 ? "sha384" : //
|
|
1915
|
-
sct.hashAlgo === 6 ? "sha512" : //
|
|
1913
|
+
var nodeAlgo = sct.hashAlgo === 4 ? "sha256" : // TLS 1.2 HashAlgorithm enum sha256
|
|
1914
|
+
sct.hashAlgo === 5 ? "sha384" : // TLS 1.2 HashAlgorithm enum sha384
|
|
1915
|
+
sct.hashAlgo === 6 ? "sha512" : // TLS 1.2 HashAlgorithm enum sha512
|
|
1916
1916
|
null;
|
|
1917
1917
|
if (nodeAlgo === null) {
|
|
1918
1918
|
perSctResults.push({ logIdHex: sct.logIdHex, verified: false,
|
|
@@ -1934,8 +1934,8 @@ function verifyScts(certDer, opts) {
|
|
|
1934
1934
|
// under one algorithm against a key registered under another.
|
|
1935
1935
|
var keyType = keyObj.asymmetricKeyType;
|
|
1936
1936
|
var sctSigAlgo = sct.signatureAlgo;
|
|
1937
|
-
var algoOk = (sctSigAlgo === 1 && keyType === "rsa") || //
|
|
1938
|
-
(sctSigAlgo === 3 && (keyType === "ec" || keyType === "ecdsa")); //
|
|
1937
|
+
var algoOk = (sctSigAlgo === 1 && keyType === "rsa") || // TLS 1.2 SignatureAlgorithm rsa
|
|
1938
|
+
(sctSigAlgo === 3 && (keyType === "ec" || keyType === "ecdsa")); // TLS 1.2 SignatureAlgorithm ecdsa
|
|
1939
1939
|
if (!algoOk) {
|
|
1940
1940
|
perSctResults.push({ logIdHex: sct.logIdHex, verified: false,
|
|
1941
1941
|
reason: "log-key-algo-mismatch",
|
|
@@ -2025,7 +2025,7 @@ function _ctLargestPowerOf2LessThan(n) {
|
|
|
2025
2025
|
// returns: Buffer (32 bytes) — computed root hash to compare
|
|
2026
2026
|
// throws: TlsTrustError on shape errors
|
|
2027
2027
|
function _ctVerifyInclusionPath(leafHash, leafIndex, treeSize, auditPath) {
|
|
2028
|
-
if (!Buffer.isBuffer(leafHash) || leafHash.length !== 32) { //
|
|
2028
|
+
if (!Buffer.isBuffer(leafHash) || leafHash.length !== 32) { // RFC 9162 SHA-256 digest length
|
|
2029
2029
|
throw new TlsTrustError("tls/ct-bad-leaf-hash",
|
|
2030
2030
|
"ct.verifyInclusion: leafHash must be a 32-byte Buffer");
|
|
2031
2031
|
}
|
|
@@ -2056,7 +2056,7 @@ function _ctVerifyInclusionPath(leafHash, leafIndex, treeSize, auditPath) {
|
|
|
2056
2056
|
"ct.verifyInclusion: audit path exhausted before tree root reached");
|
|
2057
2057
|
}
|
|
2058
2058
|
var sibling = auditPath[pathPos++];
|
|
2059
|
-
if (!Buffer.isBuffer(sibling) || sibling.length !== 32) { //
|
|
2059
|
+
if (!Buffer.isBuffer(sibling) || sibling.length !== 32) { // RFC 9162 SHA-256 digest length
|
|
2060
2060
|
throw new TlsTrustError("tls/ct-bad-audit-path",
|
|
2061
2061
|
"ct.verifyInclusion: audit path entry " + (pathPos - 1) + " is not a 32-byte Buffer");
|
|
2062
2062
|
}
|
|
@@ -2092,7 +2092,7 @@ function _ctVerifyConsistencyPath(m, n, consistencyProof, firstHash) {
|
|
|
2092
2092
|
throw new TlsTrustError("tls/ct-bad-second-size",
|
|
2093
2093
|
"ct.verifyConsistency: n (second tree size) must be an integer >= m");
|
|
2094
2094
|
}
|
|
2095
|
-
if (!Buffer.isBuffer(firstHash) || firstHash.length !== 32) { //
|
|
2095
|
+
if (!Buffer.isBuffer(firstHash) || firstHash.length !== 32) { // RFC 9162 SHA-256 digest length
|
|
2096
2096
|
throw new TlsTrustError("tls/ct-bad-first-hash",
|
|
2097
2097
|
"ct.verifyConsistency: firstHash must be a 32-byte Buffer");
|
|
2098
2098
|
}
|
|
@@ -2127,7 +2127,7 @@ function _ctVerifyConsistencyPath(m, n, consistencyProof, firstHash) {
|
|
|
2127
2127
|
"ct.verifyConsistency: consistency proof exhausted before second-tree root");
|
|
2128
2128
|
}
|
|
2129
2129
|
var sibling = path.shift();
|
|
2130
|
-
if (!Buffer.isBuffer(sibling) || sibling.length !== 32) { //
|
|
2130
|
+
if (!Buffer.isBuffer(sibling) || sibling.length !== 32) { // RFC 9162 SHA-256 digest length
|
|
2131
2131
|
throw new TlsTrustError("tls/ct-bad-consistency-entry",
|
|
2132
2132
|
"ct.verifyConsistency: consistency-proof entry is not a 32-byte Buffer");
|
|
2133
2133
|
}
|
|
@@ -2249,13 +2249,13 @@ var ct = Object.freeze({
|
|
|
2249
2249
|
if (typeof ts !== "number" && typeof ts !== "bigint") {
|
|
2250
2250
|
return { valid: false, reason: "bad-sct-timestamp" };
|
|
2251
2251
|
}
|
|
2252
|
-
var tsBuf = Buffer.alloc(8); //
|
|
2252
|
+
var tsBuf = Buffer.alloc(8); // TLS uint64 width
|
|
2253
2253
|
var tsBig = typeof ts === "bigint" ? ts : BigInt(Math.floor(ts));
|
|
2254
2254
|
tsBuf.writeBigUInt64BE(tsBig);
|
|
2255
2255
|
var entryTypeBuf = Buffer.from([0x00, 0x00]);
|
|
2256
|
-
var lenBuf = Buffer.alloc(3); //
|
|
2256
|
+
var lenBuf = Buffer.alloc(3); // TLS uint24 length prefix
|
|
2257
2257
|
lenBuf.writeUIntBE(signedEntryDer.length, 0, 3);
|
|
2258
|
-
var extensionsBuf = Buffer.from([0x00, 0x00]); //
|
|
2258
|
+
var extensionsBuf = Buffer.from([0x00, 0x00]); // empty extensions vector
|
|
2259
2259
|
var leafBytes = Buffer.concat([
|
|
2260
2260
|
Buffer.from([0x00]), // version v1
|
|
2261
2261
|
Buffer.from([0x00]), // leaf_type timestamped_entry
|
|
@@ -2281,7 +2281,7 @@ var ct = Object.freeze({
|
|
|
2281
2281
|
try { sthRoot = Buffer.from(sthRoot, "hex"); }
|
|
2282
2282
|
catch (_e) { return { valid: false, reason: "bad-sth-root-encoding" }; }
|
|
2283
2283
|
}
|
|
2284
|
-
if (!Buffer.isBuffer(sthRoot) || sthRoot.length !== 32) { //
|
|
2284
|
+
if (!Buffer.isBuffer(sthRoot) || sthRoot.length !== 32) { // RFC 9162 SHA-256 digest length
|
|
2285
2285
|
return { valid: false, reason: "bad-sth-root" };
|
|
2286
2286
|
}
|
|
2287
2287
|
if (!bCrypto.timingSafeEqual(computedRoot, sthRoot)) {
|
|
@@ -2344,10 +2344,10 @@ var ct = Object.freeze({
|
|
|
2344
2344
|
try { secondRoot = Buffer.from(secondRoot, "hex"); }
|
|
2345
2345
|
catch (_e) { return { valid: false, reason: "bad-second-root-encoding" }; }
|
|
2346
2346
|
}
|
|
2347
|
-
if (!Buffer.isBuffer(firstRoot) || firstRoot.length !== 32) { //
|
|
2347
|
+
if (!Buffer.isBuffer(firstRoot) || firstRoot.length !== 32) { // RFC 9162 SHA-256 digest length
|
|
2348
2348
|
return { valid: false, reason: "bad-first-root" };
|
|
2349
2349
|
}
|
|
2350
|
-
if (!Buffer.isBuffer(secondRoot) || secondRoot.length !== 32) { //
|
|
2350
|
+
if (!Buffer.isBuffer(secondRoot) || secondRoot.length !== 32) { // RFC 9162 SHA-256 digest length
|
|
2351
2351
|
return { valid: false, reason: "bad-second-root" };
|
|
2352
2352
|
}
|
|
2353
2353
|
var computed;
|
|
@@ -2416,7 +2416,7 @@ var ct = Object.freeze({
|
|
|
2416
2416
|
// each (uint16 kdf_id, uint16
|
|
2417
2417
|
// aead_id) — 4 bytes apiece)
|
|
2418
2418
|
|
|
2419
|
-
var ECH_CONFIG_VERSION_DRAFT_22 = 0xfe0d; //
|
|
2419
|
+
var ECH_CONFIG_VERSION_DRAFT_22 = 0xfe0d; // draft-ietf-tls-esni-22 ECH version codepoint
|
|
2420
2420
|
|
|
2421
2421
|
function _echReadU8(buf, off) {
|
|
2422
2422
|
if (off + 1 > buf.length) {
|
|
@@ -2426,7 +2426,7 @@ function _echReadU8(buf, off) {
|
|
|
2426
2426
|
return buf[off];
|
|
2427
2427
|
}
|
|
2428
2428
|
function _echReadU16(buf, off) {
|
|
2429
|
-
if (off + 2 > buf.length) { //
|
|
2429
|
+
if (off + 2 > buf.length) { // uint16 width
|
|
2430
2430
|
throw new NetworkTlsError("tls/ech-config-malformed",
|
|
2431
2431
|
"ECHConfigList: truncated reading uint16 at offset " + off);
|
|
2432
2432
|
}
|
|
@@ -2434,7 +2434,7 @@ function _echReadU16(buf, off) {
|
|
|
2434
2434
|
}
|
|
2435
2435
|
function _echReadVarOpaqueU16(buf, off) {
|
|
2436
2436
|
var len = _echReadU16(buf, off);
|
|
2437
|
-
off += 2; //
|
|
2437
|
+
off += 2; // uint16 length-prefix width
|
|
2438
2438
|
if (off + len > buf.length) {
|
|
2439
2439
|
throw new NetworkTlsError("tls/ech-config-malformed",
|
|
2440
2440
|
"ECHConfigList: opaque vector overflows buffer (declared " + len +
|
|
@@ -2500,20 +2500,20 @@ function parseEchConfigList(raw) {
|
|
|
2500
2500
|
throw new NetworkTlsError("tls/ech-config-malformed",
|
|
2501
2501
|
"parseEchConfigList: input must be a non-empty Buffer or base64 string");
|
|
2502
2502
|
}
|
|
2503
|
-
if (raw.length < 2) { //
|
|
2503
|
+
if (raw.length < 2) { // uint16 outer length prefix
|
|
2504
2504
|
throw new NetworkTlsError("tls/ech-config-malformed",
|
|
2505
2505
|
"ECHConfigList: too short for outer length prefix");
|
|
2506
2506
|
}
|
|
2507
2507
|
var totalLen = raw.readUInt16BE(0);
|
|
2508
|
-
if (2 + totalLen !== raw.length) { //
|
|
2508
|
+
if (2 + totalLen !== raw.length) { // uint16 prefix width
|
|
2509
2509
|
throw new NetworkTlsError("tls/ech-config-malformed",
|
|
2510
2510
|
"ECHConfigList: outer length " + totalLen + " does not match buffer " +
|
|
2511
2511
|
"tail length " + (raw.length - 2));
|
|
2512
2512
|
}
|
|
2513
|
-
var off = 2; //
|
|
2513
|
+
var off = 2; // uint16 prefix width
|
|
2514
2514
|
var configs = [];
|
|
2515
2515
|
while (off < raw.length) {
|
|
2516
|
-
if (off + 4 > raw.length) { //
|
|
2516
|
+
if (off + 4 > raw.length) { // uint16 ver + uint16 len
|
|
2517
2517
|
throw new NetworkTlsError("tls/ech-config-malformed",
|
|
2518
2518
|
"ECHConfig: truncated header at offset " + off);
|
|
2519
2519
|
}
|
|
@@ -2530,19 +2530,19 @@ function parseEchConfigList(raw) {
|
|
|
2530
2530
|
var p = bodyOff;
|
|
2531
2531
|
// HpkeKeyConfig
|
|
2532
2532
|
var configId = _echReadU8(raw, p); p += 1;
|
|
2533
|
-
var kemId = _echReadU16(raw, p); p += 2; //
|
|
2533
|
+
var kemId = _echReadU16(raw, p); p += 2; // uint16 KEM id width
|
|
2534
2534
|
var pkOpaque = _echReadVarOpaqueU16(raw, p); p = pkOpaque.nextOff;
|
|
2535
|
-
var suitesLen = _echReadU16(raw, p); p += 2; //
|
|
2535
|
+
var suitesLen = _echReadU16(raw, p); p += 2; // uint16 length prefix width
|
|
2536
2536
|
if (p + suitesLen > bodyEnd) {
|
|
2537
2537
|
throw new NetworkTlsError("tls/ech-config-malformed",
|
|
2538
2538
|
"ECHConfig: cipher_suites vector overflows config body");
|
|
2539
2539
|
}
|
|
2540
|
-
if (suitesLen % 4 !== 0 || suitesLen < 4) { //
|
|
2540
|
+
if (suitesLen % 4 !== 0 || suitesLen < 4) { // kdf+aead = 4 bytes per suite
|
|
2541
2541
|
throw new NetworkTlsError("tls/ech-config-malformed",
|
|
2542
2542
|
"ECHConfig: cipher_suites length must be a positive multiple of 4");
|
|
2543
2543
|
}
|
|
2544
2544
|
var suites = [];
|
|
2545
|
-
for (var sp = p; sp < p + suitesLen; sp += 4) { //
|
|
2545
|
+
for (var sp = p; sp < p + suitesLen; sp += 4) { // 4-byte cipher suite stride
|
|
2546
2546
|
suites.push({
|
|
2547
2547
|
kdfId: raw.readUInt16BE(sp),
|
|
2548
2548
|
aeadId: raw.readUInt16BE(sp + 2),
|
|
@@ -2552,7 +2552,7 @@ function parseEchConfigList(raw) {
|
|
|
2552
2552
|
// remainder of contents
|
|
2553
2553
|
var maxNameLen = _echReadU8(raw, p); p += 1;
|
|
2554
2554
|
var publicName = _echReadVarOpaqueU8(raw, p); p = publicName.nextOff;
|
|
2555
|
-
var extLen = _echReadU16(raw, p); p += 2; //
|
|
2555
|
+
var extLen = _echReadU16(raw, p); p += 2; // uint16 length prefix width
|
|
2556
2556
|
if (p + extLen !== bodyEnd) {
|
|
2557
2557
|
throw new NetworkTlsError("tls/ech-config-malformed",
|
|
2558
2558
|
"ECHConfig: extensions vector does not consume remaining body " +
|
|
@@ -2561,7 +2561,7 @@ function parseEchConfigList(raw) {
|
|
|
2561
2561
|
var extensions = [];
|
|
2562
2562
|
var extEnd = p + extLen;
|
|
2563
2563
|
while (p < extEnd) {
|
|
2564
|
-
var extType = _echReadU16(raw, p); p += 2; //
|
|
2564
|
+
var extType = _echReadU16(raw, p); p += 2; // uint16 ext type
|
|
2565
2565
|
var extData = _echReadVarOpaqueU16(raw, p); p = extData.nextOff;
|
|
2566
2566
|
extensions.push({ type: extType, data: extData.value });
|
|
2567
2567
|
}
|
|
@@ -2685,9 +2685,9 @@ function connectWithEch(opts) {
|
|
|
2685
2685
|
"network.tls.connectWithEch");
|
|
2686
2686
|
validateOpts.requireNonEmptyString(opts.host, "connectWithEch: host",
|
|
2687
2687
|
NetworkTlsError, "tls/ech-bad-opts");
|
|
2688
|
-
var port = opts.port === undefined ? 443 : opts.port; //
|
|
2688
|
+
var port = opts.port === undefined ? 443 : opts.port; // HTTPS default port
|
|
2689
2689
|
if (typeof port !== "number" || !isFinite(port) ||
|
|
2690
|
-
port <= 0 || port > 65535 || Math.floor(port) !== port) { //
|
|
2690
|
+
port <= 0 || port > 65535 || Math.floor(port) !== port) { // TCP port range
|
|
2691
2691
|
throw new NetworkTlsError("tls/ech-bad-opts",
|
|
2692
2692
|
"connectWithEch: port must be an integer in 1..65535");
|
|
2693
2693
|
}
|
|
@@ -2874,7 +2874,7 @@ function _normalizeAsciiHost(host) {
|
|
|
2874
2874
|
if (typeof host !== "string" || host.length === 0) return null;
|
|
2875
2875
|
for (var i = 0; i < host.length; i += 1) {
|
|
2876
2876
|
var cc = host.charCodeAt(i);
|
|
2877
|
-
if (cc > 0x7f) return null; //
|
|
2877
|
+
if (cc > 0x7f) return null; // ASCII upper bound codepoint
|
|
2878
2878
|
}
|
|
2879
2879
|
// Strip a trailing dot (FQDN absolute form) for matching.
|
|
2880
2880
|
var h = host.toLowerCase();
|
|
@@ -2975,17 +2975,17 @@ function _ipv6ToBytes(addr) {
|
|
|
2975
2975
|
];
|
|
2976
2976
|
}
|
|
2977
2977
|
var left = halves[0], right = halves[1];
|
|
2978
|
-
var fillCount = 8 - (left.length + right.length); //
|
|
2978
|
+
var fillCount = 8 - (left.length + right.length); // IPv6 has 8 hextets
|
|
2979
2979
|
if (fillCount < 0) return null;
|
|
2980
2980
|
var hextets = left.concat(new Array(fillCount).fill("0")).concat(right);
|
|
2981
|
-
if (hextets.length !== 8) return null; //
|
|
2982
|
-
var bytes = Buffer.alloc(16); //
|
|
2983
|
-
for (var i = 0; i < 8; i += 1) { //
|
|
2981
|
+
if (hextets.length !== 8) return null; // IPv6 hextet count
|
|
2982
|
+
var bytes = Buffer.alloc(16); // IPv6 = 16 bytes
|
|
2983
|
+
for (var i = 0; i < 8; i += 1) { // IPv6 hextet count
|
|
2984
2984
|
var h = hextets[i];
|
|
2985
2985
|
if (!safeBuffer.IPV6_HEXTET_RE.test(h)) return null;
|
|
2986
|
-
var v = parseInt(h, 16); //
|
|
2987
|
-
bytes[i * 2] = (v >> 8) & 0xff; //
|
|
2988
|
-
bytes[i * 2 + 1] = v & 0xff; //
|
|
2986
|
+
var v = parseInt(h, 16); // hex radix
|
|
2987
|
+
bytes[i * 2] = (v >> 8) & 0xff; // uint8 mask + uint16-half shift
|
|
2988
|
+
bytes[i * 2 + 1] = v & 0xff; // uint8 mask
|
|
2989
2989
|
}
|
|
2990
2990
|
return bytes;
|
|
2991
2991
|
}
|
|
@@ -3066,9 +3066,13 @@ function checkServerIdentity9525(host, cert) {
|
|
|
3066
3066
|
}
|
|
3067
3067
|
var rawSan = cert.subjectaltname;
|
|
3068
3068
|
if (typeof rawSan !== "string" || rawSan.length === 0) {
|
|
3069
|
-
// RFC 9525 §6.4.4 forbids CN fallback.
|
|
3070
|
-
//
|
|
3071
|
-
//
|
|
3069
|
+
// RFC 9525 §6.4.4 forbids CN fallback. A CN-only legacy cert (CN
|
|
3070
|
+
// present, no SAN) surfaces the distinct `tls/pkix-cn-fallback-refused`
|
|
3071
|
+
// code so audit logs can tell it apart from a cert carrying neither;
|
|
3072
|
+
// a cert with no SAN and no CN falls through to `tls/pkix-san-required`.
|
|
3073
|
+
// Both refuse — we never fall back to matching on the Common Name.
|
|
3074
|
+
var cnRefusal = _refuseCnFallback(host, cert);
|
|
3075
|
+
if (cnRefusal) return cnRefusal;
|
|
3072
3076
|
return new NetworkTlsError("tls/pkix-san-required",
|
|
3073
3077
|
"checkServerIdentity9525: certificate has no subjectAltName " +
|
|
3074
3078
|
"extension (RFC 9525 §6.4.4 forbids Common Name fallback)");
|
|
@@ -3117,10 +3121,11 @@ function _refuseCnFallback(host, cert) {
|
|
|
3117
3121
|
return null;
|
|
3118
3122
|
}
|
|
3119
3123
|
|
|
3120
|
-
//
|
|
3121
|
-
//
|
|
3122
|
-
//
|
|
3123
|
-
//
|
|
3124
|
+
// Explicit combined verifier kept for tests + callers that want the
|
|
3125
|
+
// CN-fallback / SAN-required split spelled out. The exported drop-in
|
|
3126
|
+
// `checkServerIdentity9525` already performs the CN-fallback refusal in
|
|
3127
|
+
// its no-SAN branch, so the `_refuseCnFallback` call here is a redundant
|
|
3128
|
+
// (idempotent) belt-and-suspenders; the more specific code wins either way.
|
|
3124
3129
|
function _checkServerIdentityStrict(host, cert) {
|
|
3125
3130
|
var cnRefusal = _refuseCnFallback(host, cert);
|
|
3126
3131
|
if (cnRefusal) return cnRefusal;
|