@@ -21,7 +21,21 @@ pub fn new_psiv(key []u8) !&Chacha20Poly1305RE {
2121 return error ('new_psiv: bad key size' )
2222 }
2323 // derives and initializes the new key for later purposes
24- mac_key , enc_key , po := psiv_init (key)!
24+ pol_key := fk_k (key)
25+ mac_key := fm_k (key)
26+ enc_key := fe_k (key)
27+
28+ mut s := chacha20 .State{}
29+ mut x64 := [64 ]u8 {}
30+ unsafe { vmemcpy (x64 , pol_key[0 ], 36 ) }
31+ unpack_into_state (mut s, x64 )
32+ ws := chacha20_core (s)
33+
34+ // For poly1305 mac, we only take a first 32-bytes of the state as a key
35+ mut poly1305_key := []u8 {len: 32 }
36+ pack32_from_state (mut poly1305_ key, ws)
37+ po := poly1305 .new (poly1305_ key)!
38+
2539 // set the values
2640 c := & Chacha20 Poly1305 RE{
2741 key: key.clone ()
6478 key []u8
6579 // flags that tells derivation keys has been precomputed
6680 precomp bool
67- mac_key []u8
68- enc_key []u8
81+ mac_key [36 ]u8
82+ enc_key [36 ]u8
6983 po & poly1305 .Poly1305 = unsafe { nil }
7084}
7185
7488pub fn (mut c Chacha20Poly1305RE) free () {
7589 unsafe {
7690 c.key.free ()
77- c.mac_key.free ()
78- c.enc_key.free ()
91+ // we reset derived keys
92+ vmemset (c.mac_key, 0 , 36 )
93+ vmemset (c.enc_key, 0 , 36 )
7994 c.po = nil
8095 }
8196 c.precomp = false
@@ -165,15 +180,15 @@ pub fn (c Chacha20Poly1305RE) decrypt(ciphertext []u8, nonce []u8, ad []u8) ![]u
165180// psiv_encrypt_internal is an internal encryption routine used by the core of psiv construct
166181// for encrypting (or decrypting) message.
167182@[direct_array_access]
168- fn psiv_encrypt_internal (mut dst []u8 , plaintext []u8 , key [ ]u8 , tag []u8 , nonce []u8 ) ! {
183+ fn psiv_encrypt_internal (mut dst []u8 , plaintext []u8 , dkey [ 36 ]u8 , tag []u8 , nonce []u8 ) ! {
169184 // loads the counter from the first 8-bytes of the tag input
170185 mut ctr := binary.little_endian_u64 (tag[0 ..8 ])
171186
172187 // setup some temporary vars
173188 mut tc := []u8 {len: 8 } // counter buffer
174189 mut s := chacha20 .State{}
175- mut b64 := []u8 {len: 64 } // state buffer
176- mut tt := merge_drv_key (key , nonce, tag[0 ..8 ], tag[8 ..16 ])
190+ mut b64 := [64 ]u8 {} // state buffer
191+ mut tt := merge_drv_key (dkey , nonce, tag[0 ..8 ], tag[8 ..16 ])
177192
178193 mut j := 0
179194 mut n := 0
@@ -208,15 +223,15 @@ fn psiv_encrypt_internal(mut dst []u8, plaintext []u8, key []u8, tag []u8, nonce
208223 unsafe {
209224 tc.free ()
210225 s.reset ()
211- b64 . free ( )
212- tt. free ( )
226+ vmemset ( b64 , 0 , b 64 .len )
227+ vmemset (tt, 0 , tt.len )
213228 }
214229}
215230
216231// psiv_gen_tag computes a tag from the key, nonce, and Poly1305 tag of the associated data
217232// and plaintext using the ChaCha20 permutation with the feed-forward, truncating the output.
218233@[direct_array_access]
219- fn psiv_gen_tag (mut out []u8 , mut po poly1305 .Poly1305 , input []u8 , ad_len int , mac_key []u8 , nonce []u8 ) {
234+ fn psiv_gen_tag (mut out []u8 , mut po poly1305 .Poly1305 , input []u8 , ad_len int , mac_key [36 ]u8 , nonce []u8 ) {
220235 // updates poly1305 mac by input message, associated data length and input length.
221236 update_with_padding (mut po, input)
222237 po.update (length_to_block (ad_len, input.len))
@@ -237,39 +252,12 @@ fn psiv_gen_tag(mut out []u8, mut po poly1305.Poly1305, input []u8, ad_len int,
237252
238253 // explicitly releases (reset) temporary allocated resources
239254 unsafe {
240- drv_key. free ( )
255+ vmemset (drv_key, 0 , 36 )
241256 ws.reset ()
242257 x.reset ()
243258 }
244259}
245260
246- // psiv_init initializes and expands master key into desired psiv needed construct.
247- @[direct_array_access; inline]
248- fn psiv_init (key []u8 ) ! ([]u8 , []u8 , & poly1305 .Poly1305 ) {
249- // derives some keys
250- pol_key := fk_k (key)
251- mac_key := fm_k (key)
252- enc_key := fe_k (key)
253-
254- mut x := chacha20 .State{}
255- unpack_into_state (mut x, merge_drvk_zeros (pol_key))
256- ws := chacha20_core (x)
257-
258- // For poly1305 mac, we only take a first 32-bytes of the state as a key
259- mut poly1305_key := []u8 {len: 32 }
260- pack32_from_state (mut poly1305_ key, ws)
261- po := poly1305 .new (poly1305_ key)!
262-
263- // reset (release) temporary allocated resources
264- unsafe {
265- x.reset ()
266- ws.reset ()
267- pol_key.free ()
268- poly1305_ key.free ()
269- }
270- return mac_key, enc_key, po
271- }
272-
273261// update_with_padding updates poly1305 mac with data, padding the tail block if necessary.
274262@[direct_array_access; inline]
275263fn update_with_padding (mut po poly1305 .Poly1305 , data []u8 ) {
@@ -283,76 +271,67 @@ fn update_with_padding(mut po poly1305.Poly1305, data []u8) {
283271
284272// merge_drv_key merges provided bytes into 64-bytes key
285273@[direct_array_access; inline]
286- fn merge_drv_key (dkey []u8 , nonce []u8 , tag_ctr []u8 , tag_rest []u8 ) []u8 {
287- mut x := []u8 {len: 64 }
274+ fn merge_drv_key (dkey [36 ]u8 , nonce []u8 , tag_ctr []u8 , tag_rest []u8 ) [64 ]u8 {
275+ mut x64 := [64 ]u8 {}
288276
289277 // 0..36
290278 for i := 0 ; i < dkey.len; i++ {
291- x [i] = dkey[i]
279+ x 64 [i] = dkey[i]
292280 }
293281 // 36..48
294282 for i := 0 ; i < nonce.len; i++ {
295- x [36 + i] = nonce[i]
283+ x 64 [36 + i] = nonce[i]
296284 }
297285 // 48..56
298286 for i := 0 ; i < tag_ctr.len; i++ {
299- x [i + 48 ] = tag_ctr[i]
287+ x 64 [i + 48 ] = tag_ctr[i]
300288 }
301289 // 56..64
302290 for i := 0 ; i < tag_rest.len; i++ {
303- x [i + 56 ] = tag_rest[i]
291+ x 64 [i + 56 ] = tag_rest[i]
304292 }
305293
306- return x
307- }
308-
309- // merge_drvk_zeros merges derived key in dkey with zeros nonce and zeros tag into 64-bytes of key.
310- @[direct_array_access; inline]
311- fn merge_drvk_zeros (dkey []u8 ) []u8 {
312- mut x := []u8 {len: 64 }
313- _ := copy (mut x, dkey)
314- // the others was null bytes
315- return x
294+ return x64
316295}
317296
318297// fk_k maps and transforms 32-bytes of key into 36-bytes of new key used to
319298// derive a poly1305 construction.
320299// See the papers doc on the 3.3 Additional Details part, on page 12-13
321300@[direct_array_access; inline]
322- fn fk_k (k []u8 ) []u8 {
301+ fn fk_k (key []u8 ) [36 ]u8 {
323302 // fk(K) = K1 ∥ K2 ∥ K3 ∥ 03 ∥ K5 ∥ K6 ∥ K7 ∥ 0c ∥ K9 ∥ K10 ∥ K11 ∥ 30
324303 // ∥ K4 ∥ K8 ∥ K12 ∥ c0 ∥ K13 ∥ K14 ∥ · · · ∥ K32
325304 // with 0-based index
326305 // K0 ∥ K1 ∥ K2 ∥ 03 ∥ K4 ∥ K5 ∥ K6 ∥ 0c ∥ K8 ∥ K9 ∥ K10 ∥ 30
327306 // ∥ K3 ∥ K7 ∥ K11 ∥ c0 ∥ K12 ∥ K13 ∥ · · · ∥ K31
328- mut x := []u8 {len: 36 }
307+ mut x := [36 ]u8 {}
329308 // 0 .. 4
330309 for i := 0 ; i < 3 ; i++ {
331- x[i] = k [i]
310+ x[i] = key [i]
332311 }
333312 x[3 ] = u8 (0x03 )
334313
335314 // 4 .. 8
336315 for i := 4 ; i < 7 ; i++ {
337- x[i] = k [i]
316+ x[i] = key [i]
338317 }
339318 x[7 ] = 0x0c
340319
341320 // 8 .. 12
342321 for i := 8 ; i < 11 ; i++ {
343- x[i] = k [i]
322+ x[i] = key [i]
344323 }
345324 x[11 ] = 0x30
346325
347326 // 12 .. 16
348- x[12 ] = k [3 ]
349- x[13 ] = k [7 ]
350- x[14 ] = k [11 ]
327+ x[12 ] = key [3 ]
328+ x[13 ] = key [7 ]
329+ x[14 ] = key [11 ]
351330 x[15 ] = 0xc0
352331
353332 // 16 .. 36
354333 for i := 16 ; i < 36 ; i++ {
355- x[i] = k [i - 4 ]
334+ x[i] = key [i - 4 ]
356335 }
357336
358337 return x
@@ -361,115 +340,131 @@ fn fk_k(k []u8) []u8 {
361340// fm_k maps and transforms 32-bytes of key into 36-bytes of message authentication key.
362341// It later used for psiv tag generation.
363342@[direct_array_access; inline]
364- fn fm_k (k []u8 ) []u8 {
343+ fn fm_k (key []u8 ) [36 ]u8 {
365344 // fm(K) = K1 ∥ K2 ∥ K3 ∥ 05 ∥ K5 ∥ K6 ∥ K7 ∥ 0a ∥ K9 ∥ K10 ∥ K11 ∥ 50 ∥
366345 // K4 ∥ K8 ∥ K12 ∥ a0 ∥ K13 ∥ K14 ∥ · · · ∥ K32 ,
367346 // Or, with 0-based index
368347 // fm(K) = K0 ∥ K1 ∥ K2 ∥ 05 ∥ K4 ∥ K5 ∥ K6 ∥ 0a ∥ K8 ∥ K9 ∥ K10 ∥ 50 ∥
369348 // K3 ∥ K7 ∥ K11 ∥ a0 ∥ K12 ∥ K13 ∥ · · · ∥ K31
370- mut x := []u8 {len: 36 }
349+ mut x := [36 ]u8 {}
371350 // 0 .. 4
372351 for i := 0 ; i < 3 ; i++ {
373- x[i] = k [i]
352+ x[i] = key [i]
374353 }
375354 x[3 ] = u8 (0x05 )
376355
377356 // 4 .. 8
378357 for i := 4 ; i < 7 ; i++ {
379- x[i] = k [i]
358+ x[i] = key [i]
380359 }
381360 x[7 ] = 0x0a
382361
383362 // 8 .. 12
384363 for i := 8 ; i < 11 ; i++ {
385- x[i] = k [i]
364+ x[i] = key [i]
386365 }
387366 x[11 ] = 0x50
388367
389368 // 12 .. 16
390- x[12 ] = k [3 ]
391- x[13 ] = k [7 ]
392- x[14 ] = k [11 ]
369+ x[12 ] = key [3 ]
370+ x[13 ] = key [7 ]
371+ x[14 ] = key [11 ]
393372 x[15 ] = 0xa0
394373
395374 // 16 .. 36
396375 for i := 16 ; i < 36 ; i++ {
397- x[i] = k [i - 4 ]
376+ x[i] = key [i - 4 ]
398377 }
399378
400379 return x
401380}
402381
403382// fe_k maps and transforms 32-bytes of key into 36-bytes of new encryption key
404383@[direct_array_access; inline]
405- fn fe_k (k []u8 ) []u8 {
384+ fn fe_k (key []u8 ) [36 ]u8 {
406385 // fe(K) = K1 ∥ K2 ∥ K3 ∥ 06 ∥ K5 ∥ K6 ∥ K7 ∥ 09 ∥ K9 ∥ K10 ∥ K11 ∥ 60 ∥
407386 // K4 ∥ K8 ∥ K12 ∥ 90 ∥ K13 ∥ K14 ∥ · · · ∥ K32
408387 // Or, with 0-based index
409388 // fe(K) = K0 ∥ K1 ∥ K2 ∥ 06 ∥ K4 ∥ K5 ∥ K6 ∥ 09 ∥ K8 ∥ K9 ∥ K10 ∥ 60 ∥
410389 // K3 ∥ K7 ∥ K11 ∥ 90 ∥ K12 ∥ K13 ∥ · · · ∥ K31
411- mut x := []u8 {len: 36 }
390+ mut x := [36 ]u8 {}
412391 // 0 .. 4
413392 for i := 0 ; i < 3 ; i++ {
414- x[i] = k [i]
393+ x[i] = key [i]
415394 }
416395 x[3 ] = u8 (0x06 )
417396
418397 // 4 .. 8
419398 for i := 4 ; i < 7 ; i++ {
420- x[i] = k [i]
399+ x[i] = key [i]
421400 }
422401 x[7 ] = 0x09
423402
424403 // 8 .. 12
425404 for i := 8 ; i < 11 ; i++ {
426- x[i] = k [i]
405+ x[i] = key [i]
427406 }
428407 x[11 ] = 0x60
429408
430409 // 12 .. 16
431- x[12 ] = k [3 ]
432- x[13 ] = k [7 ]
433- x[14 ] = k [11 ]
410+ x[12 ] = key [3 ]
411+ x[13 ] = key [7 ]
412+ x[14 ] = key [11 ]
434413 x[15 ] = 0x90
435414
436415 // 16 .. 36
437416 for i := 16 ; i < 36 ; i++ {
438- x[i] = k [i - 4 ]
417+ x[i] = key [i - 4 ]
439418 }
440419
441420 return x
442421}
443422
444423// unpack_into_state deserializes (in little-endian form) 64-bytes of data in x into state s.
445424@[direct_array_access; inline]
446- fn unpack_into_state (mut s chacha20 .State, x []u8 ) {
425+ fn unpack_into_state (mut s chacha20 .State, x [64 ]u8 ) {
447426 for i := 0 ; i < 16 ; i++ {
448- s[i] = binary.little_endian_u32 (x[i * 4 ..(i + 1 ) * 4 ])
427+ s[i] = u32 (x[i * 4 ]) | (u32 (x[i * 4 + 1 ]) << u32 (8 )) | (u32 (x[i * 4 + 2 ]) << u32 (16 )) | (u32 (x[
428+ i * 4 + 3 ]) << u32 (24 ))
449429 }
450430}
451431
452432// pack64_from_state serializes state s into 64-bytes output in little-endian form.
453433@[direct_array_access; inline]
454- fn pack64_from_state (mut out []u8 , s chacha20 .State) {
455- for i, v in s {
456- binary.little_endian_put_u32 (mut out[i * 4 ..(i + 1 ) * 4 ], v)
434+ fn pack64_from_state (mut out [64 ]u8 , s chacha20 .State) {
435+ mut j := 0
436+ for v in s {
437+ out[j] = u8 (v)
438+ out[j + 1 ] = u8 (v >> u32 (8 ))
439+ out[j + 2 ] = u8 (v >> u32 (16 ))
440+ out[j + 3 ] = u8 (v >> u32 (24 ))
441+ j + = 4
457442 }
458443}
459444
460445// pack32_from_state serializes only a half of state s into 32-bytes output in little-endian form.
461446@[direct_array_access; inline]
462447fn pack32_from_state (mut out []u8 , s chacha20 .State) {
463- for i := 0 ; i < 8 ; i++ {
464- binary.little_endian_put_u32 (mut out[i * 4 ..(i + 1 ) * 4 ], s[i])
448+ mut j := 0
449+ for i in 0 .. 8 {
450+ out[j] = u8 (s[i])
451+ out[j + 1 ] = u8 (s[i] >> u32 (8 ))
452+ out[j + 2 ] = u8 (s[i] >> u32 (16 ))
453+ out[j + 3 ] = u8 (s[i] >> u32 (24 ))
454+ j + = 4
465455 }
466456}
467457
468458// pack16_from_state serializes the first quartet of state s into 16-bytes output in little-endian form.
469459@[direct_array_access; inline]
470460fn pack16_from_state (mut out []u8 , s chacha20 .State) {
471- for i := 0 ; i < 4 ; i++ {
472- binary.little_endian_put_u32 (mut out[i * 4 ..(i + 1 ) * 4 ], s[i])
461+ mut j := 0
462+ for i in 0 .. 4 {
463+ out[j] = u8 (s[i])
464+ out[j + 1 ] = u8 (s[i] >> u32 (8 ))
465+ out[j + 2 ] = u8 (s[i] >> u32 (16 ))
466+ out[j + 3 ] = u8 (s[i] >> u32 (24 ))
467+ j + = 4
473468 }
474469}
475470
0 commit comments