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> 111b44c5a6SAntoine Ténart #include <crypto/sha.h> 1238f21b4bSPascal van Leeuwen #include <crypto/skcipher.h> 130f2bc131SPascal van Leeuwen #include <crypto/sm3.h> 141b44c5a6SAntoine Ténart #include <linux/device.h> 151b44c5a6SAntoine Ténart #include <linux/dma-mapping.h> 161b44c5a6SAntoine Ténart #include <linux/dmapool.h> 171b44c5a6SAntoine Ténart 181b44c5a6SAntoine Ténart #include "safexcel.h" 191b44c5a6SAntoine Ténart 201b44c5a6SAntoine Ténart struct safexcel_ahash_ctx { 211b44c5a6SAntoine Ténart struct safexcel_context base; 221b44c5a6SAntoine Ténart struct safexcel_crypto_priv *priv; 231b44c5a6SAntoine Ténart 241b44c5a6SAntoine Ténart u32 alg; 25b98687bbSPascal van Leeuwen u8 key_sz; 2638f21b4bSPascal van Leeuwen bool cbcmac; 271b44c5a6SAntoine Ténart 280de54fb1SAntoine Tenart u32 ipad[SHA512_DIGEST_SIZE / sizeof(u32)]; 290de54fb1SAntoine Tenart u32 opad[SHA512_DIGEST_SIZE / sizeof(u32)]; 3038f21b4bSPascal van Leeuwen 3138f21b4bSPascal van Leeuwen struct crypto_cipher *kaes; 321b44c5a6SAntoine Ténart }; 331b44c5a6SAntoine Ténart 341b44c5a6SAntoine Ténart struct safexcel_ahash_req { 351b44c5a6SAntoine Ténart bool last_req; 361b44c5a6SAntoine Ténart bool finish; 371b44c5a6SAntoine Ténart bool hmac; 381eb7b403SOfer Heifetz bool needs_inv; 3985b36ee8SPascal van Leeuwen bool hmac_zlen; 4085b36ee8SPascal van Leeuwen bool len_is_le; 41b98687bbSPascal van Leeuwen bool not_first; 42b98687bbSPascal van Leeuwen bool xcbcmac; 431b44c5a6SAntoine Ténart 44c957f8b3SAntoine Ténart int nents; 45b8592027SOfer Heifetz dma_addr_t result_dma; 46c957f8b3SAntoine Ténart 47b869648cSAntoine Tenart u32 digest; 48b869648cSAntoine Tenart 4941abed7dSPascal van Leeuwen u8 state_sz; /* expected state size, only set once */ 5041abed7dSPascal van Leeuwen u8 block_sz; /* block size, only set once */ 51b460edb6SAntoine Tenart u32 state[SHA512_DIGEST_SIZE / sizeof(u32)] __aligned(sizeof(u32)); 521b44c5a6SAntoine Ténart 5331fb084cSPascal van Leeuwen u64 len; 5431fb084cSPascal van Leeuwen u64 processed; 551b44c5a6SAntoine Ténart 5641abed7dSPascal van Leeuwen u8 cache[HASH_CACHE_SIZE] __aligned(sizeof(u32)); 57cff9a175SAntoine Tenart dma_addr_t cache_dma; 58cff9a175SAntoine Tenart unsigned int cache_sz; 59cff9a175SAntoine Tenart 6041abed7dSPascal van Leeuwen u8 cache_next[HASH_CACHE_SIZE] __aligned(sizeof(u32)); 611b44c5a6SAntoine Ténart }; 621b44c5a6SAntoine Ténart 63b460edb6SAntoine Tenart static inline u64 safexcel_queued_len(struct safexcel_ahash_req *req) 64b460edb6SAntoine Tenart { 6531fb084cSPascal van Leeuwen return req->len - req->processed; 66b460edb6SAntoine Tenart } 67b460edb6SAntoine Tenart 681b44c5a6SAntoine Ténart static void safexcel_hash_token(struct safexcel_command_desc *cdesc, 69b98687bbSPascal van Leeuwen u32 input_length, u32 result_length, 7038f21b4bSPascal van Leeuwen bool cbcmac) 711b44c5a6SAntoine Ténart { 721b44c5a6SAntoine Ténart struct safexcel_token *token = 731b44c5a6SAntoine Ténart (struct safexcel_token *)cdesc->control_data.token; 741b44c5a6SAntoine Ténart 751b44c5a6SAntoine Ténart token[0].opcode = EIP197_TOKEN_OPCODE_DIRECTION; 761b44c5a6SAntoine Ténart token[0].packet_length = input_length; 771b44c5a6SAntoine Ténart token[0].instructions = EIP197_TOKEN_INS_TYPE_HASH; 781b44c5a6SAntoine Ténart 79b98687bbSPascal van Leeuwen input_length &= 15; 8038f21b4bSPascal van Leeuwen if (unlikely(cbcmac && input_length)) { 811b44c5a6SAntoine Ténart token[1].opcode = EIP197_TOKEN_OPCODE_INSERT; 82b98687bbSPascal van Leeuwen token[1].packet_length = 16 - input_length; 83b98687bbSPascal van Leeuwen token[1].stat = EIP197_TOKEN_STAT_LAST_HASH; 84b98687bbSPascal van Leeuwen token[1].instructions = EIP197_TOKEN_INS_TYPE_HASH; 85b98687bbSPascal van Leeuwen } else { 86b98687bbSPascal van Leeuwen token[0].stat = EIP197_TOKEN_STAT_LAST_HASH; 87b98687bbSPascal van Leeuwen } 88b98687bbSPascal van Leeuwen 89b98687bbSPascal van Leeuwen token[2].opcode = EIP197_TOKEN_OPCODE_INSERT; 90b98687bbSPascal van Leeuwen token[2].stat = EIP197_TOKEN_STAT_LAST_HASH | 911b44c5a6SAntoine Ténart EIP197_TOKEN_STAT_LAST_PACKET; 92b98687bbSPascal van Leeuwen token[2].packet_length = result_length; 93b98687bbSPascal van Leeuwen token[2].instructions = EIP197_TOKEN_INS_TYPE_OUTPUT | 941b44c5a6SAntoine Ténart EIP197_TOKEN_INS_INSERT_HASH_DIGEST; 951b44c5a6SAntoine Ténart } 961b44c5a6SAntoine Ténart 971b44c5a6SAntoine Ténart static void safexcel_context_control(struct safexcel_ahash_ctx *ctx, 981b44c5a6SAntoine Ténart struct safexcel_ahash_req *req, 9941abed7dSPascal van Leeuwen struct safexcel_command_desc *cdesc) 1001b44c5a6SAntoine Ténart { 101b460edb6SAntoine Tenart struct safexcel_crypto_priv *priv = ctx->priv; 10241abed7dSPascal van Leeuwen u64 count = 0; 1031b44c5a6SAntoine Ténart 104a7cf8658SPascal van Leeuwen cdesc->control_data.control0 = ctx->alg; 105dc5268b6SPascal van Leeuwen 1061b44c5a6SAntoine Ténart /* 1071b44c5a6SAntoine Ténart * Copy the input digest if needed, and setup the context 1081b44c5a6SAntoine Ténart * fields. Do this now as we need it to setup the first command 1091b44c5a6SAntoine Ténart * descriptor. 1101b44c5a6SAntoine Ténart */ 111a7cf8658SPascal van Leeuwen if (unlikely(req->digest == CONTEXT_CONTROL_DIGEST_XCM)) { 112b98687bbSPascal van Leeuwen if (req->xcbcmac) 113b98687bbSPascal van Leeuwen memcpy(ctx->base.ctxr->data, ctx->ipad, ctx->key_sz); 114b98687bbSPascal van Leeuwen else 115b98687bbSPascal van Leeuwen memcpy(ctx->base.ctxr->data, req->state, req->state_sz); 116a7cf8658SPascal van Leeuwen 117b98687bbSPascal van Leeuwen if (!req->finish && req->xcbcmac) 118b98687bbSPascal van Leeuwen cdesc->control_data.control0 |= 119b98687bbSPascal van Leeuwen CONTEXT_CONTROL_DIGEST_XCM | 120a7cf8658SPascal van Leeuwen CONTEXT_CONTROL_TYPE_HASH_OUT | 121b98687bbSPascal van Leeuwen CONTEXT_CONTROL_NO_FINISH_HASH | 122b98687bbSPascal van Leeuwen CONTEXT_CONTROL_SIZE(req->state_sz / 123b98687bbSPascal van Leeuwen sizeof(u32)); 124b98687bbSPascal van Leeuwen else 125b98687bbSPascal van Leeuwen cdesc->control_data.control0 |= 126b98687bbSPascal van Leeuwen CONTEXT_CONTROL_DIGEST_XCM | 127b98687bbSPascal van Leeuwen CONTEXT_CONTROL_TYPE_HASH_OUT | 128b98687bbSPascal van Leeuwen CONTEXT_CONTROL_SIZE(req->state_sz / 129b98687bbSPascal van Leeuwen sizeof(u32)); 130a7cf8658SPascal van Leeuwen return; 131a7cf8658SPascal van Leeuwen } else if (!req->processed) { 13241abed7dSPascal van Leeuwen /* First - and possibly only - block of basic hash only */ 133b98687bbSPascal van Leeuwen if (req->finish) 134a7cf8658SPascal van Leeuwen cdesc->control_data.control0 |= req->digest | 13541abed7dSPascal van Leeuwen CONTEXT_CONTROL_TYPE_HASH_OUT | 13641abed7dSPascal van Leeuwen CONTEXT_CONTROL_RESTART_HASH | 13741abed7dSPascal van Leeuwen /* ensure its not 0! */ 13841abed7dSPascal van Leeuwen CONTEXT_CONTROL_SIZE(1); 139b98687bbSPascal van Leeuwen else 140a7cf8658SPascal van Leeuwen cdesc->control_data.control0 |= req->digest | 14141abed7dSPascal van Leeuwen CONTEXT_CONTROL_TYPE_HASH_OUT | 14241abed7dSPascal van Leeuwen CONTEXT_CONTROL_RESTART_HASH | 14341abed7dSPascal van Leeuwen CONTEXT_CONTROL_NO_FINISH_HASH | 14441abed7dSPascal van Leeuwen /* ensure its not 0! */ 14541abed7dSPascal van Leeuwen CONTEXT_CONTROL_SIZE(1); 14641abed7dSPascal van Leeuwen return; 14741abed7dSPascal van Leeuwen } 14841abed7dSPascal van Leeuwen 14941abed7dSPascal van Leeuwen /* Hash continuation or HMAC, setup (inner) digest from state */ 15041abed7dSPascal van Leeuwen memcpy(ctx->base.ctxr->data, req->state, req->state_sz); 1511b44c5a6SAntoine Ténart 152b460edb6SAntoine Tenart if (req->finish) { 15341abed7dSPascal van Leeuwen /* Compute digest count for hash/HMAC finish operations */ 15441abed7dSPascal van Leeuwen if ((req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) || 15531fb084cSPascal van Leeuwen req->hmac_zlen || (req->processed != req->block_sz)) { 15631fb084cSPascal van Leeuwen count = req->processed / EIP197_COUNTER_BLOCK_SIZE; 157b460edb6SAntoine Tenart 15841abed7dSPascal van Leeuwen /* This is a hardware limitation, as the 159b460edb6SAntoine Tenart * counter must fit into an u32. This represents 16041abed7dSPascal van Leeuwen * a fairly big amount of input data, so we 161b460edb6SAntoine Tenart * shouldn't see this. 162b460edb6SAntoine Tenart */ 16341abed7dSPascal van Leeuwen if (unlikely(count & 0xffffffff00000000ULL)) { 164b460edb6SAntoine Tenart dev_warn(priv->dev, 165b460edb6SAntoine Tenart "Input data is too big\n"); 166b460edb6SAntoine Tenart return; 167b460edb6SAntoine Tenart } 168b460edb6SAntoine Tenart } 1691b44c5a6SAntoine Ténart 17041abed7dSPascal van Leeuwen if ((req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) || 17185b36ee8SPascal van Leeuwen /* Special case: zero length HMAC */ 17285b36ee8SPascal van Leeuwen req->hmac_zlen || 17341abed7dSPascal van Leeuwen /* PE HW < 4.4 cannot do HMAC continue, fake using hash */ 17431fb084cSPascal van Leeuwen (req->processed != req->block_sz)) { 17541abed7dSPascal van Leeuwen /* Basic hash continue operation, need digest + cnt */ 17641abed7dSPascal van Leeuwen cdesc->control_data.control0 |= 17741abed7dSPascal van Leeuwen CONTEXT_CONTROL_SIZE((req->state_sz >> 2) + 1) | 17841abed7dSPascal van Leeuwen CONTEXT_CONTROL_TYPE_HASH_OUT | 17941abed7dSPascal van Leeuwen CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 18085b36ee8SPascal van Leeuwen /* For zero-len HMAC, don't finalize, already padded! */ 18185b36ee8SPascal van Leeuwen if (req->hmac_zlen) 18285b36ee8SPascal van Leeuwen cdesc->control_data.control0 |= 18385b36ee8SPascal van Leeuwen CONTEXT_CONTROL_NO_FINISH_HASH; 18441abed7dSPascal van Leeuwen cdesc->control_data.control1 |= 18541abed7dSPascal van Leeuwen CONTEXT_CONTROL_DIGEST_CNT; 18641abed7dSPascal van Leeuwen ctx->base.ctxr->data[req->state_sz >> 2] = 18741abed7dSPascal van Leeuwen cpu_to_le32(count); 18841abed7dSPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 18985b36ee8SPascal van Leeuwen 19085b36ee8SPascal van Leeuwen /* Clear zero-length HMAC flag for next operation! */ 19185b36ee8SPascal van Leeuwen req->hmac_zlen = false; 19241abed7dSPascal van Leeuwen } else { /* HMAC */ 19341abed7dSPascal van Leeuwen /* Need outer digest for HMAC finalization */ 19441abed7dSPascal van Leeuwen memcpy(ctx->base.ctxr->data + (req->state_sz >> 2), 1954505bb02SAntoine Tenart ctx->opad, req->state_sz); 19641abed7dSPascal van Leeuwen 19741abed7dSPascal van Leeuwen /* Single pass HMAC - no digest count */ 19841abed7dSPascal van Leeuwen cdesc->control_data.control0 |= 19941abed7dSPascal van Leeuwen CONTEXT_CONTROL_SIZE(req->state_sz >> 1) | 20041abed7dSPascal van Leeuwen CONTEXT_CONTROL_TYPE_HASH_OUT | 20141abed7dSPascal van Leeuwen CONTEXT_CONTROL_DIGEST_HMAC; 20241abed7dSPascal van Leeuwen } 20341abed7dSPascal van Leeuwen } else { /* Hash continuation, do not finish yet */ 20441abed7dSPascal van Leeuwen cdesc->control_data.control0 |= 20541abed7dSPascal van Leeuwen CONTEXT_CONTROL_SIZE(req->state_sz >> 2) | 20641abed7dSPascal van Leeuwen CONTEXT_CONTROL_DIGEST_PRECOMPUTED | 20741abed7dSPascal van Leeuwen CONTEXT_CONTROL_TYPE_HASH_OUT | 20841abed7dSPascal van Leeuwen CONTEXT_CONTROL_NO_FINISH_HASH; 2091b44c5a6SAntoine Ténart } 2101b44c5a6SAntoine Ténart } 2111b44c5a6SAntoine Ténart 21241abed7dSPascal van Leeuwen static int safexcel_ahash_enqueue(struct ahash_request *areq); 21341abed7dSPascal van Leeuwen 21441abed7dSPascal van Leeuwen static int safexcel_handle_req_result(struct safexcel_crypto_priv *priv, 21541abed7dSPascal van Leeuwen int ring, 2161b44c5a6SAntoine Ténart struct crypto_async_request *async, 2171b44c5a6SAntoine Ténart bool *should_complete, int *ret) 2181b44c5a6SAntoine Ténart { 2191b44c5a6SAntoine Ténart struct safexcel_result_desc *rdesc; 2201b44c5a6SAntoine Ténart struct ahash_request *areq = ahash_request_cast(async); 2211b44c5a6SAntoine Ténart struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); 2221b44c5a6SAntoine Ténart struct safexcel_ahash_req *sreq = ahash_request_ctx(areq); 22341abed7dSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(ahash); 224b460edb6SAntoine Tenart u64 cache_len; 2251b44c5a6SAntoine Ténart 2261b44c5a6SAntoine Ténart *ret = 0; 2271b44c5a6SAntoine Ténart 2281b44c5a6SAntoine Ténart rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr); 2291b44c5a6SAntoine Ténart if (IS_ERR(rdesc)) { 2301b44c5a6SAntoine Ténart dev_err(priv->dev, 2311b44c5a6SAntoine Ténart "hash: result: could not retrieve the result descriptor\n"); 2321b44c5a6SAntoine Ténart *ret = PTR_ERR(rdesc); 233bdfd1909SAntoine Tenart } else { 234bdfd1909SAntoine Tenart *ret = safexcel_rdesc_check_errors(priv, rdesc); 2351b44c5a6SAntoine Ténart } 2361b44c5a6SAntoine Ténart 2371b44c5a6SAntoine Ténart safexcel_complete(priv, ring); 2381b44c5a6SAntoine Ténart 239c957f8b3SAntoine Ténart if (sreq->nents) { 240c957f8b3SAntoine Ténart dma_unmap_sg(priv->dev, areq->src, sreq->nents, DMA_TO_DEVICE); 241c957f8b3SAntoine Ténart sreq->nents = 0; 242c957f8b3SAntoine Ténart } 2431b44c5a6SAntoine Ténart 244b8592027SOfer Heifetz if (sreq->result_dma) { 245b8592027SOfer Heifetz dma_unmap_single(priv->dev, sreq->result_dma, sreq->state_sz, 246b8592027SOfer Heifetz DMA_FROM_DEVICE); 247b8592027SOfer Heifetz sreq->result_dma = 0; 248b8592027SOfer Heifetz } 249b8592027SOfer Heifetz 250cff9a175SAntoine Tenart if (sreq->cache_dma) { 251cff9a175SAntoine Tenart dma_unmap_single(priv->dev, sreq->cache_dma, sreq->cache_sz, 252cff9a175SAntoine Tenart DMA_TO_DEVICE); 253cff9a175SAntoine Tenart sreq->cache_dma = 0; 254aa524286SAntoine Tenart sreq->cache_sz = 0; 255cff9a175SAntoine Tenart } 2561b44c5a6SAntoine Ténart 25741abed7dSPascal van Leeuwen if (sreq->finish) { 25841abed7dSPascal van Leeuwen if (sreq->hmac && 25941abed7dSPascal van Leeuwen (sreq->digest != CONTEXT_CONTROL_DIGEST_HMAC)) { 26041abed7dSPascal van Leeuwen /* Faking HMAC using hash - need to do outer hash */ 26141abed7dSPascal van Leeuwen memcpy(sreq->cache, sreq->state, 26241abed7dSPascal van Leeuwen crypto_ahash_digestsize(ahash)); 26341abed7dSPascal van Leeuwen 26441abed7dSPascal van Leeuwen memcpy(sreq->state, ctx->opad, sreq->state_sz); 26541abed7dSPascal van Leeuwen 26631fb084cSPascal van Leeuwen sreq->len = sreq->block_sz + 26741abed7dSPascal van Leeuwen crypto_ahash_digestsize(ahash); 26831fb084cSPascal van Leeuwen sreq->processed = sreq->block_sz; 26941abed7dSPascal van Leeuwen sreq->hmac = 0; 27041abed7dSPascal van Leeuwen 27141abed7dSPascal van Leeuwen ctx->base.needs_inv = true; 27241abed7dSPascal van Leeuwen areq->nbytes = 0; 27341abed7dSPascal van Leeuwen safexcel_ahash_enqueue(areq); 27441abed7dSPascal van Leeuwen 27541abed7dSPascal van Leeuwen *should_complete = false; /* Not done yet */ 27641abed7dSPascal van Leeuwen return 1; 27741abed7dSPascal van Leeuwen } 27841abed7dSPascal van Leeuwen 279b98687bbSPascal van Leeuwen if (unlikely(sreq->digest == CONTEXT_CONTROL_DIGEST_XCM && 280b98687bbSPascal van Leeuwen ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_CRC32)) { 281a7cf8658SPascal van Leeuwen /* Undo final XOR with 0xffffffff ...*/ 282a7cf8658SPascal van Leeuwen *(u32 *)areq->result = ~sreq->state[0]; 283a7cf8658SPascal van Leeuwen } else { 284b89a8159SAntoine Tenart memcpy(areq->result, sreq->state, 285b89a8159SAntoine Tenart crypto_ahash_digestsize(ahash)); 28641abed7dSPascal van Leeuwen } 287a7cf8658SPascal van Leeuwen } 288b89a8159SAntoine Tenart 289b460edb6SAntoine Tenart cache_len = safexcel_queued_len(sreq); 2901b44c5a6SAntoine Ténart if (cache_len) 2911b44c5a6SAntoine Ténart memcpy(sreq->cache, sreq->cache_next, cache_len); 2921b44c5a6SAntoine Ténart 2931b44c5a6SAntoine Ténart *should_complete = true; 2941b44c5a6SAntoine Ténart 2951b44c5a6SAntoine Ténart return 1; 2961b44c5a6SAntoine Ténart } 2971b44c5a6SAntoine Ténart 2981eb7b403SOfer Heifetz static int safexcel_ahash_send_req(struct crypto_async_request *async, int ring, 2991eb7b403SOfer Heifetz int *commands, int *results) 3001b44c5a6SAntoine Ténart { 3011b44c5a6SAntoine Ténart struct ahash_request *areq = ahash_request_cast(async); 3021b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 3031b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 3041b44c5a6SAntoine Ténart struct safexcel_crypto_priv *priv = ctx->priv; 3051b44c5a6SAntoine Ténart struct safexcel_command_desc *cdesc, *first_cdesc = NULL; 3061b44c5a6SAntoine Ténart struct safexcel_result_desc *rdesc; 3071b44c5a6SAntoine Ténart struct scatterlist *sg; 308b98687bbSPascal van Leeuwen int i, extra = 0, n_cdesc = 0, ret = 0, cache_len, skip = 0, res_sz; 309b98687bbSPascal van Leeuwen u64 queued, len; 3101b44c5a6SAntoine Ténart 311b98687bbSPascal van Leeuwen queued = safexcel_queued_len(req); 31241abed7dSPascal van Leeuwen if (queued <= HASH_CACHE_SIZE) 3131b44c5a6SAntoine Ténart cache_len = queued; 3141b44c5a6SAntoine Ténart else 3151b44c5a6SAntoine Ténart cache_len = queued - areq->nbytes; 3161b44c5a6SAntoine Ténart 31741abed7dSPascal van Leeuwen if (!req->finish && !req->last_req) { 318809778e0SAntoine Ténart /* If this is not the last request and the queued data does not 31941abed7dSPascal van Leeuwen * fit into full cache blocks, cache it for the next send call. 3201b44c5a6SAntoine Ténart */ 32141abed7dSPascal van Leeuwen extra = queued & (HASH_CACHE_SIZE - 1); 322082ec2d4SAntoine Tenart 323809778e0SAntoine Ténart /* If this is not the last request and the queued data 324809778e0SAntoine Ténart * is a multiple of a block, cache the last one for now. 325809778e0SAntoine Ténart */ 326dd4306a6SAntoine Tenart if (!extra) 32741abed7dSPascal van Leeuwen extra = HASH_CACHE_SIZE; 328809778e0SAntoine Ténart 3291b44c5a6SAntoine Ténart sg_pcopy_to_buffer(areq->src, sg_nents(areq->src), 330809778e0SAntoine Ténart req->cache_next, extra, 331809778e0SAntoine Ténart areq->nbytes - extra); 3321b44c5a6SAntoine Ténart 3331b44c5a6SAntoine Ténart queued -= extra; 334dc5268b6SPascal van Leeuwen 335dc5268b6SPascal van Leeuwen if (!queued) { 336dc5268b6SPascal van Leeuwen *commands = 0; 337dc5268b6SPascal van Leeuwen *results = 0; 338dc5268b6SPascal van Leeuwen return 0; 339dc5268b6SPascal van Leeuwen } 340b98687bbSPascal van Leeuwen 341b98687bbSPascal van Leeuwen extra = 0; 342809778e0SAntoine Ténart } 3431b44c5a6SAntoine Ténart 344b98687bbSPascal van Leeuwen if (unlikely(req->xcbcmac && req->processed > AES_BLOCK_SIZE)) { 345b98687bbSPascal van Leeuwen if (unlikely(cache_len < AES_BLOCK_SIZE)) { 346b98687bbSPascal van Leeuwen /* 347b98687bbSPascal van Leeuwen * Cache contains less than 1 full block, complete. 348b98687bbSPascal van Leeuwen */ 349b98687bbSPascal van Leeuwen extra = AES_BLOCK_SIZE - cache_len; 350b98687bbSPascal van Leeuwen if (queued > cache_len) { 351b98687bbSPascal van Leeuwen /* More data follows: borrow bytes */ 352b98687bbSPascal van Leeuwen u64 tmp = queued - cache_len; 353b98687bbSPascal van Leeuwen 354b98687bbSPascal van Leeuwen skip = min_t(u64, tmp, extra); 355b98687bbSPascal van Leeuwen sg_pcopy_to_buffer(areq->src, 356b98687bbSPascal van Leeuwen sg_nents(areq->src), 357b98687bbSPascal van Leeuwen req->cache + cache_len, 358b98687bbSPascal van Leeuwen skip, 0); 359b98687bbSPascal van Leeuwen } 360b98687bbSPascal van Leeuwen extra -= skip; 361b98687bbSPascal van Leeuwen memset(req->cache + cache_len + skip, 0, extra); 36238f21b4bSPascal van Leeuwen if (!ctx->cbcmac && extra) { 36338f21b4bSPascal van Leeuwen // 10- padding for XCBCMAC & CMAC 36438f21b4bSPascal van Leeuwen req->cache[cache_len + skip] = 0x80; 36538f21b4bSPascal van Leeuwen // HW will use K2 iso K3 - compensate! 36638f21b4bSPascal van Leeuwen for (i = 0; i < AES_BLOCK_SIZE / sizeof(u32); i++) 36738f21b4bSPascal van Leeuwen ((u32 *)req->cache)[i] ^= 36838f21b4bSPascal van Leeuwen cpu_to_be32(ctx->ipad[i]) ^ 36938f21b4bSPascal van Leeuwen cpu_to_be32(ctx->ipad[i + 4]); 37038f21b4bSPascal van Leeuwen } 371b98687bbSPascal van Leeuwen cache_len = AES_BLOCK_SIZE; 372b98687bbSPascal van Leeuwen queued = queued + extra; 373b98687bbSPascal van Leeuwen } 374b98687bbSPascal van Leeuwen 375b98687bbSPascal van Leeuwen /* XCBC continue: XOR previous result into 1st word */ 376b98687bbSPascal van Leeuwen crypto_xor(req->cache, (const u8 *)req->state, AES_BLOCK_SIZE); 377b98687bbSPascal van Leeuwen } 378b98687bbSPascal van Leeuwen 379b98687bbSPascal van Leeuwen len = queued; 3801b44c5a6SAntoine Ténart /* Add a command descriptor for the cached data, if any */ 3811b44c5a6SAntoine Ténart if (cache_len) { 382cff9a175SAntoine Tenart req->cache_dma = dma_map_single(priv->dev, req->cache, 3831b44c5a6SAntoine Ténart cache_len, DMA_TO_DEVICE); 3849744fec9SOfer Heifetz if (dma_mapping_error(priv->dev, req->cache_dma)) 385cff9a175SAntoine Tenart return -EINVAL; 3861b44c5a6SAntoine Ténart 387cff9a175SAntoine Tenart req->cache_sz = cache_len; 3881b44c5a6SAntoine Ténart first_cdesc = safexcel_add_cdesc(priv, ring, 1, 3891b44c5a6SAntoine Ténart (cache_len == len), 390b98687bbSPascal van Leeuwen req->cache_dma, cache_len, 391b98687bbSPascal van Leeuwen len, ctx->base.ctxr_dma); 3921b44c5a6SAntoine Ténart if (IS_ERR(first_cdesc)) { 3931b44c5a6SAntoine Ténart ret = PTR_ERR(first_cdesc); 3941b44c5a6SAntoine Ténart goto unmap_cache; 3951b44c5a6SAntoine Ténart } 3961b44c5a6SAntoine Ténart n_cdesc++; 3971b44c5a6SAntoine Ténart 3981b44c5a6SAntoine Ténart queued -= cache_len; 3991b44c5a6SAntoine Ténart if (!queued) 4001b44c5a6SAntoine Ténart goto send_command; 4011b44c5a6SAntoine Ténart } 4021b44c5a6SAntoine Ténart 4031b44c5a6SAntoine Ténart /* Now handle the current ahash request buffer(s) */ 40441abed7dSPascal van Leeuwen req->nents = dma_map_sg(priv->dev, areq->src, 40541abed7dSPascal van Leeuwen sg_nents_for_len(areq->src, 40641abed7dSPascal van Leeuwen areq->nbytes), 4071b44c5a6SAntoine Ténart DMA_TO_DEVICE); 408c957f8b3SAntoine Ténart if (!req->nents) { 4091b44c5a6SAntoine Ténart ret = -ENOMEM; 4101b44c5a6SAntoine Ténart goto cdesc_rollback; 4111b44c5a6SAntoine Ténart } 4121b44c5a6SAntoine Ténart 413c957f8b3SAntoine Ténart for_each_sg(areq->src, sg, req->nents, i) { 4141b44c5a6SAntoine Ténart int sglen = sg_dma_len(sg); 4151b44c5a6SAntoine Ténart 416b98687bbSPascal van Leeuwen if (unlikely(sglen <= skip)) { 417b98687bbSPascal van Leeuwen skip -= sglen; 418b98687bbSPascal van Leeuwen continue; 419b98687bbSPascal van Leeuwen } 420b98687bbSPascal van Leeuwen 4211b44c5a6SAntoine Ténart /* Do not overflow the request */ 422b98687bbSPascal van Leeuwen if ((queued + skip) <= sglen) 4231b44c5a6SAntoine Ténart sglen = queued; 424b98687bbSPascal van Leeuwen else 425b98687bbSPascal van Leeuwen sglen -= skip; 4261b44c5a6SAntoine Ténart 4271b44c5a6SAntoine Ténart cdesc = safexcel_add_cdesc(priv, ring, !n_cdesc, 42841abed7dSPascal van Leeuwen !(queued - sglen), 429b98687bbSPascal van Leeuwen sg_dma_address(sg) + skip, sglen, 430b98687bbSPascal van Leeuwen len, ctx->base.ctxr_dma); 4311b44c5a6SAntoine Ténart if (IS_ERR(cdesc)) { 4321b44c5a6SAntoine Ténart ret = PTR_ERR(cdesc); 43357433b58SAntoine Tenart goto unmap_sg; 4341b44c5a6SAntoine Ténart } 4351b44c5a6SAntoine Ténart 436b98687bbSPascal van Leeuwen if (!n_cdesc) 4371b44c5a6SAntoine Ténart first_cdesc = cdesc; 438b98687bbSPascal van Leeuwen n_cdesc++; 4391b44c5a6SAntoine Ténart 4401b44c5a6SAntoine Ténart queued -= sglen; 4411b44c5a6SAntoine Ténart if (!queued) 4421b44c5a6SAntoine Ténart break; 443b98687bbSPascal van Leeuwen skip = 0; 4441b44c5a6SAntoine Ténart } 4451b44c5a6SAntoine Ténart 4461b44c5a6SAntoine Ténart send_command: 4471b44c5a6SAntoine Ténart /* Setup the context options */ 44841abed7dSPascal van Leeuwen safexcel_context_control(ctx, req, first_cdesc); 4491b44c5a6SAntoine Ténart 450b98687bbSPascal van Leeuwen /* Add the token. Note that the XCBC result is only 1 AES block. */ 451b98687bbSPascal van Leeuwen res_sz = req->xcbcmac ? AES_BLOCK_SIZE : req->state_sz; 45238f21b4bSPascal van Leeuwen safexcel_hash_token(first_cdesc, len, res_sz, ctx->cbcmac); 4531b44c5a6SAntoine Ténart 454b8592027SOfer Heifetz req->result_dma = dma_map_single(priv->dev, req->state, req->state_sz, 455b8592027SOfer Heifetz DMA_FROM_DEVICE); 456b8592027SOfer Heifetz if (dma_mapping_error(priv->dev, req->result_dma)) { 4571b44c5a6SAntoine Ténart ret = -EINVAL; 45857433b58SAntoine Tenart goto unmap_sg; 4591b44c5a6SAntoine Ténart } 4601b44c5a6SAntoine Ténart 4611b44c5a6SAntoine Ténart /* Add a result descriptor */ 462b8592027SOfer Heifetz rdesc = safexcel_add_rdesc(priv, ring, 1, 1, req->result_dma, 463b98687bbSPascal van Leeuwen res_sz); 4641b44c5a6SAntoine Ténart if (IS_ERR(rdesc)) { 4651b44c5a6SAntoine Ténart ret = PTR_ERR(rdesc); 46657240a78SAntoine Tenart goto unmap_result; 4671b44c5a6SAntoine Ténart } 4681b44c5a6SAntoine Ténart 4699744fec9SOfer Heifetz safexcel_rdr_req_set(priv, ring, rdesc, &areq->base); 4701b44c5a6SAntoine Ténart 471b98687bbSPascal van Leeuwen req->processed += len - extra; 472b460edb6SAntoine Tenart 4731b44c5a6SAntoine Ténart *commands = n_cdesc; 4741b44c5a6SAntoine Ténart *results = 1; 4751b44c5a6SAntoine Ténart return 0; 4761b44c5a6SAntoine Ténart 47757240a78SAntoine Tenart unmap_result: 47857433b58SAntoine Tenart dma_unmap_single(priv->dev, req->result_dma, req->state_sz, 47957433b58SAntoine Tenart DMA_FROM_DEVICE); 48057433b58SAntoine Tenart unmap_sg: 481b98687bbSPascal van Leeuwen if (req->nents) { 48257240a78SAntoine Tenart dma_unmap_sg(priv->dev, areq->src, req->nents, DMA_TO_DEVICE); 483b98687bbSPascal van Leeuwen req->nents = 0; 484b98687bbSPascal van Leeuwen } 4851b44c5a6SAntoine Ténart cdesc_rollback: 4861b44c5a6SAntoine Ténart for (i = 0; i < n_cdesc; i++) 4871b44c5a6SAntoine Ténart safexcel_ring_rollback_wptr(priv, &priv->ring[ring].cdr); 4881b44c5a6SAntoine Ténart unmap_cache: 489cff9a175SAntoine Tenart if (req->cache_dma) { 490cff9a175SAntoine Tenart dma_unmap_single(priv->dev, req->cache_dma, req->cache_sz, 491cff9a175SAntoine Tenart DMA_TO_DEVICE); 492aa524286SAntoine Tenart req->cache_dma = 0; 493cff9a175SAntoine Tenart req->cache_sz = 0; 4941b44c5a6SAntoine Ténart } 4951b44c5a6SAntoine Ténart 4961b44c5a6SAntoine Ténart return ret; 4971b44c5a6SAntoine Ténart } 4981b44c5a6SAntoine Ténart 4991b44c5a6SAntoine Ténart static int safexcel_handle_inv_result(struct safexcel_crypto_priv *priv, 5001b44c5a6SAntoine Ténart int ring, 5011b44c5a6SAntoine Ténart struct crypto_async_request *async, 5021b44c5a6SAntoine Ténart bool *should_complete, int *ret) 5031b44c5a6SAntoine Ténart { 5041b44c5a6SAntoine Ténart struct safexcel_result_desc *rdesc; 5051b44c5a6SAntoine Ténart struct ahash_request *areq = ahash_request_cast(async); 5061b44c5a6SAntoine Ténart struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); 5071b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(ahash); 5081b44c5a6SAntoine Ténart int enq_ret; 5091b44c5a6SAntoine Ténart 5101b44c5a6SAntoine Ténart *ret = 0; 5111b44c5a6SAntoine Ténart 5121b44c5a6SAntoine Ténart rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr); 5131b44c5a6SAntoine Ténart if (IS_ERR(rdesc)) { 5141b44c5a6SAntoine Ténart dev_err(priv->dev, 5151b44c5a6SAntoine Ténart "hash: invalidate: could not retrieve the result descriptor\n"); 5161b44c5a6SAntoine Ténart *ret = PTR_ERR(rdesc); 517cda3e73aSAntoine Tenart } else { 518cda3e73aSAntoine Tenart *ret = safexcel_rdesc_check_errors(priv, rdesc); 5191b44c5a6SAntoine Ténart } 5201b44c5a6SAntoine Ténart 5211b44c5a6SAntoine Ténart safexcel_complete(priv, ring); 5221b44c5a6SAntoine Ténart 5231b44c5a6SAntoine Ténart if (ctx->base.exit_inv) { 5241b44c5a6SAntoine Ténart dma_pool_free(priv->context_pool, ctx->base.ctxr, 5251b44c5a6SAntoine Ténart ctx->base.ctxr_dma); 5261b44c5a6SAntoine Ténart 5271b44c5a6SAntoine Ténart *should_complete = true; 5281b44c5a6SAntoine Ténart return 1; 5291b44c5a6SAntoine Ténart } 5301b44c5a6SAntoine Ténart 53186671abbSAntoine Ténart ring = safexcel_select_ring(priv); 53286671abbSAntoine Ténart ctx->base.ring = ring; 5331b44c5a6SAntoine Ténart 53486671abbSAntoine Ténart spin_lock_bh(&priv->ring[ring].queue_lock); 53586671abbSAntoine Ténart enq_ret = crypto_enqueue_request(&priv->ring[ring].queue, async); 53686671abbSAntoine Ténart spin_unlock_bh(&priv->ring[ring].queue_lock); 5371b44c5a6SAntoine Ténart 5381b44c5a6SAntoine Ténart if (enq_ret != -EINPROGRESS) 5391b44c5a6SAntoine Ténart *ret = enq_ret; 5401b44c5a6SAntoine Ténart 5418472e778SAntoine Ténart queue_work(priv->ring[ring].workqueue, 5428472e778SAntoine Ténart &priv->ring[ring].work_data.work); 54386671abbSAntoine Ténart 5441b44c5a6SAntoine Ténart *should_complete = false; 5451b44c5a6SAntoine Ténart 5461b44c5a6SAntoine Ténart return 1; 5471b44c5a6SAntoine Ténart } 5481b44c5a6SAntoine Ténart 5491eb7b403SOfer Heifetz static int safexcel_handle_result(struct safexcel_crypto_priv *priv, int ring, 5501eb7b403SOfer Heifetz struct crypto_async_request *async, 5511eb7b403SOfer Heifetz bool *should_complete, int *ret) 5521eb7b403SOfer Heifetz { 5531eb7b403SOfer Heifetz struct ahash_request *areq = ahash_request_cast(async); 5541eb7b403SOfer Heifetz struct safexcel_ahash_req *req = ahash_request_ctx(areq); 5551eb7b403SOfer Heifetz int err; 5561eb7b403SOfer Heifetz 55753c83e91SAntoine Tenart BUG_ON(!(priv->flags & EIP197_TRC_CACHE) && req->needs_inv); 558871df319SAntoine Ténart 5591eb7b403SOfer Heifetz if (req->needs_inv) { 5601eb7b403SOfer Heifetz req->needs_inv = false; 5611eb7b403SOfer Heifetz err = safexcel_handle_inv_result(priv, ring, async, 5621eb7b403SOfer Heifetz should_complete, ret); 5631eb7b403SOfer Heifetz } else { 5641eb7b403SOfer Heifetz err = safexcel_handle_req_result(priv, ring, async, 5651eb7b403SOfer Heifetz should_complete, ret); 5661eb7b403SOfer Heifetz } 5671eb7b403SOfer Heifetz 5681eb7b403SOfer Heifetz return err; 5691eb7b403SOfer Heifetz } 5701eb7b403SOfer Heifetz 5711b44c5a6SAntoine Ténart static int safexcel_ahash_send_inv(struct crypto_async_request *async, 5729744fec9SOfer Heifetz int ring, int *commands, int *results) 5731b44c5a6SAntoine Ténart { 5741b44c5a6SAntoine Ténart struct ahash_request *areq = ahash_request_cast(async); 5751b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 5761b44c5a6SAntoine Ténart int ret; 5771b44c5a6SAntoine Ténart 5785290ad6eSOfer Heifetz ret = safexcel_invalidate_cache(async, ctx->priv, 5799744fec9SOfer Heifetz ctx->base.ctxr_dma, ring); 5801b44c5a6SAntoine Ténart if (unlikely(ret)) 5811b44c5a6SAntoine Ténart return ret; 5821b44c5a6SAntoine Ténart 5831b44c5a6SAntoine Ténart *commands = 1; 5841b44c5a6SAntoine Ténart *results = 1; 5851b44c5a6SAntoine Ténart 5861b44c5a6SAntoine Ténart return 0; 5871b44c5a6SAntoine Ténart } 5881b44c5a6SAntoine Ténart 5891eb7b403SOfer Heifetz static int safexcel_ahash_send(struct crypto_async_request *async, 5909744fec9SOfer Heifetz int ring, int *commands, int *results) 5911eb7b403SOfer Heifetz { 5921eb7b403SOfer Heifetz struct ahash_request *areq = ahash_request_cast(async); 5931eb7b403SOfer Heifetz struct safexcel_ahash_req *req = ahash_request_ctx(areq); 5941eb7b403SOfer Heifetz int ret; 5951eb7b403SOfer Heifetz 5961eb7b403SOfer Heifetz if (req->needs_inv) 5979744fec9SOfer Heifetz ret = safexcel_ahash_send_inv(async, ring, commands, results); 5981eb7b403SOfer Heifetz else 5999744fec9SOfer Heifetz ret = safexcel_ahash_send_req(async, ring, commands, results); 6009744fec9SOfer Heifetz 6011eb7b403SOfer Heifetz return ret; 6021eb7b403SOfer Heifetz } 6031eb7b403SOfer Heifetz 6041b44c5a6SAntoine Ténart static int safexcel_ahash_exit_inv(struct crypto_tfm *tfm) 6051b44c5a6SAntoine Ténart { 6061b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 6071b44c5a6SAntoine Ténart struct safexcel_crypto_priv *priv = ctx->priv; 60861824806SAntoine Tenart EIP197_REQUEST_ON_STACK(req, ahash, EIP197_AHASH_REQ_SIZE); 6097cad2fabSAntoine Ténart struct safexcel_ahash_req *rctx = ahash_request_ctx(req); 6103e1166b9SArnd Bergmann struct safexcel_inv_result result = {}; 61186671abbSAntoine Ténart int ring = ctx->base.ring; 6121b44c5a6SAntoine Ténart 613b926213dSAntoine Tenart memset(req, 0, EIP197_AHASH_REQ_SIZE); 6141b44c5a6SAntoine Ténart 6151b44c5a6SAntoine Ténart /* create invalidation request */ 6161b44c5a6SAntoine Ténart init_completion(&result.completion); 6177cad2fabSAntoine Ténart ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, 6181b44c5a6SAntoine Ténart safexcel_inv_complete, &result); 6191b44c5a6SAntoine Ténart 6207cad2fabSAntoine Ténart ahash_request_set_tfm(req, __crypto_ahash_cast(tfm)); 6217cad2fabSAntoine Ténart ctx = crypto_tfm_ctx(req->base.tfm); 6221b44c5a6SAntoine Ténart ctx->base.exit_inv = true; 6231eb7b403SOfer Heifetz rctx->needs_inv = true; 6241b44c5a6SAntoine Ténart 62586671abbSAntoine Ténart spin_lock_bh(&priv->ring[ring].queue_lock); 6267cad2fabSAntoine Ténart crypto_enqueue_request(&priv->ring[ring].queue, &req->base); 62786671abbSAntoine Ténart spin_unlock_bh(&priv->ring[ring].queue_lock); 6281b44c5a6SAntoine Ténart 6298472e778SAntoine Ténart queue_work(priv->ring[ring].workqueue, 6308472e778SAntoine Ténart &priv->ring[ring].work_data.work); 6311b44c5a6SAntoine Ténart 632b7007dbcSAntoine Tenart wait_for_completion(&result.completion); 6331b44c5a6SAntoine Ténart 6341b44c5a6SAntoine Ténart if (result.error) { 6351b44c5a6SAntoine Ténart dev_warn(priv->dev, "hash: completion error (%d)\n", 6361b44c5a6SAntoine Ténart result.error); 6371b44c5a6SAntoine Ténart return result.error; 6381b44c5a6SAntoine Ténart } 6391b44c5a6SAntoine Ténart 6401b44c5a6SAntoine Ténart return 0; 6411b44c5a6SAntoine Ténart } 6421b44c5a6SAntoine Ténart 643cc75f5ceSAntoine Ténart /* safexcel_ahash_cache: cache data until at least one request can be sent to 644cc75f5ceSAntoine Ténart * the engine, aka. when there is at least 1 block size in the pipe. 645cc75f5ceSAntoine Ténart */ 64641abed7dSPascal van Leeuwen static int safexcel_ahash_cache(struct ahash_request *areq) 6471b44c5a6SAntoine Ténart { 6481b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 64941abed7dSPascal van Leeuwen u64 cache_len; 6501b44c5a6SAntoine Ténart 651b460edb6SAntoine Tenart /* cache_len: everything accepted by the driver but not sent yet, 652b460edb6SAntoine Tenart * tot sz handled by update() - last req sz - tot sz handled by send() 653b460edb6SAntoine Tenart */ 65441abed7dSPascal van Leeuwen cache_len = safexcel_queued_len(req); 6551b44c5a6SAntoine Ténart 6561b44c5a6SAntoine Ténart /* 6571b44c5a6SAntoine Ténart * In case there isn't enough bytes to proceed (less than a 6581b44c5a6SAntoine Ténart * block size), cache the data until we have enough. 6591b44c5a6SAntoine Ténart */ 66041abed7dSPascal van Leeuwen if (cache_len + areq->nbytes <= HASH_CACHE_SIZE) { 6611b44c5a6SAntoine Ténart sg_pcopy_to_buffer(areq->src, sg_nents(areq->src), 6621b44c5a6SAntoine Ténart req->cache + cache_len, 6631b44c5a6SAntoine Ténart areq->nbytes, 0); 66441abed7dSPascal van Leeuwen return 0; 6651b44c5a6SAntoine Ténart } 6661b44c5a6SAntoine Ténart 667dfbcc08fSAntoine Ténart /* We couldn't cache all the data */ 6681b44c5a6SAntoine Ténart return -E2BIG; 6691b44c5a6SAntoine Ténart } 6701b44c5a6SAntoine Ténart 6711b44c5a6SAntoine Ténart static int safexcel_ahash_enqueue(struct ahash_request *areq) 6721b44c5a6SAntoine Ténart { 6731b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 6741b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 6751b44c5a6SAntoine Ténart struct safexcel_crypto_priv *priv = ctx->priv; 67686671abbSAntoine Ténart int ret, ring; 6771b44c5a6SAntoine Ténart 6781eb7b403SOfer Heifetz req->needs_inv = false; 6791b44c5a6SAntoine Ténart 680c4daf4ccSOfer Heifetz if (ctx->base.ctxr) { 68153c83e91SAntoine Tenart if (priv->flags & EIP197_TRC_CACHE && !ctx->base.needs_inv && 682b98687bbSPascal van Leeuwen /* invalidate for *any* non-XCBC continuation */ 683b98687bbSPascal van Leeuwen ((req->not_first && !req->xcbcmac) || 68441abed7dSPascal van Leeuwen /* invalidate if (i)digest changed */ 68541abed7dSPascal van Leeuwen memcmp(ctx->base.ctxr->data, req->state, req->state_sz) || 68641abed7dSPascal van Leeuwen /* invalidate for HMAC finish with odigest changed */ 687a7cf8658SPascal van Leeuwen (req->finish && req->hmac && 68841abed7dSPascal van Leeuwen memcmp(ctx->base.ctxr->data + (req->state_sz>>2), 68941abed7dSPascal van Leeuwen ctx->opad, req->state_sz)))) 69041abed7dSPascal van Leeuwen /* 69141abed7dSPascal van Leeuwen * We're still setting needs_inv here, even though it is 692c4daf4ccSOfer Heifetz * cleared right away, because the needs_inv flag can be 693c4daf4ccSOfer Heifetz * set in other functions and we want to keep the same 694c4daf4ccSOfer Heifetz * logic. 695c4daf4ccSOfer Heifetz */ 69641abed7dSPascal van Leeuwen ctx->base.needs_inv = true; 6971b44c5a6SAntoine Ténart 6981eb7b403SOfer Heifetz if (ctx->base.needs_inv) { 6991eb7b403SOfer Heifetz ctx->base.needs_inv = false; 7001eb7b403SOfer Heifetz req->needs_inv = true; 7011eb7b403SOfer Heifetz } 7021b44c5a6SAntoine Ténart } else { 7031b44c5a6SAntoine Ténart ctx->base.ring = safexcel_select_ring(priv); 7041b44c5a6SAntoine Ténart ctx->base.ctxr = dma_pool_zalloc(priv->context_pool, 7051b44c5a6SAntoine Ténart EIP197_GFP_FLAGS(areq->base), 7061b44c5a6SAntoine Ténart &ctx->base.ctxr_dma); 7071b44c5a6SAntoine Ténart if (!ctx->base.ctxr) 7081b44c5a6SAntoine Ténart return -ENOMEM; 7091b44c5a6SAntoine Ténart } 710b98687bbSPascal van Leeuwen req->not_first = true; 7111b44c5a6SAntoine Ténart 71286671abbSAntoine Ténart ring = ctx->base.ring; 7131b44c5a6SAntoine Ténart 71486671abbSAntoine Ténart spin_lock_bh(&priv->ring[ring].queue_lock); 71586671abbSAntoine Ténart ret = crypto_enqueue_request(&priv->ring[ring].queue, &areq->base); 71686671abbSAntoine Ténart spin_unlock_bh(&priv->ring[ring].queue_lock); 71786671abbSAntoine Ténart 7188472e778SAntoine Ténart queue_work(priv->ring[ring].workqueue, 7198472e778SAntoine Ténart &priv->ring[ring].work_data.work); 7201b44c5a6SAntoine Ténart 7211b44c5a6SAntoine Ténart return ret; 7221b44c5a6SAntoine Ténart } 7231b44c5a6SAntoine Ténart 7241b44c5a6SAntoine Ténart static int safexcel_ahash_update(struct ahash_request *areq) 7251b44c5a6SAntoine Ténart { 7261b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 72741abed7dSPascal van Leeuwen int ret; 7281b44c5a6SAntoine Ténart 7291b44c5a6SAntoine Ténart /* If the request is 0 length, do nothing */ 7301b44c5a6SAntoine Ténart if (!areq->nbytes) 7311b44c5a6SAntoine Ténart return 0; 7321b44c5a6SAntoine Ténart 73341abed7dSPascal van Leeuwen /* Add request to the cache if it fits */ 73441abed7dSPascal van Leeuwen ret = safexcel_ahash_cache(areq); 73541abed7dSPascal van Leeuwen 73641abed7dSPascal van Leeuwen /* Update total request length */ 73731fb084cSPascal van Leeuwen req->len += areq->nbytes; 7381b44c5a6SAntoine Ténart 73941abed7dSPascal van Leeuwen /* If not all data could fit into the cache, go process the excess. 74041abed7dSPascal van Leeuwen * Also go process immediately for an HMAC IV precompute, which 74141abed7dSPascal van Leeuwen * will never be finished at all, but needs to be processed anyway. 7421b44c5a6SAntoine Ténart */ 74341abed7dSPascal van Leeuwen if ((ret && !req->finish) || req->last_req) 7441b44c5a6SAntoine Ténart return safexcel_ahash_enqueue(areq); 7451b44c5a6SAntoine Ténart 7461b44c5a6SAntoine Ténart return 0; 7471b44c5a6SAntoine Ténart } 7481b44c5a6SAntoine Ténart 7491b44c5a6SAntoine Ténart static int safexcel_ahash_final(struct ahash_request *areq) 7501b44c5a6SAntoine Ténart { 7511b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 7521b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 7531b44c5a6SAntoine Ténart 7541b44c5a6SAntoine Ténart req->finish = true; 7551b44c5a6SAntoine Ténart 75631fb084cSPascal van Leeuwen if (unlikely(!req->len && !areq->nbytes)) { 75785695b09SPascal van Leeuwen /* 75885695b09SPascal van Leeuwen * If we have an overall 0 length *hash* request: 75985695b09SPascal van Leeuwen * The HW cannot do 0 length hash, so we provide the correct 76085695b09SPascal van Leeuwen * result directly here. 76185695b09SPascal van Leeuwen */ 762293f89cfSOfer Heifetz if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_MD5) 763293f89cfSOfer Heifetz memcpy(areq->result, md5_zero_message_hash, 764293f89cfSOfer Heifetz MD5_DIGEST_SIZE); 765293f89cfSOfer Heifetz else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA1) 7661b44c5a6SAntoine Ténart memcpy(areq->result, sha1_zero_message_hash, 7671b44c5a6SAntoine Ténart SHA1_DIGEST_SIZE); 7681b44c5a6SAntoine Ténart else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA224) 7691b44c5a6SAntoine Ténart memcpy(areq->result, sha224_zero_message_hash, 7701b44c5a6SAntoine Ténart SHA224_DIGEST_SIZE); 7711b44c5a6SAntoine Ténart else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA256) 7721b44c5a6SAntoine Ténart memcpy(areq->result, sha256_zero_message_hash, 7731b44c5a6SAntoine Ténart SHA256_DIGEST_SIZE); 7749e46eafdSAntoine Tenart else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA384) 7759e46eafdSAntoine Tenart memcpy(areq->result, sha384_zero_message_hash, 7769e46eafdSAntoine Tenart SHA384_DIGEST_SIZE); 777b460edb6SAntoine Tenart else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA512) 778b460edb6SAntoine Tenart memcpy(areq->result, sha512_zero_message_hash, 779b460edb6SAntoine Tenart SHA512_DIGEST_SIZE); 7800f2bc131SPascal van Leeuwen else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SM3) { 7810f2bc131SPascal van Leeuwen if (IS_ENABLED(CONFIG_CRYPTO_SM3)) 7820f2bc131SPascal van Leeuwen memcpy(areq->result, sm3_zero_message_hash, 7830f2bc131SPascal van Leeuwen SM3_DIGEST_SIZE); 7840f2bc131SPascal van Leeuwen else 7850f2bc131SPascal van Leeuwen memcpy(areq->result, 7860f2bc131SPascal van Leeuwen EIP197_SM3_ZEROM_HASH, SM3_DIGEST_SIZE); 7870f2bc131SPascal van Leeuwen } 7881b44c5a6SAntoine Ténart 7891b44c5a6SAntoine Ténart return 0; 790a7cf8658SPascal van Leeuwen } else if (unlikely(req->digest == CONTEXT_CONTROL_DIGEST_XCM && 791a7cf8658SPascal van Leeuwen ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_MD5 && 792a7cf8658SPascal van Leeuwen req->len == sizeof(u32) && !areq->nbytes)) { 793a7cf8658SPascal van Leeuwen /* Zero length CRC32 */ 794a7cf8658SPascal van Leeuwen memcpy(areq->result, ctx->ipad, sizeof(u32)); 795a7cf8658SPascal van Leeuwen return 0; 79638f21b4bSPascal van Leeuwen } else if (unlikely(ctx->cbcmac && req->len == AES_BLOCK_SIZE && 797b98687bbSPascal van Leeuwen !areq->nbytes)) { 798b98687bbSPascal van Leeuwen /* Zero length CBC MAC */ 799b98687bbSPascal van Leeuwen memset(areq->result, 0, AES_BLOCK_SIZE); 800b98687bbSPascal van Leeuwen return 0; 80138f21b4bSPascal van Leeuwen } else if (unlikely(req->xcbcmac && req->len == AES_BLOCK_SIZE && 80238f21b4bSPascal van Leeuwen !areq->nbytes)) { 80338f21b4bSPascal van Leeuwen /* Zero length (X)CBC/CMAC */ 80438f21b4bSPascal van Leeuwen int i; 80538f21b4bSPascal van Leeuwen 80638f21b4bSPascal van Leeuwen for (i = 0; i < AES_BLOCK_SIZE / sizeof(u32); i++) 80738f21b4bSPascal van Leeuwen ((u32 *)areq->result)[i] = 80838f21b4bSPascal van Leeuwen cpu_to_be32(ctx->ipad[i + 4]); // K3 80938f21b4bSPascal van Leeuwen areq->result[0] ^= 0x80; // 10- padding 81038f21b4bSPascal van Leeuwen crypto_cipher_encrypt_one(ctx->kaes, areq->result, areq->result); 81138f21b4bSPascal van Leeuwen return 0; 81231fb084cSPascal van Leeuwen } else if (unlikely(req->hmac && 81331fb084cSPascal van Leeuwen (req->len == req->block_sz) && 81441abed7dSPascal van Leeuwen !areq->nbytes)) { 81585b36ee8SPascal van Leeuwen /* 81685b36ee8SPascal van Leeuwen * If we have an overall 0 length *HMAC* request: 81785b36ee8SPascal van Leeuwen * For HMAC, we need to finalize the inner digest 81885b36ee8SPascal van Leeuwen * and then perform the outer hash. 81985b36ee8SPascal van Leeuwen */ 82085b36ee8SPascal van Leeuwen 82185b36ee8SPascal van Leeuwen /* generate pad block in the cache */ 82285b36ee8SPascal van Leeuwen /* start with a hash block of all zeroes */ 82385b36ee8SPascal van Leeuwen memset(req->cache, 0, req->block_sz); 82485b36ee8SPascal van Leeuwen /* set the first byte to 0x80 to 'append a 1 bit' */ 82585b36ee8SPascal van Leeuwen req->cache[0] = 0x80; 82685b36ee8SPascal van Leeuwen /* add the length in bits in the last 2 bytes */ 82785b36ee8SPascal van Leeuwen if (req->len_is_le) { 82885b36ee8SPascal van Leeuwen /* Little endian length word (e.g. MD5) */ 82985b36ee8SPascal van Leeuwen req->cache[req->block_sz-8] = (req->block_sz << 3) & 83085b36ee8SPascal van Leeuwen 255; 83185b36ee8SPascal van Leeuwen req->cache[req->block_sz-7] = (req->block_sz >> 5); 83285b36ee8SPascal van Leeuwen } else { 83385b36ee8SPascal van Leeuwen /* Big endian length word (e.g. any SHA) */ 83485b36ee8SPascal van Leeuwen req->cache[req->block_sz-2] = (req->block_sz >> 5); 83585b36ee8SPascal van Leeuwen req->cache[req->block_sz-1] = (req->block_sz << 3) & 83685b36ee8SPascal van Leeuwen 255; 83785b36ee8SPascal van Leeuwen } 83885b36ee8SPascal van Leeuwen 83931fb084cSPascal van Leeuwen req->len += req->block_sz; /* plus 1 hash block */ 84085b36ee8SPascal van Leeuwen 84185b36ee8SPascal van Leeuwen /* Set special zero-length HMAC flag */ 84285b36ee8SPascal van Leeuwen req->hmac_zlen = true; 84385b36ee8SPascal van Leeuwen 84485b36ee8SPascal van Leeuwen /* Finalize HMAC */ 84585b36ee8SPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_HMAC; 84641abed7dSPascal van Leeuwen } else if (req->hmac) { 84741abed7dSPascal van Leeuwen /* Finalize HMAC */ 84841abed7dSPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_HMAC; 8491b44c5a6SAntoine Ténart } 8501b44c5a6SAntoine Ténart 8511b44c5a6SAntoine Ténart return safexcel_ahash_enqueue(areq); 8521b44c5a6SAntoine Ténart } 8531b44c5a6SAntoine Ténart 8541b44c5a6SAntoine Ténart static int safexcel_ahash_finup(struct ahash_request *areq) 8551b44c5a6SAntoine Ténart { 8561b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 8571b44c5a6SAntoine Ténart 8581b44c5a6SAntoine Ténart req->finish = true; 8591b44c5a6SAntoine Ténart 8601b44c5a6SAntoine Ténart safexcel_ahash_update(areq); 8611b44c5a6SAntoine Ténart return safexcel_ahash_final(areq); 8621b44c5a6SAntoine Ténart } 8631b44c5a6SAntoine Ténart 8641b44c5a6SAntoine Ténart static int safexcel_ahash_export(struct ahash_request *areq, void *out) 8651b44c5a6SAntoine Ténart { 8661b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 8671b44c5a6SAntoine Ténart struct safexcel_ahash_export_state *export = out; 8681b44c5a6SAntoine Ténart 86931fb084cSPascal van Leeuwen export->len = req->len; 87031fb084cSPascal van Leeuwen export->processed = req->processed; 8711b44c5a6SAntoine Ténart 872b869648cSAntoine Tenart export->digest = req->digest; 873b869648cSAntoine Tenart 8741b44c5a6SAntoine Ténart memcpy(export->state, req->state, req->state_sz); 87541abed7dSPascal van Leeuwen memcpy(export->cache, req->cache, HASH_CACHE_SIZE); 8761b44c5a6SAntoine Ténart 8771b44c5a6SAntoine Ténart return 0; 8781b44c5a6SAntoine Ténart } 8791b44c5a6SAntoine Ténart 8801b44c5a6SAntoine Ténart static int safexcel_ahash_import(struct ahash_request *areq, const void *in) 8811b44c5a6SAntoine Ténart { 8821b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 8831b44c5a6SAntoine Ténart const struct safexcel_ahash_export_state *export = in; 8841b44c5a6SAntoine Ténart int ret; 8851b44c5a6SAntoine Ténart 8861b44c5a6SAntoine Ténart ret = crypto_ahash_init(areq); 8871b44c5a6SAntoine Ténart if (ret) 8881b44c5a6SAntoine Ténart return ret; 8891b44c5a6SAntoine Ténart 89031fb084cSPascal van Leeuwen req->len = export->len; 89131fb084cSPascal van Leeuwen req->processed = export->processed; 8921b44c5a6SAntoine Ténart 893b869648cSAntoine Tenart req->digest = export->digest; 894b869648cSAntoine Tenart 89541abed7dSPascal van Leeuwen memcpy(req->cache, export->cache, HASH_CACHE_SIZE); 8961b44c5a6SAntoine Ténart memcpy(req->state, export->state, req->state_sz); 8971b44c5a6SAntoine Ténart 8981b44c5a6SAntoine Ténart return 0; 8991b44c5a6SAntoine Ténart } 9001b44c5a6SAntoine Ténart 9011b44c5a6SAntoine Ténart static int safexcel_ahash_cra_init(struct crypto_tfm *tfm) 9021b44c5a6SAntoine Ténart { 9031b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 9041b44c5a6SAntoine Ténart struct safexcel_alg_template *tmpl = 9051b44c5a6SAntoine Ténart container_of(__crypto_ahash_alg(tfm->__crt_alg), 9061b44c5a6SAntoine Ténart struct safexcel_alg_template, alg.ahash); 9071b44c5a6SAntoine Ténart 9081b44c5a6SAntoine Ténart ctx->priv = tmpl->priv; 9091eb7b403SOfer Heifetz ctx->base.send = safexcel_ahash_send; 9101eb7b403SOfer Heifetz ctx->base.handle_result = safexcel_handle_result; 9111b44c5a6SAntoine Ténart 9121b44c5a6SAntoine Ténart crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), 9131b44c5a6SAntoine Ténart sizeof(struct safexcel_ahash_req)); 9141b44c5a6SAntoine Ténart return 0; 9151b44c5a6SAntoine Ténart } 9161b44c5a6SAntoine Ténart 9171b44c5a6SAntoine Ténart static int safexcel_sha1_init(struct ahash_request *areq) 9181b44c5a6SAntoine Ténart { 9191b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 9201b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 9211b44c5a6SAntoine Ténart 9221b44c5a6SAntoine Ténart memset(req, 0, sizeof(*req)); 9231b44c5a6SAntoine Ténart 9241b44c5a6SAntoine Ténart ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1; 925b869648cSAntoine Tenart req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 9261b44c5a6SAntoine Ténart req->state_sz = SHA1_DIGEST_SIZE; 92741abed7dSPascal van Leeuwen req->block_sz = SHA1_BLOCK_SIZE; 9281b44c5a6SAntoine Ténart 9291b44c5a6SAntoine Ténart return 0; 9301b44c5a6SAntoine Ténart } 9311b44c5a6SAntoine Ténart 9321b44c5a6SAntoine Ténart static int safexcel_sha1_digest(struct ahash_request *areq) 9331b44c5a6SAntoine Ténart { 9341b44c5a6SAntoine Ténart int ret = safexcel_sha1_init(areq); 9351b44c5a6SAntoine Ténart 9361b44c5a6SAntoine Ténart if (ret) 9371b44c5a6SAntoine Ténart return ret; 9381b44c5a6SAntoine Ténart 9391b44c5a6SAntoine Ténart return safexcel_ahash_finup(areq); 9401b44c5a6SAntoine Ténart } 9411b44c5a6SAntoine Ténart 9421b44c5a6SAntoine Ténart static void safexcel_ahash_cra_exit(struct crypto_tfm *tfm) 9431b44c5a6SAntoine Ténart { 9441b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 9451b44c5a6SAntoine Ténart struct safexcel_crypto_priv *priv = ctx->priv; 9461b44c5a6SAntoine Ténart int ret; 9471b44c5a6SAntoine Ténart 9481b44c5a6SAntoine Ténart /* context not allocated, skip invalidation */ 9491b44c5a6SAntoine Ténart if (!ctx->base.ctxr) 9501b44c5a6SAntoine Ténart return; 9511b44c5a6SAntoine Ténart 95253c83e91SAntoine Tenart if (priv->flags & EIP197_TRC_CACHE) { 9531b44c5a6SAntoine Ténart ret = safexcel_ahash_exit_inv(tfm); 9541b44c5a6SAntoine Ténart if (ret) 9551b44c5a6SAntoine Ténart dev_warn(priv->dev, "hash: invalidation error %d\n", ret); 956871df319SAntoine Ténart } else { 957871df319SAntoine Ténart dma_pool_free(priv->context_pool, ctx->base.ctxr, 958871df319SAntoine Ténart ctx->base.ctxr_dma); 959871df319SAntoine Ténart } 9601b44c5a6SAntoine Ténart } 9611b44c5a6SAntoine Ténart 9621b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha1 = { 9631b44c5a6SAntoine Ténart .type = SAFEXCEL_ALG_TYPE_AHASH, 964062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA1, 9651b44c5a6SAntoine Ténart .alg.ahash = { 9661b44c5a6SAntoine Ténart .init = safexcel_sha1_init, 9671b44c5a6SAntoine Ténart .update = safexcel_ahash_update, 9681b44c5a6SAntoine Ténart .final = safexcel_ahash_final, 9691b44c5a6SAntoine Ténart .finup = safexcel_ahash_finup, 9701b44c5a6SAntoine Ténart .digest = safexcel_sha1_digest, 9711b44c5a6SAntoine Ténart .export = safexcel_ahash_export, 9721b44c5a6SAntoine Ténart .import = safexcel_ahash_import, 9731b44c5a6SAntoine Ténart .halg = { 9741b44c5a6SAntoine Ténart .digestsize = SHA1_DIGEST_SIZE, 9751b44c5a6SAntoine Ténart .statesize = sizeof(struct safexcel_ahash_export_state), 9761b44c5a6SAntoine Ténart .base = { 9771b44c5a6SAntoine Ténart .cra_name = "sha1", 9781b44c5a6SAntoine Ténart .cra_driver_name = "safexcel-sha1", 979aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 9801b44c5a6SAntoine Ténart .cra_flags = CRYPTO_ALG_ASYNC | 9811b44c5a6SAntoine Ténart CRYPTO_ALG_KERN_DRIVER_ONLY, 9821b44c5a6SAntoine Ténart .cra_blocksize = SHA1_BLOCK_SIZE, 9831b44c5a6SAntoine Ténart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 9841b44c5a6SAntoine Ténart .cra_init = safexcel_ahash_cra_init, 9851b44c5a6SAntoine Ténart .cra_exit = safexcel_ahash_cra_exit, 9861b44c5a6SAntoine Ténart .cra_module = THIS_MODULE, 9871b44c5a6SAntoine Ténart }, 9881b44c5a6SAntoine Ténart }, 9891b44c5a6SAntoine Ténart }, 9901b44c5a6SAntoine Ténart }; 9911b44c5a6SAntoine Ténart 9921b44c5a6SAntoine Ténart static int safexcel_hmac_sha1_init(struct ahash_request *areq) 9931b44c5a6SAntoine Ténart { 99441abed7dSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 995b869648cSAntoine Tenart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 9961b44c5a6SAntoine Ténart 99741abed7dSPascal van Leeuwen memset(req, 0, sizeof(*req)); 99841abed7dSPascal van Leeuwen 99941abed7dSPascal van Leeuwen /* Start from ipad precompute */ 100041abed7dSPascal van Leeuwen memcpy(req->state, ctx->ipad, SHA1_DIGEST_SIZE); 100141abed7dSPascal van Leeuwen /* Already processed the key^ipad part now! */ 100231fb084cSPascal van Leeuwen req->len = SHA1_BLOCK_SIZE; 100331fb084cSPascal van Leeuwen req->processed = SHA1_BLOCK_SIZE; 100441abed7dSPascal van Leeuwen 100541abed7dSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1; 100641abed7dSPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 100741abed7dSPascal van Leeuwen req->state_sz = SHA1_DIGEST_SIZE; 100841abed7dSPascal van Leeuwen req->block_sz = SHA1_BLOCK_SIZE; 100941abed7dSPascal van Leeuwen req->hmac = true; 101041abed7dSPascal van Leeuwen 10111b44c5a6SAntoine Ténart return 0; 10121b44c5a6SAntoine Ténart } 10131b44c5a6SAntoine Ténart 10141b44c5a6SAntoine Ténart static int safexcel_hmac_sha1_digest(struct ahash_request *areq) 10151b44c5a6SAntoine Ténart { 10161b44c5a6SAntoine Ténart int ret = safexcel_hmac_sha1_init(areq); 10171b44c5a6SAntoine Ténart 10181b44c5a6SAntoine Ténart if (ret) 10191b44c5a6SAntoine Ténart return ret; 10201b44c5a6SAntoine Ténart 10211b44c5a6SAntoine Ténart return safexcel_ahash_finup(areq); 10221b44c5a6SAntoine Ténart } 10231b44c5a6SAntoine Ténart 10241b44c5a6SAntoine Ténart struct safexcel_ahash_result { 10251b44c5a6SAntoine Ténart struct completion completion; 10261b44c5a6SAntoine Ténart int error; 10271b44c5a6SAntoine Ténart }; 10281b44c5a6SAntoine Ténart 10291b44c5a6SAntoine Ténart static void safexcel_ahash_complete(struct crypto_async_request *req, int error) 10301b44c5a6SAntoine Ténart { 10311b44c5a6SAntoine Ténart struct safexcel_ahash_result *result = req->data; 10321b44c5a6SAntoine Ténart 10331b44c5a6SAntoine Ténart if (error == -EINPROGRESS) 10341b44c5a6SAntoine Ténart return; 10351b44c5a6SAntoine Ténart 10361b44c5a6SAntoine Ténart result->error = error; 10371b44c5a6SAntoine Ténart complete(&result->completion); 10381b44c5a6SAntoine Ténart } 10391b44c5a6SAntoine Ténart 10401b44c5a6SAntoine Ténart static int safexcel_hmac_init_pad(struct ahash_request *areq, 10411b44c5a6SAntoine Ténart unsigned int blocksize, const u8 *key, 10421b44c5a6SAntoine Ténart unsigned int keylen, u8 *ipad, u8 *opad) 10431b44c5a6SAntoine Ténart { 10441b44c5a6SAntoine Ténart struct safexcel_ahash_result result; 10451b44c5a6SAntoine Ténart struct scatterlist sg; 10461b44c5a6SAntoine Ténart int ret, i; 10471b44c5a6SAntoine Ténart u8 *keydup; 10481b44c5a6SAntoine Ténart 10491b44c5a6SAntoine Ténart if (keylen <= blocksize) { 10501b44c5a6SAntoine Ténart memcpy(ipad, key, keylen); 10511b44c5a6SAntoine Ténart } else { 10521b44c5a6SAntoine Ténart keydup = kmemdup(key, keylen, GFP_KERNEL); 10531b44c5a6SAntoine Ténart if (!keydup) 10541b44c5a6SAntoine Ténart return -ENOMEM; 10551b44c5a6SAntoine Ténart 10561b44c5a6SAntoine Ténart ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_BACKLOG, 10571b44c5a6SAntoine Ténart safexcel_ahash_complete, &result); 10581b44c5a6SAntoine Ténart sg_init_one(&sg, keydup, keylen); 10591b44c5a6SAntoine Ténart ahash_request_set_crypt(areq, &sg, ipad, keylen); 10601b44c5a6SAntoine Ténart init_completion(&result.completion); 10611b44c5a6SAntoine Ténart 10621b44c5a6SAntoine Ténart ret = crypto_ahash_digest(areq); 10634dc5475aSAntoine Tenart if (ret == -EINPROGRESS || ret == -EBUSY) { 10641b44c5a6SAntoine Ténart wait_for_completion_interruptible(&result.completion); 10651b44c5a6SAntoine Ténart ret = result.error; 10661b44c5a6SAntoine Ténart } 10671b44c5a6SAntoine Ténart 10681b44c5a6SAntoine Ténart /* Avoid leaking */ 10691b44c5a6SAntoine Ténart memzero_explicit(keydup, keylen); 10701b44c5a6SAntoine Ténart kfree(keydup); 10711b44c5a6SAntoine Ténart 10721b44c5a6SAntoine Ténart if (ret) 10731b44c5a6SAntoine Ténart return ret; 10741b44c5a6SAntoine Ténart 10751b44c5a6SAntoine Ténart keylen = crypto_ahash_digestsize(crypto_ahash_reqtfm(areq)); 10761b44c5a6SAntoine Ténart } 10771b44c5a6SAntoine Ténart 10781b44c5a6SAntoine Ténart memset(ipad + keylen, 0, blocksize - keylen); 10791b44c5a6SAntoine Ténart memcpy(opad, ipad, blocksize); 10801b44c5a6SAntoine Ténart 10811b44c5a6SAntoine Ténart for (i = 0; i < blocksize; i++) { 1082aed3731eSAntoine Ténart ipad[i] ^= HMAC_IPAD_VALUE; 1083aed3731eSAntoine Ténart opad[i] ^= HMAC_OPAD_VALUE; 10841b44c5a6SAntoine Ténart } 10851b44c5a6SAntoine Ténart 10861b44c5a6SAntoine Ténart return 0; 10871b44c5a6SAntoine Ténart } 10881b44c5a6SAntoine Ténart 10891b44c5a6SAntoine Ténart static int safexcel_hmac_init_iv(struct ahash_request *areq, 10901b44c5a6SAntoine Ténart unsigned int blocksize, u8 *pad, void *state) 10911b44c5a6SAntoine Ténart { 10921b44c5a6SAntoine Ténart struct safexcel_ahash_result result; 10931b44c5a6SAntoine Ténart struct safexcel_ahash_req *req; 10941b44c5a6SAntoine Ténart struct scatterlist sg; 10951b44c5a6SAntoine Ténart int ret; 10961b44c5a6SAntoine Ténart 10971b44c5a6SAntoine Ténart ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_BACKLOG, 10981b44c5a6SAntoine Ténart safexcel_ahash_complete, &result); 10991b44c5a6SAntoine Ténart sg_init_one(&sg, pad, blocksize); 11001b44c5a6SAntoine Ténart ahash_request_set_crypt(areq, &sg, pad, blocksize); 11011b44c5a6SAntoine Ténart init_completion(&result.completion); 11021b44c5a6SAntoine Ténart 11031b44c5a6SAntoine Ténart ret = crypto_ahash_init(areq); 11041b44c5a6SAntoine Ténart if (ret) 11051b44c5a6SAntoine Ténart return ret; 11061b44c5a6SAntoine Ténart 11071b44c5a6SAntoine Ténart req = ahash_request_ctx(areq); 11081b44c5a6SAntoine Ténart req->hmac = true; 11091b44c5a6SAntoine Ténart req->last_req = true; 11101b44c5a6SAntoine Ténart 11111b44c5a6SAntoine Ténart ret = crypto_ahash_update(areq); 111212bf4142SOfer Heifetz if (ret && ret != -EINPROGRESS && ret != -EBUSY) 11131b44c5a6SAntoine Ténart return ret; 11141b44c5a6SAntoine Ténart 11151b44c5a6SAntoine Ténart wait_for_completion_interruptible(&result.completion); 11161b44c5a6SAntoine Ténart if (result.error) 11171b44c5a6SAntoine Ténart return result.error; 11181b44c5a6SAntoine Ténart 11191b44c5a6SAntoine Ténart return crypto_ahash_export(areq, state); 11201b44c5a6SAntoine Ténart } 11211b44c5a6SAntoine Ténart 1122f6beaea3SAntoine Tenart int safexcel_hmac_setkey(const char *alg, const u8 *key, unsigned int keylen, 1123f6beaea3SAntoine Tenart void *istate, void *ostate) 11241b44c5a6SAntoine Ténart { 11251b44c5a6SAntoine Ténart struct ahash_request *areq; 11261b44c5a6SAntoine Ténart struct crypto_ahash *tfm; 11271b44c5a6SAntoine Ténart unsigned int blocksize; 11281b44c5a6SAntoine Ténart u8 *ipad, *opad; 11291b44c5a6SAntoine Ténart int ret; 11301b44c5a6SAntoine Ténart 113185d7311fSEric Biggers tfm = crypto_alloc_ahash(alg, 0, 0); 11321b44c5a6SAntoine Ténart if (IS_ERR(tfm)) 11331b44c5a6SAntoine Ténart return PTR_ERR(tfm); 11341b44c5a6SAntoine Ténart 11351b44c5a6SAntoine Ténart areq = ahash_request_alloc(tfm, GFP_KERNEL); 11361b44c5a6SAntoine Ténart if (!areq) { 11371b44c5a6SAntoine Ténart ret = -ENOMEM; 11381b44c5a6SAntoine Ténart goto free_ahash; 11391b44c5a6SAntoine Ténart } 11401b44c5a6SAntoine Ténart 11411b44c5a6SAntoine Ténart crypto_ahash_clear_flags(tfm, ~0); 11421b44c5a6SAntoine Ténart blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); 11431b44c5a6SAntoine Ténart 11446396bb22SKees Cook ipad = kcalloc(2, blocksize, GFP_KERNEL); 11451b44c5a6SAntoine Ténart if (!ipad) { 11461b44c5a6SAntoine Ténart ret = -ENOMEM; 11471b44c5a6SAntoine Ténart goto free_request; 11481b44c5a6SAntoine Ténart } 11491b44c5a6SAntoine Ténart 11501b44c5a6SAntoine Ténart opad = ipad + blocksize; 11511b44c5a6SAntoine Ténart 11521b44c5a6SAntoine Ténart ret = safexcel_hmac_init_pad(areq, blocksize, key, keylen, ipad, opad); 11531b44c5a6SAntoine Ténart if (ret) 11541b44c5a6SAntoine Ténart goto free_ipad; 11551b44c5a6SAntoine Ténart 11561b44c5a6SAntoine Ténart ret = safexcel_hmac_init_iv(areq, blocksize, ipad, istate); 11571b44c5a6SAntoine Ténart if (ret) 11581b44c5a6SAntoine Ténart goto free_ipad; 11591b44c5a6SAntoine Ténart 11601b44c5a6SAntoine Ténart ret = safexcel_hmac_init_iv(areq, blocksize, opad, ostate); 11611b44c5a6SAntoine Ténart 11621b44c5a6SAntoine Ténart free_ipad: 11631b44c5a6SAntoine Ténart kfree(ipad); 11641b44c5a6SAntoine Ténart free_request: 11651b44c5a6SAntoine Ténart ahash_request_free(areq); 11661b44c5a6SAntoine Ténart free_ahash: 11671b44c5a6SAntoine Ténart crypto_free_ahash(tfm); 11681b44c5a6SAntoine Ténart 11691b44c5a6SAntoine Ténart return ret; 11701b44c5a6SAntoine Ténart } 11711b44c5a6SAntoine Ténart 117273f36ea7SAntoine Tenart static int safexcel_hmac_alg_setkey(struct crypto_ahash *tfm, const u8 *key, 117373f36ea7SAntoine Tenart unsigned int keylen, const char *alg, 117473f36ea7SAntoine Tenart unsigned int state_sz) 11751b44c5a6SAntoine Ténart { 11761b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 1177871df319SAntoine Ténart struct safexcel_crypto_priv *priv = ctx->priv; 11781b44c5a6SAntoine Ténart struct safexcel_ahash_export_state istate, ostate; 117941abed7dSPascal van Leeuwen int ret; 11801b44c5a6SAntoine Ténart 118173f36ea7SAntoine Tenart ret = safexcel_hmac_setkey(alg, key, keylen, &istate, &ostate); 11821b44c5a6SAntoine Ténart if (ret) 11831b44c5a6SAntoine Ténart return ret; 11841b44c5a6SAntoine Ténart 118541abed7dSPascal van Leeuwen if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr && 118641abed7dSPascal van Leeuwen (memcmp(ctx->ipad, istate.state, state_sz) || 118741abed7dSPascal van Leeuwen memcmp(ctx->opad, ostate.state, state_sz))) 11881b44c5a6SAntoine Ténart ctx->base.needs_inv = true; 11891b44c5a6SAntoine Ténart 119073f36ea7SAntoine Tenart memcpy(ctx->ipad, &istate.state, state_sz); 119173f36ea7SAntoine Tenart memcpy(ctx->opad, &ostate.state, state_sz); 119242ef3bedSAntoine Ténart 11931b44c5a6SAntoine Ténart return 0; 11941b44c5a6SAntoine Ténart } 11951b44c5a6SAntoine Ténart 119673f36ea7SAntoine Tenart static int safexcel_hmac_sha1_setkey(struct crypto_ahash *tfm, const u8 *key, 119773f36ea7SAntoine Tenart unsigned int keylen) 119873f36ea7SAntoine Tenart { 119973f36ea7SAntoine Tenart return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha1", 120073f36ea7SAntoine Tenart SHA1_DIGEST_SIZE); 120173f36ea7SAntoine Tenart } 120273f36ea7SAntoine Tenart 12031b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_hmac_sha1 = { 12041b44c5a6SAntoine Ténart .type = SAFEXCEL_ALG_TYPE_AHASH, 1205062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA1, 12061b44c5a6SAntoine Ténart .alg.ahash = { 12071b44c5a6SAntoine Ténart .init = safexcel_hmac_sha1_init, 12081b44c5a6SAntoine Ténart .update = safexcel_ahash_update, 12091b44c5a6SAntoine Ténart .final = safexcel_ahash_final, 12101b44c5a6SAntoine Ténart .finup = safexcel_ahash_finup, 12111b44c5a6SAntoine Ténart .digest = safexcel_hmac_sha1_digest, 12121b44c5a6SAntoine Ténart .setkey = safexcel_hmac_sha1_setkey, 12131b44c5a6SAntoine Ténart .export = safexcel_ahash_export, 12141b44c5a6SAntoine Ténart .import = safexcel_ahash_import, 12151b44c5a6SAntoine Ténart .halg = { 12161b44c5a6SAntoine Ténart .digestsize = SHA1_DIGEST_SIZE, 12171b44c5a6SAntoine Ténart .statesize = sizeof(struct safexcel_ahash_export_state), 12181b44c5a6SAntoine Ténart .base = { 12191b44c5a6SAntoine Ténart .cra_name = "hmac(sha1)", 12201b44c5a6SAntoine Ténart .cra_driver_name = "safexcel-hmac-sha1", 1221aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 12221b44c5a6SAntoine Ténart .cra_flags = CRYPTO_ALG_ASYNC | 12231b44c5a6SAntoine Ténart CRYPTO_ALG_KERN_DRIVER_ONLY, 12241b44c5a6SAntoine Ténart .cra_blocksize = SHA1_BLOCK_SIZE, 12251b44c5a6SAntoine Ténart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 12261b44c5a6SAntoine Ténart .cra_init = safexcel_ahash_cra_init, 12271b44c5a6SAntoine Ténart .cra_exit = safexcel_ahash_cra_exit, 12281b44c5a6SAntoine Ténart .cra_module = THIS_MODULE, 12291b44c5a6SAntoine Ténart }, 12301b44c5a6SAntoine Ténart }, 12311b44c5a6SAntoine Ténart }, 12321b44c5a6SAntoine Ténart }; 12331b44c5a6SAntoine Ténart 12341b44c5a6SAntoine Ténart static int safexcel_sha256_init(struct ahash_request *areq) 12351b44c5a6SAntoine Ténart { 12361b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 12371b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 12381b44c5a6SAntoine Ténart 12391b44c5a6SAntoine Ténart memset(req, 0, sizeof(*req)); 12401b44c5a6SAntoine Ténart 12411b44c5a6SAntoine Ténart ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256; 1242b869648cSAntoine Tenart req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 12431b44c5a6SAntoine Ténart req->state_sz = SHA256_DIGEST_SIZE; 124441abed7dSPascal van Leeuwen req->block_sz = SHA256_BLOCK_SIZE; 12451b44c5a6SAntoine Ténart 12461b44c5a6SAntoine Ténart return 0; 12471b44c5a6SAntoine Ténart } 12481b44c5a6SAntoine Ténart 12491b44c5a6SAntoine Ténart static int safexcel_sha256_digest(struct ahash_request *areq) 12501b44c5a6SAntoine Ténart { 12511b44c5a6SAntoine Ténart int ret = safexcel_sha256_init(areq); 12521b44c5a6SAntoine Ténart 12531b44c5a6SAntoine Ténart if (ret) 12541b44c5a6SAntoine Ténart return ret; 12551b44c5a6SAntoine Ténart 12561b44c5a6SAntoine Ténart return safexcel_ahash_finup(areq); 12571b44c5a6SAntoine Ténart } 12581b44c5a6SAntoine Ténart 12591b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha256 = { 12601b44c5a6SAntoine Ténart .type = SAFEXCEL_ALG_TYPE_AHASH, 1261062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA2_256, 12621b44c5a6SAntoine Ténart .alg.ahash = { 12631b44c5a6SAntoine Ténart .init = safexcel_sha256_init, 12641b44c5a6SAntoine Ténart .update = safexcel_ahash_update, 12651b44c5a6SAntoine Ténart .final = safexcel_ahash_final, 12661b44c5a6SAntoine Ténart .finup = safexcel_ahash_finup, 12671b44c5a6SAntoine Ténart .digest = safexcel_sha256_digest, 12681b44c5a6SAntoine Ténart .export = safexcel_ahash_export, 12691b44c5a6SAntoine Ténart .import = safexcel_ahash_import, 12701b44c5a6SAntoine Ténart .halg = { 12711b44c5a6SAntoine Ténart .digestsize = SHA256_DIGEST_SIZE, 12721b44c5a6SAntoine Ténart .statesize = sizeof(struct safexcel_ahash_export_state), 12731b44c5a6SAntoine Ténart .base = { 12741b44c5a6SAntoine Ténart .cra_name = "sha256", 12751b44c5a6SAntoine Ténart .cra_driver_name = "safexcel-sha256", 1276aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 12771b44c5a6SAntoine Ténart .cra_flags = CRYPTO_ALG_ASYNC | 12781b44c5a6SAntoine Ténart CRYPTO_ALG_KERN_DRIVER_ONLY, 12791b44c5a6SAntoine Ténart .cra_blocksize = SHA256_BLOCK_SIZE, 12801b44c5a6SAntoine Ténart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 12811b44c5a6SAntoine Ténart .cra_init = safexcel_ahash_cra_init, 12821b44c5a6SAntoine Ténart .cra_exit = safexcel_ahash_cra_exit, 12831b44c5a6SAntoine Ténart .cra_module = THIS_MODULE, 12841b44c5a6SAntoine Ténart }, 12851b44c5a6SAntoine Ténart }, 12861b44c5a6SAntoine Ténart }, 12871b44c5a6SAntoine Ténart }; 12881b44c5a6SAntoine Ténart 12891b44c5a6SAntoine Ténart static int safexcel_sha224_init(struct ahash_request *areq) 12901b44c5a6SAntoine Ténart { 12911b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 12921b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 12931b44c5a6SAntoine Ténart 12941b44c5a6SAntoine Ténart memset(req, 0, sizeof(*req)); 12951b44c5a6SAntoine Ténart 12961b44c5a6SAntoine Ténart ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224; 1297b869648cSAntoine Tenart req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 12981b44c5a6SAntoine Ténart req->state_sz = SHA256_DIGEST_SIZE; 129941abed7dSPascal van Leeuwen req->block_sz = SHA256_BLOCK_SIZE; 13001b44c5a6SAntoine Ténart 13011b44c5a6SAntoine Ténart return 0; 13021b44c5a6SAntoine Ténart } 13031b44c5a6SAntoine Ténart 13041b44c5a6SAntoine Ténart static int safexcel_sha224_digest(struct ahash_request *areq) 13051b44c5a6SAntoine Ténart { 13061b44c5a6SAntoine Ténart int ret = safexcel_sha224_init(areq); 13071b44c5a6SAntoine Ténart 13081b44c5a6SAntoine Ténart if (ret) 13091b44c5a6SAntoine Ténart return ret; 13101b44c5a6SAntoine Ténart 13111b44c5a6SAntoine Ténart return safexcel_ahash_finup(areq); 13121b44c5a6SAntoine Ténart } 13131b44c5a6SAntoine Ténart 13141b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha224 = { 13151b44c5a6SAntoine Ténart .type = SAFEXCEL_ALG_TYPE_AHASH, 1316062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA2_256, 13171b44c5a6SAntoine Ténart .alg.ahash = { 13181b44c5a6SAntoine Ténart .init = safexcel_sha224_init, 13191b44c5a6SAntoine Ténart .update = safexcel_ahash_update, 13201b44c5a6SAntoine Ténart .final = safexcel_ahash_final, 13211b44c5a6SAntoine Ténart .finup = safexcel_ahash_finup, 13221b44c5a6SAntoine Ténart .digest = safexcel_sha224_digest, 13231b44c5a6SAntoine Ténart .export = safexcel_ahash_export, 13241b44c5a6SAntoine Ténart .import = safexcel_ahash_import, 13251b44c5a6SAntoine Ténart .halg = { 13261b44c5a6SAntoine Ténart .digestsize = SHA224_DIGEST_SIZE, 13271b44c5a6SAntoine Ténart .statesize = sizeof(struct safexcel_ahash_export_state), 13281b44c5a6SAntoine Ténart .base = { 13291b44c5a6SAntoine Ténart .cra_name = "sha224", 13301b44c5a6SAntoine Ténart .cra_driver_name = "safexcel-sha224", 1331aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 13321b44c5a6SAntoine Ténart .cra_flags = CRYPTO_ALG_ASYNC | 13331b44c5a6SAntoine Ténart CRYPTO_ALG_KERN_DRIVER_ONLY, 13341b44c5a6SAntoine Ténart .cra_blocksize = SHA224_BLOCK_SIZE, 13351b44c5a6SAntoine Ténart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 13361b44c5a6SAntoine Ténart .cra_init = safexcel_ahash_cra_init, 13371b44c5a6SAntoine Ténart .cra_exit = safexcel_ahash_cra_exit, 13381b44c5a6SAntoine Ténart .cra_module = THIS_MODULE, 13391b44c5a6SAntoine Ténart }, 13401b44c5a6SAntoine Ténart }, 13411b44c5a6SAntoine Ténart }, 13421b44c5a6SAntoine Ténart }; 134373f36ea7SAntoine Tenart 13443ad618d8SAntoine Tenart static int safexcel_hmac_sha224_setkey(struct crypto_ahash *tfm, const u8 *key, 13453ad618d8SAntoine Tenart unsigned int keylen) 13463ad618d8SAntoine Tenart { 13473ad618d8SAntoine Tenart return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha224", 13483ad618d8SAntoine Tenart SHA256_DIGEST_SIZE); 13493ad618d8SAntoine Tenart } 13503ad618d8SAntoine Tenart 13513ad618d8SAntoine Tenart static int safexcel_hmac_sha224_init(struct ahash_request *areq) 13523ad618d8SAntoine Tenart { 135341abed7dSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 13543ad618d8SAntoine Tenart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 13553ad618d8SAntoine Tenart 135641abed7dSPascal van Leeuwen memset(req, 0, sizeof(*req)); 135741abed7dSPascal van Leeuwen 135841abed7dSPascal van Leeuwen /* Start from ipad precompute */ 135941abed7dSPascal van Leeuwen memcpy(req->state, ctx->ipad, SHA256_DIGEST_SIZE); 136041abed7dSPascal van Leeuwen /* Already processed the key^ipad part now! */ 136131fb084cSPascal van Leeuwen req->len = SHA256_BLOCK_SIZE; 136231fb084cSPascal van Leeuwen req->processed = SHA256_BLOCK_SIZE; 136341abed7dSPascal van Leeuwen 136441abed7dSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224; 136541abed7dSPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 136641abed7dSPascal van Leeuwen req->state_sz = SHA256_DIGEST_SIZE; 136741abed7dSPascal van Leeuwen req->block_sz = SHA256_BLOCK_SIZE; 136841abed7dSPascal van Leeuwen req->hmac = true; 136941abed7dSPascal van Leeuwen 13703ad618d8SAntoine Tenart return 0; 13713ad618d8SAntoine Tenart } 13723ad618d8SAntoine Tenart 13733ad618d8SAntoine Tenart static int safexcel_hmac_sha224_digest(struct ahash_request *areq) 13743ad618d8SAntoine Tenart { 13753ad618d8SAntoine Tenart int ret = safexcel_hmac_sha224_init(areq); 13763ad618d8SAntoine Tenart 13773ad618d8SAntoine Tenart if (ret) 13783ad618d8SAntoine Tenart return ret; 13793ad618d8SAntoine Tenart 13803ad618d8SAntoine Tenart return safexcel_ahash_finup(areq); 13813ad618d8SAntoine Tenart } 13823ad618d8SAntoine Tenart 13833ad618d8SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha224 = { 13843ad618d8SAntoine Tenart .type = SAFEXCEL_ALG_TYPE_AHASH, 1385062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA2_256, 13863ad618d8SAntoine Tenart .alg.ahash = { 13873ad618d8SAntoine Tenart .init = safexcel_hmac_sha224_init, 13883ad618d8SAntoine Tenart .update = safexcel_ahash_update, 13893ad618d8SAntoine Tenart .final = safexcel_ahash_final, 13903ad618d8SAntoine Tenart .finup = safexcel_ahash_finup, 13913ad618d8SAntoine Tenart .digest = safexcel_hmac_sha224_digest, 13923ad618d8SAntoine Tenart .setkey = safexcel_hmac_sha224_setkey, 13933ad618d8SAntoine Tenart .export = safexcel_ahash_export, 13943ad618d8SAntoine Tenart .import = safexcel_ahash_import, 13953ad618d8SAntoine Tenart .halg = { 13963ad618d8SAntoine Tenart .digestsize = SHA224_DIGEST_SIZE, 13973ad618d8SAntoine Tenart .statesize = sizeof(struct safexcel_ahash_export_state), 13983ad618d8SAntoine Tenart .base = { 13993ad618d8SAntoine Tenart .cra_name = "hmac(sha224)", 14003ad618d8SAntoine Tenart .cra_driver_name = "safexcel-hmac-sha224", 1401aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 14023ad618d8SAntoine Tenart .cra_flags = CRYPTO_ALG_ASYNC | 14033ad618d8SAntoine Tenart CRYPTO_ALG_KERN_DRIVER_ONLY, 14043ad618d8SAntoine Tenart .cra_blocksize = SHA224_BLOCK_SIZE, 14053ad618d8SAntoine Tenart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 14063ad618d8SAntoine Tenart .cra_init = safexcel_ahash_cra_init, 14073ad618d8SAntoine Tenart .cra_exit = safexcel_ahash_cra_exit, 14083ad618d8SAntoine Tenart .cra_module = THIS_MODULE, 14093ad618d8SAntoine Tenart }, 14103ad618d8SAntoine Tenart }, 14113ad618d8SAntoine Tenart }, 14123ad618d8SAntoine Tenart }; 14133ad618d8SAntoine Tenart 141473f36ea7SAntoine Tenart static int safexcel_hmac_sha256_setkey(struct crypto_ahash *tfm, const u8 *key, 141573f36ea7SAntoine Tenart unsigned int keylen) 141673f36ea7SAntoine Tenart { 141773f36ea7SAntoine Tenart return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha256", 141873f36ea7SAntoine Tenart SHA256_DIGEST_SIZE); 141973f36ea7SAntoine Tenart } 142073f36ea7SAntoine Tenart 142173f36ea7SAntoine Tenart static int safexcel_hmac_sha256_init(struct ahash_request *areq) 142273f36ea7SAntoine Tenart { 142341abed7dSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 142473f36ea7SAntoine Tenart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 142573f36ea7SAntoine Tenart 142641abed7dSPascal van Leeuwen memset(req, 0, sizeof(*req)); 142741abed7dSPascal van Leeuwen 142841abed7dSPascal van Leeuwen /* Start from ipad precompute */ 142941abed7dSPascal van Leeuwen memcpy(req->state, ctx->ipad, SHA256_DIGEST_SIZE); 143041abed7dSPascal van Leeuwen /* Already processed the key^ipad part now! */ 143131fb084cSPascal van Leeuwen req->len = SHA256_BLOCK_SIZE; 143231fb084cSPascal van Leeuwen req->processed = SHA256_BLOCK_SIZE; 143341abed7dSPascal van Leeuwen 143441abed7dSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256; 143541abed7dSPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 143641abed7dSPascal van Leeuwen req->state_sz = SHA256_DIGEST_SIZE; 143741abed7dSPascal van Leeuwen req->block_sz = SHA256_BLOCK_SIZE; 143841abed7dSPascal van Leeuwen req->hmac = true; 143941abed7dSPascal van Leeuwen 144073f36ea7SAntoine Tenart return 0; 144173f36ea7SAntoine Tenart } 144273f36ea7SAntoine Tenart 144373f36ea7SAntoine Tenart static int safexcel_hmac_sha256_digest(struct ahash_request *areq) 144473f36ea7SAntoine Tenart { 144573f36ea7SAntoine Tenart int ret = safexcel_hmac_sha256_init(areq); 144673f36ea7SAntoine Tenart 144773f36ea7SAntoine Tenart if (ret) 144873f36ea7SAntoine Tenart return ret; 144973f36ea7SAntoine Tenart 145073f36ea7SAntoine Tenart return safexcel_ahash_finup(areq); 145173f36ea7SAntoine Tenart } 145273f36ea7SAntoine Tenart 145373f36ea7SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha256 = { 145473f36ea7SAntoine Tenart .type = SAFEXCEL_ALG_TYPE_AHASH, 1455062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA2_256, 145673f36ea7SAntoine Tenart .alg.ahash = { 145773f36ea7SAntoine Tenart .init = safexcel_hmac_sha256_init, 145873f36ea7SAntoine Tenart .update = safexcel_ahash_update, 145973f36ea7SAntoine Tenart .final = safexcel_ahash_final, 146073f36ea7SAntoine Tenart .finup = safexcel_ahash_finup, 146173f36ea7SAntoine Tenart .digest = safexcel_hmac_sha256_digest, 146273f36ea7SAntoine Tenart .setkey = safexcel_hmac_sha256_setkey, 146373f36ea7SAntoine Tenart .export = safexcel_ahash_export, 146473f36ea7SAntoine Tenart .import = safexcel_ahash_import, 146573f36ea7SAntoine Tenart .halg = { 146673f36ea7SAntoine Tenart .digestsize = SHA256_DIGEST_SIZE, 146773f36ea7SAntoine Tenart .statesize = sizeof(struct safexcel_ahash_export_state), 146873f36ea7SAntoine Tenart .base = { 146973f36ea7SAntoine Tenart .cra_name = "hmac(sha256)", 147073f36ea7SAntoine Tenart .cra_driver_name = "safexcel-hmac-sha256", 1471aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 147273f36ea7SAntoine Tenart .cra_flags = CRYPTO_ALG_ASYNC | 147373f36ea7SAntoine Tenart CRYPTO_ALG_KERN_DRIVER_ONLY, 147473f36ea7SAntoine Tenart .cra_blocksize = SHA256_BLOCK_SIZE, 147573f36ea7SAntoine Tenart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 147673f36ea7SAntoine Tenart .cra_init = safexcel_ahash_cra_init, 147773f36ea7SAntoine Tenart .cra_exit = safexcel_ahash_cra_exit, 147873f36ea7SAntoine Tenart .cra_module = THIS_MODULE, 147973f36ea7SAntoine Tenart }, 148073f36ea7SAntoine Tenart }, 148173f36ea7SAntoine Tenart }, 148273f36ea7SAntoine Tenart }; 1483b460edb6SAntoine Tenart 1484b460edb6SAntoine Tenart static int safexcel_sha512_init(struct ahash_request *areq) 1485b460edb6SAntoine Tenart { 1486b460edb6SAntoine Tenart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 1487b460edb6SAntoine Tenart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 1488b460edb6SAntoine Tenart 1489b460edb6SAntoine Tenart memset(req, 0, sizeof(*req)); 1490b460edb6SAntoine Tenart 1491b460edb6SAntoine Tenart ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512; 1492b460edb6SAntoine Tenart req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 1493b460edb6SAntoine Tenart req->state_sz = SHA512_DIGEST_SIZE; 149441abed7dSPascal van Leeuwen req->block_sz = SHA512_BLOCK_SIZE; 1495b460edb6SAntoine Tenart 1496b460edb6SAntoine Tenart return 0; 1497b460edb6SAntoine Tenart } 1498b460edb6SAntoine Tenart 1499b460edb6SAntoine Tenart static int safexcel_sha512_digest(struct ahash_request *areq) 1500b460edb6SAntoine Tenart { 1501b460edb6SAntoine Tenart int ret = safexcel_sha512_init(areq); 1502b460edb6SAntoine Tenart 1503b460edb6SAntoine Tenart if (ret) 1504b460edb6SAntoine Tenart return ret; 1505b460edb6SAntoine Tenart 1506b460edb6SAntoine Tenart return safexcel_ahash_finup(areq); 1507b460edb6SAntoine Tenart } 1508b460edb6SAntoine Tenart 1509b460edb6SAntoine Tenart struct safexcel_alg_template safexcel_alg_sha512 = { 1510b460edb6SAntoine Tenart .type = SAFEXCEL_ALG_TYPE_AHASH, 1511062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA2_512, 1512b460edb6SAntoine Tenart .alg.ahash = { 1513b460edb6SAntoine Tenart .init = safexcel_sha512_init, 1514b460edb6SAntoine Tenart .update = safexcel_ahash_update, 1515b460edb6SAntoine Tenart .final = safexcel_ahash_final, 1516b460edb6SAntoine Tenart .finup = safexcel_ahash_finup, 1517b460edb6SAntoine Tenart .digest = safexcel_sha512_digest, 1518b460edb6SAntoine Tenart .export = safexcel_ahash_export, 1519b460edb6SAntoine Tenart .import = safexcel_ahash_import, 1520b460edb6SAntoine Tenart .halg = { 1521b460edb6SAntoine Tenart .digestsize = SHA512_DIGEST_SIZE, 1522b460edb6SAntoine Tenart .statesize = sizeof(struct safexcel_ahash_export_state), 1523b460edb6SAntoine Tenart .base = { 1524b460edb6SAntoine Tenart .cra_name = "sha512", 1525b460edb6SAntoine Tenart .cra_driver_name = "safexcel-sha512", 1526aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 1527b460edb6SAntoine Tenart .cra_flags = CRYPTO_ALG_ASYNC | 1528b460edb6SAntoine Tenart CRYPTO_ALG_KERN_DRIVER_ONLY, 1529b460edb6SAntoine Tenart .cra_blocksize = SHA512_BLOCK_SIZE, 1530b460edb6SAntoine Tenart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 1531b460edb6SAntoine Tenart .cra_init = safexcel_ahash_cra_init, 1532b460edb6SAntoine Tenart .cra_exit = safexcel_ahash_cra_exit, 1533b460edb6SAntoine Tenart .cra_module = THIS_MODULE, 1534b460edb6SAntoine Tenart }, 1535b460edb6SAntoine Tenart }, 1536b460edb6SAntoine Tenart }, 1537b460edb6SAntoine Tenart }; 15380de54fb1SAntoine Tenart 15399e46eafdSAntoine Tenart static int safexcel_sha384_init(struct ahash_request *areq) 15409e46eafdSAntoine Tenart { 15419e46eafdSAntoine Tenart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 15429e46eafdSAntoine Tenart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 15439e46eafdSAntoine Tenart 15449e46eafdSAntoine Tenart memset(req, 0, sizeof(*req)); 15459e46eafdSAntoine Tenart 15469e46eafdSAntoine Tenart ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384; 15479e46eafdSAntoine Tenart req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 15489e46eafdSAntoine Tenart req->state_sz = SHA512_DIGEST_SIZE; 154941abed7dSPascal van Leeuwen req->block_sz = SHA512_BLOCK_SIZE; 15509e46eafdSAntoine Tenart 15519e46eafdSAntoine Tenart return 0; 15529e46eafdSAntoine Tenart } 15539e46eafdSAntoine Tenart 15549e46eafdSAntoine Tenart static int safexcel_sha384_digest(struct ahash_request *areq) 15559e46eafdSAntoine Tenart { 15569e46eafdSAntoine Tenart int ret = safexcel_sha384_init(areq); 15579e46eafdSAntoine Tenart 15589e46eafdSAntoine Tenart if (ret) 15599e46eafdSAntoine Tenart return ret; 15609e46eafdSAntoine Tenart 15619e46eafdSAntoine Tenart return safexcel_ahash_finup(areq); 15629e46eafdSAntoine Tenart } 15639e46eafdSAntoine Tenart 15649e46eafdSAntoine Tenart struct safexcel_alg_template safexcel_alg_sha384 = { 15659e46eafdSAntoine Tenart .type = SAFEXCEL_ALG_TYPE_AHASH, 1566062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA2_512, 15679e46eafdSAntoine Tenart .alg.ahash = { 15689e46eafdSAntoine Tenart .init = safexcel_sha384_init, 15699e46eafdSAntoine Tenart .update = safexcel_ahash_update, 15709e46eafdSAntoine Tenart .final = safexcel_ahash_final, 15719e46eafdSAntoine Tenart .finup = safexcel_ahash_finup, 15729e46eafdSAntoine Tenart .digest = safexcel_sha384_digest, 15739e46eafdSAntoine Tenart .export = safexcel_ahash_export, 15749e46eafdSAntoine Tenart .import = safexcel_ahash_import, 15759e46eafdSAntoine Tenart .halg = { 15769e46eafdSAntoine Tenart .digestsize = SHA384_DIGEST_SIZE, 15779e46eafdSAntoine Tenart .statesize = sizeof(struct safexcel_ahash_export_state), 15789e46eafdSAntoine Tenart .base = { 15799e46eafdSAntoine Tenart .cra_name = "sha384", 15809e46eafdSAntoine Tenart .cra_driver_name = "safexcel-sha384", 1581aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 15829e46eafdSAntoine Tenart .cra_flags = CRYPTO_ALG_ASYNC | 15839e46eafdSAntoine Tenart CRYPTO_ALG_KERN_DRIVER_ONLY, 15849e46eafdSAntoine Tenart .cra_blocksize = SHA384_BLOCK_SIZE, 15859e46eafdSAntoine Tenart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 15869e46eafdSAntoine Tenart .cra_init = safexcel_ahash_cra_init, 15879e46eafdSAntoine Tenart .cra_exit = safexcel_ahash_cra_exit, 15889e46eafdSAntoine Tenart .cra_module = THIS_MODULE, 15899e46eafdSAntoine Tenart }, 15909e46eafdSAntoine Tenart }, 15919e46eafdSAntoine Tenart }, 15929e46eafdSAntoine Tenart }; 15939e46eafdSAntoine Tenart 15940de54fb1SAntoine Tenart static int safexcel_hmac_sha512_setkey(struct crypto_ahash *tfm, const u8 *key, 15950de54fb1SAntoine Tenart unsigned int keylen) 15960de54fb1SAntoine Tenart { 15970de54fb1SAntoine Tenart return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha512", 15980de54fb1SAntoine Tenart SHA512_DIGEST_SIZE); 15990de54fb1SAntoine Tenart } 16000de54fb1SAntoine Tenart 16010de54fb1SAntoine Tenart static int safexcel_hmac_sha512_init(struct ahash_request *areq) 16020de54fb1SAntoine Tenart { 160341abed7dSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 16040de54fb1SAntoine Tenart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 16050de54fb1SAntoine Tenart 160641abed7dSPascal van Leeuwen memset(req, 0, sizeof(*req)); 160741abed7dSPascal van Leeuwen 160841abed7dSPascal van Leeuwen /* Start from ipad precompute */ 160941abed7dSPascal van Leeuwen memcpy(req->state, ctx->ipad, SHA512_DIGEST_SIZE); 161041abed7dSPascal van Leeuwen /* Already processed the key^ipad part now! */ 161131fb084cSPascal van Leeuwen req->len = SHA512_BLOCK_SIZE; 161231fb084cSPascal van Leeuwen req->processed = SHA512_BLOCK_SIZE; 161341abed7dSPascal van Leeuwen 161441abed7dSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512; 161541abed7dSPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 161641abed7dSPascal van Leeuwen req->state_sz = SHA512_DIGEST_SIZE; 161741abed7dSPascal van Leeuwen req->block_sz = SHA512_BLOCK_SIZE; 161841abed7dSPascal van Leeuwen req->hmac = true; 161941abed7dSPascal van Leeuwen 16200de54fb1SAntoine Tenart return 0; 16210de54fb1SAntoine Tenart } 16220de54fb1SAntoine Tenart 16230de54fb1SAntoine Tenart static int safexcel_hmac_sha512_digest(struct ahash_request *areq) 16240de54fb1SAntoine Tenart { 16250de54fb1SAntoine Tenart int ret = safexcel_hmac_sha512_init(areq); 16260de54fb1SAntoine Tenart 16270de54fb1SAntoine Tenart if (ret) 16280de54fb1SAntoine Tenart return ret; 16290de54fb1SAntoine Tenart 16300de54fb1SAntoine Tenart return safexcel_ahash_finup(areq); 16310de54fb1SAntoine Tenart } 16320de54fb1SAntoine Tenart 16330de54fb1SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha512 = { 16340de54fb1SAntoine Tenart .type = SAFEXCEL_ALG_TYPE_AHASH, 1635062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA2_512, 16360de54fb1SAntoine Tenart .alg.ahash = { 16370de54fb1SAntoine Tenart .init = safexcel_hmac_sha512_init, 16380de54fb1SAntoine Tenart .update = safexcel_ahash_update, 16390de54fb1SAntoine Tenart .final = safexcel_ahash_final, 16400de54fb1SAntoine Tenart .finup = safexcel_ahash_finup, 16410de54fb1SAntoine Tenart .digest = safexcel_hmac_sha512_digest, 16420de54fb1SAntoine Tenart .setkey = safexcel_hmac_sha512_setkey, 16430de54fb1SAntoine Tenart .export = safexcel_ahash_export, 16440de54fb1SAntoine Tenart .import = safexcel_ahash_import, 16450de54fb1SAntoine Tenart .halg = { 16460de54fb1SAntoine Tenart .digestsize = SHA512_DIGEST_SIZE, 16470de54fb1SAntoine Tenart .statesize = sizeof(struct safexcel_ahash_export_state), 16480de54fb1SAntoine Tenart .base = { 16490de54fb1SAntoine Tenart .cra_name = "hmac(sha512)", 16500de54fb1SAntoine Tenart .cra_driver_name = "safexcel-hmac-sha512", 1651aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 16520de54fb1SAntoine Tenart .cra_flags = CRYPTO_ALG_ASYNC | 16530de54fb1SAntoine Tenart CRYPTO_ALG_KERN_DRIVER_ONLY, 16540de54fb1SAntoine Tenart .cra_blocksize = SHA512_BLOCK_SIZE, 16550de54fb1SAntoine Tenart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 16560de54fb1SAntoine Tenart .cra_init = safexcel_ahash_cra_init, 16570de54fb1SAntoine Tenart .cra_exit = safexcel_ahash_cra_exit, 16580de54fb1SAntoine Tenart .cra_module = THIS_MODULE, 16590de54fb1SAntoine Tenart }, 16600de54fb1SAntoine Tenart }, 16610de54fb1SAntoine Tenart }, 16620de54fb1SAntoine Tenart }; 16631f5d5d98SAntoine Tenart 16641f5d5d98SAntoine Tenart static int safexcel_hmac_sha384_setkey(struct crypto_ahash *tfm, const u8 *key, 16651f5d5d98SAntoine Tenart unsigned int keylen) 16661f5d5d98SAntoine Tenart { 16671f5d5d98SAntoine Tenart return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha384", 16681f5d5d98SAntoine Tenart SHA512_DIGEST_SIZE); 16691f5d5d98SAntoine Tenart } 16701f5d5d98SAntoine Tenart 16711f5d5d98SAntoine Tenart static int safexcel_hmac_sha384_init(struct ahash_request *areq) 16721f5d5d98SAntoine Tenart { 167341abed7dSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 16741f5d5d98SAntoine Tenart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 16751f5d5d98SAntoine Tenart 167641abed7dSPascal van Leeuwen memset(req, 0, sizeof(*req)); 167741abed7dSPascal van Leeuwen 167841abed7dSPascal van Leeuwen /* Start from ipad precompute */ 167941abed7dSPascal van Leeuwen memcpy(req->state, ctx->ipad, SHA512_DIGEST_SIZE); 168041abed7dSPascal van Leeuwen /* Already processed the key^ipad part now! */ 168131fb084cSPascal van Leeuwen req->len = SHA512_BLOCK_SIZE; 168231fb084cSPascal van Leeuwen req->processed = SHA512_BLOCK_SIZE; 168341abed7dSPascal van Leeuwen 168441abed7dSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384; 168541abed7dSPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 168641abed7dSPascal van Leeuwen req->state_sz = SHA512_DIGEST_SIZE; 168741abed7dSPascal van Leeuwen req->block_sz = SHA512_BLOCK_SIZE; 168841abed7dSPascal van Leeuwen req->hmac = true; 168941abed7dSPascal van Leeuwen 16901f5d5d98SAntoine Tenart return 0; 16911f5d5d98SAntoine Tenart } 16921f5d5d98SAntoine Tenart 16931f5d5d98SAntoine Tenart static int safexcel_hmac_sha384_digest(struct ahash_request *areq) 16941f5d5d98SAntoine Tenart { 16951f5d5d98SAntoine Tenart int ret = safexcel_hmac_sha384_init(areq); 16961f5d5d98SAntoine Tenart 16971f5d5d98SAntoine Tenart if (ret) 16981f5d5d98SAntoine Tenart return ret; 16991f5d5d98SAntoine Tenart 17001f5d5d98SAntoine Tenart return safexcel_ahash_finup(areq); 17011f5d5d98SAntoine Tenart } 17021f5d5d98SAntoine Tenart 17031f5d5d98SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha384 = { 17041f5d5d98SAntoine Tenart .type = SAFEXCEL_ALG_TYPE_AHASH, 1705062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA2_512, 17061f5d5d98SAntoine Tenart .alg.ahash = { 17071f5d5d98SAntoine Tenart .init = safexcel_hmac_sha384_init, 17081f5d5d98SAntoine Tenart .update = safexcel_ahash_update, 17091f5d5d98SAntoine Tenart .final = safexcel_ahash_final, 17101f5d5d98SAntoine Tenart .finup = safexcel_ahash_finup, 17111f5d5d98SAntoine Tenart .digest = safexcel_hmac_sha384_digest, 17121f5d5d98SAntoine Tenart .setkey = safexcel_hmac_sha384_setkey, 17131f5d5d98SAntoine Tenart .export = safexcel_ahash_export, 17141f5d5d98SAntoine Tenart .import = safexcel_ahash_import, 17151f5d5d98SAntoine Tenart .halg = { 17161f5d5d98SAntoine Tenart .digestsize = SHA384_DIGEST_SIZE, 17171f5d5d98SAntoine Tenart .statesize = sizeof(struct safexcel_ahash_export_state), 17181f5d5d98SAntoine Tenart .base = { 17191f5d5d98SAntoine Tenart .cra_name = "hmac(sha384)", 17201f5d5d98SAntoine Tenart .cra_driver_name = "safexcel-hmac-sha384", 1721aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 17221f5d5d98SAntoine Tenart .cra_flags = CRYPTO_ALG_ASYNC | 17231f5d5d98SAntoine Tenart CRYPTO_ALG_KERN_DRIVER_ONLY, 17241f5d5d98SAntoine Tenart .cra_blocksize = SHA384_BLOCK_SIZE, 17251f5d5d98SAntoine Tenart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 17261f5d5d98SAntoine Tenart .cra_init = safexcel_ahash_cra_init, 17271f5d5d98SAntoine Tenart .cra_exit = safexcel_ahash_cra_exit, 17281f5d5d98SAntoine Tenart .cra_module = THIS_MODULE, 17291f5d5d98SAntoine Tenart }, 17301f5d5d98SAntoine Tenart }, 17311f5d5d98SAntoine Tenart }, 17321f5d5d98SAntoine Tenart }; 1733293f89cfSOfer Heifetz 1734293f89cfSOfer Heifetz static int safexcel_md5_init(struct ahash_request *areq) 1735293f89cfSOfer Heifetz { 1736293f89cfSOfer Heifetz struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 1737293f89cfSOfer Heifetz struct safexcel_ahash_req *req = ahash_request_ctx(areq); 1738293f89cfSOfer Heifetz 1739293f89cfSOfer Heifetz memset(req, 0, sizeof(*req)); 1740293f89cfSOfer Heifetz 1741293f89cfSOfer Heifetz ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_MD5; 1742293f89cfSOfer Heifetz req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 1743293f89cfSOfer Heifetz req->state_sz = MD5_DIGEST_SIZE; 174441abed7dSPascal van Leeuwen req->block_sz = MD5_HMAC_BLOCK_SIZE; 1745293f89cfSOfer Heifetz 1746293f89cfSOfer Heifetz return 0; 1747293f89cfSOfer Heifetz } 1748293f89cfSOfer Heifetz 1749293f89cfSOfer Heifetz static int safexcel_md5_digest(struct ahash_request *areq) 1750293f89cfSOfer Heifetz { 1751293f89cfSOfer Heifetz int ret = safexcel_md5_init(areq); 1752293f89cfSOfer Heifetz 1753293f89cfSOfer Heifetz if (ret) 1754293f89cfSOfer Heifetz return ret; 1755293f89cfSOfer Heifetz 1756293f89cfSOfer Heifetz return safexcel_ahash_finup(areq); 1757293f89cfSOfer Heifetz } 1758293f89cfSOfer Heifetz 1759293f89cfSOfer Heifetz struct safexcel_alg_template safexcel_alg_md5 = { 1760293f89cfSOfer Heifetz .type = SAFEXCEL_ALG_TYPE_AHASH, 1761062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_MD5, 1762293f89cfSOfer Heifetz .alg.ahash = { 1763293f89cfSOfer Heifetz .init = safexcel_md5_init, 1764293f89cfSOfer Heifetz .update = safexcel_ahash_update, 1765293f89cfSOfer Heifetz .final = safexcel_ahash_final, 1766293f89cfSOfer Heifetz .finup = safexcel_ahash_finup, 1767293f89cfSOfer Heifetz .digest = safexcel_md5_digest, 1768293f89cfSOfer Heifetz .export = safexcel_ahash_export, 1769293f89cfSOfer Heifetz .import = safexcel_ahash_import, 1770293f89cfSOfer Heifetz .halg = { 1771293f89cfSOfer Heifetz .digestsize = MD5_DIGEST_SIZE, 1772293f89cfSOfer Heifetz .statesize = sizeof(struct safexcel_ahash_export_state), 1773293f89cfSOfer Heifetz .base = { 1774293f89cfSOfer Heifetz .cra_name = "md5", 1775293f89cfSOfer Heifetz .cra_driver_name = "safexcel-md5", 1776aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 1777293f89cfSOfer Heifetz .cra_flags = CRYPTO_ALG_ASYNC | 1778293f89cfSOfer Heifetz CRYPTO_ALG_KERN_DRIVER_ONLY, 1779293f89cfSOfer Heifetz .cra_blocksize = MD5_HMAC_BLOCK_SIZE, 1780293f89cfSOfer Heifetz .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 1781293f89cfSOfer Heifetz .cra_init = safexcel_ahash_cra_init, 1782293f89cfSOfer Heifetz .cra_exit = safexcel_ahash_cra_exit, 1783293f89cfSOfer Heifetz .cra_module = THIS_MODULE, 1784293f89cfSOfer Heifetz }, 1785293f89cfSOfer Heifetz }, 1786293f89cfSOfer Heifetz }, 1787293f89cfSOfer Heifetz }; 1788b471e4b9SOfer Heifetz 1789b471e4b9SOfer Heifetz static int safexcel_hmac_md5_init(struct ahash_request *areq) 1790b471e4b9SOfer Heifetz { 179141abed7dSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 1792b471e4b9SOfer Heifetz struct safexcel_ahash_req *req = ahash_request_ctx(areq); 1793b471e4b9SOfer Heifetz 179441abed7dSPascal van Leeuwen memset(req, 0, sizeof(*req)); 179541abed7dSPascal van Leeuwen 179641abed7dSPascal van Leeuwen /* Start from ipad precompute */ 179741abed7dSPascal van Leeuwen memcpy(req->state, ctx->ipad, MD5_DIGEST_SIZE); 179841abed7dSPascal van Leeuwen /* Already processed the key^ipad part now! */ 179931fb084cSPascal van Leeuwen req->len = MD5_HMAC_BLOCK_SIZE; 180031fb084cSPascal van Leeuwen req->processed = MD5_HMAC_BLOCK_SIZE; 180141abed7dSPascal van Leeuwen 180241abed7dSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_MD5; 180341abed7dSPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 180441abed7dSPascal van Leeuwen req->state_sz = MD5_DIGEST_SIZE; 180541abed7dSPascal van Leeuwen req->block_sz = MD5_HMAC_BLOCK_SIZE; 180685b36ee8SPascal van Leeuwen req->len_is_le = true; /* MD5 is little endian! ... */ 180741abed7dSPascal van Leeuwen req->hmac = true; 180841abed7dSPascal van Leeuwen 1809b471e4b9SOfer Heifetz return 0; 1810b471e4b9SOfer Heifetz } 1811b471e4b9SOfer Heifetz 1812b471e4b9SOfer Heifetz static int safexcel_hmac_md5_setkey(struct crypto_ahash *tfm, const u8 *key, 1813b471e4b9SOfer Heifetz unsigned int keylen) 1814b471e4b9SOfer Heifetz { 1815b471e4b9SOfer Heifetz return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-md5", 1816b471e4b9SOfer Heifetz MD5_DIGEST_SIZE); 1817b471e4b9SOfer Heifetz } 1818b471e4b9SOfer Heifetz 1819b471e4b9SOfer Heifetz static int safexcel_hmac_md5_digest(struct ahash_request *areq) 1820b471e4b9SOfer Heifetz { 1821b471e4b9SOfer Heifetz int ret = safexcel_hmac_md5_init(areq); 1822b471e4b9SOfer Heifetz 1823b471e4b9SOfer Heifetz if (ret) 1824b471e4b9SOfer Heifetz return ret; 1825b471e4b9SOfer Heifetz 1826b471e4b9SOfer Heifetz return safexcel_ahash_finup(areq); 1827b471e4b9SOfer Heifetz } 1828b471e4b9SOfer Heifetz 1829b471e4b9SOfer Heifetz struct safexcel_alg_template safexcel_alg_hmac_md5 = { 1830b471e4b9SOfer Heifetz .type = SAFEXCEL_ALG_TYPE_AHASH, 1831062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_MD5, 1832b471e4b9SOfer Heifetz .alg.ahash = { 1833b471e4b9SOfer Heifetz .init = safexcel_hmac_md5_init, 1834b471e4b9SOfer Heifetz .update = safexcel_ahash_update, 1835b471e4b9SOfer Heifetz .final = safexcel_ahash_final, 1836b471e4b9SOfer Heifetz .finup = safexcel_ahash_finup, 1837b471e4b9SOfer Heifetz .digest = safexcel_hmac_md5_digest, 1838b471e4b9SOfer Heifetz .setkey = safexcel_hmac_md5_setkey, 1839b471e4b9SOfer Heifetz .export = safexcel_ahash_export, 1840b471e4b9SOfer Heifetz .import = safexcel_ahash_import, 1841b471e4b9SOfer Heifetz .halg = { 1842b471e4b9SOfer Heifetz .digestsize = MD5_DIGEST_SIZE, 1843b471e4b9SOfer Heifetz .statesize = sizeof(struct safexcel_ahash_export_state), 1844b471e4b9SOfer Heifetz .base = { 1845b471e4b9SOfer Heifetz .cra_name = "hmac(md5)", 1846b471e4b9SOfer Heifetz .cra_driver_name = "safexcel-hmac-md5", 1847aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 1848b471e4b9SOfer Heifetz .cra_flags = CRYPTO_ALG_ASYNC | 1849b471e4b9SOfer Heifetz CRYPTO_ALG_KERN_DRIVER_ONLY, 1850b471e4b9SOfer Heifetz .cra_blocksize = MD5_HMAC_BLOCK_SIZE, 1851b471e4b9SOfer Heifetz .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 1852b471e4b9SOfer Heifetz .cra_init = safexcel_ahash_cra_init, 1853b471e4b9SOfer Heifetz .cra_exit = safexcel_ahash_cra_exit, 1854b471e4b9SOfer Heifetz .cra_module = THIS_MODULE, 1855b471e4b9SOfer Heifetz }, 1856b471e4b9SOfer Heifetz }, 1857b471e4b9SOfer Heifetz }, 1858b471e4b9SOfer Heifetz }; 1859a7cf8658SPascal van Leeuwen 1860a7cf8658SPascal van Leeuwen static int safexcel_crc32_cra_init(struct crypto_tfm *tfm) 1861a7cf8658SPascal van Leeuwen { 1862a7cf8658SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 1863a7cf8658SPascal van Leeuwen int ret = safexcel_ahash_cra_init(tfm); 1864a7cf8658SPascal van Leeuwen 1865a7cf8658SPascal van Leeuwen /* Default 'key' is all zeroes */ 1866a7cf8658SPascal van Leeuwen memset(ctx->ipad, 0, sizeof(u32)); 1867a7cf8658SPascal van Leeuwen return ret; 1868a7cf8658SPascal van Leeuwen } 1869a7cf8658SPascal van Leeuwen 1870a7cf8658SPascal van Leeuwen static int safexcel_crc32_init(struct ahash_request *areq) 1871a7cf8658SPascal van Leeuwen { 1872a7cf8658SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 1873a7cf8658SPascal van Leeuwen struct safexcel_ahash_req *req = ahash_request_ctx(areq); 1874a7cf8658SPascal van Leeuwen 1875a7cf8658SPascal van Leeuwen memset(req, 0, sizeof(*req)); 1876a7cf8658SPascal van Leeuwen 1877a7cf8658SPascal van Leeuwen /* Start from loaded key */ 1878a7cf8658SPascal van Leeuwen req->state[0] = cpu_to_le32(~ctx->ipad[0]); 1879a7cf8658SPascal van Leeuwen /* Set processed to non-zero to enable invalidation detection */ 1880a7cf8658SPascal van Leeuwen req->len = sizeof(u32); 1881a7cf8658SPascal van Leeuwen req->processed = sizeof(u32); 1882a7cf8658SPascal van Leeuwen 1883a7cf8658SPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_CRC32; 1884a7cf8658SPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_XCM; 1885a7cf8658SPascal van Leeuwen req->state_sz = sizeof(u32); 1886a7cf8658SPascal van Leeuwen req->block_sz = sizeof(u32); 1887a7cf8658SPascal van Leeuwen 1888a7cf8658SPascal van Leeuwen return 0; 1889a7cf8658SPascal van Leeuwen } 1890a7cf8658SPascal van Leeuwen 1891a7cf8658SPascal van Leeuwen static int safexcel_crc32_setkey(struct crypto_ahash *tfm, const u8 *key, 1892a7cf8658SPascal van Leeuwen unsigned int keylen) 1893a7cf8658SPascal van Leeuwen { 1894a7cf8658SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 1895a7cf8658SPascal van Leeuwen 1896a7cf8658SPascal van Leeuwen if (keylen != sizeof(u32)) { 1897a7cf8658SPascal van Leeuwen crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); 1898a7cf8658SPascal van Leeuwen return -EINVAL; 1899a7cf8658SPascal van Leeuwen } 1900a7cf8658SPascal van Leeuwen 1901a7cf8658SPascal van Leeuwen memcpy(ctx->ipad, key, sizeof(u32)); 1902a7cf8658SPascal van Leeuwen return 0; 1903a7cf8658SPascal van Leeuwen } 1904a7cf8658SPascal van Leeuwen 1905a7cf8658SPascal van Leeuwen static int safexcel_crc32_digest(struct ahash_request *areq) 1906a7cf8658SPascal van Leeuwen { 1907a7cf8658SPascal van Leeuwen return safexcel_crc32_init(areq) ?: safexcel_ahash_finup(areq); 1908a7cf8658SPascal van Leeuwen } 1909a7cf8658SPascal van Leeuwen 1910a7cf8658SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_crc32 = { 1911a7cf8658SPascal van Leeuwen .type = SAFEXCEL_ALG_TYPE_AHASH, 1912a7cf8658SPascal van Leeuwen .algo_mask = 0, 1913a7cf8658SPascal van Leeuwen .alg.ahash = { 1914a7cf8658SPascal van Leeuwen .init = safexcel_crc32_init, 1915a7cf8658SPascal van Leeuwen .update = safexcel_ahash_update, 1916a7cf8658SPascal van Leeuwen .final = safexcel_ahash_final, 1917a7cf8658SPascal van Leeuwen .finup = safexcel_ahash_finup, 1918a7cf8658SPascal van Leeuwen .digest = safexcel_crc32_digest, 1919a7cf8658SPascal van Leeuwen .setkey = safexcel_crc32_setkey, 1920a7cf8658SPascal van Leeuwen .export = safexcel_ahash_export, 1921a7cf8658SPascal van Leeuwen .import = safexcel_ahash_import, 1922a7cf8658SPascal van Leeuwen .halg = { 1923a7cf8658SPascal van Leeuwen .digestsize = sizeof(u32), 1924a7cf8658SPascal van Leeuwen .statesize = sizeof(struct safexcel_ahash_export_state), 1925a7cf8658SPascal van Leeuwen .base = { 1926a7cf8658SPascal van Leeuwen .cra_name = "crc32", 1927a7cf8658SPascal van Leeuwen .cra_driver_name = "safexcel-crc32", 1928a7cf8658SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 1929a7cf8658SPascal van Leeuwen .cra_flags = CRYPTO_ALG_OPTIONAL_KEY | 1930a7cf8658SPascal van Leeuwen CRYPTO_ALG_ASYNC | 1931a7cf8658SPascal van Leeuwen CRYPTO_ALG_KERN_DRIVER_ONLY, 1932a7cf8658SPascal van Leeuwen .cra_blocksize = 1, 1933a7cf8658SPascal van Leeuwen .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 1934a7cf8658SPascal van Leeuwen .cra_init = safexcel_crc32_cra_init, 1935a7cf8658SPascal van Leeuwen .cra_exit = safexcel_ahash_cra_exit, 1936a7cf8658SPascal van Leeuwen .cra_module = THIS_MODULE, 1937a7cf8658SPascal van Leeuwen }, 1938a7cf8658SPascal van Leeuwen }, 1939a7cf8658SPascal van Leeuwen }, 1940a7cf8658SPascal van Leeuwen }; 1941b98687bbSPascal van Leeuwen 1942b98687bbSPascal van Leeuwen static int safexcel_cbcmac_init(struct ahash_request *areq) 1943b98687bbSPascal van Leeuwen { 1944b98687bbSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 1945b98687bbSPascal van Leeuwen struct safexcel_ahash_req *req = ahash_request_ctx(areq); 1946b98687bbSPascal van Leeuwen 1947b98687bbSPascal van Leeuwen memset(req, 0, sizeof(*req)); 1948b98687bbSPascal van Leeuwen 1949b98687bbSPascal van Leeuwen /* Start from loaded keys */ 1950b98687bbSPascal van Leeuwen memcpy(req->state, ctx->ipad, ctx->key_sz); 1951b98687bbSPascal van Leeuwen /* Set processed to non-zero to enable invalidation detection */ 1952b98687bbSPascal van Leeuwen req->len = AES_BLOCK_SIZE; 1953b98687bbSPascal van Leeuwen req->processed = AES_BLOCK_SIZE; 1954b98687bbSPascal van Leeuwen 1955b98687bbSPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_XCM; 1956b98687bbSPascal van Leeuwen req->state_sz = ctx->key_sz; 1957b98687bbSPascal van Leeuwen req->block_sz = AES_BLOCK_SIZE; 1958b98687bbSPascal van Leeuwen req->xcbcmac = true; 1959b98687bbSPascal van Leeuwen 1960b98687bbSPascal van Leeuwen return 0; 1961b98687bbSPascal van Leeuwen } 1962b98687bbSPascal van Leeuwen 1963b98687bbSPascal van Leeuwen static int safexcel_cbcmac_setkey(struct crypto_ahash *tfm, const u8 *key, 1964b98687bbSPascal van Leeuwen unsigned int len) 1965b98687bbSPascal van Leeuwen { 1966b98687bbSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 1967b98687bbSPascal van Leeuwen struct crypto_aes_ctx aes; 1968b98687bbSPascal van Leeuwen int ret, i; 1969b98687bbSPascal van Leeuwen 1970b98687bbSPascal van Leeuwen ret = aes_expandkey(&aes, key, len); 1971b98687bbSPascal van Leeuwen if (ret) { 1972b98687bbSPascal van Leeuwen crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); 1973b98687bbSPascal van Leeuwen return ret; 1974b98687bbSPascal van Leeuwen } 1975b98687bbSPascal van Leeuwen 1976b98687bbSPascal van Leeuwen memset(ctx->ipad, 0, 2 * AES_BLOCK_SIZE); 1977b98687bbSPascal van Leeuwen for (i = 0; i < len / sizeof(u32); i++) 1978b98687bbSPascal van Leeuwen ctx->ipad[i + 8] = cpu_to_be32(aes.key_enc[i]); 1979b98687bbSPascal van Leeuwen 1980b98687bbSPascal van Leeuwen if (len == AES_KEYSIZE_192) { 1981b98687bbSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC192; 1982b98687bbSPascal van Leeuwen ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE; 1983b98687bbSPascal van Leeuwen } else if (len == AES_KEYSIZE_256) { 1984b98687bbSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC256; 1985b98687bbSPascal van Leeuwen ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE; 1986b98687bbSPascal van Leeuwen } else { 1987b98687bbSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128; 1988b98687bbSPascal van Leeuwen ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE; 1989b98687bbSPascal van Leeuwen } 199038f21b4bSPascal van Leeuwen ctx->cbcmac = true; 1991b98687bbSPascal van Leeuwen 1992b98687bbSPascal van Leeuwen memzero_explicit(&aes, sizeof(aes)); 1993b98687bbSPascal van Leeuwen return 0; 1994b98687bbSPascal van Leeuwen } 1995b98687bbSPascal van Leeuwen 1996b98687bbSPascal van Leeuwen static int safexcel_cbcmac_digest(struct ahash_request *areq) 1997b98687bbSPascal van Leeuwen { 1998b98687bbSPascal van Leeuwen return safexcel_cbcmac_init(areq) ?: safexcel_ahash_finup(areq); 1999b98687bbSPascal van Leeuwen } 2000b98687bbSPascal van Leeuwen 2001b98687bbSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_cbcmac = { 2002b98687bbSPascal van Leeuwen .type = SAFEXCEL_ALG_TYPE_AHASH, 2003b98687bbSPascal van Leeuwen .algo_mask = 0, 2004b98687bbSPascal van Leeuwen .alg.ahash = { 2005b98687bbSPascal van Leeuwen .init = safexcel_cbcmac_init, 2006b98687bbSPascal van Leeuwen .update = safexcel_ahash_update, 2007b98687bbSPascal van Leeuwen .final = safexcel_ahash_final, 2008b98687bbSPascal van Leeuwen .finup = safexcel_ahash_finup, 2009b98687bbSPascal van Leeuwen .digest = safexcel_cbcmac_digest, 2010b98687bbSPascal van Leeuwen .setkey = safexcel_cbcmac_setkey, 2011b98687bbSPascal van Leeuwen .export = safexcel_ahash_export, 2012b98687bbSPascal van Leeuwen .import = safexcel_ahash_import, 2013b98687bbSPascal van Leeuwen .halg = { 2014b98687bbSPascal van Leeuwen .digestsize = AES_BLOCK_SIZE, 2015b98687bbSPascal van Leeuwen .statesize = sizeof(struct safexcel_ahash_export_state), 2016b98687bbSPascal van Leeuwen .base = { 2017b98687bbSPascal van Leeuwen .cra_name = "cbcmac(aes)", 2018b98687bbSPascal van Leeuwen .cra_driver_name = "safexcel-cbcmac-aes", 2019b98687bbSPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 2020b98687bbSPascal van Leeuwen .cra_flags = CRYPTO_ALG_ASYNC | 2021b98687bbSPascal van Leeuwen CRYPTO_ALG_KERN_DRIVER_ONLY, 2022b98687bbSPascal van Leeuwen .cra_blocksize = 1, 2023b98687bbSPascal van Leeuwen .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 2024b98687bbSPascal van Leeuwen .cra_init = safexcel_ahash_cra_init, 2025b98687bbSPascal van Leeuwen .cra_exit = safexcel_ahash_cra_exit, 2026b98687bbSPascal van Leeuwen .cra_module = THIS_MODULE, 2027b98687bbSPascal van Leeuwen }, 2028b98687bbSPascal van Leeuwen }, 2029b98687bbSPascal van Leeuwen }, 2030b98687bbSPascal van Leeuwen }; 203138f21b4bSPascal van Leeuwen 203238f21b4bSPascal van Leeuwen static int safexcel_xcbcmac_setkey(struct crypto_ahash *tfm, const u8 *key, 203338f21b4bSPascal van Leeuwen unsigned int len) 203438f21b4bSPascal van Leeuwen { 203538f21b4bSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 203638f21b4bSPascal van Leeuwen struct crypto_aes_ctx aes; 203738f21b4bSPascal van Leeuwen u32 key_tmp[3 * AES_BLOCK_SIZE / sizeof(u32)]; 203838f21b4bSPascal van Leeuwen int ret, i; 203938f21b4bSPascal van Leeuwen 204038f21b4bSPascal van Leeuwen ret = aes_expandkey(&aes, key, len); 204138f21b4bSPascal van Leeuwen if (ret) { 204238f21b4bSPascal van Leeuwen crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); 204338f21b4bSPascal van Leeuwen return ret; 204438f21b4bSPascal van Leeuwen } 204538f21b4bSPascal van Leeuwen 204638f21b4bSPascal van Leeuwen /* precompute the XCBC key material */ 204738f21b4bSPascal van Leeuwen crypto_cipher_clear_flags(ctx->kaes, CRYPTO_TFM_REQ_MASK); 204838f21b4bSPascal van Leeuwen crypto_cipher_set_flags(ctx->kaes, crypto_ahash_get_flags(tfm) & 204938f21b4bSPascal van Leeuwen CRYPTO_TFM_REQ_MASK); 205038f21b4bSPascal van Leeuwen ret = crypto_cipher_setkey(ctx->kaes, key, len); 205138f21b4bSPascal van Leeuwen crypto_ahash_set_flags(tfm, crypto_cipher_get_flags(ctx->kaes) & 205238f21b4bSPascal van Leeuwen CRYPTO_TFM_RES_MASK); 205338f21b4bSPascal van Leeuwen if (ret) 205438f21b4bSPascal van Leeuwen return ret; 205538f21b4bSPascal van Leeuwen 205638f21b4bSPascal van Leeuwen crypto_cipher_encrypt_one(ctx->kaes, (u8 *)key_tmp + 2 * AES_BLOCK_SIZE, 205738f21b4bSPascal van Leeuwen "\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1"); 205838f21b4bSPascal van Leeuwen crypto_cipher_encrypt_one(ctx->kaes, (u8 *)key_tmp, 205938f21b4bSPascal van Leeuwen "\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2"); 206038f21b4bSPascal van Leeuwen crypto_cipher_encrypt_one(ctx->kaes, (u8 *)key_tmp + AES_BLOCK_SIZE, 206138f21b4bSPascal van Leeuwen "\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3"); 206238f21b4bSPascal van Leeuwen for (i = 0; i < 3 * AES_BLOCK_SIZE / sizeof(u32); i++) 206338f21b4bSPascal van Leeuwen ctx->ipad[i] = cpu_to_be32(key_tmp[i]); 206438f21b4bSPascal van Leeuwen 206538f21b4bSPascal van Leeuwen crypto_cipher_clear_flags(ctx->kaes, CRYPTO_TFM_REQ_MASK); 206638f21b4bSPascal van Leeuwen crypto_cipher_set_flags(ctx->kaes, crypto_ahash_get_flags(tfm) & 206738f21b4bSPascal van Leeuwen CRYPTO_TFM_REQ_MASK); 206838f21b4bSPascal van Leeuwen ret = crypto_cipher_setkey(ctx->kaes, 206938f21b4bSPascal van Leeuwen (u8 *)key_tmp + 2 * AES_BLOCK_SIZE, 207038f21b4bSPascal van Leeuwen AES_MIN_KEY_SIZE); 207138f21b4bSPascal van Leeuwen crypto_ahash_set_flags(tfm, crypto_cipher_get_flags(ctx->kaes) & 207238f21b4bSPascal van Leeuwen CRYPTO_TFM_RES_MASK); 207338f21b4bSPascal van Leeuwen if (ret) 207438f21b4bSPascal van Leeuwen return ret; 207538f21b4bSPascal van Leeuwen 207638f21b4bSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128; 207738f21b4bSPascal van Leeuwen ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE; 207838f21b4bSPascal van Leeuwen ctx->cbcmac = false; 207938f21b4bSPascal van Leeuwen 208038f21b4bSPascal van Leeuwen memzero_explicit(&aes, sizeof(aes)); 208138f21b4bSPascal van Leeuwen return 0; 208238f21b4bSPascal van Leeuwen } 208338f21b4bSPascal van Leeuwen 208438f21b4bSPascal van Leeuwen static int safexcel_xcbcmac_cra_init(struct crypto_tfm *tfm) 208538f21b4bSPascal van Leeuwen { 208638f21b4bSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 208738f21b4bSPascal van Leeuwen 208838f21b4bSPascal van Leeuwen safexcel_ahash_cra_init(tfm); 208938f21b4bSPascal van Leeuwen ctx->kaes = crypto_alloc_cipher("aes", 0, 0); 209038f21b4bSPascal van Leeuwen if (IS_ERR(ctx->kaes)) 209138f21b4bSPascal van Leeuwen return PTR_ERR(ctx->kaes); 209238f21b4bSPascal van Leeuwen 209338f21b4bSPascal van Leeuwen return 0; 209438f21b4bSPascal van Leeuwen } 209538f21b4bSPascal van Leeuwen 209638f21b4bSPascal van Leeuwen static void safexcel_xcbcmac_cra_exit(struct crypto_tfm *tfm) 209738f21b4bSPascal van Leeuwen { 209838f21b4bSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 209938f21b4bSPascal van Leeuwen 210038f21b4bSPascal van Leeuwen crypto_free_cipher(ctx->kaes); 210138f21b4bSPascal van Leeuwen safexcel_ahash_cra_exit(tfm); 210238f21b4bSPascal van Leeuwen } 210338f21b4bSPascal van Leeuwen 210438f21b4bSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_xcbcmac = { 210538f21b4bSPascal van Leeuwen .type = SAFEXCEL_ALG_TYPE_AHASH, 210638f21b4bSPascal van Leeuwen .algo_mask = 0, 210738f21b4bSPascal van Leeuwen .alg.ahash = { 210838f21b4bSPascal van Leeuwen .init = safexcel_cbcmac_init, 210938f21b4bSPascal van Leeuwen .update = safexcel_ahash_update, 211038f21b4bSPascal van Leeuwen .final = safexcel_ahash_final, 211138f21b4bSPascal van Leeuwen .finup = safexcel_ahash_finup, 211238f21b4bSPascal van Leeuwen .digest = safexcel_cbcmac_digest, 211338f21b4bSPascal van Leeuwen .setkey = safexcel_xcbcmac_setkey, 211438f21b4bSPascal van Leeuwen .export = safexcel_ahash_export, 211538f21b4bSPascal van Leeuwen .import = safexcel_ahash_import, 211638f21b4bSPascal van Leeuwen .halg = { 211738f21b4bSPascal van Leeuwen .digestsize = AES_BLOCK_SIZE, 211838f21b4bSPascal van Leeuwen .statesize = sizeof(struct safexcel_ahash_export_state), 211938f21b4bSPascal van Leeuwen .base = { 212038f21b4bSPascal van Leeuwen .cra_name = "xcbc(aes)", 212138f21b4bSPascal van Leeuwen .cra_driver_name = "safexcel-xcbc-aes", 212238f21b4bSPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 212338f21b4bSPascal van Leeuwen .cra_flags = CRYPTO_ALG_ASYNC | 212438f21b4bSPascal van Leeuwen CRYPTO_ALG_KERN_DRIVER_ONLY, 212538f21b4bSPascal van Leeuwen .cra_blocksize = AES_BLOCK_SIZE, 212638f21b4bSPascal van Leeuwen .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 212738f21b4bSPascal van Leeuwen .cra_init = safexcel_xcbcmac_cra_init, 212838f21b4bSPascal van Leeuwen .cra_exit = safexcel_xcbcmac_cra_exit, 212938f21b4bSPascal van Leeuwen .cra_module = THIS_MODULE, 213038f21b4bSPascal van Leeuwen }, 213138f21b4bSPascal van Leeuwen }, 213238f21b4bSPascal van Leeuwen }, 213338f21b4bSPascal van Leeuwen }; 21347a627db9SPascal van Leeuwen 21357a627db9SPascal van Leeuwen static int safexcel_cmac_setkey(struct crypto_ahash *tfm, const u8 *key, 21367a627db9SPascal van Leeuwen unsigned int len) 21377a627db9SPascal van Leeuwen { 21387a627db9SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 21397a627db9SPascal van Leeuwen struct crypto_aes_ctx aes; 21407a627db9SPascal van Leeuwen __be64 consts[4]; 21417a627db9SPascal van Leeuwen u64 _const[2]; 21427a627db9SPascal van Leeuwen u8 msb_mask, gfmask; 21437a627db9SPascal van Leeuwen int ret, i; 21447a627db9SPascal van Leeuwen 21457a627db9SPascal van Leeuwen ret = aes_expandkey(&aes, key, len); 21467a627db9SPascal van Leeuwen if (ret) { 21477a627db9SPascal van Leeuwen crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); 21487a627db9SPascal van Leeuwen return ret; 21497a627db9SPascal van Leeuwen } 21507a627db9SPascal van Leeuwen 21517a627db9SPascal van Leeuwen for (i = 0; i < len / sizeof(u32); i++) 21527a627db9SPascal van Leeuwen ctx->ipad[i + 8] = cpu_to_be32(aes.key_enc[i]); 21537a627db9SPascal van Leeuwen 21547a627db9SPascal van Leeuwen /* precompute the CMAC key material */ 21557a627db9SPascal van Leeuwen crypto_cipher_clear_flags(ctx->kaes, CRYPTO_TFM_REQ_MASK); 21567a627db9SPascal van Leeuwen crypto_cipher_set_flags(ctx->kaes, crypto_ahash_get_flags(tfm) & 21577a627db9SPascal van Leeuwen CRYPTO_TFM_REQ_MASK); 21587a627db9SPascal van Leeuwen ret = crypto_cipher_setkey(ctx->kaes, key, len); 21597a627db9SPascal van Leeuwen crypto_ahash_set_flags(tfm, crypto_cipher_get_flags(ctx->kaes) & 21607a627db9SPascal van Leeuwen CRYPTO_TFM_RES_MASK); 21617a627db9SPascal van Leeuwen if (ret) 21627a627db9SPascal van Leeuwen return ret; 21637a627db9SPascal van Leeuwen 21647a627db9SPascal van Leeuwen /* code below borrowed from crypto/cmac.c */ 21657a627db9SPascal van Leeuwen /* encrypt the zero block */ 21667a627db9SPascal van Leeuwen memset(consts, 0, AES_BLOCK_SIZE); 21677a627db9SPascal van Leeuwen crypto_cipher_encrypt_one(ctx->kaes, (u8 *)consts, (u8 *)consts); 21687a627db9SPascal van Leeuwen 21697a627db9SPascal van Leeuwen gfmask = 0x87; 21707a627db9SPascal van Leeuwen _const[0] = be64_to_cpu(consts[1]); 21717a627db9SPascal van Leeuwen _const[1] = be64_to_cpu(consts[0]); 21727a627db9SPascal van Leeuwen 21737a627db9SPascal van Leeuwen /* gf(2^128) multiply zero-ciphertext with u and u^2 */ 21747a627db9SPascal van Leeuwen for (i = 0; i < 4; i += 2) { 21757a627db9SPascal van Leeuwen msb_mask = ((s64)_const[1] >> 63) & gfmask; 21767a627db9SPascal van Leeuwen _const[1] = (_const[1] << 1) | (_const[0] >> 63); 21777a627db9SPascal van Leeuwen _const[0] = (_const[0] << 1) ^ msb_mask; 21787a627db9SPascal van Leeuwen 21797a627db9SPascal van Leeuwen consts[i + 0] = cpu_to_be64(_const[1]); 21807a627db9SPascal van Leeuwen consts[i + 1] = cpu_to_be64(_const[0]); 21817a627db9SPascal van Leeuwen } 21827a627db9SPascal van Leeuwen /* end of code borrowed from crypto/cmac.c */ 21837a627db9SPascal van Leeuwen 21847a627db9SPascal van Leeuwen for (i = 0; i < 2 * AES_BLOCK_SIZE / sizeof(u32); i++) 21857a627db9SPascal van Leeuwen ctx->ipad[i] = cpu_to_be32(((u32 *)consts)[i]); 21867a627db9SPascal van Leeuwen 21877a627db9SPascal van Leeuwen if (len == AES_KEYSIZE_192) { 21887a627db9SPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC192; 21897a627db9SPascal van Leeuwen ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE; 21907a627db9SPascal van Leeuwen } else if (len == AES_KEYSIZE_256) { 21917a627db9SPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC256; 21927a627db9SPascal van Leeuwen ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE; 21937a627db9SPascal van Leeuwen } else { 21947a627db9SPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128; 21957a627db9SPascal van Leeuwen ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE; 21967a627db9SPascal van Leeuwen } 21977a627db9SPascal van Leeuwen ctx->cbcmac = false; 21987a627db9SPascal van Leeuwen 21997a627db9SPascal van Leeuwen memzero_explicit(&aes, sizeof(aes)); 22007a627db9SPascal van Leeuwen return 0; 22017a627db9SPascal van Leeuwen } 22027a627db9SPascal van Leeuwen 22037a627db9SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_cmac = { 22047a627db9SPascal van Leeuwen .type = SAFEXCEL_ALG_TYPE_AHASH, 22057a627db9SPascal van Leeuwen .algo_mask = 0, 22067a627db9SPascal van Leeuwen .alg.ahash = { 22077a627db9SPascal van Leeuwen .init = safexcel_cbcmac_init, 22087a627db9SPascal van Leeuwen .update = safexcel_ahash_update, 22097a627db9SPascal van Leeuwen .final = safexcel_ahash_final, 22107a627db9SPascal van Leeuwen .finup = safexcel_ahash_finup, 22117a627db9SPascal van Leeuwen .digest = safexcel_cbcmac_digest, 22127a627db9SPascal van Leeuwen .setkey = safexcel_cmac_setkey, 22137a627db9SPascal van Leeuwen .export = safexcel_ahash_export, 22147a627db9SPascal van Leeuwen .import = safexcel_ahash_import, 22157a627db9SPascal van Leeuwen .halg = { 22167a627db9SPascal van Leeuwen .digestsize = AES_BLOCK_SIZE, 22177a627db9SPascal van Leeuwen .statesize = sizeof(struct safexcel_ahash_export_state), 22187a627db9SPascal van Leeuwen .base = { 22197a627db9SPascal van Leeuwen .cra_name = "cmac(aes)", 22207a627db9SPascal van Leeuwen .cra_driver_name = "safexcel-cmac-aes", 22217a627db9SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 22227a627db9SPascal van Leeuwen .cra_flags = CRYPTO_ALG_ASYNC | 22237a627db9SPascal van Leeuwen CRYPTO_ALG_KERN_DRIVER_ONLY, 22247a627db9SPascal van Leeuwen .cra_blocksize = AES_BLOCK_SIZE, 22257a627db9SPascal van Leeuwen .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 22267a627db9SPascal van Leeuwen .cra_init = safexcel_xcbcmac_cra_init, 22277a627db9SPascal van Leeuwen .cra_exit = safexcel_xcbcmac_cra_exit, 22287a627db9SPascal van Leeuwen .cra_module = THIS_MODULE, 22297a627db9SPascal van Leeuwen }, 22307a627db9SPascal van Leeuwen }, 22317a627db9SPascal van Leeuwen }, 22327a627db9SPascal van Leeuwen }; 22330f2bc131SPascal van Leeuwen 22340f2bc131SPascal van Leeuwen static int safexcel_sm3_init(struct ahash_request *areq) 22350f2bc131SPascal van Leeuwen { 22360f2bc131SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 22370f2bc131SPascal van Leeuwen struct safexcel_ahash_req *req = ahash_request_ctx(areq); 22380f2bc131SPascal van Leeuwen 22390f2bc131SPascal van Leeuwen memset(req, 0, sizeof(*req)); 22400f2bc131SPascal van Leeuwen 22410f2bc131SPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SM3; 22420f2bc131SPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 22430f2bc131SPascal van Leeuwen req->state_sz = SM3_DIGEST_SIZE; 22440f2bc131SPascal van Leeuwen req->block_sz = SM3_BLOCK_SIZE; 22450f2bc131SPascal van Leeuwen 22460f2bc131SPascal van Leeuwen return 0; 22470f2bc131SPascal van Leeuwen } 22480f2bc131SPascal van Leeuwen 22490f2bc131SPascal van Leeuwen static int safexcel_sm3_digest(struct ahash_request *areq) 22500f2bc131SPascal van Leeuwen { 22510f2bc131SPascal van Leeuwen int ret = safexcel_sm3_init(areq); 22520f2bc131SPascal van Leeuwen 22530f2bc131SPascal van Leeuwen if (ret) 22540f2bc131SPascal van Leeuwen return ret; 22550f2bc131SPascal van Leeuwen 22560f2bc131SPascal van Leeuwen return safexcel_ahash_finup(areq); 22570f2bc131SPascal van Leeuwen } 22580f2bc131SPascal van Leeuwen 22590f2bc131SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_sm3 = { 22600f2bc131SPascal van Leeuwen .type = SAFEXCEL_ALG_TYPE_AHASH, 22610f2bc131SPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SM3, 22620f2bc131SPascal van Leeuwen .alg.ahash = { 22630f2bc131SPascal van Leeuwen .init = safexcel_sm3_init, 22640f2bc131SPascal van Leeuwen .update = safexcel_ahash_update, 22650f2bc131SPascal van Leeuwen .final = safexcel_ahash_final, 22660f2bc131SPascal van Leeuwen .finup = safexcel_ahash_finup, 22670f2bc131SPascal van Leeuwen .digest = safexcel_sm3_digest, 22680f2bc131SPascal van Leeuwen .export = safexcel_ahash_export, 22690f2bc131SPascal van Leeuwen .import = safexcel_ahash_import, 22700f2bc131SPascal van Leeuwen .halg = { 22710f2bc131SPascal van Leeuwen .digestsize = SM3_DIGEST_SIZE, 22720f2bc131SPascal van Leeuwen .statesize = sizeof(struct safexcel_ahash_export_state), 22730f2bc131SPascal van Leeuwen .base = { 22740f2bc131SPascal van Leeuwen .cra_name = "sm3", 22750f2bc131SPascal van Leeuwen .cra_driver_name = "safexcel-sm3", 22760f2bc131SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 22770f2bc131SPascal van Leeuwen .cra_flags = CRYPTO_ALG_ASYNC | 22780f2bc131SPascal van Leeuwen CRYPTO_ALG_KERN_DRIVER_ONLY, 22790f2bc131SPascal van Leeuwen .cra_blocksize = SM3_BLOCK_SIZE, 22800f2bc131SPascal van Leeuwen .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 22810f2bc131SPascal van Leeuwen .cra_init = safexcel_ahash_cra_init, 22820f2bc131SPascal van Leeuwen .cra_exit = safexcel_ahash_cra_exit, 22830f2bc131SPascal van Leeuwen .cra_module = THIS_MODULE, 22840f2bc131SPascal van Leeuwen }, 22850f2bc131SPascal van Leeuwen }, 22860f2bc131SPascal van Leeuwen }, 22870f2bc131SPascal van Leeuwen }; 2288