These keys are off-spec, but have historically been accepted by
ParsePKCS1PrivateKey.
Thanks to Philippe Antoine (Catena cyber) for reporting this issue.
Fixes #71216
Fixes CVE-2025-22865
Change-Id: I6a6a46564156fa32e29e8d6acbec3fbac47c7352
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1820
Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
Commit-Queue: Roland Shoemaker <bracewell@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/643098
Auto-Submit: Michael Knyszek <mknyszek@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
}
if priv.N.Sign() <= 0 || priv.D.Sign() <= 0 || priv.P.Sign() <= 0 || priv.Q.Sign() <= 0 ||
- priv.Dp.Sign() <= 0 || priv.Dq.Sign() <= 0 || priv.Qinv.Sign() <= 0 {
+ priv.Dp != nil && priv.Dp.Sign() <= 0 ||
+ priv.Dq != nil && priv.Dq.Sign() <= 0 ||
+ priv.Qinv != nil && priv.Qinv.Sign() <= 0 {
return nil, errors.New("x509: private key contains zero or negative value")
}
if _, err := ParsePKCS1PrivateKey(data); err == nil {
t.Errorf("parsing invalid private key did not result in an error")
}
+
+ // A partial key without CRT values should still parse.
+ b, _ := asn1.Marshal(struct {
+ Version int
+ N *big.Int
+ E int
+ D *big.Int
+ P *big.Int
+ Q *big.Int
+ }{
+ N: priv.N,
+ E: priv.PublicKey.E,
+ D: priv.D,
+ P: priv.Primes[0],
+ Q: priv.Primes[1],
+ })
+ p2, err := ParsePKCS1PrivateKey(b)
+ if err != nil {
+ t.Fatalf("parsing partial private key resulted in an error: %v", err)
+ }
+ if !p2.Equal(priv) {
+ t.Errorf("partial private key did not match original key")
+ }
+ if p2.Precomputed.Dp == nil || p2.Precomputed.Dq == nil || p2.Precomputed.Qinv == nil {
+ t.Errorf("precomputed values not recomputed")
+ }
}
func TestPKCS1MismatchPublicKeyFormat(t *testing.T) {