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

package ciphersuite

import (
	
	
	
	

	
	
	
	
)

// TLSEcdheEcdsaWithAes128GcmSha256  represents a TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 CipherSuite
type TLSEcdheEcdsaWithAes128GcmSha256 struct {
	gcm atomic.Value // *cryptoGCM
}

// CertificateType returns what type of certficate this CipherSuite exchanges
func ( *TLSEcdheEcdsaWithAes128GcmSha256) () clientcertificate.Type {
	return clientcertificate.ECDSASign
}

// KeyExchangeAlgorithm controls what key exchange algorithm is using during the handshake
func ( *TLSEcdheEcdsaWithAes128GcmSha256) () KeyExchangeAlgorithm {
	return KeyExchangeAlgorithmEcdhe
}

// ECC uses Elliptic Curve Cryptography
func ( *TLSEcdheEcdsaWithAes128GcmSha256) () bool {
	return true
}

// ID returns the ID of the CipherSuite
func ( *TLSEcdheEcdsaWithAes128GcmSha256) () ID {
	return TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
}

func ( *TLSEcdheEcdsaWithAes128GcmSha256) () string {
	return "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"
}

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

// AuthenticationType controls what authentication method is using during the handshake
func ( *TLSEcdheEcdsaWithAes128GcmSha256) () AuthenticationType {
	return AuthenticationTypeCertificate
}

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

func ( *TLSEcdheEcdsaWithAes128GcmSha256) (, ,  []byte,  bool, , ,  int,  func() hash.Hash) error {
	,  := prf.GenerateEncryptionKeys(, , , , , , )
	if  != nil {
		return 
	}

	var  *ciphersuite.GCM
	if  {
		,  = ciphersuite.NewGCM(.ClientWriteKey, .ClientWriteIV, .ServerWriteKey, .ServerWriteIV)
	} else {
		,  = ciphersuite.NewGCM(.ServerWriteKey, .ServerWriteIV, .ClientWriteKey, .ClientWriteIV)
	}
	.gcm.Store()
	return 
}

// Init initializes the internal Cipher with keying material
func ( *TLSEcdheEcdsaWithAes128GcmSha256) (, ,  []byte,  bool) error {
	const (
		 = 0
		 = 16
		  = 4
	)

	return .init(, , , , , , , .HashFunc())
}

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

	return .Encrypt(, )
}

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

	return .Decrypt()
}