Source file src/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go

     1  // Copyright 2016 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build gc && !purego
     6  // +build gc,!purego
     7  
     8  package chacha20poly1305
     9  
    10  import (
    11  	"encoding/binary"
    12  
    13  	"golang.org/x/crypto/internal/subtle"
    14  	"golang.org/x/sys/cpu"
    15  )
    16  
    17  //go:noescape
    18  func chacha20Poly1305Open(dst []byte, key []uint32, src, ad []byte) bool
    19  
    20  //go:noescape
    21  func chacha20Poly1305Seal(dst []byte, key []uint32, src, ad []byte)
    22  
    23  var (
    24  	useAVX2 = cpu.X86.HasAVX2 && cpu.X86.HasBMI2
    25  )
    26  
    27  // setupState writes a ChaCha20 input matrix to state. See
    28  // https://tools.ietf.org/html/rfc7539#section-2.3.
    29  func setupState(state *[16]uint32, key *[32]byte, nonce []byte) {
    30  	state[0] = 0x61707865
    31  	state[1] = 0x3320646e
    32  	state[2] = 0x79622d32
    33  	state[3] = 0x6b206574
    34  
    35  	state[4] = binary.LittleEndian.Uint32(key[0:4])
    36  	state[5] = binary.LittleEndian.Uint32(key[4:8])
    37  	state[6] = binary.LittleEndian.Uint32(key[8:12])
    38  	state[7] = binary.LittleEndian.Uint32(key[12:16])
    39  	state[8] = binary.LittleEndian.Uint32(key[16:20])
    40  	state[9] = binary.LittleEndian.Uint32(key[20:24])
    41  	state[10] = binary.LittleEndian.Uint32(key[24:28])
    42  	state[11] = binary.LittleEndian.Uint32(key[28:32])
    43  
    44  	state[12] = 0
    45  	state[13] = binary.LittleEndian.Uint32(nonce[0:4])
    46  	state[14] = binary.LittleEndian.Uint32(nonce[4:8])
    47  	state[15] = binary.LittleEndian.Uint32(nonce[8:12])
    48  }
    49  
    50  func (c *chacha20poly1305) seal(dst, nonce, plaintext, additionalData []byte) []byte {
    51  	if !cpu.X86.HasSSSE3 {
    52  		return c.sealGeneric(dst, nonce, plaintext, additionalData)
    53  	}
    54  
    55  	var state [16]uint32
    56  	setupState(&state, &c.key, nonce)
    57  
    58  	ret, out := sliceForAppend(dst, len(plaintext)+16)
    59  	if subtle.InexactOverlap(out, plaintext) {
    60  		panic("chacha20poly1305: invalid buffer overlap")
    61  	}
    62  	chacha20Poly1305Seal(out[:], state[:], plaintext, additionalData)
    63  	return ret
    64  }
    65  
    66  func (c *chacha20poly1305) open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
    67  	if !cpu.X86.HasSSSE3 {
    68  		return c.openGeneric(dst, nonce, ciphertext, additionalData)
    69  	}
    70  
    71  	var state [16]uint32
    72  	setupState(&state, &c.key, nonce)
    73  
    74  	ciphertext = ciphertext[:len(ciphertext)-16]
    75  	ret, out := sliceForAppend(dst, len(ciphertext))
    76  	if subtle.InexactOverlap(out, ciphertext) {
    77  		panic("chacha20poly1305: invalid buffer overlap")
    78  	}
    79  	if !chacha20Poly1305Open(out, state[:], ciphertext, additionalData) {
    80  		for i := range out {
    81  			out[i] = 0
    82  		}
    83  		return nil, errOpen
    84  	}
    85  
    86  	return ret, nil
    87  }
    88  

View as plain text