]> Cypherpunks repositories - gostls13.git/commitdiff
crypto/rsa: check CRT result.
authorAdam Langley <agl@golang.org>
Wed, 16 Dec 2015 00:07:47 +0000 (19:07 -0500)
committerAdam Langley <agl@golang.org>
Thu, 17 Dec 2015 00:00:33 +0000 (00:00 +0000)
This change adds a check after computing an RSA signature that the
signature is correct. This prevents an error in the CRT computation from
leaking the private key. See references in the linked bug.

benchmark                  old ns/op     new ns/op     delta
BenchmarkRSA2048Sign-3     5713305       6225215       +8.96%

Fixes #12453

Change-Id: I1f24e0b542f7c9a3f7e7ad4e971db3dc440ed3c1
Reviewed-on: https://go-review.googlesource.com/17862
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
src/crypto/rsa/pkcs1v15.go
src/crypto/rsa/pss.go
src/crypto/rsa/rsa.go
src/crypto/rsa/rsa_test.go

index 34037b0d674f72a8d3ec89bba1aa1a3d6c2594e7..37eaf1ab3e728911a62e6a2d7e4965c445b9210a 100644 (file)
@@ -223,7 +223,7 @@ func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []b
        copy(em[k-hashLen:k], hashed)
 
        m := new(big.Int).SetBytes(em)
-       c, err := decrypt(rand, priv, m)
+       c, err := decryptAndCheck(rand, priv, m)
        if err != nil {
                return
        }
index 0a41814a4b1e7c7a772f5ba3850068cefe88fbe9..8a94589b1c2b7d82222b3c02860442e1e613d706 100644 (file)
@@ -198,7 +198,7 @@ func signPSSWithSalt(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed,
                return
        }
        m := new(big.Int).SetBytes(em)
-       c, err := decrypt(rand, priv, m)
+       c, err := decryptAndCheck(rand, priv, m)
        if err != nil {
                return
        }
index 1293b783679b143440aabb2d5a9e04a391273f46..0a3e6acee96cb4d1cf6aae55aedc94158d743837 100644 (file)
@@ -506,6 +506,21 @@ func decrypt(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err er
        return
 }
 
+func decryptAndCheck(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err error) {
+       m, err = decrypt(random, priv, c)
+       if err != nil {
+               return nil, err
+       }
+
+       // In order to defend against errors in the CRT computation, m^e is
+       // calculated, which should match the original ciphertext.
+       check := encrypt(new(big.Int), &priv.PublicKey, m)
+       if c.Cmp(check) != 0 {
+               return nil, errors.New("rsa: internal error")
+       }
+       return m, nil
+}
+
 // DecryptOAEP decrypts ciphertext using RSA-OAEP.
 // If random != nil, DecryptOAEP uses RSA blinding to avoid timing side-channel attacks.
 func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext []byte, label []byte) (msg []byte, err error) {
index 4ee1c3a8b2afc6e4be23c041f7b40629a61c1e1b..6902f9a86735800d3d633614310e34eb051a5ee7 100644 (file)
@@ -6,8 +6,10 @@ package rsa
 
 import (
        "bytes"
+       "crypto"
        "crypto/rand"
        "crypto/sha1"
+       "crypto/sha256"
        "math/big"
        "testing"
 )
@@ -127,9 +129,10 @@ func fromBase10(base10 string) *big.Int {
        return i
 }
 
-func BenchmarkRSA2048Decrypt(b *testing.B) {
-       b.StopTimer()
-       priv := &PrivateKey{
+var test2048Key *PrivateKey
+
+func init() {
+       test2048Key = &PrivateKey{
                PublicKey: PublicKey{
                        N: fromBase10("14314132931241006650998084889274020608918049032671858325988396851334124245188214251956198731333464217832226406088020736932173064754214329009979944037640912127943488972644697423190955557435910767690712778463524983667852819010259499695177313115447116110358524558307947613422897787329221478860907963827160223559690523660574329011927531289655711860504630573766609239332569210831325633840174683944553667352219670930408593321661375473885147973879086994006440025257225431977751512374815915392249179976902953721486040787792801849818254465486633791826766873076617116727073077821584676715609985777563958286637185868165868520557"),
                        E: 3,
@@ -140,14 +143,28 @@ func BenchmarkRSA2048Decrypt(b *testing.B) {
                        fromBase10("109348945610485453577574767652527472924289229538286649661240938988020367005475727988253438647560958573506159449538793540472829815903949343191091817779240101054552748665267574271163617694640513549693841337820602726596756351006149518830932261246698766355347898158548465400674856021497190430791824869615170301029"),
                },
        }
-       priv.Precompute()
+       test2048Key.Precompute()
+}
+
+func BenchmarkRSA2048Decrypt(b *testing.B) {
+       b.StopTimer()
 
        c := fromBase10("8472002792838218989464636159316973636630013835787202418124758118372358261975764365740026024610403138425986214991379012696600761514742817632790916315594342398720903716529235119816755589383377471752116975374952783629225022962092351886861518911824745188989071172097120352727368980275252089141512321893536744324822590480751098257559766328893767334861211872318961900897793874075248286439689249972315699410830094164386544311554704755110361048571142336148077772023880664786019636334369759624917224888206329520528064315309519262325023881707530002540634660750469137117568199824615333883758410040459705787022909848740188613313")
 
        b.StartTimer()
 
        for i := 0; i < b.N; i++ {
-               decrypt(nil, priv, c)
+               decrypt(nil, test2048Key, c)
+       }
+}
+
+func BenchmarkRSA2048Sign(b *testing.B) {
+       b.StopTimer()
+       hashed := sha256.Sum256([]byte("testing"))
+       b.StartTimer()
+
+       for i := 0; i < b.N; i++ {
+               SignPKCS1v15(rand.Reader, test2048Key, crypto.SHA256, hashed[:])
        }
 }