-
Notifications
You must be signed in to change notification settings - Fork 3
/
fuzz.go
103 lines (86 loc) · 2.05 KB
/
fuzz.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package aesgcm
import (
"bytes"
"crypto/aes"
"crypto/cipher"
)
// Reference: https://github.com/golang/go/blob/f2a416b90ac68596ea05b97cefa8c72e7416e98f/src/crypto/cipher/gcm.go#L84-L86
//
// func NewGCM(cipher Block) (AEAD, error) {
// return newGCMWithNonceAndTagSize(cipher, gcmStandardNonceSize, gcmTagSize)
// }
//
// Reference: https://github.com/golang/go/blob/f2a416b90ac68596ea05b97cefa8c72e7416e98f/src/crypto/cipher/gcm.go#L147-L152
//
// const (
// gcmBlockSize = 16
// gcmTagSize = 16
// gcmMinimumTagSize = 12 // NIST SP 800-38D recommends tags with 12 or more bytes.
// gcmStandardNonceSize = 12
// )
//
const (
noncesize = 12
)
func Fuzz(data []byte) int {
// Decide if key should be 128 or 256 bit.
if len(data) == 0 {
return -1
}
chooser := data[0]
data = data[1:]
keybytes := 32 >> (chooser % 1)
// Read key.
if len(data) < keybytes {
return -1
}
key := data[:keybytes]
data = data[keybytes:]
// Read nonce.
if len(data) < noncesize {
return -1
}
nonce := data[:noncesize]
data = data[noncesize:]
// Read plaintext.
if len(data) == 0 {
return -1
}
plaintext := data
// Construct AES block cipher.
a, err := aes.NewCipher(key)
if err != nil {
panic(err.Error())
}
b := purego{wrapped: a}
// Construct GCM.
agcm, err := cipher.NewGCM(a)
if err != nil {
panic(err.Error())
}
bgcm, err := cipher.NewGCM(b)
if err != nil {
panic(err.Error())
}
// Seal.
aciphertext := agcm.Seal(nil, nonce, plaintext, nil)
bciphertext := bgcm.Seal(nil, nonce, plaintext, nil)
if !bytes.Equal(aciphertext, bciphertext) {
panic("mismatch")
}
// Roundtrip.
roundtrip, err := agcm.Open(nil, nonce, aciphertext, nil)
if err != nil {
panic(err.Error())
}
if !bytes.Equal(roundtrip, plaintext) {
panic("roundtrip failed")
}
return 1
}
type purego struct {
wrapped cipher.Block
}
func (p purego) BlockSize() int { return p.wrapped.BlockSize() }
func (p purego) Encrypt(dst, src []byte) { p.wrapped.Encrypt(dst, src) }
func (p purego) Decrypt(dst, src []byte) { p.wrapped.Decrypt(dst, src) }