2121 */
2222#include <crypto/internal/hash.h>
2323#include <linux/init.h>
24+ #include <linux/kernel.h>
2425#include <linux/module.h>
25- #include <linux/mm.h>
26- #include <asm/byteorder.h>
27- #include <linux/types.h>
26+ #include <linux/string.h>
27+ #include <linux/unaligned.h>
2828
2929#define WP512_DIGEST_SIZE 64
3030#define WP384_DIGEST_SIZE 48
3737
3838struct wp512_ctx {
3939 u8 bitLength [WP512_LENGTHBYTES ];
40- u8 buffer [WP512_BLOCK_SIZE ];
41- int bufferBits ;
42- int bufferPos ;
4340 u64 hash [WP512_DIGEST_SIZE /8 ];
4441};
4542
@@ -779,16 +776,16 @@ static const u64 rc[WHIRLPOOL_ROUNDS] = {
779776 * The core Whirlpool transform.
780777 */
781778
782- static __no_kmsan_checks void wp512_process_buffer (struct wp512_ctx * wctx ) {
779+ static __no_kmsan_checks void wp512_process_buffer (struct wp512_ctx * wctx ,
780+ const u8 * buffer ) {
783781 int i , r ;
784782 u64 K [8 ]; /* the round key */
785783 u64 block [8 ]; /* mu(buffer) */
786784 u64 state [8 ]; /* the cipher state */
787785 u64 L [8 ];
788- const __be64 * buffer = (const __be64 * )wctx -> buffer ;
789786
790787 for (i = 0 ; i < 8 ; i ++ )
791- block [i ] = be64_to_cpu (buffer [ i ] );
788+ block [i ] = get_unaligned_be64 (buffer + i * 8 );
792789
793790 state [0 ] = block [0 ] ^ (K [0 ] = wctx -> hash [0 ]);
794791 state [1 ] = block [1 ] ^ (K [1 ] = wctx -> hash [1 ]);
@@ -991,93 +988,61 @@ static int wp512_init(struct shash_desc *desc) {
991988 int i ;
992989
993990 memset (wctx -> bitLength , 0 , 32 );
994- wctx -> bufferBits = wctx -> bufferPos = 0 ;
995- wctx -> buffer [0 ] = 0 ;
996991 for (i = 0 ; i < 8 ; i ++ ) {
997992 wctx -> hash [i ] = 0L ;
998993 }
999994
1000995 return 0 ;
1001996}
1002997
1003- static int wp512_update (struct shash_desc * desc , const u8 * source ,
1004- unsigned int len )
998+ static void wp512_add_length (u8 * bitLength , u64 value )
1005999{
1006- struct wp512_ctx * wctx = shash_desc_ctx (desc );
1007- int sourcePos = 0 ;
1008- unsigned int bits_len = len * 8 ; // convert to number of bits
1009- int sourceGap = (8 - ((int )bits_len & 7 )) & 7 ;
1010- int bufferRem = wctx -> bufferBits & 7 ;
1000+ u32 carry ;
10111001 int i ;
1012- u32 b , carry ;
1013- u8 * buffer = wctx -> buffer ;
1014- u8 * bitLength = wctx -> bitLength ;
1015- int bufferBits = wctx -> bufferBits ;
1016- int bufferPos = wctx -> bufferPos ;
10171002
1018- u64 value = bits_len ;
10191003 for (i = 31 , carry = 0 ; i >= 0 && (carry != 0 || value != 0ULL ); i -- ) {
10201004 carry += bitLength [i ] + ((u32 )value & 0xff );
10211005 bitLength [i ] = (u8 )carry ;
10221006 carry >>= 8 ;
10231007 value >>= 8 ;
10241008 }
1025- while (bits_len > 8 ) {
1026- b = ((source [sourcePos ] << sourceGap ) & 0xff ) |
1027- ((source [sourcePos + 1 ] & 0xff ) >> (8 - sourceGap ));
1028- buffer [bufferPos ++ ] |= (u8 )(b >> bufferRem );
1029- bufferBits += 8 - bufferRem ;
1030- if (bufferBits == WP512_BLOCK_SIZE * 8 ) {
1031- wp512_process_buffer (wctx );
1032- bufferBits = bufferPos = 0 ;
1033- }
1034- buffer [bufferPos ] = b << (8 - bufferRem );
1035- bufferBits += bufferRem ;
1036- bits_len -= 8 ;
1037- sourcePos ++ ;
1038- }
1039- if (bits_len > 0 ) {
1040- b = (source [sourcePos ] << sourceGap ) & 0xff ;
1041- buffer [bufferPos ] |= b >> bufferRem ;
1042- } else {
1043- b = 0 ;
1044- }
1045- if (bufferRem + bits_len < 8 ) {
1046- bufferBits += bits_len ;
1047- } else {
1048- bufferPos ++ ;
1049- bufferBits += 8 - bufferRem ;
1050- bits_len -= 8 - bufferRem ;
1051- if (bufferBits == WP512_BLOCK_SIZE * 8 ) {
1052- wp512_process_buffer (wctx );
1053- bufferBits = bufferPos = 0 ;
1054- }
1055- buffer [bufferPos ] = b << (8 - bufferRem );
1056- bufferBits += (int )bits_len ;
1057- }
1009+ }
10581010
1059- wctx -> bufferBits = bufferBits ;
1060- wctx -> bufferPos = bufferPos ;
1011+ static int wp512_update (struct shash_desc * desc , const u8 * source ,
1012+ unsigned int len )
1013+ {
1014+ struct wp512_ctx * wctx = shash_desc_ctx (desc );
1015+ unsigned int remain = len % WP512_BLOCK_SIZE ;
1016+ u64 bits_len = (len - remain ) * 8ull ;
1017+ u8 * bitLength = wctx -> bitLength ;
10611018
1062- return 0 ;
1019+ wp512_add_length (bitLength , bits_len );
1020+ do {
1021+ wp512_process_buffer (wctx , source );
1022+ source += WP512_BLOCK_SIZE ;
1023+ bits_len -= WP512_BLOCK_SIZE * 8 ;
1024+ } while (bits_len );
1025+
1026+ return remain ;
10631027}
10641028
1065- static int wp512_final (struct shash_desc * desc , u8 * out )
1029+ static int wp512_finup (struct shash_desc * desc , const u8 * src ,
1030+ unsigned int bufferPos , u8 * out )
10661031{
10671032 struct wp512_ctx * wctx = shash_desc_ctx (desc );
10681033 int i ;
1069- u8 * buffer = wctx -> buffer ;
10701034 u8 * bitLength = wctx -> bitLength ;
1071- int bufferBits = wctx -> bufferBits ;
1072- int bufferPos = wctx -> bufferPos ;
10731035 __be64 * digest = (__be64 * )out ;
1036+ u8 buffer [WP512_BLOCK_SIZE ];
10741037
1075- buffer [bufferPos ] |= 0x80U >> (bufferBits & 7 );
1038+ wp512_add_length (bitLength , bufferPos * 8 );
1039+ memcpy (buffer , src , bufferPos );
1040+ buffer [bufferPos ] = 0x80U ;
10761041 bufferPos ++ ;
10771042 if (bufferPos > WP512_BLOCK_SIZE - WP512_LENGTHBYTES ) {
10781043 if (bufferPos < WP512_BLOCK_SIZE )
10791044 memset (& buffer [bufferPos ], 0 , WP512_BLOCK_SIZE - bufferPos );
1080- wp512_process_buffer (wctx );
1045+ wp512_process_buffer (wctx , buffer );
10811046 bufferPos = 0 ;
10821047 }
10831048 if (bufferPos < WP512_BLOCK_SIZE - WP512_LENGTHBYTES )
@@ -1086,31 +1051,32 @@ static int wp512_final(struct shash_desc *desc, u8 *out)
10861051 bufferPos = WP512_BLOCK_SIZE - WP512_LENGTHBYTES ;
10871052 memcpy (& buffer [WP512_BLOCK_SIZE - WP512_LENGTHBYTES ],
10881053 bitLength , WP512_LENGTHBYTES );
1089- wp512_process_buffer (wctx );
1054+ wp512_process_buffer (wctx , buffer );
1055+ memzero_explicit (buffer , sizeof (buffer ));
10901056 for (i = 0 ; i < WP512_DIGEST_SIZE /8 ; i ++ )
10911057 digest [i ] = cpu_to_be64 (wctx -> hash [i ]);
1092- wctx -> bufferBits = bufferBits ;
1093- wctx -> bufferPos = bufferPos ;
10941058
10951059 return 0 ;
10961060}
10971061
1098- static int wp384_final (struct shash_desc * desc , u8 * out )
1062+ static int wp384_finup (struct shash_desc * desc , const u8 * src ,
1063+ unsigned int len , u8 * out )
10991064{
11001065 u8 D [64 ];
11011066
1102- wp512_final (desc , D );
1067+ wp512_finup (desc , src , len , D );
11031068 memcpy (out , D , WP384_DIGEST_SIZE );
11041069 memzero_explicit (D , WP512_DIGEST_SIZE );
11051070
11061071 return 0 ;
11071072}
11081073
1109- static int wp256_final (struct shash_desc * desc , u8 * out )
1074+ static int wp256_finup (struct shash_desc * desc , const u8 * src ,
1075+ unsigned int len , u8 * out )
11101076{
11111077 u8 D [64 ];
11121078
1113- wp512_final (desc , D );
1079+ wp512_finup (desc , src , len , D );
11141080 memcpy (out , D , WP256_DIGEST_SIZE );
11151081 memzero_explicit (D , WP512_DIGEST_SIZE );
11161082
@@ -1121,35 +1087,38 @@ static struct shash_alg wp_algs[3] = { {
11211087 .digestsize = WP512_DIGEST_SIZE ,
11221088 .init = wp512_init ,
11231089 .update = wp512_update ,
1124- .final = wp512_final ,
1090+ .finup = wp512_finup ,
11251091 .descsize = sizeof (struct wp512_ctx ),
11261092 .base = {
11271093 .cra_name = "wp512" ,
11281094 .cra_driver_name = "wp512-generic" ,
1095+ .cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY ,
11291096 .cra_blocksize = WP512_BLOCK_SIZE ,
11301097 .cra_module = THIS_MODULE ,
11311098 }
11321099}, {
11331100 .digestsize = WP384_DIGEST_SIZE ,
11341101 .init = wp512_init ,
11351102 .update = wp512_update ,
1136- .final = wp384_final ,
1103+ .finup = wp384_finup ,
11371104 .descsize = sizeof (struct wp512_ctx ),
11381105 .base = {
11391106 .cra_name = "wp384" ,
11401107 .cra_driver_name = "wp384-generic" ,
1108+ .cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY ,
11411109 .cra_blocksize = WP512_BLOCK_SIZE ,
11421110 .cra_module = THIS_MODULE ,
11431111 }
11441112}, {
11451113 .digestsize = WP256_DIGEST_SIZE ,
11461114 .init = wp512_init ,
11471115 .update = wp512_update ,
1148- .final = wp256_final ,
1116+ .finup = wp256_finup ,
11491117 .descsize = sizeof (struct wp512_ctx ),
11501118 .base = {
11511119 .cra_name = "wp256" ,
11521120 .cra_driver_name = "wp256-generic" ,
1121+ .cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY ,
11531122 .cra_blocksize = WP512_BLOCK_SIZE ,
11541123 .cra_module = THIS_MODULE ,
11551124 }
0 commit comments