github.com/pion/dtls/v2@v2.2.12/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_256_cbc_sha.go (about)

     1  // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
     2  // SPDX-License-Identifier: MIT
     3  
     4  package ciphersuite
     5  
     6  import (
     7  	"crypto/sha1" //nolint: gosec,gci
     8  	"crypto/sha256"
     9  	"fmt"
    10  	"hash"
    11  	"sync/atomic"
    12  
    13  	"github.com/pion/dtls/v2/pkg/crypto/ciphersuite"
    14  	"github.com/pion/dtls/v2/pkg/crypto/clientcertificate"
    15  	"github.com/pion/dtls/v2/pkg/crypto/prf"
    16  	"github.com/pion/dtls/v2/pkg/protocol/recordlayer"
    17  )
    18  
    19  // TLSEcdheEcdsaWithAes256CbcSha represents a TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA CipherSuite
    20  type TLSEcdheEcdsaWithAes256CbcSha struct {
    21  	cbc atomic.Value // *cryptoCBC
    22  }
    23  
    24  // CertificateType returns what type of certficate this CipherSuite exchanges
    25  func (c *TLSEcdheEcdsaWithAes256CbcSha) CertificateType() clientcertificate.Type {
    26  	return clientcertificate.ECDSASign
    27  }
    28  
    29  // KeyExchangeAlgorithm controls what key exchange algorithm is using during the handshake
    30  func (c *TLSEcdheEcdsaWithAes256CbcSha) KeyExchangeAlgorithm() KeyExchangeAlgorithm {
    31  	return KeyExchangeAlgorithmEcdhe
    32  }
    33  
    34  // ECC uses Elliptic Curve Cryptography
    35  func (c *TLSEcdheEcdsaWithAes256CbcSha) ECC() bool {
    36  	return true
    37  }
    38  
    39  // ID returns the ID of the CipherSuite
    40  func (c *TLSEcdheEcdsaWithAes256CbcSha) ID() ID {
    41  	return TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
    42  }
    43  
    44  func (c *TLSEcdheEcdsaWithAes256CbcSha) String() string {
    45  	return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"
    46  }
    47  
    48  // HashFunc returns the hashing func for this CipherSuite
    49  func (c *TLSEcdheEcdsaWithAes256CbcSha) HashFunc() func() hash.Hash {
    50  	return sha256.New
    51  }
    52  
    53  // AuthenticationType controls what authentication method is using during the handshake
    54  func (c *TLSEcdheEcdsaWithAes256CbcSha) AuthenticationType() AuthenticationType {
    55  	return AuthenticationTypeCertificate
    56  }
    57  
    58  // IsInitialized returns if the CipherSuite has keying material and can
    59  // encrypt/decrypt packets
    60  func (c *TLSEcdheEcdsaWithAes256CbcSha) IsInitialized() bool {
    61  	return c.cbc.Load() != nil
    62  }
    63  
    64  // Init initializes the internal Cipher with keying material
    65  func (c *TLSEcdheEcdsaWithAes256CbcSha) Init(masterSecret, clientRandom, serverRandom []byte, isClient bool) error {
    66  	const (
    67  		prfMacLen = 20
    68  		prfKeyLen = 32
    69  		prfIvLen  = 16
    70  	)
    71  
    72  	keys, err := prf.GenerateEncryptionKeys(masterSecret, clientRandom, serverRandom, prfMacLen, prfKeyLen, prfIvLen, c.HashFunc())
    73  	if err != nil {
    74  		return err
    75  	}
    76  
    77  	var cbc *ciphersuite.CBC
    78  	if isClient {
    79  		cbc, err = ciphersuite.NewCBC(
    80  			keys.ClientWriteKey, keys.ClientWriteIV, keys.ClientMACKey,
    81  			keys.ServerWriteKey, keys.ServerWriteIV, keys.ServerMACKey,
    82  			sha1.New,
    83  		)
    84  	} else {
    85  		cbc, err = ciphersuite.NewCBC(
    86  			keys.ServerWriteKey, keys.ServerWriteIV, keys.ServerMACKey,
    87  			keys.ClientWriteKey, keys.ClientWriteIV, keys.ClientMACKey,
    88  			sha1.New,
    89  		)
    90  	}
    91  	c.cbc.Store(cbc)
    92  
    93  	return err
    94  }
    95  
    96  // Encrypt encrypts a single TLS RecordLayer
    97  func (c *TLSEcdheEcdsaWithAes256CbcSha) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) {
    98  	cipherSuite, ok := c.cbc.Load().(*ciphersuite.CBC)
    99  	if !ok {
   100  		return nil, fmt.Errorf("%w, unable to encrypt", errCipherSuiteNotInit)
   101  	}
   102  
   103  	return cipherSuite.Encrypt(pkt, raw)
   104  }
   105  
   106  // Decrypt decrypts a single TLS RecordLayer
   107  func (c *TLSEcdheEcdsaWithAes256CbcSha) Decrypt(raw []byte) ([]byte, error) {
   108  	cipherSuite, ok := c.cbc.Load().(*ciphersuite.CBC)
   109  	if !ok {
   110  		return nil, fmt.Errorf("%w, unable to decrypt", errCipherSuiteNotInit)
   111  	}
   112  
   113  	return cipherSuite.Decrypt(raw)
   114  }