@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-cmp.js
CHANGED
|
@@ -54,20 +54,15 @@ var OID_CONFIRM_WAIT_TIME = oid.byName("confirmWaitTime");
|
|
|
54
54
|
var OID_CERT_PROFILE = oid.byName("certProfile");
|
|
55
55
|
var OID_PKI_ARCHIVE_OPTIONS = oid.byName("pkiArchiveOptions");
|
|
56
56
|
|
|
57
|
-
// ---- leaves -----------------------------------------------------------
|
|
58
57
|
|
|
59
|
-
// CMP times are GeneralizedTime only; PKIFreeText elements are UTF8String
|
|
60
|
-
// (RFC 9810 sec. 5.1.1). Both ride the shared pkix leaf factories.
|
|
61
58
|
var GENERALIZED_TIME = pkix.generalizedTime(NS, { code: "cmp/bad-time", message: "CMP times must be GeneralizedTime (RFC 9810 sec. 5.1.1)" });
|
|
62
59
|
var UTF8_TEXT = pkix.utf8Text(NS, { code: "cmp/bad-freetext", message: "PKIFreeText elements must be UTF8String (RFC 9810 sec. 5.1.1)" });
|
|
63
60
|
|
|
64
|
-
// PKIFreeText ::= SEQUENCE SIZE (1..MAX) OF UTF8String.
|
|
65
61
|
var PKI_FREE_TEXT = schema.seqOf(UTF8_TEXT, {
|
|
66
62
|
min: 1, code: "cmp/bad-freetext", what: "PKIFreeText",
|
|
67
63
|
build: function (m) { return m.items.map(function (it) { return it.value; }); },
|
|
68
64
|
});
|
|
69
65
|
|
|
70
|
-
// PKIStatus ::= INTEGER {0..6} (sec. 5.2.3): a value whitelist, surfaced named.
|
|
71
66
|
var PKI_STATUS_NAMES = ["accepted", "grantedWithMods", "rejection", "waiting",
|
|
72
67
|
"revocationWarning", "revocationNotification", "keyUpdateWarning"];
|
|
73
68
|
var PKI_STATUS = schema.decode(function (n, ctx) {
|
|
@@ -77,9 +72,6 @@ var PKI_STATUS = schema.decode(function (n, ctx) {
|
|
|
77
72
|
return { code: code, name: PKI_STATUS_NAMES[code] };
|
|
78
73
|
});
|
|
79
74
|
|
|
80
|
-
// PKIFailureInfo ::= BIT STRING named bits 0..26 (sec. 5.2.3). X.690 sec. 11.2.2:
|
|
81
|
-
// a named-bit BIT STRING drops trailing zero bits, so the final carried bit
|
|
82
|
-
// must be 1. Bits past 26 are extensible and surface as numeric indexes.
|
|
83
75
|
var FAIL_INFO_NAMES = ["badAlg", "badMessageCheck", "badRequest", "badTime", "badCertId",
|
|
84
76
|
"badDataFormat", "wrongAuthority", "incorrectData", "missingTimeStamp", "badPOP",
|
|
85
77
|
"certRevoked", "certConfirmed", "wrongIntegrity", "badRecipientNonce", "timeNotAvailable",
|
|
@@ -97,18 +89,10 @@ var PKI_FAILURE_INFO = schema.decode(function (n, ctx) {
|
|
|
97
89
|
return { bits: bits, raw: bs };
|
|
98
90
|
});
|
|
99
91
|
|
|
100
|
-
// PollRep checkAfter is a delay in seconds; a negative one poisons scheduling, and
|
|
101
|
-
// the value surfaces as an exact number or not at all.
|
|
102
92
|
var CHECK_AFTER = schema.decode(function (n, ctx) {
|
|
103
93
|
return guard.range.uint31(asn1.read.integer(n), ctx.E, "cmp/bad-poll-rep", "checkAfter delay in seconds (RFC 9810 sec. 5.3.22)");
|
|
104
94
|
});
|
|
105
95
|
|
|
106
|
-
// A raw certificate / CRL / publication-info element, surfaced byte-exact for
|
|
107
|
-
// downstream parsing, but structurally a universal SEQUENCE: a CMPCertificate
|
|
108
|
-
// is a Certificate, and CertificateList / PKIPublicationInfo are SEQUENCEs, so
|
|
109
|
-
// a primitive (an INTEGER) or wrong-tag element is not a valid structure and
|
|
110
|
-
// rejects, never handing arbitrary bytes to certificate processing. The
|
|
111
|
-
// `code` names the containing structure (a shared leaf cannot know its context).
|
|
112
96
|
function rawSequence(code) {
|
|
113
97
|
return pkix.rawNonEmptySequence(NS, { code: code, message: "expected a non-empty universal SEQUENCE (Certificate / CertificateList / PKIPublicationInfo)" });
|
|
114
98
|
}
|
|
@@ -117,12 +101,7 @@ var GENERAL_NAME = pkix.generalName(NS, { decodeValue: true });
|
|
|
117
101
|
var ALG_ID = pkix.algorithmIdentifier(NS);
|
|
118
102
|
var EXTENSIONS = pkix.extensions(NS);
|
|
119
103
|
|
|
120
|
-
// ---- header ------------------------------------------------------------
|
|
121
104
|
|
|
122
|
-
// InfoTypeAndValue ::= SEQUENCE { infoType OID, infoValue ANY OPTIONAL }
|
|
123
|
-
// (sec. 5.1.1, sec. 5.3.19). Recognized id-it types with a fixed value syntax are
|
|
124
|
-
// validated (the CMS signed-attr value-syntax posture); all others surface
|
|
125
|
-
// raw with the registry name resolving.
|
|
126
105
|
var INFO_TYPE_AND_VALUE = schema.seq([
|
|
127
106
|
schema.field("infoType", schema.oidLeaf()),
|
|
128
107
|
schema.optional("infoValue", schema.any(), { whenAny: true }),
|
|
@@ -131,19 +110,10 @@ var INFO_TYPE_AND_VALUE = schema.seq([
|
|
|
131
110
|
build: function (m, ctx) {
|
|
132
111
|
var t = m.fields.infoType.value;
|
|
133
112
|
var valueNode = m.fields.infoValue.present ? m.fields.infoValue.value : null;
|
|
134
|
-
// A recognized id-it type with a FIXED value syntax (RFC 9810 sec. 5.1.1) MUST
|
|
135
|
-
// carry its infoValue -- implicitConfirm a NULL, confirmWaitTime a
|
|
136
|
-
// GeneralizedTime, certProfile a SEQUENCE OF UTF8String. A missing value is
|
|
137
|
-
// accepted only for the open / query id-it types (a bare OID in a genm body),
|
|
138
|
-
// never for a type whose value syntax the RFC defines.
|
|
139
113
|
if ((t === OID_IMPLICIT_CONFIRM || t === OID_CONFIRM_WAIT_TIME || t === OID_CERT_PROFILE) && valueNode === null) {
|
|
140
114
|
throw ctx.E("cmp/bad-info-value", "a recognized fixed-syntax id-it (implicitConfirm / confirmWaitTime / certProfile) must carry its infoValue (RFC 9810 sec. 5.1.1)");
|
|
141
115
|
}
|
|
142
116
|
if (valueNode !== null) {
|
|
143
|
-
// A recognized id-it value is validated by content, not just tag: run the
|
|
144
|
-
// strict typed reader so a well-tagged but malformed payload (a non-empty
|
|
145
|
-
// NULL, a GeneralizedTime carrying garbage, an invalid-UTF-8 string)
|
|
146
|
-
// rejects and is never surfaced as valid CMP.
|
|
147
117
|
if (t === OID_IMPLICIT_CONFIRM) {
|
|
148
118
|
if (!(valueNode.tagClass === "universal" && valueNode.tagNumber === TAGS.NULL)) {
|
|
149
119
|
throw ctx.E("cmp/bad-info-value", "an implicitConfirm value must be NULL (RFC 9810 sec. 5.1.1.1)");
|
|
@@ -182,8 +152,6 @@ var GENERAL_INFO = schema.seqOf(INFO_TYPE_AND_VALUE, {
|
|
|
182
152
|
build: function (m) { return m.items.map(function (it) { return it.value.result; }); },
|
|
183
153
|
});
|
|
184
154
|
|
|
185
|
-
// PKIHeader ::= SEQUENCE { pvno, sender, recipient, then EXPLICIT [0]..[8]
|
|
186
|
-
// optionals, ascending, at-most-once } (sec. 5.1.1).
|
|
187
155
|
var PKI_HEADER = schema.seq([
|
|
188
156
|
schema.field("pvno", pkix.versionReader(NS, { "1": 1, "2": 2, "3": 3 })),
|
|
189
157
|
schema.field("sender", GENERAL_NAME),
|
|
@@ -220,9 +188,7 @@ var PKI_HEADER = schema.seq([
|
|
|
220
188
|
},
|
|
221
189
|
});
|
|
222
190
|
|
|
223
|
-
// ---- decoded body arms ---------------------------------------------------
|
|
224
191
|
|
|
225
|
-
// PKIStatusInfo ::= SEQUENCE { status, statusString OPTIONAL, failInfo OPTIONAL } (sec. 5.2.3).
|
|
226
192
|
var PKI_STATUS_INFO = schema.seq([
|
|
227
193
|
schema.field("status", PKI_STATUS),
|
|
228
194
|
schema.optional("statusString", PKI_FREE_TEXT, { whenUniversal: [TAGS.SEQUENCE] }),
|
|
@@ -238,8 +204,6 @@ var PKI_STATUS_INFO = schema.seq([
|
|
|
238
204
|
},
|
|
239
205
|
});
|
|
240
206
|
|
|
241
|
-
// ErrorMsgContent ::= SEQUENCE { pKIStatusInfo, errorCode INTEGER OPTIONAL,
|
|
242
|
-
// errorDetails PKIFreeText OPTIONAL } (sec. 5.3.21).
|
|
243
207
|
var ERROR_MSG_CONTENT = schema.seq([
|
|
244
208
|
schema.field("pKIStatusInfo", PKI_STATUS_INFO),
|
|
245
209
|
schema.optional("errorCode", schema.integerLeaf(), { whenUniversal: [TAGS.INTEGER] }),
|
|
@@ -255,8 +219,6 @@ var ERROR_MSG_CONTENT = schema.seq([
|
|
|
255
219
|
},
|
|
256
220
|
});
|
|
257
221
|
|
|
258
|
-
// CertStatus ::= SEQUENCE { certHash, certReqId, statusInfo OPTIONAL,
|
|
259
|
-
// hashAlg [0] OPTIONAL } (sec. 5.3.18). certReqId accepts the -1 sentinel.
|
|
260
222
|
var CERT_STATUS = schema.seq([
|
|
261
223
|
schema.field("certHash", schema.octetString()),
|
|
262
224
|
schema.field("certReqId", schema.integerLeaf()),
|
|
@@ -276,23 +238,16 @@ var CERT_STATUS = schema.seq([
|
|
|
276
238
|
},
|
|
277
239
|
});
|
|
278
240
|
|
|
279
|
-
// CertConfirmContent ::= SEQUENCE OF CertStatus, where an empty sequence is legal
|
|
280
|
-
// (reject-all, sec. 5.3.18), so no SIZE floor.
|
|
281
241
|
var CERT_CONFIRM_CONTENT = schema.seqOf(CERT_STATUS, {
|
|
282
242
|
code: "cmp/bad-cert-status", what: "CertConfirmContent",
|
|
283
243
|
build: function (m) { return m.items.map(function (it) { return it.value.result; }); },
|
|
284
244
|
});
|
|
285
245
|
|
|
286
|
-
// GenMsgContent / GenRepContent ::= SEQUENCE OF InfoTypeAndValue, with no SIZE
|
|
287
|
-
// bound, empty legal (sec. 5.3.19/.20).
|
|
288
246
|
var GEN_MSG_CONTENT = schema.seqOf(INFO_TYPE_AND_VALUE, {
|
|
289
247
|
code: "cmp/bad-info-type-and-value", what: "GenMsgContent",
|
|
290
248
|
build: function (m) { return m.items.map(function (it) { return it.value.result; }); },
|
|
291
249
|
});
|
|
292
250
|
|
|
293
|
-
// RevDetails ::= SEQUENCE { certDetails CertTemplate, crlEntryDetails
|
|
294
|
-
// Extensions OPTIONAL } (sec. 5.3.9). The CertTemplate interior (an IMPLICIT
|
|
295
|
-
// TAGS module) is owned by the CRMF parser and walked NS-bound there.
|
|
296
251
|
var CERT_TEMPLATE_LEAF = schema.decode(function (n) { return crmf.walkCertTemplate(n); });
|
|
297
252
|
var REV_DETAILS = schema.seq([
|
|
298
253
|
schema.field("certDetails", CERT_TEMPLATE_LEAF),
|
|
@@ -311,7 +266,6 @@ var REV_REQ_CONTENT = schema.seqOf(REV_DETAILS, {
|
|
|
311
266
|
build: function (m) { return m.items.map(function (it) { return it.value.result; }); },
|
|
312
267
|
});
|
|
313
268
|
|
|
314
|
-
// CertId ::= SEQUENCE { issuer GeneralName, serialNumber INTEGER } (RFC 4211).
|
|
315
269
|
var CERT_ID = schema.seq([
|
|
316
270
|
schema.field("issuer", GENERAL_NAME),
|
|
317
271
|
schema.field("serialNumber", schema.integerLeaf()),
|
|
@@ -322,8 +276,6 @@ var CERT_ID = schema.seq([
|
|
|
322
276
|
},
|
|
323
277
|
});
|
|
324
278
|
|
|
325
|
-
// RevRepContent ::= SEQUENCE { status SIZE(1..MAX), revCerts [0] OPTIONAL,
|
|
326
|
-
// crls [1] OPTIONAL } (sec. 5.3.10).
|
|
327
279
|
var REV_REP_CONTENT = schema.seq([
|
|
328
280
|
schema.field("status", schema.seqOf(PKI_STATUS_INFO, {
|
|
329
281
|
min: 1, code: "cmp/bad-rev-rep", what: "RevRep status",
|
|
@@ -350,24 +302,9 @@ var REV_REP_CONTENT = schema.seq([
|
|
|
350
302
|
},
|
|
351
303
|
});
|
|
352
304
|
|
|
353
|
-
// EncryptedKey ::= CHOICE { encryptedValue EncryptedValue (deprecated),
|
|
354
|
-
// envelopedData [0] EnvelopedData } (sec. 5.2.2). EncryptedKey is imported from
|
|
355
|
-
// the RFC 4211 CRMF module, which is IMPLICIT TAGS, so `envelopedData [0]` is
|
|
356
|
-
// an IMPLICIT context tag replacing the EnvelopedData SEQUENCE tag: the [0]
|
|
357
|
-
// node's children are the EnvelopedData fields, with no inner wrapper. Retag it to
|
|
358
|
-
// the universal SEQUENCE the CMS walker expects, exactly as the sibling CRMF
|
|
359
|
-
// `encryptedKey [4] EnvelopedData` POP arm does (schema-crmf.js). The
|
|
360
|
-
// deprecated encryptedValue arm surfaces raw and is never field-walked, so nothing
|
|
361
|
-
// dereferences its optional interior (absent algorithm parameters crash
|
|
362
|
-
// consumers that walk it blindly).
|
|
363
305
|
var ENCRYPTED_KEY = schema.choice([
|
|
364
306
|
{ when: { tagClass: "universal", tagNumber: TAGS.SEQUENCE },
|
|
365
307
|
schema: schema.decode(function (n, ctx) {
|
|
366
|
-
// An RFC 4211 sec. 2 EncryptedValue REQUIRES encValue (its final BIT STRING
|
|
367
|
-
// field), so an empty SEQUENCE has the right tag but is not any valid
|
|
368
|
-
// EncryptedValue. Require at least one child, so no degenerate structure
|
|
369
|
-
// surfaces as encrypted certificate/key bytes (the same
|
|
370
|
-
// non-empty rule every raw-SEQUENCE surface in this module applies).
|
|
371
308
|
if (!(n.children && n.children.length >= 1)) {
|
|
372
309
|
throw ctx.E("cmp/bad-cert-response", "an EncryptedValue must be a non-empty SEQUENCE (RFC 4211 sec. 2)");
|
|
373
310
|
}
|
|
@@ -376,25 +313,13 @@ var ENCRYPTED_KEY = schema.choice([
|
|
|
376
313
|
{ when: { tagClass: "context", tagNumber: 0 },
|
|
377
314
|
schema: schema.decode(function (n, ctx) {
|
|
378
315
|
var env;
|
|
379
|
-
// Wrap every EnvelopedData failure -- a non-decodable retarget OR a CmsError
|
|
380
|
-
// from the composed walker -- as the CMP domain error (with the original as
|
|
381
|
-
// the cause), so cmp.parse never escapes with a cms/* error for a malformed
|
|
382
|
-
// PKIMessage (the same wrapping the sibling CRMF encryptedKey POP arm does).
|
|
383
316
|
try { env = cms.walkEnvelopedData(asn1.decode(asn1.sequenceTlv(n))); }
|
|
384
317
|
catch (e) {
|
|
385
318
|
throw ctx.E("cmp/bad-cert-response", "envelopedData [0] must be a well-formed IMPLICIT EnvelopedData (RFC 9810 sec. 5.2.2)", e);
|
|
386
319
|
}
|
|
387
|
-
// RFC 9810 sec. 5.2.2 -- a CMP EncryptedKey EnvelopedData is addressed to
|
|
388
|
-
// exactly one recipient (the end entity for a delivered cert / key). CMS
|
|
389
|
-
// permits RecipientInfos SET SIZE 1..MAX, so the single-recipient bound is
|
|
390
|
-
// CMP's: more than one recipient is a malformed EncryptedKey.
|
|
391
320
|
if (env.recipientInfos.length !== 1) {
|
|
392
321
|
throw ctx.E("cmp/bad-cert-response", "an EncryptedKey EnvelopedData must contain exactly one RecipientInfo (RFC 9810 sec. 5.2.2)");
|
|
393
322
|
}
|
|
394
|
-
// The ciphertext is the encrypted certificate / private key here, so an
|
|
395
|
-
// EnvelopedData with no ciphertext to decrypt, whether absent (detached, CMS
|
|
396
|
-
// permits it) or present-but-empty, must reject (RFC 9810 sec. 5.2.2/sec. 5.3.4;
|
|
397
|
-
// the same rule the CRMF encryptedKey POP arm enforces).
|
|
398
323
|
var ct = env.encryptedContentInfo.encryptedContent;
|
|
399
324
|
if (ct === null || ct.length === 0) {
|
|
400
325
|
throw ctx.E("cmp/bad-cert-response", "an EncryptedKey envelopedData must carry non-empty attached ciphertext -- its encryptedContent is the certificate/key payload (RFC 9810 sec. 5.2.2)");
|
|
@@ -403,7 +328,6 @@ var ENCRYPTED_KEY = schema.choice([
|
|
|
403
328
|
}) },
|
|
404
329
|
], { code: "cmp/bad-cert-response", what: "EncryptedKey" });
|
|
405
330
|
|
|
406
|
-
// CertOrEncCert ::= CHOICE { certificate [0], encryptedCert [1] } (sec. 5.3.4).
|
|
407
331
|
var CERT_OR_ENC_CERT = schema.choice([
|
|
408
332
|
{ when: { tagClass: "context", tagNumber: 0 },
|
|
409
333
|
schema: schema.explicit(0, schema.decode(function (n, ctx) {
|
|
@@ -416,8 +340,6 @@ var CERT_OR_ENC_CERT = schema.choice([
|
|
|
416
340
|
schema: schema.explicit(1, ENCRYPTED_KEY, { code: "cmp/bad-cert-response" }) },
|
|
417
341
|
], { code: "cmp/bad-cert-response", what: "CertOrEncCert" });
|
|
418
342
|
|
|
419
|
-
// CertifiedKeyPair ::= SEQUENCE { certOrEncCert, privateKey [0] OPTIONAL,
|
|
420
|
-
// publicationInfo [1] OPTIONAL } (sec. 5.3.4).
|
|
421
343
|
var CERTIFIED_KEY_PAIR = schema.seq([
|
|
422
344
|
schema.field("certOrEncCert", CERT_OR_ENC_CERT),
|
|
423
345
|
schema.trailing([
|
|
@@ -436,8 +358,6 @@ var CERTIFIED_KEY_PAIR = schema.seq([
|
|
|
436
358
|
},
|
|
437
359
|
});
|
|
438
360
|
|
|
439
|
-
// CertResponse ::= SEQUENCE { certReqId INTEGER (the -1 sentinel is legal),
|
|
440
|
-
// status PKIStatusInfo, certifiedKeyPair OPTIONAL, rspInfo OPTIONAL } (sec. 5.3.4).
|
|
441
361
|
var CERT_RESPONSE = schema.seq([
|
|
442
362
|
schema.field("certReqId", schema.integerLeaf()),
|
|
443
363
|
schema.field("status", PKI_STATUS_INFO),
|
|
@@ -448,21 +368,10 @@ var CERT_RESPONSE = schema.seq([
|
|
|
448
368
|
build: function (m, ctx) {
|
|
449
369
|
var status = m.fields.status.value.result;
|
|
450
370
|
var certifiedKeyPair = m.fields.certifiedKeyPair.present ? m.fields.certifiedKeyPair.value.result : null;
|
|
451
|
-
// RFC 9810 sec. 5.3.4 -- only one of the failInfo (in PKIStatusInfo) and
|
|
452
|
-
// certifiedKeyPair fields can be present in a CertResponse: a rejection
|
|
453
|
-
// carries no certificate. Accepting both lets a caller keying off
|
|
454
|
-
// certifiedKeyPair process a certificate from a failed response.
|
|
455
371
|
if (status.failInfo !== null && certifiedKeyPair !== null) {
|
|
456
372
|
throw ctx.E("cmp/bad-cert-response",
|
|
457
373
|
"a CertResponse must not carry both failInfo and certifiedKeyPair (RFC 9810 sec. 5.3.4)");
|
|
458
374
|
}
|
|
459
|
-
// A certifiedKeyPair is present only when the status grants the certificate:
|
|
460
|
-
// accepted (0) or grantedWithMods (1). Any other status (rejection, waiting,
|
|
461
|
-
// the revocation / keyUpdate warnings) denies or defers the request, so a
|
|
462
|
-
// certificate under it is a malformed response even when no explicit failInfo
|
|
463
|
-
// bit is set (a rejection is commonly signaled by status alone). Keying the
|
|
464
|
-
// rule off failInfo presence alone would let a bare-rejection status ship a
|
|
465
|
-
// certificate (RFC 9810 sec. 5.3.4).
|
|
466
375
|
if (certifiedKeyPair !== null && status.status.code !== 0 && status.status.code !== 1) {
|
|
467
376
|
throw ctx.E("cmp/bad-cert-response",
|
|
468
377
|
"a CertResponse certifiedKeyPair is allowed only under a granting status (accepted or grantedWithMods) (RFC 9810 sec. 5.3.4)");
|
|
@@ -476,9 +385,6 @@ var CERT_RESPONSE = schema.seq([
|
|
|
476
385
|
},
|
|
477
386
|
});
|
|
478
387
|
|
|
479
|
-
// CertRepMessage ::= SEQUENCE { caPubs [1] OPTIONAL, response SEQUENCE OF
|
|
480
|
-
// CertResponse } (sec. 5.3.4), where the optional precedes the required field (the
|
|
481
|
-
// x509-version shape). caPubs surface raw: the parser confers no trust.
|
|
482
388
|
var CERT_REP_MESSAGE = schema.seq([
|
|
483
389
|
schema.optional("caPubs", schema.seqOf(rawSequence("cmp/bad-cert-rep"), {
|
|
484
390
|
min: 1, code: "cmp/bad-cert-rep", what: "caPubs",
|
|
@@ -498,12 +404,6 @@ var CERT_REP_MESSAGE = schema.seq([
|
|
|
498
404
|
},
|
|
499
405
|
});
|
|
500
406
|
|
|
501
|
-
// KeyRecRepContent ::= SEQUENCE { status PKIStatusInfo, newSigCert [0]
|
|
502
|
-
// Certificate OPTIONAL, caCerts [1] SEQUENCE OF Certificate OPTIONAL,
|
|
503
|
-
// keyPairHist [2] SEQUENCE OF CertifiedKeyPair OPTIONAL } (sec. 5.3.8). The
|
|
504
|
-
// keyPairHist CertifiedKeyPairs can carry the same EnvelopedData form as the
|
|
505
|
-
// enrollment responses, so krp is decoded (not surfaced raw) and the operator sees
|
|
506
|
-
// the status / key history and the cross-field EnvelopedData version check runs.
|
|
507
407
|
var KEY_REC_REP_CONTENT = schema.seq([
|
|
508
408
|
schema.field("status", PKI_STATUS_INFO),
|
|
509
409
|
schema.trailing([
|
|
@@ -529,7 +429,6 @@ var KEY_REC_REP_CONTENT = schema.seq([
|
|
|
529
429
|
},
|
|
530
430
|
});
|
|
531
431
|
|
|
532
|
-
// PollReqContent / PollRepContent (sec. 5.3.22) -- certReqId may be -1.
|
|
533
432
|
var POLL_REQ_ENTRY = schema.seq([
|
|
534
433
|
schema.field("certReqId", schema.integerLeaf()),
|
|
535
434
|
], {
|
|
@@ -559,16 +458,11 @@ var POLL_REP_CONTENT = schema.seqOf(POLL_REP_ENTRY, {
|
|
|
559
458
|
build: function (m) { return m.items.map(function (it) { return it.value.result; }); },
|
|
560
459
|
});
|
|
561
460
|
|
|
562
|
-
// ---- the 27-arm body dispatch ----------------------------------------------
|
|
563
461
|
|
|
564
|
-
// Tag -> arm name, verbatim from the PKIXCMP-2023 module (sec. 5.1.2). Every
|
|
565
|
-
// defined arm is at minimum recognized; a subset decodes structurally.
|
|
566
462
|
var BODY_ARMS = ["ir", "ip", "cr", "cp", "p10cr", "popdecc", "popdecr", "kur", "kup",
|
|
567
463
|
"krr", "krp", "rr", "rp", "ccr", "ccp", "ckuann", "cann", "rann", "crlann",
|
|
568
464
|
"pkiconf", "nested", "genm", "genp", "error", "certConf", "pollReq", "pollRep"];
|
|
569
|
-
// Arms carrying RFC 4211 CertReqMessages -- walked by the CRMF parser.
|
|
570
465
|
var CRMF_ARMS = { 0: true, 2: true, 7: true, 9: true, 13: true };
|
|
571
|
-
// Arms with a structural schema here.
|
|
572
466
|
var DECODED_ARMS = {
|
|
573
467
|
1: CERT_REP_MESSAGE, 3: CERT_REP_MESSAGE, 8: CERT_REP_MESSAGE, 14: CERT_REP_MESSAGE,
|
|
574
468
|
10: KEY_REC_REP_CONTENT,
|
|
@@ -578,12 +472,6 @@ var DECODED_ARMS = {
|
|
|
578
472
|
25: POLL_REQ_CONTENT, 26: POLL_REP_CONTENT,
|
|
579
473
|
};
|
|
580
474
|
|
|
581
|
-
// The open-CHOICE dispatch: tag -> arm name; walk where a schema exists;
|
|
582
|
-
// surface every other defined arm raw as { arm, tag, bytes }, where `decoded` is
|
|
583
|
-
// absent (not null) on raw arms, so its presence discriminates decoded-empty
|
|
584
|
-
// (pkiconf decodes to null) from recognized-undecoded. `nested` [20] is never
|
|
585
|
-
// auto-recursed: a self-nesting tower amplifies per-level walk products, so
|
|
586
|
-
// the operator re-feeds its bytes to parse explicitly.
|
|
587
475
|
var BODY = schema.decode(function (n, ctx) {
|
|
588
476
|
if (n.tagClass !== "context" || !n.children) {
|
|
589
477
|
throw ctx.E("cmp/bad-body", "PKIBody must be a constructed context-tagged CHOICE arm (RFC 9810 sec. 5.1.2)");
|
|
@@ -597,26 +485,15 @@ var BODY = schema.decode(function (n, ctx) {
|
|
|
597
485
|
var inner = n.children[0];
|
|
598
486
|
var out = { arm: BODY_ARMS[n.tagNumber], tag: n.tagNumber, bytes: inner.bytes };
|
|
599
487
|
if (CRMF_ARMS[n.tagNumber]) {
|
|
600
|
-
// ccr [13] cross-certification: RFC 9810 Appendix D.6 profiles its template
|
|
601
|
-
// with signingAlg present and version "v1 or v3" (both overriding RFC 4211
|
|
602
|
-
// sec. 5 for this one arm). Those relaxations are allowed. The D.6 profile
|
|
603
|
-
// also expects exactly one CertReqMsg, but sec. 5.3.11 defines a ccr as a
|
|
604
|
-
// CertReqMessages (SIZE (1..MAX)) and App. D is OPTIONAL, so the base parser
|
|
605
|
-
// does not enforce the single-request cardinality (an App. D.6 producer keeps
|
|
606
|
-
// to one by its own policy, sending multiple cross-certificates in separate
|
|
607
|
-
// messages); only the no-private-key restriction below is normative.
|
|
608
488
|
var isCcr = n.tagNumber === 13;
|
|
609
489
|
out.decoded = crmf.walkCertReqMessages(inner, { allowSigningAlg: isCcr, allowV1Version: isCcr });
|
|
610
490
|
} else if (DECODED_ARMS[n.tagNumber]) {
|
|
611
491
|
var match = schema.walk(DECODED_ARMS[n.tagNumber], inner, ctx);
|
|
612
492
|
out.decoded = match.result;
|
|
613
493
|
} else if (n.tagNumber === 19) {
|
|
614
|
-
// PKIConfirmContent ::= NULL (sec. 5.3.16).
|
|
615
494
|
if (!(inner.tagClass === "universal" && inner.tagNumber === TAGS.NULL)) {
|
|
616
495
|
throw ctx.E("cmp/bad-pkiconf", "PKIConfirmContent must be NULL (RFC 9810 sec. 5.3.16)");
|
|
617
496
|
}
|
|
618
|
-
// A NULL is well-formed only with empty content (X.690 sec. 8.8.2); the tag check
|
|
619
|
-
// alone would surface a non-empty NULL as a valid confirmation.
|
|
620
497
|
try { asn1.read.nullValue(inner); }
|
|
621
498
|
catch (e) { throw ctx.E("cmp/bad-pkiconf", "PKIConfirmContent must be an empty NULL (RFC 9810 sec. 5.3.16)", e); }
|
|
622
499
|
out.decoded = null;
|
|
@@ -624,12 +501,7 @@ var BODY = schema.decode(function (n, ctx) {
|
|
|
624
501
|
return out;
|
|
625
502
|
});
|
|
626
503
|
|
|
627
|
-
// ---- the message envelope -----------------------------------------------------
|
|
628
504
|
|
|
629
|
-
// PKIProtection ::= BIT STRING: raw bits for the external verifier. Every
|
|
630
|
-
// RFC 9481 MSG_SIG_ALG / MSG_MAC_ALG output is an octet string, so the BIT
|
|
631
|
-
// STRING must be octet-aligned; with no in-tree CMP verify layer this is
|
|
632
|
-
// enforced at parse (the posture the OCSP signature shares), fail-closed.
|
|
633
505
|
var PROTECTION = schema.decode(function (n, ctx) {
|
|
634
506
|
var bs;
|
|
635
507
|
try { bs = asn1.read.bitString(n); }
|
|
@@ -640,13 +512,6 @@ var PROTECTION = schema.decode(function (n, ctx) {
|
|
|
640
512
|
return { unusedBits: bs.unusedBits, bytes: bs.bytes };
|
|
641
513
|
});
|
|
642
514
|
|
|
643
|
-
// PKIMessage ::= SEQUENCE { header, body, protection [0] OPTIONAL,
|
|
644
|
-
// extraCerts [1] OPTIONAL } (sec. 5.1). The build runs the two cross-checks that
|
|
645
|
-
// span structures: protection presence <=> protectionAlg presence (sec. 5.1.1,
|
|
646
|
-
// both directions), and a certConf hashAlg requires pvno cmp2021(3)
|
|
647
|
-
// (sec. 5.3.18). headerBytes / bodyBytes are the exact wire slices protection is
|
|
648
|
-
// computed over (as DER-SEQUENCE(headerBytes || bodyBytes)), surfaced raw and
|
|
649
|
-
// never re-encoded.
|
|
650
515
|
var PKI_MESSAGE = schema.seq([
|
|
651
516
|
schema.field("header", PKI_HEADER),
|
|
652
517
|
schema.field("body", BODY),
|
|
@@ -675,12 +540,6 @@ var PKI_MESSAGE = schema.seq([
|
|
|
675
540
|
}
|
|
676
541
|
}
|
|
677
542
|
}
|
|
678
|
-
// RFC 9810 sec. 5.2.2 / sec. 7: EnvelopedData is cmp2021(3) syntax, so a response
|
|
679
|
-
// carrying it (an encryptedCert or a privateKey in the envelopedData form)
|
|
680
|
-
// under pvno < 3 is a version mismatch, the same version gate the certConf
|
|
681
|
-
// hashAlg rule applies. The deprecated EncryptedValue form is the pre-2021
|
|
682
|
-
// encoding and stays legal at pvno 2. CertifiedKeyPairs arrive both in the
|
|
683
|
-
// CertRepMessage `response` array (ip/cp/kup/ccp) and in the krp keyPairHist.
|
|
684
543
|
var ckps = [];
|
|
685
544
|
if (body.decoded && body.decoded.response) {
|
|
686
545
|
for (var r = 0; r < body.decoded.response.length; r++) {
|
|
@@ -698,17 +557,7 @@ var PKI_MESSAGE = schema.seq([
|
|
|
698
557
|
throw ctx.E("cmp/bad-version", "a response carrying EnvelopedData (encryptedCert or privateKey) requires CMP version cmp2021(3) (RFC 9810 sec. 5.2.2, sec. 7)");
|
|
699
558
|
}
|
|
700
559
|
}
|
|
701
|
-
// RFC 9810 sec. 5.3.12 -- a cross-certification response (ccp) reuses the
|
|
702
|
-
// CertRepMessage syntax "with the restriction that no encrypted private key
|
|
703
|
-
// can be sent": cross-certification certifies an existing CA's public key,
|
|
704
|
-
// so there is no key generation and CertifiedKeyPair.privateKey has no
|
|
705
|
-
// meaning. Reject a ccp that carries one; never surface the key
|
|
706
|
-
// material. The field stays legal in the enrollment responses (ip/cp/kup).
|
|
707
560
|
if (body.arm === "ccp" && body.decoded && body.decoded.response) {
|
|
708
|
-
// RFC 9810 Appendix D.6 profiles a one-way ccp as exactly one CertResponse (the mirror of the ccr
|
|
709
|
-
// one-CertReqMsg profile), but sec. 5.3.12 defines a ccp as a CertRepMessage (SIZE (1..MAX)) and App. D
|
|
710
|
-
// is OPTIONAL, so the base parser does not enforce the single-response cardinality; only the
|
|
711
|
-
// no-private-key restriction is normative.
|
|
712
561
|
for (var c = 0; c < body.decoded.response.length; c++) {
|
|
713
562
|
var ckpCcp = body.decoded.response[c].certifiedKeyPair;
|
|
714
563
|
if (ckpCcp && ckpCcp.privateKey !== null) {
|
|
@@ -716,25 +565,13 @@ var PKI_MESSAGE = schema.seq([
|
|
|
716
565
|
}
|
|
717
566
|
}
|
|
718
567
|
}
|
|
719
|
-
// RFC 9810 sec. 5.3.11: a cross-certification request (ccr) MUST NOT send the
|
|
720
|
-
// private key to the responding CA (the requesting CA generates and holds
|
|
721
|
-
// it). The private-key-carrying POP choices, encryptedKey (cmp2021) and the
|
|
722
|
-
// deprecated thisMessage (cmp2000), are therefore forbidden in a ccr; the
|
|
723
|
-
// MAC (dhMAC / agreeMAC) and indirect (subsequentMessage) methods carry no
|
|
724
|
-
// key. Checked before the version gate so a ccr always gets the ccr verdict.
|
|
725
568
|
if (body.arm === "ccr" && body.decoded && body.decoded.messages) {
|
|
726
569
|
for (var cc = 0; cc < body.decoded.messages.length; cc++) {
|
|
727
570
|
var ccrMsg = body.decoded.messages[cc];
|
|
728
|
-
// Via the POP: the encryptedKey / thisMessage POPOPrivKey choices carry
|
|
729
|
-
// the private key.
|
|
730
571
|
var ccrPopo = ccrMsg.popo;
|
|
731
572
|
if (ccrPopo && (ccrPopo.method === "encryptedKey" || ccrPopo.method === "thisMessage")) {
|
|
732
573
|
throw ctx.E("cmp/bad-body", "a cross-certification request (ccr) must not send the private key -- the " + ccrPopo.method + " POP choice is forbidden (RFC 9810 sec. 5.3.11)");
|
|
733
574
|
}
|
|
734
|
-
// Via a control: a pkiArchiveOptions control with the encryptedPrivKey [0]
|
|
735
|
-
// arm is the other private-key transport (sec. 5.2.8.3.1), likewise forbidden
|
|
736
|
-
// in a ccr. The control value is the raw PKIArchiveOptions CHOICE; the
|
|
737
|
-
// encryptedPrivKey arm is context tag [0].
|
|
738
575
|
var controls = ccrMsg.certReq.controls;
|
|
739
576
|
if (controls) {
|
|
740
577
|
for (var cn = 0; cn < controls.length; cn++) {
|
|
@@ -749,21 +586,12 @@ var PKI_MESSAGE = schema.seq([
|
|
|
749
586
|
}
|
|
750
587
|
}
|
|
751
588
|
}
|
|
752
|
-
// RFC 9810 sec. 5.2.8.3 -- the agreeMAC and encryptedKey POPOPrivKey choices are
|
|
753
|
-
// cmp2021(3) syntax; a request (ir/cr/kur/krr/ccr) whose proof-of-possession
|
|
754
|
-
// uses either under pvno < 3 is a version mismatch, the same gate the
|
|
755
|
-
// response EnvelopedData rule applies. The CRMF walker surfaces the chosen
|
|
756
|
-
// POPOPrivKey method on each message's popo.
|
|
757
589
|
if (body.decoded && body.decoded.messages) {
|
|
758
590
|
for (var q = 0; q < body.decoded.messages.length; q++) {
|
|
759
591
|
var popo = body.decoded.messages[q].popo;
|
|
760
592
|
if (popo && (popo.method === "agreeMAC" || popo.method === "encryptedKey") && header.pvno !== 3) {
|
|
761
593
|
throw ctx.E("cmp/bad-version", "a request POP using the agreeMAC or encryptedKey choice requires CMP version cmp2021(3) (RFC 9810 sec. 5.2.8.3)");
|
|
762
594
|
}
|
|
763
|
-
// sec. 5.2.8.3.1/sec. 7 -- the same key transport via a pkiArchiveOptions control
|
|
764
|
-
// whose encryptedPrivKey [0] EXPLICIT wraps the envelopedData-form
|
|
765
|
-
// EncryptedKey is cmp2021 syntax too (a ccr rejects the control outright
|
|
766
|
-
// above; the other request arms are version-gated here).
|
|
767
595
|
var archCtrls = body.decoded.messages[q].certReq.controls;
|
|
768
596
|
if (archCtrls && header.pvno !== 3) {
|
|
769
597
|
for (var ac = 0; ac < archCtrls.length; ac++) {
|
|
@@ -777,11 +605,6 @@ var PKI_MESSAGE = schema.seq([
|
|
|
777
605
|
}
|
|
778
606
|
}
|
|
779
607
|
}
|
|
780
|
-
// RFC 9810 sec. 5.1.1.4 -- the certProfile name count is bounded by the message
|
|
781
|
-
// body: a p10cr carries at most one; an ir/cr/kur no more names than its
|
|
782
|
-
// CertReqMsg count, a genm no more than its GenMsgContent InfoTypeAndValue
|
|
783
|
-
// count (the names map positionally to the body entries). An overlong list
|
|
784
|
-
// makes that mapping ambiguous, so reject it.
|
|
785
608
|
if (header.generalInfo) {
|
|
786
609
|
for (var gi = 0; gi < header.generalInfo.length; gi++) {
|
|
787
610
|
if (header.generalInfo[gi].type !== OID_CERT_PROFILE) continue;
|
|
@@ -795,22 +618,12 @@ var PKI_MESSAGE = schema.seq([
|
|
|
795
618
|
}
|
|
796
619
|
}
|
|
797
620
|
}
|
|
798
|
-
// RFC 9810 sec. 5.3.13/sec. 7 -- the cAKeyUpdAnnV3 [0] RootCaKeyUpdateContent CA key
|
|
799
|
-
// update form is cmp2021(3) syntax; a ckuann using it under pvno < 3 is a
|
|
800
|
-
// version mismatch. ckuann surfaces raw, so inspect its top-level tag: the
|
|
801
|
-
// deprecated cAKeyUpdAnnV2 is a universal SEQUENCE, the v3 form is [0].
|
|
802
621
|
if (body.arm === "ckuann" && header.pvno !== 3) {
|
|
803
622
|
var caKeyUpd = asn1.decode(body.bytes);
|
|
804
623
|
if (caKeyUpd.tagClass === "context" && caKeyUpd.tagNumber === 0) {
|
|
805
624
|
throw ctx.E("cmp/bad-version", "a ckuann using the cAKeyUpdAnnV3 [0] RootCaKeyUpdateContent form requires CMP version cmp2021(3) (RFC 9810 sec. 5.3.13, sec. 7)");
|
|
806
625
|
}
|
|
807
626
|
}
|
|
808
|
-
// RFC 9810 sec. 5.2.8.3.2/sec. 7 -- Challenge.encryptedRand [0] EnvelopedData is
|
|
809
|
-
// cmp2021(3) syntax (the replacement for the deprecated challenge field).
|
|
810
|
-
// popdecc surfaces raw, so inspect the already-decoded Challenges the same
|
|
811
|
-
// way the ckuann gate inspects its top-level tag: a Challenge carrying a
|
|
812
|
-
// context [0] (its only context-tagged field) under pvno < 3 is a version
|
|
813
|
-
// mismatch; a non-Challenges shape stays on the documented raw posture.
|
|
814
627
|
if (body.arm === "popdecc" && header.pvno !== 3) {
|
|
815
628
|
var challenges = asn1.decode(body.bytes);
|
|
816
629
|
if (challenges.tagClass === "universal" && challenges.tagNumber === TAGS.SEQUENCE && challenges.children) {
|
|
@@ -835,26 +648,12 @@ var PKI_MESSAGE = schema.seq([
|
|
|
835
648
|
},
|
|
836
649
|
});
|
|
837
650
|
|
|
838
|
-
// ---- support-message infoValue structures (RFC 9480 sec. 2.14-2.17) -----
|
|
839
|
-
//
|
|
840
|
-
// A genm / genp carries its payload as an ANY, so the InfoTypeAndValue leaf above
|
|
841
|
-
// surfaces it as raw bytes. These are the strict decoders for the four values RFC 9483
|
|
842
|
-
// sec. 4.3 defines, each a standalone parser so a malformed payload is refused with the
|
|
843
|
-
// same caps, minimal-encoding and trailing-byte rules the message itself is held to.
|
|
844
|
-
// The CMP module is EXPLICIT TAGS, so every context tag here wraps its value.
|
|
845
651
|
|
|
846
|
-
// CACertsValue ::= SEQUENCE SIZE (1..MAX) OF CMPCertificate. An absent infoValue is how
|
|
847
|
-
// "no CA certificate is available" is said (sec. 4.3.1), so an EMPTY sequence is malformed
|
|
848
|
-
// rather than a second spelling of the same answer.
|
|
849
652
|
var CA_CERTS_VALUE = schema.seqOf(rawSequence("cmp/bad-info-value"), {
|
|
850
653
|
min: 1, code: "cmp/bad-info-value", what: "CACertsValue",
|
|
851
654
|
build: function (m) { return m.items.map(function (it) { return it.value; }); },
|
|
852
655
|
});
|
|
853
656
|
|
|
854
|
-
// RootCaKeyUpdateContent ::= SEQUENCE { newWithNew CMPCertificate,
|
|
855
|
-
// newWithOld [0] CMPCertificate OPTIONAL, oldWithNew [1] CMPCertificate OPTIONAL }
|
|
856
|
-
// (RFC 9480 sec. 2.15). Both optionals are OPTIONAL in the syntax; RFC 9483 sec. 4.3.2
|
|
857
|
-
// requires newWithOld of a response, which the caller of this decoder enforces.
|
|
858
657
|
var ROOT_CA_KEY_UPDATE = schema.seq([
|
|
859
658
|
schema.field("newWithNew", rawSequence("cmp/bad-info-value")),
|
|
860
659
|
schema.trailing([
|
|
@@ -872,9 +671,6 @@ var ROOT_CA_KEY_UPDATE = schema.seq([
|
|
|
872
671
|
},
|
|
873
672
|
});
|
|
874
673
|
|
|
875
|
-
// AttributeTypeAndValue ::= SEQUENCE { type OBJECT IDENTIFIER, value ANY }, the element of
|
|
876
|
-
// the Controls that carries a CertReqTemplate keySpec (RFC 9480 sec. 2.16). The value stays
|
|
877
|
-
// raw here: which syntax it must have depends on the type, which sec. 4.3.3 constrains.
|
|
878
674
|
var ATTR_TYPE_AND_VALUE = schema.seq([
|
|
879
675
|
schema.field("type", schema.oidLeaf()),
|
|
880
676
|
schema.field("value", schema.any()),
|
|
@@ -886,9 +682,6 @@ var ATTR_TYPE_AND_VALUE = schema.seq([
|
|
|
886
682
|
},
|
|
887
683
|
});
|
|
888
684
|
|
|
889
|
-
// CertReqTemplateContent ::= SEQUENCE { certTemplate CertTemplate, keySpec Controls OPTIONAL }
|
|
890
|
-
// (RFC 9480 sec. 2.16). keySpec is untagged, so it is recognized by its universal SEQUENCE tag
|
|
891
|
-
// following the CertTemplate, which is itself IMPLICIT [tagged] by the CRMF module.
|
|
892
685
|
var CERT_REQ_TEMPLATE_VALUE = schema.seq([
|
|
893
686
|
schema.field("certTemplate", CERT_TEMPLATE_LEAF),
|
|
894
687
|
schema.optional("keySpec", schema.seqOf(ATTR_TYPE_AND_VALUE, {
|
|
@@ -905,7 +698,6 @@ var CERT_REQ_TEMPLATE_VALUE = schema.seq([
|
|
|
905
698
|
},
|
|
906
699
|
});
|
|
907
700
|
|
|
908
|
-
// CRLsValue ::= SEQUENCE SIZE (1..MAX) OF CertificateList (RFC 9480 sec. 2.17).
|
|
909
701
|
var CRLS_VALUE = schema.seqOf(rawSequence("cmp/bad-info-value"), {
|
|
910
702
|
min: 1, code: "cmp/bad-info-value", what: "CRLsValue",
|
|
911
703
|
build: function (m) { return m.items.map(function (it) { return it.value; }); },
|
|
@@ -914,18 +706,12 @@ var CRLS_VALUE = schema.seqOf(rawSequence("cmp/bad-info-value"), {
|
|
|
914
706
|
function _valueParser(what, topSchema) {
|
|
915
707
|
return pkix.makeParser({ pemLabel: "CMP", PemError: PemError, ErrorClass: CmpError, prefix: "cmp", what: what, topSchema: topSchema, ns: NS });
|
|
916
708
|
}
|
|
917
|
-
// @internal
|
|
709
|
+
// @internal
|
|
918
710
|
var readCaCerts = _valueParser("CACertsValue", CA_CERTS_VALUE);
|
|
919
711
|
var readRootCaKeyUpdate = _valueParser("RootCaKeyUpdateContent", ROOT_CA_KEY_UPDATE);
|
|
920
712
|
var readCertReqTemplate = _valueParser("CertReqTemplateValue", CERT_REQ_TEMPLATE_VALUE);
|
|
921
713
|
var readCrls = _valueParser("CRLsValue", CRLS_VALUE);
|
|
922
|
-
// A CertReqTemplate keySpec states a key requirement as an AlgorithmIdentifier (RFC 9480 sec. 2.16),
|
|
923
|
-
// which is the shared sub-schema every format already reads one with: `SEQUENCE { algorithm OID,
|
|
924
|
-
// parameters ANY OPTIONAL }` and nothing after it. Reading it through the same definition is what
|
|
925
|
-
// keeps a third field from passing as a well-formed one.
|
|
926
714
|
var readAlgorithmIdentifier = _valueParser("AlgorithmIdentifier", ALG_ID);
|
|
927
|
-
// A bare Name, so a caller-encoded issuer can be read back into the RDN sequence that guard-name's
|
|
928
|
-
// canonical comparison takes. pki.cmp.session binds a returned CRL to the issuer it asked for.
|
|
929
715
|
var readName = _valueParser("Name", pkix.name(NS));
|
|
930
716
|
|
|
931
717
|
/**
|
|
@@ -1039,13 +825,6 @@ function pemDecode(text, label) { return pkix.pemDecode(text, label || "CMP", Pe
|
|
|
1039
825
|
*/
|
|
1040
826
|
function pemEncode(der, label) { return pkix.pemEncode(der, label || "CMP", PemError); }
|
|
1041
827
|
|
|
1042
|
-
// A PKIMessage root is a SEQUENCE of 2-4 whose first child (PKIHeader) is a
|
|
1043
|
-
// SEQUENCE of >= 3 leading with a bare INTEGER (pvno) and whose second child
|
|
1044
|
-
// (PKIBody) is context-class constructed [0..26]. The one overlap in the
|
|
1045
|
-
// registry is one-directional: a 2-child PKIMessage with body ir [0] also
|
|
1046
|
-
// satisfies the shallow ocsp-request probe, so this detector registers AHEAD
|
|
1047
|
-
// of ocsp-request -- while every real OCSPRequest fails here (its tbsRequest
|
|
1048
|
-
// never leads with a bare INTEGER).
|
|
1049
828
|
function matches(root) {
|
|
1050
829
|
var k = pkix.rootSequenceChildren(root, 2, 4);
|
|
1051
830
|
if (!k) return false;
|
|
@@ -1062,7 +841,7 @@ module.exports = {
|
|
|
1062
841
|
pemDecode: pemDecode,
|
|
1063
842
|
pemEncode: pemEncode,
|
|
1064
843
|
matches: matches,
|
|
1065
|
-
// @internal
|
|
844
|
+
// @internal
|
|
1066
845
|
readCaCerts: readCaCerts,
|
|
1067
846
|
readRootCaKeyUpdate: readRootCaKeyUpdate,
|
|
1068
847
|
readCertReqTemplate: readCertReqTemplate,
|