1
2
3
4
5 package chacha20poly1305
6
7 import (
8 "encoding/binary"
9
10 "golang.org/x/crypto/chacha20"
11 "golang.org/x/crypto/internal/alias"
12 "golang.org/x/crypto/internal/poly1305"
13 )
14
15 func writeWithPadding(p *poly1305.MAC, b []byte) {
16 p.Write(b)
17 if rem := len(b) % 16; rem != 0 {
18 var buf [16]byte
19 padLen := 16 - rem
20 p.Write(buf[:padLen])
21 }
22 }
23
24 func writeUint64(p *poly1305.MAC, n int) {
25 var buf [8]byte
26 binary.LittleEndian.PutUint64(buf[:], uint64(n))
27 p.Write(buf[:])
28 }
29
30 func (c *chacha20poly1305) sealGeneric(dst, nonce, plaintext, additionalData []byte) []byte {
31 ret, out := sliceForAppend(dst, len(plaintext)+poly1305.TagSize)
32 ciphertext, tag := out[:len(plaintext)], out[len(plaintext):]
33 if alias.InexactOverlap(out, plaintext) {
34 panic("chacha20poly1305: invalid buffer overlap of output and input")
35 }
36 if alias.AnyOverlap(out, additionalData) {
37 panic("chacha20poly1305: invalid buffer overlap of output and additional data")
38 }
39
40 var polyKey [32]byte
41 s, _ := chacha20.NewUnauthenticatedCipher(c.key[:], nonce)
42 s.XORKeyStream(polyKey[:], polyKey[:])
43 s.SetCounter(1)
44 s.XORKeyStream(ciphertext, plaintext)
45
46 p := poly1305.New(&polyKey)
47 writeWithPadding(p, additionalData)
48 writeWithPadding(p, ciphertext)
49 writeUint64(p, len(additionalData))
50 writeUint64(p, len(plaintext))
51 p.Sum(tag[:0])
52
53 return ret
54 }
55
56 func (c *chacha20poly1305) openGeneric(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
57 tag := ciphertext[len(ciphertext)-16:]
58 ciphertext = ciphertext[:len(ciphertext)-16]
59
60 var polyKey [32]byte
61 s, _ := chacha20.NewUnauthenticatedCipher(c.key[:], nonce)
62 s.XORKeyStream(polyKey[:], polyKey[:])
63 s.SetCounter(1)
64
65 p := poly1305.New(&polyKey)
66 writeWithPadding(p, additionalData)
67 writeWithPadding(p, ciphertext)
68 writeUint64(p, len(additionalData))
69 writeUint64(p, len(ciphertext))
70
71 ret, out := sliceForAppend(dst, len(ciphertext))
72 if alias.InexactOverlap(out, ciphertext) {
73 panic("chacha20poly1305: invalid buffer overlap of output and input")
74 }
75 if alias.AnyOverlap(out, additionalData) {
76 panic("chacha20poly1305: invalid buffer overlap of output and additional data")
77 }
78 if !p.Verify(tag) {
79 for i := range out {
80 out[i] = 0
81 }
82 return nil, errOpen
83 }
84
85 s.XORKeyStream(out, ciphertext)
86 return ret, nil
87 }
88
View as plain text