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 } 71