github.com/icodeface/tls@v0.0.0-20230910023335-34df9250cd12/internal/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 "github.com/icodeface/tls/internal/x/crypto/internal/chacha20" 11 "github.com/icodeface/tls/internal/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 ret, out := sliceForAppend(dst, len(plaintext)+poly1305.TagSize) 20 21 var polyKey [32]byte 22 s := chacha20.New(c.key, [3]uint32{ 23 binary.LittleEndian.Uint32(nonce[0:4]), 24 binary.LittleEndian.Uint32(nonce[4:8]), 25 binary.LittleEndian.Uint32(nonce[8:12]), 26 }) 27 s.XORKeyStream(polyKey[:], polyKey[:]) 28 s.Advance() // skip the next 32 bytes 29 s.XORKeyStream(out, plaintext) 30 31 polyInput := make([]byte, roundTo16(len(additionalData))+roundTo16(len(plaintext))+8+8) 32 copy(polyInput, additionalData) 33 copy(polyInput[roundTo16(len(additionalData)):], out[:len(plaintext)]) 34 binary.LittleEndian.PutUint64(polyInput[len(polyInput)-16:], uint64(len(additionalData))) 35 binary.LittleEndian.PutUint64(polyInput[len(polyInput)-8:], uint64(len(plaintext))) 36 37 var tag [poly1305.TagSize]byte 38 poly1305.Sum(&tag, polyInput, &polyKey) 39 copy(out[len(plaintext):], tag[:]) 40 41 return ret 42 } 43 44 func (c *chacha20poly1305) openGeneric(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { 45 var tag [poly1305.TagSize]byte 46 copy(tag[:], ciphertext[len(ciphertext)-16:]) 47 ciphertext = ciphertext[:len(ciphertext)-16] 48 49 var polyKey [32]byte 50 s := chacha20.New(c.key, [3]uint32{ 51 binary.LittleEndian.Uint32(nonce[0:4]), 52 binary.LittleEndian.Uint32(nonce[4:8]), 53 binary.LittleEndian.Uint32(nonce[8:12]), 54 }) 55 s.XORKeyStream(polyKey[:], polyKey[:]) 56 s.Advance() // skip the next 32 bytes 57 58 polyInput := make([]byte, roundTo16(len(additionalData))+roundTo16(len(ciphertext))+8+8) 59 copy(polyInput, additionalData) 60 copy(polyInput[roundTo16(len(additionalData)):], ciphertext) 61 binary.LittleEndian.PutUint64(polyInput[len(polyInput)-16:], uint64(len(additionalData))) 62 binary.LittleEndian.PutUint64(polyInput[len(polyInput)-8:], uint64(len(ciphertext))) 63 64 ret, out := sliceForAppend(dst, len(ciphertext)) 65 if !poly1305.Verify(&tag, polyInput, &polyKey) { 66 for i := range out { 67 out[i] = 0 68 } 69 return nil, errOpen 70 } 71 72 s.XORKeyStream(out, ciphertext) 73 return ret, nil 74 }