github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/gmtls/auth.go (about)

     1  // Copyright 2022 s1ren@github.com/hxx258456.
     2  
     3  /*
     4  gmtls是基于`golang/go`的`tls`包实现的国密改造版本。
     5  对应版权声明: thrid_licenses/github.com/golang/go/LICENSE
     6  */
     7  
     8  package gmtls
     9  
    10  /*
    11  gmtls/auth.go 补充了国密sm2相关处理
    12  */
    13  
    14  import (
    15  	"bytes"
    16  	"crypto"
    17  	"crypto/ecdsa"
    18  	"crypto/ed25519"
    19  	"crypto/elliptic"
    20  	"crypto/rsa"
    21  	"errors"
    22  	"fmt"
    23  	"hash"
    24  	"io"
    25  
    26  	"github.com/hxx258456/ccgo/sm2"
    27  	"github.com/hxx258456/ccgo/x509"
    28  )
    29  
    30  // 使用pubkey,根据sigType选择对应的签名算法对sig进行验签。
    31  //   - sigType : 签名算法
    32  //   - pubkey : 公钥
    33  //   - hashFunc : 散列算法
    34  //   - signed : 签名内容
    35  //   - sig : 签名
    36  //
    37  // 已补充国密SM2分支
    38  // verifyHandshakeSignature verifies a signature against pre-hashed
    39  // (if required) handshake contents.
    40  func verifyHandshakeSignature(sigType uint8, pubkey crypto.PublicKey, hashFunc x509.Hash, signed, sig []byte) error {
    41  	switch sigType {
    42  	// 补充sm2分支
    43  	case signatureSM2:
    44  		pubKey, ok := pubkey.(*sm2.PublicKey)
    45  		if !ok {
    46  			return fmt.Errorf("expected an SM2 public key, got %T", pubkey)
    47  		}
    48  		if !sm2.VerifyASN1(pubKey, signed, sig) {
    49  			return errors.New("SM2 verification failure")
    50  		}
    51  	case signatureECDSA:
    52  		pubKey, ok := pubkey.(*ecdsa.PublicKey)
    53  		if !ok {
    54  			return fmt.Errorf("expected an ECDSA public key, got %T", pubkey)
    55  		}
    56  		if !ecdsa.VerifyASN1(pubKey, signed, sig) {
    57  			return errors.New("ECDSA verification failure")
    58  		}
    59  	case signatureEd25519:
    60  		pubKey, ok := pubkey.(ed25519.PublicKey)
    61  		if !ok {
    62  			return fmt.Errorf("expected an Ed25519 public key, got %T", pubkey)
    63  		}
    64  		if !ed25519.Verify(pubKey, signed, sig) {
    65  			return errors.New("ed25519 verification failure")
    66  		}
    67  	case signaturePKCS1v15:
    68  		pubKey, ok := pubkey.(*rsa.PublicKey)
    69  		if !ok {
    70  			return fmt.Errorf("expected an RSA public key, got %T", pubkey)
    71  		}
    72  		if err := rsa.VerifyPKCS1v15(pubKey, hashFunc.HashFunc(), signed, sig); err != nil {
    73  			return err
    74  		}
    75  	case signatureRSAPSS:
    76  		pubKey, ok := pubkey.(*rsa.PublicKey)
    77  		if !ok {
    78  			return fmt.Errorf("expected an RSA public key, got %T", pubkey)
    79  		}
    80  		signOpts := &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash}
    81  		if err := rsa.VerifyPSS(pubKey, hashFunc.HashFunc(), signed, sig, signOpts); err != nil {
    82  			return err
    83  		}
    84  	default:
    85  		return errors.New("internal error: unknown signature type")
    86  	}
    87  	return nil
    88  }
    89  
    90  const (
    91  	serverSignatureContext = "TLS 1.3, server CertificateVerify\x00"
    92  	clientSignatureContext = "TLS 1.3, client CertificateVerify\x00"
    93  )
    94  
    95  var signaturePadding = []byte{
    96  	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    97  	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    98  	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    99  	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
   100  	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
   101  	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
   102  	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
   103  	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
   104  }
   105  
   106  // 生成一个前置的消息散列,用于证书公私钥的签名与验签。
   107  // signedMessage returns the pre-hashed (if necessary) message to be signed by
   108  // certificate keys in TLS 1.3. See RFC 8446, Section 4.4.3.
   109  func signedMessage(sigHash x509.Hash, context string, transcript hash.Hash) []byte {
   110  	// directSigning 表示不做签名内容的前置散列
   111  	if sigHash == directSigning {
   112  		b := &bytes.Buffer{}
   113  		b.Write(signaturePadding)
   114  		_, err := io.WriteString(b, context)
   115  		if err != nil {
   116  			panic(err)
   117  		}
   118  		b.Write(transcript.Sum(nil))
   119  		return b.Bytes()
   120  	}
   121  	h := sigHash.New()
   122  	h.Write(signaturePadding)
   123  	_, err := io.WriteString(h, context)
   124  	if err != nil {
   125  		panic(err)
   126  	}
   127  	h.Write(transcript.Sum(nil))
   128  	return h.Sum(nil)
   129  }
   130  
   131  // 获取签名算法与散列算法
   132  //
   133  //	已补充国密SM2签名算法分支
   134  //
   135  // typeAndHashFromSignatureScheme returns the corresponding signature type and
   136  // crypto.Hash for a given TLS SignatureScheme.
   137  func typeAndHashFromSignatureScheme(signatureAlgorithm SignatureScheme) (sigType uint8, hash x509.Hash, err error) {
   138  	switch signatureAlgorithm {
   139  	// 补充国密SM2签名算法
   140  	case SM2WITHSM3:
   141  		sigType = signatureSM2
   142  	case PKCS1WithSHA1, PKCS1WithSHA256, PKCS1WithSHA384, PKCS1WithSHA512:
   143  		sigType = signaturePKCS1v15
   144  	case PSSWithSHA256, PSSWithSHA384, PSSWithSHA512:
   145  		sigType = signatureRSAPSS
   146  	case ECDSAWithSHA1, ECDSAWithP256AndSHA256, ECDSAWithP384AndSHA384, ECDSAWithP521AndSHA512:
   147  		sigType = signatureECDSA
   148  	case Ed25519:
   149  		sigType = signatureEd25519
   150  	default:
   151  		return 0, 0, fmt.Errorf("unsupported signature algorithm: %v", signatureAlgorithm)
   152  	}
   153  	switch signatureAlgorithm {
   154  	// 补充国密SM3散列算法
   155  	case SM2WITHSM3:
   156  		hash = x509.SM3
   157  	case PKCS1WithSHA1, ECDSAWithSHA1:
   158  		hash = x509.SHA1
   159  	case PKCS1WithSHA256, PSSWithSHA256, ECDSAWithP256AndSHA256:
   160  		hash = x509.SHA256
   161  	case PKCS1WithSHA384, PSSWithSHA384, ECDSAWithP384AndSHA384:
   162  		hash = x509.SHA384
   163  	case PKCS1WithSHA512, PSSWithSHA512, ECDSAWithP521AndSHA512:
   164  		hash = x509.SHA512
   165  	case Ed25519:
   166  		hash = directSigning
   167  	default:
   168  		return 0, 0, fmt.Errorf("unsupported signature algorithm: %v", signatureAlgorithm)
   169  	}
   170  	return sigType, hash, nil
   171  }
   172  
   173  // 已补充国密SM2分支
   174  // legacyTypeAndHashFromPublicKey returns the fixed signature type and crypto.Hash for
   175  // a given public key used with TLS 1.0 and 1.1, before the introduction of
   176  // signature algorithm negotiation.
   177  func legacyTypeAndHashFromPublicKey(pub crypto.PublicKey) (sigType uint8, hash x509.Hash, err error) {
   178  	switch pub.(type) {
   179  	// 补充sm2分支
   180  	case *sm2.PublicKey:
   181  		return signatureSM2, x509.SM3, nil
   182  	case *rsa.PublicKey:
   183  		return signaturePKCS1v15, x509.MD5SHA1, nil
   184  	case *ecdsa.PublicKey:
   185  		return signatureECDSA, x509.SHA1, nil
   186  	case ed25519.PublicKey:
   187  		// RFC 8422 specifies support for Ed25519 in TLS 1.0 and 1.1,
   188  		// but it requires holding on to a handshake transcript to do a
   189  		// full signature, and not even OpenSSL bothers with the
   190  		// complexity, so we can't even test it properly.
   191  		return 0, 0, fmt.Errorf("gmtls: Ed25519 public keys are not supported before TLS 1.2")
   192  	default:
   193  		return 0, 0, fmt.Errorf("gmtls: unsupported public key: %T", pub)
   194  	}
   195  }
   196  
   197  var rsaSignatureSchemes = []struct {
   198  	scheme          SignatureScheme
   199  	minModulusBytes int
   200  	maxVersion      uint16
   201  }{
   202  	// RSA-PSS is used with PSSSaltLengthEqualsHash, and requires
   203  	//    emLen >= hLen + sLen + 2
   204  	{PSSWithSHA256, crypto.SHA256.Size()*2 + 2, VersionTLS13},
   205  	{PSSWithSHA384, crypto.SHA384.Size()*2 + 2, VersionTLS13},
   206  	{PSSWithSHA512, crypto.SHA512.Size()*2 + 2, VersionTLS13},
   207  	// PKCS #1 v1.5 uses prefixes from hashPrefixes in crypto/rsa, and requires
   208  	//    emLen >= len(prefix) + hLen + 11
   209  	// TLS 1.3 dropped support for PKCS #1 v1.5 in favor of RSA-PSS.
   210  	{PKCS1WithSHA256, 19 + crypto.SHA256.Size() + 11, VersionTLS12},
   211  	{PKCS1WithSHA384, 19 + crypto.SHA384.Size() + 11, VersionTLS12},
   212  	{PKCS1WithSHA512, 19 + crypto.SHA512.Size() + 11, VersionTLS12},
   213  	{PKCS1WithSHA1, 15 + crypto.SHA1.Size() + 11, VersionTLS12},
   214  }
   215  
   216  // 已补充国密SM2分支
   217  // signatureSchemesForCertificate returns the list of supported SignatureSchemes
   218  // for a given certificate, based on the public key and the protocol version,
   219  // and optionally filtered by its explicit SupportedSignatureAlgorithms.
   220  //
   221  // This function must be kept in sync with supportedSignatureAlgorithms.
   222  func signatureSchemesForCertificate(version uint16, cert *Certificate) []SignatureScheme {
   223  	priv, ok := cert.PrivateKey.(crypto.Signer)
   224  	if !ok {
   225  		return nil
   226  	}
   227  	var sigAlgs []SignatureScheme
   228  	switch pub := priv.Public().(type) {
   229  	// 补充国密sm2分支
   230  	case *sm2.PublicKey:
   231  		sigAlgs = []SignatureScheme{SM2WITHSM3}
   232  	case *ecdsa.PublicKey:
   233  		if version != VersionTLS13 {
   234  			// In TLS 1.2 and earlier, ECDSA algorithms are not
   235  			// constrained to a single curve.
   236  			sigAlgs = []SignatureScheme{
   237  				ECDSAWithP256AndSHA256,
   238  				ECDSAWithP384AndSHA384,
   239  				ECDSAWithP521AndSHA512,
   240  				ECDSAWithSHA1,
   241  			}
   242  			break
   243  		}
   244  		switch pub.Curve {
   245  		case elliptic.P256():
   246  			sigAlgs = []SignatureScheme{ECDSAWithP256AndSHA256}
   247  		case elliptic.P384():
   248  			sigAlgs = []SignatureScheme{ECDSAWithP384AndSHA384}
   249  		case elliptic.P521():
   250  			sigAlgs = []SignatureScheme{ECDSAWithP521AndSHA512}
   251  		default:
   252  			return nil
   253  		}
   254  	case *rsa.PublicKey:
   255  		size := pub.Size()
   256  		sigAlgs = make([]SignatureScheme, 0, len(rsaSignatureSchemes))
   257  		for _, candidate := range rsaSignatureSchemes {
   258  			if size >= candidate.minModulusBytes && version <= candidate.maxVersion {
   259  				sigAlgs = append(sigAlgs, candidate.scheme)
   260  			}
   261  		}
   262  	case ed25519.PublicKey:
   263  		sigAlgs = []SignatureScheme{Ed25519}
   264  	default:
   265  		return nil
   266  	}
   267  	// 如果证书提供了支持签名算法信息,则检查是否与私钥对应的签名算法匹配,
   268  	// 并返回匹配的签名算法集合
   269  	if cert.SupportedSignatureAlgorithms != nil {
   270  		var filteredSigAlgs []SignatureScheme
   271  		for _, sigAlg := range sigAlgs {
   272  			if isSupportedSignatureAlgorithm(sigAlg, cert.SupportedSignatureAlgorithms) {
   273  				filteredSigAlgs = append(filteredSigAlgs, sigAlg)
   274  			}
   275  		}
   276  		return filteredSigAlgs
   277  	}
   278  	// 若证书没有提供支持签名算法信息,则直接返回私钥支持的签名算法集合
   279  	return sigAlgs
   280  }
   281  
   282  // selectSignatureScheme picks a SignatureScheme from the peer's preference list
   283  // that works with the selected certificate. It's only called for protocol
   284  // versions that support signature algorithms, so TLS 1.2 and 1.3.
   285  func selectSignatureScheme(vers uint16, c *Certificate, peerAlgs []SignatureScheme) (SignatureScheme, error) {
   286  	// 获取证书支持的签名算法
   287  	supportedAlgs := signatureSchemesForCertificate(vers, c)
   288  	if len(supportedAlgs) == 0 {
   289  		return 0, unsupportedCertificateError(c)
   290  	}
   291  	if len(peerAlgs) == 0 && vers == VersionTLS12 {
   292  		// For TLS 1.2, if the client didn't send signature_algorithms then we
   293  		// can assume that it supports SHA1. See RFC 5246, Section 7.4.1.4.1.
   294  		// 补充VersionTLS12下的国密签名算法组件
   295  		peerAlgs = []SignatureScheme{SM2WITHSM3, PKCS1WithSHA1, ECDSAWithSHA1}
   296  	}
   297  	// Pick signature scheme in the peer's preference order, as our
   298  	// preference order is not configurable.
   299  	for _, preferredAlg := range peerAlgs {
   300  		if isSupportedSignatureAlgorithm(preferredAlg, supportedAlgs) {
   301  			// 返回第一个匹配的签名算法
   302  			return preferredAlg, nil
   303  		}
   304  	}
   305  	return 0, errors.New("gmtls: peer doesn't support any of the certificate's signature algorithms")
   306  }
   307  
   308  // 已补充国密sm2对应
   309  // unsupportedCertificateError returns a helpful error for certificates with
   310  // an unsupported private key.
   311  func unsupportedCertificateError(cert *Certificate) error {
   312  	switch cert.PrivateKey.(type) {
   313  	// 补充sm2匹配条件
   314  	case rsa.PrivateKey, ecdsa.PrivateKey, sm2.PrivateKey:
   315  		return fmt.Errorf("gmtls: unsupported certificate: private key is %T, expected *%T",
   316  			cert.PrivateKey, cert.PrivateKey)
   317  	case *ed25519.PrivateKey:
   318  		return fmt.Errorf("gmtls: unsupported certificate: private key is *ed25519.PrivateKey, expected ed25519.PrivateKey")
   319  	}
   320  
   321  	signer, ok := cert.PrivateKey.(crypto.Signer)
   322  	if !ok {
   323  		return fmt.Errorf("gmtls: certificate private key (%T) does not implement crypto.Signer",
   324  			cert.PrivateKey)
   325  	}
   326  
   327  	switch pub := signer.Public().(type) {
   328  	// 补充sm2分支
   329  	case *sm2.PublicKey:
   330  		switch pub.Curve {
   331  		case sm2.P256Sm2():
   332  		default:
   333  			return fmt.Errorf("gmtls: unsupported certificate curve (%s)", pub.Curve.Params().Name)
   334  		}
   335  	case *ecdsa.PublicKey:
   336  		switch pub.Curve {
   337  		case elliptic.P256():
   338  		case elliptic.P384():
   339  		case elliptic.P521():
   340  		default:
   341  			return fmt.Errorf("gmtls: unsupported certificate curve (%s)", pub.Curve.Params().Name)
   342  		}
   343  	case *rsa.PublicKey:
   344  		return fmt.Errorf("gmtls: certificate RSA key size too small for supported signature algorithms")
   345  	case ed25519.PublicKey:
   346  	default:
   347  		return fmt.Errorf("gmtls: unsupported certificate key (%T)", pub)
   348  	}
   349  
   350  	if cert.SupportedSignatureAlgorithms != nil {
   351  		return fmt.Errorf("gmtls: peer doesn't support the certificate custom signature algorithms")
   352  	}
   353  
   354  	return fmt.Errorf("gmtls: internal error: unsupported key (%T)", cert.PrivateKey)
   355  }