// Copyright 2016 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.

//go:build gc && !purego

package chacha20poly1305

import (
	

	
	
)

//go:noescape
func chacha20Poly1305Open( []byte,  []uint32, ,  []byte) bool

//go:noescape
func chacha20Poly1305Seal( []byte,  []uint32, ,  []byte)

var (
	useAVX2 = cpu.X86.HasAVX2 && cpu.X86.HasBMI2
)

// setupState writes a ChaCha20 input matrix to state. See
// https://tools.ietf.org/html/rfc7539#section-2.3.
func setupState( *[16]uint32,  *[32]byte,  []byte) {
	[0] = 0x61707865
	[1] = 0x3320646e
	[2] = 0x79622d32
	[3] = 0x6b206574

	[4] = binary.LittleEndian.Uint32([0:4])
	[5] = binary.LittleEndian.Uint32([4:8])
	[6] = binary.LittleEndian.Uint32([8:12])
	[7] = binary.LittleEndian.Uint32([12:16])
	[8] = binary.LittleEndian.Uint32([16:20])
	[9] = binary.LittleEndian.Uint32([20:24])
	[10] = binary.LittleEndian.Uint32([24:28])
	[11] = binary.LittleEndian.Uint32([28:32])

	[12] = 0
	[13] = binary.LittleEndian.Uint32([0:4])
	[14] = binary.LittleEndian.Uint32([4:8])
	[15] = binary.LittleEndian.Uint32([8:12])
}

func ( *chacha20poly1305) (, , ,  []byte) []byte {
	if !cpu.X86.HasSSSE3 {
		return .sealGeneric(, , , )
	}

	var  [16]uint32
	setupState(&, &.key, )

	,  := sliceForAppend(, len()+16)
	if alias.InexactOverlap(, ) {
		panic("chacha20poly1305: invalid buffer overlap")
	}
	chacha20Poly1305Seal([:], [:], , )
	return 
}

func ( *chacha20poly1305) (, , ,  []byte) ([]byte, error) {
	if !cpu.X86.HasSSSE3 {
		return .openGeneric(, , , )
	}

	var  [16]uint32
	setupState(&, &.key, )

	 = [:len()-16]
	,  := sliceForAppend(, len())
	if alias.InexactOverlap(, ) {
		panic("chacha20poly1305: invalid buffer overlap")
	}
	if !chacha20Poly1305Open(, [:], , ) {
		for  := range  {
			[] = 0
		}
		return nil, errOpen
	}

	return , nil
}