| 1 |
747 |
jeremybenn |
// 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, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
|
| 24 |
|
|
return nil, nil
|
| 25 |
|
|
}
|
| 26 |
|
|
|
| 27 |
|
|
func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, 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(), config.Certificates[0].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, 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 |
|
|
var x, y *big.Int
|
| 134 |
|
|
var err error
|
| 135 |
|
|
ka.privateKey, x, y, err = elliptic.GenerateKey(ka.curve, config.rand())
|
| 136 |
|
|
if err != nil {
|
| 137 |
|
|
return nil, err
|
| 138 |
|
|
}
|
| 139 |
|
|
ecdhePublic := elliptic.Marshal(ka.curve, x, y)
|
| 140 |
|
|
|
| 141 |
|
|
// http://tools.ietf.org/html/rfc4492#section-5.4
|
| 142 |
|
|
serverECDHParams := make([]byte, 1+2+1+len(ecdhePublic))
|
| 143 |
|
|
serverECDHParams[0] = 3 // named curve
|
| 144 |
|
|
serverECDHParams[1] = byte(curveid >> 8)
|
| 145 |
|
|
serverECDHParams[2] = byte(curveid)
|
| 146 |
|
|
serverECDHParams[3] = byte(len(ecdhePublic))
|
| 147 |
|
|
copy(serverECDHParams[4:], ecdhePublic)
|
| 148 |
|
|
|
| 149 |
|
|
md5sha1 := md5SHA1Hash(clientHello.random, hello.random, serverECDHParams)
|
| 150 |
|
|
sig, err := rsa.SignPKCS1v15(config.rand(), config.Certificates[0].PrivateKey.(*rsa.PrivateKey), crypto.MD5SHA1, md5sha1)
|
| 151 |
|
|
if err != nil {
|
| 152 |
|
|
return nil, errors.New("failed to sign ECDHE parameters: " + err.Error())
|
| 153 |
|
|
}
|
| 154 |
|
|
|
| 155 |
|
|
skx := new(serverKeyExchangeMsg)
|
| 156 |
|
|
skx.key = make([]byte, len(serverECDHParams)+2+len(sig))
|
| 157 |
|
|
copy(skx.key, serverECDHParams)
|
| 158 |
|
|
k := skx.key[len(serverECDHParams):]
|
| 159 |
|
|
k[0] = byte(len(sig) >> 8)
|
| 160 |
|
|
k[1] = byte(len(sig))
|
| 161 |
|
|
copy(k[2:], sig)
|
| 162 |
|
|
|
| 163 |
|
|
return skx, nil
|
| 164 |
|
|
}
|
| 165 |
|
|
|
| 166 |
|
|
func (ka *ecdheRSAKeyAgreement) processClientKeyExchange(config *Config, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
|
| 167 |
|
|
if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 {
|
| 168 |
|
|
return nil, errors.New("bad ClientKeyExchange")
|
| 169 |
|
|
}
|
| 170 |
|
|
x, y := elliptic.Unmarshal(ka.curve, ckx.ciphertext[1:])
|
| 171 |
|
|
if x == nil {
|
| 172 |
|
|
return nil, errors.New("bad ClientKeyExchange")
|
| 173 |
|
|
}
|
| 174 |
|
|
x, _ = ka.curve.ScalarMult(x, y, ka.privateKey)
|
| 175 |
|
|
preMasterSecret := make([]byte, (ka.curve.Params().BitSize+7)>>3)
|
| 176 |
|
|
xBytes := x.Bytes()
|
| 177 |
|
|
copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
|
| 178 |
|
|
|
| 179 |
|
|
return preMasterSecret, nil
|
| 180 |
|
|
}
|
| 181 |
|
|
|
| 182 |
|
|
var errServerKeyExchange = errors.New("invalid ServerKeyExchange")
|
| 183 |
|
|
|
| 184 |
|
|
func (ka *ecdheRSAKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
|
| 185 |
|
|
if len(skx.key) < 4 {
|
| 186 |
|
|
return errServerKeyExchange
|
| 187 |
|
|
}
|
| 188 |
|
|
if skx.key[0] != 3 { // named curve
|
| 189 |
|
|
return errors.New("server selected unsupported curve")
|
| 190 |
|
|
}
|
| 191 |
|
|
curveid := uint16(skx.key[1])<<8 | uint16(skx.key[2])
|
| 192 |
|
|
|
| 193 |
|
|
switch curveid {
|
| 194 |
|
|
case curveP256:
|
| 195 |
|
|
ka.curve = elliptic.P256()
|
| 196 |
|
|
case curveP384:
|
| 197 |
|
|
ka.curve = elliptic.P384()
|
| 198 |
|
|
case curveP521:
|
| 199 |
|
|
ka.curve = elliptic.P521()
|
| 200 |
|
|
default:
|
| 201 |
|
|
return errors.New("server selected unsupported curve")
|
| 202 |
|
|
}
|
| 203 |
|
|
|
| 204 |
|
|
publicLen := int(skx.key[3])
|
| 205 |
|
|
if publicLen+4 > len(skx.key) {
|
| 206 |
|
|
return errServerKeyExchange
|
| 207 |
|
|
}
|
| 208 |
|
|
ka.x, ka.y = elliptic.Unmarshal(ka.curve, skx.key[4:4+publicLen])
|
| 209 |
|
|
if ka.x == nil {
|
| 210 |
|
|
return errServerKeyExchange
|
| 211 |
|
|
}
|
| 212 |
|
|
serverECDHParams := skx.key[:4+publicLen]
|
| 213 |
|
|
|
| 214 |
|
|
sig := skx.key[4+publicLen:]
|
| 215 |
|
|
if len(sig) < 2 {
|
| 216 |
|
|
return errServerKeyExchange
|
| 217 |
|
|
}
|
| 218 |
|
|
sigLen := int(sig[0])<<8 | int(sig[1])
|
| 219 |
|
|
if sigLen+2 != len(sig) {
|
| 220 |
|
|
return errServerKeyExchange
|
| 221 |
|
|
}
|
| 222 |
|
|
sig = sig[2:]
|
| 223 |
|
|
|
| 224 |
|
|
md5sha1 := md5SHA1Hash(clientHello.random, serverHello.random, serverECDHParams)
|
| 225 |
|
|
return rsa.VerifyPKCS1v15(cert.PublicKey.(*rsa.PublicKey), crypto.MD5SHA1, md5sha1, sig)
|
| 226 |
|
|
}
|
| 227 |
|
|
|
| 228 |
|
|
func (ka *ecdheRSAKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
|
| 229 |
|
|
if ka.curve == nil {
|
| 230 |
|
|
return nil, nil, errors.New("missing ServerKeyExchange message")
|
| 231 |
|
|
}
|
| 232 |
|
|
priv, mx, my, err := elliptic.GenerateKey(ka.curve, config.rand())
|
| 233 |
|
|
if err != nil {
|
| 234 |
|
|
return nil, nil, err
|
| 235 |
|
|
}
|
| 236 |
|
|
x, _ := ka.curve.ScalarMult(ka.x, ka.y, priv)
|
| 237 |
|
|
preMasterSecret := make([]byte, (ka.curve.Params().BitSize+7)>>3)
|
| 238 |
|
|
xBytes := x.Bytes()
|
| 239 |
|
|
copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
|
| 240 |
|
|
|
| 241 |
|
|
serialized := elliptic.Marshal(ka.curve, mx, my)
|
| 242 |
|
|
|
| 243 |
|
|
ckx := new(clientKeyExchangeMsg)
|
| 244 |
|
|
ckx.ciphertext = make([]byte, 1+len(serialized))
|
| 245 |
|
|
ckx.ciphertext[0] = byte(len(serialized))
|
| 246 |
|
|
copy(ckx.ciphertext[1:], serialized)
|
| 247 |
|
|
|
| 248 |
|
|
return preMasterSecret, ckx, nil
|
| 249 |
|
|
}
|