@amritk/nish-x86_64-linux 0.18.0 → 0.20.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.
Files changed (59) hide show
  1. package/INSTALL.md +43 -25
  2. package/bin/nish +0 -0
  3. package/package.json +2 -2
  4. package/runtime/nish.d.ts +55 -5
  5. package/runtime/nish.h +215 -18
  6. package/runtime/nish.mjs +16 -0
  7. package/runtime/runtime-aes.c +490 -0
  8. package/runtime/runtime-cross.c +366 -0
  9. package/runtime/runtime-host.c +7 -6
  10. package/runtime/runtime-net.c +93 -34
  11. package/runtime/runtime-os.c +213 -15
  12. package/runtime/runtime-parallel.c +590 -107
  13. package/runtime/runtime-simd.c +4 -4
  14. package/runtime/runtime-wasm.c +5 -3
  15. package/runtime/runtime.c +69 -13
  16. package/runtime/shim.mjs +71 -1
  17. package/scripts/build.sh +223 -22
  18. package/std/README.md +81 -51
  19. package/std/bytes.ts +163 -0
  20. package/std/crypto/LICENSE-libsecp256k1 +19 -0
  21. package/std/crypto/aes.ts +238 -76
  22. package/std/crypto/chacha20poly1305.ts +43 -9
  23. package/std/crypto/ed25519.ts +840 -0
  24. package/std/crypto/hkdf.ts +304 -12
  25. package/std/crypto/hmac.ts +245 -53
  26. package/std/crypto/p256.ts +932 -61
  27. package/std/crypto/x25519.ts +55 -37
  28. package/std/crypto/x509-random.ts +71 -0
  29. package/std/crypto/x509.ts +9 -9
  30. package/std/json-tokenizer.ts +1296 -0
  31. package/std/json-typed.ts +1014 -0
  32. package/std/json-value.ts +1163 -0
  33. package/std/json.ts +1120 -34
  34. package/std/net/buffer-pool.ts +151 -0
  35. package/std/net/hpack.ts +416 -112
  36. package/std/net/http-fields.ts +93 -0
  37. package/std/net/http1-server.ts +417 -55
  38. package/std/net/http1.ts +31 -6
  39. package/std/net/http2-tls.ts +112 -24
  40. package/std/net/http2.ts +333 -75
  41. package/std/net/http3-server.ts +211 -31
  42. package/std/net/http3.ts +187 -28
  43. package/std/net/prefork.ts +412 -0
  44. package/std/net/quic-listener.ts +88 -7
  45. package/std/net/quic-packet.ts +243 -82
  46. package/std/net/quic-recovery.ts +361 -30
  47. package/std/net/quic-stream.ts +424 -24
  48. package/std/net/quic.ts +519 -167
  49. package/std/net/router.ts +676 -0
  50. package/std/net/tls/codec.ts +426 -27
  51. package/std/net/tls/record-server.ts +478 -132
  52. package/std/net/tls/record.ts +133 -42
  53. package/std/net/tls/schedule.ts +464 -55
  54. package/std/net/tls/ticket.ts +610 -0
  55. package/std/net/tls-tcp.ts +196 -53
  56. package/std/net/tls.ts +1018 -260
  57. package/std/net/url.ts +571 -0
  58. package/std/random.ts +94 -0
  59. package/std/threads.ts +438 -14
@@ -64,7 +64,14 @@
64
64
  * `exposeWith`, and the clamped copy and every ladder element are wiped before
65
65
  * it returns (ECC-2, docs/security/crypto-ecc.md).
66
66
  *
67
- * Private names carry the `f25519` / `x25519` prefix because a `std/` module's
67
+ * **The field is shared with Ed25519.** `nish/crypto/ed25519` works over the
68
+ * same GF(p), so the `f25519` functions are exported for it to import rather
69
+ * than written twice; they are the module's internals, with the bounds each
70
+ * one states, not an API for programs. Ed25519's square root needs
71
+ * `z^(2^252 - 3)`, which shares its first 250 bits with the inversion's
72
+ * exponent, so that part of the chain is `f25519Pow250`, which both call.
73
+ *
74
+ * Names carry the `f25519` / `x25519` prefix because a `std/` module's
68
75
  * private functions share the importing program's flat symbol namespace
69
76
  * (`docs/wp26-stdlib.md` §3e).
70
77
  */
@@ -84,9 +91,9 @@ const X25519_A24: i64 = 121665
84
91
  * because signed arithmetic is checked for an overflow, and a check is a
85
92
  * branch on a secret limb. Each is one instruction once LLVM inlines it.
86
93
  */
87
- const f25519Add64 = (a: i64, b: i64): i64 => toI64(toU64(a) + toU64(b))
88
- const f25519Sub64 = (a: i64, b: i64): i64 => toI64(toU64(a) - toU64(b))
89
- const f25519Mul64 = (a: i64, b: i64): i64 => toI64(toU64(a) * toU64(b))
94
+ export const f25519Add64 = (a: i64, b: i64): i64 => toI64(toU64(a) + toU64(b))
95
+ export const f25519Sub64 = (a: i64, b: i64): i64 => toI64(toU64(a) - toU64(b))
96
+ export const f25519Mul64 = (a: i64, b: i64): i64 => toI64(toU64(a) * toU64(b))
90
97
 
91
98
  /** The width of limb `i`: 26 bits for an even limb, 25 for an odd one. */
92
99
  const f25519Width = (i: i32): i64 => {
@@ -98,20 +105,20 @@ const f25519Width = (i: i32): i64 => {
98
105
  const f25519LimbMask = (i: i32): i64 => f25519Sub64(toI64(1) << f25519Width(i), toI64(1))
99
106
 
100
107
  /** A fresh field element, zero. */
101
- const f25519Zero = (): i64[] => {
108
+ export const f25519Zero = (): i64[] => {
102
109
  const f: i64[] = new Array<i64>(10)
103
110
  return f
104
111
  }
105
112
 
106
113
  /** A fresh field element holding the small constant `n`. */
107
- const f25519Small = (n: i64): i64[] => {
114
+ export const f25519Small = (n: i64): i64[] => {
108
115
  const f: i64[] = f25519Zero()
109
116
  f[0] = n
110
117
  return f
111
118
  }
112
119
 
113
120
  /** `out = f`, limb by limb. */
114
- const f25519Copy = (out: i64[], f: i64[]): void => {
121
+ export const f25519Copy = (out: i64[], f: i64[]): void => {
115
122
  if (toI32(out.length) < 10 || toI32(f.length) < 10) {
116
123
  return
117
124
  }
@@ -152,7 +159,7 @@ const f25519CarryChain = (h: i64[]): void => {
152
159
  * `h & (2^width - 1)`, which is the matching non-negative remainder for a
153
160
  * negative limb too, without shifting a negative number left.
154
161
  */
155
- const f25519Carry = (h: i64[]): void => {
162
+ export const f25519Carry = (h: i64[]): void => {
156
163
  if (toI32(h.length) < 10) {
157
164
  return
158
165
  }
@@ -169,7 +176,7 @@ const f25519Carry = (h: i64[]): void => {
169
176
  * `out = f + g`, not carried. With both reduced (limbs below 2^26 in
170
177
  * magnitude) the sum's limbs are below 2^27, which `f25519Mul` accepts.
171
178
  */
172
- const f25519Add = (out: i64[], f: i64[], g: i64[]): void => {
179
+ export const f25519Add = (out: i64[], f: i64[], g: i64[]): void => {
173
180
  if (toI32(out.length) < 10 || toI32(f.length) < 10 || toI32(g.length) < 10) {
174
181
  return
175
182
  }
@@ -183,7 +190,7 @@ const f25519Add = (out: i64[], f: i64[], g: i64[]): void => {
183
190
  * both reduced the difference's limbs are below 2^27 in magnitude, which
184
191
  * `f25519Mul` accepts.
185
192
  */
186
- const f25519Sub = (out: i64[], f: i64[], g: i64[]): void => {
193
+ export const f25519Sub = (out: i64[], f: i64[], g: i64[]): void => {
187
194
  if (toI32(out.length) < 10 || toI32(f.length) < 10 || toI32(g.length) < 10) {
188
195
  return
189
196
  }
@@ -208,7 +215,7 @@ const f25519Sub = (out: i64[], f: i64[], g: i64[]): void => {
208
215
  * sums added again, say — breaks this bound, which is why every caller carries
209
216
  * or multiplies before it adds a second time.
210
217
  */
211
- const f25519Mul = (out: i64[], f: i64[], g: i64[]): void => {
218
+ export const f25519Mul = (out: i64[], f: i64[], g: i64[]): void => {
212
219
  if (toI32(f.length) < 10 || toI32(g.length) < 10) {
213
220
  return
214
221
  }
@@ -240,12 +247,12 @@ const f25519Mul = (out: i64[], f: i64[], g: i64[]): void => {
240
247
  }
241
248
 
242
249
  /** `out = f * f`, reduced; the same bounds as `f25519Mul`. */
243
- const f25519Square = (out: i64[], f: i64[]): void => {
250
+ export const f25519Square = (out: i64[], f: i64[]): void => {
244
251
  f25519Mul(out, f, f)
245
252
  }
246
253
 
247
254
  /** `out = f` squared `n` times in a row (`n` at least 1), reduced. */
248
- const f25519SquareTimes = (out: i64[], f: i64[], n: i32): void => {
255
+ export const f25519SquareTimes = (out: i64[], f: i64[], n: i32): void => {
249
256
  f25519Square(out, f)
250
257
  for (let i: i32 = 1; i < n; i++) {
251
258
  f25519Square(out, out)
@@ -268,25 +275,20 @@ const f25519MulA24 = (out: i64[], f: i64[]): void => {
268
275
  }
269
276
 
270
277
  /**
271
- * `out = z^(p - 2)`, which is `1 / z` by Fermat's little theorem, and zero for
272
- * a zero `z` — what RFC 7748 §5 asks of the ladder's last step.
273
- *
274
- * p - 2 = 2^255 - 21 = (2^250 - 1) * 2^5 + 11, so the exponent is 250 ones
275
- * followed by `01011`. The chain builds `z^(2^n - 1)` for n = 2, 4, 5, 10, 20,
276
- * 40, 50, 100, 200 and 250 from the rule
277
- * `z^(2^(a+b) - 1) = (z^(2^a - 1))^(2^b) * z^(2^b - 1)`, then squares five
278
- * times and multiplies by `z^11`: 254 squarings and 11 multiplications, the
279
- * same for every `z`.
278
+ * `out = z^(2^250 - 1)` and `z11 = z^11`: the part of the exponent chain that
279
+ * `f25519Invert` and Ed25519's square root (`ed25519Pow22523`,
280
+ * `nish/crypto/ed25519`) share. The chain builds `z^(2^n - 1)` for n = 2, 4,
281
+ * 5, 10, 20, 40, 50, 100, 200 and 250 from the rule
282
+ * `z^(2^(a+b) - 1) = (z^(2^a - 1))^(2^b) * z^(2^b - 1)`: 251 squarings and 11
283
+ * multiplications, the same for every `z`. `out` and `z11` may not be `z`.
280
284
  */
281
- const f25519Invert = (out: i64[], z: i64[]): void => {
285
+ export const f25519Pow250 = (out: i64[], z11: i64[], z: i64[]): void => {
282
286
  const z2: i64[] = f25519Zero()
283
- const z11: i64[] = f25519Zero()
284
287
  const e2: i64[] = f25519Zero()
285
288
  const e5: i64[] = f25519Zero()
286
289
  const e10: i64[] = f25519Zero()
287
290
  const e50: i64[] = f25519Zero()
288
291
  const t: i64[] = f25519Zero()
289
- const acc: i64[] = f25519Zero()
290
292
 
291
293
  f25519Square(z2, z)
292
294
  f25519Mul(e2, z2, z) // z^3 = z^(2^2 - 1)
@@ -300,17 +302,33 @@ const f25519Invert = (out: i64[], z: i64[]): void => {
300
302
  f25519SquareTimes(t, e5, 5)
301
303
  f25519Mul(e10, t, e5) // 2^10 - 1
302
304
  f25519SquareTimes(t, e10, 10)
303
- f25519Mul(acc, t, e10) // 2^20 - 1
304
- f25519SquareTimes(t, acc, 20)
305
- f25519Mul(acc, t, acc) // 2^40 - 1
306
- f25519SquareTimes(t, acc, 10)
305
+ f25519Mul(out, t, e10) // 2^20 - 1
306
+ f25519SquareTimes(t, out, 20)
307
+ f25519Mul(out, t, out) // 2^40 - 1
308
+ f25519SquareTimes(t, out, 10)
307
309
  f25519Mul(e50, t, e10) // 2^50 - 1
308
310
  f25519SquareTimes(t, e50, 50)
309
- f25519Mul(acc, t, e50) // 2^100 - 1
310
- f25519SquareTimes(t, acc, 100)
311
- f25519Mul(acc, t, acc) // 2^200 - 1
312
- f25519SquareTimes(t, acc, 50)
313
- f25519Mul(acc, t, e50) // 2^250 - 1
311
+ f25519Mul(out, t, e50) // 2^100 - 1
312
+ f25519SquareTimes(t, out, 100)
313
+ f25519Mul(out, t, out) // 2^200 - 1
314
+ f25519SquareTimes(t, out, 50)
315
+ f25519Mul(out, t, e50) // 2^250 - 1
316
+ }
317
+
318
+ /**
319
+ * `out = z^(p - 2)`, which is `1 / z` by Fermat's little theorem, and zero for
320
+ * a zero `z` — what RFC 7748 §5 asks of the ladder's last step.
321
+ *
322
+ * p - 2 = 2^255 - 21 = (2^250 - 1) * 2^5 + 11, so the exponent is 250 ones
323
+ * followed by `01011`: `f25519Pow250`, then five squarings and a
324
+ * multiplication by `z^11` — 256 squarings and 12 multiplications, the same
325
+ * for every `z`.
326
+ */
327
+ export const f25519Invert = (out: i64[], z: i64[]): void => {
328
+ const z11: i64[] = f25519Zero()
329
+ const acc: i64[] = f25519Zero()
330
+ const t: i64[] = f25519Zero()
331
+ f25519Pow250(acc, z11, z)
314
332
  f25519SquareTimes(t, acc, 5)
315
333
  f25519Mul(out, t, z11) // 2^255 - 21
316
334
  }
@@ -320,7 +338,7 @@ const f25519Invert = (out: i64[], z: i64[]): void => {
320
338
  * same instructions either way: the mask is all ones or all zeros, and the
321
339
  * swap is the masked xor of the two.
322
340
  */
323
- const f25519Swap = (f: i64[], g: i64[], bit: i64): void => {
341
+ export const f25519Swap = (f: i64[], g: i64[], bit: i64): void => {
324
342
  if (toI32(f.length) < 10 || toI32(g.length) < 10) {
325
343
  return
326
344
  }
@@ -341,7 +359,7 @@ const f25519Swap = (f: i64[], g: i64[], bit: i64): void => {
341
359
  * `[p, 2^255)` is neither refused nor adjusted: §5 has it processed as its
342
360
  * residue, and the arithmetic does that by itself.
343
361
  */
344
- const f25519Decode = (bytes: u8[]): i64[] => {
362
+ export const f25519Decode = (bytes: u8[]): i64[] => {
345
363
  const f: i64[] = new Array<i64>(10)
346
364
  if (toI32(bytes.length) < 32) {
347
365
  return f
@@ -382,7 +400,7 @@ const f25519Decode = (bytes: u8[]): i64[] => {
382
400
  * when the value is at least p — so the element adds `19 * q` and drops bit
383
401
  * 255, which is subtracting `p * q`.
384
402
  */
385
- const f25519Encode = (f: i64[]): u8[] => {
403
+ export const f25519Encode = (f: i64[]): u8[] => {
386
404
  const h: i64[] = new Array<i64>(10)
387
405
  f25519Copy(h, f)
388
406
  f25519Carry(h)
@@ -0,0 +1,71 @@
1
+ /**
2
+ * `nish/crypto/x509-random` — the private key and the serial number
3
+ * `nish/crypto/x509`'s `x509MintSelfSigned` needs, drawn from the operating
4
+ * system's CSPRNG, and the mint that draws its own serial.
5
+ *
6
+ * import { Secret, wipe } from "nish:secret";
7
+ * import { x509DrawP256Key, x509MintSelfSignedDrawn } from "nish/crypto/x509-random";
8
+ *
9
+ * const priv: Secret<u8[]> = x509DrawP256Key();
10
+ * const der: u8[] | null = x509MintSelfSignedDrawn(priv, "localhost", toI64(Date.now()), 14);
11
+ * // ... present `der` and sign the handshake with `priv` ...
12
+ * wipe(priv);
13
+ *
14
+ * **Native only.** Every function here reaches `crypto.getRandomValues`, so a
15
+ * program that imports this module does not compile for wasm32, which has no
16
+ * entropy to reach. That is why it is a module of its own: `nish/crypto/x509`
17
+ * takes the key and the serial as arguments and imports nothing from here, so
18
+ * a wasm32 program can still parse, verify and mint with bytes it was handed
19
+ * (X509-6, docs/security/crypto-x509.md).
20
+ */
21
+ import { Secret, secret, wipe } from "nish:secret"
22
+ import { P256_SCALAR_SIZE, p256PublicKey } from "nish/crypto/p256"
23
+ import { X509_MAX_SERIAL, x509MintSelfSigned } from "nish/crypto/x509"
24
+
25
+ /**
26
+ * A fresh P-256 private key: `P256_SCALAR_SIZE` bytes from
27
+ * `crypto.getRandomValues`, drawn again until they hold a scalar in [1, n),
28
+ * which `p256PublicKey` is the test of. Rejection rather than reduction mod n,
29
+ * so every key is equally likely; a draw is refused with odds below 2^-32. A
30
+ * refused draw is wiped before the next, and the caller wipes the one
31
+ * returned.
32
+ */
33
+ export const x509DrawP256Key = (): Secret<u8[]> => {
34
+ while (true) {
35
+ const drawn: u8[] = new Array<u8>(P256_SCALAR_SIZE)
36
+ crypto.getRandomValues(drawn)
37
+ const key: Secret<u8[]> = secret(drawn)
38
+ if (p256PublicKey(key) !== null) {
39
+ return key
40
+ }
41
+ wipe(key)
42
+ }
43
+ }
44
+
45
+ /**
46
+ * A fresh serial number for `x509MintSelfSigned`: `X509_MAX_SERIAL` (20) bytes
47
+ * from `crypto.getRandomValues` with the first one's top two bits set to `01`,
48
+ * so the INTEGER is positive, never zero, and always twenty octets long — 158
49
+ * random bits, past the 64 the CA/Browser Forum asks of a serial. A serial is
50
+ * public, written into the certificate, so it is a plain array.
51
+ */
52
+ export const x509DrawSerial = (): u8[] => {
53
+ const serial: u8[] = new Array<u8>(X509_MAX_SERIAL)
54
+ crypto.getRandomValues(serial)
55
+ serial[0] = (serial[0] & toU8(0x3f)) | toU8(0x40)
56
+ return serial
57
+ }
58
+
59
+ /**
60
+ * `x509MintSelfSigned(priv, commonName, notBeforeMs, days, x509DrawSerial())`:
61
+ * the self-signed certificate with a serial drawn here, `null` for everything
62
+ * the mint answers `null` for. The key stays the caller's, since the server
63
+ * that presents the certificate signs its handshakes with it; draw one with
64
+ * `x509DrawP256Key`.
65
+ */
66
+ export const x509MintSelfSignedDrawn = (
67
+ priv: Secret<u8[]>,
68
+ commonName: string,
69
+ notBeforeMs: i64,
70
+ days: i32
71
+ ): u8[] | null => x509MintSelfSigned(priv, commonName, notBeforeMs, days, x509DrawSerial())
@@ -5,15 +5,13 @@
5
5
  * pins by its SHA-256.
6
6
  *
7
7
  * import { x509MintSelfSigned, x509CertificateHash, derToPem } from "nish/crypto/x509";
8
+ * // Native only: a program that imports this does not compile for wasm32, which has no entropy.
9
+ * import { x509DrawP256Key, x509DrawSerial } from "nish/crypto/x509-random";
8
10
  *
9
- * // Both secrets come from the kernel's CSPRNG; a predictable key or serial is the caller's bug.
10
- * const drawn: u8[] = new Array<u8>(32);
11
- * crypto.getRandomValues(drawn);
12
- * const priv: Secret<u8[]> = secret(drawn); // nish:secret; p256PublicKey(priv) === null: draw again (odds 2^-32)
13
- * const serial: u8[] = new Array<u8>(16);
14
- * crypto.getRandomValues(serial);
15
- * serial[0] = serial[0] & toU8(0x7f); // positive, so it stays 16 octets
16
- * const der: u8[] | null = x509MintSelfSigned(priv, "localhost", toI64(Date.now()), 14, serial);
11
+ * // Both come from the kernel's CSPRNG; a predictable key or serial is the caller's bug.
12
+ * // A wasm32 program is handed them instead, and passes them in as they are passed here.
13
+ * const priv: Secret<u8[]> = x509DrawP256Key();
14
+ * const der: u8[] | null = x509MintSelfSigned(priv, "localhost", toI64(Date.now()), 14, x509DrawSerial());
17
15
  * wipe(priv);
18
16
  * // x509CertificateHash(der) is what serverCertificateHashes names;
19
17
  * // derToPem(der, "CERTIFICATE") is the file a TLS stack loads.
@@ -68,7 +66,9 @@
68
66
  * parameters so the golden certificate is deterministic; a caller passes
69
67
  * `Date.now()` and, for the key and the serial, bytes from
70
68
  * `crypto.getRandomValues`. This module does not draw them itself,
71
- * because a call to the operating system would stop it compiling for wasm32.
69
+ * because a call to the operating system would stop it compiling for wasm32;
70
+ * `nish/crypto/x509-random`, which this module does not import, draws both
71
+ * for a native program (X509-6).
72
72
  *
73
73
  * **Constant time.** A private key is the one secret that passes through here:
74
74
  * it is base64-decoded from PEM, lifted out of its DER, and handed to