1
2
3
4
5 package hpke
6
7 import (
8 "crypto/aes"
9 "crypto/cipher"
10 "errors"
11 "fmt"
12
13 "golang.org/x/crypto/chacha20poly1305"
14 )
15
16
17
18 type AEAD interface {
19 ID() uint16
20 keySize() int
21 nonceSize() int
22 aead(key []byte) (cipher.AEAD, error)
23 }
24
25
26
27
28
29 func NewAEAD(id uint16) (AEAD, error) {
30 switch id {
31 case 0x0001:
32 return AES128GCM(), nil
33 case 0x0002:
34 return AES256GCM(), nil
35 case 0x0003:
36 return ChaCha20Poly1305(), nil
37 case 0xFFFF:
38 return ExportOnly(), nil
39 default:
40 return nil, fmt.Errorf("unsupported AEAD %04x", id)
41 }
42 }
43
44
45 func AES128GCM() AEAD { return aes128GCM }
46
47
48 func AES256GCM() AEAD { return aes256GCM }
49
50
51 func ChaCha20Poly1305() AEAD { return chacha20poly1305AEAD }
52
53
54
55
56
57 func ExportOnly() AEAD { return exportOnlyAEAD{} }
58
59 type aead struct {
60 nK int
61 nN int
62 new func([]byte) (cipher.AEAD, error)
63 id uint16
64 }
65
66 var aes128GCM = &aead{
67 nK: 128 / 8,
68 nN: 96 / 8,
69 new: newAESGCM,
70 id: 0x0001,
71 }
72
73 var aes256GCM = &aead{
74 nK: 256 / 8,
75 nN: 96 / 8,
76 new: newAESGCM,
77 id: 0x0002,
78 }
79
80 var chacha20poly1305AEAD = &aead{
81 nK: chacha20poly1305.KeySize,
82 nN: chacha20poly1305.NonceSize,
83 new: chacha20poly1305.New,
84 id: 0x0003,
85 }
86
87 func newAESGCM(key []byte) (cipher.AEAD, error) {
88 b, err := aes.NewCipher(key)
89 if err != nil {
90 return nil, err
91 }
92 return cipher.NewGCM(b)
93 }
94
95 func (a *aead) ID() uint16 {
96 return a.id
97 }
98
99 func (a *aead) aead(key []byte) (cipher.AEAD, error) {
100 if len(key) != a.nK {
101 return nil, errors.New("invalid key size")
102 }
103 return a.new(key)
104 }
105
106 func (a *aead) keySize() int {
107 return a.nK
108 }
109
110 func (a *aead) nonceSize() int {
111 return a.nN
112 }
113
114 type exportOnlyAEAD struct{}
115
116 func (exportOnlyAEAD) ID() uint16 {
117 return 0xFFFF
118 }
119
120 func (exportOnlyAEAD) aead(key []byte) (cipher.AEAD, error) {
121 return nil, nil
122 }
123
124 func (exportOnlyAEAD) keySize() int {
125 return 0
126 }
127
128 func (exportOnlyAEAD) nonceSize() int {
129 return 0
130 }
131
View as plain text