]> Cypherpunks.ru repositories - gostls13.git/blobdiff - src/crypto/rsa/rsa.go
[dev.boringcrypto] all: merge master (nearly Go 1.10 beta 1) into dev.boringcrypto
[gostls13.git] / src / crypto / rsa / rsa.go
index 0faca43e430766dac34d87a6c4b5e864866bb0f4..9af5cbb16549cc801a35c5c77e239e40ff9903a4 100644 (file)
@@ -24,6 +24,7 @@ package rsa
 
 import (
        "crypto"
+       "crypto/internal/boring"
        "crypto/rand"
        "crypto/subtle"
        "errors"
@@ -31,6 +32,7 @@ import (
        "io"
        "math"
        "math/big"
+       "unsafe"
 )
 
 var bigZero = big.NewInt(0)
@@ -40,6 +42,8 @@ var bigOne = big.NewInt(1)
 type PublicKey struct {
        N *big.Int // modulus
        E int      // public exponent
+
+       boring unsafe.Pointer
 }
 
 // OAEPOptions is an interface for passing options to OAEP decryption using the
@@ -85,6 +89,8 @@ type PrivateKey struct {
        // Precomputed contains precomputed values that speed up private
        // operations, if available.
        Precomputed PrecomputedValues
+
+       boring unsafe.Pointer
 }
 
 // Public returns the public key corresponding to priv.
@@ -212,6 +218,32 @@ func GenerateKey(random io.Reader, bits int) (*PrivateKey, error) {
 // [1] US patent 4405829 (1972, expired)
 // [2] http://www.cacr.math.uwaterloo.ca/techreports/2006/cacr2006-16.pdf
 func GenerateMultiPrimeKey(random io.Reader, nprimes int, bits int) (*PrivateKey, error) {
+       if boring.Enabled && random == boring.RandReader && nprimes == 2 && (bits == 2048 || bits == 3072) {
+               N, E, D, P, Q, Dp, Dq, Qinv, err := boring.GenerateKeyRSA(bits)
+               if err != nil {
+                       return nil, err
+               }
+               e64 := E.Int64()
+               if !E.IsInt64() || int64(int(e64)) != e64 {
+                       return nil, errors.New("crypto/rsa: generated key exponent too large")
+               }
+               key := &PrivateKey{
+                       PublicKey: PublicKey{
+                               N: N,
+                               E: int(e64),
+                       },
+                       D:      D,
+                       Primes: []*big.Int{P, Q},
+                       Precomputed: PrecomputedValues{
+                               Dp:        Dp,
+                               Dq:        Dq,
+                               Qinv:      Qinv,
+                               CRTValues: make([]CRTValue, 0), // non-nil, to match Precompute
+                       },
+               }
+               return key, nil
+       }
+
        priv := new(PrivateKey)
        priv.E = 65537
 
@@ -346,6 +378,7 @@ func mgf1XOR(out []byte, hash hash.Hash, seed []byte) {
 var ErrMessageTooLong = errors.New("crypto/rsa: message too long for RSA public key size")
 
 func encrypt(c *big.Int, pub *PublicKey, m *big.Int) *big.Int {
+       boring.Unreachable()
        e := big.NewInt(int64(pub.E))
        c.Exp(m, e, pub.N)
        return c
@@ -378,6 +411,15 @@ func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, l
                return nil, ErrMessageTooLong
        }
 
+       if boring.Enabled && random == boring.RandReader {
+               bkey, err := boringPublicKey(pub)
+               if err != nil {
+                       return nil, err
+               }
+               return boring.EncryptRSAOAEP(hash, bkey, msg, label)
+       }
+       boring.UnreachableExceptTests()
+
        hash.Write(label)
        lHash := hash.Sum(nil)
        hash.Reset()
@@ -398,10 +440,24 @@ func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, l
        mgf1XOR(db, hash, seed)
        mgf1XOR(seed, hash, db)
 
-       m := new(big.Int)
-       m.SetBytes(em)
-       c := encrypt(new(big.Int), pub, m)
-       out := c.Bytes()
+       var out []byte
+       if boring.Enabled {
+               var bkey *boring.PublicKeyRSA
+               bkey, err = boringPublicKey(pub)
+               if err != nil {
+                       return nil, err
+               }
+               c, err := boring.EncryptRSANoPadding(bkey, em)
+               if err != nil {
+                       return nil, err
+               }
+               out = c
+       } else {
+               m := new(big.Int)
+               m.SetBytes(em)
+               c := encrypt(new(big.Int), pub, m)
+               out = c.Bytes()
+       }
 
        if len(out) < k {
                // If the output is too small, we need to left-pad with zeros.
@@ -478,6 +534,9 @@ func (priv *PrivateKey) Precompute() {
 // decrypt performs an RSA decryption, resulting in a plaintext integer. If a
 // random source is given, RSA blinding is used.
 func decrypt(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err error) {
+       if len(priv.Primes) <= 2 {
+               boring.Unreachable()
+       }
        // TODO(agl): can we get away with reusing blinds?
        if c.Cmp(priv.N) > 0 {
                err = ErrDecryption
@@ -593,6 +652,18 @@ func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext
                return nil, ErrDecryption
        }
 
+       if boring.Enabled {
+               boringFakeRandomBlind(random, priv)
+               bkey, err := boringPrivateKey(priv)
+               if err != nil {
+                       return nil, err
+               }
+               out, err := boring.DecryptRSAOAEP(hash, bkey, ciphertext, label)
+               if err != nil {
+                       return nil, ErrDecryption
+               }
+               return out, nil
+       }
        c := new(big.Int).SetBytes(ciphertext)
 
        m, err := decrypt(random, priv, c)