@scriptc/runtime 0.0.30 → 0.0.32
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/package.json +1 -1
- package/src/scr_musl.c +170 -6
- package/src/scr_runtime.h +17 -10
- package/src/scr_tls.c +23 -10
- package/src/scr_tls_ca.c +133 -15
- package/vendor/README.md +1 -1
package/package.json
CHANGED
package/src/scr_musl.c
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* this TU together with -DSCR_MUSL). musl deliberately provides no libc
|
|
3
3
|
* identification macro, so the target-selected project macro is the guard.
|
|
4
4
|
*
|
|
5
|
-
* The x86_64 ucontext
|
|
5
|
+
* The x86_64 and AArch64 ucontext implementations below are derived from libucontext
|
|
6
6
|
* commit 49e671dd52ff6791295d8161ad3b6da7dc5f6f9d:
|
|
7
7
|
* https://github.com/kaniini/libucontext
|
|
8
8
|
*
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
#include <ucontext.h>
|
|
28
28
|
#endif
|
|
29
29
|
|
|
30
|
-
#if !defined(__x86_64__)
|
|
31
|
-
#error "scriptc's musl runtime currently supports x86_64 only"
|
|
30
|
+
#if !defined(__x86_64__) && !defined(__aarch64__)
|
|
31
|
+
#error "scriptc's musl runtime currently supports x86_64 and AArch64 only"
|
|
32
32
|
#endif
|
|
33
33
|
|
|
34
34
|
/* The scriptc runtime uses arc4random_buf as its infallible CSPRNG contract.
|
|
@@ -57,9 +57,10 @@ void arc4random_buf(void *buf, size_t n) {
|
|
|
57
57
|
|
|
58
58
|
/* musl exposes the POSIX ucontext types but intentionally omits these legacy
|
|
59
59
|
* functions. scriptc's async/generator fibers need only user-space register
|
|
60
|
-
* swaps; they never use a context to mutate the process signal mask.
|
|
61
|
-
* libucontext's fast (non-POSIX-signal-mask)
|
|
62
|
-
*
|
|
60
|
+
* swaps; they never use a context to mutate the process signal mask. These are
|
|
61
|
+
* libucontext's fast (non-POSIX-signal-mask) implementations, emitted under
|
|
62
|
+
* the standard symbol names that musl leaves unresolved. */
|
|
63
|
+
#if defined(__x86_64__)
|
|
63
64
|
_Static_assert(offsetof(ucontext_t, uc_mcontext.gregs) == 40,
|
|
64
65
|
"unexpected musl x86_64 ucontext layout");
|
|
65
66
|
_Static_assert(offsetof(ucontext_t, uc_mcontext.fpregs) == 224,
|
|
@@ -265,6 +266,169 @@ void makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) {
|
|
|
265
266
|
#undef SCR_STR
|
|
266
267
|
#undef SCR_STR_INNER
|
|
267
268
|
|
|
269
|
+
#elif defined(__aarch64__)
|
|
270
|
+
|
|
271
|
+
/* musl's AArch64 ucontext embeds the kernel sigcontext after a 128-byte
|
|
272
|
+
* signal mask. Keep the offsets pinned to the Zig 0.16 musl headers: the
|
|
273
|
+
* assembly below saves the ABI's callee-preserved GPR and SIMD state there. */
|
|
274
|
+
_Static_assert(offsetof(ucontext_t, uc_mcontext.regs[0]) == 184,
|
|
275
|
+
"unexpected musl AArch64 register layout");
|
|
276
|
+
_Static_assert(offsetof(ucontext_t, uc_mcontext.sp) == 432,
|
|
277
|
+
"unexpected musl AArch64 stack-pointer layout");
|
|
278
|
+
_Static_assert(offsetof(ucontext_t, uc_mcontext.pc) == 440,
|
|
279
|
+
"unexpected musl AArch64 program-counter layout");
|
|
280
|
+
_Static_assert(offsetof(ucontext_t, uc_mcontext.pstate) == 448,
|
|
281
|
+
"unexpected musl AArch64 processor-state layout");
|
|
282
|
+
_Static_assert(offsetof(ucontext_t, uc_mcontext.__reserved) == 464,
|
|
283
|
+
"unexpected musl AArch64 SIMD-state layout");
|
|
284
|
+
|
|
285
|
+
#define SCR_STR_INNER(x) #x
|
|
286
|
+
#define SCR_STR(x) SCR_STR_INNER(x)
|
|
287
|
+
#define SCR_A64_UC_REG(reg) (184 + ((reg) * 8))
|
|
288
|
+
#define SCR_A64_UC_SP 432
|
|
289
|
+
#define SCR_A64_UC_PC 440
|
|
290
|
+
#define SCR_A64_UC_PSTATE 448
|
|
291
|
+
#define SCR_A64_UC_FPSIMD 464
|
|
292
|
+
|
|
293
|
+
__asm__(
|
|
294
|
+
".text\n"
|
|
295
|
+
".p2align 2\n"
|
|
296
|
+
".global getcontext\n"
|
|
297
|
+
"getcontext:\n"
|
|
298
|
+
" str xzr, [x0, #" SCR_STR(SCR_A64_UC_REG(0)) "]\n"
|
|
299
|
+
" stp x2, x3, [x0, #" SCR_STR(SCR_A64_UC_REG(2)) "]\n"
|
|
300
|
+
" str x30, [x0, #" SCR_STR(SCR_A64_UC_PC) "]\n"
|
|
301
|
+
" mov x2, sp\n"
|
|
302
|
+
" str x2, [x0, #" SCR_STR(SCR_A64_UC_SP) "]\n"
|
|
303
|
+
" str xzr, [x0, #" SCR_STR(SCR_A64_UC_PSTATE) "]\n"
|
|
304
|
+
" add x2, x0, #" SCR_STR(SCR_A64_UC_FPSIMD) "\n"
|
|
305
|
+
" stp q8, q9, [x2, #144]\n"
|
|
306
|
+
" stp q10, q11, [x2, #176]\n"
|
|
307
|
+
" stp q12, q13, [x2, #208]\n"
|
|
308
|
+
" stp q14, q15, [x2, #240]\n"
|
|
309
|
+
" mov x2, x0\n"
|
|
310
|
+
" mov x0, #0\n"
|
|
311
|
+
" stp x0, x1, [x2, #" SCR_STR(SCR_A64_UC_REG(0)) "]\n"
|
|
312
|
+
" stp x4, x5, [x2, #" SCR_STR(SCR_A64_UC_REG(4)) "]\n"
|
|
313
|
+
" stp x6, x7, [x2, #" SCR_STR(SCR_A64_UC_REG(6)) "]\n"
|
|
314
|
+
" stp x8, x9, [x2, #" SCR_STR(SCR_A64_UC_REG(8)) "]\n"
|
|
315
|
+
" stp x10, x11, [x2, #" SCR_STR(SCR_A64_UC_REG(10)) "]\n"
|
|
316
|
+
" stp x12, x13, [x2, #" SCR_STR(SCR_A64_UC_REG(12)) "]\n"
|
|
317
|
+
" stp x14, x15, [x2, #" SCR_STR(SCR_A64_UC_REG(14)) "]\n"
|
|
318
|
+
" stp x16, x17, [x2, #" SCR_STR(SCR_A64_UC_REG(16)) "]\n"
|
|
319
|
+
" stp x18, x19, [x2, #" SCR_STR(SCR_A64_UC_REG(18)) "]\n"
|
|
320
|
+
" stp x20, x21, [x2, #" SCR_STR(SCR_A64_UC_REG(20)) "]\n"
|
|
321
|
+
" stp x22, x23, [x2, #" SCR_STR(SCR_A64_UC_REG(22)) "]\n"
|
|
322
|
+
" stp x24, x25, [x2, #" SCR_STR(SCR_A64_UC_REG(24)) "]\n"
|
|
323
|
+
" stp x26, x27, [x2, #" SCR_STR(SCR_A64_UC_REG(26)) "]\n"
|
|
324
|
+
" stp x28, x29, [x2, #" SCR_STR(SCR_A64_UC_REG(28)) "]\n"
|
|
325
|
+
" str x30, [x2, #" SCR_STR(SCR_A64_UC_REG(30)) "]\n"
|
|
326
|
+
" ret\n"
|
|
327
|
+
|
|
328
|
+
".p2align 2\n"
|
|
329
|
+
".global setcontext\n"
|
|
330
|
+
"setcontext:\n"
|
|
331
|
+
" ldp x18, x19, [x0, #" SCR_STR(SCR_A64_UC_REG(18)) "]\n"
|
|
332
|
+
" ldp x20, x21, [x0, #" SCR_STR(SCR_A64_UC_REG(20)) "]\n"
|
|
333
|
+
" ldp x22, x23, [x0, #" SCR_STR(SCR_A64_UC_REG(22)) "]\n"
|
|
334
|
+
" ldp x24, x25, [x0, #" SCR_STR(SCR_A64_UC_REG(24)) "]\n"
|
|
335
|
+
" ldp x26, x27, [x0, #" SCR_STR(SCR_A64_UC_REG(26)) "]\n"
|
|
336
|
+
" ldp x28, x29, [x0, #" SCR_STR(SCR_A64_UC_REG(28)) "]\n"
|
|
337
|
+
" ldr x30, [x0, #" SCR_STR(SCR_A64_UC_REG(30)) "]\n"
|
|
338
|
+
" ldr x2, [x0, #" SCR_STR(SCR_A64_UC_SP) "]\n"
|
|
339
|
+
" mov sp, x2\n"
|
|
340
|
+
" add x2, x0, #" SCR_STR(SCR_A64_UC_FPSIMD) "\n"
|
|
341
|
+
" ldp q8, q9, [x2, #144]\n"
|
|
342
|
+
" ldp q10, q11, [x2, #176]\n"
|
|
343
|
+
" ldp q12, q13, [x2, #208]\n"
|
|
344
|
+
" ldp q14, q15, [x2, #240]\n"
|
|
345
|
+
" ldr x16, [x0, #" SCR_STR(SCR_A64_UC_PC) "]\n"
|
|
346
|
+
" ldp x2, x3, [x0, #" SCR_STR(SCR_A64_UC_REG(2)) "]\n"
|
|
347
|
+
" ldp x4, x5, [x0, #" SCR_STR(SCR_A64_UC_REG(4)) "]\n"
|
|
348
|
+
" ldp x6, x7, [x0, #" SCR_STR(SCR_A64_UC_REG(6)) "]\n"
|
|
349
|
+
" ldp x0, x1, [x0, #" SCR_STR(SCR_A64_UC_REG(0)) "]\n"
|
|
350
|
+
" br x16\n"
|
|
351
|
+
|
|
352
|
+
".p2align 2\n"
|
|
353
|
+
".global swapcontext\n"
|
|
354
|
+
"swapcontext:\n"
|
|
355
|
+
" str xzr, [x0, #" SCR_STR(SCR_A64_UC_REG(0)) "]\n"
|
|
356
|
+
" stp x2, x3, [x0, #" SCR_STR(SCR_A64_UC_REG(2)) "]\n"
|
|
357
|
+
" stp x4, x5, [x0, #" SCR_STR(SCR_A64_UC_REG(4)) "]\n"
|
|
358
|
+
" stp x6, x7, [x0, #" SCR_STR(SCR_A64_UC_REG(6)) "]\n"
|
|
359
|
+
" stp x8, x9, [x0, #" SCR_STR(SCR_A64_UC_REG(8)) "]\n"
|
|
360
|
+
" stp x10, x11, [x0, #" SCR_STR(SCR_A64_UC_REG(10)) "]\n"
|
|
361
|
+
" stp x12, x13, [x0, #" SCR_STR(SCR_A64_UC_REG(12)) "]\n"
|
|
362
|
+
" stp x14, x15, [x0, #" SCR_STR(SCR_A64_UC_REG(14)) "]\n"
|
|
363
|
+
" stp x16, x17, [x0, #" SCR_STR(SCR_A64_UC_REG(16)) "]\n"
|
|
364
|
+
" stp x18, x19, [x0, #" SCR_STR(SCR_A64_UC_REG(18)) "]\n"
|
|
365
|
+
" stp x20, x21, [x0, #" SCR_STR(SCR_A64_UC_REG(20)) "]\n"
|
|
366
|
+
" stp x22, x23, [x0, #" SCR_STR(SCR_A64_UC_REG(22)) "]\n"
|
|
367
|
+
" stp x24, x25, [x0, #" SCR_STR(SCR_A64_UC_REG(24)) "]\n"
|
|
368
|
+
" stp x26, x27, [x0, #" SCR_STR(SCR_A64_UC_REG(26)) "]\n"
|
|
369
|
+
" stp x28, x29, [x0, #" SCR_STR(SCR_A64_UC_REG(28)) "]\n"
|
|
370
|
+
" str x30, [x0, #" SCR_STR(SCR_A64_UC_REG(30)) "]\n"
|
|
371
|
+
" str x30, [x0, #" SCR_STR(SCR_A64_UC_PC) "]\n"
|
|
372
|
+
" mov x2, sp\n"
|
|
373
|
+
" str x2, [x0, #" SCR_STR(SCR_A64_UC_SP) "]\n"
|
|
374
|
+
" str xzr, [x0, #" SCR_STR(SCR_A64_UC_PSTATE) "]\n"
|
|
375
|
+
" add x2, x0, #" SCR_STR(SCR_A64_UC_FPSIMD) "\n"
|
|
376
|
+
" stp q8, q9, [x2, #144]\n"
|
|
377
|
+
" stp q10, q11, [x2, #176]\n"
|
|
378
|
+
" stp q12, q13, [x2, #208]\n"
|
|
379
|
+
" stp q14, q15, [x2, #240]\n"
|
|
380
|
+
" mov x0, x1\n"
|
|
381
|
+
" b setcontext\n"
|
|
382
|
+
|
|
383
|
+
".p2align 2\n"
|
|
384
|
+
".hidden scr_musl_context_trampoline\n"
|
|
385
|
+
"scr_musl_context_trampoline:\n"
|
|
386
|
+
" mov x0, x19\n"
|
|
387
|
+
" cbz x0, 1f\n"
|
|
388
|
+
" bl setcontext\n"
|
|
389
|
+
" brk #0\n"
|
|
390
|
+
"1:\n"
|
|
391
|
+
" mov w0, #0\n"
|
|
392
|
+
" bl exit\n"
|
|
393
|
+
" brk #0\n");
|
|
394
|
+
|
|
395
|
+
extern void scr_musl_context_trampoline(void);
|
|
396
|
+
|
|
397
|
+
void makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) {
|
|
398
|
+
greg_t *sp;
|
|
399
|
+
va_list va;
|
|
400
|
+
int i;
|
|
401
|
+
|
|
402
|
+
sp = (greg_t *)((uintptr_t)ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size);
|
|
403
|
+
sp -= argc < 8 ? 0 : argc - 8;
|
|
404
|
+
sp = (greg_t *)((uintptr_t)sp & ~(uintptr_t)15);
|
|
405
|
+
|
|
406
|
+
ucp->uc_mcontext.sp = (greg_t)(uintptr_t)sp;
|
|
407
|
+
ucp->uc_mcontext.pc = (greg_t)(uintptr_t)func;
|
|
408
|
+
ucp->uc_mcontext.regs[19] = (greg_t)(uintptr_t)ucp->uc_link;
|
|
409
|
+
ucp->uc_mcontext.regs[30] =
|
|
410
|
+
(greg_t)(uintptr_t)&scr_musl_context_trampoline;
|
|
411
|
+
|
|
412
|
+
va_start(va, argc);
|
|
413
|
+
for (i = 0; i < argc && i < 8; i++) {
|
|
414
|
+
ucp->uc_mcontext.regs[i] = va_arg(va, greg_t);
|
|
415
|
+
}
|
|
416
|
+
for (; i < argc; i++) {
|
|
417
|
+
*sp++ = va_arg(va, greg_t);
|
|
418
|
+
}
|
|
419
|
+
va_end(va);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
#undef SCR_A64_UC_FPSIMD
|
|
423
|
+
#undef SCR_A64_UC_PSTATE
|
|
424
|
+
#undef SCR_A64_UC_PC
|
|
425
|
+
#undef SCR_A64_UC_SP
|
|
426
|
+
#undef SCR_A64_UC_REG
|
|
427
|
+
#undef SCR_STR
|
|
428
|
+
#undef SCR_STR_INNER
|
|
429
|
+
|
|
430
|
+
#endif /* architecture */
|
|
431
|
+
|
|
268
432
|
#endif /* !SCR_LIB */
|
|
269
433
|
|
|
270
434
|
#else /* !SCR_MUSL */
|
package/src/scr_runtime.h
CHANGED
|
@@ -5493,18 +5493,25 @@ long scr_secure_ctx_live_count(void);
|
|
|
5493
5493
|
#endif
|
|
5494
5494
|
|
|
5495
5495
|
/* ── node:tls, the CA-store introspection slice (scr_tls_ca.c — its own
|
|
5496
|
-
* unit and link gate;
|
|
5497
|
-
*
|
|
5498
|
-
*
|
|
5499
|
-
*
|
|
5500
|
-
*
|
|
5501
|
-
*
|
|
5502
|
-
*
|
|
5503
|
-
*
|
|
5504
|
-
*
|
|
5505
|
-
* with strictEqual). */
|
|
5496
|
+
* unit and link gate; NO mbedTLS, so a getCACertificates-only binary never
|
|
5497
|
+
* builds the archive; cc.ts also compiles it whenever scr_tls.c does). The
|
|
5498
|
+
* HOST roots (Windows' system certificate stores, the established bundle probe on
|
|
5499
|
+
* POSIX) stand in for both Node's compiled-in Mozilla roots ('bundled',
|
|
5500
|
+
* rootCertificates) and the platform store ('system') — the established
|
|
5501
|
+
* SEMANTICS divergence, extended to introspection; 'extra' uses the
|
|
5502
|
+
* NODE_EXTRA_CA_CERTS file captured before user code runs. Arrays are cached
|
|
5503
|
+
* per type (+1 retained answers each call — Node's own caching, and the
|
|
5504
|
+
* identity the suite pins with strictEqual). */
|
|
5506
5505
|
void scr_tls_ca_install(void); /* snapshots NODE_EXTRA_CA_CERTS + file bytes */
|
|
5507
5506
|
bool scr_tls_ca_extra_pem(const char **pem, size_t *len); /* borrowed launch snapshot */
|
|
5507
|
+
#ifdef _WIN32
|
|
5508
|
+
/* Enumerates Windows' trusted ROOT, intermediate CA, and TrustedPeople store
|
|
5509
|
+
* locations, yielding only certificates whose effective Windows EKU policy
|
|
5510
|
+
* permits TLS server authentication. DER is borrowed for the call. */
|
|
5511
|
+
typedef void (*ScrTlsCaWindowsCertFn)(void *ctx, const unsigned char *der, size_t len);
|
|
5512
|
+
bool scr_tls_ca_windows_cert_server_auth(const void *cert_context);
|
|
5513
|
+
void scr_tls_ca_windows_certs(ScrTlsCaWindowsCertFn fn, void *ctx);
|
|
5514
|
+
#endif
|
|
5508
5515
|
ScrArr *scr_tls_ca_get(ScrStr *type); /* +1; throws ERR_INVALID_ARG_VALUE on unknown types */
|
|
5509
5516
|
ScrArr *scr_tls_ca_root(void); /* +1; === getCACertificates("bundled") */
|
|
5510
5517
|
/* Replaces the 'default' set: entries filter to their PEM certificate
|
package/src/scr_tls.c
CHANGED
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
* head buffers in the socket's write buffer until the handshake
|
|
57
57
|
* establishes (the mid-connect buffering path, reused verbatim).
|
|
58
58
|
* rejectUnauthorized:false maps to VERIFY_NONE; `ca` replaces the trust
|
|
59
|
-
* anchors; with neither,
|
|
59
|
+
* anchors; with neither, the host trust store stands in for Node's bundled
|
|
60
60
|
* Mozilla roots (SEMANTICS.md documents the divergence). Verify
|
|
61
61
|
* failures surface as Node-shaped 'error' messages on the request
|
|
62
62
|
* ("self-signed certificate", "self-signed certificate in certificate
|
|
@@ -336,15 +336,15 @@ typedef struct ScrTlsCli {
|
|
|
336
336
|
bool verify_recorded;
|
|
337
337
|
} ScrTlsCli;
|
|
338
338
|
|
|
339
|
-
/* The default trust anchors when no `ca` option is given: the
|
|
340
|
-
*
|
|
341
|
-
* NODE_EXTRA_CA_CERTS.
|
|
342
|
-
*
|
|
343
|
-
*
|
|
344
|
-
*
|
|
345
|
-
*
|
|
346
|
-
*
|
|
347
|
-
* bundle
|
|
339
|
+
/* The default trust anchors when no `ca` option is given: the host trust
|
|
340
|
+
* store, standing in for Node's compiled-in Mozilla roots, plus
|
|
341
|
+
* NODE_EXTRA_CA_CERTS. Windows certificates live as DER entries across the
|
|
342
|
+
* machine, enterprise, current-user, and policy ROOT/CA/TrustedPeople store
|
|
343
|
+
* locations; mbedTLS copies each successfully parsed entry into its own chain.
|
|
344
|
+
* POSIX hosts probe the established bundle spellings — /etc/ssl/cert.pem
|
|
345
|
+
* first (macOS ships it; Alpine links it), then Debian/Ubuntu's
|
|
346
|
+
* ca-certificates.crt, Fedora/RHEL's ca-bundle.crt, and openSUSE's
|
|
347
|
+
* ca-bundle.pem. */
|
|
348
348
|
static mbedtls_x509_crt scr_tls_system_roots;
|
|
349
349
|
static bool scr_tls_system_roots_loaded = false;
|
|
350
350
|
|
|
@@ -356,6 +356,12 @@ static bool scr_tls_system_roots_loaded = false;
|
|
|
356
356
|
static mbedtls_x509_crt scr_tls_override_roots;
|
|
357
357
|
static uint64_t scr_tls_override_parsed_gen = 0;
|
|
358
358
|
|
|
359
|
+
#ifdef _WIN32
|
|
360
|
+
static void scr_tls_add_windows_ca(void *ctx, const unsigned char *der, size_t len) {
|
|
361
|
+
(void)mbedtls_x509_crt_parse_der((mbedtls_x509_crt *)ctx, der, len);
|
|
362
|
+
}
|
|
363
|
+
#endif
|
|
364
|
+
|
|
359
365
|
static mbedtls_x509_crt *scr_tls_system_ca(void) {
|
|
360
366
|
const char *pem = NULL;
|
|
361
367
|
size_t pem_len = 0;
|
|
@@ -375,6 +381,12 @@ static mbedtls_x509_crt *scr_tls_system_ca(void) {
|
|
|
375
381
|
if (!scr_tls_system_roots_loaded) {
|
|
376
382
|
scr_tls_system_roots_loaded = true;
|
|
377
383
|
mbedtls_x509_crt_init(&scr_tls_system_roots);
|
|
384
|
+
#ifdef _WIN32
|
|
385
|
+
/* The shared enumerator applies Windows' effective server-auth EKU
|
|
386
|
+
* policy before yielding DER. mbedTLS copies every successfully parsed
|
|
387
|
+
* entry, so the store contexts may die immediately after each callback. */
|
|
388
|
+
scr_tls_ca_windows_certs(scr_tls_add_windows_ca, &scr_tls_system_roots);
|
|
389
|
+
#else
|
|
378
390
|
static const char *const bundles[] = {
|
|
379
391
|
"/etc/ssl/cert.pem", /* macOS, Alpine */
|
|
380
392
|
"/etc/ssl/certs/ca-certificates.crt", /* Debian/Ubuntu */
|
|
@@ -384,6 +396,7 @@ static mbedtls_x509_crt *scr_tls_system_ca(void) {
|
|
|
384
396
|
for (size_t i = 0; i < sizeof bundles / sizeof bundles[0]; i++) {
|
|
385
397
|
if (mbedtls_x509_crt_parse_file(&scr_tls_system_roots, bundles[i]) == 0) break;
|
|
386
398
|
}
|
|
399
|
+
#endif
|
|
387
400
|
const char *extra = NULL;
|
|
388
401
|
size_t extra_len = 0;
|
|
389
402
|
if (scr_tls_ca_extra_pem(&extra, &extra_len) && extra_len > 0) {
|
package/src/scr_tls_ca.c
CHANGED
|
@@ -2,28 +2,33 @@
|
|
|
2
2
|
* rootCertificates, and setDefaultCACertificates (scr_runtime.h has the
|
|
3
3
|
* contracts). Its own link gate ("tlsca." libCalls), deliberately free
|
|
4
4
|
* of mbedTLS: everything here is PEM-BLOCK bookkeeping over the host
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* alongside it) consults
|
|
8
|
-
* trust anchors, which is what
|
|
9
|
-
* semantics: the next https/tls dial
|
|
5
|
+
* roots (plus crypt32 store access on Windows), so a program that only
|
|
6
|
+
* inspects the CA store never builds the TLS archive. scr_tls.c (when it
|
|
7
|
+
* links — cc.ts compiles this unit alongside it) consults
|
|
8
|
+
* scr_tls_ca_default_override for its client trust anchors, which is what
|
|
9
|
+
* makes setDefaultCACertificates LIVE semantics: the next https/tls dial
|
|
10
|
+
* verifies against the replaced set.
|
|
10
11
|
*
|
|
11
12
|
* Divergences, documented: the host bundle stands in for Node's
|
|
12
13
|
* compiled-in Mozilla roots ('bundled' and rootCertificates) AND for the
|
|
13
|
-
* platform store ('system') —
|
|
14
|
-
* scr_tls.c's anchors
|
|
15
|
-
* shaped (a well-formed block with corrupt DER
|
|
16
|
-
* Node's X509 parse would drop it — such a cert
|
|
17
|
-
* instead, the same observable outcome one step
|
|
18
|
-
* byte-exact over the extracted block where Node
|
|
19
|
-
* identities; re-encoded duplicates of one certificate
|
|
20
|
-
* entries, which no equality the tests observe can distinguish
|
|
21
|
-
* parser. */
|
|
14
|
+
* platform store ('system') — Windows' system certificate stores and the POSIX
|
|
15
|
+
* bundle probe are the same sources scr_tls.c's anchors use; and set-time
|
|
16
|
+
* validation is PEM-BLOCK shaped (a well-formed block with corrupt DER
|
|
17
|
+
* inside is kept here where Node's X509 parse would drop it — such a cert
|
|
18
|
+
* then fails verification instead, the same observable outcome one step
|
|
19
|
+
* later). Deduplication is byte-exact over the extracted block where Node
|
|
20
|
+
* compares parsed X509 identities; re-encoded duplicates of one certificate
|
|
21
|
+
* stay distinct entries, which no equality the tests observe can distinguish
|
|
22
|
+
* without a parser. */
|
|
22
23
|
#include "scr_runtime.h"
|
|
23
24
|
|
|
24
25
|
#include <stdio.h>
|
|
25
26
|
#include <stdlib.h>
|
|
26
27
|
#include <string.h>
|
|
28
|
+
#ifdef _WIN32
|
|
29
|
+
#include <windows.h>
|
|
30
|
+
#include <wincrypt.h>
|
|
31
|
+
#endif
|
|
27
32
|
|
|
28
33
|
/* The per-type caches: +1 held here for the process lifetime (an atexit
|
|
29
34
|
* teardown releases them so the RC audit stays clean). 'default' also
|
|
@@ -154,9 +159,121 @@ bool scr_tls_ca_extra_pem(const char **pem, size_t *len) {
|
|
|
154
159
|
return true;
|
|
155
160
|
}
|
|
156
161
|
|
|
157
|
-
|
|
162
|
+
#ifdef _WIN32
|
|
163
|
+
/* Windows can restrict a certificate's purposes in a store property that is
|
|
164
|
+
* not part of its DER. CertGetEnhancedKeyUsage with flags 0 intersects that
|
|
165
|
+
* property with the encoded EKU extension. An empty result means either all
|
|
166
|
+
* purposes (CRYPT_E_NOT_FOUND) or no purposes (ERROR_SUCCESS); every other
|
|
167
|
+
* API failure is fail-closed too. */
|
|
168
|
+
bool scr_tls_ca_windows_cert_server_auth(const void *cert_context) {
|
|
169
|
+
PCCERT_CONTEXT cert = (PCCERT_CONTEXT)cert_context;
|
|
170
|
+
DWORD usage_len = 0;
|
|
171
|
+
if (!CertGetEnhancedKeyUsage(cert, 0, NULL, &usage_len) || usage_len == 0) {
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
CERT_ENHKEY_USAGE *usage = malloc((size_t)usage_len);
|
|
175
|
+
if (usage == NULL) scr_ca_oom();
|
|
176
|
+
if (!CertGetEnhancedKeyUsage(cert, 0, usage, &usage_len)) {
|
|
177
|
+
free(usage);
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
DWORD usage_error = GetLastError();
|
|
181
|
+
bool allowed = usage->cUsageIdentifier == 0 &&
|
|
182
|
+
usage_error == CRYPT_E_NOT_FOUND;
|
|
183
|
+
for (DWORD i = 0; !allowed && usage->rgpszUsageIdentifier != NULL &&
|
|
184
|
+
i < usage->cUsageIdentifier; i++) {
|
|
185
|
+
const char *oid = usage->rgpszUsageIdentifier[i];
|
|
186
|
+
allowed = oid != NULL &&
|
|
187
|
+
(strcmp(oid, szOID_PKIX_KP_SERVER_AUTH) == 0 ||
|
|
188
|
+
strcmp(oid, szOID_ANY_ENHANCED_KEY_USAGE) == 0);
|
|
189
|
+
}
|
|
190
|
+
free(usage);
|
|
191
|
+
return allowed;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
static void scr_tls_ca_windows_certs_at(
|
|
195
|
+
DWORD location, const char *store_name, HCERTSTORE seen,
|
|
196
|
+
ScrTlsCaWindowsCertFn fn, void *ctx) {
|
|
197
|
+
HCERTSTORE store = CertOpenStore(
|
|
198
|
+
CERT_STORE_PROV_SYSTEM_A, 0, 0,
|
|
199
|
+
location | CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG,
|
|
200
|
+
store_name);
|
|
201
|
+
if (store == NULL) return;
|
|
202
|
+
PCCERT_CONTEXT cert = NULL;
|
|
203
|
+
/* CertEnumCertificatesInStore frees the previous context on every call,
|
|
204
|
+
* including the final NULL result. Each callback must copy DER it keeps. */
|
|
205
|
+
while ((cert = CertEnumCertificatesInStore(store, cert)) != NULL) {
|
|
206
|
+
/* The logical stores overlap (notably CurrentUser inherits machine
|
|
207
|
+
* roots). CERT_STORE_ADD_NEW turns the memory store into a process-local
|
|
208
|
+
* identity set: only the first allowed context reaches the consumer. */
|
|
209
|
+
if (scr_tls_ca_windows_cert_server_auth(cert) &&
|
|
210
|
+
CertAddCertificateContextToStore(
|
|
211
|
+
seen, cert, CERT_STORE_ADD_NEW, NULL)) {
|
|
212
|
+
fn(ctx, cert->pbCertEncoded, (size_t)cert->cbCertEncoded);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
(void)CertCloseStore(store, 0);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
void scr_tls_ca_windows_certs(ScrTlsCaWindowsCertFn fn, void *ctx) {
|
|
219
|
+
/* Match Node's Windows system-certificate sources: roots and intermediate
|
|
220
|
+
* CAs from all five applicable locations, plus explicitly trusted server
|
|
221
|
+
* certificates from the three local-machine TrustedPeople locations.
|
|
222
|
+
* A memory store deduplicates their overlapping contents. */
|
|
223
|
+
typedef struct ScrTlsCaWindowsStore {
|
|
224
|
+
DWORD location;
|
|
225
|
+
const char *name;
|
|
226
|
+
} ScrTlsCaWindowsStore;
|
|
227
|
+
static const ScrTlsCaWindowsStore stores[] = {
|
|
228
|
+
{CERT_SYSTEM_STORE_LOCAL_MACHINE, "ROOT"},
|
|
229
|
+
{CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY, "ROOT"},
|
|
230
|
+
{CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE, "ROOT"},
|
|
231
|
+
{CERT_SYSTEM_STORE_CURRENT_USER, "ROOT"},
|
|
232
|
+
{CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY, "ROOT"},
|
|
233
|
+
{CERT_SYSTEM_STORE_LOCAL_MACHINE, "CA"},
|
|
234
|
+
{CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY, "CA"},
|
|
235
|
+
{CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE, "CA"},
|
|
236
|
+
{CERT_SYSTEM_STORE_CURRENT_USER, "CA"},
|
|
237
|
+
{CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY, "CA"},
|
|
238
|
+
{CERT_SYSTEM_STORE_LOCAL_MACHINE, "TrustedPeople"},
|
|
239
|
+
{CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY, "TrustedPeople"},
|
|
240
|
+
{CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE, "TrustedPeople"},
|
|
241
|
+
};
|
|
242
|
+
HCERTSTORE seen = CertOpenStore(
|
|
243
|
+
CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
|
|
244
|
+
if (seen == NULL) return;
|
|
245
|
+
for (size_t i = 0; i < sizeof stores / sizeof stores[0]; i++) {
|
|
246
|
+
scr_tls_ca_windows_certs_at(
|
|
247
|
+
stores[i].location, stores[i].name, seen, fn, ctx);
|
|
248
|
+
}
|
|
249
|
+
(void)CertCloseStore(seen, 0);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
static void scr_ca_push_windows_cert(void *ctx, const unsigned char *der, size_t len) {
|
|
253
|
+
if (len > UINT32_MAX) return;
|
|
254
|
+
DWORD pem_cap = 0;
|
|
255
|
+
DWORD flags = CRYPT_STRING_BASE64HEADER | CRYPT_STRING_NOCR;
|
|
256
|
+
if (!CryptBinaryToStringA(der, (DWORD)len, flags, NULL, &pem_cap) ||
|
|
257
|
+
pem_cap == 0) {
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
char *pem = malloc((size_t)pem_cap);
|
|
261
|
+
if (pem == NULL) scr_ca_oom();
|
|
262
|
+
DWORD pem_len = pem_cap;
|
|
263
|
+
if (CryptBinaryToStringA(der, (DWORD)len, flags, pem, &pem_len)) {
|
|
264
|
+
scr_arr_push_ref((ScrArr *)ctx, scr_str_new(pem, (size_t)pem_len));
|
|
265
|
+
}
|
|
266
|
+
free(pem);
|
|
267
|
+
}
|
|
268
|
+
#endif
|
|
269
|
+
|
|
270
|
+
/* The host roots, from the Windows logical store or the POSIX bundle probe
|
|
271
|
+
* shared with scr_tls.c. */
|
|
158
272
|
static ScrArr *scr_ca_load_host_bundle(void) {
|
|
159
273
|
ScrArr *arr = scr_arr_new(SCR_ELEM_STR, 128);
|
|
274
|
+
#ifdef _WIN32
|
|
275
|
+
scr_tls_ca_windows_certs(scr_ca_push_windows_cert, arr);
|
|
276
|
+
#else
|
|
160
277
|
static const char *const bundles[] = {
|
|
161
278
|
"/etc/ssl/cert.pem", /* macOS, Alpine */
|
|
162
279
|
"/etc/ssl/certs/ca-certificates.crt", /* Debian/Ubuntu */
|
|
@@ -171,6 +288,7 @@ static ScrArr *scr_ca_load_host_bundle(void) {
|
|
|
171
288
|
free(text);
|
|
172
289
|
break; /* first bundle wins, like the anchor probe */
|
|
173
290
|
}
|
|
291
|
+
#endif
|
|
174
292
|
return arr;
|
|
175
293
|
}
|
|
176
294
|
|
package/vendor/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
- Commit: 49e671dd52ff6791295d8161ad3b6da7dc5f6f9d
|
|
7
7
|
- License: ISC (copyright and permission notice reproduced in `src/scr_musl.c`)
|
|
8
8
|
|
|
9
|
-
The x86_64 register-save/restore and `makecontext` logic is adapted into `src/scr_musl.c`, rather than carried as a separate library, to supply the legacy `ucontext` functions that musl declares but does not implement. It is compiled
|
|
9
|
+
The x86_64 and AArch64 register-save/restore and `makecontext` logic is adapted into `src/scr_musl.c`, rather than carried as a separate library, to supply the legacy `ucontext` functions that musl declares but does not implement. It is compiled for the explicit `x86_64-linux-musl` and `aarch64-linux-musl` targets and uses musl's public `ucontext_t` layouts. The signal-mask compatibility wrapper is deliberately not included: scriptc fibers perform user-space register swaps and do not change a per-fiber signal mask.
|
|
10
10
|
|
|
11
11
|
## ryu/
|
|
12
12
|
|