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