1
2
3
4
5 package hpke
6
7 import (
8 "crypto/ecdh"
9 "crypto/rand"
10 "errors"
11 "internal/byteorder"
12 )
13
14
15
16 type KEM interface {
17
18 ID() uint16
19
20
21 GenerateKey() (PrivateKey, error)
22
23
24
25
26 NewPublicKey([]byte) (PublicKey, error)
27
28
29
30
31 NewPrivateKey([]byte) (PrivateKey, error)
32
33
34
35
36 DeriveKeyPair(ikm []byte) (PrivateKey, error)
37
38 encSize() int
39 }
40
41
42
43
44
45 func NewKEM(id uint16) (KEM, error) {
46 switch id {
47 case 0x0010:
48 return DHKEM(ecdh.P256()), nil
49 case 0x0011:
50 return DHKEM(ecdh.P384()), nil
51 case 0x0012:
52 return DHKEM(ecdh.P521()), nil
53 case 0x0020:
54 return DHKEM(ecdh.X25519()), nil
55 case 0x0041:
56 return MLKEM768(), nil
57 case 0x0042:
58 return MLKEM1024(), nil
59 case 0x647a:
60 return MLKEM768X25519(), nil
61 case 0x0050:
62 return MLKEM768P256(), nil
63 case 0x0051:
64 return MLKEM1024P384(), nil
65 default:
66 return nil, errors.New("unsupported KEM")
67 }
68 }
69
70
71
72
73
74
75 type PublicKey interface {
76
77 KEM() KEM
78
79
80 Bytes() []byte
81
82 encap() (sharedSecret, enc []byte, err error)
83 }
84
85
86
87
88
89
90 type PrivateKey interface {
91
92 KEM() KEM
93
94
95
96
97
98
99 Bytes() ([]byte, error)
100
101
102 PublicKey() PublicKey
103
104 decap(enc []byte) (sharedSecret []byte, err error)
105 }
106
107 type dhKEM struct {
108 kdf KDF
109 id uint16
110 curve ecdh.Curve
111 Nsecret uint16
112 Nsk uint16
113 Nenc int
114 }
115
116 func (kem *dhKEM) extractAndExpand(dhKey, kemContext []byte) ([]byte, error) {
117 suiteID := byteorder.BEAppendUint16([]byte("KEM"), kem.id)
118 eaePRK, err := kem.kdf.labeledExtract(suiteID, nil, "eae_prk", dhKey)
119 if err != nil {
120 return nil, err
121 }
122 return kem.kdf.labeledExpand(suiteID, eaePRK, "shared_secret", kemContext, kem.Nsecret)
123 }
124
125 func (kem *dhKEM) ID() uint16 {
126 return kem.id
127 }
128
129 func (kem *dhKEM) encSize() int {
130 return kem.Nenc
131 }
132
133 var dhKEMP256 = &dhKEM{HKDFSHA256(), 0x0010, ecdh.P256(), 32, 32, 65}
134 var dhKEMP384 = &dhKEM{HKDFSHA384(), 0x0011, ecdh.P384(), 48, 48, 97}
135 var dhKEMP521 = &dhKEM{HKDFSHA512(), 0x0012, ecdh.P521(), 64, 66, 133}
136 var dhKEMX25519 = &dhKEM{HKDFSHA256(), 0x0020, ecdh.X25519(), 32, 32, 32}
137
138
139
140
141
142
143
144
145
146 func DHKEM(curve ecdh.Curve) KEM {
147 switch curve {
148 case ecdh.P256():
149 return dhKEMP256
150 case ecdh.P384():
151 return dhKEMP384
152 case ecdh.P521():
153 return dhKEMP521
154 case ecdh.X25519():
155 return dhKEMX25519
156 default:
157
158
159
160 return unsupportedCurveKEM{}
161 }
162 }
163
164 type unsupportedCurveKEM struct{}
165
166 func (unsupportedCurveKEM) ID() uint16 {
167 return 0
168 }
169 func (unsupportedCurveKEM) GenerateKey() (PrivateKey, error) {
170 return nil, errors.New("unsupported curve")
171 }
172 func (unsupportedCurveKEM) NewPublicKey([]byte) (PublicKey, error) {
173 return nil, errors.New("unsupported curve")
174 }
175 func (unsupportedCurveKEM) NewPrivateKey([]byte) (PrivateKey, error) {
176 return nil, errors.New("unsupported curve")
177 }
178 func (unsupportedCurveKEM) DeriveKeyPair([]byte) (PrivateKey, error) {
179 return nil, errors.New("unsupported curve")
180 }
181 func (unsupportedCurveKEM) encSize() int {
182 return 0
183 }
184
185 type dhKEMPublicKey struct {
186 kem *dhKEM
187 pub *ecdh.PublicKey
188 }
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203 func NewDHKEMPublicKey(pub *ecdh.PublicKey) (PublicKey, error) {
204 kem, ok := DHKEM(pub.Curve()).(*dhKEM)
205 if !ok {
206 return nil, errors.New("unsupported curve")
207 }
208 return &dhKEMPublicKey{
209 kem: kem,
210 pub: pub,
211 }, nil
212 }
213
214 func (kem *dhKEM) NewPublicKey(data []byte) (PublicKey, error) {
215 pub, err := kem.curve.NewPublicKey(data)
216 if err != nil {
217 return nil, err
218 }
219 return NewDHKEMPublicKey(pub)
220 }
221
222 func (pk *dhKEMPublicKey) KEM() KEM {
223 return pk.kem
224 }
225
226 func (pk *dhKEMPublicKey) Bytes() []byte {
227 return pk.pub.Bytes()
228 }
229
230
231
232 var testingOnlyGenerateKey func() *ecdh.PrivateKey
233
234 func (pk *dhKEMPublicKey) encap() (sharedSecret []byte, encapPub []byte, err error) {
235 privEph, err := pk.pub.Curve().GenerateKey(rand.Reader)
236 if err != nil {
237 return nil, nil, err
238 }
239 if testingOnlyGenerateKey != nil {
240 privEph = testingOnlyGenerateKey()
241 }
242 dhVal, err := privEph.ECDH(pk.pub)
243 if err != nil {
244 return nil, nil, err
245 }
246 encPubEph := privEph.PublicKey().Bytes()
247
248 encPubRecip := pk.pub.Bytes()
249 kemContext := append(encPubEph, encPubRecip...)
250 sharedSecret, err = pk.kem.extractAndExpand(dhVal, kemContext)
251 if err != nil {
252 return nil, nil, err
253 }
254 return sharedSecret, encPubEph, nil
255 }
256
257 type dhKEMPrivateKey struct {
258 kem *dhKEM
259 priv ecdh.KeyExchanger
260 }
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276 func NewDHKEMPrivateKey(priv ecdh.KeyExchanger) (PrivateKey, error) {
277 kem, ok := DHKEM(priv.Curve()).(*dhKEM)
278 if !ok {
279 return nil, errors.New("unsupported curve")
280 }
281 return &dhKEMPrivateKey{
282 kem: kem,
283 priv: priv,
284 }, nil
285 }
286
287 func (kem *dhKEM) GenerateKey() (PrivateKey, error) {
288 priv, err := kem.curve.GenerateKey(rand.Reader)
289 if err != nil {
290 return nil, err
291 }
292 return NewDHKEMPrivateKey(priv)
293 }
294
295 func (kem *dhKEM) NewPrivateKey(ikm []byte) (PrivateKey, error) {
296 priv, err := kem.curve.NewPrivateKey(ikm)
297 if err != nil {
298 return nil, err
299 }
300 return NewDHKEMPrivateKey(priv)
301 }
302
303 func (kem *dhKEM) DeriveKeyPair(ikm []byte) (PrivateKey, error) {
304
305 suiteID := byteorder.BEAppendUint16([]byte("KEM"), kem.id)
306 prk, err := kem.kdf.labeledExtract(suiteID, nil, "dkp_prk", ikm)
307 if err != nil {
308 return nil, err
309 }
310 if kem == dhKEMX25519 {
311 s, err := kem.kdf.labeledExpand(suiteID, prk, "sk", nil, kem.Nsk)
312 if err != nil {
313 return nil, err
314 }
315 return kem.NewPrivateKey(s)
316 }
317 var counter uint8
318 for counter < 4 {
319 s, err := kem.kdf.labeledExpand(suiteID, prk, "candidate", []byte{counter}, kem.Nsk)
320 if err != nil {
321 return nil, err
322 }
323 if kem == dhKEMP521 {
324 s[0] &= 0x01
325 }
326 r, err := kem.NewPrivateKey(s)
327 if err != nil {
328 counter++
329 continue
330 }
331 return r, nil
332 }
333 panic("chance of four rejections is < 2^-128")
334 }
335
336 func (k *dhKEMPrivateKey) KEM() KEM {
337 return k.kem
338 }
339
340 func (k *dhKEMPrivateKey) Bytes() ([]byte, error) {
341
342
343
344
345
346
347
348
349
350 priv, ok := k.priv.(*ecdh.PrivateKey)
351 if !ok {
352 return nil, errors.New("ecdh: private key does not support Bytes")
353 }
354 if k.kem == dhKEMX25519 {
355 b := priv.Bytes()
356 b[0] &= 248
357 b[31] &= 127
358 b[31] |= 64
359 return b, nil
360 }
361 return priv.Bytes(), nil
362 }
363
364 func (k *dhKEMPrivateKey) PublicKey() PublicKey {
365 return &dhKEMPublicKey{
366 kem: k.kem,
367 pub: k.priv.PublicKey(),
368 }
369 }
370
371 func (k *dhKEMPrivateKey) decap(encPubEph []byte) ([]byte, error) {
372 pubEph, err := k.priv.Curve().NewPublicKey(encPubEph)
373 if err != nil {
374 return nil, err
375 }
376 dhVal, err := k.priv.ECDH(pubEph)
377 if err != nil {
378 return nil, err
379 }
380 kemContext := append(encPubEph, k.priv.PublicKey().Bytes()...)
381 return k.kem.extractAndExpand(dhVal, kemContext)
382 }
383
View as plain text