github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/crypto/tls/key_agreement.go (about) 1 // Copyright 2010 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package tls 6 7 import ( 8 "crypto" 9 "crypto/elliptic" 10 "crypto/md5" 11 "crypto/rsa" 12 "crypto/sha1" 13 "crypto/x509" 14 "errors" 15 "io" 16 "math/big" 17 ) 18 19 // rsaKeyAgreement implements the standard TLS key agreement where the client 20 // encrypts the pre-master secret to the server's public key. 21 type rsaKeyAgreement struct{} 22 23 func (ka rsaKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) { 24 return nil, nil 25 } 26 27 func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) { 28 preMasterSecret := make([]byte, 48) 29 _, err := io.ReadFull(config.rand(), preMasterSecret[2:]) 30 if err != nil { 31 return nil, err 32 } 33 34 if len(ckx.ciphertext) < 2 { 35 return nil, errors.New("bad ClientKeyExchange") 36 } 37 38 ciphertext := ckx.ciphertext 39 if version != versionSSL30 { 40 ciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1]) 41 if ciphertextLen != len(ckx.ciphertext)-2 { 42 return nil, errors.New("bad ClientKeyExchange") 43 } 44 ciphertext = ckx.ciphertext[2:] 45 } 46 47 err = rsa.DecryptPKCS1v15SessionKey(config.rand(), cert.PrivateKey.(*rsa.PrivateKey), ciphertext, preMasterSecret) 48 if err != nil { 49 return nil, err 50 } 51 // We don't check the version number in the premaster secret. For one, 52 // by checking it, we would leak information about the validity of the 53 // encrypted pre-master secret. Secondly, it provides only a small 54 // benefit against a downgrade attack and some implementations send the 55 // wrong version anyway. See the discussion at the end of section 56 // 7.4.7.1 of RFC 4346. 57 return preMasterSecret, nil 58 } 59 60 func (ka rsaKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error { 61 return errors.New("unexpected ServerKeyExchange") 62 } 63 64 func (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) { 65 preMasterSecret := make([]byte, 48) 66 preMasterSecret[0] = byte(clientHello.vers >> 8) 67 preMasterSecret[1] = byte(clientHello.vers) 68 _, err := io.ReadFull(config.rand(), preMasterSecret[2:]) 69 if err != nil { 70 return nil, nil, err 71 } 72 73 encrypted, err := rsa.EncryptPKCS1v15(config.rand(), cert.PublicKey.(*rsa.PublicKey), preMasterSecret) 74 if err != nil { 75 return nil, nil, err 76 } 77 ckx := new(clientKeyExchangeMsg) 78 ckx.ciphertext = make([]byte, len(encrypted)+2) 79 ckx.ciphertext[0] = byte(len(encrypted) >> 8) 80 ckx.ciphertext[1] = byte(len(encrypted)) 81 copy(ckx.ciphertext[2:], encrypted) 82 return preMasterSecret, ckx, nil 83 } 84 85 // md5SHA1Hash implements TLS 1.0's hybrid hash function which consists of the 86 // concatenation of an MD5 and SHA1 hash. 87 func md5SHA1Hash(slices ...[]byte) []byte { 88 md5sha1 := make([]byte, md5.Size+sha1.Size) 89 hmd5 := md5.New() 90 for _, slice := range slices { 91 hmd5.Write(slice) 92 } 93 copy(md5sha1, hmd5.Sum(nil)) 94 95 hsha1 := sha1.New() 96 for _, slice := range slices { 97 hsha1.Write(slice) 98 } 99 copy(md5sha1[md5.Size:], hsha1.Sum(nil)) 100 return md5sha1 101 } 102 103 // ecdheRSAKeyAgreement implements a TLS key agreement where the server 104 // generates a ephemeral EC public/private key pair and signs it. The 105 // pre-master secret is then calculated using ECDH. 106 type ecdheRSAKeyAgreement struct { 107 privateKey []byte 108 curve elliptic.Curve 109 x, y *big.Int 110 } 111 112 func (ka *ecdheRSAKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) { 113 var curveid uint16 114 115 Curve: 116 for _, c := range clientHello.supportedCurves { 117 switch c { 118 case curveP256: 119 ka.curve = elliptic.P256() 120 curveid = c 121 break Curve 122 case curveP384: 123 ka.curve = elliptic.P384() 124 curveid = c 125 break Curve 126 case curveP521: 127 ka.curve = elliptic.P521() 128 curveid = c 129 break Curve 130 } 131 } 132 133 if curveid == 0 { 134 return nil, errors.New("tls: no supported elliptic curves offered") 135 } 136 137 var x, y *big.Int 138 var err error 139 ka.privateKey, x, y, err = elliptic.GenerateKey(ka.curve, config.rand()) 140 if err != nil { 141 return nil, err 142 } 143 ecdhePublic := elliptic.Marshal(ka.curve, x, y) 144 145 // http://tools.ietf.org/html/rfc4492#section-5.4 146 serverECDHParams := make([]byte, 1+2+1+len(ecdhePublic)) 147 serverECDHParams[0] = 3 // named curve 148 serverECDHParams[1] = byte(curveid >> 8) 149 serverECDHParams[2] = byte(curveid) 150 serverECDHParams[3] = byte(len(ecdhePublic)) 151 copy(serverECDHParams[4:], ecdhePublic) 152 153 md5sha1 := md5SHA1Hash(clientHello.random, hello.random, serverECDHParams) 154 sig, err := rsa.SignPKCS1v15(config.rand(), cert.PrivateKey.(*rsa.PrivateKey), crypto.MD5SHA1, md5sha1) 155 if err != nil { 156 return nil, errors.New("failed to sign ECDHE parameters: " + err.Error()) 157 } 158 159 skx := new(serverKeyExchangeMsg) 160 skx.key = make([]byte, len(serverECDHParams)+2+len(sig)) 161 copy(skx.key, serverECDHParams) 162 k := skx.key[len(serverECDHParams):] 163 k[0] = byte(len(sig) >> 8) 164 k[1] = byte(len(sig)) 165 copy(k[2:], sig) 166 167 return skx, nil 168 } 169 170 func (ka *ecdheRSAKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) { 171 if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 { 172 return nil, errors.New("bad ClientKeyExchange") 173 } 174 x, y := elliptic.Unmarshal(ka.curve, ckx.ciphertext[1:]) 175 if x == nil { 176 return nil, errors.New("bad ClientKeyExchange") 177 } 178 x, _ = ka.curve.ScalarMult(x, y, ka.privateKey) 179 preMasterSecret := make([]byte, (ka.curve.Params().BitSize+7)>>3) 180 xBytes := x.Bytes() 181 copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes) 182 183 return preMasterSecret, nil 184 } 185 186 var errServerKeyExchange = errors.New("invalid ServerKeyExchange") 187 188 func (ka *ecdheRSAKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error { 189 if len(skx.key) < 4 { 190 return errServerKeyExchange 191 } 192 if skx.key[0] != 3 { // named curve 193 return errors.New("server selected unsupported curve") 194 } 195 curveid := uint16(skx.key[1])<<8 | uint16(skx.key[2]) 196 197 switch curveid { 198 case curveP256: 199 ka.curve = elliptic.P256() 200 case curveP384: 201 ka.curve = elliptic.P384() 202 case curveP521: 203 ka.curve = elliptic.P521() 204 default: 205 return errors.New("server selected unsupported curve") 206 } 207 208 publicLen := int(skx.key[3]) 209 if publicLen+4 > len(skx.key) { 210 return errServerKeyExchange 211 } 212 ka.x, ka.y = elliptic.Unmarshal(ka.curve, skx.key[4:4+publicLen]) 213 if ka.x == nil { 214 return errServerKeyExchange 215 } 216 serverECDHParams := skx.key[:4+publicLen] 217 218 sig := skx.key[4+publicLen:] 219 if len(sig) < 2 { 220 return errServerKeyExchange 221 } 222 sigLen := int(sig[0])<<8 | int(sig[1]) 223 if sigLen+2 != len(sig) { 224 return errServerKeyExchange 225 } 226 sig = sig[2:] 227 228 md5sha1 := md5SHA1Hash(clientHello.random, serverHello.random, serverECDHParams) 229 return rsa.VerifyPKCS1v15(cert.PublicKey.(*rsa.PublicKey), crypto.MD5SHA1, md5sha1, sig) 230 } 231 232 func (ka *ecdheRSAKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) { 233 if ka.curve == nil { 234 return nil, nil, errors.New("missing ServerKeyExchange message") 235 } 236 priv, mx, my, err := elliptic.GenerateKey(ka.curve, config.rand()) 237 if err != nil { 238 return nil, nil, err 239 } 240 x, _ := ka.curve.ScalarMult(ka.x, ka.y, priv) 241 preMasterSecret := make([]byte, (ka.curve.Params().BitSize+7)>>3) 242 xBytes := x.Bytes() 243 copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes) 244 245 serialized := elliptic.Marshal(ka.curve, mx, my) 246 247 ckx := new(clientKeyExchangeMsg) 248 ckx.ciphertext = make([]byte, 1+len(serialized)) 249 ckx.ciphertext[0] = byte(len(serialized)) 250 copy(ckx.ciphertext[1:], serialized) 251 252 return preMasterSecret, ckx, nil 253 }