gitee.com/lh-her-team/common@v1.5.1/crypto/tls/gm_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 "bytes" 9 "crypto" 10 "crypto/elliptic" 11 "encoding/asn1" 12 "errors" 13 "io" 14 "math/big" 15 16 "gitee.com/lh-her-team/common/crypto/x509" 17 "github.com/tjfoc/gmsm/sm2" 18 19 "golang.org/x/crypto/curve25519" 20 ) 21 22 // ecdheKeyAgreementGM implements a TLS key agreement where the server 23 // generates an ephemeral SM2 public/private key pair and signs it. The 24 // pre-master secret is then calculated using ECDH. 25 type ecdheKeyAgreementGM struct { 26 version uint16 27 privateKey []byte 28 curveid CurveID 29 // publicKey is used to store the peer's public value when X25519 is 30 // being used. 31 publicKey []byte 32 // x and y are used to store the peer's public value when one of the 33 // NIST curves is being used. 34 x, y *big.Int 35 } 36 37 func (ka *ecdheKeyAgreementGM) generateServerKeyExchange(config *Config, signCert, cipherCert *Certificate, 38 clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) { 39 panic("") 40 // preferredCurves := config.curvePreferences() 41 // 42 //NextCandidate: 43 // for _, candidate := range preferredCurves { 44 // for _, c := range clientHello.supportedCurves { 45 // if candidate == c { 46 // ka.curveid = c 47 // break NextCandidate 48 // } 49 // } 50 // } 51 // 52 // if ka.curveid == 0 { 53 // return nil, errors.New("tls: no supported elliptic curves offered") 54 // } 55 // 56 // var ecdhePublic []byte 57 // 58 // if ka.curveid == X25519 { 59 // var scalar, public [32]byte 60 // if _, err := io.ReadFull(config.rand(), scalar[:]); err != nil { 61 // return nil, err 62 // } 63 // 64 // curve25519.ScalarBaseMult(&public, &scalar) 65 // ka.privateKey = scalar[:] 66 // ecdhePublic = public[:] 67 // } else { 68 // curve, ok := curveForCurveID(ka.curveid) 69 // if !ok { 70 // return nil, errors.New("tls: preferredCurves includes unsupported curve") 71 // } 72 // 73 // var x, y *big.Int 74 // var err error 75 // ka.privateKey, x, y, err = elliptic.GenerateKey(curve, config.rand()) 76 // if err != nil { 77 // return nil, err 78 // } 79 // ecdhePublic = elliptic.Marshal(curve, x, y) 80 // } 81 // 82 // // https://tools.ietf.org/html/rfc4492#section-5.4 83 // serverECDHParams := make([]byte, 1+2+1+len(ecdhePublic)) 84 // serverECDHParams[0] = 3 // named curve 85 // serverECDHParams[1] = byte(ka.curveid >> 8) 86 // serverECDHParams[2] = byte(ka.curveid) 87 // serverECDHParams[3] = byte(len(ecdhePublic)) 88 // copy(serverECDHParams[4:], ecdhePublic) 89 // 90 // priv, ok := cert.PrivateKey.(crypto.Signer) 91 // if !ok { 92 // return nil, errors.New("tls: certificate private key does not implement crypto.Signer") 93 // } 94 // 95 // signatureAlgorithm, sigType, hashFunc, err := pickSignatureAlgorithm(priv.Public(), clientHello.supportedSignatureAlgorithms, supportedSignatureAlgorithms, ka.version) 96 // if err != nil { 97 // return nil, err 98 // } 99 // if (sigType == signaturePKCS1v15 || sigType == signatureRSAPSS) != ka.isRSA { 100 // return nil, errors.New("tls: certificate cannot be used with the selected cipher suite") 101 // } 102 // 103 // digest, err := hashForServerKeyExchange(sigType, hashFunc, ka.version, clientHello.random, hello.random, serverECDHParams) 104 // if err != nil { 105 // return nil, err 106 // } 107 // 108 // signOpts := crypto.SignerOpts(hashFunc) 109 // if sigType == signatureRSAPSS { 110 // signOpts = &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: hashFunc} 111 // } 112 // sig, err := priv.Sign(config.rand(), digest, signOpts) 113 // if err != nil { 114 // return nil, errors.New("tls: failed to sign ECDHE parameters: " + err.Error()) 115 // } 116 // 117 // skx := new(serverKeyExchangeMsg) 118 // sigAndHashLen := 0 119 // if ka.version >= VersionTLS12 { 120 // sigAndHashLen = 2 121 // } 122 // skx.key = make([]byte, len(serverECDHParams)+sigAndHashLen+2+len(sig)) 123 // copy(skx.key, serverECDHParams) 124 // k := skx.key[len(serverECDHParams):] 125 // if ka.version >= VersionTLS12 { 126 // k[0] = byte(signatureAlgorithm >> 8) 127 // k[1] = byte(signatureAlgorithm) 128 // k = k[2:] 129 // } 130 // k[0] = byte(len(sig) >> 8) 131 // k[1] = byte(len(sig)) 132 // copy(k[2:], sig) 133 // 134 // return skx, nil 135 } 136 137 func (ka *ecdheKeyAgreementGM) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) { 138 panic("") 139 // if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 { 140 // return nil, errClientKeyExchange 141 // } 142 // 143 // if ka.curveid == X25519 { 144 // if len(ckx.ciphertext) != 1+32 { 145 // return nil, errClientKeyExchange 146 // } 147 // 148 // var theirPublic, sharedKey, scalar [32]byte 149 // copy(theirPublic[:], ckx.ciphertext[1:]) 150 // copy(scalar[:], ka.privateKey) 151 // curve25519.ScalarMult(&sharedKey, &scalar, &theirPublic) 152 // return sharedKey[:], nil 153 // } 154 // 155 // curve, ok := curveForCurveID(ka.curveid) 156 // if !ok { 157 // panic("internal error") 158 // } 159 // x, y := elliptic.Unmarshal(curve, ckx.ciphertext[1:]) // Unmarshal also checks whether the given point is on the curve 160 // if x == nil { 161 // return nil, errClientKeyExchange 162 // } 163 // x, _ = curve.ScalarMult(x, y, ka.privateKey) 164 // preMasterSecret := make([]byte, (curve.Params().BitSize+7)>>3) 165 // xBytes := x.Bytes() 166 // copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes) 167 // 168 // return preMasterSecret, nil 169 } 170 171 func (ka *ecdheKeyAgreementGM) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error { 172 if len(skx.key) < 4 { 173 return errServerKeyExchange 174 } 175 if skx.key[0] != 3 { // named curve 176 return errors.New("tls: server selected unsupported curve") 177 } 178 ka.curveid = CurveID(skx.key[1])<<8 | CurveID(skx.key[2]) 179 180 publicLen := int(skx.key[3]) 181 if publicLen+4 > len(skx.key) { 182 return errServerKeyExchange 183 } 184 serverECDHParams := skx.key[:4+publicLen] 185 publicKey := serverECDHParams[4:] 186 sig := skx.key[4+publicLen:] 187 if len(sig) < 2 { 188 return errServerKeyExchange 189 } 190 //according to GMT0024, we don't care about 191 curve := sm2.P256Sm2() 192 ka.x, ka.y = elliptic.Unmarshal(curve, publicKey) // Unmarshal also checks whether the given point is on the curve 193 if ka.x == nil { 194 return errServerKeyExchange 195 } 196 sigType, hashFunc, err := typeAndHashFromSignatureScheme(SM2WithSM3) 197 if err != nil { 198 return err 199 } 200 sigLen := int(sig[0])<<8 | int(sig[1]) 201 if sigLen+2 != len(sig) { 202 return errServerKeyExchange 203 } 204 sig = sig[2:] 205 digest := hashForServerKeyExchange(sigType, hashFunc, ka.version, clientHello.random, serverHello.random, serverECDHParams) 206 if err != nil { 207 return err 208 } 209 return verifyHandshakeSignature(sigType, cert.PublicKey, hashFunc, digest, sig) 210 } 211 212 func (ka *ecdheKeyAgreementGM) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) { 213 if ka.curveid == 0 { 214 return nil, nil, errors.New("tls: missing ServerKeyExchange message") 215 } 216 var serialized, preMasterSecret []byte 217 if ka.curveid == X25519 { 218 var ourPublic, theirPublic, sharedKey, scalar [32]byte 219 if _, err := io.ReadFull(config.rand(), scalar[:]); err != nil { 220 return nil, nil, err 221 } 222 copy(theirPublic[:], ka.publicKey) 223 curve25519.ScalarBaseMult(&ourPublic, &scalar) 224 curve25519.ScalarMult(&sharedKey, &scalar, &theirPublic) 225 serialized = ourPublic[:] 226 preMasterSecret = sharedKey[:] 227 } else { 228 curve, ok := curveForCurveID(ka.curveid) 229 if !ok { 230 panic("internal error") 231 } 232 priv, mx, my, err := elliptic.GenerateKey(curve, config.rand()) 233 if err != nil { 234 return nil, nil, err 235 } 236 x, _ := curve.ScalarMult(ka.x, ka.y, priv) 237 preMasterSecret = make([]byte, (curve.Params().BitSize+7)>>3) 238 xBytes := x.Bytes() 239 copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes) 240 serialized = elliptic.Marshal(curve, mx, my) 241 } 242 ckx := new(clientKeyExchangeMsg) 243 ckx.ciphertext = make([]byte, 1+len(serialized)) 244 ckx.ciphertext[0] = byte(len(serialized)) 245 copy(ckx.ciphertext[1:], serialized) 246 return preMasterSecret, ckx, nil 247 } 248 249 // eccKeyAgreementGM implements a TLS key agreement where the server 250 // generates an ephemeral SM2 public/private key pair and signs it. The 251 // pre-master secret is then calculated using ECDH. 252 type eccKeyAgreementGM struct { 253 version uint16 254 privateKey []byte 255 curveid CurveID 256 257 // publicKey is used to store the peer's public value when X25519 is 258 // being used. 259 publicKey []byte 260 // x and y are used to store the peer's public value when one of the 261 // NIST curves is being used. 262 x, y *big.Int 263 264 //cert for encipher referred to GMT0024 265 encipherCert *x509.Certificate 266 } 267 268 func (ka *eccKeyAgreementGM) generateServerKeyExchange(config *Config, signCert, cipherCert *Certificate, 269 clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) { 270 // mod by syl only one cert 271 //digest := ka.hashForServerKeyExchange(clientHello.random, hello.random, cert.Certificate[1]) 272 digest := ka.hashForServerKeyExchange(clientHello.random, hello.random, cipherCert.Certificate[0]) 273 priv, ok := signCert.PrivateKey.(crypto.Signer) 274 if !ok { 275 return nil, errors.New("tls: certificate private key does not implement crypto.Signer") 276 } 277 sig, err := priv.Sign(config.rand(), digest, nil) 278 if err != nil { 279 return nil, err 280 } 281 len := len(sig) 282 ske := new(serverKeyExchangeMsg) 283 ske.key = make([]byte, len+2) 284 ske.key[0] = byte(len >> 8) 285 ske.key[1] = byte(len) 286 copy(ske.key[2:], sig) 287 return ske, nil 288 } 289 290 func (ka *eccKeyAgreementGM) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) { 291 if len(ckx.ciphertext) == 0 { 292 return nil, errClientKeyExchange 293 } 294 if int(ckx.ciphertext[0]<<8|ckx.ciphertext[1]) != len(ckx.ciphertext)-2 { 295 return nil, errClientKeyExchange 296 } 297 cipher := ckx.ciphertext[2:] 298 decrypter, ok := cert.PrivateKey.(crypto.Decrypter) 299 if !ok { 300 return nil, errors.New("tls: certificate private key does not implement crypto.Decrypter") 301 } 302 cipher, err := sm2.CipherUnmarshal(cipher) 303 if err != nil { 304 return nil, err 305 } 306 plain, err := decrypter.Decrypt(config.rand(), cipher, nil) 307 if err != nil { 308 return nil, err 309 } 310 if len(plain) != 48 { 311 return nil, errClientKeyExchange 312 } 313 //we do not examine the version here according to openssl practice 314 return plain, nil 315 } 316 317 func (ka *eccKeyAgreementGM) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error { 318 if len(skx.key) <= 2 { 319 return errServerKeyExchange 320 } 321 sigLen := int(skx.key[0]<<8 | skx.key[1]) 322 if sigLen+2 != len(skx.key) { 323 return errServerKeyExchange 324 } 325 sig := skx.key[2:] 326 //sig := skx.key[:] 327 digest := ka.hashForServerKeyExchange(clientHello.random, serverHello.random, ka.encipherCert.Raw) 328 //verify 329 pubKey, ok := cert.PublicKey.ToStandardKey().(*sm2.PublicKey) 330 if !ok { 331 return errors.New("tls: sm2 signing requires a sm2 public key") 332 } 333 ecdsaSig := new(ecdsaSignature) 334 rest, err := asn1.Unmarshal(sig, ecdsaSig) 335 if err != nil { 336 return err 337 } 338 if len(rest) != 0 { 339 return errors.New("tls:processServerKeyExchange: sm2 get signature failed") 340 } 341 if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 { 342 return errors.New("tls: processServerKeyExchange: sm2 signature contained zero or negative values") 343 } 344 sm2PubKey := sm2.PublicKey{ 345 Curve: pubKey.Curve, 346 X: pubKey.X, 347 Y: pubKey.Y, 348 } 349 if !sm2PubKey.Verify(digest, sig) { 350 return errors.New("tls: processServerKeyExchange: sm2 verification failure") 351 } 352 return nil 353 } 354 355 func (ka *eccKeyAgreementGM) hashForServerKeyExchange(slices ...[]byte) []byte { 356 buffer := new(bytes.Buffer) 357 for i, slice := range slices { 358 if i == 2 { 359 buffer.Write([]byte{byte(len(slice) >> 16), byte(len(slice) >> 8), byte(len(slice))}) 360 } 361 buffer.Write(slice) 362 } 363 return buffer.Bytes() 364 } 365 366 func (ka *eccKeyAgreementGM) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) { 367 preMasterSecret := make([]byte, 48) 368 preMasterSecret[0] = byte(clientHello.vers >> 8) 369 preMasterSecret[1] = byte(clientHello.vers) 370 _, err := io.ReadFull(config.rand(), preMasterSecret[2:]) 371 if err != nil { 372 return nil, nil, err 373 } 374 sm2PubKey := ka.encipherCert.PublicKey.ToStandardKey().(*sm2.PublicKey) 375 encrypted, err := sm2.Encrypt(sm2PubKey, preMasterSecret, config.rand(), sm2.C1C3C2) 376 if err != nil { 377 return nil, nil, err 378 } 379 // GMT0024 通信时密文采用 GMT009 ASN1方式组织 380 encrypted, err = sm2.CipherMarshal(encrypted) 381 if err != nil { 382 return nil, nil, err 383 } 384 ckx := new(clientKeyExchangeMsg) 385 ckx.ciphertext = make([]byte, len(encrypted)+2) 386 ckx.ciphertext[0] = byte(len(encrypted) >> 8) 387 ckx.ciphertext[1] = byte(len(encrypted)) 388 copy(ckx.ciphertext[2:], encrypted) 389 return preMasterSecret, ckx, nil 390 }