crypto/elliptic: add constant-time P224.

(Sending to r because of the API change.)

This change alters the API for crypto/elliptic to permit different
implementations in the future. This will allow us to add faster,
constant-time implementations of the standard curves without any more
API changes.

As a demonstration, it also adds a constant-time implementation of
P224. Since it's only 32-bit, it's actually only about 40% the speed
of the generic code on a 64-bit system.

R=r, rsc
CC=golang-dev
https://golang.org/cl/5528088
This commit is contained in:
Adam Langley 2012-01-19 08:39:03 -05:00
parent afedc6a568
commit 86824d5328

View File

@ -105,7 +105,7 @@ func md5SHA1Hash(slices ...[]byte) []byte {
// pre-master secret is then calculated using ECDH. // pre-master secret is then calculated using ECDH.
type ecdheRSAKeyAgreement struct { type ecdheRSAKeyAgreement struct {
privateKey []byte privateKey []byte
curve *elliptic.Curve curve elliptic.Curve
x, y *big.Int x, y *big.Int
} }
@ -132,11 +132,11 @@ Curve:
var x, y *big.Int var x, y *big.Int
var err error var err error
ka.privateKey, x, y, err = ka.curve.GenerateKey(config.rand()) ka.privateKey, x, y, err = elliptic.GenerateKey(ka.curve, config.rand())
if err != nil { if err != nil {
return nil, err return nil, err
} }
ecdhePublic := ka.curve.Marshal(x, y) ecdhePublic := elliptic.Marshal(ka.curve, x, y)
// http://tools.ietf.org/html/rfc4492#section-5.4 // http://tools.ietf.org/html/rfc4492#section-5.4
serverECDHParams := make([]byte, 1+2+1+len(ecdhePublic)) serverECDHParams := make([]byte, 1+2+1+len(ecdhePublic))
@ -167,12 +167,12 @@ func (ka *ecdheRSAKeyAgreement) processClientKeyExchange(config *Config, ckx *cl
if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 { if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 {
return nil, errors.New("bad ClientKeyExchange") return nil, errors.New("bad ClientKeyExchange")
} }
x, y := ka.curve.Unmarshal(ckx.ciphertext[1:]) x, y := elliptic.Unmarshal(ka.curve, ckx.ciphertext[1:])
if x == nil { if x == nil {
return nil, errors.New("bad ClientKeyExchange") return nil, errors.New("bad ClientKeyExchange")
} }
x, _ = ka.curve.ScalarMult(x, y, ka.privateKey) x, _ = ka.curve.ScalarMult(x, y, ka.privateKey)
preMasterSecret := make([]byte, (ka.curve.BitSize+7)>>3) preMasterSecret := make([]byte, (ka.curve.Params().BitSize+7)>>3)
xBytes := x.Bytes() xBytes := x.Bytes()
copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes) copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
@ -205,7 +205,7 @@ func (ka *ecdheRSAKeyAgreement) processServerKeyExchange(config *Config, clientH
if publicLen+4 > len(skx.key) { if publicLen+4 > len(skx.key) {
return errServerKeyExchange return errServerKeyExchange
} }
ka.x, ka.y = ka.curve.Unmarshal(skx.key[4 : 4+publicLen]) ka.x, ka.y = elliptic.Unmarshal(ka.curve, skx.key[4:4+publicLen])
if ka.x == nil { if ka.x == nil {
return errServerKeyExchange return errServerKeyExchange
} }
@ -229,16 +229,16 @@ func (ka *ecdheRSAKeyAgreement) generateClientKeyExchange(config *Config, client
if ka.curve == nil { if ka.curve == nil {
return nil, nil, errors.New("missing ServerKeyExchange message") return nil, nil, errors.New("missing ServerKeyExchange message")
} }
priv, mx, my, err := ka.curve.GenerateKey(config.rand()) priv, mx, my, err := elliptic.GenerateKey(ka.curve, config.rand())
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
x, _ := ka.curve.ScalarMult(ka.x, ka.y, priv) x, _ := ka.curve.ScalarMult(ka.x, ka.y, priv)
preMasterSecret := make([]byte, (ka.curve.BitSize+7)>>3) preMasterSecret := make([]byte, (ka.curve.Params().BitSize+7)>>3)
xBytes := x.Bytes() xBytes := x.Bytes()
copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes) copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
serialized := ka.curve.Marshal(mx, my) serialized := elliptic.Marshal(ka.curve, mx, my)
ckx := new(clientKeyExchangeMsg) ckx := new(clientKeyExchangeMsg)
ckx.ciphertext = make([]byte, 1+len(serialized)) ckx.ciphertext = make([]byte, 1+len(serialized))