Skip to content

Commit 932ec2b

Browse files
FiloSottilegopherbot
authored andcommitted
crypto/rsa: fix GenerateKey flakes for toy-sized keys
Could have fixed this some other ways, including inside the FIPS 140-3 module, but this is small and self-contained, clearly not affecting production non-toy key sizes. This late in the freeze, a surgical fix felt best. Fixes #71185 Change-Id: I6a6a465641357c9d6b076c8a520b221be4210ed5 Reviewed-on: https://go-review.googlesource.com/c/go/+/641755 LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Roland Shoemaker <[email protected]> Auto-Submit: Filippo Valsorda <[email protected]> Reviewed-by: Russ Cox <[email protected]>
1 parent d0c9142 commit 932ec2b

File tree

2 files changed

+32
-0
lines changed

2 files changed

+32
-0
lines changed

src/crypto/rsa/rsa.go

+15
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,21 @@ func GenerateKey(random io.Reader, bits int) (*PrivateKey, error) {
327327
}
328328

329329
k, err := rsa.GenerateKey(random, bits)
330+
if bits < 256 && err != nil {
331+
// Toy-sized keys have a non-negligible chance of hitting two hard
332+
// failure cases: p == q and d <= 2^(nlen / 2).
333+
//
334+
// Since these are impossible to hit for real keys, we don't want to
335+
// make the production code path more complex and harder to think about
336+
// to handle them.
337+
//
338+
// Instead, just rerun the whole process a total of 8 times, which
339+
// brings the chance of failure for 32-bit keys down to the same as for
340+
// 256-bit keys.
341+
for i := 1; i < 8 && err != nil; i++ {
342+
k, err = rsa.GenerateKey(random, bits)
343+
}
344+
}
330345
if err != nil {
331346
return nil, err
332347
}

src/crypto/rsa/rsa_test.go

+17
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,23 @@ func TestImpossibleKeyGeneration(t *testing.T) {
109109
}
110110
}
111111

112+
func TestTinyKeyGeneration(t *testing.T) {
113+
// Toy-sized keys can randomly hit hard failures in GenerateKey.
114+
if testing.Short() {
115+
t.Skip("skipping in short mode")
116+
}
117+
t.Setenv("GODEBUG", "rsa1024min=0")
118+
for range 10000 {
119+
k, err := GenerateKey(rand.Reader, 32)
120+
if err != nil {
121+
t.Fatalf("GenerateKey(32): %v", err)
122+
}
123+
if err := k.Validate(); err != nil {
124+
t.Fatalf("Validate(32): %v", err)
125+
}
126+
}
127+
}
128+
112129
func TestGnuTLSKey(t *testing.T) {
113130
t.Setenv("GODEBUG", "rsa1024min=0")
114131
// This is a key generated by `certtool --generate-privkey --bits 128`.

0 commit comments

Comments
 (0)