1301422e3SAntoine Tenart // SPDX-License-Identifier: GPL-2.0 21b44c5a6SAntoine Ténart /* 31b44c5a6SAntoine Ténart * Copyright (C) 2017 Marvell 41b44c5a6SAntoine Ténart * 51b44c5a6SAntoine Ténart * Antoine Tenart <antoine.tenart@free-electrons.com> 61b44c5a6SAntoine Ténart */ 71b44c5a6SAntoine Ténart 8b98687bbSPascal van Leeuwen #include <crypto/aes.h> 9aed3731eSAntoine Ténart #include <crypto/hmac.h> 10293f89cfSOfer Heifetz #include <crypto/md5.h> 11a24d22b2SEric Biggers #include <crypto/sha1.h> 12a24d22b2SEric Biggers #include <crypto/sha2.h> 13aaf5a383SPascal van Leeuwen #include <crypto/sha3.h> 1438f21b4bSPascal van Leeuwen #include <crypto/skcipher.h> 150f2bc131SPascal van Leeuwen #include <crypto/sm3.h> 160eb76ba2SArd Biesheuvel #include <crypto/internal/cipher.h> 171b44c5a6SAntoine Ténart #include <linux/device.h> 181b44c5a6SAntoine Ténart #include <linux/dma-mapping.h> 191b44c5a6SAntoine Ténart #include <linux/dmapool.h> 201b44c5a6SAntoine Ténart 211b44c5a6SAntoine Ténart #include "safexcel.h" 221b44c5a6SAntoine Ténart 231b44c5a6SAntoine Ténart struct safexcel_ahash_ctx { 241b44c5a6SAntoine Ténart struct safexcel_context base; 251b44c5a6SAntoine Ténart 261b44c5a6SAntoine Ténart u32 alg; 27b98687bbSPascal van Leeuwen u8 key_sz; 2838f21b4bSPascal van Leeuwen bool cbcmac; 29aaf5a383SPascal van Leeuwen bool do_fallback; 30aaf5a383SPascal van Leeuwen bool fb_init_done; 316c1c09b3SPascal van Leeuwen bool fb_do_setkey; 321b44c5a6SAntoine Ténart 33*320406cbSPeter Harliman Liem struct crypto_aes_ctx *aes; 34aaf5a383SPascal van Leeuwen struct crypto_ahash *fback; 356c1c09b3SPascal van Leeuwen struct crypto_shash *shpre; 366c1c09b3SPascal van Leeuwen struct shash_desc *shdesc; 371b44c5a6SAntoine Ténart }; 381b44c5a6SAntoine Ténart 391b44c5a6SAntoine Ténart struct safexcel_ahash_req { 401b44c5a6SAntoine Ténart bool last_req; 411b44c5a6SAntoine Ténart bool finish; 421b44c5a6SAntoine Ténart bool hmac; 431eb7b403SOfer Heifetz bool needs_inv; 4485b36ee8SPascal van Leeuwen bool hmac_zlen; 4585b36ee8SPascal van Leeuwen bool len_is_le; 46b98687bbSPascal van Leeuwen bool not_first; 47b98687bbSPascal van Leeuwen bool xcbcmac; 481b44c5a6SAntoine Ténart 49c957f8b3SAntoine Ténart int nents; 50b8592027SOfer Heifetz dma_addr_t result_dma; 51c957f8b3SAntoine Ténart 52b869648cSAntoine Tenart u32 digest; 53b869648cSAntoine Tenart 5441abed7dSPascal van Leeuwen u8 state_sz; /* expected state size, only set once */ 5541abed7dSPascal van Leeuwen u8 block_sz; /* block size, only set once */ 566c1c09b3SPascal van Leeuwen u8 digest_sz; /* output digest size, only set once */ 5713a1bb93SPascal van Leeuwen __le32 state[SHA3_512_BLOCK_SIZE / 5813a1bb93SPascal van Leeuwen sizeof(__le32)] __aligned(sizeof(__le32)); 591b44c5a6SAntoine Ténart 6031fb084cSPascal van Leeuwen u64 len; 6131fb084cSPascal van Leeuwen u64 processed; 621b44c5a6SAntoine Ténart 6341abed7dSPascal van Leeuwen u8 cache[HASH_CACHE_SIZE] __aligned(sizeof(u32)); 64cff9a175SAntoine Tenart dma_addr_t cache_dma; 65cff9a175SAntoine Tenart unsigned int cache_sz; 66cff9a175SAntoine Tenart 6741abed7dSPascal van Leeuwen u8 cache_next[HASH_CACHE_SIZE] __aligned(sizeof(u32)); 681b44c5a6SAntoine Ténart }; 691b44c5a6SAntoine Ténart 70b460edb6SAntoine Tenart static inline u64 safexcel_queued_len(struct safexcel_ahash_req *req) 71b460edb6SAntoine Tenart { 7231fb084cSPascal van Leeuwen return req->len - req->processed; 73b460edb6SAntoine Tenart } 74b460edb6SAntoine Tenart 751b44c5a6SAntoine Ténart static void safexcel_hash_token(struct safexcel_command_desc *cdesc, 76b98687bbSPascal van Leeuwen u32 input_length, u32 result_length, 7738f21b4bSPascal van Leeuwen bool cbcmac) 781b44c5a6SAntoine Ténart { 791b44c5a6SAntoine Ténart struct safexcel_token *token = 801b44c5a6SAntoine Ténart (struct safexcel_token *)cdesc->control_data.token; 811b44c5a6SAntoine Ténart 821b44c5a6SAntoine Ténart token[0].opcode = EIP197_TOKEN_OPCODE_DIRECTION; 831b44c5a6SAntoine Ténart token[0].packet_length = input_length; 841b44c5a6SAntoine Ténart token[0].instructions = EIP197_TOKEN_INS_TYPE_HASH; 851b44c5a6SAntoine Ténart 86b98687bbSPascal van Leeuwen input_length &= 15; 8738f21b4bSPascal van Leeuwen if (unlikely(cbcmac && input_length)) { 88098e51e5SPascal van Leeuwen token[0].stat = 0; 891b44c5a6SAntoine Ténart token[1].opcode = EIP197_TOKEN_OPCODE_INSERT; 90b98687bbSPascal van Leeuwen token[1].packet_length = 16 - input_length; 91b98687bbSPascal van Leeuwen token[1].stat = EIP197_TOKEN_STAT_LAST_HASH; 92b98687bbSPascal van Leeuwen token[1].instructions = EIP197_TOKEN_INS_TYPE_HASH; 93b98687bbSPascal van Leeuwen } else { 94b98687bbSPascal van Leeuwen token[0].stat = EIP197_TOKEN_STAT_LAST_HASH; 95098e51e5SPascal van Leeuwen eip197_noop_token(&token[1]); 96b98687bbSPascal van Leeuwen } 97b98687bbSPascal van Leeuwen 98b98687bbSPascal van Leeuwen token[2].opcode = EIP197_TOKEN_OPCODE_INSERT; 99b98687bbSPascal van Leeuwen token[2].stat = EIP197_TOKEN_STAT_LAST_HASH | 1001b44c5a6SAntoine Ténart EIP197_TOKEN_STAT_LAST_PACKET; 101b98687bbSPascal van Leeuwen token[2].packet_length = result_length; 102b98687bbSPascal van Leeuwen token[2].instructions = EIP197_TOKEN_INS_TYPE_OUTPUT | 1031b44c5a6SAntoine Ténart EIP197_TOKEN_INS_INSERT_HASH_DIGEST; 104098e51e5SPascal van Leeuwen 105098e51e5SPascal van Leeuwen eip197_noop_token(&token[3]); 1061b44c5a6SAntoine Ténart } 1071b44c5a6SAntoine Ténart 1081b44c5a6SAntoine Ténart static void safexcel_context_control(struct safexcel_ahash_ctx *ctx, 1091b44c5a6SAntoine Ténart struct safexcel_ahash_req *req, 11041abed7dSPascal van Leeuwen struct safexcel_command_desc *cdesc) 1111b44c5a6SAntoine Ténart { 11218e51895SHerbert Xu struct safexcel_crypto_priv *priv = ctx->base.priv; 11341abed7dSPascal van Leeuwen u64 count = 0; 1141b44c5a6SAntoine Ténart 115a7cf8658SPascal van Leeuwen cdesc->control_data.control0 = ctx->alg; 116098e51e5SPascal van Leeuwen cdesc->control_data.control1 = 0; 117dc5268b6SPascal van Leeuwen 1181b44c5a6SAntoine Ténart /* 1191b44c5a6SAntoine Ténart * Copy the input digest if needed, and setup the context 1201b44c5a6SAntoine Ténart * fields. Do this now as we need it to setup the first command 1211b44c5a6SAntoine Ténart * descriptor. 1221b44c5a6SAntoine Ténart */ 123a7cf8658SPascal van Leeuwen if (unlikely(req->digest == CONTEXT_CONTROL_DIGEST_XCM)) { 124b98687bbSPascal van Leeuwen if (req->xcbcmac) 12578cf1c8bSHerbert Xu memcpy(ctx->base.ctxr->data, &ctx->base.ipad, ctx->key_sz); 126b98687bbSPascal van Leeuwen else 127b98687bbSPascal van Leeuwen memcpy(ctx->base.ctxr->data, req->state, req->state_sz); 128a7cf8658SPascal van Leeuwen 129b98687bbSPascal van Leeuwen if (!req->finish && req->xcbcmac) 130b98687bbSPascal van Leeuwen cdesc->control_data.control0 |= 131b98687bbSPascal van Leeuwen CONTEXT_CONTROL_DIGEST_XCM | 132a7cf8658SPascal van Leeuwen CONTEXT_CONTROL_TYPE_HASH_OUT | 133b98687bbSPascal van Leeuwen CONTEXT_CONTROL_NO_FINISH_HASH | 134b98687bbSPascal van Leeuwen CONTEXT_CONTROL_SIZE(req->state_sz / 135b98687bbSPascal van Leeuwen sizeof(u32)); 136b98687bbSPascal van Leeuwen else 137b98687bbSPascal van Leeuwen cdesc->control_data.control0 |= 138b98687bbSPascal van Leeuwen CONTEXT_CONTROL_DIGEST_XCM | 139b98687bbSPascal van Leeuwen CONTEXT_CONTROL_TYPE_HASH_OUT | 140b98687bbSPascal van Leeuwen CONTEXT_CONTROL_SIZE(req->state_sz / 141b98687bbSPascal van Leeuwen sizeof(u32)); 142a7cf8658SPascal van Leeuwen return; 143a7cf8658SPascal van Leeuwen } else if (!req->processed) { 14441abed7dSPascal van Leeuwen /* First - and possibly only - block of basic hash only */ 145b98687bbSPascal van Leeuwen if (req->finish) 146a7cf8658SPascal van Leeuwen cdesc->control_data.control0 |= req->digest | 14741abed7dSPascal van Leeuwen CONTEXT_CONTROL_TYPE_HASH_OUT | 14841abed7dSPascal van Leeuwen CONTEXT_CONTROL_RESTART_HASH | 14941abed7dSPascal van Leeuwen /* ensure its not 0! */ 15041abed7dSPascal van Leeuwen CONTEXT_CONTROL_SIZE(1); 151b98687bbSPascal van Leeuwen else 152a7cf8658SPascal van Leeuwen cdesc->control_data.control0 |= req->digest | 15341abed7dSPascal van Leeuwen CONTEXT_CONTROL_TYPE_HASH_OUT | 15441abed7dSPascal van Leeuwen CONTEXT_CONTROL_RESTART_HASH | 15541abed7dSPascal van Leeuwen CONTEXT_CONTROL_NO_FINISH_HASH | 15641abed7dSPascal van Leeuwen /* ensure its not 0! */ 15741abed7dSPascal van Leeuwen CONTEXT_CONTROL_SIZE(1); 15841abed7dSPascal van Leeuwen return; 15941abed7dSPascal van Leeuwen } 16041abed7dSPascal van Leeuwen 16141abed7dSPascal van Leeuwen /* Hash continuation or HMAC, setup (inner) digest from state */ 16241abed7dSPascal van Leeuwen memcpy(ctx->base.ctxr->data, req->state, req->state_sz); 1631b44c5a6SAntoine Ténart 164b460edb6SAntoine Tenart if (req->finish) { 16541abed7dSPascal van Leeuwen /* Compute digest count for hash/HMAC finish operations */ 16641abed7dSPascal van Leeuwen if ((req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) || 16731fb084cSPascal van Leeuwen req->hmac_zlen || (req->processed != req->block_sz)) { 16831fb084cSPascal van Leeuwen count = req->processed / EIP197_COUNTER_BLOCK_SIZE; 169b460edb6SAntoine Tenart 17041abed7dSPascal van Leeuwen /* This is a hardware limitation, as the 171b460edb6SAntoine Tenart * counter must fit into an u32. This represents 17241abed7dSPascal van Leeuwen * a fairly big amount of input data, so we 173b460edb6SAntoine Tenart * shouldn't see this. 174b460edb6SAntoine Tenart */ 17541abed7dSPascal van Leeuwen if (unlikely(count & 0xffffffff00000000ULL)) { 176b460edb6SAntoine Tenart dev_warn(priv->dev, 177b460edb6SAntoine Tenart "Input data is too big\n"); 178b460edb6SAntoine Tenart return; 179b460edb6SAntoine Tenart } 180b460edb6SAntoine Tenart } 1811b44c5a6SAntoine Ténart 18241abed7dSPascal van Leeuwen if ((req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) || 18385b36ee8SPascal van Leeuwen /* Special case: zero length HMAC */ 18485b36ee8SPascal van Leeuwen req->hmac_zlen || 18541abed7dSPascal van Leeuwen /* PE HW < 4.4 cannot do HMAC continue, fake using hash */ 18631fb084cSPascal van Leeuwen (req->processed != req->block_sz)) { 18741abed7dSPascal van Leeuwen /* Basic hash continue operation, need digest + cnt */ 18841abed7dSPascal van Leeuwen cdesc->control_data.control0 |= 18941abed7dSPascal van Leeuwen CONTEXT_CONTROL_SIZE((req->state_sz >> 2) + 1) | 19041abed7dSPascal van Leeuwen CONTEXT_CONTROL_TYPE_HASH_OUT | 19141abed7dSPascal van Leeuwen CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 19285b36ee8SPascal van Leeuwen /* For zero-len HMAC, don't finalize, already padded! */ 19385b36ee8SPascal van Leeuwen if (req->hmac_zlen) 19485b36ee8SPascal van Leeuwen cdesc->control_data.control0 |= 19585b36ee8SPascal van Leeuwen CONTEXT_CONTROL_NO_FINISH_HASH; 19641abed7dSPascal van Leeuwen cdesc->control_data.control1 |= 19741abed7dSPascal van Leeuwen CONTEXT_CONTROL_DIGEST_CNT; 19841abed7dSPascal van Leeuwen ctx->base.ctxr->data[req->state_sz >> 2] = 19941abed7dSPascal van Leeuwen cpu_to_le32(count); 20041abed7dSPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 20185b36ee8SPascal van Leeuwen 20285b36ee8SPascal van Leeuwen /* Clear zero-length HMAC flag for next operation! */ 20385b36ee8SPascal van Leeuwen req->hmac_zlen = false; 20441abed7dSPascal van Leeuwen } else { /* HMAC */ 20541abed7dSPascal van Leeuwen /* Need outer digest for HMAC finalization */ 20641abed7dSPascal van Leeuwen memcpy(ctx->base.ctxr->data + (req->state_sz >> 2), 20778cf1c8bSHerbert Xu &ctx->base.opad, req->state_sz); 20841abed7dSPascal van Leeuwen 20941abed7dSPascal van Leeuwen /* Single pass HMAC - no digest count */ 21041abed7dSPascal van Leeuwen cdesc->control_data.control0 |= 21141abed7dSPascal van Leeuwen CONTEXT_CONTROL_SIZE(req->state_sz >> 1) | 21241abed7dSPascal van Leeuwen CONTEXT_CONTROL_TYPE_HASH_OUT | 21341abed7dSPascal van Leeuwen CONTEXT_CONTROL_DIGEST_HMAC; 21441abed7dSPascal van Leeuwen } 21541abed7dSPascal van Leeuwen } else { /* Hash continuation, do not finish yet */ 21641abed7dSPascal van Leeuwen cdesc->control_data.control0 |= 21741abed7dSPascal van Leeuwen CONTEXT_CONTROL_SIZE(req->state_sz >> 2) | 21841abed7dSPascal van Leeuwen CONTEXT_CONTROL_DIGEST_PRECOMPUTED | 21941abed7dSPascal van Leeuwen CONTEXT_CONTROL_TYPE_HASH_OUT | 22041abed7dSPascal van Leeuwen CONTEXT_CONTROL_NO_FINISH_HASH; 2211b44c5a6SAntoine Ténart } 2221b44c5a6SAntoine Ténart } 2231b44c5a6SAntoine Ténart 22441abed7dSPascal van Leeuwen static int safexcel_ahash_enqueue(struct ahash_request *areq); 22541abed7dSPascal van Leeuwen 22641abed7dSPascal van Leeuwen static int safexcel_handle_req_result(struct safexcel_crypto_priv *priv, 22741abed7dSPascal van Leeuwen int ring, 2281b44c5a6SAntoine Ténart struct crypto_async_request *async, 2291b44c5a6SAntoine Ténart bool *should_complete, int *ret) 2301b44c5a6SAntoine Ténart { 2311b44c5a6SAntoine Ténart struct safexcel_result_desc *rdesc; 2321b44c5a6SAntoine Ténart struct ahash_request *areq = ahash_request_cast(async); 2331b44c5a6SAntoine Ténart struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); 2341b44c5a6SAntoine Ténart struct safexcel_ahash_req *sreq = ahash_request_ctx(areq); 23541abed7dSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(ahash); 236b460edb6SAntoine Tenart u64 cache_len; 2371b44c5a6SAntoine Ténart 2381b44c5a6SAntoine Ténart *ret = 0; 2391b44c5a6SAntoine Ténart 2401b44c5a6SAntoine Ténart rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr); 2411b44c5a6SAntoine Ténart if (IS_ERR(rdesc)) { 2421b44c5a6SAntoine Ténart dev_err(priv->dev, 2431b44c5a6SAntoine Ténart "hash: result: could not retrieve the result descriptor\n"); 2441b44c5a6SAntoine Ténart *ret = PTR_ERR(rdesc); 245bdfd1909SAntoine Tenart } else { 246bdfd1909SAntoine Tenart *ret = safexcel_rdesc_check_errors(priv, rdesc); 2471b44c5a6SAntoine Ténart } 2481b44c5a6SAntoine Ténart 2491b44c5a6SAntoine Ténart safexcel_complete(priv, ring); 2501b44c5a6SAntoine Ténart 251c957f8b3SAntoine Ténart if (sreq->nents) { 252c957f8b3SAntoine Ténart dma_unmap_sg(priv->dev, areq->src, sreq->nents, DMA_TO_DEVICE); 253c957f8b3SAntoine Ténart sreq->nents = 0; 254c957f8b3SAntoine Ténart } 2551b44c5a6SAntoine Ténart 256b8592027SOfer Heifetz if (sreq->result_dma) { 2576c1c09b3SPascal van Leeuwen dma_unmap_single(priv->dev, sreq->result_dma, sreq->digest_sz, 258b8592027SOfer Heifetz DMA_FROM_DEVICE); 259b8592027SOfer Heifetz sreq->result_dma = 0; 260b8592027SOfer Heifetz } 261b8592027SOfer Heifetz 262cff9a175SAntoine Tenart if (sreq->cache_dma) { 263cff9a175SAntoine Tenart dma_unmap_single(priv->dev, sreq->cache_dma, sreq->cache_sz, 264cff9a175SAntoine Tenart DMA_TO_DEVICE); 265cff9a175SAntoine Tenart sreq->cache_dma = 0; 266aa524286SAntoine Tenart sreq->cache_sz = 0; 267cff9a175SAntoine Tenart } 2681b44c5a6SAntoine Ténart 26941abed7dSPascal van Leeuwen if (sreq->finish) { 27041abed7dSPascal van Leeuwen if (sreq->hmac && 27141abed7dSPascal van Leeuwen (sreq->digest != CONTEXT_CONTROL_DIGEST_HMAC)) { 27241abed7dSPascal van Leeuwen /* Faking HMAC using hash - need to do outer hash */ 27341abed7dSPascal van Leeuwen memcpy(sreq->cache, sreq->state, 27441abed7dSPascal van Leeuwen crypto_ahash_digestsize(ahash)); 27541abed7dSPascal van Leeuwen 27678cf1c8bSHerbert Xu memcpy(sreq->state, &ctx->base.opad, sreq->digest_sz); 27741abed7dSPascal van Leeuwen 27831fb084cSPascal van Leeuwen sreq->len = sreq->block_sz + 27941abed7dSPascal van Leeuwen crypto_ahash_digestsize(ahash); 28031fb084cSPascal van Leeuwen sreq->processed = sreq->block_sz; 28141abed7dSPascal van Leeuwen sreq->hmac = 0; 28241abed7dSPascal van Leeuwen 283177e358cSPascal van Leeuwen if (priv->flags & EIP197_TRC_CACHE) 28441abed7dSPascal van Leeuwen ctx->base.needs_inv = true; 28541abed7dSPascal van Leeuwen areq->nbytes = 0; 28641abed7dSPascal van Leeuwen safexcel_ahash_enqueue(areq); 28741abed7dSPascal van Leeuwen 28841abed7dSPascal van Leeuwen *should_complete = false; /* Not done yet */ 28941abed7dSPascal van Leeuwen return 1; 29041abed7dSPascal van Leeuwen } 29141abed7dSPascal van Leeuwen 292b98687bbSPascal van Leeuwen if (unlikely(sreq->digest == CONTEXT_CONTROL_DIGEST_XCM && 293b98687bbSPascal van Leeuwen ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_CRC32)) { 294a7cf8658SPascal van Leeuwen /* Undo final XOR with 0xffffffff ...*/ 29513a1bb93SPascal van Leeuwen *(__le32 *)areq->result = ~sreq->state[0]; 296a7cf8658SPascal van Leeuwen } else { 297b89a8159SAntoine Tenart memcpy(areq->result, sreq->state, 298b89a8159SAntoine Tenart crypto_ahash_digestsize(ahash)); 29941abed7dSPascal van Leeuwen } 300a7cf8658SPascal van Leeuwen } 301b89a8159SAntoine Tenart 302b460edb6SAntoine Tenart cache_len = safexcel_queued_len(sreq); 3031b44c5a6SAntoine Ténart if (cache_len) 3041b44c5a6SAntoine Ténart memcpy(sreq->cache, sreq->cache_next, cache_len); 3051b44c5a6SAntoine Ténart 3061b44c5a6SAntoine Ténart *should_complete = true; 3071b44c5a6SAntoine Ténart 3081b44c5a6SAntoine Ténart return 1; 3091b44c5a6SAntoine Ténart } 3101b44c5a6SAntoine Ténart 3111eb7b403SOfer Heifetz static int safexcel_ahash_send_req(struct crypto_async_request *async, int ring, 3121eb7b403SOfer Heifetz int *commands, int *results) 3131b44c5a6SAntoine Ténart { 3141b44c5a6SAntoine Ténart struct ahash_request *areq = ahash_request_cast(async); 3151b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 3161b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 31718e51895SHerbert Xu struct safexcel_crypto_priv *priv = ctx->base.priv; 3181b44c5a6SAntoine Ténart struct safexcel_command_desc *cdesc, *first_cdesc = NULL; 3191b44c5a6SAntoine Ténart struct safexcel_result_desc *rdesc; 3201b44c5a6SAntoine Ténart struct scatterlist *sg; 321098e51e5SPascal van Leeuwen struct safexcel_token *dmmy; 3226c1c09b3SPascal van Leeuwen int i, extra = 0, n_cdesc = 0, ret = 0, cache_len, skip = 0; 323b98687bbSPascal van Leeuwen u64 queued, len; 3241b44c5a6SAntoine Ténart 325b98687bbSPascal van Leeuwen queued = safexcel_queued_len(req); 32641abed7dSPascal van Leeuwen if (queued <= HASH_CACHE_SIZE) 3271b44c5a6SAntoine Ténart cache_len = queued; 3281b44c5a6SAntoine Ténart else 3291b44c5a6SAntoine Ténart cache_len = queued - areq->nbytes; 3301b44c5a6SAntoine Ténart 33141abed7dSPascal van Leeuwen if (!req->finish && !req->last_req) { 332809778e0SAntoine Ténart /* If this is not the last request and the queued data does not 33341abed7dSPascal van Leeuwen * fit into full cache blocks, cache it for the next send call. 3341b44c5a6SAntoine Ténart */ 33541abed7dSPascal van Leeuwen extra = queued & (HASH_CACHE_SIZE - 1); 336082ec2d4SAntoine Tenart 337809778e0SAntoine Ténart /* If this is not the last request and the queued data 338809778e0SAntoine Ténart * is a multiple of a block, cache the last one for now. 339809778e0SAntoine Ténart */ 340dd4306a6SAntoine Tenart if (!extra) 34141abed7dSPascal van Leeuwen extra = HASH_CACHE_SIZE; 342809778e0SAntoine Ténart 3431b44c5a6SAntoine Ténart sg_pcopy_to_buffer(areq->src, sg_nents(areq->src), 344809778e0SAntoine Ténart req->cache_next, extra, 345809778e0SAntoine Ténart areq->nbytes - extra); 3461b44c5a6SAntoine Ténart 3471b44c5a6SAntoine Ténart queued -= extra; 348dc5268b6SPascal van Leeuwen 349dc5268b6SPascal van Leeuwen if (!queued) { 350dc5268b6SPascal van Leeuwen *commands = 0; 351dc5268b6SPascal van Leeuwen *results = 0; 352dc5268b6SPascal van Leeuwen return 0; 353dc5268b6SPascal van Leeuwen } 354b98687bbSPascal van Leeuwen 355b98687bbSPascal van Leeuwen extra = 0; 356809778e0SAntoine Ténart } 3571b44c5a6SAntoine Ténart 358b98687bbSPascal van Leeuwen if (unlikely(req->xcbcmac && req->processed > AES_BLOCK_SIZE)) { 359b98687bbSPascal van Leeuwen if (unlikely(cache_len < AES_BLOCK_SIZE)) { 360b98687bbSPascal van Leeuwen /* 361b98687bbSPascal van Leeuwen * Cache contains less than 1 full block, complete. 362b98687bbSPascal van Leeuwen */ 363b98687bbSPascal van Leeuwen extra = AES_BLOCK_SIZE - cache_len; 364b98687bbSPascal van Leeuwen if (queued > cache_len) { 365b98687bbSPascal van Leeuwen /* More data follows: borrow bytes */ 366b98687bbSPascal van Leeuwen u64 tmp = queued - cache_len; 367b98687bbSPascal van Leeuwen 368b98687bbSPascal van Leeuwen skip = min_t(u64, tmp, extra); 369b98687bbSPascal van Leeuwen sg_pcopy_to_buffer(areq->src, 370b98687bbSPascal van Leeuwen sg_nents(areq->src), 371b98687bbSPascal van Leeuwen req->cache + cache_len, 372b98687bbSPascal van Leeuwen skip, 0); 373b98687bbSPascal van Leeuwen } 374b98687bbSPascal van Leeuwen extra -= skip; 375b98687bbSPascal van Leeuwen memset(req->cache + cache_len + skip, 0, extra); 37638f21b4bSPascal van Leeuwen if (!ctx->cbcmac && extra) { 37738f21b4bSPascal van Leeuwen // 10- padding for XCBCMAC & CMAC 37838f21b4bSPascal van Leeuwen req->cache[cache_len + skip] = 0x80; 37938f21b4bSPascal van Leeuwen // HW will use K2 iso K3 - compensate! 38078cf1c8bSHerbert Xu for (i = 0; i < AES_BLOCK_SIZE / 4; i++) { 38178cf1c8bSHerbert Xu u32 *cache = (void *)req->cache; 38278cf1c8bSHerbert Xu u32 *ipad = ctx->base.ipad.word; 38378cf1c8bSHerbert Xu u32 x; 38478cf1c8bSHerbert Xu 38578cf1c8bSHerbert Xu x = ipad[i] ^ ipad[i + 4]; 38666459340SPeter Harliman Liem cache[i] ^= swab32(x); 38778cf1c8bSHerbert Xu } 38838f21b4bSPascal van Leeuwen } 389b98687bbSPascal van Leeuwen cache_len = AES_BLOCK_SIZE; 390b98687bbSPascal van Leeuwen queued = queued + extra; 391b98687bbSPascal van Leeuwen } 392b98687bbSPascal van Leeuwen 393b98687bbSPascal van Leeuwen /* XCBC continue: XOR previous result into 1st word */ 394b98687bbSPascal van Leeuwen crypto_xor(req->cache, (const u8 *)req->state, AES_BLOCK_SIZE); 395b98687bbSPascal van Leeuwen } 396b98687bbSPascal van Leeuwen 397b98687bbSPascal van Leeuwen len = queued; 3981b44c5a6SAntoine Ténart /* Add a command descriptor for the cached data, if any */ 3991b44c5a6SAntoine Ténart if (cache_len) { 400cff9a175SAntoine Tenart req->cache_dma = dma_map_single(priv->dev, req->cache, 4011b44c5a6SAntoine Ténart cache_len, DMA_TO_DEVICE); 4029744fec9SOfer Heifetz if (dma_mapping_error(priv->dev, req->cache_dma)) 403cff9a175SAntoine Tenart return -EINVAL; 4041b44c5a6SAntoine Ténart 405cff9a175SAntoine Tenart req->cache_sz = cache_len; 4061b44c5a6SAntoine Ténart first_cdesc = safexcel_add_cdesc(priv, ring, 1, 4071b44c5a6SAntoine Ténart (cache_len == len), 408b98687bbSPascal van Leeuwen req->cache_dma, cache_len, 409098e51e5SPascal van Leeuwen len, ctx->base.ctxr_dma, 410098e51e5SPascal van Leeuwen &dmmy); 4111b44c5a6SAntoine Ténart if (IS_ERR(first_cdesc)) { 4121b44c5a6SAntoine Ténart ret = PTR_ERR(first_cdesc); 4131b44c5a6SAntoine Ténart goto unmap_cache; 4141b44c5a6SAntoine Ténart } 4151b44c5a6SAntoine Ténart n_cdesc++; 4161b44c5a6SAntoine Ténart 4171b44c5a6SAntoine Ténart queued -= cache_len; 4181b44c5a6SAntoine Ténart if (!queued) 4191b44c5a6SAntoine Ténart goto send_command; 4201b44c5a6SAntoine Ténart } 4211b44c5a6SAntoine Ténart 4221b44c5a6SAntoine Ténart /* Now handle the current ahash request buffer(s) */ 42341abed7dSPascal van Leeuwen req->nents = dma_map_sg(priv->dev, areq->src, 42441abed7dSPascal van Leeuwen sg_nents_for_len(areq->src, 42541abed7dSPascal van Leeuwen areq->nbytes), 4261b44c5a6SAntoine Ténart DMA_TO_DEVICE); 427c957f8b3SAntoine Ténart if (!req->nents) { 4281b44c5a6SAntoine Ténart ret = -ENOMEM; 4291b44c5a6SAntoine Ténart goto cdesc_rollback; 4301b44c5a6SAntoine Ténart } 4311b44c5a6SAntoine Ténart 432c957f8b3SAntoine Ténart for_each_sg(areq->src, sg, req->nents, i) { 4331b44c5a6SAntoine Ténart int sglen = sg_dma_len(sg); 4341b44c5a6SAntoine Ténart 435b98687bbSPascal van Leeuwen if (unlikely(sglen <= skip)) { 436b98687bbSPascal van Leeuwen skip -= sglen; 437b98687bbSPascal van Leeuwen continue; 438b98687bbSPascal van Leeuwen } 439b98687bbSPascal van Leeuwen 4401b44c5a6SAntoine Ténart /* Do not overflow the request */ 441b98687bbSPascal van Leeuwen if ((queued + skip) <= sglen) 4421b44c5a6SAntoine Ténart sglen = queued; 443b98687bbSPascal van Leeuwen else 444b98687bbSPascal van Leeuwen sglen -= skip; 4451b44c5a6SAntoine Ténart 4461b44c5a6SAntoine Ténart cdesc = safexcel_add_cdesc(priv, ring, !n_cdesc, 44741abed7dSPascal van Leeuwen !(queued - sglen), 448b98687bbSPascal van Leeuwen sg_dma_address(sg) + skip, sglen, 449098e51e5SPascal van Leeuwen len, ctx->base.ctxr_dma, &dmmy); 4501b44c5a6SAntoine Ténart if (IS_ERR(cdesc)) { 4511b44c5a6SAntoine Ténart ret = PTR_ERR(cdesc); 45257433b58SAntoine Tenart goto unmap_sg; 4531b44c5a6SAntoine Ténart } 4541b44c5a6SAntoine Ténart 455b98687bbSPascal van Leeuwen if (!n_cdesc) 4561b44c5a6SAntoine Ténart first_cdesc = cdesc; 457b98687bbSPascal van Leeuwen n_cdesc++; 4581b44c5a6SAntoine Ténart 4591b44c5a6SAntoine Ténart queued -= sglen; 4601b44c5a6SAntoine Ténart if (!queued) 4611b44c5a6SAntoine Ténart break; 462b98687bbSPascal van Leeuwen skip = 0; 4631b44c5a6SAntoine Ténart } 4641b44c5a6SAntoine Ténart 4651b44c5a6SAntoine Ténart send_command: 4661b44c5a6SAntoine Ténart /* Setup the context options */ 46741abed7dSPascal van Leeuwen safexcel_context_control(ctx, req, first_cdesc); 4681b44c5a6SAntoine Ténart 4696c1c09b3SPascal van Leeuwen /* Add the token */ 4706c1c09b3SPascal van Leeuwen safexcel_hash_token(first_cdesc, len, req->digest_sz, ctx->cbcmac); 4711b44c5a6SAntoine Ténart 4726c1c09b3SPascal van Leeuwen req->result_dma = dma_map_single(priv->dev, req->state, req->digest_sz, 473b8592027SOfer Heifetz DMA_FROM_DEVICE); 474b8592027SOfer Heifetz if (dma_mapping_error(priv->dev, req->result_dma)) { 4751b44c5a6SAntoine Ténart ret = -EINVAL; 47657433b58SAntoine Tenart goto unmap_sg; 4771b44c5a6SAntoine Ténart } 4781b44c5a6SAntoine Ténart 4791b44c5a6SAntoine Ténart /* Add a result descriptor */ 480b8592027SOfer Heifetz rdesc = safexcel_add_rdesc(priv, ring, 1, 1, req->result_dma, 4816c1c09b3SPascal van Leeuwen req->digest_sz); 4821b44c5a6SAntoine Ténart if (IS_ERR(rdesc)) { 4831b44c5a6SAntoine Ténart ret = PTR_ERR(rdesc); 48457240a78SAntoine Tenart goto unmap_result; 4851b44c5a6SAntoine Ténart } 4861b44c5a6SAntoine Ténart 4879744fec9SOfer Heifetz safexcel_rdr_req_set(priv, ring, rdesc, &areq->base); 4881b44c5a6SAntoine Ténart 489b98687bbSPascal van Leeuwen req->processed += len - extra; 490b460edb6SAntoine Tenart 4911b44c5a6SAntoine Ténart *commands = n_cdesc; 4921b44c5a6SAntoine Ténart *results = 1; 4931b44c5a6SAntoine Ténart return 0; 4941b44c5a6SAntoine Ténart 49557240a78SAntoine Tenart unmap_result: 4966c1c09b3SPascal van Leeuwen dma_unmap_single(priv->dev, req->result_dma, req->digest_sz, 49757433b58SAntoine Tenart DMA_FROM_DEVICE); 49857433b58SAntoine Tenart unmap_sg: 499b98687bbSPascal van Leeuwen if (req->nents) { 50057240a78SAntoine Tenart dma_unmap_sg(priv->dev, areq->src, req->nents, DMA_TO_DEVICE); 501b98687bbSPascal van Leeuwen req->nents = 0; 502b98687bbSPascal van Leeuwen } 5031b44c5a6SAntoine Ténart cdesc_rollback: 5041b44c5a6SAntoine Ténart for (i = 0; i < n_cdesc; i++) 5051b44c5a6SAntoine Ténart safexcel_ring_rollback_wptr(priv, &priv->ring[ring].cdr); 5061b44c5a6SAntoine Ténart unmap_cache: 507cff9a175SAntoine Tenart if (req->cache_dma) { 508cff9a175SAntoine Tenart dma_unmap_single(priv->dev, req->cache_dma, req->cache_sz, 509cff9a175SAntoine Tenart DMA_TO_DEVICE); 510aa524286SAntoine Tenart req->cache_dma = 0; 511cff9a175SAntoine Tenart req->cache_sz = 0; 5121b44c5a6SAntoine Ténart } 5131b44c5a6SAntoine Ténart 5141b44c5a6SAntoine Ténart return ret; 5151b44c5a6SAntoine Ténart } 5161b44c5a6SAntoine Ténart 5171b44c5a6SAntoine Ténart static int safexcel_handle_inv_result(struct safexcel_crypto_priv *priv, 5181b44c5a6SAntoine Ténart int ring, 5191b44c5a6SAntoine Ténart struct crypto_async_request *async, 5201b44c5a6SAntoine Ténart bool *should_complete, int *ret) 5211b44c5a6SAntoine Ténart { 5221b44c5a6SAntoine Ténart struct safexcel_result_desc *rdesc; 5231b44c5a6SAntoine Ténart struct ahash_request *areq = ahash_request_cast(async); 5241b44c5a6SAntoine Ténart struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); 5251b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(ahash); 5261b44c5a6SAntoine Ténart int enq_ret; 5271b44c5a6SAntoine Ténart 5281b44c5a6SAntoine Ténart *ret = 0; 5291b44c5a6SAntoine Ténart 5301b44c5a6SAntoine Ténart rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr); 5311b44c5a6SAntoine Ténart if (IS_ERR(rdesc)) { 5321b44c5a6SAntoine Ténart dev_err(priv->dev, 5331b44c5a6SAntoine Ténart "hash: invalidate: could not retrieve the result descriptor\n"); 5341b44c5a6SAntoine Ténart *ret = PTR_ERR(rdesc); 535cda3e73aSAntoine Tenart } else { 536cda3e73aSAntoine Tenart *ret = safexcel_rdesc_check_errors(priv, rdesc); 5371b44c5a6SAntoine Ténart } 5381b44c5a6SAntoine Ténart 5391b44c5a6SAntoine Ténart safexcel_complete(priv, ring); 5401b44c5a6SAntoine Ténart 5411b44c5a6SAntoine Ténart if (ctx->base.exit_inv) { 5421b44c5a6SAntoine Ténart dma_pool_free(priv->context_pool, ctx->base.ctxr, 5431b44c5a6SAntoine Ténart ctx->base.ctxr_dma); 5441b44c5a6SAntoine Ténart 5451b44c5a6SAntoine Ténart *should_complete = true; 5461b44c5a6SAntoine Ténart return 1; 5471b44c5a6SAntoine Ténart } 5481b44c5a6SAntoine Ténart 54986671abbSAntoine Ténart ring = safexcel_select_ring(priv); 55086671abbSAntoine Ténart ctx->base.ring = ring; 5511b44c5a6SAntoine Ténart 55286671abbSAntoine Ténart spin_lock_bh(&priv->ring[ring].queue_lock); 55386671abbSAntoine Ténart enq_ret = crypto_enqueue_request(&priv->ring[ring].queue, async); 55486671abbSAntoine Ténart spin_unlock_bh(&priv->ring[ring].queue_lock); 5551b44c5a6SAntoine Ténart 5561b44c5a6SAntoine Ténart if (enq_ret != -EINPROGRESS) 5571b44c5a6SAntoine Ténart *ret = enq_ret; 5581b44c5a6SAntoine Ténart 5598472e778SAntoine Ténart queue_work(priv->ring[ring].workqueue, 5608472e778SAntoine Ténart &priv->ring[ring].work_data.work); 56186671abbSAntoine Ténart 5621b44c5a6SAntoine Ténart *should_complete = false; 5631b44c5a6SAntoine Ténart 5641b44c5a6SAntoine Ténart return 1; 5651b44c5a6SAntoine Ténart } 5661b44c5a6SAntoine Ténart 5671eb7b403SOfer Heifetz static int safexcel_handle_result(struct safexcel_crypto_priv *priv, int ring, 5681eb7b403SOfer Heifetz struct crypto_async_request *async, 5691eb7b403SOfer Heifetz bool *should_complete, int *ret) 5701eb7b403SOfer Heifetz { 5711eb7b403SOfer Heifetz struct ahash_request *areq = ahash_request_cast(async); 5721eb7b403SOfer Heifetz struct safexcel_ahash_req *req = ahash_request_ctx(areq); 5731eb7b403SOfer Heifetz int err; 5741eb7b403SOfer Heifetz 57553c83e91SAntoine Tenart BUG_ON(!(priv->flags & EIP197_TRC_CACHE) && req->needs_inv); 576871df319SAntoine Ténart 5771eb7b403SOfer Heifetz if (req->needs_inv) { 5781eb7b403SOfer Heifetz req->needs_inv = false; 5791eb7b403SOfer Heifetz err = safexcel_handle_inv_result(priv, ring, async, 5801eb7b403SOfer Heifetz should_complete, ret); 5811eb7b403SOfer Heifetz } else { 5821eb7b403SOfer Heifetz err = safexcel_handle_req_result(priv, ring, async, 5831eb7b403SOfer Heifetz should_complete, ret); 5841eb7b403SOfer Heifetz } 5851eb7b403SOfer Heifetz 5861eb7b403SOfer Heifetz return err; 5871eb7b403SOfer Heifetz } 5881eb7b403SOfer Heifetz 5891b44c5a6SAntoine Ténart static int safexcel_ahash_send_inv(struct crypto_async_request *async, 5909744fec9SOfer Heifetz int ring, int *commands, int *results) 5911b44c5a6SAntoine Ténart { 5921b44c5a6SAntoine Ténart struct ahash_request *areq = ahash_request_cast(async); 5931b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 5941b44c5a6SAntoine Ténart int ret; 5951b44c5a6SAntoine Ténart 59618e51895SHerbert Xu ret = safexcel_invalidate_cache(async, ctx->base.priv, 5979744fec9SOfer Heifetz ctx->base.ctxr_dma, ring); 5981b44c5a6SAntoine Ténart if (unlikely(ret)) 5991b44c5a6SAntoine Ténart return ret; 6001b44c5a6SAntoine Ténart 6011b44c5a6SAntoine Ténart *commands = 1; 6021b44c5a6SAntoine Ténart *results = 1; 6031b44c5a6SAntoine Ténart 6041b44c5a6SAntoine Ténart return 0; 6051b44c5a6SAntoine Ténart } 6061b44c5a6SAntoine Ténart 6071eb7b403SOfer Heifetz static int safexcel_ahash_send(struct crypto_async_request *async, 6089744fec9SOfer Heifetz int ring, int *commands, int *results) 6091eb7b403SOfer Heifetz { 6101eb7b403SOfer Heifetz struct ahash_request *areq = ahash_request_cast(async); 6111eb7b403SOfer Heifetz struct safexcel_ahash_req *req = ahash_request_ctx(areq); 6121eb7b403SOfer Heifetz int ret; 6131eb7b403SOfer Heifetz 6141eb7b403SOfer Heifetz if (req->needs_inv) 6159744fec9SOfer Heifetz ret = safexcel_ahash_send_inv(async, ring, commands, results); 6161eb7b403SOfer Heifetz else 6179744fec9SOfer Heifetz ret = safexcel_ahash_send_req(async, ring, commands, results); 6189744fec9SOfer Heifetz 6191eb7b403SOfer Heifetz return ret; 6201eb7b403SOfer Heifetz } 6211eb7b403SOfer Heifetz 6221b44c5a6SAntoine Ténart static int safexcel_ahash_exit_inv(struct crypto_tfm *tfm) 6231b44c5a6SAntoine Ténart { 6241b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 62518e51895SHerbert Xu struct safexcel_crypto_priv *priv = ctx->base.priv; 62661824806SAntoine Tenart EIP197_REQUEST_ON_STACK(req, ahash, EIP197_AHASH_REQ_SIZE); 6277cad2fabSAntoine Ténart struct safexcel_ahash_req *rctx = ahash_request_ctx(req); 6283e1166b9SArnd Bergmann struct safexcel_inv_result result = {}; 62986671abbSAntoine Ténart int ring = ctx->base.ring; 6301b44c5a6SAntoine Ténart 631b926213dSAntoine Tenart memset(req, 0, EIP197_AHASH_REQ_SIZE); 6321b44c5a6SAntoine Ténart 6331b44c5a6SAntoine Ténart /* create invalidation request */ 6341b44c5a6SAntoine Ténart init_completion(&result.completion); 6357cad2fabSAntoine Ténart ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, 6361b44c5a6SAntoine Ténart safexcel_inv_complete, &result); 6371b44c5a6SAntoine Ténart 6387cad2fabSAntoine Ténart ahash_request_set_tfm(req, __crypto_ahash_cast(tfm)); 6397cad2fabSAntoine Ténart ctx = crypto_tfm_ctx(req->base.tfm); 6401b44c5a6SAntoine Ténart ctx->base.exit_inv = true; 6411eb7b403SOfer Heifetz rctx->needs_inv = true; 6421b44c5a6SAntoine Ténart 64386671abbSAntoine Ténart spin_lock_bh(&priv->ring[ring].queue_lock); 6447cad2fabSAntoine Ténart crypto_enqueue_request(&priv->ring[ring].queue, &req->base); 64586671abbSAntoine Ténart spin_unlock_bh(&priv->ring[ring].queue_lock); 6461b44c5a6SAntoine Ténart 6478472e778SAntoine Ténart queue_work(priv->ring[ring].workqueue, 6488472e778SAntoine Ténart &priv->ring[ring].work_data.work); 6491b44c5a6SAntoine Ténart 650b7007dbcSAntoine Tenart wait_for_completion(&result.completion); 6511b44c5a6SAntoine Ténart 6521b44c5a6SAntoine Ténart if (result.error) { 6531b44c5a6SAntoine Ténart dev_warn(priv->dev, "hash: completion error (%d)\n", 6541b44c5a6SAntoine Ténart result.error); 6551b44c5a6SAntoine Ténart return result.error; 6561b44c5a6SAntoine Ténart } 6571b44c5a6SAntoine Ténart 6581b44c5a6SAntoine Ténart return 0; 6591b44c5a6SAntoine Ténart } 6601b44c5a6SAntoine Ténart 661cc75f5ceSAntoine Ténart /* safexcel_ahash_cache: cache data until at least one request can be sent to 662cc75f5ceSAntoine Ténart * the engine, aka. when there is at least 1 block size in the pipe. 663cc75f5ceSAntoine Ténart */ 66441abed7dSPascal van Leeuwen static int safexcel_ahash_cache(struct ahash_request *areq) 6651b44c5a6SAntoine Ténart { 6661b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 66741abed7dSPascal van Leeuwen u64 cache_len; 6681b44c5a6SAntoine Ténart 669b460edb6SAntoine Tenart /* cache_len: everything accepted by the driver but not sent yet, 670b460edb6SAntoine Tenart * tot sz handled by update() - last req sz - tot sz handled by send() 671b460edb6SAntoine Tenart */ 67241abed7dSPascal van Leeuwen cache_len = safexcel_queued_len(req); 6731b44c5a6SAntoine Ténart 6741b44c5a6SAntoine Ténart /* 6751b44c5a6SAntoine Ténart * In case there isn't enough bytes to proceed (less than a 6761b44c5a6SAntoine Ténart * block size), cache the data until we have enough. 6771b44c5a6SAntoine Ténart */ 67841abed7dSPascal van Leeuwen if (cache_len + areq->nbytes <= HASH_CACHE_SIZE) { 6791b44c5a6SAntoine Ténart sg_pcopy_to_buffer(areq->src, sg_nents(areq->src), 6801b44c5a6SAntoine Ténart req->cache + cache_len, 6811b44c5a6SAntoine Ténart areq->nbytes, 0); 68241abed7dSPascal van Leeuwen return 0; 6831b44c5a6SAntoine Ténart } 6841b44c5a6SAntoine Ténart 685dfbcc08fSAntoine Ténart /* We couldn't cache all the data */ 6861b44c5a6SAntoine Ténart return -E2BIG; 6871b44c5a6SAntoine Ténart } 6881b44c5a6SAntoine Ténart 6891b44c5a6SAntoine Ténart static int safexcel_ahash_enqueue(struct ahash_request *areq) 6901b44c5a6SAntoine Ténart { 6911b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 6921b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 69318e51895SHerbert Xu struct safexcel_crypto_priv *priv = ctx->base.priv; 69486671abbSAntoine Ténart int ret, ring; 6951b44c5a6SAntoine Ténart 6961eb7b403SOfer Heifetz req->needs_inv = false; 6971b44c5a6SAntoine Ténart 698c4daf4ccSOfer Heifetz if (ctx->base.ctxr) { 69953c83e91SAntoine Tenart if (priv->flags & EIP197_TRC_CACHE && !ctx->base.needs_inv && 700b98687bbSPascal van Leeuwen /* invalidate for *any* non-XCBC continuation */ 701b98687bbSPascal van Leeuwen ((req->not_first && !req->xcbcmac) || 70241abed7dSPascal van Leeuwen /* invalidate if (i)digest changed */ 70341abed7dSPascal van Leeuwen memcmp(ctx->base.ctxr->data, req->state, req->state_sz) || 70441abed7dSPascal van Leeuwen /* invalidate for HMAC finish with odigest changed */ 705a7cf8658SPascal van Leeuwen (req->finish && req->hmac && 70641abed7dSPascal van Leeuwen memcmp(ctx->base.ctxr->data + (req->state_sz>>2), 70778cf1c8bSHerbert Xu &ctx->base.opad, req->state_sz)))) 70841abed7dSPascal van Leeuwen /* 70941abed7dSPascal van Leeuwen * We're still setting needs_inv here, even though it is 710c4daf4ccSOfer Heifetz * cleared right away, because the needs_inv flag can be 711c4daf4ccSOfer Heifetz * set in other functions and we want to keep the same 712c4daf4ccSOfer Heifetz * logic. 713c4daf4ccSOfer Heifetz */ 71441abed7dSPascal van Leeuwen ctx->base.needs_inv = true; 7151b44c5a6SAntoine Ténart 7161eb7b403SOfer Heifetz if (ctx->base.needs_inv) { 7171eb7b403SOfer Heifetz ctx->base.needs_inv = false; 7181eb7b403SOfer Heifetz req->needs_inv = true; 7191eb7b403SOfer Heifetz } 7201b44c5a6SAntoine Ténart } else { 7211b44c5a6SAntoine Ténart ctx->base.ring = safexcel_select_ring(priv); 7221b44c5a6SAntoine Ténart ctx->base.ctxr = dma_pool_zalloc(priv->context_pool, 7231b44c5a6SAntoine Ténart EIP197_GFP_FLAGS(areq->base), 7241b44c5a6SAntoine Ténart &ctx->base.ctxr_dma); 7251b44c5a6SAntoine Ténart if (!ctx->base.ctxr) 7261b44c5a6SAntoine Ténart return -ENOMEM; 7271b44c5a6SAntoine Ténart } 728b98687bbSPascal van Leeuwen req->not_first = true; 7291b44c5a6SAntoine Ténart 73086671abbSAntoine Ténart ring = ctx->base.ring; 7311b44c5a6SAntoine Ténart 73286671abbSAntoine Ténart spin_lock_bh(&priv->ring[ring].queue_lock); 73386671abbSAntoine Ténart ret = crypto_enqueue_request(&priv->ring[ring].queue, &areq->base); 73486671abbSAntoine Ténart spin_unlock_bh(&priv->ring[ring].queue_lock); 73586671abbSAntoine Ténart 7368472e778SAntoine Ténart queue_work(priv->ring[ring].workqueue, 7378472e778SAntoine Ténart &priv->ring[ring].work_data.work); 7381b44c5a6SAntoine Ténart 7391b44c5a6SAntoine Ténart return ret; 7401b44c5a6SAntoine Ténart } 7411b44c5a6SAntoine Ténart 7421b44c5a6SAntoine Ténart static int safexcel_ahash_update(struct ahash_request *areq) 7431b44c5a6SAntoine Ténart { 7441b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 74541abed7dSPascal van Leeuwen int ret; 7461b44c5a6SAntoine Ténart 7471b44c5a6SAntoine Ténart /* If the request is 0 length, do nothing */ 7481b44c5a6SAntoine Ténart if (!areq->nbytes) 7491b44c5a6SAntoine Ténart return 0; 7501b44c5a6SAntoine Ténart 75141abed7dSPascal van Leeuwen /* Add request to the cache if it fits */ 75241abed7dSPascal van Leeuwen ret = safexcel_ahash_cache(areq); 75341abed7dSPascal van Leeuwen 75441abed7dSPascal van Leeuwen /* Update total request length */ 75531fb084cSPascal van Leeuwen req->len += areq->nbytes; 7561b44c5a6SAntoine Ténart 75741abed7dSPascal van Leeuwen /* If not all data could fit into the cache, go process the excess. 75841abed7dSPascal van Leeuwen * Also go process immediately for an HMAC IV precompute, which 75941abed7dSPascal van Leeuwen * will never be finished at all, but needs to be processed anyway. 7601b44c5a6SAntoine Ténart */ 76141abed7dSPascal van Leeuwen if ((ret && !req->finish) || req->last_req) 7621b44c5a6SAntoine Ténart return safexcel_ahash_enqueue(areq); 7631b44c5a6SAntoine Ténart 7641b44c5a6SAntoine Ténart return 0; 7651b44c5a6SAntoine Ténart } 7661b44c5a6SAntoine Ténart 7671b44c5a6SAntoine Ténart static int safexcel_ahash_final(struct ahash_request *areq) 7681b44c5a6SAntoine Ténart { 7691b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 7701b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 7711b44c5a6SAntoine Ténart 7721b44c5a6SAntoine Ténart req->finish = true; 7731b44c5a6SAntoine Ténart 77431fb084cSPascal van Leeuwen if (unlikely(!req->len && !areq->nbytes)) { 77585695b09SPascal van Leeuwen /* 77685695b09SPascal van Leeuwen * If we have an overall 0 length *hash* request: 77785695b09SPascal van Leeuwen * The HW cannot do 0 length hash, so we provide the correct 77885695b09SPascal van Leeuwen * result directly here. 77985695b09SPascal van Leeuwen */ 780293f89cfSOfer Heifetz if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_MD5) 781293f89cfSOfer Heifetz memcpy(areq->result, md5_zero_message_hash, 782293f89cfSOfer Heifetz MD5_DIGEST_SIZE); 783293f89cfSOfer Heifetz else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA1) 7841b44c5a6SAntoine Ténart memcpy(areq->result, sha1_zero_message_hash, 7851b44c5a6SAntoine Ténart SHA1_DIGEST_SIZE); 7861b44c5a6SAntoine Ténart else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA224) 7871b44c5a6SAntoine Ténart memcpy(areq->result, sha224_zero_message_hash, 7881b44c5a6SAntoine Ténart SHA224_DIGEST_SIZE); 7891b44c5a6SAntoine Ténart else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA256) 7901b44c5a6SAntoine Ténart memcpy(areq->result, sha256_zero_message_hash, 7911b44c5a6SAntoine Ténart SHA256_DIGEST_SIZE); 7929e46eafdSAntoine Tenart else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA384) 7939e46eafdSAntoine Tenart memcpy(areq->result, sha384_zero_message_hash, 7949e46eafdSAntoine Tenart SHA384_DIGEST_SIZE); 795b460edb6SAntoine Tenart else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA512) 796b460edb6SAntoine Tenart memcpy(areq->result, sha512_zero_message_hash, 797b460edb6SAntoine Tenart SHA512_DIGEST_SIZE); 7980f2bc131SPascal van Leeuwen else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SM3) { 7990f2bc131SPascal van Leeuwen memcpy(areq->result, 8000f2bc131SPascal van Leeuwen EIP197_SM3_ZEROM_HASH, SM3_DIGEST_SIZE); 8010f2bc131SPascal van Leeuwen } 8021b44c5a6SAntoine Ténart 8031b44c5a6SAntoine Ténart return 0; 804a7cf8658SPascal van Leeuwen } else if (unlikely(req->digest == CONTEXT_CONTROL_DIGEST_XCM && 805a7cf8658SPascal van Leeuwen ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_MD5 && 806a7cf8658SPascal van Leeuwen req->len == sizeof(u32) && !areq->nbytes)) { 807a7cf8658SPascal van Leeuwen /* Zero length CRC32 */ 80878cf1c8bSHerbert Xu memcpy(areq->result, &ctx->base.ipad, sizeof(u32)); 809a7cf8658SPascal van Leeuwen return 0; 81038f21b4bSPascal van Leeuwen } else if (unlikely(ctx->cbcmac && req->len == AES_BLOCK_SIZE && 811b98687bbSPascal van Leeuwen !areq->nbytes)) { 812b98687bbSPascal van Leeuwen /* Zero length CBC MAC */ 813b98687bbSPascal van Leeuwen memset(areq->result, 0, AES_BLOCK_SIZE); 814b98687bbSPascal van Leeuwen return 0; 81538f21b4bSPascal van Leeuwen } else if (unlikely(req->xcbcmac && req->len == AES_BLOCK_SIZE && 81638f21b4bSPascal van Leeuwen !areq->nbytes)) { 81738f21b4bSPascal van Leeuwen /* Zero length (X)CBC/CMAC */ 81838f21b4bSPascal van Leeuwen int i; 81938f21b4bSPascal van Leeuwen 82078cf1c8bSHerbert Xu for (i = 0; i < AES_BLOCK_SIZE / sizeof(u32); i++) { 82178cf1c8bSHerbert Xu u32 *result = (void *)areq->result; 82278cf1c8bSHerbert Xu 82378cf1c8bSHerbert Xu /* K3 */ 82466459340SPeter Harliman Liem result[i] = swab32(ctx->base.ipad.word[i + 4]); 82578cf1c8bSHerbert Xu } 82638f21b4bSPascal van Leeuwen areq->result[0] ^= 0x80; // 10- padding 827*320406cbSPeter Harliman Liem aes_encrypt(ctx->aes, areq->result, areq->result); 82838f21b4bSPascal van Leeuwen return 0; 82931fb084cSPascal van Leeuwen } else if (unlikely(req->hmac && 83031fb084cSPascal van Leeuwen (req->len == req->block_sz) && 83141abed7dSPascal van Leeuwen !areq->nbytes)) { 83285b36ee8SPascal van Leeuwen /* 83385b36ee8SPascal van Leeuwen * If we have an overall 0 length *HMAC* request: 83485b36ee8SPascal van Leeuwen * For HMAC, we need to finalize the inner digest 83585b36ee8SPascal van Leeuwen * and then perform the outer hash. 83685b36ee8SPascal van Leeuwen */ 83785b36ee8SPascal van Leeuwen 83885b36ee8SPascal van Leeuwen /* generate pad block in the cache */ 83985b36ee8SPascal van Leeuwen /* start with a hash block of all zeroes */ 84085b36ee8SPascal van Leeuwen memset(req->cache, 0, req->block_sz); 84185b36ee8SPascal van Leeuwen /* set the first byte to 0x80 to 'append a 1 bit' */ 84285b36ee8SPascal van Leeuwen req->cache[0] = 0x80; 84385b36ee8SPascal van Leeuwen /* add the length in bits in the last 2 bytes */ 84485b36ee8SPascal van Leeuwen if (req->len_is_le) { 84585b36ee8SPascal van Leeuwen /* Little endian length word (e.g. MD5) */ 84685b36ee8SPascal van Leeuwen req->cache[req->block_sz-8] = (req->block_sz << 3) & 84785b36ee8SPascal van Leeuwen 255; 84885b36ee8SPascal van Leeuwen req->cache[req->block_sz-7] = (req->block_sz >> 5); 84985b36ee8SPascal van Leeuwen } else { 85085b36ee8SPascal van Leeuwen /* Big endian length word (e.g. any SHA) */ 85185b36ee8SPascal van Leeuwen req->cache[req->block_sz-2] = (req->block_sz >> 5); 85285b36ee8SPascal van Leeuwen req->cache[req->block_sz-1] = (req->block_sz << 3) & 85385b36ee8SPascal van Leeuwen 255; 85485b36ee8SPascal van Leeuwen } 85585b36ee8SPascal van Leeuwen 85631fb084cSPascal van Leeuwen req->len += req->block_sz; /* plus 1 hash block */ 85785b36ee8SPascal van Leeuwen 85885b36ee8SPascal van Leeuwen /* Set special zero-length HMAC flag */ 85985b36ee8SPascal van Leeuwen req->hmac_zlen = true; 86085b36ee8SPascal van Leeuwen 86185b36ee8SPascal van Leeuwen /* Finalize HMAC */ 86285b36ee8SPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_HMAC; 86341abed7dSPascal van Leeuwen } else if (req->hmac) { 86441abed7dSPascal van Leeuwen /* Finalize HMAC */ 86541abed7dSPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_HMAC; 8661b44c5a6SAntoine Ténart } 8671b44c5a6SAntoine Ténart 8681b44c5a6SAntoine Ténart return safexcel_ahash_enqueue(areq); 8691b44c5a6SAntoine Ténart } 8701b44c5a6SAntoine Ténart 8711b44c5a6SAntoine Ténart static int safexcel_ahash_finup(struct ahash_request *areq) 8721b44c5a6SAntoine Ténart { 8731b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 8741b44c5a6SAntoine Ténart 8751b44c5a6SAntoine Ténart req->finish = true; 8761b44c5a6SAntoine Ténart 8771b44c5a6SAntoine Ténart safexcel_ahash_update(areq); 8781b44c5a6SAntoine Ténart return safexcel_ahash_final(areq); 8791b44c5a6SAntoine Ténart } 8801b44c5a6SAntoine Ténart 8811b44c5a6SAntoine Ténart static int safexcel_ahash_export(struct ahash_request *areq, void *out) 8821b44c5a6SAntoine Ténart { 8831b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 8841b44c5a6SAntoine Ténart struct safexcel_ahash_export_state *export = out; 8851b44c5a6SAntoine Ténart 88631fb084cSPascal van Leeuwen export->len = req->len; 88731fb084cSPascal van Leeuwen export->processed = req->processed; 8881b44c5a6SAntoine Ténart 889b869648cSAntoine Tenart export->digest = req->digest; 890b869648cSAntoine Tenart 8911b44c5a6SAntoine Ténart memcpy(export->state, req->state, req->state_sz); 89241abed7dSPascal van Leeuwen memcpy(export->cache, req->cache, HASH_CACHE_SIZE); 8931b44c5a6SAntoine Ténart 8941b44c5a6SAntoine Ténart return 0; 8951b44c5a6SAntoine Ténart } 8961b44c5a6SAntoine Ténart 8971b44c5a6SAntoine Ténart static int safexcel_ahash_import(struct ahash_request *areq, const void *in) 8981b44c5a6SAntoine Ténart { 8991b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 9001b44c5a6SAntoine Ténart const struct safexcel_ahash_export_state *export = in; 9011b44c5a6SAntoine Ténart int ret; 9021b44c5a6SAntoine Ténart 9031b44c5a6SAntoine Ténart ret = crypto_ahash_init(areq); 9041b44c5a6SAntoine Ténart if (ret) 9051b44c5a6SAntoine Ténart return ret; 9061b44c5a6SAntoine Ténart 90731fb084cSPascal van Leeuwen req->len = export->len; 90831fb084cSPascal van Leeuwen req->processed = export->processed; 9091b44c5a6SAntoine Ténart 910b869648cSAntoine Tenart req->digest = export->digest; 911b869648cSAntoine Tenart 91241abed7dSPascal van Leeuwen memcpy(req->cache, export->cache, HASH_CACHE_SIZE); 9131b44c5a6SAntoine Ténart memcpy(req->state, export->state, req->state_sz); 9141b44c5a6SAntoine Ténart 9151b44c5a6SAntoine Ténart return 0; 9161b44c5a6SAntoine Ténart } 9171b44c5a6SAntoine Ténart 9181b44c5a6SAntoine Ténart static int safexcel_ahash_cra_init(struct crypto_tfm *tfm) 9191b44c5a6SAntoine Ténart { 9201b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 9211b44c5a6SAntoine Ténart struct safexcel_alg_template *tmpl = 9221b44c5a6SAntoine Ténart container_of(__crypto_ahash_alg(tfm->__crt_alg), 9231b44c5a6SAntoine Ténart struct safexcel_alg_template, alg.ahash); 9241b44c5a6SAntoine Ténart 92518e51895SHerbert Xu ctx->base.priv = tmpl->priv; 9261eb7b403SOfer Heifetz ctx->base.send = safexcel_ahash_send; 9271eb7b403SOfer Heifetz ctx->base.handle_result = safexcel_handle_result; 9286c1c09b3SPascal van Leeuwen ctx->fb_do_setkey = false; 9291b44c5a6SAntoine Ténart 9301b44c5a6SAntoine Ténart crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), 9311b44c5a6SAntoine Ténart sizeof(struct safexcel_ahash_req)); 9321b44c5a6SAntoine Ténart return 0; 9331b44c5a6SAntoine Ténart } 9341b44c5a6SAntoine Ténart 9351b44c5a6SAntoine Ténart static int safexcel_sha1_init(struct ahash_request *areq) 9361b44c5a6SAntoine Ténart { 9371b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 9381b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 9391b44c5a6SAntoine Ténart 9401b44c5a6SAntoine Ténart memset(req, 0, sizeof(*req)); 9411b44c5a6SAntoine Ténart 9421b44c5a6SAntoine Ténart ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1; 943b869648cSAntoine Tenart req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 9441b44c5a6SAntoine Ténart req->state_sz = SHA1_DIGEST_SIZE; 9456c1c09b3SPascal van Leeuwen req->digest_sz = SHA1_DIGEST_SIZE; 94641abed7dSPascal van Leeuwen req->block_sz = SHA1_BLOCK_SIZE; 9471b44c5a6SAntoine Ténart 9481b44c5a6SAntoine Ténart return 0; 9491b44c5a6SAntoine Ténart } 9501b44c5a6SAntoine Ténart 9511b44c5a6SAntoine Ténart static int safexcel_sha1_digest(struct ahash_request *areq) 9521b44c5a6SAntoine Ténart { 9531b44c5a6SAntoine Ténart int ret = safexcel_sha1_init(areq); 9541b44c5a6SAntoine Ténart 9551b44c5a6SAntoine Ténart if (ret) 9561b44c5a6SAntoine Ténart return ret; 9571b44c5a6SAntoine Ténart 9581b44c5a6SAntoine Ténart return safexcel_ahash_finup(areq); 9591b44c5a6SAntoine Ténart } 9601b44c5a6SAntoine Ténart 9611b44c5a6SAntoine Ténart static void safexcel_ahash_cra_exit(struct crypto_tfm *tfm) 9621b44c5a6SAntoine Ténart { 9631b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 96418e51895SHerbert Xu struct safexcel_crypto_priv *priv = ctx->base.priv; 9651b44c5a6SAntoine Ténart int ret; 9661b44c5a6SAntoine Ténart 9671b44c5a6SAntoine Ténart /* context not allocated, skip invalidation */ 9681b44c5a6SAntoine Ténart if (!ctx->base.ctxr) 9691b44c5a6SAntoine Ténart return; 9701b44c5a6SAntoine Ténart 97153c83e91SAntoine Tenart if (priv->flags & EIP197_TRC_CACHE) { 9721b44c5a6SAntoine Ténart ret = safexcel_ahash_exit_inv(tfm); 9731b44c5a6SAntoine Ténart if (ret) 9741b44c5a6SAntoine Ténart dev_warn(priv->dev, "hash: invalidation error %d\n", ret); 975871df319SAntoine Ténart } else { 976871df319SAntoine Ténart dma_pool_free(priv->context_pool, ctx->base.ctxr, 977871df319SAntoine Ténart ctx->base.ctxr_dma); 978871df319SAntoine Ténart } 9791b44c5a6SAntoine Ténart } 9801b44c5a6SAntoine Ténart 9811b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha1 = { 9821b44c5a6SAntoine Ténart .type = SAFEXCEL_ALG_TYPE_AHASH, 983062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA1, 9841b44c5a6SAntoine Ténart .alg.ahash = { 9851b44c5a6SAntoine Ténart .init = safexcel_sha1_init, 9861b44c5a6SAntoine Ténart .update = safexcel_ahash_update, 9871b44c5a6SAntoine Ténart .final = safexcel_ahash_final, 9881b44c5a6SAntoine Ténart .finup = safexcel_ahash_finup, 9891b44c5a6SAntoine Ténart .digest = safexcel_sha1_digest, 9901b44c5a6SAntoine Ténart .export = safexcel_ahash_export, 9911b44c5a6SAntoine Ténart .import = safexcel_ahash_import, 9921b44c5a6SAntoine Ténart .halg = { 9931b44c5a6SAntoine Ténart .digestsize = SHA1_DIGEST_SIZE, 9941b44c5a6SAntoine Ténart .statesize = sizeof(struct safexcel_ahash_export_state), 9951b44c5a6SAntoine Ténart .base = { 9961b44c5a6SAntoine Ténart .cra_name = "sha1", 9971b44c5a6SAntoine Ténart .cra_driver_name = "safexcel-sha1", 998aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 9991b44c5a6SAntoine Ténart .cra_flags = CRYPTO_ALG_ASYNC | 1000b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 10011b44c5a6SAntoine Ténart CRYPTO_ALG_KERN_DRIVER_ONLY, 10021b44c5a6SAntoine Ténart .cra_blocksize = SHA1_BLOCK_SIZE, 10031b44c5a6SAntoine Ténart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 10041b44c5a6SAntoine Ténart .cra_init = safexcel_ahash_cra_init, 10051b44c5a6SAntoine Ténart .cra_exit = safexcel_ahash_cra_exit, 10061b44c5a6SAntoine Ténart .cra_module = THIS_MODULE, 10071b44c5a6SAntoine Ténart }, 10081b44c5a6SAntoine Ténart }, 10091b44c5a6SAntoine Ténart }, 10101b44c5a6SAntoine Ténart }; 10111b44c5a6SAntoine Ténart 10121b44c5a6SAntoine Ténart static int safexcel_hmac_sha1_init(struct ahash_request *areq) 10131b44c5a6SAntoine Ténart { 101441abed7dSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 1015b869648cSAntoine Tenart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 10161b44c5a6SAntoine Ténart 101741abed7dSPascal van Leeuwen memset(req, 0, sizeof(*req)); 101841abed7dSPascal van Leeuwen 101941abed7dSPascal van Leeuwen /* Start from ipad precompute */ 102078cf1c8bSHerbert Xu memcpy(req->state, &ctx->base.ipad, SHA1_DIGEST_SIZE); 102141abed7dSPascal van Leeuwen /* Already processed the key^ipad part now! */ 102231fb084cSPascal van Leeuwen req->len = SHA1_BLOCK_SIZE; 102331fb084cSPascal van Leeuwen req->processed = SHA1_BLOCK_SIZE; 102441abed7dSPascal van Leeuwen 102541abed7dSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1; 102641abed7dSPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 102741abed7dSPascal van Leeuwen req->state_sz = SHA1_DIGEST_SIZE; 10286c1c09b3SPascal van Leeuwen req->digest_sz = SHA1_DIGEST_SIZE; 102941abed7dSPascal van Leeuwen req->block_sz = SHA1_BLOCK_SIZE; 103041abed7dSPascal van Leeuwen req->hmac = true; 103141abed7dSPascal van Leeuwen 10321b44c5a6SAntoine Ténart return 0; 10331b44c5a6SAntoine Ténart } 10341b44c5a6SAntoine Ténart 10351b44c5a6SAntoine Ténart static int safexcel_hmac_sha1_digest(struct ahash_request *areq) 10361b44c5a6SAntoine Ténart { 10371b44c5a6SAntoine Ténart int ret = safexcel_hmac_sha1_init(areq); 10381b44c5a6SAntoine Ténart 10391b44c5a6SAntoine Ténart if (ret) 10401b44c5a6SAntoine Ténart return ret; 10411b44c5a6SAntoine Ténart 10421b44c5a6SAntoine Ténart return safexcel_ahash_finup(areq); 10431b44c5a6SAntoine Ténart } 10441b44c5a6SAntoine Ténart 10451b44c5a6SAntoine Ténart struct safexcel_ahash_result { 10461b44c5a6SAntoine Ténart struct completion completion; 10471b44c5a6SAntoine Ténart int error; 10481b44c5a6SAntoine Ténart }; 10491b44c5a6SAntoine Ténart 10501b44c5a6SAntoine Ténart static void safexcel_ahash_complete(struct crypto_async_request *req, int error) 10511b44c5a6SAntoine Ténart { 10521b44c5a6SAntoine Ténart struct safexcel_ahash_result *result = req->data; 10531b44c5a6SAntoine Ténart 10541b44c5a6SAntoine Ténart if (error == -EINPROGRESS) 10551b44c5a6SAntoine Ténart return; 10561b44c5a6SAntoine Ténart 10571b44c5a6SAntoine Ténart result->error = error; 10581b44c5a6SAntoine Ténart complete(&result->completion); 10591b44c5a6SAntoine Ténart } 10601b44c5a6SAntoine Ténart 10611b44c5a6SAntoine Ténart static int safexcel_hmac_init_pad(struct ahash_request *areq, 10621b44c5a6SAntoine Ténart unsigned int blocksize, const u8 *key, 10631b44c5a6SAntoine Ténart unsigned int keylen, u8 *ipad, u8 *opad) 10641b44c5a6SAntoine Ténart { 10651b44c5a6SAntoine Ténart struct safexcel_ahash_result result; 10661b44c5a6SAntoine Ténart struct scatterlist sg; 10671b44c5a6SAntoine Ténart int ret, i; 10681b44c5a6SAntoine Ténart u8 *keydup; 10691b44c5a6SAntoine Ténart 10701b44c5a6SAntoine Ténart if (keylen <= blocksize) { 10711b44c5a6SAntoine Ténart memcpy(ipad, key, keylen); 10721b44c5a6SAntoine Ténart } else { 10731b44c5a6SAntoine Ténart keydup = kmemdup(key, keylen, GFP_KERNEL); 10741b44c5a6SAntoine Ténart if (!keydup) 10751b44c5a6SAntoine Ténart return -ENOMEM; 10761b44c5a6SAntoine Ténart 10771b44c5a6SAntoine Ténart ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_BACKLOG, 10781b44c5a6SAntoine Ténart safexcel_ahash_complete, &result); 10791b44c5a6SAntoine Ténart sg_init_one(&sg, keydup, keylen); 10801b44c5a6SAntoine Ténart ahash_request_set_crypt(areq, &sg, ipad, keylen); 10811b44c5a6SAntoine Ténart init_completion(&result.completion); 10821b44c5a6SAntoine Ténart 10831b44c5a6SAntoine Ténart ret = crypto_ahash_digest(areq); 10844dc5475aSAntoine Tenart if (ret == -EINPROGRESS || ret == -EBUSY) { 10851b44c5a6SAntoine Ténart wait_for_completion_interruptible(&result.completion); 10861b44c5a6SAntoine Ténart ret = result.error; 10871b44c5a6SAntoine Ténart } 10881b44c5a6SAntoine Ténart 10891b44c5a6SAntoine Ténart /* Avoid leaking */ 109057059185SDenis Efremov kfree_sensitive(keydup); 10911b44c5a6SAntoine Ténart 10921b44c5a6SAntoine Ténart if (ret) 10931b44c5a6SAntoine Ténart return ret; 10941b44c5a6SAntoine Ténart 10951b44c5a6SAntoine Ténart keylen = crypto_ahash_digestsize(crypto_ahash_reqtfm(areq)); 10961b44c5a6SAntoine Ténart } 10971b44c5a6SAntoine Ténart 10981b44c5a6SAntoine Ténart memset(ipad + keylen, 0, blocksize - keylen); 10991b44c5a6SAntoine Ténart memcpy(opad, ipad, blocksize); 11001b44c5a6SAntoine Ténart 11011b44c5a6SAntoine Ténart for (i = 0; i < blocksize; i++) { 1102aed3731eSAntoine Ténart ipad[i] ^= HMAC_IPAD_VALUE; 1103aed3731eSAntoine Ténart opad[i] ^= HMAC_OPAD_VALUE; 11041b44c5a6SAntoine Ténart } 11051b44c5a6SAntoine Ténart 11061b44c5a6SAntoine Ténart return 0; 11071b44c5a6SAntoine Ténart } 11081b44c5a6SAntoine Ténart 11091b44c5a6SAntoine Ténart static int safexcel_hmac_init_iv(struct ahash_request *areq, 11101b44c5a6SAntoine Ténart unsigned int blocksize, u8 *pad, void *state) 11111b44c5a6SAntoine Ténart { 11121b44c5a6SAntoine Ténart struct safexcel_ahash_result result; 11131b44c5a6SAntoine Ténart struct safexcel_ahash_req *req; 11141b44c5a6SAntoine Ténart struct scatterlist sg; 11151b44c5a6SAntoine Ténart int ret; 11161b44c5a6SAntoine Ténart 11171b44c5a6SAntoine Ténart ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_BACKLOG, 11181b44c5a6SAntoine Ténart safexcel_ahash_complete, &result); 11191b44c5a6SAntoine Ténart sg_init_one(&sg, pad, blocksize); 11201b44c5a6SAntoine Ténart ahash_request_set_crypt(areq, &sg, pad, blocksize); 11211b44c5a6SAntoine Ténart init_completion(&result.completion); 11221b44c5a6SAntoine Ténart 11231b44c5a6SAntoine Ténart ret = crypto_ahash_init(areq); 11241b44c5a6SAntoine Ténart if (ret) 11251b44c5a6SAntoine Ténart return ret; 11261b44c5a6SAntoine Ténart 11271b44c5a6SAntoine Ténart req = ahash_request_ctx(areq); 11281b44c5a6SAntoine Ténart req->hmac = true; 11291b44c5a6SAntoine Ténart req->last_req = true; 11301b44c5a6SAntoine Ténart 11311b44c5a6SAntoine Ténart ret = crypto_ahash_update(areq); 113212bf4142SOfer Heifetz if (ret && ret != -EINPROGRESS && ret != -EBUSY) 11331b44c5a6SAntoine Ténart return ret; 11341b44c5a6SAntoine Ténart 11351b44c5a6SAntoine Ténart wait_for_completion_interruptible(&result.completion); 11361b44c5a6SAntoine Ténart if (result.error) 11371b44c5a6SAntoine Ténart return result.error; 11381b44c5a6SAntoine Ténart 11391b44c5a6SAntoine Ténart return crypto_ahash_export(areq, state); 11401b44c5a6SAntoine Ténart } 11411b44c5a6SAntoine Ténart 114263cdd870SHerbert Xu static int __safexcel_hmac_setkey(const char *alg, const u8 *key, 114363cdd870SHerbert Xu unsigned int keylen, 1144f6beaea3SAntoine Tenart void *istate, void *ostate) 11451b44c5a6SAntoine Ténart { 11461b44c5a6SAntoine Ténart struct ahash_request *areq; 11471b44c5a6SAntoine Ténart struct crypto_ahash *tfm; 11481b44c5a6SAntoine Ténart unsigned int blocksize; 11491b44c5a6SAntoine Ténart u8 *ipad, *opad; 11501b44c5a6SAntoine Ténart int ret; 11511b44c5a6SAntoine Ténart 115285d7311fSEric Biggers tfm = crypto_alloc_ahash(alg, 0, 0); 11531b44c5a6SAntoine Ténart if (IS_ERR(tfm)) 11541b44c5a6SAntoine Ténart return PTR_ERR(tfm); 11551b44c5a6SAntoine Ténart 11561b44c5a6SAntoine Ténart areq = ahash_request_alloc(tfm, GFP_KERNEL); 11571b44c5a6SAntoine Ténart if (!areq) { 11581b44c5a6SAntoine Ténart ret = -ENOMEM; 11591b44c5a6SAntoine Ténart goto free_ahash; 11601b44c5a6SAntoine Ténart } 11611b44c5a6SAntoine Ténart 11621b44c5a6SAntoine Ténart crypto_ahash_clear_flags(tfm, ~0); 11631b44c5a6SAntoine Ténart blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); 11641b44c5a6SAntoine Ténart 11656396bb22SKees Cook ipad = kcalloc(2, blocksize, GFP_KERNEL); 11661b44c5a6SAntoine Ténart if (!ipad) { 11671b44c5a6SAntoine Ténart ret = -ENOMEM; 11681b44c5a6SAntoine Ténart goto free_request; 11691b44c5a6SAntoine Ténart } 11701b44c5a6SAntoine Ténart 11711b44c5a6SAntoine Ténart opad = ipad + blocksize; 11721b44c5a6SAntoine Ténart 11731b44c5a6SAntoine Ténart ret = safexcel_hmac_init_pad(areq, blocksize, key, keylen, ipad, opad); 11741b44c5a6SAntoine Ténart if (ret) 11751b44c5a6SAntoine Ténart goto free_ipad; 11761b44c5a6SAntoine Ténart 11771b44c5a6SAntoine Ténart ret = safexcel_hmac_init_iv(areq, blocksize, ipad, istate); 11781b44c5a6SAntoine Ténart if (ret) 11791b44c5a6SAntoine Ténart goto free_ipad; 11801b44c5a6SAntoine Ténart 11811b44c5a6SAntoine Ténart ret = safexcel_hmac_init_iv(areq, blocksize, opad, ostate); 11821b44c5a6SAntoine Ténart 11831b44c5a6SAntoine Ténart free_ipad: 11841b44c5a6SAntoine Ténart kfree(ipad); 11851b44c5a6SAntoine Ténart free_request: 11861b44c5a6SAntoine Ténart ahash_request_free(areq); 11871b44c5a6SAntoine Ténart free_ahash: 11881b44c5a6SAntoine Ténart crypto_free_ahash(tfm); 11891b44c5a6SAntoine Ténart 11901b44c5a6SAntoine Ténart return ret; 11911b44c5a6SAntoine Ténart } 11921b44c5a6SAntoine Ténart 119363cdd870SHerbert Xu int safexcel_hmac_setkey(struct safexcel_context *base, const u8 *key, 119463cdd870SHerbert Xu unsigned int keylen, const char *alg, 119563cdd870SHerbert Xu unsigned int state_sz) 119663cdd870SHerbert Xu { 119763cdd870SHerbert Xu struct safexcel_crypto_priv *priv = base->priv; 119863cdd870SHerbert Xu struct safexcel_ahash_export_state istate, ostate; 119963cdd870SHerbert Xu int ret; 120063cdd870SHerbert Xu 120163cdd870SHerbert Xu ret = __safexcel_hmac_setkey(alg, key, keylen, &istate, &ostate); 120263cdd870SHerbert Xu if (ret) 120363cdd870SHerbert Xu return ret; 120463cdd870SHerbert Xu 120563cdd870SHerbert Xu if (priv->flags & EIP197_TRC_CACHE && base->ctxr && 120663cdd870SHerbert Xu (memcmp(&base->ipad, istate.state, state_sz) || 120763cdd870SHerbert Xu memcmp(&base->opad, ostate.state, state_sz))) 120863cdd870SHerbert Xu base->needs_inv = true; 120963cdd870SHerbert Xu 121063cdd870SHerbert Xu memcpy(&base->ipad, &istate.state, state_sz); 121163cdd870SHerbert Xu memcpy(&base->opad, &ostate.state, state_sz); 121263cdd870SHerbert Xu 121363cdd870SHerbert Xu return 0; 121463cdd870SHerbert Xu } 121563cdd870SHerbert Xu 121673f36ea7SAntoine Tenart static int safexcel_hmac_alg_setkey(struct crypto_ahash *tfm, const u8 *key, 121773f36ea7SAntoine Tenart unsigned int keylen, const char *alg, 121873f36ea7SAntoine Tenart unsigned int state_sz) 12191b44c5a6SAntoine Ténart { 122063cdd870SHerbert Xu struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 12211b44c5a6SAntoine Ténart 122263cdd870SHerbert Xu return safexcel_hmac_setkey(&ctx->base, key, keylen, alg, state_sz); 12231b44c5a6SAntoine Ténart } 12241b44c5a6SAntoine Ténart 122573f36ea7SAntoine Tenart static int safexcel_hmac_sha1_setkey(struct crypto_ahash *tfm, const u8 *key, 122673f36ea7SAntoine Tenart unsigned int keylen) 122773f36ea7SAntoine Tenart { 122873f36ea7SAntoine Tenart return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha1", 122973f36ea7SAntoine Tenart SHA1_DIGEST_SIZE); 123073f36ea7SAntoine Tenart } 123173f36ea7SAntoine Tenart 12321b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_hmac_sha1 = { 12331b44c5a6SAntoine Ténart .type = SAFEXCEL_ALG_TYPE_AHASH, 1234062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA1, 12351b44c5a6SAntoine Ténart .alg.ahash = { 12361b44c5a6SAntoine Ténart .init = safexcel_hmac_sha1_init, 12371b44c5a6SAntoine Ténart .update = safexcel_ahash_update, 12381b44c5a6SAntoine Ténart .final = safexcel_ahash_final, 12391b44c5a6SAntoine Ténart .finup = safexcel_ahash_finup, 12401b44c5a6SAntoine Ténart .digest = safexcel_hmac_sha1_digest, 12411b44c5a6SAntoine Ténart .setkey = safexcel_hmac_sha1_setkey, 12421b44c5a6SAntoine Ténart .export = safexcel_ahash_export, 12431b44c5a6SAntoine Ténart .import = safexcel_ahash_import, 12441b44c5a6SAntoine Ténart .halg = { 12451b44c5a6SAntoine Ténart .digestsize = SHA1_DIGEST_SIZE, 12461b44c5a6SAntoine Ténart .statesize = sizeof(struct safexcel_ahash_export_state), 12471b44c5a6SAntoine Ténart .base = { 12481b44c5a6SAntoine Ténart .cra_name = "hmac(sha1)", 12491b44c5a6SAntoine Ténart .cra_driver_name = "safexcel-hmac-sha1", 1250aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 12511b44c5a6SAntoine Ténart .cra_flags = CRYPTO_ALG_ASYNC | 1252b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 12531b44c5a6SAntoine Ténart CRYPTO_ALG_KERN_DRIVER_ONLY, 12541b44c5a6SAntoine Ténart .cra_blocksize = SHA1_BLOCK_SIZE, 12551b44c5a6SAntoine Ténart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 12561b44c5a6SAntoine Ténart .cra_init = safexcel_ahash_cra_init, 12571b44c5a6SAntoine Ténart .cra_exit = safexcel_ahash_cra_exit, 12581b44c5a6SAntoine Ténart .cra_module = THIS_MODULE, 12591b44c5a6SAntoine Ténart }, 12601b44c5a6SAntoine Ténart }, 12611b44c5a6SAntoine Ténart }, 12621b44c5a6SAntoine Ténart }; 12631b44c5a6SAntoine Ténart 12641b44c5a6SAntoine Ténart static int safexcel_sha256_init(struct ahash_request *areq) 12651b44c5a6SAntoine Ténart { 12661b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 12671b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 12681b44c5a6SAntoine Ténart 12691b44c5a6SAntoine Ténart memset(req, 0, sizeof(*req)); 12701b44c5a6SAntoine Ténart 12711b44c5a6SAntoine Ténart ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256; 1272b869648cSAntoine Tenart req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 12731b44c5a6SAntoine Ténart req->state_sz = SHA256_DIGEST_SIZE; 12746c1c09b3SPascal van Leeuwen req->digest_sz = SHA256_DIGEST_SIZE; 127541abed7dSPascal van Leeuwen req->block_sz = SHA256_BLOCK_SIZE; 12761b44c5a6SAntoine Ténart 12771b44c5a6SAntoine Ténart return 0; 12781b44c5a6SAntoine Ténart } 12791b44c5a6SAntoine Ténart 12801b44c5a6SAntoine Ténart static int safexcel_sha256_digest(struct ahash_request *areq) 12811b44c5a6SAntoine Ténart { 12821b44c5a6SAntoine Ténart int ret = safexcel_sha256_init(areq); 12831b44c5a6SAntoine Ténart 12841b44c5a6SAntoine Ténart if (ret) 12851b44c5a6SAntoine Ténart return ret; 12861b44c5a6SAntoine Ténart 12871b44c5a6SAntoine Ténart return safexcel_ahash_finup(areq); 12881b44c5a6SAntoine Ténart } 12891b44c5a6SAntoine Ténart 12901b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha256 = { 12911b44c5a6SAntoine Ténart .type = SAFEXCEL_ALG_TYPE_AHASH, 1292062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA2_256, 12931b44c5a6SAntoine Ténart .alg.ahash = { 12941b44c5a6SAntoine Ténart .init = safexcel_sha256_init, 12951b44c5a6SAntoine Ténart .update = safexcel_ahash_update, 12961b44c5a6SAntoine Ténart .final = safexcel_ahash_final, 12971b44c5a6SAntoine Ténart .finup = safexcel_ahash_finup, 12981b44c5a6SAntoine Ténart .digest = safexcel_sha256_digest, 12991b44c5a6SAntoine Ténart .export = safexcel_ahash_export, 13001b44c5a6SAntoine Ténart .import = safexcel_ahash_import, 13011b44c5a6SAntoine Ténart .halg = { 13021b44c5a6SAntoine Ténart .digestsize = SHA256_DIGEST_SIZE, 13031b44c5a6SAntoine Ténart .statesize = sizeof(struct safexcel_ahash_export_state), 13041b44c5a6SAntoine Ténart .base = { 13051b44c5a6SAntoine Ténart .cra_name = "sha256", 13061b44c5a6SAntoine Ténart .cra_driver_name = "safexcel-sha256", 1307aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 13081b44c5a6SAntoine Ténart .cra_flags = CRYPTO_ALG_ASYNC | 1309b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 13101b44c5a6SAntoine Ténart CRYPTO_ALG_KERN_DRIVER_ONLY, 13111b44c5a6SAntoine Ténart .cra_blocksize = SHA256_BLOCK_SIZE, 13121b44c5a6SAntoine Ténart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 13131b44c5a6SAntoine Ténart .cra_init = safexcel_ahash_cra_init, 13141b44c5a6SAntoine Ténart .cra_exit = safexcel_ahash_cra_exit, 13151b44c5a6SAntoine Ténart .cra_module = THIS_MODULE, 13161b44c5a6SAntoine Ténart }, 13171b44c5a6SAntoine Ténart }, 13181b44c5a6SAntoine Ténart }, 13191b44c5a6SAntoine Ténart }; 13201b44c5a6SAntoine Ténart 13211b44c5a6SAntoine Ténart static int safexcel_sha224_init(struct ahash_request *areq) 13221b44c5a6SAntoine Ténart { 13231b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 13241b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 13251b44c5a6SAntoine Ténart 13261b44c5a6SAntoine Ténart memset(req, 0, sizeof(*req)); 13271b44c5a6SAntoine Ténart 13281b44c5a6SAntoine Ténart ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224; 1329b869648cSAntoine Tenart req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 13301b44c5a6SAntoine Ténart req->state_sz = SHA256_DIGEST_SIZE; 13316c1c09b3SPascal van Leeuwen req->digest_sz = SHA256_DIGEST_SIZE; 133241abed7dSPascal van Leeuwen req->block_sz = SHA256_BLOCK_SIZE; 13331b44c5a6SAntoine Ténart 13341b44c5a6SAntoine Ténart return 0; 13351b44c5a6SAntoine Ténart } 13361b44c5a6SAntoine Ténart 13371b44c5a6SAntoine Ténart static int safexcel_sha224_digest(struct ahash_request *areq) 13381b44c5a6SAntoine Ténart { 13391b44c5a6SAntoine Ténart int ret = safexcel_sha224_init(areq); 13401b44c5a6SAntoine Ténart 13411b44c5a6SAntoine Ténart if (ret) 13421b44c5a6SAntoine Ténart return ret; 13431b44c5a6SAntoine Ténart 13441b44c5a6SAntoine Ténart return safexcel_ahash_finup(areq); 13451b44c5a6SAntoine Ténart } 13461b44c5a6SAntoine Ténart 13471b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha224 = { 13481b44c5a6SAntoine Ténart .type = SAFEXCEL_ALG_TYPE_AHASH, 1349062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA2_256, 13501b44c5a6SAntoine Ténart .alg.ahash = { 13511b44c5a6SAntoine Ténart .init = safexcel_sha224_init, 13521b44c5a6SAntoine Ténart .update = safexcel_ahash_update, 13531b44c5a6SAntoine Ténart .final = safexcel_ahash_final, 13541b44c5a6SAntoine Ténart .finup = safexcel_ahash_finup, 13551b44c5a6SAntoine Ténart .digest = safexcel_sha224_digest, 13561b44c5a6SAntoine Ténart .export = safexcel_ahash_export, 13571b44c5a6SAntoine Ténart .import = safexcel_ahash_import, 13581b44c5a6SAntoine Ténart .halg = { 13591b44c5a6SAntoine Ténart .digestsize = SHA224_DIGEST_SIZE, 13601b44c5a6SAntoine Ténart .statesize = sizeof(struct safexcel_ahash_export_state), 13611b44c5a6SAntoine Ténart .base = { 13621b44c5a6SAntoine Ténart .cra_name = "sha224", 13631b44c5a6SAntoine Ténart .cra_driver_name = "safexcel-sha224", 1364aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 13651b44c5a6SAntoine Ténart .cra_flags = CRYPTO_ALG_ASYNC | 1366b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 13671b44c5a6SAntoine Ténart CRYPTO_ALG_KERN_DRIVER_ONLY, 13681b44c5a6SAntoine Ténart .cra_blocksize = SHA224_BLOCK_SIZE, 13691b44c5a6SAntoine Ténart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 13701b44c5a6SAntoine Ténart .cra_init = safexcel_ahash_cra_init, 13711b44c5a6SAntoine Ténart .cra_exit = safexcel_ahash_cra_exit, 13721b44c5a6SAntoine Ténart .cra_module = THIS_MODULE, 13731b44c5a6SAntoine Ténart }, 13741b44c5a6SAntoine Ténart }, 13751b44c5a6SAntoine Ténart }, 13761b44c5a6SAntoine Ténart }; 137773f36ea7SAntoine Tenart 13783ad618d8SAntoine Tenart static int safexcel_hmac_sha224_setkey(struct crypto_ahash *tfm, const u8 *key, 13793ad618d8SAntoine Tenart unsigned int keylen) 13803ad618d8SAntoine Tenart { 13813ad618d8SAntoine Tenart return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha224", 13823ad618d8SAntoine Tenart SHA256_DIGEST_SIZE); 13833ad618d8SAntoine Tenart } 13843ad618d8SAntoine Tenart 13853ad618d8SAntoine Tenart static int safexcel_hmac_sha224_init(struct ahash_request *areq) 13863ad618d8SAntoine Tenart { 138741abed7dSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 13883ad618d8SAntoine Tenart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 13893ad618d8SAntoine Tenart 139041abed7dSPascal van Leeuwen memset(req, 0, sizeof(*req)); 139141abed7dSPascal van Leeuwen 139241abed7dSPascal van Leeuwen /* Start from ipad precompute */ 139378cf1c8bSHerbert Xu memcpy(req->state, &ctx->base.ipad, SHA256_DIGEST_SIZE); 139441abed7dSPascal van Leeuwen /* Already processed the key^ipad part now! */ 139531fb084cSPascal van Leeuwen req->len = SHA256_BLOCK_SIZE; 139631fb084cSPascal van Leeuwen req->processed = SHA256_BLOCK_SIZE; 139741abed7dSPascal van Leeuwen 139841abed7dSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224; 139941abed7dSPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 140041abed7dSPascal van Leeuwen req->state_sz = SHA256_DIGEST_SIZE; 14016c1c09b3SPascal van Leeuwen req->digest_sz = SHA256_DIGEST_SIZE; 140241abed7dSPascal van Leeuwen req->block_sz = SHA256_BLOCK_SIZE; 140341abed7dSPascal van Leeuwen req->hmac = true; 140441abed7dSPascal van Leeuwen 14053ad618d8SAntoine Tenart return 0; 14063ad618d8SAntoine Tenart } 14073ad618d8SAntoine Tenart 14083ad618d8SAntoine Tenart static int safexcel_hmac_sha224_digest(struct ahash_request *areq) 14093ad618d8SAntoine Tenart { 14103ad618d8SAntoine Tenart int ret = safexcel_hmac_sha224_init(areq); 14113ad618d8SAntoine Tenart 14123ad618d8SAntoine Tenart if (ret) 14133ad618d8SAntoine Tenart return ret; 14143ad618d8SAntoine Tenart 14153ad618d8SAntoine Tenart return safexcel_ahash_finup(areq); 14163ad618d8SAntoine Tenart } 14173ad618d8SAntoine Tenart 14183ad618d8SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha224 = { 14193ad618d8SAntoine Tenart .type = SAFEXCEL_ALG_TYPE_AHASH, 1420062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA2_256, 14213ad618d8SAntoine Tenart .alg.ahash = { 14223ad618d8SAntoine Tenart .init = safexcel_hmac_sha224_init, 14233ad618d8SAntoine Tenart .update = safexcel_ahash_update, 14243ad618d8SAntoine Tenart .final = safexcel_ahash_final, 14253ad618d8SAntoine Tenart .finup = safexcel_ahash_finup, 14263ad618d8SAntoine Tenart .digest = safexcel_hmac_sha224_digest, 14273ad618d8SAntoine Tenart .setkey = safexcel_hmac_sha224_setkey, 14283ad618d8SAntoine Tenart .export = safexcel_ahash_export, 14293ad618d8SAntoine Tenart .import = safexcel_ahash_import, 14303ad618d8SAntoine Tenart .halg = { 14313ad618d8SAntoine Tenart .digestsize = SHA224_DIGEST_SIZE, 14323ad618d8SAntoine Tenart .statesize = sizeof(struct safexcel_ahash_export_state), 14333ad618d8SAntoine Tenart .base = { 14343ad618d8SAntoine Tenart .cra_name = "hmac(sha224)", 14353ad618d8SAntoine Tenart .cra_driver_name = "safexcel-hmac-sha224", 1436aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 14373ad618d8SAntoine Tenart .cra_flags = CRYPTO_ALG_ASYNC | 1438b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 14393ad618d8SAntoine Tenart CRYPTO_ALG_KERN_DRIVER_ONLY, 14403ad618d8SAntoine Tenart .cra_blocksize = SHA224_BLOCK_SIZE, 14413ad618d8SAntoine Tenart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 14423ad618d8SAntoine Tenart .cra_init = safexcel_ahash_cra_init, 14433ad618d8SAntoine Tenart .cra_exit = safexcel_ahash_cra_exit, 14443ad618d8SAntoine Tenart .cra_module = THIS_MODULE, 14453ad618d8SAntoine Tenart }, 14463ad618d8SAntoine Tenart }, 14473ad618d8SAntoine Tenart }, 14483ad618d8SAntoine Tenart }; 14493ad618d8SAntoine Tenart 145073f36ea7SAntoine Tenart static int safexcel_hmac_sha256_setkey(struct crypto_ahash *tfm, const u8 *key, 145173f36ea7SAntoine Tenart unsigned int keylen) 145273f36ea7SAntoine Tenart { 145373f36ea7SAntoine Tenart return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha256", 145473f36ea7SAntoine Tenart SHA256_DIGEST_SIZE); 145573f36ea7SAntoine Tenart } 145673f36ea7SAntoine Tenart 145773f36ea7SAntoine Tenart static int safexcel_hmac_sha256_init(struct ahash_request *areq) 145873f36ea7SAntoine Tenart { 145941abed7dSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 146073f36ea7SAntoine Tenart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 146173f36ea7SAntoine Tenart 146241abed7dSPascal van Leeuwen memset(req, 0, sizeof(*req)); 146341abed7dSPascal van Leeuwen 146441abed7dSPascal van Leeuwen /* Start from ipad precompute */ 146578cf1c8bSHerbert Xu memcpy(req->state, &ctx->base.ipad, SHA256_DIGEST_SIZE); 146641abed7dSPascal van Leeuwen /* Already processed the key^ipad part now! */ 146731fb084cSPascal van Leeuwen req->len = SHA256_BLOCK_SIZE; 146831fb084cSPascal van Leeuwen req->processed = SHA256_BLOCK_SIZE; 146941abed7dSPascal van Leeuwen 147041abed7dSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256; 147141abed7dSPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 147241abed7dSPascal van Leeuwen req->state_sz = SHA256_DIGEST_SIZE; 14736c1c09b3SPascal van Leeuwen req->digest_sz = SHA256_DIGEST_SIZE; 147441abed7dSPascal van Leeuwen req->block_sz = SHA256_BLOCK_SIZE; 147541abed7dSPascal van Leeuwen req->hmac = true; 147641abed7dSPascal van Leeuwen 147773f36ea7SAntoine Tenart return 0; 147873f36ea7SAntoine Tenart } 147973f36ea7SAntoine Tenart 148073f36ea7SAntoine Tenart static int safexcel_hmac_sha256_digest(struct ahash_request *areq) 148173f36ea7SAntoine Tenart { 148273f36ea7SAntoine Tenart int ret = safexcel_hmac_sha256_init(areq); 148373f36ea7SAntoine Tenart 148473f36ea7SAntoine Tenart if (ret) 148573f36ea7SAntoine Tenart return ret; 148673f36ea7SAntoine Tenart 148773f36ea7SAntoine Tenart return safexcel_ahash_finup(areq); 148873f36ea7SAntoine Tenart } 148973f36ea7SAntoine Tenart 149073f36ea7SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha256 = { 149173f36ea7SAntoine Tenart .type = SAFEXCEL_ALG_TYPE_AHASH, 1492062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA2_256, 149373f36ea7SAntoine Tenart .alg.ahash = { 149473f36ea7SAntoine Tenart .init = safexcel_hmac_sha256_init, 149573f36ea7SAntoine Tenart .update = safexcel_ahash_update, 149673f36ea7SAntoine Tenart .final = safexcel_ahash_final, 149773f36ea7SAntoine Tenart .finup = safexcel_ahash_finup, 149873f36ea7SAntoine Tenart .digest = safexcel_hmac_sha256_digest, 149973f36ea7SAntoine Tenart .setkey = safexcel_hmac_sha256_setkey, 150073f36ea7SAntoine Tenart .export = safexcel_ahash_export, 150173f36ea7SAntoine Tenart .import = safexcel_ahash_import, 150273f36ea7SAntoine Tenart .halg = { 150373f36ea7SAntoine Tenart .digestsize = SHA256_DIGEST_SIZE, 150473f36ea7SAntoine Tenart .statesize = sizeof(struct safexcel_ahash_export_state), 150573f36ea7SAntoine Tenart .base = { 150673f36ea7SAntoine Tenart .cra_name = "hmac(sha256)", 150773f36ea7SAntoine Tenart .cra_driver_name = "safexcel-hmac-sha256", 1508aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 150973f36ea7SAntoine Tenart .cra_flags = CRYPTO_ALG_ASYNC | 1510b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 151173f36ea7SAntoine Tenart CRYPTO_ALG_KERN_DRIVER_ONLY, 151273f36ea7SAntoine Tenart .cra_blocksize = SHA256_BLOCK_SIZE, 151373f36ea7SAntoine Tenart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 151473f36ea7SAntoine Tenart .cra_init = safexcel_ahash_cra_init, 151573f36ea7SAntoine Tenart .cra_exit = safexcel_ahash_cra_exit, 151673f36ea7SAntoine Tenart .cra_module = THIS_MODULE, 151773f36ea7SAntoine Tenart }, 151873f36ea7SAntoine Tenart }, 151973f36ea7SAntoine Tenart }, 152073f36ea7SAntoine Tenart }; 1521b460edb6SAntoine Tenart 1522b460edb6SAntoine Tenart static int safexcel_sha512_init(struct ahash_request *areq) 1523b460edb6SAntoine Tenart { 1524b460edb6SAntoine Tenart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 1525b460edb6SAntoine Tenart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 1526b460edb6SAntoine Tenart 1527b460edb6SAntoine Tenart memset(req, 0, sizeof(*req)); 1528b460edb6SAntoine Tenart 1529b460edb6SAntoine Tenart ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512; 1530b460edb6SAntoine Tenart req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 1531b460edb6SAntoine Tenart req->state_sz = SHA512_DIGEST_SIZE; 15326c1c09b3SPascal van Leeuwen req->digest_sz = SHA512_DIGEST_SIZE; 153341abed7dSPascal van Leeuwen req->block_sz = SHA512_BLOCK_SIZE; 1534b460edb6SAntoine Tenart 1535b460edb6SAntoine Tenart return 0; 1536b460edb6SAntoine Tenart } 1537b460edb6SAntoine Tenart 1538b460edb6SAntoine Tenart static int safexcel_sha512_digest(struct ahash_request *areq) 1539b460edb6SAntoine Tenart { 1540b460edb6SAntoine Tenart int ret = safexcel_sha512_init(areq); 1541b460edb6SAntoine Tenart 1542b460edb6SAntoine Tenart if (ret) 1543b460edb6SAntoine Tenart return ret; 1544b460edb6SAntoine Tenart 1545b460edb6SAntoine Tenart return safexcel_ahash_finup(areq); 1546b460edb6SAntoine Tenart } 1547b460edb6SAntoine Tenart 1548b460edb6SAntoine Tenart struct safexcel_alg_template safexcel_alg_sha512 = { 1549b460edb6SAntoine Tenart .type = SAFEXCEL_ALG_TYPE_AHASH, 1550062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA2_512, 1551b460edb6SAntoine Tenart .alg.ahash = { 1552b460edb6SAntoine Tenart .init = safexcel_sha512_init, 1553b460edb6SAntoine Tenart .update = safexcel_ahash_update, 1554b460edb6SAntoine Tenart .final = safexcel_ahash_final, 1555b460edb6SAntoine Tenart .finup = safexcel_ahash_finup, 1556b460edb6SAntoine Tenart .digest = safexcel_sha512_digest, 1557b460edb6SAntoine Tenart .export = safexcel_ahash_export, 1558b460edb6SAntoine Tenart .import = safexcel_ahash_import, 1559b460edb6SAntoine Tenart .halg = { 1560b460edb6SAntoine Tenart .digestsize = SHA512_DIGEST_SIZE, 1561b460edb6SAntoine Tenart .statesize = sizeof(struct safexcel_ahash_export_state), 1562b460edb6SAntoine Tenart .base = { 1563b460edb6SAntoine Tenart .cra_name = "sha512", 1564b460edb6SAntoine Tenart .cra_driver_name = "safexcel-sha512", 1565aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 1566b460edb6SAntoine Tenart .cra_flags = CRYPTO_ALG_ASYNC | 1567b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 1568b460edb6SAntoine Tenart CRYPTO_ALG_KERN_DRIVER_ONLY, 1569b460edb6SAntoine Tenart .cra_blocksize = SHA512_BLOCK_SIZE, 1570b460edb6SAntoine Tenart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 1571b460edb6SAntoine Tenart .cra_init = safexcel_ahash_cra_init, 1572b460edb6SAntoine Tenart .cra_exit = safexcel_ahash_cra_exit, 1573b460edb6SAntoine Tenart .cra_module = THIS_MODULE, 1574b460edb6SAntoine Tenart }, 1575b460edb6SAntoine Tenart }, 1576b460edb6SAntoine Tenart }, 1577b460edb6SAntoine Tenart }; 15780de54fb1SAntoine Tenart 15799e46eafdSAntoine Tenart static int safexcel_sha384_init(struct ahash_request *areq) 15809e46eafdSAntoine Tenart { 15819e46eafdSAntoine Tenart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 15829e46eafdSAntoine Tenart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 15839e46eafdSAntoine Tenart 15849e46eafdSAntoine Tenart memset(req, 0, sizeof(*req)); 15859e46eafdSAntoine Tenart 15869e46eafdSAntoine Tenart ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384; 15879e46eafdSAntoine Tenart req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 15889e46eafdSAntoine Tenart req->state_sz = SHA512_DIGEST_SIZE; 15896c1c09b3SPascal van Leeuwen req->digest_sz = SHA512_DIGEST_SIZE; 159041abed7dSPascal van Leeuwen req->block_sz = SHA512_BLOCK_SIZE; 15919e46eafdSAntoine Tenart 15929e46eafdSAntoine Tenart return 0; 15939e46eafdSAntoine Tenart } 15949e46eafdSAntoine Tenart 15959e46eafdSAntoine Tenart static int safexcel_sha384_digest(struct ahash_request *areq) 15969e46eafdSAntoine Tenart { 15979e46eafdSAntoine Tenart int ret = safexcel_sha384_init(areq); 15989e46eafdSAntoine Tenart 15999e46eafdSAntoine Tenart if (ret) 16009e46eafdSAntoine Tenart return ret; 16019e46eafdSAntoine Tenart 16029e46eafdSAntoine Tenart return safexcel_ahash_finup(areq); 16039e46eafdSAntoine Tenart } 16049e46eafdSAntoine Tenart 16059e46eafdSAntoine Tenart struct safexcel_alg_template safexcel_alg_sha384 = { 16069e46eafdSAntoine Tenart .type = SAFEXCEL_ALG_TYPE_AHASH, 1607062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA2_512, 16089e46eafdSAntoine Tenart .alg.ahash = { 16099e46eafdSAntoine Tenart .init = safexcel_sha384_init, 16109e46eafdSAntoine Tenart .update = safexcel_ahash_update, 16119e46eafdSAntoine Tenart .final = safexcel_ahash_final, 16129e46eafdSAntoine Tenart .finup = safexcel_ahash_finup, 16139e46eafdSAntoine Tenart .digest = safexcel_sha384_digest, 16149e46eafdSAntoine Tenart .export = safexcel_ahash_export, 16159e46eafdSAntoine Tenart .import = safexcel_ahash_import, 16169e46eafdSAntoine Tenart .halg = { 16179e46eafdSAntoine Tenart .digestsize = SHA384_DIGEST_SIZE, 16189e46eafdSAntoine Tenart .statesize = sizeof(struct safexcel_ahash_export_state), 16199e46eafdSAntoine Tenart .base = { 16209e46eafdSAntoine Tenart .cra_name = "sha384", 16219e46eafdSAntoine Tenart .cra_driver_name = "safexcel-sha384", 1622aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 16239e46eafdSAntoine Tenart .cra_flags = CRYPTO_ALG_ASYNC | 1624b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 16259e46eafdSAntoine Tenart CRYPTO_ALG_KERN_DRIVER_ONLY, 16269e46eafdSAntoine Tenart .cra_blocksize = SHA384_BLOCK_SIZE, 16279e46eafdSAntoine Tenart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 16289e46eafdSAntoine Tenart .cra_init = safexcel_ahash_cra_init, 16299e46eafdSAntoine Tenart .cra_exit = safexcel_ahash_cra_exit, 16309e46eafdSAntoine Tenart .cra_module = THIS_MODULE, 16319e46eafdSAntoine Tenart }, 16329e46eafdSAntoine Tenart }, 16339e46eafdSAntoine Tenart }, 16349e46eafdSAntoine Tenart }; 16359e46eafdSAntoine Tenart 16360de54fb1SAntoine Tenart static int safexcel_hmac_sha512_setkey(struct crypto_ahash *tfm, const u8 *key, 16370de54fb1SAntoine Tenart unsigned int keylen) 16380de54fb1SAntoine Tenart { 16390de54fb1SAntoine Tenart return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha512", 16400de54fb1SAntoine Tenart SHA512_DIGEST_SIZE); 16410de54fb1SAntoine Tenart } 16420de54fb1SAntoine Tenart 16430de54fb1SAntoine Tenart static int safexcel_hmac_sha512_init(struct ahash_request *areq) 16440de54fb1SAntoine Tenart { 164541abed7dSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 16460de54fb1SAntoine Tenart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 16470de54fb1SAntoine Tenart 164841abed7dSPascal van Leeuwen memset(req, 0, sizeof(*req)); 164941abed7dSPascal van Leeuwen 165041abed7dSPascal van Leeuwen /* Start from ipad precompute */ 165178cf1c8bSHerbert Xu memcpy(req->state, &ctx->base.ipad, SHA512_DIGEST_SIZE); 165241abed7dSPascal van Leeuwen /* Already processed the key^ipad part now! */ 165331fb084cSPascal van Leeuwen req->len = SHA512_BLOCK_SIZE; 165431fb084cSPascal van Leeuwen req->processed = SHA512_BLOCK_SIZE; 165541abed7dSPascal van Leeuwen 165641abed7dSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512; 165741abed7dSPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 165841abed7dSPascal van Leeuwen req->state_sz = SHA512_DIGEST_SIZE; 16596c1c09b3SPascal van Leeuwen req->digest_sz = SHA512_DIGEST_SIZE; 166041abed7dSPascal van Leeuwen req->block_sz = SHA512_BLOCK_SIZE; 166141abed7dSPascal van Leeuwen req->hmac = true; 166241abed7dSPascal van Leeuwen 16630de54fb1SAntoine Tenart return 0; 16640de54fb1SAntoine Tenart } 16650de54fb1SAntoine Tenart 16660de54fb1SAntoine Tenart static int safexcel_hmac_sha512_digest(struct ahash_request *areq) 16670de54fb1SAntoine Tenart { 16680de54fb1SAntoine Tenart int ret = safexcel_hmac_sha512_init(areq); 16690de54fb1SAntoine Tenart 16700de54fb1SAntoine Tenart if (ret) 16710de54fb1SAntoine Tenart return ret; 16720de54fb1SAntoine Tenart 16730de54fb1SAntoine Tenart return safexcel_ahash_finup(areq); 16740de54fb1SAntoine Tenart } 16750de54fb1SAntoine Tenart 16760de54fb1SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha512 = { 16770de54fb1SAntoine Tenart .type = SAFEXCEL_ALG_TYPE_AHASH, 1678062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA2_512, 16790de54fb1SAntoine Tenart .alg.ahash = { 16800de54fb1SAntoine Tenart .init = safexcel_hmac_sha512_init, 16810de54fb1SAntoine Tenart .update = safexcel_ahash_update, 16820de54fb1SAntoine Tenart .final = safexcel_ahash_final, 16830de54fb1SAntoine Tenart .finup = safexcel_ahash_finup, 16840de54fb1SAntoine Tenart .digest = safexcel_hmac_sha512_digest, 16850de54fb1SAntoine Tenart .setkey = safexcel_hmac_sha512_setkey, 16860de54fb1SAntoine Tenart .export = safexcel_ahash_export, 16870de54fb1SAntoine Tenart .import = safexcel_ahash_import, 16880de54fb1SAntoine Tenart .halg = { 16890de54fb1SAntoine Tenart .digestsize = SHA512_DIGEST_SIZE, 16900de54fb1SAntoine Tenart .statesize = sizeof(struct safexcel_ahash_export_state), 16910de54fb1SAntoine Tenart .base = { 16920de54fb1SAntoine Tenart .cra_name = "hmac(sha512)", 16930de54fb1SAntoine Tenart .cra_driver_name = "safexcel-hmac-sha512", 1694aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 16950de54fb1SAntoine Tenart .cra_flags = CRYPTO_ALG_ASYNC | 1696b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 16970de54fb1SAntoine Tenart CRYPTO_ALG_KERN_DRIVER_ONLY, 16980de54fb1SAntoine Tenart .cra_blocksize = SHA512_BLOCK_SIZE, 16990de54fb1SAntoine Tenart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 17000de54fb1SAntoine Tenart .cra_init = safexcel_ahash_cra_init, 17010de54fb1SAntoine Tenart .cra_exit = safexcel_ahash_cra_exit, 17020de54fb1SAntoine Tenart .cra_module = THIS_MODULE, 17030de54fb1SAntoine Tenart }, 17040de54fb1SAntoine Tenart }, 17050de54fb1SAntoine Tenart }, 17060de54fb1SAntoine Tenart }; 17071f5d5d98SAntoine Tenart 17081f5d5d98SAntoine Tenart static int safexcel_hmac_sha384_setkey(struct crypto_ahash *tfm, const u8 *key, 17091f5d5d98SAntoine Tenart unsigned int keylen) 17101f5d5d98SAntoine Tenart { 17111f5d5d98SAntoine Tenart return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha384", 17121f5d5d98SAntoine Tenart SHA512_DIGEST_SIZE); 17131f5d5d98SAntoine Tenart } 17141f5d5d98SAntoine Tenart 17151f5d5d98SAntoine Tenart static int safexcel_hmac_sha384_init(struct ahash_request *areq) 17161f5d5d98SAntoine Tenart { 171741abed7dSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 17181f5d5d98SAntoine Tenart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 17191f5d5d98SAntoine Tenart 172041abed7dSPascal van Leeuwen memset(req, 0, sizeof(*req)); 172141abed7dSPascal van Leeuwen 172241abed7dSPascal van Leeuwen /* Start from ipad precompute */ 172378cf1c8bSHerbert Xu memcpy(req->state, &ctx->base.ipad, SHA512_DIGEST_SIZE); 172441abed7dSPascal van Leeuwen /* Already processed the key^ipad part now! */ 172531fb084cSPascal van Leeuwen req->len = SHA512_BLOCK_SIZE; 172631fb084cSPascal van Leeuwen req->processed = SHA512_BLOCK_SIZE; 172741abed7dSPascal van Leeuwen 172841abed7dSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384; 172941abed7dSPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 173041abed7dSPascal van Leeuwen req->state_sz = SHA512_DIGEST_SIZE; 17316c1c09b3SPascal van Leeuwen req->digest_sz = SHA512_DIGEST_SIZE; 173241abed7dSPascal van Leeuwen req->block_sz = SHA512_BLOCK_SIZE; 173341abed7dSPascal van Leeuwen req->hmac = true; 173441abed7dSPascal van Leeuwen 17351f5d5d98SAntoine Tenart return 0; 17361f5d5d98SAntoine Tenart } 17371f5d5d98SAntoine Tenart 17381f5d5d98SAntoine Tenart static int safexcel_hmac_sha384_digest(struct ahash_request *areq) 17391f5d5d98SAntoine Tenart { 17401f5d5d98SAntoine Tenart int ret = safexcel_hmac_sha384_init(areq); 17411f5d5d98SAntoine Tenart 17421f5d5d98SAntoine Tenart if (ret) 17431f5d5d98SAntoine Tenart return ret; 17441f5d5d98SAntoine Tenart 17451f5d5d98SAntoine Tenart return safexcel_ahash_finup(areq); 17461f5d5d98SAntoine Tenart } 17471f5d5d98SAntoine Tenart 17481f5d5d98SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha384 = { 17491f5d5d98SAntoine Tenart .type = SAFEXCEL_ALG_TYPE_AHASH, 1750062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA2_512, 17511f5d5d98SAntoine Tenart .alg.ahash = { 17521f5d5d98SAntoine Tenart .init = safexcel_hmac_sha384_init, 17531f5d5d98SAntoine Tenart .update = safexcel_ahash_update, 17541f5d5d98SAntoine Tenart .final = safexcel_ahash_final, 17551f5d5d98SAntoine Tenart .finup = safexcel_ahash_finup, 17561f5d5d98SAntoine Tenart .digest = safexcel_hmac_sha384_digest, 17571f5d5d98SAntoine Tenart .setkey = safexcel_hmac_sha384_setkey, 17581f5d5d98SAntoine Tenart .export = safexcel_ahash_export, 17591f5d5d98SAntoine Tenart .import = safexcel_ahash_import, 17601f5d5d98SAntoine Tenart .halg = { 17611f5d5d98SAntoine Tenart .digestsize = SHA384_DIGEST_SIZE, 17621f5d5d98SAntoine Tenart .statesize = sizeof(struct safexcel_ahash_export_state), 17631f5d5d98SAntoine Tenart .base = { 17641f5d5d98SAntoine Tenart .cra_name = "hmac(sha384)", 17651f5d5d98SAntoine Tenart .cra_driver_name = "safexcel-hmac-sha384", 1766aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 17671f5d5d98SAntoine Tenart .cra_flags = CRYPTO_ALG_ASYNC | 1768b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 17691f5d5d98SAntoine Tenart CRYPTO_ALG_KERN_DRIVER_ONLY, 17701f5d5d98SAntoine Tenart .cra_blocksize = SHA384_BLOCK_SIZE, 17711f5d5d98SAntoine Tenart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 17721f5d5d98SAntoine Tenart .cra_init = safexcel_ahash_cra_init, 17731f5d5d98SAntoine Tenart .cra_exit = safexcel_ahash_cra_exit, 17741f5d5d98SAntoine Tenart .cra_module = THIS_MODULE, 17751f5d5d98SAntoine Tenart }, 17761f5d5d98SAntoine Tenart }, 17771f5d5d98SAntoine Tenart }, 17781f5d5d98SAntoine Tenart }; 1779293f89cfSOfer Heifetz 1780293f89cfSOfer Heifetz static int safexcel_md5_init(struct ahash_request *areq) 1781293f89cfSOfer Heifetz { 1782293f89cfSOfer Heifetz struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 1783293f89cfSOfer Heifetz struct safexcel_ahash_req *req = ahash_request_ctx(areq); 1784293f89cfSOfer Heifetz 1785293f89cfSOfer Heifetz memset(req, 0, sizeof(*req)); 1786293f89cfSOfer Heifetz 1787293f89cfSOfer Heifetz ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_MD5; 1788293f89cfSOfer Heifetz req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 1789293f89cfSOfer Heifetz req->state_sz = MD5_DIGEST_SIZE; 17906c1c09b3SPascal van Leeuwen req->digest_sz = MD5_DIGEST_SIZE; 179141abed7dSPascal van Leeuwen req->block_sz = MD5_HMAC_BLOCK_SIZE; 1792293f89cfSOfer Heifetz 1793293f89cfSOfer Heifetz return 0; 1794293f89cfSOfer Heifetz } 1795293f89cfSOfer Heifetz 1796293f89cfSOfer Heifetz static int safexcel_md5_digest(struct ahash_request *areq) 1797293f89cfSOfer Heifetz { 1798293f89cfSOfer Heifetz int ret = safexcel_md5_init(areq); 1799293f89cfSOfer Heifetz 1800293f89cfSOfer Heifetz if (ret) 1801293f89cfSOfer Heifetz return ret; 1802293f89cfSOfer Heifetz 1803293f89cfSOfer Heifetz return safexcel_ahash_finup(areq); 1804293f89cfSOfer Heifetz } 1805293f89cfSOfer Heifetz 1806293f89cfSOfer Heifetz struct safexcel_alg_template safexcel_alg_md5 = { 1807293f89cfSOfer Heifetz .type = SAFEXCEL_ALG_TYPE_AHASH, 1808062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_MD5, 1809293f89cfSOfer Heifetz .alg.ahash = { 1810293f89cfSOfer Heifetz .init = safexcel_md5_init, 1811293f89cfSOfer Heifetz .update = safexcel_ahash_update, 1812293f89cfSOfer Heifetz .final = safexcel_ahash_final, 1813293f89cfSOfer Heifetz .finup = safexcel_ahash_finup, 1814293f89cfSOfer Heifetz .digest = safexcel_md5_digest, 1815293f89cfSOfer Heifetz .export = safexcel_ahash_export, 1816293f89cfSOfer Heifetz .import = safexcel_ahash_import, 1817293f89cfSOfer Heifetz .halg = { 1818293f89cfSOfer Heifetz .digestsize = MD5_DIGEST_SIZE, 1819293f89cfSOfer Heifetz .statesize = sizeof(struct safexcel_ahash_export_state), 1820293f89cfSOfer Heifetz .base = { 1821293f89cfSOfer Heifetz .cra_name = "md5", 1822293f89cfSOfer Heifetz .cra_driver_name = "safexcel-md5", 1823aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 1824293f89cfSOfer Heifetz .cra_flags = CRYPTO_ALG_ASYNC | 1825b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 1826293f89cfSOfer Heifetz CRYPTO_ALG_KERN_DRIVER_ONLY, 1827293f89cfSOfer Heifetz .cra_blocksize = MD5_HMAC_BLOCK_SIZE, 1828293f89cfSOfer Heifetz .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 1829293f89cfSOfer Heifetz .cra_init = safexcel_ahash_cra_init, 1830293f89cfSOfer Heifetz .cra_exit = safexcel_ahash_cra_exit, 1831293f89cfSOfer Heifetz .cra_module = THIS_MODULE, 1832293f89cfSOfer Heifetz }, 1833293f89cfSOfer Heifetz }, 1834293f89cfSOfer Heifetz }, 1835293f89cfSOfer Heifetz }; 1836b471e4b9SOfer Heifetz 1837b471e4b9SOfer Heifetz static int safexcel_hmac_md5_init(struct ahash_request *areq) 1838b471e4b9SOfer Heifetz { 183941abed7dSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 1840b471e4b9SOfer Heifetz struct safexcel_ahash_req *req = ahash_request_ctx(areq); 1841b471e4b9SOfer Heifetz 184241abed7dSPascal van Leeuwen memset(req, 0, sizeof(*req)); 184341abed7dSPascal van Leeuwen 184441abed7dSPascal van Leeuwen /* Start from ipad precompute */ 184578cf1c8bSHerbert Xu memcpy(req->state, &ctx->base.ipad, MD5_DIGEST_SIZE); 184641abed7dSPascal van Leeuwen /* Already processed the key^ipad part now! */ 184731fb084cSPascal van Leeuwen req->len = MD5_HMAC_BLOCK_SIZE; 184831fb084cSPascal van Leeuwen req->processed = MD5_HMAC_BLOCK_SIZE; 184941abed7dSPascal van Leeuwen 185041abed7dSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_MD5; 185141abed7dSPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 185241abed7dSPascal van Leeuwen req->state_sz = MD5_DIGEST_SIZE; 18536c1c09b3SPascal van Leeuwen req->digest_sz = MD5_DIGEST_SIZE; 185441abed7dSPascal van Leeuwen req->block_sz = MD5_HMAC_BLOCK_SIZE; 185585b36ee8SPascal van Leeuwen req->len_is_le = true; /* MD5 is little endian! ... */ 185641abed7dSPascal van Leeuwen req->hmac = true; 185741abed7dSPascal van Leeuwen 1858b471e4b9SOfer Heifetz return 0; 1859b471e4b9SOfer Heifetz } 1860b471e4b9SOfer Heifetz 1861b471e4b9SOfer Heifetz static int safexcel_hmac_md5_setkey(struct crypto_ahash *tfm, const u8 *key, 1862b471e4b9SOfer Heifetz unsigned int keylen) 1863b471e4b9SOfer Heifetz { 1864b471e4b9SOfer Heifetz return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-md5", 1865b471e4b9SOfer Heifetz MD5_DIGEST_SIZE); 1866b471e4b9SOfer Heifetz } 1867b471e4b9SOfer Heifetz 1868b471e4b9SOfer Heifetz static int safexcel_hmac_md5_digest(struct ahash_request *areq) 1869b471e4b9SOfer Heifetz { 1870b471e4b9SOfer Heifetz int ret = safexcel_hmac_md5_init(areq); 1871b471e4b9SOfer Heifetz 1872b471e4b9SOfer Heifetz if (ret) 1873b471e4b9SOfer Heifetz return ret; 1874b471e4b9SOfer Heifetz 1875b471e4b9SOfer Heifetz return safexcel_ahash_finup(areq); 1876b471e4b9SOfer Heifetz } 1877b471e4b9SOfer Heifetz 1878b471e4b9SOfer Heifetz struct safexcel_alg_template safexcel_alg_hmac_md5 = { 1879b471e4b9SOfer Heifetz .type = SAFEXCEL_ALG_TYPE_AHASH, 1880062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_MD5, 1881b471e4b9SOfer Heifetz .alg.ahash = { 1882b471e4b9SOfer Heifetz .init = safexcel_hmac_md5_init, 1883b471e4b9SOfer Heifetz .update = safexcel_ahash_update, 1884b471e4b9SOfer Heifetz .final = safexcel_ahash_final, 1885b471e4b9SOfer Heifetz .finup = safexcel_ahash_finup, 1886b471e4b9SOfer Heifetz .digest = safexcel_hmac_md5_digest, 1887b471e4b9SOfer Heifetz .setkey = safexcel_hmac_md5_setkey, 1888b471e4b9SOfer Heifetz .export = safexcel_ahash_export, 1889b471e4b9SOfer Heifetz .import = safexcel_ahash_import, 1890b471e4b9SOfer Heifetz .halg = { 1891b471e4b9SOfer Heifetz .digestsize = MD5_DIGEST_SIZE, 1892b471e4b9SOfer Heifetz .statesize = sizeof(struct safexcel_ahash_export_state), 1893b471e4b9SOfer Heifetz .base = { 1894b471e4b9SOfer Heifetz .cra_name = "hmac(md5)", 1895b471e4b9SOfer Heifetz .cra_driver_name = "safexcel-hmac-md5", 1896aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 1897b471e4b9SOfer Heifetz .cra_flags = CRYPTO_ALG_ASYNC | 1898b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 1899b471e4b9SOfer Heifetz CRYPTO_ALG_KERN_DRIVER_ONLY, 1900b471e4b9SOfer Heifetz .cra_blocksize = MD5_HMAC_BLOCK_SIZE, 1901b471e4b9SOfer Heifetz .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 1902b471e4b9SOfer Heifetz .cra_init = safexcel_ahash_cra_init, 1903b471e4b9SOfer Heifetz .cra_exit = safexcel_ahash_cra_exit, 1904b471e4b9SOfer Heifetz .cra_module = THIS_MODULE, 1905b471e4b9SOfer Heifetz }, 1906b471e4b9SOfer Heifetz }, 1907b471e4b9SOfer Heifetz }, 1908b471e4b9SOfer Heifetz }; 1909a7cf8658SPascal van Leeuwen 1910a7cf8658SPascal van Leeuwen static int safexcel_crc32_cra_init(struct crypto_tfm *tfm) 1911a7cf8658SPascal van Leeuwen { 1912a7cf8658SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 1913a7cf8658SPascal van Leeuwen int ret = safexcel_ahash_cra_init(tfm); 1914a7cf8658SPascal van Leeuwen 1915a7cf8658SPascal van Leeuwen /* Default 'key' is all zeroes */ 191678cf1c8bSHerbert Xu memset(&ctx->base.ipad, 0, sizeof(u32)); 1917a7cf8658SPascal van Leeuwen return ret; 1918a7cf8658SPascal van Leeuwen } 1919a7cf8658SPascal van Leeuwen 1920a7cf8658SPascal van Leeuwen static int safexcel_crc32_init(struct ahash_request *areq) 1921a7cf8658SPascal van Leeuwen { 1922a7cf8658SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 1923a7cf8658SPascal van Leeuwen struct safexcel_ahash_req *req = ahash_request_ctx(areq); 1924a7cf8658SPascal van Leeuwen 1925a7cf8658SPascal van Leeuwen memset(req, 0, sizeof(*req)); 1926a7cf8658SPascal van Leeuwen 1927a7cf8658SPascal van Leeuwen /* Start from loaded key */ 192878cf1c8bSHerbert Xu req->state[0] = cpu_to_le32(~ctx->base.ipad.word[0]); 1929a7cf8658SPascal van Leeuwen /* Set processed to non-zero to enable invalidation detection */ 1930a7cf8658SPascal van Leeuwen req->len = sizeof(u32); 1931a7cf8658SPascal van Leeuwen req->processed = sizeof(u32); 1932a7cf8658SPascal van Leeuwen 1933a7cf8658SPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_CRC32; 1934a7cf8658SPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_XCM; 1935a7cf8658SPascal van Leeuwen req->state_sz = sizeof(u32); 19366c1c09b3SPascal van Leeuwen req->digest_sz = sizeof(u32); 1937a7cf8658SPascal van Leeuwen req->block_sz = sizeof(u32); 1938a7cf8658SPascal van Leeuwen 1939a7cf8658SPascal van Leeuwen return 0; 1940a7cf8658SPascal van Leeuwen } 1941a7cf8658SPascal van Leeuwen 1942a7cf8658SPascal van Leeuwen static int safexcel_crc32_setkey(struct crypto_ahash *tfm, const u8 *key, 1943a7cf8658SPascal van Leeuwen unsigned int keylen) 1944a7cf8658SPascal van Leeuwen { 1945a7cf8658SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 1946a7cf8658SPascal van Leeuwen 1947674f368aSEric Biggers if (keylen != sizeof(u32)) 1948a7cf8658SPascal van Leeuwen return -EINVAL; 1949a7cf8658SPascal van Leeuwen 195078cf1c8bSHerbert Xu memcpy(&ctx->base.ipad, key, sizeof(u32)); 1951a7cf8658SPascal van Leeuwen return 0; 1952a7cf8658SPascal van Leeuwen } 1953a7cf8658SPascal van Leeuwen 1954a7cf8658SPascal van Leeuwen static int safexcel_crc32_digest(struct ahash_request *areq) 1955a7cf8658SPascal van Leeuwen { 1956a7cf8658SPascal van Leeuwen return safexcel_crc32_init(areq) ?: safexcel_ahash_finup(areq); 1957a7cf8658SPascal van Leeuwen } 1958a7cf8658SPascal van Leeuwen 1959a7cf8658SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_crc32 = { 1960a7cf8658SPascal van Leeuwen .type = SAFEXCEL_ALG_TYPE_AHASH, 1961a7cf8658SPascal van Leeuwen .algo_mask = 0, 1962a7cf8658SPascal van Leeuwen .alg.ahash = { 1963a7cf8658SPascal van Leeuwen .init = safexcel_crc32_init, 1964a7cf8658SPascal van Leeuwen .update = safexcel_ahash_update, 1965a7cf8658SPascal van Leeuwen .final = safexcel_ahash_final, 1966a7cf8658SPascal van Leeuwen .finup = safexcel_ahash_finup, 1967a7cf8658SPascal van Leeuwen .digest = safexcel_crc32_digest, 1968a7cf8658SPascal van Leeuwen .setkey = safexcel_crc32_setkey, 1969a7cf8658SPascal van Leeuwen .export = safexcel_ahash_export, 1970a7cf8658SPascal van Leeuwen .import = safexcel_ahash_import, 1971a7cf8658SPascal van Leeuwen .halg = { 1972a7cf8658SPascal van Leeuwen .digestsize = sizeof(u32), 1973a7cf8658SPascal van Leeuwen .statesize = sizeof(struct safexcel_ahash_export_state), 1974a7cf8658SPascal van Leeuwen .base = { 1975a7cf8658SPascal van Leeuwen .cra_name = "crc32", 1976a7cf8658SPascal van Leeuwen .cra_driver_name = "safexcel-crc32", 1977a7cf8658SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 1978a7cf8658SPascal van Leeuwen .cra_flags = CRYPTO_ALG_OPTIONAL_KEY | 1979a7cf8658SPascal van Leeuwen CRYPTO_ALG_ASYNC | 1980b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 1981a7cf8658SPascal van Leeuwen CRYPTO_ALG_KERN_DRIVER_ONLY, 1982a7cf8658SPascal van Leeuwen .cra_blocksize = 1, 1983a7cf8658SPascal van Leeuwen .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 1984a7cf8658SPascal van Leeuwen .cra_init = safexcel_crc32_cra_init, 1985a7cf8658SPascal van Leeuwen .cra_exit = safexcel_ahash_cra_exit, 1986a7cf8658SPascal van Leeuwen .cra_module = THIS_MODULE, 1987a7cf8658SPascal van Leeuwen }, 1988a7cf8658SPascal van Leeuwen }, 1989a7cf8658SPascal van Leeuwen }, 1990a7cf8658SPascal van Leeuwen }; 1991b98687bbSPascal van Leeuwen 1992b98687bbSPascal van Leeuwen static int safexcel_cbcmac_init(struct ahash_request *areq) 1993b98687bbSPascal van Leeuwen { 1994b98687bbSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 1995b98687bbSPascal van Leeuwen struct safexcel_ahash_req *req = ahash_request_ctx(areq); 1996b98687bbSPascal van Leeuwen 1997b98687bbSPascal van Leeuwen memset(req, 0, sizeof(*req)); 1998b98687bbSPascal van Leeuwen 1999b98687bbSPascal van Leeuwen /* Start from loaded keys */ 200078cf1c8bSHerbert Xu memcpy(req->state, &ctx->base.ipad, ctx->key_sz); 2001b98687bbSPascal van Leeuwen /* Set processed to non-zero to enable invalidation detection */ 2002b98687bbSPascal van Leeuwen req->len = AES_BLOCK_SIZE; 2003b98687bbSPascal van Leeuwen req->processed = AES_BLOCK_SIZE; 2004b98687bbSPascal van Leeuwen 2005b98687bbSPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_XCM; 2006b98687bbSPascal van Leeuwen req->state_sz = ctx->key_sz; 20076c1c09b3SPascal van Leeuwen req->digest_sz = AES_BLOCK_SIZE; 2008b98687bbSPascal van Leeuwen req->block_sz = AES_BLOCK_SIZE; 2009b98687bbSPascal van Leeuwen req->xcbcmac = true; 2010b98687bbSPascal van Leeuwen 2011b98687bbSPascal van Leeuwen return 0; 2012b98687bbSPascal van Leeuwen } 2013b98687bbSPascal van Leeuwen 2014b98687bbSPascal van Leeuwen static int safexcel_cbcmac_setkey(struct crypto_ahash *tfm, const u8 *key, 2015b98687bbSPascal van Leeuwen unsigned int len) 2016b98687bbSPascal van Leeuwen { 2017b98687bbSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 2018b98687bbSPascal van Leeuwen struct crypto_aes_ctx aes; 2019b98687bbSPascal van Leeuwen int ret, i; 2020b98687bbSPascal van Leeuwen 2021b98687bbSPascal van Leeuwen ret = aes_expandkey(&aes, key, len); 2022674f368aSEric Biggers if (ret) 2023b98687bbSPascal van Leeuwen return ret; 2024b98687bbSPascal van Leeuwen 202578cf1c8bSHerbert Xu memset(&ctx->base.ipad, 0, 2 * AES_BLOCK_SIZE); 2026b98687bbSPascal van Leeuwen for (i = 0; i < len / sizeof(u32); i++) 202778cf1c8bSHerbert Xu ctx->base.ipad.be[i + 8] = cpu_to_be32(aes.key_enc[i]); 2028b98687bbSPascal van Leeuwen 2029b98687bbSPascal van Leeuwen if (len == AES_KEYSIZE_192) { 2030b98687bbSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC192; 2031b98687bbSPascal van Leeuwen ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE; 2032b98687bbSPascal van Leeuwen } else if (len == AES_KEYSIZE_256) { 2033b98687bbSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC256; 2034b98687bbSPascal van Leeuwen ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE; 2035b98687bbSPascal van Leeuwen } else { 2036b98687bbSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128; 2037b98687bbSPascal van Leeuwen ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE; 2038b98687bbSPascal van Leeuwen } 203938f21b4bSPascal van Leeuwen ctx->cbcmac = true; 2040b98687bbSPascal van Leeuwen 2041b98687bbSPascal van Leeuwen memzero_explicit(&aes, sizeof(aes)); 2042b98687bbSPascal van Leeuwen return 0; 2043b98687bbSPascal van Leeuwen } 2044b98687bbSPascal van Leeuwen 2045b98687bbSPascal van Leeuwen static int safexcel_cbcmac_digest(struct ahash_request *areq) 2046b98687bbSPascal van Leeuwen { 2047b98687bbSPascal van Leeuwen return safexcel_cbcmac_init(areq) ?: safexcel_ahash_finup(areq); 2048b98687bbSPascal van Leeuwen } 2049b98687bbSPascal van Leeuwen 2050b98687bbSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_cbcmac = { 2051b98687bbSPascal van Leeuwen .type = SAFEXCEL_ALG_TYPE_AHASH, 2052b98687bbSPascal van Leeuwen .algo_mask = 0, 2053b98687bbSPascal van Leeuwen .alg.ahash = { 2054b98687bbSPascal van Leeuwen .init = safexcel_cbcmac_init, 2055b98687bbSPascal van Leeuwen .update = safexcel_ahash_update, 2056b98687bbSPascal van Leeuwen .final = safexcel_ahash_final, 2057b98687bbSPascal van Leeuwen .finup = safexcel_ahash_finup, 2058b98687bbSPascal van Leeuwen .digest = safexcel_cbcmac_digest, 2059b98687bbSPascal van Leeuwen .setkey = safexcel_cbcmac_setkey, 2060b98687bbSPascal van Leeuwen .export = safexcel_ahash_export, 2061b98687bbSPascal van Leeuwen .import = safexcel_ahash_import, 2062b98687bbSPascal van Leeuwen .halg = { 2063b98687bbSPascal van Leeuwen .digestsize = AES_BLOCK_SIZE, 2064b98687bbSPascal van Leeuwen .statesize = sizeof(struct safexcel_ahash_export_state), 2065b98687bbSPascal van Leeuwen .base = { 2066b98687bbSPascal van Leeuwen .cra_name = "cbcmac(aes)", 2067b98687bbSPascal van Leeuwen .cra_driver_name = "safexcel-cbcmac-aes", 2068b98687bbSPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 2069b98687bbSPascal van Leeuwen .cra_flags = CRYPTO_ALG_ASYNC | 2070b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 2071b98687bbSPascal van Leeuwen CRYPTO_ALG_KERN_DRIVER_ONLY, 2072b98687bbSPascal van Leeuwen .cra_blocksize = 1, 2073b98687bbSPascal van Leeuwen .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 2074b98687bbSPascal van Leeuwen .cra_init = safexcel_ahash_cra_init, 2075b98687bbSPascal van Leeuwen .cra_exit = safexcel_ahash_cra_exit, 2076b98687bbSPascal van Leeuwen .cra_module = THIS_MODULE, 2077b98687bbSPascal van Leeuwen }, 2078b98687bbSPascal van Leeuwen }, 2079b98687bbSPascal van Leeuwen }, 2080b98687bbSPascal van Leeuwen }; 208138f21b4bSPascal van Leeuwen 208238f21b4bSPascal van Leeuwen static int safexcel_xcbcmac_setkey(struct crypto_ahash *tfm, const u8 *key, 208338f21b4bSPascal van Leeuwen unsigned int len) 208438f21b4bSPascal van Leeuwen { 208538f21b4bSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 208638f21b4bSPascal van Leeuwen u32 key_tmp[3 * AES_BLOCK_SIZE / sizeof(u32)]; 208738f21b4bSPascal van Leeuwen int ret, i; 208838f21b4bSPascal van Leeuwen 2089*320406cbSPeter Harliman Liem ret = aes_expandkey(ctx->aes, key, len); 2090674f368aSEric Biggers if (ret) 209138f21b4bSPascal van Leeuwen return ret; 209238f21b4bSPascal van Leeuwen 209338f21b4bSPascal van Leeuwen /* precompute the XCBC key material */ 2094*320406cbSPeter Harliman Liem aes_encrypt(ctx->aes, (u8 *)key_tmp + 2 * AES_BLOCK_SIZE, 209538f21b4bSPascal van Leeuwen "\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1"); 2096*320406cbSPeter Harliman Liem aes_encrypt(ctx->aes, (u8 *)key_tmp, 209738f21b4bSPascal van Leeuwen "\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2"); 2098*320406cbSPeter Harliman Liem aes_encrypt(ctx->aes, (u8 *)key_tmp + AES_BLOCK_SIZE, 209938f21b4bSPascal van Leeuwen "\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3"); 210038f21b4bSPascal van Leeuwen for (i = 0; i < 3 * AES_BLOCK_SIZE / sizeof(u32); i++) 210166459340SPeter Harliman Liem ctx->base.ipad.word[i] = swab32(key_tmp[i]); 210238f21b4bSPascal van Leeuwen 2103*320406cbSPeter Harliman Liem ret = aes_expandkey(ctx->aes, 210438f21b4bSPascal van Leeuwen (u8 *)key_tmp + 2 * AES_BLOCK_SIZE, 210538f21b4bSPascal van Leeuwen AES_MIN_KEY_SIZE); 210638f21b4bSPascal van Leeuwen if (ret) 210738f21b4bSPascal van Leeuwen return ret; 210838f21b4bSPascal van Leeuwen 210938f21b4bSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128; 211038f21b4bSPascal van Leeuwen ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE; 211138f21b4bSPascal van Leeuwen ctx->cbcmac = false; 211238f21b4bSPascal van Leeuwen 211338f21b4bSPascal van Leeuwen return 0; 211438f21b4bSPascal van Leeuwen } 211538f21b4bSPascal van Leeuwen 211638f21b4bSPascal van Leeuwen static int safexcel_xcbcmac_cra_init(struct crypto_tfm *tfm) 211738f21b4bSPascal van Leeuwen { 211838f21b4bSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 211938f21b4bSPascal van Leeuwen 212038f21b4bSPascal van Leeuwen safexcel_ahash_cra_init(tfm); 2121*320406cbSPeter Harliman Liem ctx->aes = kmalloc(sizeof(*ctx->aes), GFP_KERNEL); 2122*320406cbSPeter Harliman Liem return PTR_ERR_OR_ZERO(ctx->aes); 212338f21b4bSPascal van Leeuwen } 212438f21b4bSPascal van Leeuwen 212538f21b4bSPascal van Leeuwen static void safexcel_xcbcmac_cra_exit(struct crypto_tfm *tfm) 212638f21b4bSPascal van Leeuwen { 212738f21b4bSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 212838f21b4bSPascal van Leeuwen 2129*320406cbSPeter Harliman Liem kfree(ctx->aes); 213038f21b4bSPascal van Leeuwen safexcel_ahash_cra_exit(tfm); 213138f21b4bSPascal van Leeuwen } 213238f21b4bSPascal van Leeuwen 213338f21b4bSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_xcbcmac = { 213438f21b4bSPascal van Leeuwen .type = SAFEXCEL_ALG_TYPE_AHASH, 213538f21b4bSPascal van Leeuwen .algo_mask = 0, 213638f21b4bSPascal van Leeuwen .alg.ahash = { 213738f21b4bSPascal van Leeuwen .init = safexcel_cbcmac_init, 213838f21b4bSPascal van Leeuwen .update = safexcel_ahash_update, 213938f21b4bSPascal van Leeuwen .final = safexcel_ahash_final, 214038f21b4bSPascal van Leeuwen .finup = safexcel_ahash_finup, 214138f21b4bSPascal van Leeuwen .digest = safexcel_cbcmac_digest, 214238f21b4bSPascal van Leeuwen .setkey = safexcel_xcbcmac_setkey, 214338f21b4bSPascal van Leeuwen .export = safexcel_ahash_export, 214438f21b4bSPascal van Leeuwen .import = safexcel_ahash_import, 214538f21b4bSPascal van Leeuwen .halg = { 214638f21b4bSPascal van Leeuwen .digestsize = AES_BLOCK_SIZE, 214738f21b4bSPascal van Leeuwen .statesize = sizeof(struct safexcel_ahash_export_state), 214838f21b4bSPascal van Leeuwen .base = { 214938f21b4bSPascal van Leeuwen .cra_name = "xcbc(aes)", 215038f21b4bSPascal van Leeuwen .cra_driver_name = "safexcel-xcbc-aes", 215138f21b4bSPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 215238f21b4bSPascal van Leeuwen .cra_flags = CRYPTO_ALG_ASYNC | 2153b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 215438f21b4bSPascal van Leeuwen CRYPTO_ALG_KERN_DRIVER_ONLY, 215538f21b4bSPascal van Leeuwen .cra_blocksize = AES_BLOCK_SIZE, 215638f21b4bSPascal van Leeuwen .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 215738f21b4bSPascal van Leeuwen .cra_init = safexcel_xcbcmac_cra_init, 215838f21b4bSPascal van Leeuwen .cra_exit = safexcel_xcbcmac_cra_exit, 215938f21b4bSPascal van Leeuwen .cra_module = THIS_MODULE, 216038f21b4bSPascal van Leeuwen }, 216138f21b4bSPascal van Leeuwen }, 216238f21b4bSPascal van Leeuwen }, 216338f21b4bSPascal van Leeuwen }; 21647a627db9SPascal van Leeuwen 21657a627db9SPascal van Leeuwen static int safexcel_cmac_setkey(struct crypto_ahash *tfm, const u8 *key, 21667a627db9SPascal van Leeuwen unsigned int len) 21677a627db9SPascal van Leeuwen { 21687a627db9SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 21697a627db9SPascal van Leeuwen __be64 consts[4]; 21707a627db9SPascal van Leeuwen u64 _const[2]; 21717a627db9SPascal van Leeuwen u8 msb_mask, gfmask; 21727a627db9SPascal van Leeuwen int ret, i; 21737a627db9SPascal van Leeuwen 2174*320406cbSPeter Harliman Liem /* precompute the CMAC key material */ 2175*320406cbSPeter Harliman Liem ret = aes_expandkey(ctx->aes, key, len); 2176674f368aSEric Biggers if (ret) 21777a627db9SPascal van Leeuwen return ret; 21787a627db9SPascal van Leeuwen 21797a627db9SPascal van Leeuwen for (i = 0; i < len / sizeof(u32); i++) 2180*320406cbSPeter Harliman Liem ctx->base.ipad.word[i + 8] = swab32(ctx->aes->key_enc[i]); 21817a627db9SPascal van Leeuwen 21827a627db9SPascal van Leeuwen /* code below borrowed from crypto/cmac.c */ 21837a627db9SPascal van Leeuwen /* encrypt the zero block */ 21847a627db9SPascal van Leeuwen memset(consts, 0, AES_BLOCK_SIZE); 2185*320406cbSPeter Harliman Liem aes_encrypt(ctx->aes, (u8 *)consts, (u8 *)consts); 21867a627db9SPascal van Leeuwen 21877a627db9SPascal van Leeuwen gfmask = 0x87; 21887a627db9SPascal van Leeuwen _const[0] = be64_to_cpu(consts[1]); 21897a627db9SPascal van Leeuwen _const[1] = be64_to_cpu(consts[0]); 21907a627db9SPascal van Leeuwen 21917a627db9SPascal van Leeuwen /* gf(2^128) multiply zero-ciphertext with u and u^2 */ 21927a627db9SPascal van Leeuwen for (i = 0; i < 4; i += 2) { 21937a627db9SPascal van Leeuwen msb_mask = ((s64)_const[1] >> 63) & gfmask; 21947a627db9SPascal van Leeuwen _const[1] = (_const[1] << 1) | (_const[0] >> 63); 21957a627db9SPascal van Leeuwen _const[0] = (_const[0] << 1) ^ msb_mask; 21967a627db9SPascal van Leeuwen 21977a627db9SPascal van Leeuwen consts[i + 0] = cpu_to_be64(_const[1]); 21987a627db9SPascal van Leeuwen consts[i + 1] = cpu_to_be64(_const[0]); 21997a627db9SPascal van Leeuwen } 22007a627db9SPascal van Leeuwen /* end of code borrowed from crypto/cmac.c */ 22017a627db9SPascal van Leeuwen 22027a627db9SPascal van Leeuwen for (i = 0; i < 2 * AES_BLOCK_SIZE / sizeof(u32); i++) 220378cf1c8bSHerbert Xu ctx->base.ipad.be[i] = cpu_to_be32(((u32 *)consts)[i]); 22047a627db9SPascal van Leeuwen 22057a627db9SPascal van Leeuwen if (len == AES_KEYSIZE_192) { 22067a627db9SPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC192; 22077a627db9SPascal van Leeuwen ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE; 22087a627db9SPascal van Leeuwen } else if (len == AES_KEYSIZE_256) { 22097a627db9SPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC256; 22107a627db9SPascal van Leeuwen ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE; 22117a627db9SPascal van Leeuwen } else { 22127a627db9SPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128; 22137a627db9SPascal van Leeuwen ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE; 22147a627db9SPascal van Leeuwen } 22157a627db9SPascal van Leeuwen ctx->cbcmac = false; 22167a627db9SPascal van Leeuwen 22177a627db9SPascal van Leeuwen return 0; 22187a627db9SPascal van Leeuwen } 22197a627db9SPascal van Leeuwen 22207a627db9SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_cmac = { 22217a627db9SPascal van Leeuwen .type = SAFEXCEL_ALG_TYPE_AHASH, 22227a627db9SPascal van Leeuwen .algo_mask = 0, 22237a627db9SPascal van Leeuwen .alg.ahash = { 22247a627db9SPascal van Leeuwen .init = safexcel_cbcmac_init, 22257a627db9SPascal van Leeuwen .update = safexcel_ahash_update, 22267a627db9SPascal van Leeuwen .final = safexcel_ahash_final, 22277a627db9SPascal van Leeuwen .finup = safexcel_ahash_finup, 22287a627db9SPascal van Leeuwen .digest = safexcel_cbcmac_digest, 22297a627db9SPascal van Leeuwen .setkey = safexcel_cmac_setkey, 22307a627db9SPascal van Leeuwen .export = safexcel_ahash_export, 22317a627db9SPascal van Leeuwen .import = safexcel_ahash_import, 22327a627db9SPascal van Leeuwen .halg = { 22337a627db9SPascal van Leeuwen .digestsize = AES_BLOCK_SIZE, 22347a627db9SPascal van Leeuwen .statesize = sizeof(struct safexcel_ahash_export_state), 22357a627db9SPascal van Leeuwen .base = { 22367a627db9SPascal van Leeuwen .cra_name = "cmac(aes)", 22377a627db9SPascal van Leeuwen .cra_driver_name = "safexcel-cmac-aes", 22387a627db9SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 22397a627db9SPascal van Leeuwen .cra_flags = CRYPTO_ALG_ASYNC | 2240b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 22417a627db9SPascal van Leeuwen CRYPTO_ALG_KERN_DRIVER_ONLY, 22427a627db9SPascal van Leeuwen .cra_blocksize = AES_BLOCK_SIZE, 22437a627db9SPascal van Leeuwen .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 22447a627db9SPascal van Leeuwen .cra_init = safexcel_xcbcmac_cra_init, 22457a627db9SPascal van Leeuwen .cra_exit = safexcel_xcbcmac_cra_exit, 22467a627db9SPascal van Leeuwen .cra_module = THIS_MODULE, 22477a627db9SPascal van Leeuwen }, 22487a627db9SPascal van Leeuwen }, 22497a627db9SPascal van Leeuwen }, 22507a627db9SPascal van Leeuwen }; 22510f2bc131SPascal van Leeuwen 22520f2bc131SPascal van Leeuwen static int safexcel_sm3_init(struct ahash_request *areq) 22530f2bc131SPascal van Leeuwen { 22540f2bc131SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 22550f2bc131SPascal van Leeuwen struct safexcel_ahash_req *req = ahash_request_ctx(areq); 22560f2bc131SPascal van Leeuwen 22570f2bc131SPascal van Leeuwen memset(req, 0, sizeof(*req)); 22580f2bc131SPascal van Leeuwen 22590f2bc131SPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SM3; 22600f2bc131SPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 22610f2bc131SPascal van Leeuwen req->state_sz = SM3_DIGEST_SIZE; 22626c1c09b3SPascal van Leeuwen req->digest_sz = SM3_DIGEST_SIZE; 22630f2bc131SPascal van Leeuwen req->block_sz = SM3_BLOCK_SIZE; 22640f2bc131SPascal van Leeuwen 22650f2bc131SPascal van Leeuwen return 0; 22660f2bc131SPascal van Leeuwen } 22670f2bc131SPascal van Leeuwen 22680f2bc131SPascal van Leeuwen static int safexcel_sm3_digest(struct ahash_request *areq) 22690f2bc131SPascal van Leeuwen { 22700f2bc131SPascal van Leeuwen int ret = safexcel_sm3_init(areq); 22710f2bc131SPascal van Leeuwen 22720f2bc131SPascal van Leeuwen if (ret) 22730f2bc131SPascal van Leeuwen return ret; 22740f2bc131SPascal van Leeuwen 22750f2bc131SPascal van Leeuwen return safexcel_ahash_finup(areq); 22760f2bc131SPascal van Leeuwen } 22770f2bc131SPascal van Leeuwen 22780f2bc131SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_sm3 = { 22790f2bc131SPascal van Leeuwen .type = SAFEXCEL_ALG_TYPE_AHASH, 22800f2bc131SPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SM3, 22810f2bc131SPascal van Leeuwen .alg.ahash = { 22820f2bc131SPascal van Leeuwen .init = safexcel_sm3_init, 22830f2bc131SPascal van Leeuwen .update = safexcel_ahash_update, 22840f2bc131SPascal van Leeuwen .final = safexcel_ahash_final, 22850f2bc131SPascal van Leeuwen .finup = safexcel_ahash_finup, 22860f2bc131SPascal van Leeuwen .digest = safexcel_sm3_digest, 22870f2bc131SPascal van Leeuwen .export = safexcel_ahash_export, 22880f2bc131SPascal van Leeuwen .import = safexcel_ahash_import, 22890f2bc131SPascal van Leeuwen .halg = { 22900f2bc131SPascal van Leeuwen .digestsize = SM3_DIGEST_SIZE, 22910f2bc131SPascal van Leeuwen .statesize = sizeof(struct safexcel_ahash_export_state), 22920f2bc131SPascal van Leeuwen .base = { 22930f2bc131SPascal van Leeuwen .cra_name = "sm3", 22940f2bc131SPascal van Leeuwen .cra_driver_name = "safexcel-sm3", 22950f2bc131SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 22960f2bc131SPascal van Leeuwen .cra_flags = CRYPTO_ALG_ASYNC | 2297b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 22980f2bc131SPascal van Leeuwen CRYPTO_ALG_KERN_DRIVER_ONLY, 22990f2bc131SPascal van Leeuwen .cra_blocksize = SM3_BLOCK_SIZE, 23000f2bc131SPascal van Leeuwen .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 23010f2bc131SPascal van Leeuwen .cra_init = safexcel_ahash_cra_init, 23020f2bc131SPascal van Leeuwen .cra_exit = safexcel_ahash_cra_exit, 23030f2bc131SPascal van Leeuwen .cra_module = THIS_MODULE, 23040f2bc131SPascal van Leeuwen }, 23050f2bc131SPascal van Leeuwen }, 23060f2bc131SPascal van Leeuwen }, 23070f2bc131SPascal van Leeuwen }; 2308aa3a43e6SPascal van Leeuwen 2309aa3a43e6SPascal van Leeuwen static int safexcel_hmac_sm3_setkey(struct crypto_ahash *tfm, const u8 *key, 2310aa3a43e6SPascal van Leeuwen unsigned int keylen) 2311aa3a43e6SPascal van Leeuwen { 2312aa3a43e6SPascal van Leeuwen return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sm3", 2313aa3a43e6SPascal van Leeuwen SM3_DIGEST_SIZE); 2314aa3a43e6SPascal van Leeuwen } 2315aa3a43e6SPascal van Leeuwen 2316aa3a43e6SPascal van Leeuwen static int safexcel_hmac_sm3_init(struct ahash_request *areq) 2317aa3a43e6SPascal van Leeuwen { 2318aa3a43e6SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 2319aa3a43e6SPascal van Leeuwen struct safexcel_ahash_req *req = ahash_request_ctx(areq); 2320aa3a43e6SPascal van Leeuwen 2321aa3a43e6SPascal van Leeuwen memset(req, 0, sizeof(*req)); 2322aa3a43e6SPascal van Leeuwen 2323aa3a43e6SPascal van Leeuwen /* Start from ipad precompute */ 232478cf1c8bSHerbert Xu memcpy(req->state, &ctx->base.ipad, SM3_DIGEST_SIZE); 2325aa3a43e6SPascal van Leeuwen /* Already processed the key^ipad part now! */ 2326aa3a43e6SPascal van Leeuwen req->len = SM3_BLOCK_SIZE; 2327aa3a43e6SPascal van Leeuwen req->processed = SM3_BLOCK_SIZE; 2328aa3a43e6SPascal van Leeuwen 2329aa3a43e6SPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SM3; 2330aa3a43e6SPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 2331aa3a43e6SPascal van Leeuwen req->state_sz = SM3_DIGEST_SIZE; 23326c1c09b3SPascal van Leeuwen req->digest_sz = SM3_DIGEST_SIZE; 2333aa3a43e6SPascal van Leeuwen req->block_sz = SM3_BLOCK_SIZE; 2334aa3a43e6SPascal van Leeuwen req->hmac = true; 2335aa3a43e6SPascal van Leeuwen 2336aa3a43e6SPascal van Leeuwen return 0; 2337aa3a43e6SPascal van Leeuwen } 2338aa3a43e6SPascal van Leeuwen 2339aa3a43e6SPascal van Leeuwen static int safexcel_hmac_sm3_digest(struct ahash_request *areq) 2340aa3a43e6SPascal van Leeuwen { 2341aa3a43e6SPascal van Leeuwen int ret = safexcel_hmac_sm3_init(areq); 2342aa3a43e6SPascal van Leeuwen 2343aa3a43e6SPascal van Leeuwen if (ret) 2344aa3a43e6SPascal van Leeuwen return ret; 2345aa3a43e6SPascal van Leeuwen 2346aa3a43e6SPascal van Leeuwen return safexcel_ahash_finup(areq); 2347aa3a43e6SPascal van Leeuwen } 2348aa3a43e6SPascal van Leeuwen 2349aa3a43e6SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_hmac_sm3 = { 2350aa3a43e6SPascal van Leeuwen .type = SAFEXCEL_ALG_TYPE_AHASH, 2351aa3a43e6SPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SM3, 2352aa3a43e6SPascal van Leeuwen .alg.ahash = { 2353aa3a43e6SPascal van Leeuwen .init = safexcel_hmac_sm3_init, 2354aa3a43e6SPascal van Leeuwen .update = safexcel_ahash_update, 2355aa3a43e6SPascal van Leeuwen .final = safexcel_ahash_final, 2356aa3a43e6SPascal van Leeuwen .finup = safexcel_ahash_finup, 2357aa3a43e6SPascal van Leeuwen .digest = safexcel_hmac_sm3_digest, 2358aa3a43e6SPascal van Leeuwen .setkey = safexcel_hmac_sm3_setkey, 2359aa3a43e6SPascal van Leeuwen .export = safexcel_ahash_export, 2360aa3a43e6SPascal van Leeuwen .import = safexcel_ahash_import, 2361aa3a43e6SPascal van Leeuwen .halg = { 2362aa3a43e6SPascal van Leeuwen .digestsize = SM3_DIGEST_SIZE, 2363aa3a43e6SPascal van Leeuwen .statesize = sizeof(struct safexcel_ahash_export_state), 2364aa3a43e6SPascal van Leeuwen .base = { 2365aa3a43e6SPascal van Leeuwen .cra_name = "hmac(sm3)", 2366aa3a43e6SPascal van Leeuwen .cra_driver_name = "safexcel-hmac-sm3", 2367aa3a43e6SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 2368aa3a43e6SPascal van Leeuwen .cra_flags = CRYPTO_ALG_ASYNC | 2369b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 2370aa3a43e6SPascal van Leeuwen CRYPTO_ALG_KERN_DRIVER_ONLY, 2371aa3a43e6SPascal van Leeuwen .cra_blocksize = SM3_BLOCK_SIZE, 2372aa3a43e6SPascal van Leeuwen .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 2373aa3a43e6SPascal van Leeuwen .cra_init = safexcel_ahash_cra_init, 2374aa3a43e6SPascal van Leeuwen .cra_exit = safexcel_ahash_cra_exit, 2375aa3a43e6SPascal van Leeuwen .cra_module = THIS_MODULE, 2376aa3a43e6SPascal van Leeuwen }, 2377aa3a43e6SPascal van Leeuwen }, 2378aa3a43e6SPascal van Leeuwen }, 2379aa3a43e6SPascal van Leeuwen }; 2380aaf5a383SPascal van Leeuwen 2381aaf5a383SPascal van Leeuwen static int safexcel_sha3_224_init(struct ahash_request *areq) 2382aaf5a383SPascal van Leeuwen { 2383aaf5a383SPascal van Leeuwen struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 2384aaf5a383SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 2385aaf5a383SPascal van Leeuwen struct safexcel_ahash_req *req = ahash_request_ctx(areq); 2386aaf5a383SPascal van Leeuwen 2387aaf5a383SPascal van Leeuwen memset(req, 0, sizeof(*req)); 2388aaf5a383SPascal van Leeuwen 2389aaf5a383SPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_224; 2390aaf5a383SPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_INITIAL; 2391aaf5a383SPascal van Leeuwen req->state_sz = SHA3_224_DIGEST_SIZE; 23926c1c09b3SPascal van Leeuwen req->digest_sz = SHA3_224_DIGEST_SIZE; 2393aaf5a383SPascal van Leeuwen req->block_sz = SHA3_224_BLOCK_SIZE; 2394aaf5a383SPascal van Leeuwen ctx->do_fallback = false; 2395aaf5a383SPascal van Leeuwen ctx->fb_init_done = false; 2396aaf5a383SPascal van Leeuwen return 0; 2397aaf5a383SPascal van Leeuwen } 2398aaf5a383SPascal van Leeuwen 2399aaf5a383SPascal van Leeuwen static int safexcel_sha3_fbcheck(struct ahash_request *req) 2400aaf5a383SPascal van Leeuwen { 2401aaf5a383SPascal van Leeuwen struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 2402aaf5a383SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 2403aaf5a383SPascal van Leeuwen struct ahash_request *subreq = ahash_request_ctx(req); 2404aaf5a383SPascal van Leeuwen int ret = 0; 2405aaf5a383SPascal van Leeuwen 2406aaf5a383SPascal van Leeuwen if (ctx->do_fallback) { 2407aaf5a383SPascal van Leeuwen ahash_request_set_tfm(subreq, ctx->fback); 2408aaf5a383SPascal van Leeuwen ahash_request_set_callback(subreq, req->base.flags, 2409aaf5a383SPascal van Leeuwen req->base.complete, req->base.data); 2410aaf5a383SPascal van Leeuwen ahash_request_set_crypt(subreq, req->src, req->result, 2411aaf5a383SPascal van Leeuwen req->nbytes); 2412aaf5a383SPascal van Leeuwen if (!ctx->fb_init_done) { 24136c1c09b3SPascal van Leeuwen if (ctx->fb_do_setkey) { 24146c1c09b3SPascal van Leeuwen /* Set fallback cipher HMAC key */ 24156c1c09b3SPascal van Leeuwen u8 key[SHA3_224_BLOCK_SIZE]; 24166c1c09b3SPascal van Leeuwen 241778cf1c8bSHerbert Xu memcpy(key, &ctx->base.ipad, 24186c1c09b3SPascal van Leeuwen crypto_ahash_blocksize(ctx->fback) / 2); 24196c1c09b3SPascal van Leeuwen memcpy(key + 24206c1c09b3SPascal van Leeuwen crypto_ahash_blocksize(ctx->fback) / 2, 242178cf1c8bSHerbert Xu &ctx->base.opad, 24226c1c09b3SPascal van Leeuwen crypto_ahash_blocksize(ctx->fback) / 2); 24236c1c09b3SPascal van Leeuwen ret = crypto_ahash_setkey(ctx->fback, key, 24246c1c09b3SPascal van Leeuwen crypto_ahash_blocksize(ctx->fback)); 24256c1c09b3SPascal van Leeuwen memzero_explicit(key, 24266c1c09b3SPascal van Leeuwen crypto_ahash_blocksize(ctx->fback)); 24276c1c09b3SPascal van Leeuwen ctx->fb_do_setkey = false; 24286c1c09b3SPascal van Leeuwen } 24296c1c09b3SPascal van Leeuwen ret = ret ?: crypto_ahash_init(subreq); 2430aaf5a383SPascal van Leeuwen ctx->fb_init_done = true; 2431aaf5a383SPascal van Leeuwen } 2432aaf5a383SPascal van Leeuwen } 2433aaf5a383SPascal van Leeuwen return ret; 2434aaf5a383SPascal van Leeuwen } 2435aaf5a383SPascal van Leeuwen 2436aaf5a383SPascal van Leeuwen static int safexcel_sha3_update(struct ahash_request *req) 2437aaf5a383SPascal van Leeuwen { 2438aaf5a383SPascal van Leeuwen struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 2439aaf5a383SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 2440aaf5a383SPascal van Leeuwen struct ahash_request *subreq = ahash_request_ctx(req); 2441aaf5a383SPascal van Leeuwen 2442aaf5a383SPascal van Leeuwen ctx->do_fallback = true; 2443aaf5a383SPascal van Leeuwen return safexcel_sha3_fbcheck(req) ?: crypto_ahash_update(subreq); 2444aaf5a383SPascal van Leeuwen } 2445aaf5a383SPascal van Leeuwen 2446aaf5a383SPascal van Leeuwen static int safexcel_sha3_final(struct ahash_request *req) 2447aaf5a383SPascal van Leeuwen { 2448aaf5a383SPascal van Leeuwen struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 2449aaf5a383SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 2450aaf5a383SPascal van Leeuwen struct ahash_request *subreq = ahash_request_ctx(req); 2451aaf5a383SPascal van Leeuwen 2452aaf5a383SPascal van Leeuwen ctx->do_fallback = true; 2453aaf5a383SPascal van Leeuwen return safexcel_sha3_fbcheck(req) ?: crypto_ahash_final(subreq); 2454aaf5a383SPascal van Leeuwen } 2455aaf5a383SPascal van Leeuwen 2456aaf5a383SPascal van Leeuwen static int safexcel_sha3_finup(struct ahash_request *req) 2457aaf5a383SPascal van Leeuwen { 2458aaf5a383SPascal van Leeuwen struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 2459aaf5a383SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 2460aaf5a383SPascal van Leeuwen struct ahash_request *subreq = ahash_request_ctx(req); 2461aaf5a383SPascal van Leeuwen 2462aaf5a383SPascal van Leeuwen ctx->do_fallback |= !req->nbytes; 2463aaf5a383SPascal van Leeuwen if (ctx->do_fallback) 2464aaf5a383SPascal van Leeuwen /* Update or ex/import happened or len 0, cannot use the HW */ 2465aaf5a383SPascal van Leeuwen return safexcel_sha3_fbcheck(req) ?: 2466aaf5a383SPascal van Leeuwen crypto_ahash_finup(subreq); 2467aaf5a383SPascal van Leeuwen else 2468aaf5a383SPascal van Leeuwen return safexcel_ahash_finup(req); 2469aaf5a383SPascal van Leeuwen } 2470aaf5a383SPascal van Leeuwen 2471aaf5a383SPascal van Leeuwen static int safexcel_sha3_digest_fallback(struct ahash_request *req) 2472aaf5a383SPascal van Leeuwen { 2473aaf5a383SPascal van Leeuwen struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 2474aaf5a383SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 2475aaf5a383SPascal van Leeuwen struct ahash_request *subreq = ahash_request_ctx(req); 2476aaf5a383SPascal van Leeuwen 2477aaf5a383SPascal van Leeuwen ctx->do_fallback = true; 2478aaf5a383SPascal van Leeuwen ctx->fb_init_done = false; 2479aaf5a383SPascal van Leeuwen return safexcel_sha3_fbcheck(req) ?: crypto_ahash_finup(subreq); 2480aaf5a383SPascal van Leeuwen } 2481aaf5a383SPascal van Leeuwen 2482aaf5a383SPascal van Leeuwen static int safexcel_sha3_224_digest(struct ahash_request *req) 2483aaf5a383SPascal van Leeuwen { 2484aaf5a383SPascal van Leeuwen if (req->nbytes) 2485aaf5a383SPascal van Leeuwen return safexcel_sha3_224_init(req) ?: safexcel_ahash_finup(req); 2486aaf5a383SPascal van Leeuwen 2487aaf5a383SPascal van Leeuwen /* HW cannot do zero length hash, use fallback instead */ 2488aaf5a383SPascal van Leeuwen return safexcel_sha3_digest_fallback(req); 2489aaf5a383SPascal van Leeuwen } 2490aaf5a383SPascal van Leeuwen 2491aaf5a383SPascal van Leeuwen static int safexcel_sha3_export(struct ahash_request *req, void *out) 2492aaf5a383SPascal van Leeuwen { 2493aaf5a383SPascal van Leeuwen struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 2494aaf5a383SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 2495aaf5a383SPascal van Leeuwen struct ahash_request *subreq = ahash_request_ctx(req); 2496aaf5a383SPascal van Leeuwen 2497aaf5a383SPascal van Leeuwen ctx->do_fallback = true; 2498aaf5a383SPascal van Leeuwen return safexcel_sha3_fbcheck(req) ?: crypto_ahash_export(subreq, out); 2499aaf5a383SPascal van Leeuwen } 2500aaf5a383SPascal van Leeuwen 2501aaf5a383SPascal van Leeuwen static int safexcel_sha3_import(struct ahash_request *req, const void *in) 2502aaf5a383SPascal van Leeuwen { 2503aaf5a383SPascal van Leeuwen struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 2504aaf5a383SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 2505aaf5a383SPascal van Leeuwen struct ahash_request *subreq = ahash_request_ctx(req); 2506aaf5a383SPascal van Leeuwen 2507aaf5a383SPascal van Leeuwen ctx->do_fallback = true; 2508aaf5a383SPascal van Leeuwen return safexcel_sha3_fbcheck(req) ?: crypto_ahash_import(subreq, in); 2509aaf5a383SPascal van Leeuwen // return safexcel_ahash_import(req, in); 2510aaf5a383SPascal van Leeuwen } 2511aaf5a383SPascal van Leeuwen 2512aaf5a383SPascal van Leeuwen static int safexcel_sha3_cra_init(struct crypto_tfm *tfm) 2513aaf5a383SPascal van Leeuwen { 2514aaf5a383SPascal van Leeuwen struct crypto_ahash *ahash = __crypto_ahash_cast(tfm); 2515aaf5a383SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 2516aaf5a383SPascal van Leeuwen 2517aaf5a383SPascal van Leeuwen safexcel_ahash_cra_init(tfm); 2518aaf5a383SPascal van Leeuwen 2519aaf5a383SPascal van Leeuwen /* Allocate fallback implementation */ 2520aaf5a383SPascal van Leeuwen ctx->fback = crypto_alloc_ahash(crypto_tfm_alg_name(tfm), 0, 2521aaf5a383SPascal van Leeuwen CRYPTO_ALG_ASYNC | 2522aaf5a383SPascal van Leeuwen CRYPTO_ALG_NEED_FALLBACK); 2523aaf5a383SPascal van Leeuwen if (IS_ERR(ctx->fback)) 2524aaf5a383SPascal van Leeuwen return PTR_ERR(ctx->fback); 2525aaf5a383SPascal van Leeuwen 2526aaf5a383SPascal van Leeuwen /* Update statesize from fallback algorithm! */ 2527aaf5a383SPascal van Leeuwen crypto_hash_alg_common(ahash)->statesize = 2528aaf5a383SPascal van Leeuwen crypto_ahash_statesize(ctx->fback); 2529aaf5a383SPascal van Leeuwen crypto_ahash_set_reqsize(ahash, max(sizeof(struct safexcel_ahash_req), 2530aaf5a383SPascal van Leeuwen sizeof(struct ahash_request) + 2531aaf5a383SPascal van Leeuwen crypto_ahash_reqsize(ctx->fback))); 2532aaf5a383SPascal van Leeuwen return 0; 2533aaf5a383SPascal van Leeuwen } 2534aaf5a383SPascal van Leeuwen 2535aaf5a383SPascal van Leeuwen static void safexcel_sha3_cra_exit(struct crypto_tfm *tfm) 2536aaf5a383SPascal van Leeuwen { 2537aaf5a383SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 2538aaf5a383SPascal van Leeuwen 2539aaf5a383SPascal van Leeuwen crypto_free_ahash(ctx->fback); 2540aaf5a383SPascal van Leeuwen safexcel_ahash_cra_exit(tfm); 2541aaf5a383SPascal van Leeuwen } 2542aaf5a383SPascal van Leeuwen 2543aaf5a383SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_sha3_224 = { 2544aaf5a383SPascal van Leeuwen .type = SAFEXCEL_ALG_TYPE_AHASH, 2545aaf5a383SPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA3, 2546aaf5a383SPascal van Leeuwen .alg.ahash = { 2547aaf5a383SPascal van Leeuwen .init = safexcel_sha3_224_init, 2548aaf5a383SPascal van Leeuwen .update = safexcel_sha3_update, 2549aaf5a383SPascal van Leeuwen .final = safexcel_sha3_final, 2550aaf5a383SPascal van Leeuwen .finup = safexcel_sha3_finup, 2551aaf5a383SPascal van Leeuwen .digest = safexcel_sha3_224_digest, 2552aaf5a383SPascal van Leeuwen .export = safexcel_sha3_export, 2553aaf5a383SPascal van Leeuwen .import = safexcel_sha3_import, 2554aaf5a383SPascal van Leeuwen .halg = { 2555aaf5a383SPascal van Leeuwen .digestsize = SHA3_224_DIGEST_SIZE, 2556aaf5a383SPascal van Leeuwen .statesize = sizeof(struct safexcel_ahash_export_state), 2557aaf5a383SPascal van Leeuwen .base = { 2558aaf5a383SPascal van Leeuwen .cra_name = "sha3-224", 2559aaf5a383SPascal van Leeuwen .cra_driver_name = "safexcel-sha3-224", 2560aaf5a383SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 2561aaf5a383SPascal van Leeuwen .cra_flags = CRYPTO_ALG_ASYNC | 2562aaf5a383SPascal van Leeuwen CRYPTO_ALG_KERN_DRIVER_ONLY | 2563aaf5a383SPascal van Leeuwen CRYPTO_ALG_NEED_FALLBACK, 2564aaf5a383SPascal van Leeuwen .cra_blocksize = SHA3_224_BLOCK_SIZE, 2565aaf5a383SPascal van Leeuwen .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 2566aaf5a383SPascal van Leeuwen .cra_init = safexcel_sha3_cra_init, 2567aaf5a383SPascal van Leeuwen .cra_exit = safexcel_sha3_cra_exit, 2568aaf5a383SPascal van Leeuwen .cra_module = THIS_MODULE, 2569aaf5a383SPascal van Leeuwen }, 2570aaf5a383SPascal van Leeuwen }, 2571aaf5a383SPascal van Leeuwen }, 2572aaf5a383SPascal van Leeuwen }; 2573aaf5a383SPascal van Leeuwen 2574aaf5a383SPascal van Leeuwen static int safexcel_sha3_256_init(struct ahash_request *areq) 2575aaf5a383SPascal van Leeuwen { 2576aaf5a383SPascal van Leeuwen struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 2577aaf5a383SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 2578aaf5a383SPascal van Leeuwen struct safexcel_ahash_req *req = ahash_request_ctx(areq); 2579aaf5a383SPascal van Leeuwen 2580aaf5a383SPascal van Leeuwen memset(req, 0, sizeof(*req)); 2581aaf5a383SPascal van Leeuwen 2582aaf5a383SPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_256; 2583aaf5a383SPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_INITIAL; 2584aaf5a383SPascal van Leeuwen req->state_sz = SHA3_256_DIGEST_SIZE; 25856c1c09b3SPascal van Leeuwen req->digest_sz = SHA3_256_DIGEST_SIZE; 2586aaf5a383SPascal van Leeuwen req->block_sz = SHA3_256_BLOCK_SIZE; 2587aaf5a383SPascal van Leeuwen ctx->do_fallback = false; 2588aaf5a383SPascal van Leeuwen ctx->fb_init_done = false; 2589aaf5a383SPascal van Leeuwen return 0; 2590aaf5a383SPascal van Leeuwen } 2591aaf5a383SPascal van Leeuwen 2592aaf5a383SPascal van Leeuwen static int safexcel_sha3_256_digest(struct ahash_request *req) 2593aaf5a383SPascal van Leeuwen { 2594aaf5a383SPascal van Leeuwen if (req->nbytes) 2595aaf5a383SPascal van Leeuwen return safexcel_sha3_256_init(req) ?: safexcel_ahash_finup(req); 2596aaf5a383SPascal van Leeuwen 2597aaf5a383SPascal van Leeuwen /* HW cannot do zero length hash, use fallback instead */ 2598aaf5a383SPascal van Leeuwen return safexcel_sha3_digest_fallback(req); 2599aaf5a383SPascal van Leeuwen } 2600aaf5a383SPascal van Leeuwen 2601aaf5a383SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_sha3_256 = { 2602aaf5a383SPascal van Leeuwen .type = SAFEXCEL_ALG_TYPE_AHASH, 2603aaf5a383SPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA3, 2604aaf5a383SPascal van Leeuwen .alg.ahash = { 2605aaf5a383SPascal van Leeuwen .init = safexcel_sha3_256_init, 2606aaf5a383SPascal van Leeuwen .update = safexcel_sha3_update, 2607aaf5a383SPascal van Leeuwen .final = safexcel_sha3_final, 2608aaf5a383SPascal van Leeuwen .finup = safexcel_sha3_finup, 2609aaf5a383SPascal van Leeuwen .digest = safexcel_sha3_256_digest, 2610aaf5a383SPascal van Leeuwen .export = safexcel_sha3_export, 2611aaf5a383SPascal van Leeuwen .import = safexcel_sha3_import, 2612aaf5a383SPascal van Leeuwen .halg = { 2613aaf5a383SPascal van Leeuwen .digestsize = SHA3_256_DIGEST_SIZE, 2614aaf5a383SPascal van Leeuwen .statesize = sizeof(struct safexcel_ahash_export_state), 2615aaf5a383SPascal van Leeuwen .base = { 2616aaf5a383SPascal van Leeuwen .cra_name = "sha3-256", 2617aaf5a383SPascal van Leeuwen .cra_driver_name = "safexcel-sha3-256", 2618aaf5a383SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 2619aaf5a383SPascal van Leeuwen .cra_flags = CRYPTO_ALG_ASYNC | 2620aaf5a383SPascal van Leeuwen CRYPTO_ALG_KERN_DRIVER_ONLY | 2621aaf5a383SPascal van Leeuwen CRYPTO_ALG_NEED_FALLBACK, 2622aaf5a383SPascal van Leeuwen .cra_blocksize = SHA3_256_BLOCK_SIZE, 2623aaf5a383SPascal van Leeuwen .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 2624aaf5a383SPascal van Leeuwen .cra_init = safexcel_sha3_cra_init, 2625aaf5a383SPascal van Leeuwen .cra_exit = safexcel_sha3_cra_exit, 2626aaf5a383SPascal van Leeuwen .cra_module = THIS_MODULE, 2627aaf5a383SPascal van Leeuwen }, 2628aaf5a383SPascal van Leeuwen }, 2629aaf5a383SPascal van Leeuwen }, 2630aaf5a383SPascal van Leeuwen }; 2631aaf5a383SPascal van Leeuwen 2632aaf5a383SPascal van Leeuwen static int safexcel_sha3_384_init(struct ahash_request *areq) 2633aaf5a383SPascal van Leeuwen { 2634aaf5a383SPascal van Leeuwen struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 2635aaf5a383SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 2636aaf5a383SPascal van Leeuwen struct safexcel_ahash_req *req = ahash_request_ctx(areq); 2637aaf5a383SPascal van Leeuwen 2638aaf5a383SPascal van Leeuwen memset(req, 0, sizeof(*req)); 2639aaf5a383SPascal van Leeuwen 2640aaf5a383SPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_384; 2641aaf5a383SPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_INITIAL; 2642aaf5a383SPascal van Leeuwen req->state_sz = SHA3_384_DIGEST_SIZE; 26436c1c09b3SPascal van Leeuwen req->digest_sz = SHA3_384_DIGEST_SIZE; 2644aaf5a383SPascal van Leeuwen req->block_sz = SHA3_384_BLOCK_SIZE; 2645aaf5a383SPascal van Leeuwen ctx->do_fallback = false; 2646aaf5a383SPascal van Leeuwen ctx->fb_init_done = false; 2647aaf5a383SPascal van Leeuwen return 0; 2648aaf5a383SPascal van Leeuwen } 2649aaf5a383SPascal van Leeuwen 2650aaf5a383SPascal van Leeuwen static int safexcel_sha3_384_digest(struct ahash_request *req) 2651aaf5a383SPascal van Leeuwen { 2652aaf5a383SPascal van Leeuwen if (req->nbytes) 2653aaf5a383SPascal van Leeuwen return safexcel_sha3_384_init(req) ?: safexcel_ahash_finup(req); 2654aaf5a383SPascal van Leeuwen 2655aaf5a383SPascal van Leeuwen /* HW cannot do zero length hash, use fallback instead */ 2656aaf5a383SPascal van Leeuwen return safexcel_sha3_digest_fallback(req); 2657aaf5a383SPascal van Leeuwen } 2658aaf5a383SPascal van Leeuwen 2659aaf5a383SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_sha3_384 = { 2660aaf5a383SPascal van Leeuwen .type = SAFEXCEL_ALG_TYPE_AHASH, 2661aaf5a383SPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA3, 2662aaf5a383SPascal van Leeuwen .alg.ahash = { 2663aaf5a383SPascal van Leeuwen .init = safexcel_sha3_384_init, 2664aaf5a383SPascal van Leeuwen .update = safexcel_sha3_update, 2665aaf5a383SPascal van Leeuwen .final = safexcel_sha3_final, 2666aaf5a383SPascal van Leeuwen .finup = safexcel_sha3_finup, 2667aaf5a383SPascal van Leeuwen .digest = safexcel_sha3_384_digest, 2668aaf5a383SPascal van Leeuwen .export = safexcel_sha3_export, 2669aaf5a383SPascal van Leeuwen .import = safexcel_sha3_import, 2670aaf5a383SPascal van Leeuwen .halg = { 2671aaf5a383SPascal van Leeuwen .digestsize = SHA3_384_DIGEST_SIZE, 2672aaf5a383SPascal van Leeuwen .statesize = sizeof(struct safexcel_ahash_export_state), 2673aaf5a383SPascal van Leeuwen .base = { 2674aaf5a383SPascal van Leeuwen .cra_name = "sha3-384", 2675aaf5a383SPascal van Leeuwen .cra_driver_name = "safexcel-sha3-384", 2676aaf5a383SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 2677aaf5a383SPascal van Leeuwen .cra_flags = CRYPTO_ALG_ASYNC | 2678aaf5a383SPascal van Leeuwen CRYPTO_ALG_KERN_DRIVER_ONLY | 2679aaf5a383SPascal van Leeuwen CRYPTO_ALG_NEED_FALLBACK, 2680aaf5a383SPascal van Leeuwen .cra_blocksize = SHA3_384_BLOCK_SIZE, 2681aaf5a383SPascal van Leeuwen .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 2682aaf5a383SPascal van Leeuwen .cra_init = safexcel_sha3_cra_init, 2683aaf5a383SPascal van Leeuwen .cra_exit = safexcel_sha3_cra_exit, 2684aaf5a383SPascal van Leeuwen .cra_module = THIS_MODULE, 2685aaf5a383SPascal van Leeuwen }, 2686aaf5a383SPascal van Leeuwen }, 2687aaf5a383SPascal van Leeuwen }, 2688aaf5a383SPascal van Leeuwen }; 2689aaf5a383SPascal van Leeuwen 2690aaf5a383SPascal van Leeuwen static int safexcel_sha3_512_init(struct ahash_request *areq) 2691aaf5a383SPascal van Leeuwen { 2692aaf5a383SPascal van Leeuwen struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 2693aaf5a383SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 2694aaf5a383SPascal van Leeuwen struct safexcel_ahash_req *req = ahash_request_ctx(areq); 2695aaf5a383SPascal van Leeuwen 2696aaf5a383SPascal van Leeuwen memset(req, 0, sizeof(*req)); 2697aaf5a383SPascal van Leeuwen 2698aaf5a383SPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_512; 2699aaf5a383SPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_INITIAL; 2700aaf5a383SPascal van Leeuwen req->state_sz = SHA3_512_DIGEST_SIZE; 27016c1c09b3SPascal van Leeuwen req->digest_sz = SHA3_512_DIGEST_SIZE; 2702aaf5a383SPascal van Leeuwen req->block_sz = SHA3_512_BLOCK_SIZE; 2703aaf5a383SPascal van Leeuwen ctx->do_fallback = false; 2704aaf5a383SPascal van Leeuwen ctx->fb_init_done = false; 2705aaf5a383SPascal van Leeuwen return 0; 2706aaf5a383SPascal van Leeuwen } 2707aaf5a383SPascal van Leeuwen 2708aaf5a383SPascal van Leeuwen static int safexcel_sha3_512_digest(struct ahash_request *req) 2709aaf5a383SPascal van Leeuwen { 2710aaf5a383SPascal van Leeuwen if (req->nbytes) 2711aaf5a383SPascal van Leeuwen return safexcel_sha3_512_init(req) ?: safexcel_ahash_finup(req); 2712aaf5a383SPascal van Leeuwen 2713aaf5a383SPascal van Leeuwen /* HW cannot do zero length hash, use fallback instead */ 2714aaf5a383SPascal van Leeuwen return safexcel_sha3_digest_fallback(req); 2715aaf5a383SPascal van Leeuwen } 2716aaf5a383SPascal van Leeuwen 2717aaf5a383SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_sha3_512 = { 2718aaf5a383SPascal van Leeuwen .type = SAFEXCEL_ALG_TYPE_AHASH, 2719aaf5a383SPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA3, 2720aaf5a383SPascal van Leeuwen .alg.ahash = { 2721aaf5a383SPascal van Leeuwen .init = safexcel_sha3_512_init, 2722aaf5a383SPascal van Leeuwen .update = safexcel_sha3_update, 2723aaf5a383SPascal van Leeuwen .final = safexcel_sha3_final, 2724aaf5a383SPascal van Leeuwen .finup = safexcel_sha3_finup, 2725aaf5a383SPascal van Leeuwen .digest = safexcel_sha3_512_digest, 2726aaf5a383SPascal van Leeuwen .export = safexcel_sha3_export, 2727aaf5a383SPascal van Leeuwen .import = safexcel_sha3_import, 2728aaf5a383SPascal van Leeuwen .halg = { 2729aaf5a383SPascal van Leeuwen .digestsize = SHA3_512_DIGEST_SIZE, 2730aaf5a383SPascal van Leeuwen .statesize = sizeof(struct safexcel_ahash_export_state), 2731aaf5a383SPascal van Leeuwen .base = { 2732aaf5a383SPascal van Leeuwen .cra_name = "sha3-512", 2733aaf5a383SPascal van Leeuwen .cra_driver_name = "safexcel-sha3-512", 2734aaf5a383SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 2735aaf5a383SPascal van Leeuwen .cra_flags = CRYPTO_ALG_ASYNC | 2736aaf5a383SPascal van Leeuwen CRYPTO_ALG_KERN_DRIVER_ONLY | 2737aaf5a383SPascal van Leeuwen CRYPTO_ALG_NEED_FALLBACK, 2738aaf5a383SPascal van Leeuwen .cra_blocksize = SHA3_512_BLOCK_SIZE, 2739aaf5a383SPascal van Leeuwen .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 2740aaf5a383SPascal van Leeuwen .cra_init = safexcel_sha3_cra_init, 2741aaf5a383SPascal van Leeuwen .cra_exit = safexcel_sha3_cra_exit, 2742aaf5a383SPascal van Leeuwen .cra_module = THIS_MODULE, 2743aaf5a383SPascal van Leeuwen }, 2744aaf5a383SPascal van Leeuwen }, 2745aaf5a383SPascal van Leeuwen }, 2746aaf5a383SPascal van Leeuwen }; 27476c1c09b3SPascal van Leeuwen 27486c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_cra_init(struct crypto_tfm *tfm, const char *alg) 27496c1c09b3SPascal van Leeuwen { 27506c1c09b3SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 27516c1c09b3SPascal van Leeuwen int ret; 27526c1c09b3SPascal van Leeuwen 27536c1c09b3SPascal van Leeuwen ret = safexcel_sha3_cra_init(tfm); 27546c1c09b3SPascal van Leeuwen if (ret) 27556c1c09b3SPascal van Leeuwen return ret; 27566c1c09b3SPascal van Leeuwen 27576c1c09b3SPascal van Leeuwen /* Allocate precalc basic digest implementation */ 27586c1c09b3SPascal van Leeuwen ctx->shpre = crypto_alloc_shash(alg, 0, CRYPTO_ALG_NEED_FALLBACK); 27596c1c09b3SPascal van Leeuwen if (IS_ERR(ctx->shpre)) 27606c1c09b3SPascal van Leeuwen return PTR_ERR(ctx->shpre); 27616c1c09b3SPascal van Leeuwen 27626c1c09b3SPascal van Leeuwen ctx->shdesc = kmalloc(sizeof(*ctx->shdesc) + 27636c1c09b3SPascal van Leeuwen crypto_shash_descsize(ctx->shpre), GFP_KERNEL); 27646c1c09b3SPascal van Leeuwen if (!ctx->shdesc) { 27656c1c09b3SPascal van Leeuwen crypto_free_shash(ctx->shpre); 27666c1c09b3SPascal van Leeuwen return -ENOMEM; 27676c1c09b3SPascal van Leeuwen } 27686c1c09b3SPascal van Leeuwen ctx->shdesc->tfm = ctx->shpre; 27696c1c09b3SPascal van Leeuwen return 0; 27706c1c09b3SPascal van Leeuwen } 27716c1c09b3SPascal van Leeuwen 27726c1c09b3SPascal van Leeuwen static void safexcel_hmac_sha3_cra_exit(struct crypto_tfm *tfm) 27736c1c09b3SPascal van Leeuwen { 27746c1c09b3SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 27756c1c09b3SPascal van Leeuwen 27766c1c09b3SPascal van Leeuwen crypto_free_ahash(ctx->fback); 27776c1c09b3SPascal van Leeuwen crypto_free_shash(ctx->shpre); 27786c1c09b3SPascal van Leeuwen kfree(ctx->shdesc); 27796c1c09b3SPascal van Leeuwen safexcel_ahash_cra_exit(tfm); 27806c1c09b3SPascal van Leeuwen } 27816c1c09b3SPascal van Leeuwen 27826c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_setkey(struct crypto_ahash *tfm, const u8 *key, 27836c1c09b3SPascal van Leeuwen unsigned int keylen) 27846c1c09b3SPascal van Leeuwen { 27856c1c09b3SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 27866c1c09b3SPascal van Leeuwen int ret = 0; 27876c1c09b3SPascal van Leeuwen 27886c1c09b3SPascal van Leeuwen if (keylen > crypto_ahash_blocksize(tfm)) { 27896c1c09b3SPascal van Leeuwen /* 27906c1c09b3SPascal van Leeuwen * If the key is larger than the blocksize, then hash it 27916c1c09b3SPascal van Leeuwen * first using our fallback cipher 27926c1c09b3SPascal van Leeuwen */ 27936c1c09b3SPascal van Leeuwen ret = crypto_shash_digest(ctx->shdesc, key, keylen, 279478cf1c8bSHerbert Xu ctx->base.ipad.byte); 27956c1c09b3SPascal van Leeuwen keylen = crypto_shash_digestsize(ctx->shpre); 27966c1c09b3SPascal van Leeuwen 27976c1c09b3SPascal van Leeuwen /* 27986c1c09b3SPascal van Leeuwen * If the digest is larger than half the blocksize, we need to 27996c1c09b3SPascal van Leeuwen * move the rest to opad due to the way our HMAC infra works. 28006c1c09b3SPascal van Leeuwen */ 28016c1c09b3SPascal van Leeuwen if (keylen > crypto_ahash_blocksize(tfm) / 2) 28026c1c09b3SPascal van Leeuwen /* Buffers overlap, need to use memmove iso memcpy! */ 280378cf1c8bSHerbert Xu memmove(&ctx->base.opad, 280478cf1c8bSHerbert Xu ctx->base.ipad.byte + 28056c1c09b3SPascal van Leeuwen crypto_ahash_blocksize(tfm) / 2, 28066c1c09b3SPascal van Leeuwen keylen - crypto_ahash_blocksize(tfm) / 2); 28076c1c09b3SPascal van Leeuwen } else { 28086c1c09b3SPascal van Leeuwen /* 28096c1c09b3SPascal van Leeuwen * Copy the key to our ipad & opad buffers 28106c1c09b3SPascal van Leeuwen * Note that ipad and opad each contain one half of the key, 28116c1c09b3SPascal van Leeuwen * to match the existing HMAC driver infrastructure. 28126c1c09b3SPascal van Leeuwen */ 28136c1c09b3SPascal van Leeuwen if (keylen <= crypto_ahash_blocksize(tfm) / 2) { 281478cf1c8bSHerbert Xu memcpy(&ctx->base.ipad, key, keylen); 28156c1c09b3SPascal van Leeuwen } else { 281678cf1c8bSHerbert Xu memcpy(&ctx->base.ipad, key, 28176c1c09b3SPascal van Leeuwen crypto_ahash_blocksize(tfm) / 2); 281878cf1c8bSHerbert Xu memcpy(&ctx->base.opad, 28196c1c09b3SPascal van Leeuwen key + crypto_ahash_blocksize(tfm) / 2, 28206c1c09b3SPascal van Leeuwen keylen - crypto_ahash_blocksize(tfm) / 2); 28216c1c09b3SPascal van Leeuwen } 28226c1c09b3SPascal van Leeuwen } 28236c1c09b3SPascal van Leeuwen 28246c1c09b3SPascal van Leeuwen /* Pad key with zeroes */ 28256c1c09b3SPascal van Leeuwen if (keylen <= crypto_ahash_blocksize(tfm) / 2) { 282678cf1c8bSHerbert Xu memset(ctx->base.ipad.byte + keylen, 0, 28276c1c09b3SPascal van Leeuwen crypto_ahash_blocksize(tfm) / 2 - keylen); 282878cf1c8bSHerbert Xu memset(&ctx->base.opad, 0, crypto_ahash_blocksize(tfm) / 2); 28296c1c09b3SPascal van Leeuwen } else { 283078cf1c8bSHerbert Xu memset(ctx->base.opad.byte + keylen - 28316c1c09b3SPascal van Leeuwen crypto_ahash_blocksize(tfm) / 2, 0, 28326c1c09b3SPascal van Leeuwen crypto_ahash_blocksize(tfm) - keylen); 28336c1c09b3SPascal van Leeuwen } 28346c1c09b3SPascal van Leeuwen 28356c1c09b3SPascal van Leeuwen /* If doing fallback, still need to set the new key! */ 28366c1c09b3SPascal van Leeuwen ctx->fb_do_setkey = true; 28376c1c09b3SPascal van Leeuwen return ret; 28386c1c09b3SPascal van Leeuwen } 28396c1c09b3SPascal van Leeuwen 28406c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_224_init(struct ahash_request *areq) 28416c1c09b3SPascal van Leeuwen { 28426c1c09b3SPascal van Leeuwen struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 28436c1c09b3SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 28446c1c09b3SPascal van Leeuwen struct safexcel_ahash_req *req = ahash_request_ctx(areq); 28456c1c09b3SPascal van Leeuwen 28466c1c09b3SPascal van Leeuwen memset(req, 0, sizeof(*req)); 28476c1c09b3SPascal van Leeuwen 28486c1c09b3SPascal van Leeuwen /* Copy (half of) the key */ 284978cf1c8bSHerbert Xu memcpy(req->state, &ctx->base.ipad, SHA3_224_BLOCK_SIZE / 2); 28506c1c09b3SPascal van Leeuwen /* Start of HMAC should have len == processed == blocksize */ 28516c1c09b3SPascal van Leeuwen req->len = SHA3_224_BLOCK_SIZE; 28526c1c09b3SPascal van Leeuwen req->processed = SHA3_224_BLOCK_SIZE; 28536c1c09b3SPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_224; 28546c1c09b3SPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_HMAC; 28556c1c09b3SPascal van Leeuwen req->state_sz = SHA3_224_BLOCK_SIZE / 2; 28566c1c09b3SPascal van Leeuwen req->digest_sz = SHA3_224_DIGEST_SIZE; 28576c1c09b3SPascal van Leeuwen req->block_sz = SHA3_224_BLOCK_SIZE; 28586c1c09b3SPascal van Leeuwen req->hmac = true; 28596c1c09b3SPascal van Leeuwen ctx->do_fallback = false; 28606c1c09b3SPascal van Leeuwen ctx->fb_init_done = false; 28616c1c09b3SPascal van Leeuwen return 0; 28626c1c09b3SPascal van Leeuwen } 28636c1c09b3SPascal van Leeuwen 28646c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_224_digest(struct ahash_request *req) 28656c1c09b3SPascal van Leeuwen { 28666c1c09b3SPascal van Leeuwen if (req->nbytes) 28676c1c09b3SPascal van Leeuwen return safexcel_hmac_sha3_224_init(req) ?: 28686c1c09b3SPascal van Leeuwen safexcel_ahash_finup(req); 28696c1c09b3SPascal van Leeuwen 28706c1c09b3SPascal van Leeuwen /* HW cannot do zero length HMAC, use fallback instead */ 28716c1c09b3SPascal van Leeuwen return safexcel_sha3_digest_fallback(req); 28726c1c09b3SPascal van Leeuwen } 28736c1c09b3SPascal van Leeuwen 28746c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_224_cra_init(struct crypto_tfm *tfm) 28756c1c09b3SPascal van Leeuwen { 28766c1c09b3SPascal van Leeuwen return safexcel_hmac_sha3_cra_init(tfm, "sha3-224"); 28776c1c09b3SPascal van Leeuwen } 28786c1c09b3SPascal van Leeuwen 28796c1c09b3SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_hmac_sha3_224 = { 28806c1c09b3SPascal van Leeuwen .type = SAFEXCEL_ALG_TYPE_AHASH, 28816c1c09b3SPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA3, 28826c1c09b3SPascal van Leeuwen .alg.ahash = { 28836c1c09b3SPascal van Leeuwen .init = safexcel_hmac_sha3_224_init, 28846c1c09b3SPascal van Leeuwen .update = safexcel_sha3_update, 28856c1c09b3SPascal van Leeuwen .final = safexcel_sha3_final, 28866c1c09b3SPascal van Leeuwen .finup = safexcel_sha3_finup, 28876c1c09b3SPascal van Leeuwen .digest = safexcel_hmac_sha3_224_digest, 28886c1c09b3SPascal van Leeuwen .setkey = safexcel_hmac_sha3_setkey, 28896c1c09b3SPascal van Leeuwen .export = safexcel_sha3_export, 28906c1c09b3SPascal van Leeuwen .import = safexcel_sha3_import, 28916c1c09b3SPascal van Leeuwen .halg = { 28926c1c09b3SPascal van Leeuwen .digestsize = SHA3_224_DIGEST_SIZE, 28936c1c09b3SPascal van Leeuwen .statesize = sizeof(struct safexcel_ahash_export_state), 28946c1c09b3SPascal van Leeuwen .base = { 28956c1c09b3SPascal van Leeuwen .cra_name = "hmac(sha3-224)", 28966c1c09b3SPascal van Leeuwen .cra_driver_name = "safexcel-hmac-sha3-224", 28976c1c09b3SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 28986c1c09b3SPascal van Leeuwen .cra_flags = CRYPTO_ALG_ASYNC | 28996c1c09b3SPascal van Leeuwen CRYPTO_ALG_KERN_DRIVER_ONLY | 29006c1c09b3SPascal van Leeuwen CRYPTO_ALG_NEED_FALLBACK, 29016c1c09b3SPascal van Leeuwen .cra_blocksize = SHA3_224_BLOCK_SIZE, 29026c1c09b3SPascal van Leeuwen .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 29036c1c09b3SPascal van Leeuwen .cra_init = safexcel_hmac_sha3_224_cra_init, 29046c1c09b3SPascal van Leeuwen .cra_exit = safexcel_hmac_sha3_cra_exit, 29056c1c09b3SPascal van Leeuwen .cra_module = THIS_MODULE, 29066c1c09b3SPascal van Leeuwen }, 29076c1c09b3SPascal van Leeuwen }, 29086c1c09b3SPascal van Leeuwen }, 29096c1c09b3SPascal van Leeuwen }; 29106c1c09b3SPascal van Leeuwen 29116c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_256_init(struct ahash_request *areq) 29126c1c09b3SPascal van Leeuwen { 29136c1c09b3SPascal van Leeuwen struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 29146c1c09b3SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 29156c1c09b3SPascal van Leeuwen struct safexcel_ahash_req *req = ahash_request_ctx(areq); 29166c1c09b3SPascal van Leeuwen 29176c1c09b3SPascal van Leeuwen memset(req, 0, sizeof(*req)); 29186c1c09b3SPascal van Leeuwen 29196c1c09b3SPascal van Leeuwen /* Copy (half of) the key */ 292078cf1c8bSHerbert Xu memcpy(req->state, &ctx->base.ipad, SHA3_256_BLOCK_SIZE / 2); 29216c1c09b3SPascal van Leeuwen /* Start of HMAC should have len == processed == blocksize */ 29226c1c09b3SPascal van Leeuwen req->len = SHA3_256_BLOCK_SIZE; 29236c1c09b3SPascal van Leeuwen req->processed = SHA3_256_BLOCK_SIZE; 29246c1c09b3SPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_256; 29256c1c09b3SPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_HMAC; 29266c1c09b3SPascal van Leeuwen req->state_sz = SHA3_256_BLOCK_SIZE / 2; 29276c1c09b3SPascal van Leeuwen req->digest_sz = SHA3_256_DIGEST_SIZE; 29286c1c09b3SPascal van Leeuwen req->block_sz = SHA3_256_BLOCK_SIZE; 29296c1c09b3SPascal van Leeuwen req->hmac = true; 29306c1c09b3SPascal van Leeuwen ctx->do_fallback = false; 29316c1c09b3SPascal van Leeuwen ctx->fb_init_done = false; 29326c1c09b3SPascal van Leeuwen return 0; 29336c1c09b3SPascal van Leeuwen } 29346c1c09b3SPascal van Leeuwen 29356c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_256_digest(struct ahash_request *req) 29366c1c09b3SPascal van Leeuwen { 29376c1c09b3SPascal van Leeuwen if (req->nbytes) 29386c1c09b3SPascal van Leeuwen return safexcel_hmac_sha3_256_init(req) ?: 29396c1c09b3SPascal van Leeuwen safexcel_ahash_finup(req); 29406c1c09b3SPascal van Leeuwen 29416c1c09b3SPascal van Leeuwen /* HW cannot do zero length HMAC, use fallback instead */ 29426c1c09b3SPascal van Leeuwen return safexcel_sha3_digest_fallback(req); 29436c1c09b3SPascal van Leeuwen } 29446c1c09b3SPascal van Leeuwen 29456c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_256_cra_init(struct crypto_tfm *tfm) 29466c1c09b3SPascal van Leeuwen { 29476c1c09b3SPascal van Leeuwen return safexcel_hmac_sha3_cra_init(tfm, "sha3-256"); 29486c1c09b3SPascal van Leeuwen } 29496c1c09b3SPascal van Leeuwen 29506c1c09b3SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_hmac_sha3_256 = { 29516c1c09b3SPascal van Leeuwen .type = SAFEXCEL_ALG_TYPE_AHASH, 29526c1c09b3SPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA3, 29536c1c09b3SPascal van Leeuwen .alg.ahash = { 29546c1c09b3SPascal van Leeuwen .init = safexcel_hmac_sha3_256_init, 29556c1c09b3SPascal van Leeuwen .update = safexcel_sha3_update, 29566c1c09b3SPascal van Leeuwen .final = safexcel_sha3_final, 29576c1c09b3SPascal van Leeuwen .finup = safexcel_sha3_finup, 29586c1c09b3SPascal van Leeuwen .digest = safexcel_hmac_sha3_256_digest, 29596c1c09b3SPascal van Leeuwen .setkey = safexcel_hmac_sha3_setkey, 29606c1c09b3SPascal van Leeuwen .export = safexcel_sha3_export, 29616c1c09b3SPascal van Leeuwen .import = safexcel_sha3_import, 29626c1c09b3SPascal van Leeuwen .halg = { 29636c1c09b3SPascal van Leeuwen .digestsize = SHA3_256_DIGEST_SIZE, 29646c1c09b3SPascal van Leeuwen .statesize = sizeof(struct safexcel_ahash_export_state), 29656c1c09b3SPascal van Leeuwen .base = { 29666c1c09b3SPascal van Leeuwen .cra_name = "hmac(sha3-256)", 29676c1c09b3SPascal van Leeuwen .cra_driver_name = "safexcel-hmac-sha3-256", 29686c1c09b3SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 29696c1c09b3SPascal van Leeuwen .cra_flags = CRYPTO_ALG_ASYNC | 29706c1c09b3SPascal van Leeuwen CRYPTO_ALG_KERN_DRIVER_ONLY | 29716c1c09b3SPascal van Leeuwen CRYPTO_ALG_NEED_FALLBACK, 29726c1c09b3SPascal van Leeuwen .cra_blocksize = SHA3_256_BLOCK_SIZE, 29736c1c09b3SPascal van Leeuwen .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 29746c1c09b3SPascal van Leeuwen .cra_init = safexcel_hmac_sha3_256_cra_init, 29756c1c09b3SPascal van Leeuwen .cra_exit = safexcel_hmac_sha3_cra_exit, 29766c1c09b3SPascal van Leeuwen .cra_module = THIS_MODULE, 29776c1c09b3SPascal van Leeuwen }, 29786c1c09b3SPascal van Leeuwen }, 29796c1c09b3SPascal van Leeuwen }, 29806c1c09b3SPascal van Leeuwen }; 29816c1c09b3SPascal van Leeuwen 29826c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_384_init(struct ahash_request *areq) 29836c1c09b3SPascal van Leeuwen { 29846c1c09b3SPascal van Leeuwen struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 29856c1c09b3SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 29866c1c09b3SPascal van Leeuwen struct safexcel_ahash_req *req = ahash_request_ctx(areq); 29876c1c09b3SPascal van Leeuwen 29886c1c09b3SPascal van Leeuwen memset(req, 0, sizeof(*req)); 29896c1c09b3SPascal van Leeuwen 29906c1c09b3SPascal van Leeuwen /* Copy (half of) the key */ 299178cf1c8bSHerbert Xu memcpy(req->state, &ctx->base.ipad, SHA3_384_BLOCK_SIZE / 2); 29926c1c09b3SPascal van Leeuwen /* Start of HMAC should have len == processed == blocksize */ 29936c1c09b3SPascal van Leeuwen req->len = SHA3_384_BLOCK_SIZE; 29946c1c09b3SPascal van Leeuwen req->processed = SHA3_384_BLOCK_SIZE; 29956c1c09b3SPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_384; 29966c1c09b3SPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_HMAC; 29976c1c09b3SPascal van Leeuwen req->state_sz = SHA3_384_BLOCK_SIZE / 2; 29986c1c09b3SPascal van Leeuwen req->digest_sz = SHA3_384_DIGEST_SIZE; 29996c1c09b3SPascal van Leeuwen req->block_sz = SHA3_384_BLOCK_SIZE; 30006c1c09b3SPascal van Leeuwen req->hmac = true; 30016c1c09b3SPascal van Leeuwen ctx->do_fallback = false; 30026c1c09b3SPascal van Leeuwen ctx->fb_init_done = false; 30036c1c09b3SPascal van Leeuwen return 0; 30046c1c09b3SPascal van Leeuwen } 30056c1c09b3SPascal van Leeuwen 30066c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_384_digest(struct ahash_request *req) 30076c1c09b3SPascal van Leeuwen { 30086c1c09b3SPascal van Leeuwen if (req->nbytes) 30096c1c09b3SPascal van Leeuwen return safexcel_hmac_sha3_384_init(req) ?: 30106c1c09b3SPascal van Leeuwen safexcel_ahash_finup(req); 30116c1c09b3SPascal van Leeuwen 30126c1c09b3SPascal van Leeuwen /* HW cannot do zero length HMAC, use fallback instead */ 30136c1c09b3SPascal van Leeuwen return safexcel_sha3_digest_fallback(req); 30146c1c09b3SPascal van Leeuwen } 30156c1c09b3SPascal van Leeuwen 30166c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_384_cra_init(struct crypto_tfm *tfm) 30176c1c09b3SPascal van Leeuwen { 30186c1c09b3SPascal van Leeuwen return safexcel_hmac_sha3_cra_init(tfm, "sha3-384"); 30196c1c09b3SPascal van Leeuwen } 30206c1c09b3SPascal van Leeuwen 30216c1c09b3SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_hmac_sha3_384 = { 30226c1c09b3SPascal van Leeuwen .type = SAFEXCEL_ALG_TYPE_AHASH, 30236c1c09b3SPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA3, 30246c1c09b3SPascal van Leeuwen .alg.ahash = { 30256c1c09b3SPascal van Leeuwen .init = safexcel_hmac_sha3_384_init, 30266c1c09b3SPascal van Leeuwen .update = safexcel_sha3_update, 30276c1c09b3SPascal van Leeuwen .final = safexcel_sha3_final, 30286c1c09b3SPascal van Leeuwen .finup = safexcel_sha3_finup, 30296c1c09b3SPascal van Leeuwen .digest = safexcel_hmac_sha3_384_digest, 30306c1c09b3SPascal van Leeuwen .setkey = safexcel_hmac_sha3_setkey, 30316c1c09b3SPascal van Leeuwen .export = safexcel_sha3_export, 30326c1c09b3SPascal van Leeuwen .import = safexcel_sha3_import, 30336c1c09b3SPascal van Leeuwen .halg = { 30346c1c09b3SPascal van Leeuwen .digestsize = SHA3_384_DIGEST_SIZE, 30356c1c09b3SPascal van Leeuwen .statesize = sizeof(struct safexcel_ahash_export_state), 30366c1c09b3SPascal van Leeuwen .base = { 30376c1c09b3SPascal van Leeuwen .cra_name = "hmac(sha3-384)", 30386c1c09b3SPascal van Leeuwen .cra_driver_name = "safexcel-hmac-sha3-384", 30396c1c09b3SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 30406c1c09b3SPascal van Leeuwen .cra_flags = CRYPTO_ALG_ASYNC | 30416c1c09b3SPascal van Leeuwen CRYPTO_ALG_KERN_DRIVER_ONLY | 30426c1c09b3SPascal van Leeuwen CRYPTO_ALG_NEED_FALLBACK, 30436c1c09b3SPascal van Leeuwen .cra_blocksize = SHA3_384_BLOCK_SIZE, 30446c1c09b3SPascal van Leeuwen .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 30456c1c09b3SPascal van Leeuwen .cra_init = safexcel_hmac_sha3_384_cra_init, 30466c1c09b3SPascal van Leeuwen .cra_exit = safexcel_hmac_sha3_cra_exit, 30476c1c09b3SPascal van Leeuwen .cra_module = THIS_MODULE, 30486c1c09b3SPascal van Leeuwen }, 30496c1c09b3SPascal van Leeuwen }, 30506c1c09b3SPascal van Leeuwen }, 30516c1c09b3SPascal van Leeuwen }; 30526c1c09b3SPascal van Leeuwen 30536c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_512_init(struct ahash_request *areq) 30546c1c09b3SPascal van Leeuwen { 30556c1c09b3SPascal van Leeuwen struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 30566c1c09b3SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 30576c1c09b3SPascal van Leeuwen struct safexcel_ahash_req *req = ahash_request_ctx(areq); 30586c1c09b3SPascal van Leeuwen 30596c1c09b3SPascal van Leeuwen memset(req, 0, sizeof(*req)); 30606c1c09b3SPascal van Leeuwen 30616c1c09b3SPascal van Leeuwen /* Copy (half of) the key */ 306278cf1c8bSHerbert Xu memcpy(req->state, &ctx->base.ipad, SHA3_512_BLOCK_SIZE / 2); 30636c1c09b3SPascal van Leeuwen /* Start of HMAC should have len == processed == blocksize */ 30646c1c09b3SPascal van Leeuwen req->len = SHA3_512_BLOCK_SIZE; 30656c1c09b3SPascal van Leeuwen req->processed = SHA3_512_BLOCK_SIZE; 30666c1c09b3SPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_512; 30676c1c09b3SPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_HMAC; 30686c1c09b3SPascal van Leeuwen req->state_sz = SHA3_512_BLOCK_SIZE / 2; 30696c1c09b3SPascal van Leeuwen req->digest_sz = SHA3_512_DIGEST_SIZE; 30706c1c09b3SPascal van Leeuwen req->block_sz = SHA3_512_BLOCK_SIZE; 30716c1c09b3SPascal van Leeuwen req->hmac = true; 30726c1c09b3SPascal van Leeuwen ctx->do_fallback = false; 30736c1c09b3SPascal van Leeuwen ctx->fb_init_done = false; 30746c1c09b3SPascal van Leeuwen return 0; 30756c1c09b3SPascal van Leeuwen } 30766c1c09b3SPascal van Leeuwen 30776c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_512_digest(struct ahash_request *req) 30786c1c09b3SPascal van Leeuwen { 30796c1c09b3SPascal van Leeuwen if (req->nbytes) 30806c1c09b3SPascal van Leeuwen return safexcel_hmac_sha3_512_init(req) ?: 30816c1c09b3SPascal van Leeuwen safexcel_ahash_finup(req); 30826c1c09b3SPascal van Leeuwen 30836c1c09b3SPascal van Leeuwen /* HW cannot do zero length HMAC, use fallback instead */ 30846c1c09b3SPascal van Leeuwen return safexcel_sha3_digest_fallback(req); 30856c1c09b3SPascal van Leeuwen } 30866c1c09b3SPascal van Leeuwen 30876c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_512_cra_init(struct crypto_tfm *tfm) 30886c1c09b3SPascal van Leeuwen { 30896c1c09b3SPascal van Leeuwen return safexcel_hmac_sha3_cra_init(tfm, "sha3-512"); 30906c1c09b3SPascal van Leeuwen } 30916c1c09b3SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_hmac_sha3_512 = { 30926c1c09b3SPascal van Leeuwen .type = SAFEXCEL_ALG_TYPE_AHASH, 30936c1c09b3SPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA3, 30946c1c09b3SPascal van Leeuwen .alg.ahash = { 30956c1c09b3SPascal van Leeuwen .init = safexcel_hmac_sha3_512_init, 30966c1c09b3SPascal van Leeuwen .update = safexcel_sha3_update, 30976c1c09b3SPascal van Leeuwen .final = safexcel_sha3_final, 30986c1c09b3SPascal van Leeuwen .finup = safexcel_sha3_finup, 30996c1c09b3SPascal van Leeuwen .digest = safexcel_hmac_sha3_512_digest, 31006c1c09b3SPascal van Leeuwen .setkey = safexcel_hmac_sha3_setkey, 31016c1c09b3SPascal van Leeuwen .export = safexcel_sha3_export, 31026c1c09b3SPascal van Leeuwen .import = safexcel_sha3_import, 31036c1c09b3SPascal van Leeuwen .halg = { 31046c1c09b3SPascal van Leeuwen .digestsize = SHA3_512_DIGEST_SIZE, 31056c1c09b3SPascal van Leeuwen .statesize = sizeof(struct safexcel_ahash_export_state), 31066c1c09b3SPascal van Leeuwen .base = { 31076c1c09b3SPascal van Leeuwen .cra_name = "hmac(sha3-512)", 31086c1c09b3SPascal van Leeuwen .cra_driver_name = "safexcel-hmac-sha3-512", 31096c1c09b3SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 31106c1c09b3SPascal van Leeuwen .cra_flags = CRYPTO_ALG_ASYNC | 31116c1c09b3SPascal van Leeuwen CRYPTO_ALG_KERN_DRIVER_ONLY | 31126c1c09b3SPascal van Leeuwen CRYPTO_ALG_NEED_FALLBACK, 31136c1c09b3SPascal van Leeuwen .cra_blocksize = SHA3_512_BLOCK_SIZE, 31146c1c09b3SPascal van Leeuwen .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 31156c1c09b3SPascal van Leeuwen .cra_init = safexcel_hmac_sha3_512_cra_init, 31166c1c09b3SPascal van Leeuwen .cra_exit = safexcel_hmac_sha3_cra_exit, 31176c1c09b3SPascal van Leeuwen .cra_module = THIS_MODULE, 31186c1c09b3SPascal van Leeuwen }, 31196c1c09b3SPascal van Leeuwen }, 31206c1c09b3SPascal van Leeuwen }, 31216c1c09b3SPascal van Leeuwen }; 3122