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 }