@@ -75,6 +75,29 @@ aegis128l_absorb(const uint8_t *const src, aes_block_t *const state)
7575 aegis128l_update (state , msg0 , msg1 );
7676}
7777
78+ static inline void
79+ aegis128l_absorb_rate (const uint8_t * const src , aes_block_t * const state )
80+ {
81+ aes_block_t msg0 , msg1 ;
82+
83+ msg0 = AES_BLOCK_LOAD (src );
84+ msg1 = AES_BLOCK_LOAD (src + AES_BLOCK_LENGTH );
85+ aegis128l_update (state , msg0 , msg1 );
86+ }
87+
88+ static inline void
89+ aegis128l_squeeze_keystream (uint8_t * const dst , aes_block_t * const state )
90+ {
91+ aes_block_t tmp0 , tmp1 ;
92+
93+ tmp0 = AES_BLOCK_XOR (state [6 ], state [1 ]);
94+ tmp0 = AES_BLOCK_XOR (tmp0 , AES_BLOCK_AND (state [2 ], state [3 ]));
95+ tmp1 = AES_BLOCK_XOR (state [5 ], state [2 ]);
96+ tmp1 = AES_BLOCK_XOR (tmp1 , AES_BLOCK_AND (state [6 ], state [7 ]));
97+ AES_BLOCK_STORE (dst , tmp0 );
98+ AES_BLOCK_STORE (dst + AES_BLOCK_LENGTH , tmp1 );
99+ }
100+
78101static void
79102aegis128l_enc (uint8_t * const dst , const uint8_t * const src , aes_block_t * const state )
80103{
@@ -356,42 +379,61 @@ state_encrypt_update(aegis128l_state *st_, uint8_t *c, size_t clen_max, size_t *
356379
357380 * written = 0 ;
358381 st -> mlen += mlen ;
382+
383+ if (clen_max < mlen ) {
384+ errno = ERANGE ;
385+ return -1 ;
386+ }
387+
388+ // Handle leftover keystream from previous call
359389 if (st -> pos != 0 ) {
360- const size_t available = ( sizeof st -> buf ) - st -> pos ;
390+ const size_t available = RATE - st -> pos ;
361391 const size_t n = mlen < available ? mlen : available ;
392+ size_t j ;
393+ uint8_t tmp ;
362394
363- if (n != 0 ) {
364- memcpy (st -> buf + st -> pos , m + i , n );
365- m += n ;
366- mlen -= n ;
367- st -> pos += n ;
395+ for (j = 0 ; j < n ; j ++ ) {
396+ tmp = m [j ];
397+ c [j ] = m [j ] ^ st -> buf [st -> pos + j ];
398+ st -> buf [st -> pos + j ] = tmp ;
368399 }
369- if (st -> pos == sizeof st -> buf ) {
370- if (clen_max < RATE ) {
371- errno = ERANGE ;
372- return -1 ;
373- }
374- clen_max -= RATE ;
375- aegis128l_enc (c , st -> buf , blocks );
376- * written += RATE ;
377- c += RATE ;
378- st -> pos = 0 ;
379- } else {
400+ st -> pos += n ;
401+ * written += n ;
402+ m += n ;
403+ c += n ;
404+ mlen -= n ;
405+
406+ if (st -> pos < RATE ) {
407+ // Still consuming keystream from previous call
408+ memcpy (st -> blocks , blocks , sizeof blocks );
380409 return 0 ;
381410 }
411+
412+ // Full block accumulated, update state
413+ aegis128l_absorb_rate (st -> buf , blocks );
414+ st -> pos = 0 ;
382415 }
383- if (clen_max < (mlen & ~(size_t ) (RATE - 1 ))) {
384- errno = ERANGE ;
385- return -1 ;
386- }
416+
387417 for (i = 0 ; i + RATE <= mlen ; i += RATE ) {
388418 aegis128l_enc (c + i , m + i , blocks );
389419 }
390420 * written += i ;
391- left = mlen % RATE ;
421+
422+ left = mlen - i ;
392423 if (left != 0 ) {
393- memcpy (st -> buf , m + i , left );
424+ size_t j ;
425+ uint8_t tmp ;
426+
427+ // Generate keystream without updating state
428+ aegis128l_squeeze_keystream (st -> buf , blocks );
429+
430+ for (j = 0 ; j < left ; j ++ ) {
431+ tmp = m [i + j ];
432+ c [i + j ] = m [i + j ] ^ st -> buf [j ];
433+ st -> buf [j ] = tmp ;
434+ }
394435 st -> pos = left ;
436+ * written += left ;
395437 }
396438
397439 memcpy (st -> blocks , blocks , sizeof blocks );
@@ -407,25 +449,20 @@ state_encrypt_detached_final(aegis128l_state *st_, uint8_t *c, size_t clen_max,
407449 _aegis128l_state * const st =
408450 (_aegis128l_state * ) ((((uintptr_t ) & st_ -> opaque ) + (ALIGNMENT - 1 )) &
409451 ~(uintptr_t ) (ALIGNMENT - 1 ));
410- CRYPTO_ALIGN (ALIGNMENT ) uint8_t src [RATE ];
411- CRYPTO_ALIGN (ALIGNMENT ) uint8_t dst [RATE ];
412452
413453 memcpy (blocks , st -> blocks , sizeof blocks );
414454
415455 * written = 0 ;
416- if (clen_max < st -> pos ) {
417- errno = ERANGE ;
418- return -1 ;
419- }
456+
457+ // Ciphertext was already output during _update; absorb cached plaintext into state
420458 if (st -> pos != 0 ) {
421- memset ( src , 0 , sizeof src ) ;
422- memcpy ( src , st -> buf , st -> pos );
423- aegis128l_enc ( dst , src , blocks );
424- memcpy ( c , dst , st -> pos );
459+ CRYPTO_ALIGN ( ALIGNMENT ) uint8_t tmp [ RATE ] ;
460+ memset ( tmp , 0 , sizeof tmp );
461+ memcpy ( tmp , st -> buf , st -> pos );
462+ aegis128l_absorb_rate ( tmp , blocks );
425463 }
426- aegis128l_mac (mac , maclen , st -> adlen , st -> mlen , blocks );
427464
428- * written = st -> pos ;
465+ aegis128l_mac ( mac , maclen , st -> adlen , st -> mlen , blocks ) ;
429466
430467 memcpy (st -> blocks , blocks , sizeof blocks );
431468
@@ -440,25 +477,26 @@ state_encrypt_final(aegis128l_state *st_, uint8_t *c, size_t clen_max, size_t *w
440477 _aegis128l_state * const st =
441478 (_aegis128l_state * ) ((((uintptr_t ) & st_ -> opaque ) + (ALIGNMENT - 1 )) &
442479 ~(uintptr_t ) (ALIGNMENT - 1 ));
443- CRYPTO_ALIGN (ALIGNMENT ) uint8_t src [RATE ];
444- CRYPTO_ALIGN (ALIGNMENT ) uint8_t dst [RATE ];
445480
446481 memcpy (blocks , st -> blocks , sizeof blocks );
447482
448483 * written = 0 ;
449- if (clen_max < st -> pos + maclen ) {
484+ if (clen_max < maclen ) {
450485 errno = ERANGE ;
451486 return -1 ;
452487 }
488+
489+ // Ciphertext was already output during _update; absorb cached plaintext into state
453490 if (st -> pos != 0 ) {
454- memset ( src , 0 , sizeof src ) ;
455- memcpy ( src , st -> buf , st -> pos );
456- aegis128l_enc ( dst , src , blocks );
457- memcpy ( c , dst , st -> pos );
491+ CRYPTO_ALIGN ( ALIGNMENT ) uint8_t tmp [ RATE ] ;
492+ memset ( tmp , 0 , sizeof tmp );
493+ memcpy ( tmp , st -> buf , st -> pos );
494+ aegis128l_absorb_rate ( tmp , blocks );
458495 }
459- aegis128l_mac (c + st -> pos , maclen , st -> adlen , st -> mlen , blocks );
460496
461- * written = st -> pos + maclen ;
497+ aegis128l_mac (c , maclen , st -> adlen , st -> mlen , blocks );
498+
499+ * written = maclen ;
462500
463501 memcpy (st -> blocks , blocks , sizeof blocks );
464502
@@ -473,60 +511,83 @@ state_decrypt_detached_update(aegis128l_state *st_, uint8_t *m, size_t mlen_max,
473511 _aegis128l_state * const st =
474512 (_aegis128l_state * ) ((((uintptr_t ) & st_ -> opaque ) + (ALIGNMENT - 1 )) &
475513 ~(uintptr_t ) (ALIGNMENT - 1 ));
476- CRYPTO_ALIGN (ALIGNMENT ) uint8_t dst [RATE ];
477- size_t i = 0 ;
478- size_t left ;
514+ size_t i = 0 ;
515+ size_t left ;
479516
480517 memcpy (blocks , st -> blocks , sizeof blocks );
481518
482519 * written = 0 ;
483520 st -> mlen += clen ;
484521
522+ if (m != NULL && mlen_max < clen ) {
523+ errno = ERANGE ;
524+ return -1 ;
525+ }
526+
527+ // Handle leftover keystream from previous call
485528 if (st -> pos != 0 ) {
486- const size_t available = ( sizeof st -> buf ) - st -> pos ;
529+ const size_t available = RATE - st -> pos ;
487530 const size_t n = clen < available ? clen : available ;
488-
489- if (n != 0 ) {
490- memcpy (st -> buf + st -> pos , c , n );
491- c += n ;
492- clen -= n ;
493- st -> pos += n ;
531+ size_t j ;
532+
533+ for (j = 0 ; j < n ; j ++ ) {
534+ if (m != NULL ) {
535+ m [j ] = c [j ] ^ st -> buf [st -> pos + j ];
536+ st -> buf [st -> pos + j ] = m [j ];
537+ } else {
538+ uint8_t plaintext = c [j ] ^ st -> buf [st -> pos + j ];
539+ st -> buf [st -> pos + j ] = plaintext ;
540+ }
494541 }
495- if (st -> pos < (sizeof st -> buf )) {
542+ st -> pos += n ;
543+ * written += n ;
544+ if (m != NULL ) {
545+ m += n ;
546+ }
547+ c += n ;
548+ clen -= n ;
549+
550+ if (st -> pos < RATE ) {
551+ // Still consuming keystream
552+ memcpy (st -> blocks , blocks , sizeof blocks );
496553 return 0 ;
497554 }
555+
556+ // Full block accumulated, update state
557+ aegis128l_absorb_rate (st -> buf , blocks );
498558 st -> pos = 0 ;
499- if (m != NULL ) {
500- if (mlen_max < RATE ) {
501- errno = ERANGE ;
502- return -1 ;
503- }
504- mlen_max -= RATE ;
505- aegis128l_dec (m , st -> buf , blocks );
506- m += RATE ;
507- } else {
508- aegis128l_dec (dst , st -> buf , blocks );
509- }
510- * written += RATE ;
511559 }
560+
512561 if (m != NULL ) {
513- if (mlen_max < (clen & ~(size_t ) (RATE - 1 ))) {
514- errno = ERANGE ;
515- return -1 ;
516- }
517562 for (i = 0 ; i + RATE <= clen ; i += RATE ) {
518563 aegis128l_dec (m + i , c + i , blocks );
519564 }
520565 } else {
566+ CRYPTO_ALIGN (ALIGNMENT ) uint8_t dst [RATE ];
521567 for (i = 0 ; i + RATE <= clen ; i += RATE ) {
522568 aegis128l_dec (dst , c + i , blocks );
523569 }
524570 }
525571 * written += i ;
526- left = clen % RATE ;
527- if (left ) {
528- memcpy (st -> buf , c + i , left );
572+
573+ left = clen - i ;
574+ if (left != 0 ) {
575+ size_t j ;
576+
577+ // Generate keystream without updating state
578+ aegis128l_squeeze_keystream (st -> buf , blocks );
579+
580+ for (j = 0 ; j < left ; j ++ ) {
581+ if (m != NULL ) {
582+ m [i + j ] = c [i + j ] ^ st -> buf [j ];
583+ st -> buf [j ] = m [i + j ];
584+ } else {
585+ uint8_t plaintext = c [i + j ] ^ st -> buf [j ];
586+ st -> buf [j ] = plaintext ;
587+ }
588+ }
529589 st -> pos = left ;
590+ * written += left ;
530591 }
531592
532593 memcpy (st -> blocks , blocks , sizeof blocks );
@@ -538,40 +599,32 @@ static int
538599state_decrypt_detached_final (aegis128l_state * st_ , uint8_t * m , size_t mlen_max , size_t * written ,
539600 const uint8_t * mac , size_t maclen )
540601{
541- aegis_blocks blocks ;
542- CRYPTO_ALIGN (16 ) uint8_t computed_mac [32 ];
543- CRYPTO_ALIGN (ALIGNMENT ) uint8_t dst [RATE ];
544- _aegis128l_state * const st =
602+ aegis_blocks blocks ;
603+ CRYPTO_ALIGN (16 ) uint8_t computed_mac [32 ];
604+ _aegis128l_state * const st =
545605 (_aegis128l_state * ) ((((uintptr_t ) & st_ -> opaque ) + (ALIGNMENT - 1 )) &
546606 ~(uintptr_t ) (ALIGNMENT - 1 ));
547607 int ret ;
548608
549609 memcpy (blocks , st -> blocks , sizeof blocks );
550610
551611 * written = 0 ;
612+
613+ // Plaintext was already output during _update; absorb cached plaintext into state
552614 if (st -> pos != 0 ) {
553- if (m != NULL ) {
554- if (mlen_max < st -> pos ) {
555- errno = ERANGE ;
556- return -1 ;
557- }
558- aegis128l_declast (m , st -> buf , st -> pos , blocks );
559- } else {
560- aegis128l_declast (dst , st -> buf , st -> pos , blocks );
561- }
615+ CRYPTO_ALIGN (ALIGNMENT ) uint8_t tmp [RATE ];
616+ memset (tmp , 0 , sizeof tmp );
617+ memcpy (tmp , st -> buf , st -> pos );
618+ aegis128l_absorb_rate (tmp , blocks );
562619 }
620+
563621 aegis128l_mac (computed_mac , maclen , st -> adlen , st -> mlen , blocks );
564622 ret = -1 ;
565623 if (maclen == 16 ) {
566624 ret = aegis_verify_16 (computed_mac , mac );
567625 } else if (maclen == 32 ) {
568626 ret = aegis_verify_32 (computed_mac , mac );
569627 }
570- if (ret == 0 ) {
571- * written = st -> pos ;
572- } else {
573- memset (m , 0 , st -> pos );
574- }
575628
576629 memcpy (st -> blocks , blocks , sizeof blocks );
577630
0 commit comments