@amritk/nish-aarch64-linux 0.13.0 → 0.15.0

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.
@@ -0,0 +1,1214 @@
1
+ /**
2
+ * `nish/crypto/x509` — DER, PEM and the X.509 certificates a WebTransport or
3
+ * TLS server holds: read a P-256 private key and a certificate chain out of
4
+ * PEM, and mint the short-lived self-signed ECDSA P-256 certificate a browser
5
+ * pins by its SHA-256.
6
+ *
7
+ * import { x509MintSelfSigned, x509CertificateHash, derToPem } from "nish/crypto/x509";
8
+ *
9
+ * const serial: u8[] = new Array<u8>(16);
10
+ * crypto.getRandomValues(serial);
11
+ * serial[0] = serial[0] & toU8(0x7f); // positive, so it stays 16 octets
12
+ * const der: u8[] | null = x509MintSelfSigned(priv, "localhost", toI64(Date.now()), 14, serial);
13
+ * // x509CertificateHash(der) is what serverCertificateHashes names;
14
+ * // derToPem(der, "CERTIFICATE") is the file a TLS stack loads.
15
+ *
16
+ * Written for this module from ITU-T X.690 (DER), RFC 5280 (the certificate
17
+ * profile), RFC 7468 (PEM's textual encoding), RFC 5915 and RFC 5208/5958 (the
18
+ * SEC1 and PKCS#8 private-key structures), RFC 5480 (the P-256 key's
19
+ * identifiers) and RFC 5758 (ecdsa-with-SHA256).
20
+ *
21
+ * **DER is read strictly.** X.690 §10 leaves one encoding per value, and a
22
+ * reader that accepts a second spelling gives a certificate two identities
23
+ * while its hash — which is what a browser pins — names only one. So a length
24
+ * must be definite and minimal (no `0x80`, no long form below 128, no leading
25
+ * zero length octet), an INTEGER must be minimal in two's complement, a tag
26
+ * must fit in one octet, every element must end inside its parent, and a
27
+ * certificate must end where its outer SEQUENCE does. Anything else answers
28
+ * `null`, never a panic. The reader looks at what this module uses — the
29
+ * version, serial, algorithms, names as opaque bytes, validity, the subject
30
+ * public key and the signature — and checks the order of what follows the key
31
+ * (`[1]`, `[2]`, `[3]`) without parsing extensions.
32
+ *
33
+ * **PEM is RFC 7468's strict grammar**, with standard base64 (`+` and `/`,
34
+ * padded with `=`), not `base64url`: 64 characters a line and a shorter last
35
+ * one, a `-----END` label equal to its `-----BEGIN`, no headers (so an
36
+ * RFC 1421 encrypted key is refused), and canonical base64 whose unused low
37
+ * bits are zero. Text between blocks is ignored, as RFC 7468 §5.2 allows, and
38
+ * so are blocks with another label; a line may end in CRLF.
39
+ *
40
+ * **The minted certificate** is what the WebTransport specification's
41
+ * `serverCertificateHashes` accepts (W3C WebTransport, "custom certificate
42
+ * requirements"): X.509 v3, an ECDSA P-256 key signed with ecdsa-with-SHA256,
43
+ * and a validity period of at most fourteen days — `notAfter - notBefore`,
44
+ * which is what Chromium compares, so `days` is 1 to 14. Subject and issuer
45
+ * are the same single common name, as a UTF8String. It carries **no
46
+ * extensions**: the specification requires none, a browser checking a pinned
47
+ * hash does no path building for basicConstraints or keyUsage to inform, and
48
+ * every extension would be one more field whose absence is part of the
49
+ * contract a hash pins. OpenSSL verifies it as its own trust anchor all the
50
+ * same (`tests/link/crypto_x509`'s header has the commands). The serial and
51
+ * the time are parameters so the golden certificate is deterministic; a caller
52
+ * passes `Date.now()` and random bytes.
53
+ *
54
+ * **Constant time.** A private key is the one secret that passes through here:
55
+ * it is base64-decoded from PEM, lifted out of its DER, and handed to
56
+ * `nish/crypto/p256`. Base64 maps a character to its sextet and back by
57
+ * arithmetic on range masks, as `nish/crypto/base64url` does, and folds a bad
58
+ * character into one word read after the whole text, so neither a branch nor a
59
+ * table index depends on the key's bytes. PEM's framing is found by comparing
60
+ * the start of each line with the fixed `-----BEGIN ` and `-----END `, which no
61
+ * base64 character matches, so those comparisons end on a line's first byte
62
+ * whatever the key is. The DER reader branches on tags and
63
+ * lengths, which are the key's public framing, and copies its 32 octets with a
64
+ * fixed loop. Signing is `p256SignSha256`, and checking a key against the
65
+ * public key stored beside it compares public values. None of this is under
66
+ * the disassembly check; it is discipline.
67
+ *
68
+ * Private names carry the `x509` prefix because a `std/` module's private
69
+ * functions share the importing program's flat symbol namespace
70
+ * (`docs/wp26-stdlib.md` §3e).
71
+ */
72
+ import { p256PublicKey, p256SignSha256, p256VerifySha256 } from "nish/crypto/p256"
73
+ import { sha256 } from "nish/crypto/sha256"
74
+
75
+ /** The longest validity `x509MintSelfSigned` writes, in days: WebTransport's two weeks. */
76
+ export const X509_MAX_DAYS: i32 = 14
77
+
78
+ /** Longest serial number, in content octets of its INTEGER (RFC 5280 §4.1.2.2). */
79
+ export const X509_MAX_SERIAL: i32 = 20
80
+
81
+ /** The longest common name minted, in bytes (RFC 5280 Appendix A's `ub-common-name`). */
82
+ const X509_MAX_COMMON_NAME: i32 = 64
83
+
84
+ /** What a time field reads as when it is not a valid RFC 5280 time: before any year the reader accepts. */
85
+ const X509_NO_TIME: i64 = -1000000000000
86
+
87
+ const X509_MS_PER_DAY: i64 = 86400000
88
+
89
+ // DER tags (X.690 §8, and the context tags RFC 5280 gives them).
90
+ const X509_TAG_INTEGER: i32 = 0x02
91
+ const X509_TAG_BIT_STRING: i32 = 0x03
92
+ const X509_TAG_OCTET_STRING: i32 = 0x04
93
+ const X509_TAG_OID: i32 = 0x06
94
+ const X509_TAG_UTF8_STRING: i32 = 0x0c
95
+ const X509_TAG_UTC_TIME: i32 = 0x17
96
+ const X509_TAG_GENERALIZED_TIME: i32 = 0x18
97
+ const X509_TAG_SEQUENCE: i32 = 0x30
98
+ const X509_TAG_SET: i32 = 0x31
99
+
100
+ /**
101
+ * One certificate, as `x509ParseCertificate` and `x509ParseChain` read it.
102
+ * The byte fields are copies, so the certificate outlives the text it was read
103
+ * from. Times are milliseconds since 1970-01-01 UTC, as `Date.now()` counts.
104
+ */
105
+ export class X509Certificate {
106
+ /** The whole certificate, as its SHA-256 is taken. */
107
+ der: u8[]
108
+ /** The DER of `tbsCertificate`, the bytes the signature covers. */
109
+ tbs: u8[]
110
+ /** The serial number's INTEGER contents, two's complement as encoded. */
111
+ serial: u8[]
112
+ /** The issuer Name's DER, whole, to compare with another certificate's `subject`. */
113
+ issuer: u8[]
114
+ /** The subject Name's DER, whole. */
115
+ subject: u8[]
116
+ /** The subjectPublicKey BIT STRING's octets: for a P-256 key, the 65-byte uncompressed point. */
117
+ publicKey: u8[]
118
+ /** The signatureValue BIT STRING's octets: for ECDSA, the DER `SEQUENCE { r, s }`. */
119
+ signature: u8[]
120
+ /** The first instant the certificate is valid, inclusive (RFC 5280 §4.1.2.5). */
121
+ notBefore: i64 = 0
122
+ /** The last instant it is valid, inclusive. */
123
+ notAfter: i64 = 0
124
+ /** Whether the key is id-ecPublicKey on prime256v1 (RFC 5480 §2.1.1), so `publicKey` is a P-256 point. */
125
+ p256: boolean = false
126
+ /** Whether the signature algorithm is ecdsa-with-SHA256 with its parameters absent (RFC 5758 §3.2). */
127
+ ecdsaSha256: boolean = false
128
+
129
+ constructor() {
130
+ this.der = []
131
+ this.tbs = []
132
+ this.serial = []
133
+ this.issuer = []
134
+ this.subject = []
135
+ this.publicKey = []
136
+ this.signature = []
137
+ }
138
+ }
139
+
140
+ // ---------------------------------------------------------------------------
141
+ // DER, reading (X.690 §8 and §10)
142
+ // ---------------------------------------------------------------------------
143
+
144
+ /** One element's identifier octet and where its contents lie: `der[start .. end)`. */
145
+ class X509DerElement {
146
+ tag: i32
147
+ /** Where the identifier octet is, so the whole element can be copied. */
148
+ at: i32
149
+ start: i32
150
+ end: i32
151
+
152
+ constructor(tag: i32, at: i32, start: i32, end: i32) {
153
+ this.tag = tag
154
+ this.at = at
155
+ this.start = start
156
+ this.end = end
157
+ }
158
+ }
159
+
160
+ /**
161
+ * The element whose identifier octet is at `der[at]`, or `null` unless its
162
+ * header and contents lie in `der[at .. limit)` and its length is DER's: definite
163
+ * (§10.1) and minimal (§8.1.3.5 note 2 with §10.1 — long form only from 128,
164
+ * with no leading zero octet). A tag needing more than one octet is refused,
165
+ * since nothing in a certificate or a key uses one; lengths past 2^31 - 1 are
166
+ * refused before they can overflow.
167
+ */
168
+ const x509DerRead = (der: u8[], at: i32, limit: i32): X509DerElement | null => {
169
+ if (at < 0 || limit > toI32(der.length) || at > limit - 2) {
170
+ return null
171
+ }
172
+ const tag: i32 = toI32(der[at])
173
+ if ((tag & 0x1f) === 0x1f) {
174
+ return null
175
+ }
176
+ let length: i32 = toI32(der[at + 1])
177
+ let start: i32 = at + 2
178
+ if (length >= 0x80) {
179
+ const count: i32 = length & 0x7f
180
+ // 0x80 alone is BER's indefinite length, which DER forbids.
181
+ if (count < 1 || count > 4 || count > limit - start) {
182
+ return null
183
+ }
184
+ if (toI32(der[start]) === 0 || (count === 4 && toI32(der[start]) >= 0x80)) {
185
+ return null
186
+ }
187
+ length = 0
188
+ for (let k: i32 = 0; k < count; k++) {
189
+ length = (length << 8) | toI32(der[start + k])
190
+ }
191
+ if (length < 0x80) {
192
+ return null
193
+ }
194
+ start = start + count
195
+ }
196
+ if (length > limit - start) {
197
+ return null
198
+ }
199
+ return new X509DerElement(tag, at, start, start + length)
200
+ }
201
+
202
+ /** `x509DerRead`, answering `null` also when the element's tag is not `tag`. */
203
+ const x509DerExpect = (der: u8[], at: i32, limit: i32, tag: i32): X509DerElement | null => {
204
+ const e: X509DerElement | null = x509DerRead(der, at, limit)
205
+ if (e === null || e.tag !== tag) {
206
+ return null
207
+ }
208
+ return e
209
+ }
210
+
211
+ /**
212
+ * The identifier octet at `der[at]` when `at` is inside `der[.. limit)`, else
213
+ * `-1`: how an optional element is looked for.
214
+ */
215
+ const x509DerPeek = (der: u8[], at: i32, limit: i32): i32 => {
216
+ if (at < 0 || at >= limit || at >= toI32(der.length)) {
217
+ return -1
218
+ }
219
+ return toI32(der[at])
220
+ }
221
+
222
+ /** A copy of `der[from .. to)`. */
223
+ const x509DerSlice = (der: u8[], from: i32, to: i32): u8[] => {
224
+ const out: u8[] = new Array<u8>(to - from)
225
+ for (let k: i32 = 0; k < toI32(out.length); k++) {
226
+ const i: i32 = from + k
227
+ // Always true for the callers' ranges, and what lets the load drop its check.
228
+ if (i >= 0 && i < toI32(der.length)) {
229
+ out[k] = der[i]
230
+ }
231
+ }
232
+ return out
233
+ }
234
+
235
+ /** A copy of the element whole, identifier and length octets included. */
236
+ const x509DerWhole = (der: u8[], e: X509DerElement): u8[] => x509DerSlice(der, e.at, e.end)
237
+
238
+ /** Whether two byte strings are equal. Both are public here. */
239
+ const x509BytesEqual = (a: u8[], b: u8[]): boolean => {
240
+ if (toI32(b.length) !== toI32(a.length)) {
241
+ return false
242
+ }
243
+ for (let k: i32 = 0; k < toI32(a.length); k++) {
244
+ if (k < toI32(b.length) && a[k] !== b[k]) {
245
+ return false
246
+ }
247
+ }
248
+ return true
249
+ }
250
+
251
+ /** Whether `e`'s contents are exactly `expected`, as an OID is recognised by its encoding. */
252
+ const x509DerContentsAre = (der: u8[], e: X509DerElement, expected: u8[]): boolean => {
253
+ const n: i32 = toI32(expected.length)
254
+ if (e.end - e.start !== n) {
255
+ return false
256
+ }
257
+ for (let k: i32 = 0; k < n; k++) {
258
+ if (der[e.start + k] !== expected[k]) {
259
+ return false
260
+ }
261
+ }
262
+ return true
263
+ }
264
+
265
+ /**
266
+ * Whether an INTEGER's contents are DER's (X.690 §8.3.2): at least one octet,
267
+ * and the first nine bits neither all zero nor all one, which would make the
268
+ * first octet redundant.
269
+ */
270
+ const x509DerIntegerMinimal = (der: u8[], e: X509DerElement): boolean => {
271
+ const n: i32 = e.end - e.start
272
+ if (n < 1) {
273
+ return false
274
+ }
275
+ if (n === 1) {
276
+ return true
277
+ }
278
+ const b0: i32 = toI32(der[e.start])
279
+ const b1: i32 = toI32(der[e.start + 1])
280
+ return !((b0 === 0 && b1 < 0x80) || (b0 === 0xff && b1 >= 0x80))
281
+ }
282
+
283
+ /** The value of a one-octet, non-negative INTEGER such as a version, or `-1`. */
284
+ const x509DerSmallInteger = (der: u8[], e: X509DerElement): i32 => {
285
+ if (e.tag !== X509_TAG_INTEGER || e.end - e.start !== 1 || toI32(der[e.start]) >= 0x80) {
286
+ return -1
287
+ }
288
+ return toI32(der[e.start])
289
+ }
290
+
291
+ /**
292
+ * The octets of a BIT STRING that has no unused bits, or `null`. Keys and
293
+ * signatures are whole octets, so the leading unused-bits count must be 0.
294
+ */
295
+ const x509DerBitStringOctets = (der: u8[], e: X509DerElement): u8[] | null => {
296
+ if (e.tag !== X509_TAG_BIT_STRING || e.end - e.start < 1 || toI32(der[e.start]) !== 0) {
297
+ return null
298
+ }
299
+ return x509DerSlice(der, e.start + 1, e.end)
300
+ }
301
+
302
+ /** `count` decimal digits at `der[at ..)` as a number, or `-1` if any is not a digit. */
303
+ const x509DerDigits = (der: u8[], at: i32, count: i32): i32 => {
304
+ let value: i32 = 0
305
+ for (let k: i32 = 0; k < count; k++) {
306
+ const d: i32 = toI32(der[at + k]) - 48
307
+ if (d < 0 || d > 9) {
308
+ return -1
309
+ }
310
+ value = value * 10 + d
311
+ }
312
+ return value
313
+ }
314
+
315
+ /** Whether `year` is a leap year of the Gregorian calendar. */
316
+ const x509IsLeapYear = (year: i32): boolean => (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0
317
+
318
+ /** Days in `month` (1 to 12) of `year`. */
319
+ const x509DaysInMonth = (year: i32, month: i32): i32 => {
320
+ if (month === 2) {
321
+ return x509IsLeapYear(year) ? 29 : 28
322
+ }
323
+ return month === 4 || month === 6 || month === 9 || month === 11 ? 30 : 31
324
+ }
325
+
326
+ /**
327
+ * Days from 1970-01-01 to `year`-`month`-`day`: the days of the years between,
328
+ * counted by the leap-year rule over whole years before each, and then the
329
+ * months of the year itself. `year` is at least 1.
330
+ */
331
+ const x509DaysFromCivil = (year: i32, month: i32, day: i32): i32 => {
332
+ const y: i32 = year - 1
333
+ const before: i32 = 365 * y + y / 4 - y / 100 + y / 400
334
+ // 1969 * 365 + 492 - 19 + 4: the same count for 1970.
335
+ let days: i32 = before - 719162
336
+ for (let m: i32 = 1; m < month; m++) {
337
+ days = days + x509DaysInMonth(year, m)
338
+ }
339
+ return days + day - 1
340
+ }
341
+
342
+ /**
343
+ * A UTCTime or GeneralizedTime in the forms RFC 5280 §4.1.2.5 allows —
344
+ * `YYMMDDHHMMSSZ` and `YYYYMMDDHHMMSSZ`, in UTC, with seconds and without a
345
+ * fraction — as milliseconds since 1970, or `X509_NO_TIME`. A two-digit year
346
+ * of 50 or more is 19YY and below 50 is 20YY (§4.1.2.5.1). Both forms are
347
+ * accepted for any year from 1950, though §4.1.2.5 asks issuers to use UTCTime
348
+ * through 2049; the fields must name a real date and a time before 24:00:00.
349
+ */
350
+ const x509DerTime = (der: u8[], e: X509DerElement): i64 => {
351
+ const n: i32 = e.end - e.start
352
+ let at: i32 = e.start
353
+ let year: i32 = 0
354
+ if (e.tag === X509_TAG_UTC_TIME && n === 13) {
355
+ year = x509DerDigits(der, at, 2)
356
+ if (year >= 0) {
357
+ year = year + (year >= 50 ? 1900 : 2000)
358
+ }
359
+ at = at + 2
360
+ } else if (e.tag === X509_TAG_GENERALIZED_TIME && n === 15) {
361
+ year = x509DerDigits(der, at, 4)
362
+ at = at + 4
363
+ } else {
364
+ return X509_NO_TIME
365
+ }
366
+ const month: i32 = x509DerDigits(der, at, 2)
367
+ const day: i32 = x509DerDigits(der, at + 2, 2)
368
+ const hour: i32 = x509DerDigits(der, at + 4, 2)
369
+ const minute: i32 = x509DerDigits(der, at + 6, 2)
370
+ const second: i32 = x509DerDigits(der, at + 8, 2)
371
+ if (toI32(der[at + 10]) !== 90 || year < 1950 || month < 1 || month > 12) {
372
+ return X509_NO_TIME
373
+ }
374
+ if (day < 1 || day > x509DaysInMonth(year, month) || hour < 0 || hour > 23) {
375
+ return X509_NO_TIME
376
+ }
377
+ if (minute < 0 || minute > 59 || second < 0 || second > 59) {
378
+ return X509_NO_TIME
379
+ }
380
+ const seconds: i32 = hour * 3600 + minute * 60 + second
381
+ return toI64(x509DaysFromCivil(year, month, day)) * X509_MS_PER_DAY + toI64(seconds) * 1000
382
+ }
383
+
384
+ /**
385
+ * The OID's contents octets (X.690 §8.19): the first two arcs as one
386
+ * subidentifier `40 * a + b`, then each arc in base 128, big-endian, with the
387
+ * top bit set on every octet but its last.
388
+ */
389
+ const x509DerOidContents = (arcs: i32[]): u8[] => {
390
+ const out: u8[] = []
391
+ for (let i: i32 = 1; i < toI32(arcs.length); i++) {
392
+ const arc: i32 = i === 1 ? arcs[0] * 40 + arcs[1] : arcs[i]
393
+ let shift: i32 = 28
394
+ while (shift > 0 && arc >> shift === 0) {
395
+ shift = shift - 7
396
+ }
397
+ while (shift > 0) {
398
+ out.push(toU8(((arc >> shift) & 0x7f) | 0x80))
399
+ shift = shift - 7
400
+ }
401
+ out.push(toU8(arc & 0x7f))
402
+ }
403
+ return out
404
+ }
405
+
406
+ /** ecdsa-with-SHA256, 1.2.840.10045.4.3.2 (RFC 5758 §3.2). */
407
+ const x509OidEcdsaSha256 = (): u8[] => x509DerOidContents([1, 2, 840, 10045, 4, 3, 2])
408
+
409
+ /** id-ecPublicKey, 1.2.840.10045.2.1 (RFC 5480 §2.1.1). */
410
+ const x509OidEcPublicKey = (): u8[] => x509DerOidContents([1, 2, 840, 10045, 2, 1])
411
+
412
+ /** secp256r1, also called prime256v1 and P-256: 1.2.840.10045.3.1.7 (RFC 5480 §2.1.1.1). */
413
+ const x509OidPrime256v1 = (): u8[] => x509DerOidContents([1, 2, 840, 10045, 3, 1, 7])
414
+
415
+ /** id-at-commonName, 2.5.4.3 (RFC 5280 Appendix A). */
416
+ const x509OidCommonName = (): u8[] => x509DerOidContents([2, 5, 4, 3])
417
+
418
+ /**
419
+ * Whether `der[start .. end)` is exactly one OID element equal to `oid` and
420
+ * nothing after it.
421
+ */
422
+ const x509DerIsOnlyOid = (der: u8[], start: i32, end: i32, oid: u8[]): boolean => {
423
+ const e: X509DerElement | null = x509DerExpect(der, start, end, X509_TAG_OID)
424
+ return e !== null && e.end === end && x509DerContentsAre(der, e, oid)
425
+ }
426
+
427
+ /**
428
+ * Whether an AlgorithmIdentifier SEQUENCE is `{ oid, params }` with `params`
429
+ * the named-curve OID given, or `{ oid }` alone when `params` is empty.
430
+ */
431
+ const x509DerIsAlgorithm = (der: u8[], alg: X509DerElement, oid: u8[], params: u8[]): boolean => {
432
+ if (alg.tag !== X509_TAG_SEQUENCE) {
433
+ return false
434
+ }
435
+ const id: X509DerElement | null = x509DerExpect(der, alg.start, alg.end, X509_TAG_OID)
436
+ if (id === null || !x509DerContentsAre(der, id, oid)) {
437
+ return false
438
+ }
439
+ if (toI32(params.length) === 0) {
440
+ return id.end === alg.end
441
+ }
442
+ return x509DerIsOnlyOid(der, id.end, alg.end, params)
443
+ }
444
+
445
+ /**
446
+ * A minimal, non-negative INTEGER right-aligned into `out[off .. off + 32)`,
447
+ * or `false` when it is negative, not minimal or wider than 32 octets once a
448
+ * sign octet is set aside.
449
+ */
450
+ const x509DerUnsignedInto = (der: u8[], e: X509DerElement, out: u8[], off: i32): boolean => {
451
+ if (!x509DerIntegerMinimal(der, e) || toI32(der[e.start]) >= 0x80) {
452
+ return false
453
+ }
454
+ let start: i32 = e.start
455
+ if (toI32(der[start]) === 0 && e.end - start > 1) {
456
+ start = start + 1
457
+ }
458
+ const n: i32 = e.end - start
459
+ if (n > 32) {
460
+ return false
461
+ }
462
+ for (let k: i32 = 0; k < n; k++) {
463
+ out[off + 32 - n + k] = der[start + k]
464
+ }
465
+ return true
466
+ }
467
+
468
+ /**
469
+ * `r || s`, 32 octets each, out of an ECDSA-Sig-Value `SEQUENCE { INTEGER r,
470
+ * INTEGER s }` (RFC 5480 §2.2 by way of RFC 3279 §2.2.3), or `null` unless it
471
+ * is exactly one with both integers minimal, positive and below 2^256.
472
+ */
473
+ const x509DerSignatureRS = (sig: u8[]): u8[] | null => {
474
+ const total: i32 = toI32(sig.length)
475
+ const seq: X509DerElement | null = x509DerExpect(sig, 0, total, X509_TAG_SEQUENCE)
476
+ if (seq === null || seq.end !== total) {
477
+ return null
478
+ }
479
+ const r: X509DerElement | null = x509DerExpect(sig, seq.start, seq.end, X509_TAG_INTEGER)
480
+ if (r === null) {
481
+ return null
482
+ }
483
+ const s: X509DerElement | null = x509DerExpect(sig, r.end, seq.end, X509_TAG_INTEGER)
484
+ if (s === null || s.end !== seq.end) {
485
+ return null
486
+ }
487
+ const out: u8[] = new Array<u8>(64)
488
+ if (!x509DerUnsignedInto(sig, r, out, 0) || !x509DerUnsignedInto(sig, s, out, 32)) {
489
+ return null
490
+ }
491
+ return out
492
+ }
493
+
494
+ // ---------------------------------------------------------------------------
495
+ // DER, writing
496
+ // ---------------------------------------------------------------------------
497
+
498
+ /** One element: `tag`, the minimal definite length of `contents` (X.690 §10.1), and `contents`. */
499
+ const x509DerTlv = (tag: i32, contents: u8[]): u8[] => {
500
+ const n: i32 = toI32(contents.length)
501
+ const out: u8[] = [toU8(tag)]
502
+ if (n < 0x80) {
503
+ out.push(toU8(n))
504
+ } else {
505
+ let count: i32 = 0
506
+ for (let v: i32 = n; v > 0; v = v >> 8) {
507
+ count = count + 1
508
+ }
509
+ out.push(toU8(0x80 | count))
510
+ for (let k: i32 = count - 1; k >= 0; k--) {
511
+ out.push(toU8((n >> (8 * k)) & 0xff))
512
+ }
513
+ }
514
+ for (let k: i32 = 0; k < toI32(contents.length); k++) {
515
+ out.push(contents[k])
516
+ }
517
+ return out
518
+ }
519
+
520
+ /** `parts` end to end. */
521
+ const x509DerConcat = (parts: u8[][]): u8[] => {
522
+ const out: u8[] = []
523
+ for (const part of parts) {
524
+ for (let k: i32 = 0; k < toI32(part.length); k++) {
525
+ out.push(part[k])
526
+ }
527
+ }
528
+ return out
529
+ }
530
+
531
+ /** A constructed element around `parts`: a SEQUENCE, a SET or an explicit context tag. */
532
+ const x509DerWrap = (tag: i32, parts: u8[][]): u8[] => x509DerTlv(tag, x509DerConcat(parts))
533
+
534
+ /**
535
+ * The INTEGER holding the non-negative big-endian `magnitude`: its leading
536
+ * zero octets dropped, and one put back when the top bit would read as a sign
537
+ * (X.690 §8.3). Zero is the single octet `00`.
538
+ */
539
+ const x509DerUnsignedInteger = (magnitude: u8[]): u8[] => {
540
+ const contents: u8[] = []
541
+ for (let k: i32 = 0; k < toI32(magnitude.length); k++) {
542
+ const octet: i32 = toI32(magnitude[k])
543
+ // The first significant octet: a sign octet in front of it if its top bit is set.
544
+ if (toI32(contents.length) === 0 && octet >= 0x80) {
545
+ contents.push(0)
546
+ }
547
+ if (toI32(contents.length) > 0 || octet !== 0) {
548
+ contents.push(toU8(octet))
549
+ }
550
+ }
551
+ if (toI32(contents.length) === 0) {
552
+ contents.push(0)
553
+ }
554
+ return x509DerTlv(X509_TAG_INTEGER, contents)
555
+ }
556
+
557
+ /** A BIT STRING of whole `octets`: the unused-bits count 0, then the octets. */
558
+ const x509DerBitString = (octets: u8[]): u8[] => {
559
+ const contents: u8[] = [0]
560
+ for (let k: i32 = 0; k < toI32(octets.length); k++) {
561
+ contents.push(octets[k])
562
+ }
563
+ return x509DerTlv(X509_TAG_BIT_STRING, contents)
564
+ }
565
+
566
+ /** `value` as `width` decimal digits, pushed onto `out`. */
567
+ const x509PushDigits = (out: u8[], value: i32, width: i32): void => {
568
+ let scale: i32 = 1
569
+ for (let k: i32 = 1; k < width; k++) {
570
+ scale = scale * 10
571
+ }
572
+ for (let k: i32 = 0; k < width; k++) {
573
+ out.push(toU8(((value / scale) % 10) + 48))
574
+ scale = scale / 10
575
+ }
576
+ }
577
+
578
+ /**
579
+ * The Time for `seconds` after 1970 (not negative, at most the last second of
580
+ * 9999), as RFC 5280 §4.1.2.5 has an issuer write it: UTCTime through 2049,
581
+ * GeneralizedTime from 2050, both in UTC with seconds.
582
+ */
583
+ const x509DerTimeAt = (seconds: i64): u8[] => {
584
+ let days: i32 = toI32(seconds / 86400)
585
+ const rest: i32 = toI32(seconds % 86400)
586
+ let year: i32 = 1970
587
+ while (days >= (x509IsLeapYear(year) ? 366 : 365)) {
588
+ days = days - (x509IsLeapYear(year) ? 366 : 365)
589
+ year = year + 1
590
+ }
591
+ let month: i32 = 1
592
+ while (days >= x509DaysInMonth(year, month)) {
593
+ days = days - x509DaysInMonth(year, month)
594
+ month = month + 1
595
+ }
596
+ const text: u8[] = []
597
+ const utc: boolean = year < 2050
598
+ x509PushDigits(text, utc ? year % 100 : year, utc ? 2 : 4)
599
+ x509PushDigits(text, month, 2)
600
+ x509PushDigits(text, days + 1, 2)
601
+ x509PushDigits(text, rest / 3600, 2)
602
+ x509PushDigits(text, (rest / 60) % 60, 2)
603
+ x509PushDigits(text, rest % 60, 2)
604
+ text.push(90)
605
+ return x509DerTlv(utc ? X509_TAG_UTC_TIME : X509_TAG_GENERALIZED_TIME, text)
606
+ }
607
+
608
+ /** The bytes of `text`, as the language holds a string. */
609
+ const x509Bytes = (text: string): u8[] => {
610
+ const out: u8[] = []
611
+ const n: i32 = toI32(text.length)
612
+ for (let k: i32 = 0; k < n; k++) {
613
+ out.push(toU8(toI32(text.charCodeAt(k))))
614
+ }
615
+ return out
616
+ }
617
+
618
+ // ---------------------------------------------------------------------------
619
+ // PEM (RFC 7468) and standard base64 (RFC 4648 §4)
620
+ // ---------------------------------------------------------------------------
621
+
622
+ /** All ones when `lo <= c <= hi`, else zero, without a branch; `c` is a byte or a sextet. */
623
+ const x509RangeMask = (c: i32, lo: i32, hi: i32): i32 => ((lo - 1 - c) & (c - hi - 1)) >> 31
624
+
625
+ /**
626
+ * The base64 character for the sextet `v`: `'A' + v`, stepped by the gap to
627
+ * each later range it has reached — 26 lands on `a`, 52 on `0`, 62 on `+` and
628
+ * 63 on `/`.
629
+ */
630
+ const x509Base64CharOf = (v: i32): i32 =>
631
+ 65 +
632
+ v +
633
+ (x509RangeMask(v, 26, 63) & 6) -
634
+ (x509RangeMask(v, 52, 63) & 75) -
635
+ (x509RangeMask(v, 62, 63) & 15) +
636
+ (x509RangeMask(v, 63, 63) & 3)
637
+
638
+ /** The sextet the byte `c` stands for in base64, or `-1` when it is not in the alphabet. */
639
+ const x509Base64SextetOf = (c: i32): i32 => {
640
+ const upper: i32 = x509RangeMask(c, 65, 90)
641
+ const lower: i32 = x509RangeMask(c, 97, 122)
642
+ const digit: i32 = x509RangeMask(c, 48, 57)
643
+ const plus: i32 = x509RangeMask(c, 43, 43)
644
+ const slash: i32 = x509RangeMask(c, 47, 47)
645
+ const value: i32 = (upper & (c - 65)) | (lower & (c - 71)) | (digit & (c + 4)) | (plus & 62) | (slash & 63)
646
+ return value | ~(upper | lower | digit | plus | slash)
647
+ }
648
+
649
+ /** `data` in padded base64, as one line. */
650
+ const x509Base64Encode = (data: u8[]): string => {
651
+ const parts: string[] = []
652
+ let acc: i32 = 0
653
+ let bits: i32 = 0
654
+ for (let k: i32 = 0; k < toI32(data.length); k++) {
655
+ acc = ((acc << 8) | toI32(data[k])) & 0xfff
656
+ bits = bits + 8
657
+ while (bits >= 6) {
658
+ bits = bits - 6
659
+ parts.push(String.fromCharCode(x509Base64CharOf((acc >> bits) & 63)))
660
+ }
661
+ }
662
+ if (bits > 0) {
663
+ parts.push(String.fromCharCode(x509Base64CharOf((acc << (6 - bits)) & 63)))
664
+ }
665
+ // One `=` for a final group of two bytes, two for one byte.
666
+ const tail: i32 = toI32(data.length) % 3
667
+ if (tail > 0) {
668
+ parts.push(tail === 1 ? "==" : "=")
669
+ }
670
+ return parts.join("")
671
+ }
672
+
673
+ /**
674
+ * The bytes of padded base64 `text`, or `null` unless it is the one canonical
675
+ * spelling of them: a whole number of four-character groups, `=` only as the
676
+ * last one or two characters, every other character in the alphabet, and the
677
+ * bits the padding leaves over all zero (RFC 4648 §3.5). Where the padding is
678
+ * depends on the length alone; the characters themselves are read by masks and
679
+ * judged once, after the last.
680
+ */
681
+ const x509Base64Decode = (text: string): u8[] | null => {
682
+ const n: i32 = toI32(text.length)
683
+ if (n === 0 || (n & 3) !== 0) {
684
+ return null
685
+ }
686
+ let pad: i32 = 0
687
+ if (toI32(text.charCodeAt(n - 1)) === 61) {
688
+ pad = toI32(text.charCodeAt(n - 2)) === 61 ? 2 : 1
689
+ }
690
+ const chars: i32 = n - pad
691
+ const out: u8[] = new Array<u8>((n >> 2) * 3 - pad)
692
+ const outLen: i32 = toI32(out.length)
693
+ let bad: i32 = 0
694
+ let acc: i32 = 0
695
+ let bits: i32 = 0
696
+ let j: i32 = 0
697
+ for (let k: i32 = 0; k < toI32(text.length); k++) {
698
+ // The padding is past `chars`, and is not data; which positions those are
699
+ // is a fact about the length.
700
+ if (k < chars) {
701
+ const v: i32 = x509Base64SextetOf(toI32(text.charCodeAt(k)))
702
+ bad = bad | (v >> 31)
703
+ acc = ((acc << 6) | (v & 63)) & 0xfff
704
+ bits = bits + 6
705
+ if (bits >= 8) {
706
+ bits = bits - 8
707
+ // Always true — `out` was sized from the same length — and written so
708
+ // the store keeps no bounds check.
709
+ if (j >= 0 && j < outLen) {
710
+ out[j] = toU8((acc >> bits) & 0xff)
711
+ }
712
+ j = j + 1
713
+ }
714
+ }
715
+ }
716
+ bad = bad | (acc & ((1 << bits) - 1))
717
+ if (bad !== 0) {
718
+ return null
719
+ }
720
+ return out
721
+ }
722
+
723
+ /** Whether `text` starts with `prefix`. */
724
+ const x509StartsWith = (text: string, prefix: string): boolean => {
725
+ const n: i32 = toI32(prefix.length)
726
+ return toI32(text.length) >= n && text.substring(0, n) === prefix
727
+ }
728
+
729
+ /** Whether `text` ends with `suffix`. */
730
+ const x509EndsWith = (text: string, suffix: string): boolean => {
731
+ const n: i32 = toI32(text.length)
732
+ const m: i32 = toI32(suffix.length)
733
+ return n >= m && text.substring(n - m, n) === suffix
734
+ }
735
+
736
+ /**
737
+ * `der` as a PEM block (RFC 7468 §2): `-----BEGIN label-----`, the base64 of
738
+ * the DER in lines of 64 characters, and `-----END label-----`, each line
739
+ * ending in a line feed.
740
+ */
741
+ export const derToPem = (der: u8[], label: string): string => {
742
+ const body: string = x509Base64Encode(der)
743
+ const n: i32 = toI32(body.length)
744
+ const lines: string[] = [`-----BEGIN ${label}-----`]
745
+ for (let at: i32 = 0; at < n; at = at + 64) {
746
+ lines.push(body.substring(at, at + 64 < n ? at + 64 : n))
747
+ }
748
+ lines.push(`-----END ${label}-----`)
749
+ lines.push("")
750
+ return lines.join("\n")
751
+ }
752
+
753
+ /**
754
+ * The DER of every PEM block in `pem` whose label is exactly `label`, in the
755
+ * order they appear, or `null` when there is none or any block is malformed:
756
+ * an unterminated block, an END whose label is not its BEGIN's, a line longer
757
+ * than 64 characters or a short line before the last, a header line, or
758
+ * base64 that is not canonical. Blocks with other labels must be as well
759
+ * formed, and are skipped; so is text outside the blocks.
760
+ */
761
+ export const pemToDer = (pem: string, label: string): u8[][] | null => {
762
+ const out: u8[][] = []
763
+ const n: i32 = toI32(pem.length)
764
+ // The label of the block being read, or "" outside one; its body lines so far.
765
+ let inside: string = ""
766
+ let body: string[] = []
767
+ let shortSeen: boolean = false
768
+ let lineStart: i32 = 0
769
+ while (lineStart < n) {
770
+ let lineEnd: i32 = lineStart
771
+ while (lineEnd >= 0 && lineEnd < toI32(pem.length) && toI32(pem.charCodeAt(lineEnd)) !== 10) {
772
+ lineEnd = lineEnd + 1
773
+ }
774
+ const next: i32 = lineEnd + 1
775
+ if (lineEnd > lineStart && toI32(pem.charCodeAt(lineEnd - 1)) === 13) {
776
+ lineEnd = lineEnd - 1
777
+ }
778
+ const line: string = pem.slice(lineStart, lineEnd)
779
+ lineStart = next
780
+ const length: i32 = toI32(line.length)
781
+ if (inside === "") {
782
+ if (x509StartsWith(line, "-----BEGIN ") && x509EndsWith(line, "-----") && length > 16) {
783
+ inside = line.substring(11, length - 5)
784
+ body = []
785
+ shortSeen = false
786
+ } else if (x509StartsWith(line, "-----END ")) {
787
+ return null
788
+ }
789
+ } else if (x509StartsWith(line, "-----END ")) {
790
+ if (line !== `-----END ${inside}-----`) {
791
+ return null
792
+ }
793
+ if (inside === label) {
794
+ const der: u8[] | null = x509Base64Decode(body.join(""))
795
+ if (der === null) {
796
+ return null
797
+ }
798
+ out.push(der)
799
+ }
800
+ inside = ""
801
+ } else {
802
+ if (shortSeen || length < 1 || length > 64) {
803
+ return null
804
+ }
805
+ shortSeen = length < 64
806
+ body.push(line)
807
+ }
808
+ }
809
+ if (inside !== "" || toI32(out.length) === 0) {
810
+ return null
811
+ }
812
+ return out
813
+ }
814
+
815
+ // ---------------------------------------------------------------------------
816
+ // Private keys (RFC 5915, RFC 5208 / RFC 5958)
817
+ // ---------------------------------------------------------------------------
818
+
819
+ /**
820
+ * The 32-byte scalar of an ECPrivateKey (RFC 5915 §3) filling `der[start ..
821
+ * end)`: version 1, the key as an OCTET STRING of exactly 32 octets, the
822
+ * optional `[0]` parameters, which must name prime256v1 and are required when
823
+ * `needCurve` (a bare SEC1 key has nowhere else to say its curve), and the
824
+ * optional `[1]` public key, which must be the key's own. `null` otherwise,
825
+ * or when the scalar is 0 or not below n.
826
+ */
827
+ const x509Sec1Key = (der: u8[], start: i32, end: i32, needCurve: boolean): u8[] | null => {
828
+ const seq: X509DerElement | null = x509DerExpect(der, start, end, X509_TAG_SEQUENCE)
829
+ if (seq === null || seq.end !== end) {
830
+ return null
831
+ }
832
+ const version: X509DerElement | null = x509DerRead(der, seq.start, seq.end)
833
+ if (version === null || x509DerSmallInteger(der, version) !== 1) {
834
+ return null
835
+ }
836
+ const key: X509DerElement | null = x509DerExpect(der, version.end, seq.end, X509_TAG_OCTET_STRING)
837
+ if (key === null || key.end - key.start !== 32) {
838
+ return null
839
+ }
840
+ const priv: u8[] = x509DerSlice(der, key.start, key.end)
841
+ let at: i32 = key.end
842
+ let curve: boolean = false
843
+ let stored: u8[] | null = null
844
+ if (x509DerPeek(der, at, seq.end) === 0xa0) {
845
+ const params: X509DerElement | null = x509DerRead(der, at, seq.end)
846
+ if (params === null || !x509DerIsOnlyOid(der, params.start, params.end, x509OidPrime256v1())) {
847
+ return null
848
+ }
849
+ curve = true
850
+ at = params.end
851
+ }
852
+ if (x509DerPeek(der, at, seq.end) === 0xa1) {
853
+ const wrapper: X509DerElement | null = x509DerRead(der, at, seq.end)
854
+ if (wrapper === null) {
855
+ return null
856
+ }
857
+ const bits: X509DerElement | null = x509DerExpect(der, wrapper.start, wrapper.end, X509_TAG_BIT_STRING)
858
+ if (bits === null || bits.end !== wrapper.end) {
859
+ return null
860
+ }
861
+ stored = x509DerBitStringOctets(der, bits)
862
+ if (stored === null) {
863
+ return null
864
+ }
865
+ at = wrapper.end
866
+ }
867
+ if (at !== seq.end || (needCurve && !curve)) {
868
+ return null
869
+ }
870
+ // Refuses 0 and n and above, and gives the point to hold `stored` against.
871
+ const pub: u8[] | null = p256PublicKey(priv)
872
+ if (pub === null) {
873
+ return null
874
+ }
875
+ if (stored !== null && !x509BytesEqual(stored, pub)) {
876
+ return null
877
+ }
878
+ return priv
879
+ }
880
+
881
+ /**
882
+ * The scalar of a PKCS#8 PrivateKeyInfo (RFC 5208 §5) or OneAsymmetricKey
883
+ * (RFC 5958 §2): version 0 or 1, the algorithm id-ecPublicKey with the
884
+ * prime256v1 curve, and an ECPrivateKey inside the OCTET STRING, followed by
885
+ * the optional `[0]` attributes and — in version 1 — `[1]` public key, which
886
+ * are skipped.
887
+ */
888
+ const x509Pkcs8Key = (der: u8[]): u8[] | null => {
889
+ const total: i32 = toI32(der.length)
890
+ const seq: X509DerElement | null = x509DerExpect(der, 0, total, X509_TAG_SEQUENCE)
891
+ if (seq === null || seq.end !== total) {
892
+ return null
893
+ }
894
+ const version: X509DerElement | null = x509DerRead(der, seq.start, seq.end)
895
+ if (version === null) {
896
+ return null
897
+ }
898
+ const v: i32 = x509DerSmallInteger(der, version)
899
+ if (v !== 0 && v !== 1) {
900
+ return null
901
+ }
902
+ const alg: X509DerElement | null = x509DerRead(der, version.end, seq.end)
903
+ if (alg === null || !x509DerIsAlgorithm(der, alg, x509OidEcPublicKey(), x509OidPrime256v1())) {
904
+ return null
905
+ }
906
+ const key: X509DerElement | null = x509DerExpect(der, alg.end, seq.end, X509_TAG_OCTET_STRING)
907
+ if (key === null) {
908
+ return null
909
+ }
910
+ let at: i32 = key.end
911
+ if (x509DerPeek(der, at, seq.end) === 0xa0) {
912
+ const attributes: X509DerElement | null = x509DerRead(der, at, seq.end)
913
+ if (attributes === null) {
914
+ return null
915
+ }
916
+ at = attributes.end
917
+ }
918
+ if (v === 1 && x509DerPeek(der, at, seq.end) === 0x81) {
919
+ const pub: X509DerElement | null = x509DerRead(der, at, seq.end)
920
+ if (pub === null) {
921
+ return null
922
+ }
923
+ at = pub.end
924
+ }
925
+ if (at !== seq.end) {
926
+ return null
927
+ }
928
+ return x509Sec1Key(der, key.start, key.end, false)
929
+ }
930
+
931
+ /**
932
+ * The 32-byte P-256 private key in `pem`: one `EC PRIVATE KEY` block (SEC1,
933
+ * RFC 5915, which must name its curve) or one `PRIVATE KEY` block (unencrypted
934
+ * PKCS#8, RFC 5208 or RFC 5958), and not both. `null` for no such block or
935
+ * more than one, for any curve but P-256, for a scalar of 0 or n or more, for
936
+ * a stored public key that is not the key's own, and for anything malformed.
937
+ * An `ENCRYPTED PRIVATE KEY` is a different label, and answers `null`.
938
+ */
939
+ export const x509ParseP256PrivateKey = (pem: string): u8[] | null => {
940
+ const sec1: u8[][] | null = pemToDer(pem, "EC PRIVATE KEY")
941
+ const pkcs8: u8[][] | null = pemToDer(pem, "PRIVATE KEY")
942
+ if (sec1 !== null && pkcs8 === null && toI32(sec1.length) === 1) {
943
+ const der: u8[] = sec1[0]
944
+ return x509Sec1Key(der, 0, toI32(der.length), true)
945
+ }
946
+ if (pkcs8 !== null && sec1 === null && toI32(pkcs8.length) === 1) {
947
+ return x509Pkcs8Key(pkcs8[0])
948
+ }
949
+ return null
950
+ }
951
+
952
+ // ---------------------------------------------------------------------------
953
+ // Certificates (RFC 5280 §4.1)
954
+ // ---------------------------------------------------------------------------
955
+
956
+ /**
957
+ * `der` read as one Certificate (RFC 5280 §4.1), or `null` unless it is
958
+ * exactly one in DER: `SEQUENCE { tbsCertificate, signatureAlgorithm,
959
+ * signatureValue }`, where tbsCertificate holds an explicit version of v2 or
960
+ * v3 or none (DER omits v1, the default), a minimal serial, an algorithm equal
961
+ * to the outer one byte for byte (§4.1.1.2), issuer and subject Names, a
962
+ * Validity of two valid times, a SubjectPublicKeyInfo whose key is whole
963
+ * octets, then only the optional `[1]` and `[2]` unique identifiers (v2 and
964
+ * v3) and `[3]` extensions (v3), in that order. Any algorithm and key type is
965
+ * read; `p256` and `ecdsaSha256` say whether they are this module's.
966
+ */
967
+ export const x509ParseCertificate = (der: u8[]): X509Certificate | null => {
968
+ const total: i32 = toI32(der.length)
969
+ const cert: X509DerElement | null = x509DerExpect(der, 0, total, X509_TAG_SEQUENCE)
970
+ if (cert === null || cert.end !== total) {
971
+ return null
972
+ }
973
+ const tbs: X509DerElement | null = x509DerExpect(der, cert.start, cert.end, X509_TAG_SEQUENCE)
974
+ if (tbs === null) {
975
+ return null
976
+ }
977
+ const outerAlg: X509DerElement | null = x509DerExpect(der, tbs.end, cert.end, X509_TAG_SEQUENCE)
978
+ if (outerAlg === null) {
979
+ return null
980
+ }
981
+ const sigValue: X509DerElement | null = x509DerExpect(der, outerAlg.end, cert.end, X509_TAG_BIT_STRING)
982
+ if (sigValue === null || sigValue.end !== cert.end) {
983
+ return null
984
+ }
985
+ const signature: u8[] | null = x509DerBitStringOctets(der, sigValue)
986
+ if (signature === null) {
987
+ return null
988
+ }
989
+
990
+ let at: i32 = tbs.start
991
+ let version: i32 = 0
992
+ if (x509DerPeek(der, at, tbs.end) === 0xa0) {
993
+ const explicit: X509DerElement | null = x509DerRead(der, at, tbs.end)
994
+ if (explicit === null) {
995
+ return null
996
+ }
997
+ const inner: X509DerElement | null = x509DerRead(der, explicit.start, explicit.end)
998
+ if (inner === null || inner.end !== explicit.end) {
999
+ return null
1000
+ }
1001
+ version = x509DerSmallInteger(der, inner)
1002
+ if (version !== 1 && version !== 2) {
1003
+ return null
1004
+ }
1005
+ at = explicit.end
1006
+ }
1007
+ const serial: X509DerElement | null = x509DerExpect(der, at, tbs.end, X509_TAG_INTEGER)
1008
+ if (serial === null || !x509DerIntegerMinimal(der, serial)) {
1009
+ return null
1010
+ }
1011
+ const alg: X509DerElement | null = x509DerExpect(der, serial.end, tbs.end, X509_TAG_SEQUENCE)
1012
+ if (alg === null || !x509BytesEqual(x509DerWhole(der, alg), x509DerWhole(der, outerAlg))) {
1013
+ return null
1014
+ }
1015
+ const issuer: X509DerElement | null = x509DerExpect(der, alg.end, tbs.end, X509_TAG_SEQUENCE)
1016
+ if (issuer === null) {
1017
+ return null
1018
+ }
1019
+ const validity: X509DerElement | null = x509DerExpect(der, issuer.end, tbs.end, X509_TAG_SEQUENCE)
1020
+ if (validity === null) {
1021
+ return null
1022
+ }
1023
+ const notBefore: X509DerElement | null = x509DerRead(der, validity.start, validity.end)
1024
+ if (notBefore === null) {
1025
+ return null
1026
+ }
1027
+ const notAfter: X509DerElement | null = x509DerRead(der, notBefore.end, validity.end)
1028
+ if (notAfter === null || notAfter.end !== validity.end) {
1029
+ return null
1030
+ }
1031
+ const subject: X509DerElement | null = x509DerExpect(der, validity.end, tbs.end, X509_TAG_SEQUENCE)
1032
+ if (subject === null) {
1033
+ return null
1034
+ }
1035
+ const spki: X509DerElement | null = x509DerExpect(der, subject.end, tbs.end, X509_TAG_SEQUENCE)
1036
+ if (spki === null) {
1037
+ return null
1038
+ }
1039
+ const keyAlg: X509DerElement | null = x509DerExpect(der, spki.start, spki.end, X509_TAG_SEQUENCE)
1040
+ if (keyAlg === null) {
1041
+ return null
1042
+ }
1043
+ const keyBits: X509DerElement | null = x509DerExpect(der, keyAlg.end, spki.end, X509_TAG_BIT_STRING)
1044
+ if (keyBits === null || keyBits.end !== spki.end) {
1045
+ return null
1046
+ }
1047
+ const publicKey: u8[] | null = x509DerBitStringOctets(der, keyBits)
1048
+ if (publicKey === null) {
1049
+ return null
1050
+ }
1051
+ at = spki.end
1052
+ // [1] issuerUniqueID and [2] subjectUniqueID are IMPLICIT BIT STRINGs (so
1053
+ // primitive, 0x81 and 0x82) from v2; [3] extensions is explicit (0xa3), v3.
1054
+ const trailing: i32[] = [0x81, 0x82, 0xa3]
1055
+ for (let i: i32 = 0; i < 3; i++) {
1056
+ if (x509DerPeek(der, at, tbs.end) === trailing[i]) {
1057
+ const e: X509DerElement | null = x509DerRead(der, at, tbs.end)
1058
+ if (e === null || version < (i === 2 ? 2 : 1)) {
1059
+ return null
1060
+ }
1061
+ at = e.end
1062
+ }
1063
+ }
1064
+ if (at !== tbs.end) {
1065
+ return null
1066
+ }
1067
+
1068
+ const before: i64 = x509DerTime(der, notBefore)
1069
+ const after: i64 = x509DerTime(der, notAfter)
1070
+ if (before === X509_NO_TIME || after === X509_NO_TIME) {
1071
+ return null
1072
+ }
1073
+ const out = new X509Certificate()
1074
+ out.der = x509DerSlice(der, 0, total)
1075
+ out.tbs = x509DerWhole(der, tbs)
1076
+ out.serial = x509DerSlice(der, serial.start, serial.end)
1077
+ out.issuer = x509DerWhole(der, issuer)
1078
+ out.subject = x509DerWhole(der, subject)
1079
+ out.publicKey = publicKey
1080
+ out.p256 = x509DerIsAlgorithm(der, keyAlg, x509OidEcPublicKey(), x509OidPrime256v1())
1081
+ out.notBefore = before
1082
+ out.notAfter = after
1083
+ out.signature = signature
1084
+ out.ecdsaSha256 = x509DerIsAlgorithm(der, outerAlg, x509OidEcdsaSha256(), [])
1085
+ return out
1086
+ }
1087
+
1088
+ /**
1089
+ * Every `CERTIFICATE` block in `pem`, in order — a server's chain, leaf first
1090
+ * as TLS sends it — or `null` when there is none, or when any block is not
1091
+ * PEM `pemToDer` accepts or a certificate `x509ParseCertificate` accepts.
1092
+ */
1093
+ export const x509ParseChain = (pem: string): X509Certificate[] | null => {
1094
+ const blocks: u8[][] | null = pemToDer(pem, "CERTIFICATE")
1095
+ if (blocks === null) {
1096
+ return null
1097
+ }
1098
+ const out: X509Certificate[] = []
1099
+ for (const der of blocks) {
1100
+ const cert: X509Certificate | null = x509ParseCertificate(der)
1101
+ if (cert === null) {
1102
+ return null
1103
+ }
1104
+ out.push(cert)
1105
+ }
1106
+ return out
1107
+ }
1108
+
1109
+ /**
1110
+ * Whether `cert`'s signature is a valid ecdsa-with-SHA256 signature of its TBS
1111
+ * bytes under `issuer`'s P-256 key — a self-signed certificate passes itself
1112
+ * as both. `false` for any other algorithm or key, and for a signature that is
1113
+ * not a DER ECDSA-Sig-Value. Only the signature: names, times and extensions
1114
+ * are the caller's policy.
1115
+ */
1116
+ export const x509VerifySignature = (cert: X509Certificate, issuer: X509Certificate): boolean => {
1117
+ if (!cert.ecdsaSha256 || !issuer.p256) {
1118
+ return false
1119
+ }
1120
+ const rs: u8[] | null = x509DerSignatureRS(cert.signature)
1121
+ if (rs === null) {
1122
+ return false
1123
+ }
1124
+ return p256VerifySha256(issuer.publicKey, cert.tbs, rs)
1125
+ }
1126
+
1127
+ /**
1128
+ * A self-signed X.509 v3 certificate, in DER, for the P-256 key `priv`: subject
1129
+ * and issuer `CN=commonName`, valid from `notBeforeMs` (milliseconds since
1130
+ * 1970, rounded down to the second) for exactly `days` days, serial number
1131
+ * `serial`, and signed with ecdsa-with-SHA256 — see the module comment for why
1132
+ * it has no extensions. `null` when `days` is below 1 or above
1133
+ * `X509_MAX_DAYS`, `notBeforeMs` is negative or the validity would end after
1134
+ * 9999, `commonName` is empty or longer than 64 bytes, `priv` is not a P-256
1135
+ * private key, or `serial` — big-endian, leading zeros ignored — is zero or
1136
+ * needs more than `X509_MAX_SERIAL` octets as a positive INTEGER (clear the top
1137
+ * bit of 20 random bytes, or use fewer).
1138
+ */
1139
+ export const x509MintSelfSigned = (
1140
+ priv: u8[],
1141
+ commonName: string,
1142
+ notBeforeMs: i64,
1143
+ days: i32,
1144
+ serial: u8[]
1145
+ ): u8[] | null => {
1146
+ if (days < 1 || days > X509_MAX_DAYS || notBeforeMs < 0) {
1147
+ return null
1148
+ }
1149
+ const start: i64 = notBeforeMs / 1000
1150
+ const end: i64 = start + toI64(days) * 86400
1151
+ // 9999-12-31T23:59:59Z, the last second RFC 5280's times can spell.
1152
+ if (end > 253402300799) {
1153
+ return null
1154
+ }
1155
+ const name: u8[] = x509Bytes(commonName)
1156
+ const nameLength: i32 = toI32(name.length)
1157
+ if (nameLength < 1 || nameLength > X509_MAX_COMMON_NAME) {
1158
+ return null
1159
+ }
1160
+ const serialDer: u8[] = x509DerUnsignedInteger(serial)
1161
+ // Tag, length, and at most twenty content octets, of which at least one is not zero.
1162
+ let nonzero: i32 = 0
1163
+ for (let k: i32 = 0; k < toI32(serial.length); k++) {
1164
+ nonzero = nonzero | toI32(serial[k])
1165
+ }
1166
+ if (nonzero === 0 || toI32(serialDer.length) - 2 > X509_MAX_SERIAL) {
1167
+ return null
1168
+ }
1169
+ const pub: u8[] | null = p256PublicKey(priv)
1170
+ if (pub === null) {
1171
+ return null
1172
+ }
1173
+
1174
+ const algorithm: u8[] = x509DerWrap(X509_TAG_SEQUENCE, [x509DerTlv(X509_TAG_OID, x509OidEcdsaSha256())])
1175
+ const rdn: u8[] = x509DerWrap(X509_TAG_SET, [
1176
+ x509DerWrap(X509_TAG_SEQUENCE, [
1177
+ x509DerTlv(X509_TAG_OID, x509OidCommonName()),
1178
+ x509DerTlv(X509_TAG_UTF8_STRING, name),
1179
+ ]),
1180
+ ])
1181
+ const distinguished: u8[] = x509DerWrap(X509_TAG_SEQUENCE, [rdn])
1182
+ const spki: u8[] = x509DerWrap(X509_TAG_SEQUENCE, [
1183
+ x509DerWrap(X509_TAG_SEQUENCE, [
1184
+ x509DerTlv(X509_TAG_OID, x509OidEcPublicKey()),
1185
+ x509DerTlv(X509_TAG_OID, x509OidPrime256v1()),
1186
+ ]),
1187
+ x509DerBitString(pub),
1188
+ ])
1189
+ const tbs: u8[] = x509DerWrap(X509_TAG_SEQUENCE, [
1190
+ // [0] EXPLICIT Version: v3 is the INTEGER 2.
1191
+ x509DerWrap(0xa0, [x509DerTlv(X509_TAG_INTEGER, [2])]),
1192
+ serialDer,
1193
+ algorithm,
1194
+ distinguished,
1195
+ x509DerWrap(X509_TAG_SEQUENCE, [x509DerTimeAt(start), x509DerTimeAt(end)]),
1196
+ distinguished,
1197
+ spki,
1198
+ ])
1199
+ const rs: u8[] | null = p256SignSha256(priv, tbs)
1200
+ if (rs === null) {
1201
+ return null
1202
+ }
1203
+ const r: u8[] = x509DerSlice(rs, 0, 32)
1204
+ const s: u8[] = x509DerSlice(rs, 32, 64)
1205
+ const sig: u8[] = x509DerWrap(X509_TAG_SEQUENCE, [x509DerUnsignedInteger(r), x509DerUnsignedInteger(s)])
1206
+ return x509DerWrap(X509_TAG_SEQUENCE, [tbs, algorithm, x509DerBitString(sig)])
1207
+ }
1208
+
1209
+ /**
1210
+ * The SHA-256 of a certificate's DER: the value WebTransport's
1211
+ * `serverCertificateHashes` pins, and what `openssl x509 -outform DER |
1212
+ * sha256sum` prints.
1213
+ */
1214
+ export const x509CertificateHash = (der: u8[]): u8[] => sha256(der)