1
2
3
4
5
6
7
8
9
10
11
12
13
14 package hpke
15
16 import (
17 "crypto/rand"
18 "encoding"
19 "errors"
20 "io"
21
22 "github.com/cloudflare/circl/kem"
23 )
24
25 const versionLabel = "HPKE-v1"
26
27
28 type Context interface {
29 encoding.BinaryMarshaler
30
31
32
33
34
35 Export(exporterContext []byte, length uint) []byte
36
37 Suite() Suite
38 }
39
40
41 type Sealer interface {
42 Context
43
44
45 Seal(pt, aad []byte) (ct []byte, err error)
46 }
47
48
49 type Opener interface {
50 Context
51
52
53
54 Open(ct, aad []byte) (pt []byte, err error)
55 }
56
57
58 type modeID = uint8
59
60 const (
61
62 modeBase modeID = 0x00
63
64
65 modePSK modeID = 0x01
66
67
68 modeAuth modeID = 0x02
69
70 modeAuthPSK modeID = 0x03
71 )
72
73
74 type Suite struct {
75 kemID KEM
76 kdfID KDF
77 aeadID AEAD
78 }
79
80
81
82 func NewSuite(kemID KEM, kdfID KDF, aeadID AEAD) Suite {
83 s := Suite{kemID, kdfID, aeadID}
84 if !s.isValid() {
85 panic(ErrInvalidHPKESuite)
86 }
87 return s
88 }
89
90 type state struct {
91 Suite
92 modeID modeID
93 skS kem.PrivateKey
94 pkS kem.PublicKey
95 psk []byte
96 pskID []byte
97 info []byte
98 }
99
100
101 type Sender struct {
102 state
103 pkR kem.PublicKey
104 }
105
106
107 func (suite Suite) NewSender(pkR kem.PublicKey, info []byte) (*Sender, error) {
108 return &Sender{
109 state: state{Suite: suite, info: info},
110 pkR: pkR,
111 }, nil
112 }
113
114
115
116 func (s *Sender) Setup(rnd io.Reader) (enc []byte, seal Sealer, err error) {
117 s.modeID = modeBase
118 return s.allSetup(rnd)
119 }
120
121
122
123 func (s *Sender) SetupAuth(rnd io.Reader, skS kem.PrivateKey) (
124 enc []byte, seal Sealer, err error,
125 ) {
126 s.modeID = modeAuth
127 s.state.skS = skS
128 return s.allSetup(rnd)
129 }
130
131
132
133 func (s *Sender) SetupPSK(rnd io.Reader, psk, pskID []byte) (
134 enc []byte, seal Sealer, err error,
135 ) {
136 s.modeID = modePSK
137 s.state.psk = psk
138 s.state.pskID = pskID
139 return s.allSetup(rnd)
140 }
141
142
143
144 func (s *Sender) SetupAuthPSK(rnd io.Reader, skS kem.PrivateKey, psk, pskID []byte) (
145 enc []byte, seal Sealer, err error,
146 ) {
147 s.modeID = modeAuthPSK
148 s.state.skS = skS
149 s.state.psk = psk
150 s.state.pskID = pskID
151 return s.allSetup(rnd)
152 }
153
154
155 type Receiver struct {
156 state
157 skR kem.PrivateKey
158 enc []byte
159 }
160
161
162 func (suite Suite) NewReceiver(skR kem.PrivateKey, info []byte) (
163 *Receiver, error,
164 ) {
165 return &Receiver{state: state{Suite: suite, info: info}, skR: skR}, nil
166 }
167
168
169
170 func (r *Receiver) Setup(enc []byte) (Opener, error) {
171 r.modeID = modeBase
172 r.enc = enc
173 return r.allSetup()
174 }
175
176
177
178 func (r *Receiver) SetupAuth(enc []byte, pkS kem.PublicKey) (Opener, error) {
179 r.modeID = modeAuth
180 r.enc = enc
181 r.state.pkS = pkS
182 return r.allSetup()
183 }
184
185
186
187
188 func (r *Receiver) SetupPSK(enc, psk, pskID []byte) (Opener, error) {
189 r.modeID = modePSK
190 r.enc = enc
191 r.state.psk = psk
192 r.state.pskID = pskID
193 return r.allSetup()
194 }
195
196
197
198
199 func (r *Receiver) SetupAuthPSK(
200 enc, psk, pskID []byte, pkS kem.PublicKey,
201 ) (Opener, error) {
202 r.modeID = modeAuthPSK
203 r.enc = enc
204 r.state.psk = psk
205 r.state.pskID = pskID
206 r.state.pkS = pkS
207 return r.allSetup()
208 }
209
210 func (s *Sender) allSetup(rnd io.Reader) ([]byte, Sealer, error) {
211 scheme := s.kemID.Scheme()
212
213 if rnd == nil {
214 rnd = rand.Reader
215 }
216 seed := make([]byte, scheme.EncapsulationSeedSize())
217 _, err := io.ReadFull(rnd, seed)
218 if err != nil {
219 return nil, nil, err
220 }
221
222 var enc, ss []byte
223 switch s.modeID {
224 case modeBase, modePSK:
225 enc, ss, err = scheme.EncapsulateDeterministically(s.pkR, seed)
226 case modeAuth, modeAuthPSK:
227 enc, ss, err = scheme.AuthEncapsulateDeterministically(s.pkR, s.skS, seed)
228 }
229 if err != nil {
230 return nil, nil, err
231 }
232
233 ctx, err := s.keySchedule(ss, s.info, s.psk, s.pskID)
234 if err != nil {
235 return nil, nil, err
236 }
237
238 return enc, &sealContext{ctx}, nil
239 }
240
241 func (r *Receiver) allSetup() (Opener, error) {
242 var err error
243 var ss []byte
244 scheme := r.kemID.Scheme()
245 switch r.modeID {
246 case modeBase, modePSK:
247 ss, err = scheme.Decapsulate(r.skR, r.enc)
248 case modeAuth, modeAuthPSK:
249 ss, err = scheme.AuthDecapsulate(r.skR, r.enc, r.pkS)
250 }
251 if err != nil {
252 return nil, err
253 }
254
255 ctx, err := r.keySchedule(ss, r.info, r.psk, r.pskID)
256 if err != nil {
257 return nil, err
258 }
259 return &openContext{ctx}, nil
260 }
261
262 var (
263 ErrInvalidHPKESuite = errors.New("hpke: invalid HPKE suite")
264 ErrInvalidKDF = errors.New("hpke: invalid KDF identifier")
265 ErrInvalidKEM = errors.New("hpke: invalid KEM identifier")
266 ErrInvalidAEAD = errors.New("hpke: invalid AEAD identifier")
267 ErrInvalidKEMPublicKey = errors.New("hpke: invalid KEM public key")
268 ErrInvalidKEMPrivateKey = errors.New("hpke: invalid KEM private key")
269 ErrInvalidKEMSharedSecret = errors.New("hpke: invalid KEM shared secret")
270 ErrAEADSeqOverflows = errors.New("hpke: AEAD sequence number overflows")
271 )
272
View as plain text