99#define pr_fmt (fmt ) KMSG_COMPONENT ": " fmt
1010
1111#include <asm/cpacf.h>
12- #include <crypto/sha2.h>
1312#include <crypto/internal/hash.h>
13+ #include <crypto/hmac.h>
14+ #include <crypto/sha2.h>
1415#include <linux/cpufeature.h>
16+ #include <linux/errno.h>
17+ #include <linux/kernel.h>
1518#include <linux/module.h>
19+ #include <linux/string.h>
1620
1721/*
1822 * KMAC param block layout for sha2 function codes:
@@ -71,7 +75,6 @@ union s390_kmac_gr0 {
7175struct s390_kmac_sha2_ctx {
7276 u8 param [MAX_DIGEST_SIZE + MAX_IMBL_SIZE + MAX_BLOCK_SIZE ];
7377 union s390_kmac_gr0 gr0 ;
74- u8 buf [MAX_BLOCK_SIZE ];
7578 u64 buflen [2 ];
7679};
7780
@@ -95,8 +98,8 @@ static inline void kmac_sha2_set_imbl(u8 *param, u64 buflen_lo,
9598 }
9699}
97100
98- static int hash_key (const u8 * in , unsigned int inlen ,
99- u8 * digest , unsigned int digestsize )
101+ static int hash_data (const u8 * in , unsigned int inlen ,
102+ u8 * digest , unsigned int digestsize , bool final )
100103{
101104 unsigned long func ;
102105 union {
@@ -123,19 +126,23 @@ static int hash_key(const u8 *in, unsigned int inlen,
123126
124127 switch (digestsize ) {
125128 case SHA224_DIGEST_SIZE :
126- func = CPACF_KLMD_SHA_256 ;
129+ func = final ? CPACF_KLMD_SHA_256 : CPACF_KIMD_SHA_256 ;
127130 PARAM_INIT (256 , 224 , inlen * 8 );
131+ if (!final )
132+ digestsize = SHA256_DIGEST_SIZE ;
128133 break ;
129134 case SHA256_DIGEST_SIZE :
130- func = CPACF_KLMD_SHA_256 ;
135+ func = final ? CPACF_KLMD_SHA_256 : CPACF_KIMD_SHA_256 ;
131136 PARAM_INIT (256 , 256 , inlen * 8 );
132137 break ;
133138 case SHA384_DIGEST_SIZE :
134- func = CPACF_KLMD_SHA_512 ;
139+ func = final ? CPACF_KLMD_SHA_512 : CPACF_KIMD_SHA_512 ;
135140 PARAM_INIT (512 , 384 , inlen * 8 );
141+ if (!final )
142+ digestsize = SHA512_DIGEST_SIZE ;
136143 break ;
137144 case SHA512_DIGEST_SIZE :
138- func = CPACF_KLMD_SHA_512 ;
145+ func = final ? CPACF_KLMD_SHA_512 : CPACF_KIMD_SHA_512 ;
139146 PARAM_INIT (512 , 512 , inlen * 8 );
140147 break ;
141148 default :
@@ -151,6 +158,12 @@ static int hash_key(const u8 *in, unsigned int inlen,
151158 return 0 ;
152159}
153160
161+ static int hash_key (const u8 * in , unsigned int inlen ,
162+ u8 * digest , unsigned int digestsize )
163+ {
164+ return hash_data (in , inlen , digest , digestsize , true);
165+ }
166+
154167static int s390_hmac_sha2_setkey (struct crypto_shash * tfm ,
155168 const u8 * key , unsigned int keylen )
156169{
@@ -204,50 +217,31 @@ static int s390_hmac_sha2_update(struct shash_desc *desc,
204217{
205218 struct s390_kmac_sha2_ctx * ctx = shash_desc_ctx (desc );
206219 unsigned int bs = crypto_shash_blocksize (desc -> tfm );
207- unsigned int offset , n ;
220+ unsigned int n = round_down ( len , bs ) ;
208221
209- /* check current buffer */
210- offset = ctx -> buflen [0 ] % bs ;
211- ctx -> buflen [0 ] += len ;
212- if (ctx -> buflen [0 ] < len )
222+ ctx -> buflen [0 ] += n ;
223+ if (ctx -> buflen [0 ] < n )
213224 ctx -> buflen [1 ]++ ;
214- if (offset + len < bs )
215- goto store ;
216-
217- /* process one stored block */
218- if (offset ) {
219- n = bs - offset ;
220- memcpy (ctx -> buf + offset , data , n );
221- ctx -> gr0 .iimp = 1 ;
222- _cpacf_kmac (& ctx -> gr0 .reg , ctx -> param , ctx -> buf , bs );
223- data += n ;
224- len -= n ;
225- offset = 0 ;
226- }
227- /* process as many blocks as possible */
228- if (len >= bs ) {
229- n = (len / bs ) * bs ;
230- ctx -> gr0 .iimp = 1 ;
231- _cpacf_kmac (& ctx -> gr0 .reg , ctx -> param , data , n );
232- data += n ;
233- len -= n ;
234- }
235- store :
236- /* store incomplete block in buffer */
237- if (len )
238- memcpy (ctx -> buf + offset , data , len );
239225
240- return 0 ;
226+ /* process as many blocks as possible */
227+ ctx -> gr0 .iimp = 1 ;
228+ _cpacf_kmac (& ctx -> gr0 .reg , ctx -> param , data , n );
229+ return len - n ;
241230}
242231
243- static int s390_hmac_sha2_final (struct shash_desc * desc , u8 * out )
232+ static int s390_hmac_sha2_finup (struct shash_desc * desc , const u8 * src ,
233+ unsigned int len , u8 * out )
244234{
245235 struct s390_kmac_sha2_ctx * ctx = shash_desc_ctx (desc );
246236 unsigned int bs = crypto_shash_blocksize (desc -> tfm );
247237
238+ ctx -> buflen [0 ] += len ;
239+ if (ctx -> buflen [0 ] < len )
240+ ctx -> buflen [1 ]++ ;
241+
248242 ctx -> gr0 .iimp = 0 ;
249243 kmac_sha2_set_imbl (ctx -> param , ctx -> buflen [0 ], ctx -> buflen [1 ], bs );
250- _cpacf_kmac (& ctx -> gr0 .reg , ctx -> param , ctx -> buf , ctx -> buflen [ 0 ] % bs );
244+ _cpacf_kmac (& ctx -> gr0 .reg , ctx -> param , src , len );
251245 memcpy (out , ctx -> param , crypto_shash_digestsize (desc -> tfm ));
252246
253247 return 0 ;
@@ -273,22 +267,89 @@ static int s390_hmac_sha2_digest(struct shash_desc *desc,
273267 return 0 ;
274268}
275269
276- #define S390_HMAC_SHA2_ALG (x ) { \
270+ static int s390_hmac_export_zero (struct shash_desc * desc , void * out )
271+ {
272+ struct crypto_shash * tfm = desc -> tfm ;
273+ u8 ipad [SHA512_BLOCK_SIZE ];
274+ struct s390_hmac_ctx * ctx ;
275+ unsigned int bs ;
276+ int err , i ;
277+
278+ ctx = crypto_shash_ctx (tfm );
279+ bs = crypto_shash_blocksize (tfm );
280+ for (i = 0 ; i < bs ; i ++ )
281+ ipad [i ] = ctx -> key [i ] ^ HMAC_IPAD_VALUE ;
282+
283+ err = hash_data (ipad , bs , out , crypto_shash_digestsize (tfm ), false);
284+ memzero_explicit (ipad , sizeof (ipad ));
285+ return err ;
286+ }
287+
288+ static int s390_hmac_export (struct shash_desc * desc , void * out )
289+ {
290+ struct s390_kmac_sha2_ctx * ctx = shash_desc_ctx (desc );
291+ unsigned int bs = crypto_shash_blocksize (desc -> tfm );
292+ unsigned int ds = bs / 2 ;
293+ union {
294+ u8 * u8 ;
295+ u64 * u64 ;
296+ } p = { .u8 = out };
297+ int err = 0 ;
298+
299+ if (!ctx -> gr0 .ikp )
300+ err = s390_hmac_export_zero (desc , out );
301+ else
302+ memcpy (p .u8 , ctx -> param , ds );
303+ p .u8 += ds ;
304+ put_unaligned (ctx -> buflen [0 ], p .u64 ++ );
305+ if (ds == SHA512_DIGEST_SIZE )
306+ put_unaligned (ctx -> buflen [1 ], p .u64 );
307+ return err ;
308+ }
309+
310+ static int s390_hmac_import (struct shash_desc * desc , const void * in )
311+ {
312+ struct s390_kmac_sha2_ctx * ctx = shash_desc_ctx (desc );
313+ unsigned int bs = crypto_shash_blocksize (desc -> tfm );
314+ unsigned int ds = bs / 2 ;
315+ union {
316+ const u8 * u8 ;
317+ const u64 * u64 ;
318+ } p = { .u8 = in };
319+ int err ;
320+
321+ err = s390_hmac_sha2_init (desc );
322+ memcpy (ctx -> param , p .u8 , ds );
323+ p .u8 += ds ;
324+ ctx -> buflen [0 ] = get_unaligned (p .u64 ++ );
325+ if (ds == SHA512_DIGEST_SIZE )
326+ ctx -> buflen [1 ] = get_unaligned (p .u64 );
327+ if (ctx -> buflen [0 ] | ctx -> buflen [1 ])
328+ ctx -> gr0 .ikp = 1 ;
329+ return err ;
330+ }
331+
332+ #define S390_HMAC_SHA2_ALG (x , ss ) { \
277333 .fc = CPACF_KMAC_HMAC_SHA_##x, \
278334 .alg = { \
279335 .init = s390_hmac_sha2_init, \
280336 .update = s390_hmac_sha2_update, \
281- .final = s390_hmac_sha2_final , \
337+ .finup = s390_hmac_sha2_finup , \
282338 .digest = s390_hmac_sha2_digest, \
283339 .setkey = s390_hmac_sha2_setkey, \
340+ .export = s390_hmac_export, \
341+ .import = s390_hmac_import, \
284342 .descsize = sizeof(struct s390_kmac_sha2_ctx), \
285343 .halg = { \
344+ .statesize = ss, \
286345 .digestsize = SHA##x##_DIGEST_SIZE, \
287346 .base = { \
288347 .cra_name = "hmac(sha" #x ")", \
289348 .cra_driver_name = "hmac_s390_sha" #x, \
290349 .cra_blocksize = SHA##x##_BLOCK_SIZE, \
291350 .cra_priority = 400, \
351+ .cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY | \
352+ CRYPTO_AHASH_ALG_FINUP_MAX, \
292353 .cra_ctxsize = sizeof(struct s390_hmac_ctx), \
293354 .cra_module = THIS_MODULE, \
294355 }, \
@@ -301,10 +362,10 @@ static struct s390_hmac_alg {
301362 unsigned int fc ;
302363 struct shash_alg alg ;
303364} s390_hmac_algs [] = {
304- S390_HMAC_SHA2_ALG (224 ),
305- S390_HMAC_SHA2_ALG (256 ),
306- S390_HMAC_SHA2_ALG (384 ),
307- S390_HMAC_SHA2_ALG (512 ),
365+ S390_HMAC_SHA2_ALG (224 , sizeof ( struct crypto_sha256_state ) ),
366+ S390_HMAC_SHA2_ALG (256 , sizeof ( struct crypto_sha256_state ) ),
367+ S390_HMAC_SHA2_ALG (384 , SHA512_STATE_SIZE ),
368+ S390_HMAC_SHA2_ALG (512 , SHA512_STATE_SIZE ),
308369};
309370
310371static __always_inline void _s390_hmac_algs_unregister (void )
0 commit comments