github.com/Psiphon-Labs/tls-tris@v0.0.0-20230824155421-58bf6d336a9a/auth.go (about) 1 // Copyright 2017 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/ecdsa" 10 "crypto/rsa" 11 "encoding/asn1" 12 "errors" 13 "fmt" 14 ) 15 16 // pickSignatureAlgorithm selects a signature algorithm that is compatible with 17 // the given public key and the list of algorithms from the peer and this side. 18 // 19 // The returned SignatureScheme codepoint is only meaningful for TLS 1.2, 20 // previous TLS versions have a fixed hash function. 21 func pickSignatureAlgorithm(pubkey crypto.PublicKey, peerSigAlgs, ourSigAlgs []SignatureScheme, tlsVersion uint16) (SignatureScheme, uint8, crypto.Hash, error) { 22 if tlsVersion < VersionTLS12 || len(peerSigAlgs) == 0 { 23 // If the client didn't specify any signature_algorithms 24 // extension then we can assume that it supports SHA1. See 25 // http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 26 switch pubkey.(type) { 27 case *rsa.PublicKey: 28 if tlsVersion < VersionTLS12 { 29 return 0, signaturePKCS1v15, crypto.MD5SHA1, nil 30 } else { 31 return PKCS1WithSHA1, signaturePKCS1v15, crypto.SHA1, nil 32 } 33 case *ecdsa.PublicKey: 34 return ECDSAWithSHA1, signatureECDSA, crypto.SHA1, nil 35 default: 36 return 0, 0, 0, fmt.Errorf("tls: unsupported public key: %T", pubkey) 37 } 38 } 39 for _, sigAlg := range peerSigAlgs { 40 if !isSupportedSignatureAlgorithm(sigAlg, ourSigAlgs) { 41 continue 42 } 43 hashAlg, err := lookupTLSHash(sigAlg) 44 if err != nil { 45 panic("tls: supported signature algorithm has an unknown hash function") 46 } 47 sigType := signatureFromSignatureScheme(sigAlg) 48 if (sigType == signaturePKCS1v15 || hashAlg == crypto.SHA1) && tlsVersion >= VersionTLS13 { 49 // TLS 1.3 forbids RSASSA-PKCS1-v1_5 and SHA-1 for 50 // handshake messages. 51 continue 52 } 53 switch pubkey.(type) { 54 case *rsa.PublicKey: 55 if sigType == signaturePKCS1v15 || sigType == signatureRSAPSS { 56 return sigAlg, sigType, hashAlg, nil 57 } 58 case *ecdsa.PublicKey: 59 if sigType == signatureECDSA { 60 return sigAlg, sigType, hashAlg, nil 61 } 62 } 63 } 64 return 0, 0, 0, errors.New("tls: peer doesn't support any common signature algorithms") 65 } 66 67 // verifyHandshakeSignature verifies a signature against pre-hashed handshake 68 // contents. 69 func verifyHandshakeSignature(sigType uint8, pubkey crypto.PublicKey, hashFunc crypto.Hash, digest, sig []byte) error { 70 switch sigType { 71 case signatureECDSA: 72 pubKey, ok := pubkey.(*ecdsa.PublicKey) 73 if !ok { 74 return errors.New("tls: ECDSA signing requires a ECDSA public key") 75 } 76 ecdsaSig := new(ecdsaSignature) 77 if _, err := asn1.Unmarshal(sig, ecdsaSig); err != nil { 78 return err 79 } 80 if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 { 81 return errors.New("tls: ECDSA signature contained zero or negative values") 82 } 83 if !ecdsa.Verify(pubKey, digest, ecdsaSig.R, ecdsaSig.S) { 84 return errors.New("tls: ECDSA verification failure") 85 } 86 case signaturePKCS1v15: 87 pubKey, ok := pubkey.(*rsa.PublicKey) 88 if !ok { 89 return errors.New("tls: RSA signing requires a RSA public key") 90 } 91 if err := rsa.VerifyPKCS1v15(pubKey, hashFunc, digest, sig); err != nil { 92 return err 93 } 94 case signatureRSAPSS: 95 pubKey, ok := pubkey.(*rsa.PublicKey) 96 if !ok { 97 return errors.New("tls: RSA signing requires a RSA public key") 98 } 99 signOpts := &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash} 100 if err := rsa.VerifyPSS(pubKey, hashFunc, digest, sig, signOpts); err != nil { 101 return err 102 } 103 default: 104 return errors.New("tls: unknown signature algorithm") 105 } 106 return nil 107 }