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