Skip to content

Re-seed a CtrDrbg in a fresh context; keep raw add_source! objects alive - #322

Merged
quinnj merged 1 commit into
masterfrom
jq/ctr-drbg-reseed
Oct 23, 2026
Merged

quinnj merged 1 commit into
masterfrom
jq/ctr-drbg-reseed

Conversation

@quinnj

@quinnj quinnj commented Oct 23, 2026

Copy link
Copy Markdown
Member
  • Re-seeding: mbedtls_ctr_drbg_seed must be called on a fresh context (ctr_drbg.h). seed! on a generator that had served more than ~336 requests failed with CTR_DRBG - The input (entropy + additional data) is too large, because mbedtls reuses its request counter as the nonce length. The failed seed also left mbedtls pointing at the new Entropy, which nothing kept alive, so the automatic reseed 10,000 requests later called freed memory (CTR_DRBG - The entropy source failed, or worse). seed! now frees and re-initializes the context first, and marks the generator seeded only once seeding succeeds. random! checks that under the lock.
  • The raw add_source!(ctx, ::Ptr, f, ...) now stores f and passes the stored object, under the Entropy's lock, as the Function method already did; that method now just calls it.
  • jl_entropy caps a source's reported length at the buffer size mbedtls gave it. A source that over-reported made mbedtls read past its 128-byte stack buffer.

New test: draw 400 times, re-seed, GC, then draw past the reseed interval. It errors on master at the re-seed.

Found by a fifth independent review pass; reproduced and checked here.

🤖 Generated with Claude Code

- mbedtls_ctr_drbg_seed must be called on a fresh context: seed! on a generator that had
  served more than ~336 requests failed with "input too large" (it reuses the request
  counter as the nonce length), and the failed seeding left mbedtls pointing at the new,
  unrooted Entropy, so the automatic reseed 10000 requests later called freed memory.
  seed! now frees and re-initializes the context first, and marks the generator seeded only
  once seeding succeeds.
- The raw add_source!(ctx, ::Ptr, f, ...) now stores f and passes the stored object, under
  the Entropy's lock; the Function method just calls it.
- jl_entropy caps a source's reported length at the buffer size mbedtls gave it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@codecov

codecov Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 89.79%. Comparing base (06ecccb) to head (fb759ec).

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #322      +/-   ##
==========================================
+ Coverage   89.70%   89.79%   +0.08%     
==========================================
  Files          12       12              
  Lines         913      921       +8     
==========================================
+ Hits          819      827       +8     
  Misses         94       94              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@quinnj
quinnj merged commit df553a3 into master Oct 23, 2026
9 checks passed
@quinnj
quinnj deleted the jq/ctr-drbg-reseed branch October 23, 2026 21:48
quinnj added a commit that referenced this pull request Oct 23, 2026
… re-seed, empty CRT info, empty ALPN (#324)

- isreadable(ctx) decrypted arriving records even while another task waited in eof(ctx)
  for them, leaving that task waiting on an empty socket (or, with renegotiation on,
  blocked behind it). It now processes them only when it can take waitlock.
- mbedtls parses a key only into an empty PKContext: given one that holds a key, it frees
  that key and fails, breaking configs and RSA(pk) views that use it. The parse functions
  now throw an ArgumentError first.
- seed! (since #322) freed the context before seeding, so a failed re-seed (bad pdata, a
  failing source) left a working generator unusable. It now seeds a fresh context and swaps
  it in only on success.
- show(::CRT) on an empty CRT grew its buffer until out of memory (since #302): mbedtls
  reports "buffer too small" for its own internal buffer there. Growth stops at 16 MiB.
- set_alpn!(conf, String[]) made mbedtls send an empty ALPN extension, which servers
  reject; it now throws an ArgumentError.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant