This commit is contained in:
bluepython508 committed 2026-10-22 12:27:19 +01:00
1 parent 3530afb854
commit 6903fcff27
2146 files changed
+112256 -190703

No files matched your search

@@ -0,0 +1,136 @@
// SPDX-License-Identifier: BSD-3-Clause
//go:build arm
// Package chacha20poly1305 provides a ChaCha20-Poly1305 AEAD built
// from the hand-ported ChaCha20 and Poly1305 kernels in
// tsasm/arm/chacha20 and tsasm/arm/poly1305. It only builds on
// GOARCH=arm; other architectures should use
// golang.org/x/crypto/chacha20poly1305.
package chacha20poly1305
import (
"crypto/cipher"
"crypto/subtle"
"encoding/binary"
"errors"
chacha "github.com/tailscale/wireguard-go/tsasm/arm/chacha20"
"github.com/tailscale/wireguard-go/tsasm/arm/poly1305"
)
const (
KeySize = 32
NonceSize = 12
Overhead = 16
)
type aead struct {
key [KeySize]byte
}
// New returns a chacha20poly1305 AEAD with the given 32-byte key.
func New(key []byte) (cipher.AEAD, error) {
if len(key) != KeySize {
return nil, errors.New("chacha20poly1305: bad key length")
}
a := &aead{}
copy(a.key[:], key)
return a, nil
}
func (a *aead) NonceSize() int { return NonceSize }
func (a *aead) Overhead() int { return Overhead }
func (a *aead) Seal(dst, nonce, plaintext, additionalData []byte) []byte {
if len(nonce) != NonceSize {
panic("chacha20poly1305: bad nonce length")
}
ret, out := sliceForAppend(dst, len(plaintext)+Overhead)
var nonceArr [chacha.NonceSize]byte
copy(nonceArr[:], nonce)
// Derive the Poly1305 one-time key from the first 32 bytes of the
// ChaCha20 keystream at counter 0, then encrypt at counter 1.
var (
zeros [64]byte
polyBuf [64]byte
polyKey [32]byte
)
chacha.XORKeyStream(polyBuf[:], zeros[:], &a.key, &nonceArr, 0)
copy(polyKey[:], polyBuf[:32])
chacha.XORKeyStream(out[:len(plaintext)], plaintext, &a.key, &nonceArr, 1)
tag := computeTag(additionalData, out[:len(plaintext)], &polyKey)
copy(out[len(plaintext):], tag[:])
return ret
}
func (a *aead) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
if len(nonce) != NonceSize {
return nil, errors.New("chacha20poly1305: bad nonce length")
}
if len(ciphertext) < Overhead {
return nil, errors.New("chacha20poly1305: ciphertext too short")
}
ctLen := len(ciphertext) - Overhead
ct := ciphertext[:ctLen]
receivedTag := ciphertext[ctLen:]
var nonceArr [chacha.NonceSize]byte
copy(nonceArr[:], nonce)
var (
zeros [64]byte
polyBuf [64]byte
polyKey [32]byte
)
chacha.XORKeyStream(polyBuf[:], zeros[:], &a.key, &nonceArr, 0)
copy(polyKey[:], polyBuf[:32])
expectedTag := computeTag(additionalData, ct, &polyKey)
if subtle.ConstantTimeCompare(receivedTag, expectedTag[:]) != 1 {
return nil, errors.New("chacha20poly1305: message authentication failed")
}
ret, out := sliceForAppend(dst, ctLen)
chacha.XORKeyStream(out, ct, &a.key, &nonceArr, 1)
return ret, nil
}
var zeros16 [16]byte
// computeTag streams (aad || pad16 || ct || pad16 || u64le(|aad|) ||
// u64le(|ct|)) through a stack-allocated Poly1305 MAC.
func computeTag(aad, ct []byte, polyKey *[32]byte) [16]byte {
var mac poly1305.MAC
mac.Init(polyKey)
mac.Write(aad)
if rem := len(aad) % 16; rem != 0 {
mac.Write(zeros16[:16-rem])
}
mac.Write(ct)
if rem := len(ct) % 16; rem != 0 {
mac.Write(zeros16[:16-rem])
}
var lenBuf [16]byte
binary.LittleEndian.PutUint64(lenBuf[0:8], uint64(len(aad)))
binary.LittleEndian.PutUint64(lenBuf[8:16], uint64(len(ct)))
mac.Write(lenBuf[:])
var tag [16]byte
mac.Sum(&tag)
return tag
}
func sliceForAppend(dst []byte, n int) (head, tail []byte) {
if total := len(dst) + n; cap(dst) >= total {
head = dst[:total]
} else {
head = make([]byte, total)
copy(head, dst)
}
tail = head[len(dst):]
return
}