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 }