github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/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/ecdsa" 10 "crypto/elliptic" 11 "crypto/md5" 12 "crypto/rsa" 13 "crypto/sha1" 14 "crypto/sha256" 15 "crypto/x509" 16 "encoding/asn1" 17 "errors" 18 "io" 19 "math/big" 20 ) 21 22 // rsaKeyAgreement implements the standard TLS key agreement where the client 23 // encrypts the pre-master secret to the server's public key. 24 type rsaKeyAgreement struct{} 25 26 func (ka rsaKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) { 27 return nil, nil 28 } 29 30 func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) { 31 preMasterSecret := make([]byte, 48) 32 _, err := io.ReadFull(config.rand(), preMasterSecret[2:]) 33 if err != nil { 34 return nil, err 35 } 36 37 if len(ckx.ciphertext) < 2 { 38 return nil, errors.New("bad ClientKeyExchange") 39 } 40 41 ciphertext := ckx.ciphertext 42 if version != VersionSSL30 { 43 ciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1]) 44 if ciphertextLen != len(ckx.ciphertext)-2 { 45 return nil, errors.New("bad ClientKeyExchange") 46 } 47 ciphertext = ckx.ciphertext[2:] 48 } 49 50 err = rsa.DecryptPKCS1v15SessionKey(config.rand(), cert.PrivateKey.(*rsa.PrivateKey), ciphertext, preMasterSecret) 51 if err != nil { 52 return nil, err 53 } 54 // We don't check the version number in the premaster secret. For one, 55 // by checking it, we would leak information about the validity of the 56 // encrypted pre-master secret. Secondly, it provides only a small 57 // benefit against a downgrade attack and some implementations send the 58 // wrong version anyway. See the discussion at the end of section 59 // 7.4.7.1 of RFC 4346. 60 return preMasterSecret, nil 61 } 62 63 func (ka rsaKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error { 64 return errors.New("unexpected ServerKeyExchange") 65 } 66 67 func (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) { 68 preMasterSecret := make([]byte, 48) 69 preMasterSecret[0] = byte(clientHello.vers >> 8) 70 preMasterSecret[1] = byte(clientHello.vers) 71 _, err := io.ReadFull(config.rand(), preMasterSecret[2:]) 72 if err != nil { 73 return nil, nil, err 74 } 75 76 encrypted, err := rsa.EncryptPKCS1v15(config.rand(), cert.PublicKey.(*rsa.PublicKey), preMasterSecret) 77 if err != nil { 78 return nil, nil, err 79 } 80 ckx := new(clientKeyExchangeMsg) 81 ckx.ciphertext = make([]byte, len(encrypted)+2) 82 ckx.ciphertext[0] = byte(len(encrypted) >> 8) 83 ckx.ciphertext[1] = byte(len(encrypted)) 84 copy(ckx.ciphertext[2:], encrypted) 85 return preMasterSecret, ckx, nil 86 } 87 88 // sha1Hash calculates a SHA1 hash over the given byte slices. 89 func sha1Hash(slices [][]byte) []byte { 90 hsha1 := sha1.New() 91 for _, slice := range slices { 92 hsha1.Write(slice) 93 } 94 return hsha1.Sum(nil) 95 } 96 97 // md5SHA1Hash implements TLS 1.0's hybrid hash function which consists of the 98 // concatenation of an MD5 and SHA1 hash. 99 func md5SHA1Hash(slices [][]byte) []byte { 100 md5sha1 := make([]byte, md5.Size+sha1.Size) 101 hmd5 := md5.New() 102 for _, slice := range slices { 103 hmd5.Write(slice) 104 } 105 copy(md5sha1, hmd5.Sum(nil)) 106 copy(md5sha1[md5.Size:], sha1Hash(slices)) 107 return md5sha1 108 } 109 110 // sha256Hash implements TLS 1.2's hash function. 111 func sha256Hash(slices [][]byte) []byte { 112 h := sha256.New() 113 for _, slice := range slices { 114 h.Write(slice) 115 } 116 return h.Sum(nil) 117 } 118 119 // hashForServerKeyExchange hashes the given slices and returns their digest 120 // and the identifier of the hash function used. 121 func hashForServerKeyExchange(sigType uint8, version uint16, slices ...[]byte) ([]byte, crypto.Hash) { 122 if version >= VersionTLS12 { 123 return sha256Hash(slices), crypto.SHA256 124 } 125 if sigType == signatureECDSA { 126 return sha1Hash(slices), crypto.SHA1 127 } 128 return md5SHA1Hash(slices), crypto.MD5SHA1 129 } 130 131 // ecdheRSAKeyAgreement implements a TLS key agreement where the server 132 // generates a ephemeral EC public/private key pair and signs it. The 133 // pre-master secret is then calculated using ECDH. The signature may 134 // either be ECDSA or RSA. 135 type ecdheKeyAgreement struct { 136 version uint16 137 sigType uint8 138 privateKey []byte 139 curve elliptic.Curve 140 x, y *big.Int 141 } 142 143 func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) { 144 var curveid uint16 145 146 Curve: 147 for _, c := range clientHello.supportedCurves { 148 switch c { 149 case curveP256: 150 ka.curve = elliptic.P256() 151 curveid = c 152 break Curve 153 case curveP384: 154 ka.curve = elliptic.P384() 155 curveid = c 156 break Curve 157 case curveP521: 158 ka.curve = elliptic.P521() 159 curveid = c 160 break Curve 161 } 162 } 163 164 if curveid == 0 { 165 return nil, errors.New("tls: no supported elliptic curves offered") 166 } 167 168 var x, y *big.Int 169 var err error 170 ka.privateKey, x, y, err = elliptic.GenerateKey(ka.curve, config.rand()) 171 if err != nil { 172 return nil, err 173 } 174 ecdhePublic := elliptic.Marshal(ka.curve, x, y) 175 176 // http://tools.ietf.org/html/rfc4492#section-5.4 177 serverECDHParams := make([]byte, 1+2+1+len(ecdhePublic)) 178 serverECDHParams[0] = 3 // named curve 179 serverECDHParams[1] = byte(curveid >> 8) 180 serverECDHParams[2] = byte(curveid) 181 serverECDHParams[3] = byte(len(ecdhePublic)) 182 copy(serverECDHParams[4:], ecdhePublic) 183 184 digest, hashFunc := hashForServerKeyExchange(ka.sigType, ka.version, clientHello.random, hello.random, serverECDHParams) 185 var sig []byte 186 switch ka.sigType { 187 case signatureECDSA: 188 privKey, ok := cert.PrivateKey.(*ecdsa.PrivateKey) 189 if !ok { 190 return nil, errors.New("ECDHE ECDSA requires an ECDSA server private key") 191 } 192 r, s, err := ecdsa.Sign(config.rand(), privKey, digest) 193 if err != nil { 194 return nil, errors.New("failed to sign ECDHE parameters: " + err.Error()) 195 } 196 sig, err = asn1.Marshal(ecdsaSignature{r, s}) 197 case signatureRSA: 198 privKey, ok := cert.PrivateKey.(*rsa.PrivateKey) 199 if !ok { 200 return nil, errors.New("ECDHE RSA requires a RSA server private key") 201 } 202 sig, err = rsa.SignPKCS1v15(config.rand(), privKey, hashFunc, digest) 203 if err != nil { 204 return nil, errors.New("failed to sign ECDHE parameters: " + err.Error()) 205 } 206 default: 207 return nil, errors.New("unknown ECDHE signature algorithm") 208 } 209 210 skx := new(serverKeyExchangeMsg) 211 sigAndHashLen := 0 212 if ka.version >= VersionTLS12 { 213 sigAndHashLen = 2 214 } 215 skx.key = make([]byte, len(serverECDHParams)+sigAndHashLen+2+len(sig)) 216 copy(skx.key, serverECDHParams) 217 k := skx.key[len(serverECDHParams):] 218 if ka.version >= VersionTLS12 { 219 k[0] = hashSHA256 220 k[1] = ka.sigType 221 k = k[2:] 222 } 223 k[0] = byte(len(sig) >> 8) 224 k[1] = byte(len(sig)) 225 copy(k[2:], sig) 226 227 return skx, nil 228 } 229 230 func (ka *ecdheKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) { 231 if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 { 232 return nil, errors.New("bad ClientKeyExchange") 233 } 234 x, y := elliptic.Unmarshal(ka.curve, ckx.ciphertext[1:]) 235 if x == nil { 236 return nil, errors.New("bad ClientKeyExchange") 237 } 238 x, _ = ka.curve.ScalarMult(x, y, ka.privateKey) 239 preMasterSecret := make([]byte, (ka.curve.Params().BitSize+7)>>3) 240 xBytes := x.Bytes() 241 copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes) 242 243 return preMasterSecret, nil 244 } 245 246 var errServerKeyExchange = errors.New("invalid ServerKeyExchange") 247 248 func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error { 249 if len(skx.key) < 4 { 250 return errServerKeyExchange 251 } 252 if skx.key[0] != 3 { // named curve 253 return errors.New("server selected unsupported curve") 254 } 255 curveid := uint16(skx.key[1])<<8 | uint16(skx.key[2]) 256 257 switch curveid { 258 case curveP256: 259 ka.curve = elliptic.P256() 260 case curveP384: 261 ka.curve = elliptic.P384() 262 case curveP521: 263 ka.curve = elliptic.P521() 264 default: 265 return errors.New("server selected unsupported curve") 266 } 267 268 publicLen := int(skx.key[3]) 269 if publicLen+4 > len(skx.key) { 270 return errServerKeyExchange 271 } 272 ka.x, ka.y = elliptic.Unmarshal(ka.curve, skx.key[4:4+publicLen]) 273 if ka.x == nil { 274 return errServerKeyExchange 275 } 276 serverECDHParams := skx.key[:4+publicLen] 277 278 sig := skx.key[4+publicLen:] 279 if len(sig) < 2 { 280 return errServerKeyExchange 281 } 282 if ka.version >= VersionTLS12 { 283 // ignore SignatureAndHashAlgorithm 284 sig = sig[2:] 285 if len(sig) < 2 { 286 return errServerKeyExchange 287 } 288 } 289 sigLen := int(sig[0])<<8 | int(sig[1]) 290 if sigLen+2 != len(sig) { 291 return errServerKeyExchange 292 } 293 sig = sig[2:] 294 295 digest, hashFunc := hashForServerKeyExchange(ka.sigType, ka.version, clientHello.random, serverHello.random, serverECDHParams) 296 switch ka.sigType { 297 case signatureECDSA: 298 pubKey, ok := cert.PublicKey.(*ecdsa.PublicKey) 299 if !ok { 300 return errors.New("ECDHE ECDSA requires a ECDSA server public key") 301 } 302 ecdsaSig := new(ecdsaSignature) 303 if _, err := asn1.Unmarshal(sig, ecdsaSig); err != nil { 304 return err 305 } 306 if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 { 307 return errors.New("ECDSA signature contained zero or negative values") 308 } 309 if !ecdsa.Verify(pubKey, digest, ecdsaSig.R, ecdsaSig.S) { 310 return errors.New("ECDSA verification failure") 311 } 312 case signatureRSA: 313 pubKey, ok := cert.PublicKey.(*rsa.PublicKey) 314 if !ok { 315 return errors.New("ECDHE RSA requires a RSA server public key") 316 } 317 if err := rsa.VerifyPKCS1v15(pubKey, hashFunc, digest, sig); err != nil { 318 return err 319 } 320 default: 321 return errors.New("unknown ECDHE signature algorithm") 322 } 323 324 return nil 325 } 326 327 func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) { 328 if ka.curve == nil { 329 return nil, nil, errors.New("missing ServerKeyExchange message") 330 } 331 priv, mx, my, err := elliptic.GenerateKey(ka.curve, config.rand()) 332 if err != nil { 333 return nil, nil, err 334 } 335 x, _ := ka.curve.ScalarMult(ka.x, ka.y, priv) 336 preMasterSecret := make([]byte, (ka.curve.Params().BitSize+7)>>3) 337 xBytes := x.Bytes() 338 copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes) 339 340 serialized := elliptic.Marshal(ka.curve, mx, my) 341 342 ckx := new(clientKeyExchangeMsg) 343 ckx.ciphertext = make([]byte, 1+len(serialized)) 344 ckx.ciphertext[0] = byte(len(serialized)) 345 copy(ckx.ciphertext[1:], serialized) 346 347 return preMasterSecret, ckx, nil 348 }