// Copyright 2025 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package hpke

import (
	
	
	

	
)

// The AEAD is one of the three components of an HPKE ciphersuite, implementing
// symmetric encryption.
type AEAD interface {
	ID() uint16
	keySize() int
	nonceSize() int
	aead(key []byte) (cipher.AEAD, error)
}

// NewAEAD returns the AEAD implementation for the given AEAD ID.
//
// Applications are encouraged to use specific implementations like [AES128GCM]
// or [ChaCha20Poly1305] instead, unless runtime agility is required.
func ( uint16) (AEAD, error) {
	switch  {
	case 0x0001: // AES-128-GCM
		return AES128GCM(), nil
	case 0x0002: // AES-256-GCM
		return AES256GCM(), nil
	case 0x0003: // ChaCha20Poly1305
		return ChaCha20Poly1305(), nil
	case 0xFFFF: // Export-only
		return ExportOnly(), nil
	default:
		return nil, fmt.Errorf("unsupported AEAD %04x", )
	}
}

// AES128GCM returns an AES-128-GCM AEAD implementation.
func () AEAD { return aes128GCM }

// AES256GCM returns an AES-256-GCM AEAD implementation.
func () AEAD { return aes256GCM }

// ChaCha20Poly1305 returns a ChaCha20Poly1305 AEAD implementation.
func () AEAD { return chacha20poly1305AEAD }

// ExportOnly returns a placeholder AEAD implementation that cannot encrypt or
// decrypt, but only export secrets with [Sender.Export] or [Recipient.Export].
//
// When this is used, [Sender.Seal] and [Recipient.Open] return errors.
func () AEAD { return exportOnlyAEAD{} }

type aead struct {
	nK  int
	nN  int
	new func([]byte) (cipher.AEAD, error)
	id  uint16
}

var aes128GCM = &aead{
	nK:  128 / 8,
	nN:  96 / 8,
	new: newAESGCM,
	id:  0x0001,
}

var aes256GCM = &aead{
	nK:  256 / 8,
	nN:  96 / 8,
	new: newAESGCM,
	id:  0x0002,
}

var chacha20poly1305AEAD = &aead{
	nK:  chacha20poly1305.KeySize,
	nN:  chacha20poly1305.NonceSize,
	new: chacha20poly1305.New,
	id:  0x0003,
}

func ( *aead) () uint16 {
	return .id
}

func ( *aead) ( []byte) (cipher.AEAD, error) {
	if len() != .nK {
		return nil, errors.New("invalid key size")
	}
	return .new()
}

func ( *aead) () int {
	return .nK
}

func ( *aead) () int {
	return .nN
}

type exportOnlyAEAD struct{}

func (exportOnlyAEAD) () uint16 {
	return 0xFFFF
}

func (exportOnlyAEAD) ( []byte) (cipher.AEAD, error) {
	return nil, nil
}

func (exportOnlyAEAD) () int {
	return 0
}

func (exportOnlyAEAD) () int {
	return 0
}