...
Source file src/pkg/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go
1
2
3
4
5 package chacha20poly1305
6
7 import (
8 "encoding/binary"
9
10 "golang.org/x/crypto/internal/chacha20"
11 "golang.org/x/crypto/internal/subtle"
12 "golang.org/x/crypto/poly1305"
13 )
14
15 func roundTo16(n int) int {
16 return 16 * ((n + 15) / 16)
17 }
18
19 func (c *chacha20poly1305) sealGeneric(dst, nonce, plaintext, additionalData []byte) []byte {
20 ret, out := sliceForAppend(dst, len(plaintext)+poly1305.TagSize)
21 if subtle.InexactOverlap(out, plaintext) {
22 panic("chacha20poly1305: invalid buffer overlap")
23 }
24
25 var polyKey [32]byte
26 s := chacha20.New(c.key, [3]uint32{
27 binary.LittleEndian.Uint32(nonce[0:4]),
28 binary.LittleEndian.Uint32(nonce[4:8]),
29 binary.LittleEndian.Uint32(nonce[8:12]),
30 })
31 s.XORKeyStream(polyKey[:], polyKey[:])
32 s.Advance()
33 s.XORKeyStream(out, plaintext)
34
35 polyInput := make([]byte, roundTo16(len(additionalData))+roundTo16(len(plaintext))+8+8)
36 copy(polyInput, additionalData)
37 copy(polyInput[roundTo16(len(additionalData)):], out[:len(plaintext)])
38 binary.LittleEndian.PutUint64(polyInput[len(polyInput)-16:], uint64(len(additionalData)))
39 binary.LittleEndian.PutUint64(polyInput[len(polyInput)-8:], uint64(len(plaintext)))
40
41 var tag [poly1305.TagSize]byte
42 poly1305.Sum(&tag, polyInput, &polyKey)
43 copy(out[len(plaintext):], tag[:])
44
45 return ret
46 }
47
48 func (c *chacha20poly1305) openGeneric(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
49 var tag [poly1305.TagSize]byte
50 copy(tag[:], ciphertext[len(ciphertext)-16:])
51 ciphertext = ciphertext[:len(ciphertext)-16]
52
53 var polyKey [32]byte
54 s := chacha20.New(c.key, [3]uint32{
55 binary.LittleEndian.Uint32(nonce[0:4]),
56 binary.LittleEndian.Uint32(nonce[4:8]),
57 binary.LittleEndian.Uint32(nonce[8:12]),
58 })
59 s.XORKeyStream(polyKey[:], polyKey[:])
60 s.Advance()
61
62 polyInput := make([]byte, roundTo16(len(additionalData))+roundTo16(len(ciphertext))+8+8)
63 copy(polyInput, additionalData)
64 copy(polyInput[roundTo16(len(additionalData)):], ciphertext)
65 binary.LittleEndian.PutUint64(polyInput[len(polyInput)-16:], uint64(len(additionalData)))
66 binary.LittleEndian.PutUint64(polyInput[len(polyInput)-8:], uint64(len(ciphertext)))
67
68 ret, out := sliceForAppend(dst, len(ciphertext))
69 if subtle.InexactOverlap(out, ciphertext) {
70 panic("chacha20poly1305: invalid buffer overlap")
71 }
72 if !poly1305.Verify(&tag, polyInput, &polyKey) {
73 for i := range out {
74 out[i] = 0
75 }
76 return nil, errOpen
77 }
78
79 s.XORKeyStream(out, ciphertext)
80 return ret, nil
81 }
82
View as plain text