@blamejs/pki 0.6.13 → 0.6.15
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 +22 -1
- package/README.md +1 -1
- package/index.js +1 -1
- package/lib/acme.js +59 -815
- package/lib/asn1-der.js +7 -245
- package/lib/attrcert-sign.js +12 -260
- package/lib/attrcert-verify.js +1 -7
- package/lib/byte-reader.js +0 -8
- package/lib/byte-writer.js +0 -11
- package/lib/cbor-det.js +0 -54
- package/lib/cmc-build.js +15 -357
- package/lib/cmc-verify.js +6 -239
- package/lib/cmp-build.js +41 -317
- package/lib/cmp-session.js +73 -760
- package/lib/cmp-verify.js +32 -488
- package/lib/cms-compress.js +3 -32
- package/lib/cms-decrypt.js +29 -294
- package/lib/cms-encrypt.js +14 -234
- package/lib/cms-sign.js +29 -324
- package/lib/cms-verify.js +9 -500
- package/lib/composite-kem.js +2 -102
- package/lib/composite-sig.js +1 -77
- package/lib/constants.js +0 -249
- package/lib/crl-sign.js +9 -237
- package/lib/crl-verify.js +1 -10
- package/lib/crmf-sign.js +19 -198
- package/lib/crmf-verify.js +1 -12
- package/lib/csr-sign.js +3 -34
- package/lib/csr-verify.js +1 -12
- package/lib/ct.js +28 -253
- package/lib/edwards-point.js +10 -44
- package/lib/est.js +28 -764
- package/lib/framework-error.js +4 -182
- package/lib/guard-all.js +1 -58
- package/lib/guard-async.js +1 -36
- package/lib/guard-bytes.js +6 -650
- package/lib/guard-compress.js +5 -102
- package/lib/guard-crypto.js +1 -40
- package/lib/guard-der.js +2 -93
- package/lib/guard-encoding.js +2 -60
- package/lib/guard-header.js +1 -36
- package/lib/guard-identifier.js +7 -531
- package/lib/guard-intrinsic.js +1 -150
- package/lib/guard-json.js +10 -73
- package/lib/guard-limits.js +1 -77
- package/lib/guard-list.js +1 -49
- package/lib/guard-name.js +3 -209
- package/lib/guard-parsed.js +7 -335
- package/lib/guard-range.js +1 -71
- package/lib/guard-secret.js +1 -102
- package/lib/guard-text.js +1 -64
- package/lib/guard-time.js +1 -97
- package/lib/hpke.js +3 -105
- package/lib/http-digest.js +14 -142
- package/lib/http-retry-after.js +1 -47
- package/lib/http-transport.js +21 -131
- package/lib/inspect.js +30 -284
- package/lib/ip-utils.js +6 -47
- package/lib/jose.js +7 -142
- package/lib/key.js +2 -67
- package/lib/lint.js +9 -194
- package/lib/merkle.js +1 -27
- package/lib/mime.js +9 -82
- package/lib/ocsp-request-verify.js +1 -14
- package/lib/ocsp-verify.js +1 -82
- package/lib/ocsp.js +11 -169
- package/lib/oid.js +5 -337
- package/lib/path-validate.js +103 -1492
- package/lib/pbes2.js +2 -89
- package/lib/pkcs12-build.js +31 -379
- package/lib/pki-build.js +64 -290
- package/lib/rc2.js +2 -18
- package/lib/rfc3339.js +4 -27
- package/lib/scep.js +59 -233
- package/lib/schema-all.js +0 -122
- package/lib/schema-attrcert.js +4 -146
- package/lib/schema-c509.js +153 -802
- package/lib/schema-cmc.js +5 -220
- package/lib/schema-cmp.js +2 -223
- package/lib/schema-cms.js +13 -427
- package/lib/schema-crl.js +5 -68
- package/lib/schema-crmf.js +6 -167
- package/lib/schema-csr.js +1 -54
- package/lib/schema-csrattrs.js +2 -87
- package/lib/schema-engine.js +0 -152
- package/lib/schema-ocsp.js +0 -117
- package/lib/schema-pkcs12.js +2 -93
- package/lib/schema-pkcs8.js +3 -35
- package/lib/schema-pkix.js +24 -655
- package/lib/schema-smime.js +0 -54
- package/lib/schema-tsp.js +3 -99
- package/lib/schema-x509.js +4 -63
- package/lib/shbs.js +11 -95
- package/lib/sign-scheme.js +2 -97
- package/lib/sigstore.js +9 -169
- package/lib/sleep.js +2 -8
- package/lib/smime.js +15 -408
- package/lib/tls-cert-compress.js +0 -62
- package/lib/trust.js +19 -185
- package/lib/tsp-sign.js +16 -270
- package/lib/validator-all.js +1 -30
- package/lib/validator-attcert.js +2 -46
- package/lib/validator-cose.js +2 -153
- package/lib/validator-keydesc.js +1 -37
- package/lib/validator-sig.js +1 -46
- package/lib/validator-tls.js +1 -88
- package/lib/validator-tpm.js +19 -122
- package/lib/verify-seam.js +1 -24
- package/lib/webauthn-mds.js +3 -400
- package/lib/webauthn.js +12 -833
- package/lib/webcrypto.js +5 -485
- package/lib/x509-sign.js +4 -108
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
package/lib/schema-ocsp.js
CHANGED
|
@@ -40,53 +40,30 @@ var oid = require("./oid");
|
|
|
40
40
|
var constants = require("./constants");
|
|
41
41
|
var frameworkError = require("./framework-error");
|
|
42
42
|
var intrinsic = require("./guard-intrinsic");
|
|
43
|
-
// Own-key membership through an operation taken at load. Written out, the question reads two
|
|
44
|
-
// replaceable properties to answer one thing, and here it decides which response statuses and
|
|
45
|
-
// revocation reasons are defined -- an admitted name names a status RFC 6960 never assigned.
|
|
46
43
|
var _hasOwn = intrinsic.hasOwn;
|
|
47
44
|
|
|
48
45
|
var OcspError = frameworkError.OcspError;
|
|
49
46
|
var PemError = frameworkError.PemError;
|
|
50
47
|
|
|
51
|
-
// The ocsp error namespace the schema engine walks under.
|
|
52
48
|
var NS = pkix.makeNS("ocsp", OcspError, oid);
|
|
53
49
|
|
|
54
50
|
var ALGORITHM_IDENTIFIER = pkix.algorithmIdentifier(NS);
|
|
55
51
|
var NAME = pkix.name(NS);
|
|
56
52
|
var EXTENSIONS = pkix.extensions(NS);
|
|
57
53
|
|
|
58
|
-
// Version ::= INTEGER { v1(0) }. OCSP defines only v1(0), which DER forbids
|
|
59
|
-
// encoding (it is the DEFAULT), so ANY explicitly-encoded version is a fault; the
|
|
60
|
-
// empty accept map rejects every value and absence yields the default 1.
|
|
61
54
|
var VERSION = pkix.versionReader(NS, {});
|
|
62
55
|
|
|
63
|
-
// id-pkix-ocsp-basic is the one ResponseBytes.responseType this build decodes; any
|
|
64
|
-
// other is recognized-and-deferred. Resolved from the registry, never a literal.
|
|
65
56
|
var OID_OCSP_BASIC = oid.byName("ocspBasic");
|
|
66
57
|
|
|
67
|
-
// id-pkix-ocsp-nonce -- the request/response binding extension whose value syntax
|
|
68
|
-
// RFC 9654 sec. 2.1 (updating RFC 6960 sec. 4.4.1) fixes to OCTET STRING (SIZE(1..128)).
|
|
69
58
|
var OID_OCSP_NONCE = oid.byName("ocspNonce");
|
|
70
59
|
|
|
71
|
-
// OCSPResponseStatus ::= ENUMERATED. Value 4 is "not used" and >= 7 is undefined,
|
|
72
|
-
// so both are rejected (RFC 6960 sec. 4.2.1).
|
|
73
|
-
// OCSPResponseStatus value names -- single source pki.C.NAMES.OCSP_STATUS.
|
|
74
60
|
var STATUS_NAMES = constants.NAMES.OCSP_STATUS;
|
|
75
61
|
|
|
76
|
-
// CRLReason ::= ENUMERATED. Value 7 is "not used"; the rest are RFC 5280
|
|
77
|
-
// sec. 5.3.1. The legal set + names live once in pkix.CRL_REASON_NAMES (shared
|
|
78
|
-
// with the CRL reasonCode decoder, which surfaces the numeric code).
|
|
79
62
|
var CRL_REASONS = pkix.CRL_REASON_NAMES;
|
|
80
63
|
|
|
81
|
-
// ---- shared leaves ---------------------------------------------------
|
|
82
64
|
|
|
83
|
-
// A GeneralizedTime-only leaf. OCSP times (producedAt / thisUpdate / nextUpdate /
|
|
84
|
-
// revocationTime) are GeneralizedTime, never UTCTime (RFC 6960); assert the tag
|
|
85
|
-
// before the codec reads it so a UTCTime is rejected ocsp/bad-time.
|
|
86
65
|
var GENERALIZED_TIME = pkix.generalizedTime(NS, { code: "ocsp/bad-time", message: "OCSP time must be a GeneralizedTime (RFC 6960)" });
|
|
87
66
|
|
|
88
|
-
// OCSPResponseStatus decode-and-whitelist leaf. read.enumerated is tag-checked, so
|
|
89
|
-
// an INTEGER-encoded status is rejected at the leaf (asn1/unexpected-tag).
|
|
90
67
|
var OCSP_RESPONSE_STATUS = schema.decode(function (n, ctx) {
|
|
91
68
|
var v = asn1.read.enumerated(n);
|
|
92
69
|
var key = v.toString();
|
|
@@ -94,7 +71,6 @@ var OCSP_RESPONSE_STATUS = schema.decode(function (n, ctx) {
|
|
|
94
71
|
return { code: Number(v), name: STATUS_NAMES[key] };
|
|
95
72
|
});
|
|
96
73
|
|
|
97
|
-
// CRLReason decode-and-whitelist leaf.
|
|
98
74
|
var CRL_REASON = schema.decode(function (n, ctx) {
|
|
99
75
|
var v = asn1.read.enumerated(n);
|
|
100
76
|
var key = v.toString();
|
|
@@ -102,44 +78,20 @@ var CRL_REASON = schema.decode(function (n, ctx) {
|
|
|
102
78
|
return CRL_REASONS[key];
|
|
103
79
|
});
|
|
104
80
|
|
|
105
|
-
// A certs [0] SEQUENCE OF Certificate element. Unlike the CMS CertificateChoices
|
|
106
|
-
// (a tagged CHOICE), an OCSP certs element is a plain Certificate, a universal
|
|
107
|
-
// SEQUENCE (RFC 5280 sec. 4.1), so assert that shape before surfacing its raw DER, and
|
|
108
|
-
// reject a non-SEQUENCE element instead of reporting arbitrary bytes as a cert.
|
|
109
81
|
function certificateBytes() {
|
|
110
82
|
return pkix.rawNonEmptySequence(NS, { code: "ocsp/bad-certs", message: "each certs element must be a non-empty Certificate SEQUENCE (RFC 6960 sec. 4.1.1/sec. 4.2.1)" });
|
|
111
83
|
}
|
|
112
84
|
|
|
113
|
-
// requestorName [1] EXPLICIT GeneralName (RFC 6960 sec. 4.1.1), validated and surfaced raw
|
|
114
|
-
// via the shared pkix.generalName primitive (RFC 5280 sec. 4.2.1.6), so a malformed
|
|
115
|
-
// GeneralName fails closed and the OCSP + TSP parsers cannot drift on this grammar.
|
|
116
85
|
var GENERAL_NAME_RAW = pkix.generalName(NS, { code: "ocsp/bad-requestor-name" });
|
|
117
86
|
|
|
118
|
-
// An OCSP signature BIT STRING is a byte string handed to a cryptographic verifier,
|
|
119
|
-
// so it MUST be octet-aligned (0 unused bits); a non-octet-aligned signature is
|
|
120
|
-
// malformed. Shared by the request Signature and the BasicOCSPResponse.
|
|
121
87
|
function _rawSignature(field) {
|
|
122
88
|
var sig = field.value;
|
|
123
89
|
if (sig.unusedBits !== 0) throw NS.E("ocsp/bad-signature", "an OCSP signature BIT STRING must be octet-aligned (0 unused bits)");
|
|
124
90
|
return sig.bytes;
|
|
125
91
|
}
|
|
126
92
|
|
|
127
|
-
// certs [0] EXPLICIT SEQUENCE OF Certificate, each element raw. Shared by the
|
|
128
|
-
// request Signature and the BasicOCSPResponse.
|
|
129
|
-
// The certs list is capped: the delegated-responder authorization loop verifies
|
|
130
|
-
// each candidate before the response signature is checked, so an unbounded list in
|
|
131
|
-
// a relayed / stapled response would drive unbounded pre-auth signature verifies.
|
|
132
93
|
var CERTS = schema.seqOf(certificateBytes(), { assert: "sequence", code: "ocsp/bad-certs", what: "certs", max: constants.LIMITS.OCSP_MAX_CERTS, maxCode: "ocsp/too-many-certs" });
|
|
133
94
|
|
|
134
|
-
// Validate the OCSP protocol extension values in a decoded extension list,
|
|
135
|
-
// applied to every extension surface (request / single-request / response /
|
|
136
|
-
// single-response) so a hostile placement cannot dodge the syntax rule. The
|
|
137
|
-
// nonce is the one extension whose value the module names: Nonce ::= OCTET
|
|
138
|
-
// STRING (SIZE(1..128)) (RFC 9654 sec. 2.1, updating RFC 6960 sec. 4.4.1; the 128
|
|
139
|
-
// upper bound is the RFC 9654 responder rule; RFC 8954's was 32). The decoded
|
|
140
|
-
// nonce bytes are surfaced on the extension as `nonce` alongside the raw value;
|
|
141
|
-
// other extension values stay opaque (an unknown extension is representable,
|
|
142
|
-
// not a fault).
|
|
143
95
|
function _validateOcspExtensions(list) {
|
|
144
96
|
if (!list) return list;
|
|
145
97
|
for (var i = 0; i < list.length; i++) {
|
|
@@ -159,11 +111,7 @@ function _validateOcspExtensions(list) {
|
|
|
159
111
|
return list;
|
|
160
112
|
}
|
|
161
113
|
|
|
162
|
-
// ---- CertID (shared request + response) ------------------------------
|
|
163
114
|
|
|
164
|
-
// CertID ::= SEQUENCE { hashAlgorithm AlgorithmIdentifier, issuerNameHash OCTET
|
|
165
|
-
// STRING, issuerKeyHash OCTET STRING, serialNumber CertificateSerialNumber }
|
|
166
|
-
// (RFC 6960 sec. 4.1.1). The two hashes are surfaced raw for the caller to verify.
|
|
167
115
|
var CERT_ID = schema.seq([
|
|
168
116
|
schema.field("hashAlgorithm", ALGORITHM_IDENTIFIER),
|
|
169
117
|
schema.field("issuerNameHash", schema.octetString()),
|
|
@@ -182,11 +130,7 @@ var CERT_ID = schema.seq([
|
|
|
182
130
|
},
|
|
183
131
|
});
|
|
184
132
|
|
|
185
|
-
// ---- response tree ---------------------------------------------------
|
|
186
133
|
|
|
187
|
-
// RevokedInfo ::= SEQUENCE { revocationTime GeneralizedTime, revocationReason [0]
|
|
188
|
-
// EXPLICIT CRLReason OPTIONAL } (RFC 6960 sec. 4.2.1). Walked on the [1] IMPLICIT node,
|
|
189
|
-
// so assert:"constructed" (the context tag replaced the universal SEQUENCE tag).
|
|
190
134
|
var REVOKED_INFO = schema.seq([
|
|
191
135
|
schema.field("revocationTime", GENERALIZED_TIME),
|
|
192
136
|
schema.trailing([
|
|
@@ -202,9 +146,6 @@ var REVOKED_INFO = schema.seq([
|
|
|
202
146
|
},
|
|
203
147
|
});
|
|
204
148
|
|
|
205
|
-
// CertStatus ::= CHOICE { good [0] IMPLICIT NULL, revoked [1] IMPLICIT RevokedInfo,
|
|
206
|
-
// unknown [2] IMPLICIT NULL } (RFC 6960 sec. 4.2.1). good/unknown are primitive empty
|
|
207
|
-
// context nodes; revoked is a constructed context [1] whose body is RevokedInfo.
|
|
208
149
|
var CERT_STATUS = schema.choice([
|
|
209
150
|
{ when: { tagClass: "context", tagNumber: 0 }, schema: schema.implicitNull(0) },
|
|
210
151
|
{ when: { tagClass: "context", tagNumber: 1 }, schema: REVOKED_INFO },
|
|
@@ -219,11 +160,6 @@ function _shapeCertStatus(field) {
|
|
|
219
160
|
return { type: "revoked", revocationTime: ri.revocationTime, revocationReason: ri.revocationReason };
|
|
220
161
|
}
|
|
221
162
|
|
|
222
|
-
// SingleResponse ::= SEQUENCE { certID, certStatus, thisUpdate GeneralizedTime,
|
|
223
|
-
// nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL, singleExtensions [1] EXPLICIT
|
|
224
|
-
// Extensions OPTIONAL } (RFC 6960 sec. 4.2.1). certStatus is consumed positionally
|
|
225
|
-
// (before thisUpdate), so its context [0] good arm cannot be confused with the
|
|
226
|
-
// trailing nextUpdate [0].
|
|
227
163
|
var SINGLE_RESPONSE = schema.seq([
|
|
228
164
|
schema.field("certID", CERT_ID),
|
|
229
165
|
schema.field("certStatus", CERT_STATUS),
|
|
@@ -245,9 +181,6 @@ var SINGLE_RESPONSE = schema.seq([
|
|
|
245
181
|
},
|
|
246
182
|
});
|
|
247
183
|
|
|
248
|
-
// ResponderID ::= CHOICE { byName [1] Name, byKey [2] KeyHash } (RFC 6960 sec. 4.2.1),
|
|
249
|
-
// both EXPLICIT (the module is EXPLICIT TAGS). byKey is an EXPLICIT-wrapped universal
|
|
250
|
-
// OCTET STRING (0xA2 04 ...) and not an IMPLICIT primitive [2].
|
|
251
184
|
var RESPONDER_ID = schema.choice([
|
|
252
185
|
{ when: { tagClass: "context", tagNumber: 1 }, schema: schema.explicit(1, NAME, { code: "ocsp/bad-responder-id" }) },
|
|
253
186
|
{ when: { tagClass: "context", tagNumber: 2 }, schema: schema.explicit(2, schema.octetString(), { code: "ocsp/bad-responder-id" }) },
|
|
@@ -255,16 +188,11 @@ var RESPONDER_ID = schema.choice([
|
|
|
255
188
|
|
|
256
189
|
function _shapeResponderID(field) {
|
|
257
190
|
if (field.node.tagNumber === 1) return { byName: field.value.result };
|
|
258
|
-
// RFC 6960 sec. 4.2.1 -- KeyHash is the SHA-1 hash of the responder's public key, so a
|
|
259
|
-
// conformant byKey ResponderID is exactly 20 octets; reject any other length.
|
|
260
191
|
var keyHash = field.value;
|
|
261
192
|
if (keyHash.length !== 20) throw NS.E("ocsp/bad-responder-id", "ResponderID byKey (KeyHash) must be a 20-byte SHA-1 hash (RFC 6960 sec. 4.2.1)");
|
|
262
193
|
return { byKey: keyHash };
|
|
263
194
|
}
|
|
264
195
|
|
|
265
|
-
// ResponseData ::= SEQUENCE { version [0] EXPLICIT DEFAULT v1, responderID,
|
|
266
|
-
// producedAt GeneralizedTime, responses SEQUENCE OF SingleResponse,
|
|
267
|
-
// responseExtensions [1] EXPLICIT Extensions OPTIONAL } (RFC 6960 sec. 4.2.1).
|
|
268
196
|
var RESPONSE_DATA = schema.seq([
|
|
269
197
|
schema.optional("version", VERSION, { tag: 0, explicit: true, default: 1, emptyCode: "ocsp/bad-version" }),
|
|
270
198
|
schema.field("responderID", RESPONDER_ID),
|
|
@@ -286,10 +214,6 @@ var RESPONSE_DATA = schema.seq([
|
|
|
286
214
|
},
|
|
287
215
|
});
|
|
288
216
|
|
|
289
|
-
// BasicOCSPResponse ::= SEQUENCE { tbsResponseData ResponseData, signatureAlgorithm
|
|
290
|
-
// AlgorithmIdentifier, signature BIT STRING, certs [0] EXPLICIT SEQUENCE OF
|
|
291
|
-
// Certificate OPTIONAL } (RFC 6960 sec. 4.2.1). tbsResponseData.node.bytes is the exact
|
|
292
|
-
// signed region (no CMS-style re-tag divergence, the clean case).
|
|
293
217
|
var BASIC_OCSP_RESPONSE = schema.seq([
|
|
294
218
|
schema.field("tbsResponseData", RESPONSE_DATA),
|
|
295
219
|
schema.field("signatureAlgorithm", ALGORITHM_IDENTIFIER),
|
|
@@ -315,10 +239,6 @@ var BASIC_OCSP_RESPONSE = schema.seq([
|
|
|
315
239
|
},
|
|
316
240
|
});
|
|
317
241
|
|
|
318
|
-
// ResponseBytes ::= SEQUENCE { responseType OBJECT IDENTIFIER, response OCTET STRING }
|
|
319
|
-
// (RFC 6960 sec. 4.2.1). For id-pkix-ocsp-basic the response OCTET STRING content is a
|
|
320
|
-
// fresh DER BasicOCSPResponse (decoded + walked); an unknown responseType is
|
|
321
|
-
// recognized-and-deferred with a precise ocsp/unsupported-response-type.
|
|
322
242
|
var RESPONSE_BYTES = schema.seq([
|
|
323
243
|
schema.field("responseType", schema.oidLeaf()),
|
|
324
244
|
schema.field("response", schema.octetString()),
|
|
@@ -340,12 +260,6 @@ var RESPONSE_BYTES = schema.seq([
|
|
|
340
260
|
},
|
|
341
261
|
});
|
|
342
262
|
|
|
343
|
-
// OCSPResponse ::= SEQUENCE { responseStatus OCSPResponseStatus, responseBytes [0]
|
|
344
|
-
// EXPLICIT ResponseBytes OPTIONAL } (RFC 6960 sec. 4.2.1). The status <-> responseBytes
|
|
345
|
-
// biconditional (successful iff responseBytes present) is the OCSP-specific
|
|
346
|
-
// cross-field guard. The top-level reject code predates the
|
|
347
|
-
// `<prefix>/not-a-<structure>` convention (ocsp/not-a-request follows it) and
|
|
348
|
-
// stays frozen on the public error-code surface.
|
|
349
263
|
var OCSP_RESPONSE = schema.seq([
|
|
350
264
|
schema.field("responseStatus", OCSP_RESPONSE_STATUS),
|
|
351
265
|
schema.optional("responseBytes", RESPONSE_BYTES, { tag: 0, explicit: true, emptyCode: "ocsp/bad-ocsp-response" }),
|
|
@@ -354,8 +268,6 @@ var OCSP_RESPONSE = schema.seq([
|
|
|
354
268
|
build: function (m) {
|
|
355
269
|
var status = m.fields.responseStatus.value;
|
|
356
270
|
var present = m.fields.responseBytes.present;
|
|
357
|
-
// RFC 6960 sec. 4.2.1 -- a successful response MUST carry responseBytes; any other
|
|
358
|
-
// status MUST NOT (there is nothing to convey but the status).
|
|
359
271
|
if (status.code === 0 && !present) throw NS.E("ocsp/bad-response-bytes", "a successful OCSPResponse must carry responseBytes (RFC 6960 sec. 4.2.1)");
|
|
360
272
|
if (status.code !== 0 && present) throw NS.E("ocsp/bad-response-bytes", "a non-successful OCSPResponse must not carry responseBytes (RFC 6960 sec. 4.2.1)");
|
|
361
273
|
var rb = present ? m.fields.responseBytes.value.result : null;
|
|
@@ -367,10 +279,7 @@ var OCSP_RESPONSE = schema.seq([
|
|
|
367
279
|
},
|
|
368
280
|
});
|
|
369
281
|
|
|
370
|
-
// ---- request tree ----------------------------------------------------
|
|
371
282
|
|
|
372
|
-
// Request ::= SEQUENCE { reqCert CertID, singleRequestExtensions [0] EXPLICIT
|
|
373
|
-
// Extensions OPTIONAL } (RFC 6960 sec. 4.1.1).
|
|
374
283
|
var REQUEST = schema.seq([
|
|
375
284
|
schema.field("reqCert", CERT_ID),
|
|
376
285
|
schema.trailing([
|
|
@@ -386,8 +295,6 @@ var REQUEST = schema.seq([
|
|
|
386
295
|
},
|
|
387
296
|
});
|
|
388
297
|
|
|
389
|
-
// Signature ::= SEQUENCE { signatureAlgorithm AlgorithmIdentifier, signature BIT
|
|
390
|
-
// STRING, certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL } (RFC 6960 sec. 4.1.1).
|
|
391
298
|
var SIGNATURE = schema.seq([
|
|
392
299
|
schema.field("signatureAlgorithm", ALGORITHM_IDENTIFIER),
|
|
393
300
|
schema.field("signature", schema.bitString()),
|
|
@@ -405,10 +312,6 @@ var SIGNATURE = schema.seq([
|
|
|
405
312
|
},
|
|
406
313
|
});
|
|
407
314
|
|
|
408
|
-
// TBSRequest ::= SEQUENCE { version [0] EXPLICIT DEFAULT v1, requestorName [1]
|
|
409
|
-
// EXPLICIT GeneralName OPTIONAL, requestList SEQUENCE OF Request, requestExtensions
|
|
410
|
-
// [2] EXPLICIT Extensions OPTIONAL } (RFC 6960 sec. 4.1.1). requestorName is surfaced
|
|
411
|
-
// raw (GeneralName is a wide CHOICE with no factory yet).
|
|
412
315
|
var TBS_REQUEST = schema.seq([
|
|
413
316
|
schema.optional("version", VERSION, { tag: 0, explicit: true, default: 1, emptyCode: "ocsp/bad-version" }),
|
|
414
317
|
schema.optional("requestorName", GENERAL_NAME_RAW, { tag: 1, explicit: true, emptyCode: "ocsp/bad-requestor-name" }),
|
|
@@ -429,9 +332,6 @@ var TBS_REQUEST = schema.seq([
|
|
|
429
332
|
},
|
|
430
333
|
});
|
|
431
334
|
|
|
432
|
-
// OCSPRequest ::= SEQUENCE { tbsRequest TBSRequest, optionalSignature [0] EXPLICIT
|
|
433
|
-
// Signature OPTIONAL } (RFC 6960 sec. 4.1.1). tbsRequest.node.bytes is the raw signed
|
|
434
|
-
// region for external verification.
|
|
435
335
|
var OCSP_REQUEST = schema.seq([
|
|
436
336
|
schema.field("tbsRequest", TBS_REQUEST),
|
|
437
337
|
schema.optional("optionalSignature", SIGNATURE, { tag: 0, explicit: true, emptyCode: "ocsp/not-a-request" }),
|
|
@@ -440,9 +340,6 @@ var OCSP_REQUEST = schema.seq([
|
|
|
440
340
|
build: function (m) {
|
|
441
341
|
var tbs = m.fields.tbsRequest.value.result;
|
|
442
342
|
var optionalSignature = m.fields.optionalSignature.present ? m.fields.optionalSignature.value.result : null;
|
|
443
|
-
// RFC 6960 sec. 4.1.2 -- if the request is signed, the requestor SHALL specify its
|
|
444
|
-
// name in requestorName (the identity the signature binds to). A signed request
|
|
445
|
-
// without it is internally inconsistent; reject fail-closed.
|
|
446
343
|
if (optionalSignature && tbs.requestorName === null) {
|
|
447
344
|
throw NS.E("ocsp/missing-requestor-name", "a signed OCSPRequest must specify requestorName (RFC 6960 sec. 4.1.2)");
|
|
448
345
|
}
|
|
@@ -522,11 +419,6 @@ var parseRequest = pkix.makeParser({ pemLabel: "OCSP REQUEST", PemError: PemErro
|
|
|
522
419
|
* res.responseStatus.name; // -> "successful"
|
|
523
420
|
* res.basicResponse.responses[0].certStatus.type; // -> "good" | "revoked" | "unknown"
|
|
524
421
|
*/
|
|
525
|
-
// The result records the input it was derived from. A verdict verb reads the
|
|
526
|
-
// signature, the algorithm that verifies it and the bytes it covers off this object as
|
|
527
|
-
// three separate properties, and re-derives all three from the recorded input rather
|
|
528
|
-
// than trusting the object it was handed -- so an object rebuilt or edited after
|
|
529
|
-
// parsing cannot make the three describe different responses.
|
|
530
422
|
var parseResponse = pkix.makeRecordingParser({ pemLabel: "OCSP RESPONSE", PemError: PemError, ErrorClass: OcspError, prefix: "ocsp", what: "OCSP response", topSchema: OCSP_RESPONSE, ns: NS }, "ocspResponse");
|
|
531
423
|
|
|
532
424
|
/**
|
|
@@ -583,11 +475,6 @@ function pemDecode(text, label) { return pkix.pemDecode(text, label || "OCSP RES
|
|
|
583
475
|
*/
|
|
584
476
|
function pemEncode(der, label) { return pkix.pemEncode(der, label || "OCSP RESPONSE", PemError); }
|
|
585
477
|
|
|
586
|
-
// An OCSPResponse root is the only registered structure that leads with an
|
|
587
|
-
// ENUMERATED child (a SEQUENCE of 1-2: responseStatus + an optional context [0]
|
|
588
|
-
// responseBytes). Every other root leads with a SEQUENCE (x509/crl/csr/ocsp-request),
|
|
589
|
-
// an OBJECT IDENTIFIER (cms), or an INTEGER (pkcs8), so the detector is
|
|
590
|
-
// unconditionally exclusive.
|
|
591
478
|
function matchesResponse(root) {
|
|
592
479
|
var T = asn1.TAGS;
|
|
593
480
|
var k = pkix.rootSequenceChildren(root, 1, 2);
|
|
@@ -597,10 +484,6 @@ function matchesResponse(root) {
|
|
|
597
484
|
return true;
|
|
598
485
|
}
|
|
599
486
|
|
|
600
|
-
// An OCSPRequest root is a SEQUENCE of 1-2 whose first child is the tbsRequest
|
|
601
|
-
// SEQUENCE (optionally followed by a context [0] EXPLICIT signature). It leads with
|
|
602
|
-
// a SEQUENCE like x509/crl/csr, but those require EXACTLY 3 children (the
|
|
603
|
-
// signed-envelope trio), while an OCSPRequest is 1-2 -- so it is excluded by arity.
|
|
604
487
|
function matchesRequest(root) {
|
|
605
488
|
var T = asn1.TAGS;
|
|
606
489
|
var k = pkix.rootSequenceChildren(root, 1, 2);
|
package/lib/schema-pkcs12.js
CHANGED
|
@@ -53,27 +53,22 @@ var PemError = frameworkError.PemError;
|
|
|
53
53
|
var NS = pkix.makeNS("pkcs12", Pkcs12Error, oid);
|
|
54
54
|
var TAGS = asn1.TAGS;
|
|
55
55
|
|
|
56
|
-
// Content types (RFC 5652 sec. 4 / RFC 7292 sec. 4.1).
|
|
57
56
|
var OID_DATA = oid.byName("data");
|
|
58
57
|
var OID_SIGNED_DATA = oid.byName("signedData");
|
|
59
58
|
var OID_ENVELOPED_DATA = oid.byName("envelopedData");
|
|
60
59
|
var OID_ENCRYPTED_DATA = oid.byName("encryptedData");
|
|
61
|
-
// Bag types (RFC 7292 sec. 4.2).
|
|
62
60
|
var OID_KEY_BAG = oid.byName("keyBag");
|
|
63
61
|
var OID_SHROUDED_KEY_BAG = oid.byName("pkcs8ShroudedKeyBag");
|
|
64
62
|
var OID_CERT_BAG = oid.byName("certBag");
|
|
65
63
|
var OID_CRL_BAG = oid.byName("crlBag");
|
|
66
64
|
var OID_SECRET_BAG = oid.byName("secretBag");
|
|
67
65
|
var OID_SAFE_CONTENTS_BAG = oid.byName("safeContentsBag");
|
|
68
|
-
// CertBag / CRLBag discriminators (sec. 4.2.3-sec. 4.2.4).
|
|
69
66
|
var OID_X509_CERTIFICATE = oid.byName("x509Certificate");
|
|
70
67
|
var OID_SDSI_CERTIFICATE = oid.byName("sdsiCertificate");
|
|
71
68
|
var OID_X509_CRL = oid.byName("x509CRL");
|
|
72
|
-
// Bag attributes (sec. 4.2) + the RFC 9579 MacData arm.
|
|
73
69
|
var OID_FRIENDLY_NAME = oid.byName("friendlyName");
|
|
74
70
|
var OID_LOCAL_KEY_ID = oid.byName("localKeyId");
|
|
75
71
|
var OID_PBMAC1 = oid.byName("pbmac1");
|
|
76
|
-
// DigestInfo ::= SEQUENCE { digestAlgorithm AlgorithmIdentifier, digest OCTET STRING }.
|
|
77
72
|
var DIGEST_INFO = schema.seq([
|
|
78
73
|
schema.field("digestAlgorithm", pkix.algorithmIdentifier(NS)),
|
|
79
74
|
schema.field("digest", schema.octetString()),
|
|
@@ -84,14 +79,8 @@ var DIGEST_INFO = schema.seq([
|
|
|
84
79
|
},
|
|
85
80
|
});
|
|
86
81
|
|
|
87
|
-
// PBKDF2-params + PBMAC1-params (RFC 8018 sec. 5.2 / App. A.5, RFC 9579 sec. 4) constrained to the PBMAC1
|
|
88
|
-
// profile -- keyLength MUST be present, the prf DEFAULT is enforced non-canonical. Shared with CMP PBMAC1
|
|
89
|
-
// protection verification, so the reader lives once in schema-pkix (ns-parameterized) instead of a second
|
|
90
|
-
// copy per format; composed here with the pkcs12 namespace so it emits pkcs12/bad-mac-data.
|
|
91
82
|
var PBMAC1_PARAMS = pkix.pbmac1Params(NS);
|
|
92
83
|
|
|
93
|
-
// MacData ::= SEQUENCE { mac DigestInfo, macSalt OCTET STRING,
|
|
94
|
-
// iterations INTEGER DEFAULT 1 }.
|
|
95
84
|
var MAC_DATA = schema.seq([
|
|
96
85
|
schema.field("mac", DIGEST_INFO),
|
|
97
86
|
schema.field("macSalt", schema.octetString()),
|
|
@@ -99,8 +88,6 @@ var MAC_DATA = schema.seq([
|
|
|
99
88
|
], {
|
|
100
89
|
assert: "sequence", code: "pkcs12/bad-mac-data", what: "MacData",
|
|
101
90
|
build: function (m, ctx) {
|
|
102
|
-
// X.690 sec. 11.5 -- a DEFAULT-valued component must be omitted from a DER
|
|
103
|
-
// encoding, so an explicitly-encoded iterations = 1 is non-canonical.
|
|
104
91
|
var it = m.fields.iterations;
|
|
105
92
|
var iterations = 1;
|
|
106
93
|
if (it.present) {
|
|
@@ -111,8 +98,6 @@ var MAC_DATA = schema.seq([
|
|
|
111
98
|
var di = m.fields.mac.value.result;
|
|
112
99
|
var pbmac1 = null;
|
|
113
100
|
if (di.digestAlgorithm.oid === OID_PBMAC1) {
|
|
114
|
-
// RFC 9579 sec. 4 -- the PBMAC1 algorithm identifier MUST carry PBMAC1-params
|
|
115
|
-
// (the KDF and MAC scheme a verifier needs live there, not in MacData).
|
|
116
101
|
if (di.digestAlgorithm.parameters === null) {
|
|
117
102
|
throw ctx.E("pkcs12/bad-mac-data", "a PBMAC1 MacData must carry PBMAC1-params (RFC 9579 sec. 4)");
|
|
118
103
|
}
|
|
@@ -132,10 +117,6 @@ var MAC_DATA = schema.seq([
|
|
|
132
117
|
},
|
|
133
118
|
});
|
|
134
119
|
|
|
135
|
-
// CertBag ::= SEQUENCE { certId OID, certValue [0] EXPLICIT ANY } (sec. 4.2.3):
|
|
136
|
-
// x509Certificate wraps the DER certificate in an OCTET STRING; sdsiCertificate
|
|
137
|
-
// is an IA5String. Both arms of the closed set are accepted; the value is
|
|
138
|
-
// surfaced raw (byte-exact), never re-encoded or recursively parsed.
|
|
139
120
|
var CERT_BAG = schema.seq([
|
|
140
121
|
schema.field("certId", schema.oidLeaf()),
|
|
141
122
|
schema.field("certValue", schema.explicit(0, schema.any(), { code: "pkcs12/bad-bag-value", what: "certValue" })),
|
|
@@ -157,7 +138,6 @@ var CERT_BAG = schema.seq([
|
|
|
157
138
|
},
|
|
158
139
|
});
|
|
159
140
|
|
|
160
|
-
// CRLBag ::= SEQUENCE { crlId OID, crlValue [0] EXPLICIT ANY } (sec. 4.2.4).
|
|
161
141
|
var CRL_BAG = schema.seq([
|
|
162
142
|
schema.field("crlId", schema.oidLeaf()),
|
|
163
143
|
schema.field("crlValue", schema.explicit(0, schema.any(), { code: "pkcs12/bad-bag-value", what: "crlValue" })),
|
|
@@ -172,9 +152,6 @@ var CRL_BAG = schema.seq([
|
|
|
172
152
|
},
|
|
173
153
|
});
|
|
174
154
|
|
|
175
|
-
// SecretBag ::= SEQUENCE { secretTypeId OID, secretValue [0] EXPLICIT ANY }
|
|
176
|
-
// (sec. 4.2.5). SecretTypes is an open set, so the type is surfaced by OID with
|
|
177
|
-
// the value raw -- an unrecognized secret is representable, not a fault.
|
|
178
155
|
var SECRET_BAG = schema.seq([
|
|
179
156
|
schema.field("secretTypeId", schema.oidLeaf()),
|
|
180
157
|
schema.field("secretValue", schema.explicit(0, schema.any(), { code: "pkcs12/bad-bag-value", what: "secretValue" })),
|
|
@@ -186,11 +163,6 @@ var SECRET_BAG = schema.seq([
|
|
|
186
163
|
},
|
|
187
164
|
});
|
|
188
165
|
|
|
189
|
-
// SafeBag ::= SEQUENCE { bagId OID, bagValue [0] EXPLICIT ANY DEFINED BY bagId,
|
|
190
|
-
// bagAttributes SET OF PKCS12Attribute OPTIONAL } (sec. 4.2).
|
|
191
|
-
// The build surfaces the structural record (bagId + the inner value node +
|
|
192
|
-
// decoded attributes); the bagId dispatch happens in _buildBag, where the
|
|
193
|
-
// per-parse recursion state lives.
|
|
194
166
|
var SAFE_BAG = schema.seq([
|
|
195
167
|
schema.field("bagId", schema.oidLeaf()),
|
|
196
168
|
schema.field("bagValue", schema.explicit(0, schema.any(), { code: "pkcs12/bad-bag-value", what: "bagValue" })),
|
|
@@ -210,16 +182,12 @@ var SAFE_BAG = schema.seq([
|
|
|
210
182
|
for (var i = 0; i < items.length; i++) {
|
|
211
183
|
var a = items[i].value.result;
|
|
212
184
|
attributes.push(a);
|
|
213
|
-
// friendlyName / localKeyId are SINGLE VALUE TRUE (PKCS#9 / RFC 2985):
|
|
214
|
-
// exactly one value, at most one instance of each attribute.
|
|
215
185
|
if (a.type === OID_FRIENDLY_NAME) {
|
|
216
186
|
if (seen[a.type] || a.values.length !== 1) throw ctx.E("pkcs12/bad-friendly-name", "friendlyName carries exactly one BMPString value (PKCS#9 SINGLE VALUE)");
|
|
217
187
|
friendlyName = _bmpValue(a.values[0], ctx);
|
|
218
188
|
}
|
|
219
189
|
if (a.type === OID_LOCAL_KEY_ID) {
|
|
220
190
|
if (seen[a.type] || a.values.length !== 1) throw ctx.E("pkcs12/bad-local-key-id", "localKeyId carries exactly one OCTET STRING value (PKCS#9 SINGLE VALUE)");
|
|
221
|
-
// The value bytes are a raw wire slice out of a store whose content
|
|
222
|
-
// is normatively BER, so the re-decode follows the same BER rules.
|
|
223
191
|
localKeyId = _octetContent(asn1.decode(a.values[0], { ber: true }), ctx, "a localKeyId value", "pkcs12/bad-local-key-id");
|
|
224
192
|
}
|
|
225
193
|
seen[a.type] = true;
|
|
@@ -235,15 +203,11 @@ var SAFE_BAG = schema.seq([
|
|
|
235
203
|
},
|
|
236
204
|
});
|
|
237
205
|
|
|
238
|
-
// SafeContents ::= SEQUENCE OF SafeBag (sec. 4.2). Strictly a SEQUENCE: a SET OF
|
|
239
|
-
// here is a known producer divergence and rejects.
|
|
240
206
|
var SAFE_CONTENTS = schema.seqOf(SAFE_BAG, {
|
|
241
207
|
code: "pkcs12/bad-safe-contents", what: "SafeContents",
|
|
242
208
|
max: C.LIMITS.PKCS12_MAX_ELEMENTS, maxCode: "pkcs12/too-many-elements",
|
|
243
209
|
});
|
|
244
210
|
|
|
245
|
-
// AuthenticatedSafe ::= SEQUENCE OF ContentInfo (sec. 4.1), each element parsed
|
|
246
|
-
// structurally here and dispatched by contentType in _dispatchSafes.
|
|
247
211
|
var AS_ELEMENT = schema.seq([
|
|
248
212
|
schema.field("contentType", schema.oidLeaf()),
|
|
249
213
|
schema.field("content", schema.explicit(0, schema.any(), { code: "pkcs12/bad-safe-contentinfo", what: "safe ContentInfo content" })),
|
|
@@ -258,8 +222,6 @@ var AUTHENTICATED_SAFE = schema.seqOf(AS_ELEMENT, {
|
|
|
258
222
|
max: C.LIMITS.PKCS12_MAX_ELEMENTS, maxCode: "pkcs12/too-many-elements",
|
|
259
223
|
});
|
|
260
224
|
|
|
261
|
-
// The authSafe ContentInfo (sec. 4): contentType is data (password integrity) or
|
|
262
|
-
// signedData (public-key integrity) and nothing else.
|
|
263
225
|
var AUTH_SAFE = schema.seq([
|
|
264
226
|
schema.field("contentType", schema.oidLeaf()),
|
|
265
227
|
schema.field("content", schema.explicit(0, schema.any(), { code: "pkcs12/bad-authsafe", what: "authSafe content" })),
|
|
@@ -270,8 +232,6 @@ var AUTH_SAFE = schema.seq([
|
|
|
270
232
|
},
|
|
271
233
|
});
|
|
272
234
|
|
|
273
|
-
// PFX ::= SEQUENCE { version INTEGER {v3(3)}, authSafe ContentInfo,
|
|
274
|
-
// macData MacData OPTIONAL } (sec. 4).
|
|
275
235
|
var PFX = schema.seq([
|
|
276
236
|
schema.field("version", pkix.versionReader(NS, { "3": 3 })),
|
|
277
237
|
schema.field("authSafe", AUTH_SAFE),
|
|
@@ -283,18 +243,9 @@ var PFX = schema.seq([
|
|
|
283
243
|
var authSafe = m.fields.authSafe.value.result;
|
|
284
244
|
var macPresent = m.fields.macData.present;
|
|
285
245
|
var mac = macPresent ? m.fields.macData.value.result : null;
|
|
286
|
-
// Every re-decode below shares one budget, so nesting chained across
|
|
287
|
-
// OCTET-STRING (and delegation) boundaries cannot restart the caps.
|
|
288
246
|
var state = { budget: { remaining: C.LIMITS.PKCS12_MAX_REDECODES }, bagDepth: 0 };
|
|
289
247
|
|
|
290
248
|
if (authSafe.contentType === OID_DATA) {
|
|
291
|
-
// sec. 5.1 step 5B -- the MAC covers the value octets of the id-data OCTET
|
|
292
|
-
// STRING (the AuthenticatedSafe encoding), excluding the TLV header.
|
|
293
|
-
// MacData itself is OPTIONAL in the PFX syntax: a store without it
|
|
294
|
-
// (OpenSSL `pkcs12 -export -nomac`) carries no integrity protection at
|
|
295
|
-
// all, which is a policy concern for the caller. It is surfaced as
|
|
296
|
-
// integrityMode "none", never rejected by a parser whose job is to
|
|
297
|
-
// surface integrity inputs and not to verify them.
|
|
298
249
|
var macedBytes = _octetContent(authSafe.innerNode, ctx, "an id-data authSafe content", "pkcs12/bad-authsafe");
|
|
299
250
|
var dispatched = _dispatchSafes(_walkAuthenticatedSafe(macedBytes, state, ctx), state, ctx);
|
|
300
251
|
return {
|
|
@@ -303,7 +254,6 @@ var PFX = schema.seq([
|
|
|
303
254
|
};
|
|
304
255
|
}
|
|
305
256
|
if (authSafe.contentType === OID_SIGNED_DATA) {
|
|
306
|
-
// sec. 4 integrity coherence: public-key integrity has no MacData.
|
|
307
257
|
if (macPresent) throw ctx.E("pkcs12/bad-integrity-mode", "an id-signedData authSafe (public-key integrity) must omit macData (RFC 7292 sec. 4)");
|
|
308
258
|
var signed = cms.walkSignedData(authSafe.innerNode);
|
|
309
259
|
if (signed.encapContentInfo.eContentType !== OID_DATA) {
|
|
@@ -312,8 +262,6 @@ var PFX = schema.seq([
|
|
|
312
262
|
if (signed.encapContentInfo.eContent === null) {
|
|
313
263
|
throw ctx.E("pkcs12/bad-authsafe", "a public-key-integrity authSafe must carry attached eContent (RFC 7292 sec. 4.1)");
|
|
314
264
|
}
|
|
315
|
-
// A signer-less SignedData carries no integrity at all, the one thing
|
|
316
|
-
// public-key-integrity mode exists to provide.
|
|
317
265
|
if (signed.signerInfos.length < 1) {
|
|
318
266
|
throw ctx.E("pkcs12/bad-authsafe", "a public-key-integrity authSafe must carry at least one SignerInfo (RFC 7292 sec. 4)");
|
|
319
267
|
}
|
|
@@ -328,8 +276,6 @@ var PFX = schema.seq([
|
|
|
328
276
|
},
|
|
329
277
|
});
|
|
330
278
|
|
|
331
|
-
// The value octets of a universal OCTET STRING node (a BER constructed string
|
|
332
|
-
// arrives already reassembled to primitive content by the codec's ber mode).
|
|
333
279
|
function _octetContent(node, ctx, what, code) {
|
|
334
280
|
if (!(node && node.tagClass === "universal" && node.tagNumber === TAGS.OCTET_STRING && node.content)) {
|
|
335
281
|
throw ctx.E(code || "pkcs12/bad-bag-value", what + " must be an OCTET STRING");
|
|
@@ -337,11 +283,6 @@ function _octetContent(node, ctx, what, code) {
|
|
|
337
283
|
return node.content;
|
|
338
284
|
}
|
|
339
285
|
|
|
340
|
-
// RFC 7292 sec. 4.1 -- a privacy-mode safe wraps a SafeContents, so the encrypted
|
|
341
|
-
// content's declared type must be id-data whichever CMS privacy structure
|
|
342
|
-
// carries it, and the ciphertext must be attached: CMS permits a detached
|
|
343
|
-
// EncryptedContentInfo, but here the ciphertext is the safe's contents, and a
|
|
344
|
-
// safe without it holds nothing a passphrase could ever recover.
|
|
345
286
|
function _privacySafe(content, ctx) {
|
|
346
287
|
if (content.encryptedContentInfo.contentType !== OID_DATA) {
|
|
347
288
|
throw ctx.E("pkcs12/bad-safe-contentinfo-type",
|
|
@@ -354,8 +295,6 @@ function _privacySafe(content, ctx) {
|
|
|
354
295
|
return content;
|
|
355
296
|
}
|
|
356
297
|
|
|
357
|
-
// A PKCS#9 SINGLE-VALUE BMPString attribute value (friendlyName), decoded
|
|
358
|
-
// UTF-16BE by the codec's string reader (even length + surrogate rules there).
|
|
359
298
|
function _bmpValue(bytes, ctx) {
|
|
360
299
|
var node = asn1.decode(bytes, { ber: true });
|
|
361
300
|
if (!(node.tagClass === "universal" && node.tagNumber === TAGS.BMP_STRING)) {
|
|
@@ -364,7 +303,6 @@ function _bmpValue(bytes, ctx) {
|
|
|
364
303
|
return asn1.read.string(node);
|
|
365
304
|
}
|
|
366
305
|
|
|
367
|
-
// Re-decode the AuthenticatedSafe blob (BER content region, budgeted).
|
|
368
306
|
function _walkAuthenticatedSafe(bytes, state, ctx) {
|
|
369
307
|
return schema.embeddedDer(AUTHENTICATED_SAFE, bytes, ctx, {
|
|
370
308
|
code: "pkcs12/bad-der", what: "the AuthenticatedSafe", ber: true,
|
|
@@ -372,16 +310,8 @@ function _walkAuthenticatedSafe(bytes, state, ctx) {
|
|
|
372
310
|
});
|
|
373
311
|
}
|
|
374
312
|
|
|
375
|
-
//
|
|
376
|
-
// carries plaintext SafeContents (re-decoded here); the two privacy modes are
|
|
377
|
-
// full CMS structures validated by the CMS module on the already-decoded node
|
|
378
|
-
// -- ciphertext stays opaque inside the CMS surface.
|
|
379
|
-
// @internal -- re-parse a DECRYPTED privacy-safe's plaintext (a SafeContents ::= SEQUENCE OF SafeBag) through
|
|
380
|
-
// the same strict SAFE_CONTENTS walk and bag dispatch the plaintext path uses, so a decrypted blob shares every
|
|
381
|
-
// PKCS12_MAX_* cap and produces the identical bag records. Consumed by pki.pkcs12.open for an encrypted safe.
|
|
313
|
+
// @internal
|
|
382
314
|
function walkSafeContents(der) {
|
|
383
|
-
// PKCS#12 content regions are normatively BER (RFC 7292 sec. 4.1), so a decrypted SafeContents may use an
|
|
384
|
-
// indefinite-length SEQUENCE, exactly as the plaintext-safe path (_dispatchSafes) decodes it with ber:true.
|
|
385
315
|
var walked = schema.walk(SAFE_CONTENTS, asn1.decode(der, { ber: true }), NS);
|
|
386
316
|
var state = { budget: { remaining: C.LIMITS.PKCS12_MAX_REDECODES }, bagDepth: 0 };
|
|
387
317
|
var bags = [];
|
|
@@ -405,9 +335,6 @@ function _dispatchSafes(asMatch, state, ctx) {
|
|
|
405
335
|
} else if (el.contentType === OID_ENCRYPTED_DATA) {
|
|
406
336
|
encryptedSafes.push({ type: "encryptedData", content: _privacySafe(cms.walkEncryptedData(el.innerNode), ctx) });
|
|
407
337
|
} else if (el.contentType === OID_ENVELOPED_DATA) {
|
|
408
|
-
// Surface the raw EnvelopedData DER alongside the walked structure: public-key privacy opens by driving
|
|
409
|
-
// pki.cms.decrypt, which re-parses strict DER (it takes no pre-parsed object), so pkcs12.open reconstructs
|
|
410
|
-
// the ContentInfo around these bytes and never re-serializes the recipientInfos the integrity check trusts.
|
|
411
338
|
encryptedSafes.push({ type: "envelopedData", content: _privacySafe(cms.walkEnvelopedData(el.innerNode), ctx), envelopedDataDer: el.innerNode.bytes });
|
|
412
339
|
} else {
|
|
413
340
|
throw ctx.E("pkcs12/bad-safe-contentinfo-type", "an AuthenticatedSafe element must be id-data, id-encryptedData, or id-envelopedData (RFC 7292 sec. 4.1), got " +
|
|
@@ -417,21 +344,15 @@ function _dispatchSafes(asMatch, state, ctx) {
|
|
|
417
344
|
return { safeBags: safeBags, encryptedSafes: encryptedSafes };
|
|
418
345
|
}
|
|
419
346
|
|
|
420
|
-
// bagId dispatch (sec. 4.2, Appendix D). The bag-type set is closed: an
|
|
421
|
-
// unrecognized bagId rejects. Key material delegates to the exported PKCS#8
|
|
422
|
-
// parsers; cert / CRL / secret values are surfaced raw.
|
|
423
347
|
function _buildBag(rec, state, ctx) {
|
|
424
348
|
var bag = {
|
|
425
349
|
type: null, bagId: rec.bagId,
|
|
426
350
|
friendlyName: rec.friendlyName, localKeyId: rec.localKeyId, attributes: rec.attributes,
|
|
427
351
|
};
|
|
428
|
-
// Key bags are walked from the decoded node, since their wire bytes may carry
|
|
429
|
-
// BER shapes the strict pkcs8 parse entry refuses, and the node already
|
|
430
|
-
// exists (no re-decode).
|
|
431
352
|
if (rec.bagId === OID_KEY_BAG) {
|
|
432
353
|
bag.type = "keyBag";
|
|
433
354
|
bag.key = pkcs8.walkPrivateKeyInfo(rec.valueNode);
|
|
434
|
-
bag.keyDer = rec.valueNode.bytes;
|
|
355
|
+
bag.keyDer = rec.valueNode.bytes;
|
|
435
356
|
return bag;
|
|
436
357
|
}
|
|
437
358
|
if (rec.bagId === OID_SHROUDED_KEY_BAG) {
|
|
@@ -458,8 +379,6 @@ function _buildBag(rec, state, ctx) {
|
|
|
458
379
|
return bag;
|
|
459
380
|
}
|
|
460
381
|
if (rec.bagId === OID_SAFE_CONTENTS_BAG) {
|
|
461
|
-
// sec. 4.2.6 recursion -- bounded independently of the codec depth cap so a
|
|
462
|
-
// chain across re-decode boundaries cannot restart it.
|
|
463
382
|
if (state.bagDepth + 1 > C.LIMITS.PKCS12_MAX_BAG_DEPTH) {
|
|
464
383
|
throw ctx.E("pkcs12/too-deep", "safeContentsBag nesting exceeds the depth cap " + C.LIMITS.PKCS12_MAX_BAG_DEPTH);
|
|
465
384
|
}
|
|
@@ -523,11 +442,6 @@ function _buildBag(rec, state, ctx) {
|
|
|
523
442
|
* var store = pki.schema.pkcs12.parse(der);
|
|
524
443
|
* store.safeBags.map(function (b) { return b.type; });
|
|
525
444
|
*/
|
|
526
|
-
// The result records the input it was derived from. pki.pkcs12.verifyMac and open read
|
|
527
|
-
// the MACed byte range and the bags returned as verified off this object as two
|
|
528
|
-
// separate properties, and re-derive both from the recorded input rather than trusting
|
|
529
|
-
// the object -- so "verify this" and "return that" cannot come to name different
|
|
530
|
-
// stores, whether by rebuilding the object or by editing it after parsing.
|
|
531
445
|
var parse = pkix.makeRecordingParser({
|
|
532
446
|
pemLabel: "PKCS12", PemError: PemError, ErrorClass: Pkcs12Error,
|
|
533
447
|
prefix: "pkcs12", what: "PFX", topSchema: PFX, ns: NS, ber: true,
|
|
@@ -576,11 +490,6 @@ function pemDecode(text, label) { return pkix.pemDecode(text, label || "PKCS12",
|
|
|
576
490
|
*/
|
|
577
491
|
function pemEncode(der, label) { return pkix.pemEncode(der, label || "PKCS12", PemError); }
|
|
578
492
|
|
|
579
|
-
// A PFX root leads with a universal INTEGER (version), colliding with the
|
|
580
|
-
// PKCS#8 detector on the first child -- so the discriminators are children[1]
|
|
581
|
-
// (a ContentInfo: SEQUENCE of exactly 2, OID first, [0] constructed second --
|
|
582
|
-
// a shape a PrivateKeyInfo's AlgorithmIdentifier never presents) and
|
|
583
|
-
// children[2] (a SEQUENCE MacData or absent, never PKCS#8's OCTET STRING).
|
|
584
493
|
function matches(root) {
|
|
585
494
|
var k = pkix.rootSequenceChildren(root, 2, 3);
|
|
586
495
|
if (!k) return false;
|