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  }