github.com/pion/dtls/v2@v2.2.12/crypto.go (about)

     1  // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
     2  // SPDX-License-Identifier: MIT
     3  
     4  package dtls
     5  
     6  import (
     7  	"crypto"
     8  	"crypto/ecdsa"
     9  	"crypto/ed25519"
    10  	"crypto/rand"
    11  	"crypto/rsa"
    12  	"crypto/sha256"
    13  	"crypto/x509"
    14  	"encoding/asn1"
    15  	"encoding/binary"
    16  	"math/big"
    17  	"time"
    18  
    19  	"github.com/pion/dtls/v2/pkg/crypto/elliptic"
    20  	"github.com/pion/dtls/v2/pkg/crypto/hash"
    21  )
    22  
    23  type ecdsaSignature struct {
    24  	R, S *big.Int
    25  }
    26  
    27  func valueKeyMessage(clientRandom, serverRandom, publicKey []byte, namedCurve elliptic.Curve) []byte {
    28  	serverECDHParams := make([]byte, 4)
    29  	serverECDHParams[0] = 3 // named curve
    30  	binary.BigEndian.PutUint16(serverECDHParams[1:], uint16(namedCurve))
    31  	serverECDHParams[3] = byte(len(publicKey))
    32  
    33  	plaintext := []byte{}
    34  	plaintext = append(plaintext, clientRandom...)
    35  	plaintext = append(plaintext, serverRandom...)
    36  	plaintext = append(plaintext, serverECDHParams...)
    37  	plaintext = append(plaintext, publicKey...)
    38  
    39  	return plaintext
    40  }
    41  
    42  // If the client provided a "signature_algorithms" extension, then all
    43  // certificates provided by the server MUST be signed by a
    44  // hash/signature algorithm pair that appears in that extension
    45  //
    46  // https://tools.ietf.org/html/rfc5246#section-7.4.2
    47  func generateKeySignature(clientRandom, serverRandom, publicKey []byte, namedCurve elliptic.Curve, privateKey crypto.PrivateKey, hashAlgorithm hash.Algorithm) ([]byte, error) {
    48  	msg := valueKeyMessage(clientRandom, serverRandom, publicKey, namedCurve)
    49  	switch p := privateKey.(type) {
    50  	case ed25519.PrivateKey:
    51  		// https://crypto.stackexchange.com/a/55483
    52  		return p.Sign(rand.Reader, msg, crypto.Hash(0))
    53  	case *ecdsa.PrivateKey:
    54  		hashed := hashAlgorithm.Digest(msg)
    55  		return p.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash())
    56  	case *rsa.PrivateKey:
    57  		hashed := hashAlgorithm.Digest(msg)
    58  		return p.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash())
    59  	}
    60  
    61  	return nil, errKeySignatureGenerateUnimplemented
    62  }
    63  
    64  func verifyKeySignature(message, remoteKeySignature []byte, hashAlgorithm hash.Algorithm, rawCertificates [][]byte) error { //nolint:dupl
    65  	if len(rawCertificates) == 0 {
    66  		return errLengthMismatch
    67  	}
    68  	certificate, err := x509.ParseCertificate(rawCertificates[0])
    69  	if err != nil {
    70  		return err
    71  	}
    72  
    73  	switch p := certificate.PublicKey.(type) {
    74  	case ed25519.PublicKey:
    75  		if ok := ed25519.Verify(p, message, remoteKeySignature); !ok {
    76  			return errKeySignatureMismatch
    77  		}
    78  		return nil
    79  	case *ecdsa.PublicKey:
    80  		ecdsaSig := &ecdsaSignature{}
    81  		if _, err := asn1.Unmarshal(remoteKeySignature, ecdsaSig); err != nil {
    82  			return err
    83  		}
    84  		if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
    85  			return errInvalidECDSASignature
    86  		}
    87  		hashed := hashAlgorithm.Digest(message)
    88  		if !ecdsa.Verify(p, hashed, ecdsaSig.R, ecdsaSig.S) {
    89  			return errKeySignatureMismatch
    90  		}
    91  		return nil
    92  	case *rsa.PublicKey:
    93  		switch certificate.SignatureAlgorithm {
    94  		case x509.SHA1WithRSA, x509.SHA256WithRSA, x509.SHA384WithRSA, x509.SHA512WithRSA:
    95  			hashed := hashAlgorithm.Digest(message)
    96  			return rsa.VerifyPKCS1v15(p, hashAlgorithm.CryptoHash(), hashed, remoteKeySignature)
    97  		default:
    98  			return errKeySignatureVerifyUnimplemented
    99  		}
   100  	}
   101  
   102  	return errKeySignatureVerifyUnimplemented
   103  }
   104  
   105  // If the server has sent a CertificateRequest message, the client MUST send the Certificate
   106  // message.  The ClientKeyExchange message is now sent, and the content
   107  // of that message will depend on the public key algorithm selected
   108  // between the ClientHello and the ServerHello.  If the client has sent
   109  // a certificate with signing ability, a digitally-signed
   110  // CertificateVerify message is sent to explicitly verify possession of
   111  // the private key in the certificate.
   112  // https://tools.ietf.org/html/rfc5246#section-7.3
   113  func generateCertificateVerify(handshakeBodies []byte, privateKey crypto.PrivateKey, hashAlgorithm hash.Algorithm) ([]byte, error) {
   114  	if p, ok := privateKey.(ed25519.PrivateKey); ok {
   115  		// https://pkg.go.dev/crypto/ed25519#PrivateKey.Sign
   116  		// Sign signs the given message with priv. Ed25519 performs two passes over
   117  		// messages to be signed and therefore cannot handle pre-hashed messages.
   118  		return p.Sign(rand.Reader, handshakeBodies, crypto.Hash(0))
   119  	}
   120  
   121  	h := sha256.New()
   122  	if _, err := h.Write(handshakeBodies); err != nil {
   123  		return nil, err
   124  	}
   125  	hashed := h.Sum(nil)
   126  
   127  	switch p := privateKey.(type) {
   128  	case *ecdsa.PrivateKey:
   129  		return p.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash())
   130  	case *rsa.PrivateKey:
   131  		return p.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash())
   132  	}
   133  
   134  	return nil, errInvalidSignatureAlgorithm
   135  }
   136  
   137  func verifyCertificateVerify(handshakeBodies []byte, hashAlgorithm hash.Algorithm, remoteKeySignature []byte, rawCertificates [][]byte) error { //nolint:dupl
   138  	if len(rawCertificates) == 0 {
   139  		return errLengthMismatch
   140  	}
   141  	certificate, err := x509.ParseCertificate(rawCertificates[0])
   142  	if err != nil {
   143  		return err
   144  	}
   145  
   146  	switch p := certificate.PublicKey.(type) {
   147  	case ed25519.PublicKey:
   148  		if ok := ed25519.Verify(p, handshakeBodies, remoteKeySignature); !ok {
   149  			return errKeySignatureMismatch
   150  		}
   151  		return nil
   152  	case *ecdsa.PublicKey:
   153  		ecdsaSig := &ecdsaSignature{}
   154  		if _, err := asn1.Unmarshal(remoteKeySignature, ecdsaSig); err != nil {
   155  			return err
   156  		}
   157  		if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
   158  			return errInvalidECDSASignature
   159  		}
   160  		hash := hashAlgorithm.Digest(handshakeBodies)
   161  		if !ecdsa.Verify(p, hash, ecdsaSig.R, ecdsaSig.S) {
   162  			return errKeySignatureMismatch
   163  		}
   164  		return nil
   165  	case *rsa.PublicKey:
   166  		switch certificate.SignatureAlgorithm {
   167  		case x509.SHA1WithRSA, x509.SHA256WithRSA, x509.SHA384WithRSA, x509.SHA512WithRSA:
   168  			hash := hashAlgorithm.Digest(handshakeBodies)
   169  			return rsa.VerifyPKCS1v15(p, hashAlgorithm.CryptoHash(), hash, remoteKeySignature)
   170  		default:
   171  			return errKeySignatureVerifyUnimplemented
   172  		}
   173  	}
   174  
   175  	return errKeySignatureVerifyUnimplemented
   176  }
   177  
   178  func loadCerts(rawCertificates [][]byte) ([]*x509.Certificate, error) {
   179  	if len(rawCertificates) == 0 {
   180  		return nil, errLengthMismatch
   181  	}
   182  
   183  	certs := make([]*x509.Certificate, 0, len(rawCertificates))
   184  	for _, rawCert := range rawCertificates {
   185  		cert, err := x509.ParseCertificate(rawCert)
   186  		if err != nil {
   187  			return nil, err
   188  		}
   189  		certs = append(certs, cert)
   190  	}
   191  	return certs, nil
   192  }
   193  
   194  func verifyClientCert(rawCertificates [][]byte, roots *x509.CertPool) (chains [][]*x509.Certificate, err error) {
   195  	certificate, err := loadCerts(rawCertificates)
   196  	if err != nil {
   197  		return nil, err
   198  	}
   199  	intermediateCAPool := x509.NewCertPool()
   200  	for _, cert := range certificate[1:] {
   201  		intermediateCAPool.AddCert(cert)
   202  	}
   203  	opts := x509.VerifyOptions{
   204  		Roots:         roots,
   205  		CurrentTime:   time.Now(),
   206  		Intermediates: intermediateCAPool,
   207  		KeyUsages:     []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
   208  	}
   209  	return certificate[0].Verify(opts)
   210  }
   211  
   212  func verifyServerCert(rawCertificates [][]byte, roots *x509.CertPool, serverName string) (chains [][]*x509.Certificate, err error) {
   213  	certificate, err := loadCerts(rawCertificates)
   214  	if err != nil {
   215  		return nil, err
   216  	}
   217  	intermediateCAPool := x509.NewCertPool()
   218  	for _, cert := range certificate[1:] {
   219  		intermediateCAPool.AddCert(cert)
   220  	}
   221  	opts := x509.VerifyOptions{
   222  		Roots:         roots,
   223  		CurrentTime:   time.Now(),
   224  		DNSName:       serverName,
   225  		Intermediates: intermediateCAPool,
   226  	}
   227  	return certificate[0].Verify(opts)
   228  }