// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
// SPDX-License-Identifier: MIT

package ciphersuite

import (
	
	
	
	

	
	
	
	
)

// TLSPskWithAes128CbcSha256 implements the TLS_PSK_WITH_AES_128_CBC_SHA256 CipherSuite.
type TLSPskWithAes128CbcSha256 struct {
	cbc atomic.Value // *cryptoCBC
}

// CertificateType returns what type of certificate this CipherSuite exchanges.
func ( *TLSPskWithAes128CbcSha256) () clientcertificate.Type {
	return clientcertificate.Type(0)
}

// KeyExchangeAlgorithm controls what key exchange algorithm is using during the handshake.
func ( *TLSPskWithAes128CbcSha256) () KeyExchangeAlgorithm {
	return KeyExchangeAlgorithmPsk
}

// ECC uses Elliptic Curve Cryptography.
func ( *TLSPskWithAes128CbcSha256) () bool {
	return false
}

// ID returns the ID of the CipherSuite.
func ( *TLSPskWithAes128CbcSha256) () ID {
	return TLS_PSK_WITH_AES_128_CBC_SHA256
}

func ( *TLSPskWithAes128CbcSha256) () string {
	return "TLS_PSK_WITH_AES_128_CBC_SHA256"
}

// HashFunc returns the hashing func for this CipherSuite.
func ( *TLSPskWithAes128CbcSha256) () func() hash.Hash {
	return sha256.New
}

// AuthenticationType controls what authentication method is using during the handshake.
func ( *TLSPskWithAes128CbcSha256) () AuthenticationType {
	return AuthenticationTypePreSharedKey
}

// IsInitialized returns if the CipherSuite has keying material and can
// encrypt/decrypt packets.
func ( *TLSPskWithAes128CbcSha256) () bool {
	return .cbc.Load() != nil
}

// Init initializes the internal Cipher with keying material.
func ( *TLSPskWithAes128CbcSha256) (, ,  []byte,  bool) error {
	const (
		 = 32
		 = 16
		  = 16
	)

	,  := prf.GenerateEncryptionKeys(
		, , , , , , .HashFunc(),
	)
	if  != nil {
		return 
	}

	var  *ciphersuite.CBC
	if  {
		,  = ciphersuite.NewCBC(
			.ClientWriteKey, .ClientWriteIV, .ClientMACKey,
			.ServerWriteKey, .ServerWriteIV, .ServerMACKey,
			.HashFunc(),
		)
	} else {
		,  = ciphersuite.NewCBC(
			.ServerWriteKey, .ServerWriteIV, .ServerMACKey,
			.ClientWriteKey, .ClientWriteIV, .ClientMACKey,
			.HashFunc(),
		)
	}
	.cbc.Store()

	return 
}

// Encrypt encrypts a single TLS RecordLayer.
func ( *TLSPskWithAes128CbcSha256) ( *recordlayer.RecordLayer,  []byte) ([]byte, error) {
	,  := .cbc.Load().(*ciphersuite.CBC)
	if ! {
		return nil, fmt.Errorf("%w, unable to encrypt", errCipherSuiteNotInit)
	}

	return .Encrypt(, )
}

// Decrypt decrypts a single TLS RecordLayer.
func ( *TLSPskWithAes128CbcSha256) ( recordlayer.Header,  []byte) ([]byte, error) {
	,  := .cbc.Load().(*ciphersuite.CBC)
	if ! {
		return nil, fmt.Errorf("%w, unable to decrypt", errCipherSuiteNotInit)
	}

	return .Decrypt(, )
}