Repository navigation
Check the draws behind the DKG, dealer and refresh secrets too - #1066
Merged
Merged
Conversation
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 59 minutes. View limit details
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
#1064 routed FROST nonce commitments through an RNG that is checked at the point of the draw. The draws behind the long-lived secrets were still unchecked: DKG round one, the trusted dealer, the ed25519 dealer, and share refresh. Those draws produce the signing shares and the group key, so a degraded source there is worse than a degraded nonce: a nonce leak exposes one share, a predictable dealer polynomial exposes the key the shares were derived from.
Five call sites now draw through
CheckedRng, and the module moves fromfrost/nonce.rstofrost/checked_rng.rssince it is no longer specific to nonces.What the criteria now apply to
Each 32-byte block is compared against every block already judged in the same call, not only against the block before it. Retaining one block makes the comparisons adjacent-only, which a source alternating two far-apart values passes: a threshold-3 polynomial draws A, B, A, both adjacent pairs look healthy, and the group key is accepted from a source holding one bit of entropy. Comparing against all of them catches the repeat, and a third block additionally allows the one criterion a pair cannot carry, a byte position the source never moves. Across two draws that position holds the same extreme value about once in a thousand tries, which would refuse healthy draws at that rate, so the pairwise criterion drops it and this one restores it.
Fills are accumulated into whole blocks rather than judged per fill.
curve25519-dalek'sScalar::randomfills 64 bytes in one call where k256 fills 32 in a rejection loop, so a rule written for a single width judges nothing at all on the other curve. Accumulating also means a remainder joins the next fill instead of being dropped.A call that judged no whole block, or that ends with bytes left over, is refused as
Unavailablerather than passed. Those bytes became a secret and no criterion examined them, and certifying them with blocks drawn afterwards would read as assurance over material nothing looked at.Unavailablerather thanDegradedbecause this is the absence of a verdict, not a bad one: the caller refuses the draw without concluding the machine is broken, which is whatDegradedlatches a co-signer for.Calls that make a single draw
A share refresh at a threshold of two draws one coefficient, and that coefficient is the refresh delta, so leaving it unjudged means a refresh that heals nothing while reporting success. When a call has judged fewer blocks than the criteria need, the checked source draws from the same RNG until it has them. That costs at most two extra 32-byte draws, needs no process-wide state, and catches a stuck source on the first affected call rather than the second.
Worth being exact about the reach: at such a site the only comparison is the secret block against bytes drawn after it. That catches a source stuck, cycling or barely moving, because such a source is still that way when probed. It says nothing about a source that emits one chosen value and then healthy bytes, and no check at the draw can.
Supporting changes
refresh_sharesrefuses a threshold below two. The value comes from stored share metadata, which carries no floor of its own, and is handed to frost-core asmin_signers; frost-core validates before it draws, so the refusal arrived from inside the draw rather than from keep-core's own guard.clippy.tomldisallows the raw draw functions in both ciphersuite spellings, including the refresh and repair entries that take an RNG but have no caller here yet. Each sanctioned site marks the lintexpectrather thanallow: an entry that stops resolving after a dependency bump would otherwise go quiet, where an unfulfilled expectation is a warning and CI runs with-D warnings.--workspace --all-targetswith the features named. Test code was previously unlinted, and whether the ed25519 module was linted at all depended on workspace feature unification.cargo test -p keep-core --features ed25519 --lib. No job enabled that feature, so the ed25519 tests were type-checked and never executed, for the one ciphersuite whose fill width the block rule exists for.Coverage: stuck, creeping, all-zero, alternating and frozen-position sources; a source that looks healthy between fills but repeats within one, which isolates the width rule; a narrow draw and a ragged draw; a closure that never draws, which is an ordinary validation error and not a fault; group key generation on both curves; and the probe accounted for by byte count.