// Code generated by generate1024.go. DO NOT EDIT.

package mlkem

import (
	
	
	
	
	
)

// A DecapsulationKey1024 is the secret key used to decapsulate a shared key from a
// ciphertext. It includes various precomputed values.
type DecapsulationKey1024 struct {
	d [32]byte // decapsulation key seed
	z [32]byte // implicit rejection sampling seed

	ρ [32]byte // sampleNTT seed for A, stored for the encapsulation key
	h [32]byte // H(ek), stored for ML-KEM.Decaps_internal

	encryptionKey1024
	decryptionKey1024
}

// Bytes returns the decapsulation key as a 64-byte seed in the "d || z" form.
//
// The decapsulation key must be kept secret.
func ( *DecapsulationKey1024) () []byte {
	var  [SeedSize]byte
	copy([:], .d[:])
	copy([32:], .z[:])
	return [:]
}

// EncapsulationKey returns the public encapsulation key necessary to produce
// ciphertexts.
func ( *DecapsulationKey1024) () *EncapsulationKey1024 {
	return &EncapsulationKey1024{
		ρ:                 .ρ,
		h:                 .h,
		encryptionKey1024: .encryptionKey1024,
	}
}

// An EncapsulationKey1024 is the public key used to produce ciphertexts to be
// decapsulated by the corresponding [DecapsulationKey1024].
type EncapsulationKey1024 struct {
	ρ [32]byte // sampleNTT seed for A
	h [32]byte // H(ek)
	encryptionKey1024
}

// Bytes returns the encapsulation key as a byte slice.
func ( *EncapsulationKey1024) () []byte {
	// The actual logic is in a separate function to outline this allocation.
	 := make([]byte, 0, EncapsulationKeySize1024)
	return .bytes()
}

func ( *EncapsulationKey1024) ( []byte) []byte {
	for  := range .t {
		 = polyByteEncode(, .t[])
	}
	 = append(, .ρ[:]...)
	return 
}

// encryptionKey1024 is the parsed and expanded form of a PKE encryption key.
type encryptionKey1024 struct {
	t [k1024]nttElement         // ByteDecode₁₂(ek[:384k])
	a [k1024 * k1024]nttElement // A[i*k+j] = sampleNTT(ρ, j, i)
}

// decryptionKey1024 is the parsed and expanded form of a PKE decryption key.
type decryptionKey1024 struct {
	s [k1024]nttElement // ByteDecode₁₂(dk[:decryptionKey1024Size])
}

// GenerateKey1024 generates a new decapsulation key, drawing random bytes from
// a DRBG. The decapsulation key must be kept secret.
func () (*DecapsulationKey1024, error) {
	// The actual logic is in a separate function to outline this allocation.
	 := &DecapsulationKey1024{}
	return generateKey1024()
}

func generateKey1024( *DecapsulationKey1024) (*DecapsulationKey1024, error) {
	var  [32]byte
	drbg.Read([:])
	var  [32]byte
	drbg.Read([:])
	kemKeyGen1024(, &, &)
	if  := fips140.PCT("ML-KEM PCT", func() error { return kemPCT1024() });  != nil {
		// This clearly can't happen, but FIPS 140-3 requires us to check.
		panic()
	}
	fips140.RecordApproved()
	return , nil
}

// GenerateKeyInternal1024 is a derandomized version of GenerateKey1024,
// exclusively for use in tests.
func (,  *[32]byte) *DecapsulationKey1024 {
	 := &DecapsulationKey1024{}
	kemKeyGen1024(, , )
	return 
}

// NewDecapsulationKey1024 parses a decapsulation key from a 64-byte
// seed in the "d || z" form. The seed must be uniformly random.
func ( []byte) (*DecapsulationKey1024, error) {
	// The actual logic is in a separate function to outline this allocation.
	 := &DecapsulationKey1024{}
	return newKeyFromSeed1024(, )
}

func newKeyFromSeed1024( *DecapsulationKey1024,  []byte) (*DecapsulationKey1024, error) {
	if len() != SeedSize {
		return nil, errors.New("mlkem: invalid seed length")
	}
	 := (*[32]byte)([:32])
	 := (*[32]byte)([32:])
	kemKeyGen1024(, , )
	if  := fips140.PCT("ML-KEM PCT", func() error { return kemPCT1024() });  != nil {
		// This clearly can't happen, but FIPS 140-3 requires us to check.
		panic()
	}
	fips140.RecordApproved()
	return , nil
}

// kemKeyGen1024 generates a decapsulation key.
//
// It implements ML-KEM.KeyGen_internal according to FIPS 203, Algorithm 16, and
// K-PKE.KeyGen according to FIPS 203, Algorithm 13. The two are merged to save
// copies and allocations.
func kemKeyGen1024( *DecapsulationKey1024, ,  *[32]byte) {
	.d = *
	.z = *

	 := sha3.New512()
	.Write([:])
	.Write([]byte{k1024}) // Module dimension as a domain separator.
	 := .Sum(make([]byte, 0, 64))
	,  := [:32], [32:]
	.ρ = [32]byte()

	 := &.a
	for  := byte(0);  < k1024; ++ {
		for  := byte(0);  < k1024; ++ {
			[*k1024+] = sampleNTT(, , )
		}
	}

	var  byte
	 := &.s
	for  := range  {
		[] = ntt(samplePolyCBD(, ))
		++
	}
	 := make([]nttElement, k1024)
	for  := range  {
		[] = ntt(samplePolyCBD(, ))
		++
	}

	 := &.t
	for  := range  { // t = A ◦ s + e
		[] = []
		for  := range  {
			[] = polyAdd([], nttMul([*k1024+], []))
		}
	}

	 := sha3.New256()
	 := .EncapsulationKey().Bytes()
	.Write()
	.Sum(.h[:0])
}

// kemPCT1024 performs a Pairwise Consistency Test per FIPS 140-3 IG 10.3.A
// Additional Comment 1: "For key pairs generated for use with approved KEMs in
// FIPS 203, the PCT shall consist of applying the encapsulation key ek to
// encapsulate a shared secret K leading to ciphertext c, and then applying
// decapsulation key dk to retrieve the same shared secret K. The PCT passes if
// the two shared secret K values are equal. The PCT shall be performed either
// when keys are generated/imported, prior to the first exportation, or prior to
// the first operational use (if not exported before the first use)."
func kemPCT1024( *DecapsulationKey1024) error {
	 := .EncapsulationKey()
	,  := .Encapsulate()
	,  := .Decapsulate()
	if  != nil {
		return 
	}
	if subtle.ConstantTimeCompare(, ) != 1 {
		return errors.New("mlkem: PCT failed")
	}
	return nil
}

// Encapsulate generates a shared key and an associated ciphertext from an
// encapsulation key, drawing random bytes from a DRBG.
//
// The shared key must be kept secret.
func ( *EncapsulationKey1024) () (,  []byte) {
	// The actual logic is in a separate function to outline this allocation.
	var  [CiphertextSize1024]byte
	return .encapsulate(&)
}

func ( *EncapsulationKey1024) ( *[CiphertextSize1024]byte) (,  []byte) {
	var  [messageSize]byte
	drbg.Read([:])
	// Note that the modulus check (step 2 of the encapsulation key check from
	// FIPS 203, Section 7.2) is performed by polyByteDecode in parseEK1024.
	fips140.RecordApproved()
	return kemEncaps1024(, , &)
}

// EncapsulateInternal is a derandomized version of Encapsulate, exclusively for
// use in tests.
func ( *EncapsulationKey1024) ( *[32]byte) (,  []byte) {
	 := &[CiphertextSize1024]byte{}
	return kemEncaps1024(, , )
}

// kemEncaps1024 generates a shared key and an associated ciphertext.
//
// It implements ML-KEM.Encaps_internal according to FIPS 203, Algorithm 17.
func kemEncaps1024( *[CiphertextSize1024]byte,  *EncapsulationKey1024,  *[messageSize]byte) (,  []byte) {
	 := sha3.New512()
	.Write([:])
	.Write(.h[:])
	 := .Sum(nil)
	,  := [:SharedKeySize], [SharedKeySize:]
	 = pkeEncrypt1024(, &.encryptionKey1024, , )
	return , 
}

// NewEncapsulationKey1024 parses an encapsulation key from its encoded form.
// If the encapsulation key is not valid, NewEncapsulationKey1024 returns an error.
func ( []byte) (*EncapsulationKey1024, error) {
	// The actual logic is in a separate function to outline this allocation.
	 := &EncapsulationKey1024{}
	return parseEK1024(, )
}

// parseEK1024 parses an encryption key from its encoded form.
//
// It implements the initial stages of K-PKE.Encrypt according to FIPS 203,
// Algorithm 14.
func parseEK1024( *EncapsulationKey1024,  []byte) (*EncapsulationKey1024, error) {
	if len() != EncapsulationKeySize1024 {
		return nil, errors.New("mlkem: invalid encapsulation key length")
	}

	 := sha3.New256()
	.Write()
	.Sum(.h[:0])

	for  := range .t {
		var  error
		.t[],  = polyByteDecode[nttElement]([:encodingSize12])
		if  != nil {
			return nil, 
		}
		 = [encodingSize12:]
	}
	copy(.ρ[:], )

	for  := byte(0);  < k1024; ++ {
		for  := byte(0);  < k1024; ++ {
			.a[*k1024+] = sampleNTT(.ρ[:], , )
		}
	}

	return , nil
}

// pkeEncrypt1024 encrypt a plaintext message.
//
// It implements K-PKE.Encrypt according to FIPS 203, Algorithm 14, although the
// computation of t and AT is done in parseEK1024.
func pkeEncrypt1024( *[CiphertextSize1024]byte,  *encryptionKey1024,  *[messageSize]byte,  []byte) []byte {
	var  byte
	,  := make([]nttElement, k1024), make([]ringElement, k1024)
	for  := range  {
		[] = ntt(samplePolyCBD(, ))
		++
	}
	for  := range  {
		[] = samplePolyCBD(, )
		++
	}
	 := samplePolyCBD(, )

	 := make([]ringElement, k1024) // NTT⁻¹(AT ◦ r) + e1
	for  := range  {
		[] = []
		for  := range  {
			// Note that i and j are inverted, as we need the transposed of A.
			[] = polyAdd([], inverseNTT(nttMul(.a[*k1024+], [])))
		}
	}

	 := ringDecodeAndDecompress1()

	var  nttElement // t⊺ ◦ r
	for  := range .t {
		 = polyAdd(, nttMul(.t[], []))
	}
	 := polyAdd(polyAdd(inverseNTT(), ), )

	 := [:0]
	for ,  := range  {
		 = ringCompressAndEncode11(, )
	}
	 = ringCompressAndEncode5(, )

	return 
}

// Decapsulate generates a shared key from a ciphertext and a decapsulation key.
// If the ciphertext is not valid, Decapsulate returns an error.
//
// The shared key must be kept secret.
func ( *DecapsulationKey1024) ( []byte) ( []byte,  error) {
	if len() != CiphertextSize1024 {
		return nil, errors.New("mlkem: invalid ciphertext length")
	}
	 := (*[CiphertextSize1024]byte)()
	// Note that the hash check (step 3 of the decapsulation input check from
	// FIPS 203, Section 7.3) is foregone as a DecapsulationKey is always
	// validly generated by ML-KEM.KeyGen_internal.
	return kemDecaps1024(, ), nil
}

// kemDecaps1024 produces a shared key from a ciphertext.
//
// It implements ML-KEM.Decaps_internal according to FIPS 203, Algorithm 18.
func kemDecaps1024( *DecapsulationKey1024,  *[CiphertextSize1024]byte) ( []byte) {
	fips140.RecordApproved()
	 := pkeDecrypt1024(&.decryptionKey1024, )
	 := sha3.New512()
	.Write([:])
	.Write(.h[:])
	 := .Sum(make([]byte, 0, 64))
	,  := [:SharedKeySize], [SharedKeySize:]
	 := sha3.NewShake256()
	.Write(.z[:])
	.Write([:])
	 := make([]byte, SharedKeySize)
	.Read()
	var  [CiphertextSize1024]byte
	 := pkeEncrypt1024(&, &.encryptionKey1024, (*[32]byte)(), )

	subtle.ConstantTimeCopy(subtle.ConstantTimeCompare([:], ), , )
	return 
}

// pkeDecrypt1024 decrypts a ciphertext.
//
// It implements K-PKE.Decrypt according to FIPS 203, Algorithm 15,
// although s is retained from kemKeyGen1024.
func pkeDecrypt1024( *decryptionKey1024,  *[CiphertextSize1024]byte) []byte {
	 := make([]ringElement, k1024)
	for  := range  {
		 := (*[encodingSize11]byte)([encodingSize11* : encodingSize11*(+1)])
		[] = ringDecodeAndDecompress11()
	}

	 := (*[encodingSize5]byte)([encodingSize11*k1024:])
	 := ringDecodeAndDecompress5()

	var  nttElement // s⊺ ◦ NTT(u)
	for  := range .s {
		 = polyAdd(, nttMul(.s[], ntt([])))
	}
	 := polySub(, inverseNTT())

	return ringCompressAndEncode1(nil, )
}