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