golang.org/toolchain@v0.0.1-go1.9rc2.windows-amd64/src/vendor/golang_org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go (about)

     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  package chacha20poly1305
     6  
     7  import (
     8  	"encoding/binary"
     9  
    10  	"golang_org/x/crypto/chacha20poly1305/internal/chacha20"
    11  	"golang_org/x/crypto/poly1305"
    12  )
    13  
    14  func roundTo16(n int) int {
    15  	return 16 * ((n + 15) / 16)
    16  }
    17  
    18  func (c *chacha20poly1305) sealGeneric(dst, nonce, plaintext, additionalData []byte) []byte {
    19  	var counter [16]byte
    20  	copy(counter[4:], nonce)
    21  
    22  	var polyKey [32]byte
    23  	chacha20.XORKeyStream(polyKey[:], polyKey[:], &counter, &c.key)
    24  
    25  	ret, out := sliceForAppend(dst, len(plaintext)+poly1305.TagSize)
    26  	counter[0] = 1
    27  	chacha20.XORKeyStream(out, plaintext, &counter, &c.key)
    28  
    29  	polyInput := make([]byte, roundTo16(len(additionalData))+roundTo16(len(plaintext))+8+8)
    30  	copy(polyInput, additionalData)
    31  	copy(polyInput[roundTo16(len(additionalData)):], out[:len(plaintext)])
    32  	binary.LittleEndian.PutUint64(polyInput[len(polyInput)-16:], uint64(len(additionalData)))
    33  	binary.LittleEndian.PutUint64(polyInput[len(polyInput)-8:], uint64(len(plaintext)))
    34  
    35  	var tag [poly1305.TagSize]byte
    36  	poly1305.Sum(&tag, polyInput, &polyKey)
    37  	copy(out[len(plaintext):], tag[:])
    38  
    39  	return ret
    40  }
    41  
    42  func (c *chacha20poly1305) openGeneric(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
    43  	var tag [poly1305.TagSize]byte
    44  	copy(tag[:], ciphertext[len(ciphertext)-16:])
    45  	ciphertext = ciphertext[:len(ciphertext)-16]
    46  
    47  	var counter [16]byte
    48  	copy(counter[4:], nonce)
    49  
    50  	var polyKey [32]byte
    51  	chacha20.XORKeyStream(polyKey[:], polyKey[:], &counter, &c.key)
    52  
    53  	polyInput := make([]byte, roundTo16(len(additionalData))+roundTo16(len(ciphertext))+8+8)
    54  	copy(polyInput, additionalData)
    55  	copy(polyInput[roundTo16(len(additionalData)):], ciphertext)
    56  	binary.LittleEndian.PutUint64(polyInput[len(polyInput)-16:], uint64(len(additionalData)))
    57  	binary.LittleEndian.PutUint64(polyInput[len(polyInput)-8:], uint64(len(ciphertext)))
    58  
    59  	ret, out := sliceForAppend(dst, len(ciphertext))
    60  	if !poly1305.Verify(&tag, polyInput, &polyKey) {
    61  		for i := range out {
    62  			out[i] = 0
    63  		}
    64  		return nil, errOpen
    65  	}
    66  
    67  	counter[0] = 1
    68  	chacha20.XORKeyStream(out, ciphertext, &counter, &c.key)
    69  	return ret, nil
    70  }