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  }