18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2017 Marvell 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Antoine Tenart <antoine.tenart@free-electrons.com> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <crypto/aes.h> 98c2ecf20Sopenharmony_ci#include <crypto/hmac.h> 108c2ecf20Sopenharmony_ci#include <crypto/md5.h> 118c2ecf20Sopenharmony_ci#include <crypto/sha.h> 128c2ecf20Sopenharmony_ci#include <crypto/sha3.h> 138c2ecf20Sopenharmony_ci#include <crypto/skcipher.h> 148c2ecf20Sopenharmony_ci#include <crypto/sm3.h> 158c2ecf20Sopenharmony_ci#include <linux/device.h> 168c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h> 178c2ecf20Sopenharmony_ci#include <linux/dmapool.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include "safexcel.h" 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_cistruct safexcel_ahash_ctx { 228c2ecf20Sopenharmony_ci struct safexcel_context base; 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci u32 alg; 258c2ecf20Sopenharmony_ci u8 key_sz; 268c2ecf20Sopenharmony_ci bool cbcmac; 278c2ecf20Sopenharmony_ci bool do_fallback; 288c2ecf20Sopenharmony_ci bool fb_init_done; 298c2ecf20Sopenharmony_ci bool fb_do_setkey; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci struct crypto_cipher *kaes; 328c2ecf20Sopenharmony_ci struct crypto_ahash *fback; 338c2ecf20Sopenharmony_ci struct crypto_shash *shpre; 348c2ecf20Sopenharmony_ci struct shash_desc *shdesc; 358c2ecf20Sopenharmony_ci}; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_cistruct safexcel_ahash_req { 388c2ecf20Sopenharmony_ci bool last_req; 398c2ecf20Sopenharmony_ci bool finish; 408c2ecf20Sopenharmony_ci bool hmac; 418c2ecf20Sopenharmony_ci bool needs_inv; 428c2ecf20Sopenharmony_ci bool hmac_zlen; 438c2ecf20Sopenharmony_ci bool len_is_le; 448c2ecf20Sopenharmony_ci bool not_first; 458c2ecf20Sopenharmony_ci bool xcbcmac; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci int nents; 488c2ecf20Sopenharmony_ci dma_addr_t result_dma; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci u32 digest; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci u8 state_sz; /* expected state size, only set once */ 538c2ecf20Sopenharmony_ci u8 block_sz; /* block size, only set once */ 548c2ecf20Sopenharmony_ci u8 digest_sz; /* output digest size, only set once */ 558c2ecf20Sopenharmony_ci __le32 state[SHA3_512_BLOCK_SIZE / 568c2ecf20Sopenharmony_ci sizeof(__le32)] __aligned(sizeof(__le32)); 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci u64 len; 598c2ecf20Sopenharmony_ci u64 processed; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci u8 cache[HASH_CACHE_SIZE] __aligned(sizeof(u32)); 628c2ecf20Sopenharmony_ci dma_addr_t cache_dma; 638c2ecf20Sopenharmony_ci unsigned int cache_sz; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci u8 cache_next[HASH_CACHE_SIZE] __aligned(sizeof(u32)); 668c2ecf20Sopenharmony_ci}; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_cistatic inline u64 safexcel_queued_len(struct safexcel_ahash_req *req) 698c2ecf20Sopenharmony_ci{ 708c2ecf20Sopenharmony_ci return req->len - req->processed; 718c2ecf20Sopenharmony_ci} 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_cistatic void safexcel_hash_token(struct safexcel_command_desc *cdesc, 748c2ecf20Sopenharmony_ci u32 input_length, u32 result_length, 758c2ecf20Sopenharmony_ci bool cbcmac) 768c2ecf20Sopenharmony_ci{ 778c2ecf20Sopenharmony_ci struct safexcel_token *token = 788c2ecf20Sopenharmony_ci (struct safexcel_token *)cdesc->control_data.token; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci token[0].opcode = EIP197_TOKEN_OPCODE_DIRECTION; 818c2ecf20Sopenharmony_ci token[0].packet_length = input_length; 828c2ecf20Sopenharmony_ci token[0].instructions = EIP197_TOKEN_INS_TYPE_HASH; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci input_length &= 15; 858c2ecf20Sopenharmony_ci if (unlikely(cbcmac && input_length)) { 868c2ecf20Sopenharmony_ci token[0].stat = 0; 878c2ecf20Sopenharmony_ci token[1].opcode = EIP197_TOKEN_OPCODE_INSERT; 888c2ecf20Sopenharmony_ci token[1].packet_length = 16 - input_length; 898c2ecf20Sopenharmony_ci token[1].stat = EIP197_TOKEN_STAT_LAST_HASH; 908c2ecf20Sopenharmony_ci token[1].instructions = EIP197_TOKEN_INS_TYPE_HASH; 918c2ecf20Sopenharmony_ci } else { 928c2ecf20Sopenharmony_ci token[0].stat = EIP197_TOKEN_STAT_LAST_HASH; 938c2ecf20Sopenharmony_ci eip197_noop_token(&token[1]); 948c2ecf20Sopenharmony_ci } 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci token[2].opcode = EIP197_TOKEN_OPCODE_INSERT; 978c2ecf20Sopenharmony_ci token[2].stat = EIP197_TOKEN_STAT_LAST_HASH | 988c2ecf20Sopenharmony_ci EIP197_TOKEN_STAT_LAST_PACKET; 998c2ecf20Sopenharmony_ci token[2].packet_length = result_length; 1008c2ecf20Sopenharmony_ci token[2].instructions = EIP197_TOKEN_INS_TYPE_OUTPUT | 1018c2ecf20Sopenharmony_ci EIP197_TOKEN_INS_INSERT_HASH_DIGEST; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci eip197_noop_token(&token[3]); 1048c2ecf20Sopenharmony_ci} 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_cistatic void safexcel_context_control(struct safexcel_ahash_ctx *ctx, 1078c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req, 1088c2ecf20Sopenharmony_ci struct safexcel_command_desc *cdesc) 1098c2ecf20Sopenharmony_ci{ 1108c2ecf20Sopenharmony_ci struct safexcel_crypto_priv *priv = ctx->base.priv; 1118c2ecf20Sopenharmony_ci u64 count = 0; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci cdesc->control_data.control0 = ctx->alg; 1148c2ecf20Sopenharmony_ci cdesc->control_data.control1 = 0; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci /* 1178c2ecf20Sopenharmony_ci * Copy the input digest if needed, and setup the context 1188c2ecf20Sopenharmony_ci * fields. Do this now as we need it to setup the first command 1198c2ecf20Sopenharmony_ci * descriptor. 1208c2ecf20Sopenharmony_ci */ 1218c2ecf20Sopenharmony_ci if (unlikely(req->digest == CONTEXT_CONTROL_DIGEST_XCM)) { 1228c2ecf20Sopenharmony_ci if (req->xcbcmac) 1238c2ecf20Sopenharmony_ci memcpy(ctx->base.ctxr->data, &ctx->base.ipad, ctx->key_sz); 1248c2ecf20Sopenharmony_ci else 1258c2ecf20Sopenharmony_ci memcpy(ctx->base.ctxr->data, req->state, req->state_sz); 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci if (!req->finish && req->xcbcmac) 1288c2ecf20Sopenharmony_ci cdesc->control_data.control0 |= 1298c2ecf20Sopenharmony_ci CONTEXT_CONTROL_DIGEST_XCM | 1308c2ecf20Sopenharmony_ci CONTEXT_CONTROL_TYPE_HASH_OUT | 1318c2ecf20Sopenharmony_ci CONTEXT_CONTROL_NO_FINISH_HASH | 1328c2ecf20Sopenharmony_ci CONTEXT_CONTROL_SIZE(req->state_sz / 1338c2ecf20Sopenharmony_ci sizeof(u32)); 1348c2ecf20Sopenharmony_ci else 1358c2ecf20Sopenharmony_ci cdesc->control_data.control0 |= 1368c2ecf20Sopenharmony_ci CONTEXT_CONTROL_DIGEST_XCM | 1378c2ecf20Sopenharmony_ci CONTEXT_CONTROL_TYPE_HASH_OUT | 1388c2ecf20Sopenharmony_ci CONTEXT_CONTROL_SIZE(req->state_sz / 1398c2ecf20Sopenharmony_ci sizeof(u32)); 1408c2ecf20Sopenharmony_ci return; 1418c2ecf20Sopenharmony_ci } else if (!req->processed) { 1428c2ecf20Sopenharmony_ci /* First - and possibly only - block of basic hash only */ 1438c2ecf20Sopenharmony_ci if (req->finish) 1448c2ecf20Sopenharmony_ci cdesc->control_data.control0 |= req->digest | 1458c2ecf20Sopenharmony_ci CONTEXT_CONTROL_TYPE_HASH_OUT | 1468c2ecf20Sopenharmony_ci CONTEXT_CONTROL_RESTART_HASH | 1478c2ecf20Sopenharmony_ci /* ensure its not 0! */ 1488c2ecf20Sopenharmony_ci CONTEXT_CONTROL_SIZE(1); 1498c2ecf20Sopenharmony_ci else 1508c2ecf20Sopenharmony_ci cdesc->control_data.control0 |= req->digest | 1518c2ecf20Sopenharmony_ci CONTEXT_CONTROL_TYPE_HASH_OUT | 1528c2ecf20Sopenharmony_ci CONTEXT_CONTROL_RESTART_HASH | 1538c2ecf20Sopenharmony_ci CONTEXT_CONTROL_NO_FINISH_HASH | 1548c2ecf20Sopenharmony_ci /* ensure its not 0! */ 1558c2ecf20Sopenharmony_ci CONTEXT_CONTROL_SIZE(1); 1568c2ecf20Sopenharmony_ci return; 1578c2ecf20Sopenharmony_ci } 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci /* Hash continuation or HMAC, setup (inner) digest from state */ 1608c2ecf20Sopenharmony_ci memcpy(ctx->base.ctxr->data, req->state, req->state_sz); 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci if (req->finish) { 1638c2ecf20Sopenharmony_ci /* Compute digest count for hash/HMAC finish operations */ 1648c2ecf20Sopenharmony_ci if ((req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) || 1658c2ecf20Sopenharmony_ci req->hmac_zlen || (req->processed != req->block_sz)) { 1668c2ecf20Sopenharmony_ci count = req->processed / EIP197_COUNTER_BLOCK_SIZE; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci /* This is a hardware limitation, as the 1698c2ecf20Sopenharmony_ci * counter must fit into an u32. This represents 1708c2ecf20Sopenharmony_ci * a fairly big amount of input data, so we 1718c2ecf20Sopenharmony_ci * shouldn't see this. 1728c2ecf20Sopenharmony_ci */ 1738c2ecf20Sopenharmony_ci if (unlikely(count & 0xffffffff00000000ULL)) { 1748c2ecf20Sopenharmony_ci dev_warn(priv->dev, 1758c2ecf20Sopenharmony_ci "Input data is too big\n"); 1768c2ecf20Sopenharmony_ci return; 1778c2ecf20Sopenharmony_ci } 1788c2ecf20Sopenharmony_ci } 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci if ((req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) || 1818c2ecf20Sopenharmony_ci /* Special case: zero length HMAC */ 1828c2ecf20Sopenharmony_ci req->hmac_zlen || 1838c2ecf20Sopenharmony_ci /* PE HW < 4.4 cannot do HMAC continue, fake using hash */ 1848c2ecf20Sopenharmony_ci (req->processed != req->block_sz)) { 1858c2ecf20Sopenharmony_ci /* Basic hash continue operation, need digest + cnt */ 1868c2ecf20Sopenharmony_ci cdesc->control_data.control0 |= 1878c2ecf20Sopenharmony_ci CONTEXT_CONTROL_SIZE((req->state_sz >> 2) + 1) | 1888c2ecf20Sopenharmony_ci CONTEXT_CONTROL_TYPE_HASH_OUT | 1898c2ecf20Sopenharmony_ci CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 1908c2ecf20Sopenharmony_ci /* For zero-len HMAC, don't finalize, already padded! */ 1918c2ecf20Sopenharmony_ci if (req->hmac_zlen) 1928c2ecf20Sopenharmony_ci cdesc->control_data.control0 |= 1938c2ecf20Sopenharmony_ci CONTEXT_CONTROL_NO_FINISH_HASH; 1948c2ecf20Sopenharmony_ci cdesc->control_data.control1 |= 1958c2ecf20Sopenharmony_ci CONTEXT_CONTROL_DIGEST_CNT; 1968c2ecf20Sopenharmony_ci ctx->base.ctxr->data[req->state_sz >> 2] = 1978c2ecf20Sopenharmony_ci cpu_to_le32(count); 1988c2ecf20Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci /* Clear zero-length HMAC flag for next operation! */ 2018c2ecf20Sopenharmony_ci req->hmac_zlen = false; 2028c2ecf20Sopenharmony_ci } else { /* HMAC */ 2038c2ecf20Sopenharmony_ci /* Need outer digest for HMAC finalization */ 2048c2ecf20Sopenharmony_ci memcpy(ctx->base.ctxr->data + (req->state_sz >> 2), 2058c2ecf20Sopenharmony_ci &ctx->base.opad, req->state_sz); 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci /* Single pass HMAC - no digest count */ 2088c2ecf20Sopenharmony_ci cdesc->control_data.control0 |= 2098c2ecf20Sopenharmony_ci CONTEXT_CONTROL_SIZE(req->state_sz >> 1) | 2108c2ecf20Sopenharmony_ci CONTEXT_CONTROL_TYPE_HASH_OUT | 2118c2ecf20Sopenharmony_ci CONTEXT_CONTROL_DIGEST_HMAC; 2128c2ecf20Sopenharmony_ci } 2138c2ecf20Sopenharmony_ci } else { /* Hash continuation, do not finish yet */ 2148c2ecf20Sopenharmony_ci cdesc->control_data.control0 |= 2158c2ecf20Sopenharmony_ci CONTEXT_CONTROL_SIZE(req->state_sz >> 2) | 2168c2ecf20Sopenharmony_ci CONTEXT_CONTROL_DIGEST_PRECOMPUTED | 2178c2ecf20Sopenharmony_ci CONTEXT_CONTROL_TYPE_HASH_OUT | 2188c2ecf20Sopenharmony_ci CONTEXT_CONTROL_NO_FINISH_HASH; 2198c2ecf20Sopenharmony_ci } 2208c2ecf20Sopenharmony_ci} 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_cistatic int safexcel_ahash_enqueue(struct ahash_request *areq); 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_cistatic int safexcel_handle_req_result(struct safexcel_crypto_priv *priv, 2258c2ecf20Sopenharmony_ci int ring, 2268c2ecf20Sopenharmony_ci struct crypto_async_request *async, 2278c2ecf20Sopenharmony_ci bool *should_complete, int *ret) 2288c2ecf20Sopenharmony_ci{ 2298c2ecf20Sopenharmony_ci struct safexcel_result_desc *rdesc; 2308c2ecf20Sopenharmony_ci struct ahash_request *areq = ahash_request_cast(async); 2318c2ecf20Sopenharmony_ci struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); 2328c2ecf20Sopenharmony_ci struct safexcel_ahash_req *sreq = ahash_request_ctx(areq); 2338c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(ahash); 2348c2ecf20Sopenharmony_ci u64 cache_len; 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci *ret = 0; 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr); 2398c2ecf20Sopenharmony_ci if (IS_ERR(rdesc)) { 2408c2ecf20Sopenharmony_ci dev_err(priv->dev, 2418c2ecf20Sopenharmony_ci "hash: result: could not retrieve the result descriptor\n"); 2428c2ecf20Sopenharmony_ci *ret = PTR_ERR(rdesc); 2438c2ecf20Sopenharmony_ci } else { 2448c2ecf20Sopenharmony_ci *ret = safexcel_rdesc_check_errors(priv, rdesc); 2458c2ecf20Sopenharmony_ci } 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci safexcel_complete(priv, ring); 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci if (sreq->nents) { 2508c2ecf20Sopenharmony_ci dma_unmap_sg(priv->dev, areq->src, sreq->nents, DMA_TO_DEVICE); 2518c2ecf20Sopenharmony_ci sreq->nents = 0; 2528c2ecf20Sopenharmony_ci } 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci if (sreq->result_dma) { 2558c2ecf20Sopenharmony_ci dma_unmap_single(priv->dev, sreq->result_dma, sreq->digest_sz, 2568c2ecf20Sopenharmony_ci DMA_FROM_DEVICE); 2578c2ecf20Sopenharmony_ci sreq->result_dma = 0; 2588c2ecf20Sopenharmony_ci } 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci if (sreq->cache_dma) { 2618c2ecf20Sopenharmony_ci dma_unmap_single(priv->dev, sreq->cache_dma, sreq->cache_sz, 2628c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 2638c2ecf20Sopenharmony_ci sreq->cache_dma = 0; 2648c2ecf20Sopenharmony_ci sreq->cache_sz = 0; 2658c2ecf20Sopenharmony_ci } 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci if (sreq->finish) { 2688c2ecf20Sopenharmony_ci if (sreq->hmac && 2698c2ecf20Sopenharmony_ci (sreq->digest != CONTEXT_CONTROL_DIGEST_HMAC)) { 2708c2ecf20Sopenharmony_ci /* Faking HMAC using hash - need to do outer hash */ 2718c2ecf20Sopenharmony_ci memcpy(sreq->cache, sreq->state, 2728c2ecf20Sopenharmony_ci crypto_ahash_digestsize(ahash)); 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci memcpy(sreq->state, &ctx->base.opad, sreq->digest_sz); 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci sreq->len = sreq->block_sz + 2778c2ecf20Sopenharmony_ci crypto_ahash_digestsize(ahash); 2788c2ecf20Sopenharmony_ci sreq->processed = sreq->block_sz; 2798c2ecf20Sopenharmony_ci sreq->hmac = 0; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci if (priv->flags & EIP197_TRC_CACHE) 2828c2ecf20Sopenharmony_ci ctx->base.needs_inv = true; 2838c2ecf20Sopenharmony_ci areq->nbytes = 0; 2848c2ecf20Sopenharmony_ci safexcel_ahash_enqueue(areq); 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci *should_complete = false; /* Not done yet */ 2878c2ecf20Sopenharmony_ci return 1; 2888c2ecf20Sopenharmony_ci } 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci if (unlikely(sreq->digest == CONTEXT_CONTROL_DIGEST_XCM && 2918c2ecf20Sopenharmony_ci ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_CRC32)) { 2928c2ecf20Sopenharmony_ci /* Undo final XOR with 0xffffffff ...*/ 2938c2ecf20Sopenharmony_ci *(__le32 *)areq->result = ~sreq->state[0]; 2948c2ecf20Sopenharmony_ci } else { 2958c2ecf20Sopenharmony_ci memcpy(areq->result, sreq->state, 2968c2ecf20Sopenharmony_ci crypto_ahash_digestsize(ahash)); 2978c2ecf20Sopenharmony_ci } 2988c2ecf20Sopenharmony_ci } 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci cache_len = safexcel_queued_len(sreq); 3018c2ecf20Sopenharmony_ci if (cache_len) 3028c2ecf20Sopenharmony_ci memcpy(sreq->cache, sreq->cache_next, cache_len); 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci *should_complete = true; 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci return 1; 3078c2ecf20Sopenharmony_ci} 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_cistatic int safexcel_ahash_send_req(struct crypto_async_request *async, int ring, 3108c2ecf20Sopenharmony_ci int *commands, int *results) 3118c2ecf20Sopenharmony_ci{ 3128c2ecf20Sopenharmony_ci struct ahash_request *areq = ahash_request_cast(async); 3138c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx(areq); 3148c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 3158c2ecf20Sopenharmony_ci struct safexcel_crypto_priv *priv = ctx->base.priv; 3168c2ecf20Sopenharmony_ci struct safexcel_command_desc *cdesc, *first_cdesc = NULL; 3178c2ecf20Sopenharmony_ci struct safexcel_result_desc *rdesc; 3188c2ecf20Sopenharmony_ci struct scatterlist *sg; 3198c2ecf20Sopenharmony_ci struct safexcel_token *dmmy; 3208c2ecf20Sopenharmony_ci int i, extra = 0, n_cdesc = 0, ret = 0, cache_len, skip = 0; 3218c2ecf20Sopenharmony_ci u64 queued, len; 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci queued = safexcel_queued_len(req); 3248c2ecf20Sopenharmony_ci if (queued <= HASH_CACHE_SIZE) 3258c2ecf20Sopenharmony_ci cache_len = queued; 3268c2ecf20Sopenharmony_ci else 3278c2ecf20Sopenharmony_ci cache_len = queued - areq->nbytes; 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci if (!req->finish && !req->last_req) { 3308c2ecf20Sopenharmony_ci /* If this is not the last request and the queued data does not 3318c2ecf20Sopenharmony_ci * fit into full cache blocks, cache it for the next send call. 3328c2ecf20Sopenharmony_ci */ 3338c2ecf20Sopenharmony_ci extra = queued & (HASH_CACHE_SIZE - 1); 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci /* If this is not the last request and the queued data 3368c2ecf20Sopenharmony_ci * is a multiple of a block, cache the last one for now. 3378c2ecf20Sopenharmony_ci */ 3388c2ecf20Sopenharmony_ci if (!extra) 3398c2ecf20Sopenharmony_ci extra = HASH_CACHE_SIZE; 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci sg_pcopy_to_buffer(areq->src, sg_nents(areq->src), 3428c2ecf20Sopenharmony_ci req->cache_next, extra, 3438c2ecf20Sopenharmony_ci areq->nbytes - extra); 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci queued -= extra; 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci if (!queued) { 3488c2ecf20Sopenharmony_ci *commands = 0; 3498c2ecf20Sopenharmony_ci *results = 0; 3508c2ecf20Sopenharmony_ci return 0; 3518c2ecf20Sopenharmony_ci } 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci extra = 0; 3548c2ecf20Sopenharmony_ci } 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci if (unlikely(req->xcbcmac && req->processed > AES_BLOCK_SIZE)) { 3578c2ecf20Sopenharmony_ci if (unlikely(cache_len < AES_BLOCK_SIZE)) { 3588c2ecf20Sopenharmony_ci /* 3598c2ecf20Sopenharmony_ci * Cache contains less than 1 full block, complete. 3608c2ecf20Sopenharmony_ci */ 3618c2ecf20Sopenharmony_ci extra = AES_BLOCK_SIZE - cache_len; 3628c2ecf20Sopenharmony_ci if (queued > cache_len) { 3638c2ecf20Sopenharmony_ci /* More data follows: borrow bytes */ 3648c2ecf20Sopenharmony_ci u64 tmp = queued - cache_len; 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci skip = min_t(u64, tmp, extra); 3678c2ecf20Sopenharmony_ci sg_pcopy_to_buffer(areq->src, 3688c2ecf20Sopenharmony_ci sg_nents(areq->src), 3698c2ecf20Sopenharmony_ci req->cache + cache_len, 3708c2ecf20Sopenharmony_ci skip, 0); 3718c2ecf20Sopenharmony_ci } 3728c2ecf20Sopenharmony_ci extra -= skip; 3738c2ecf20Sopenharmony_ci memset(req->cache + cache_len + skip, 0, extra); 3748c2ecf20Sopenharmony_ci if (!ctx->cbcmac && extra) { 3758c2ecf20Sopenharmony_ci // 10- padding for XCBCMAC & CMAC 3768c2ecf20Sopenharmony_ci req->cache[cache_len + skip] = 0x80; 3778c2ecf20Sopenharmony_ci // HW will use K2 iso K3 - compensate! 3788c2ecf20Sopenharmony_ci for (i = 0; i < AES_BLOCK_SIZE / 4; i++) { 3798c2ecf20Sopenharmony_ci u32 *cache = (void *)req->cache; 3808c2ecf20Sopenharmony_ci u32 *ipad = ctx->base.ipad.word; 3818c2ecf20Sopenharmony_ci u32 x; 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci x = ipad[i] ^ ipad[i + 4]; 3848c2ecf20Sopenharmony_ci cache[i] ^= swab32(x); 3858c2ecf20Sopenharmony_ci } 3868c2ecf20Sopenharmony_ci } 3878c2ecf20Sopenharmony_ci cache_len = AES_BLOCK_SIZE; 3888c2ecf20Sopenharmony_ci queued = queued + extra; 3898c2ecf20Sopenharmony_ci } 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci /* XCBC continue: XOR previous result into 1st word */ 3928c2ecf20Sopenharmony_ci crypto_xor(req->cache, (const u8 *)req->state, AES_BLOCK_SIZE); 3938c2ecf20Sopenharmony_ci } 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci len = queued; 3968c2ecf20Sopenharmony_ci /* Add a command descriptor for the cached data, if any */ 3978c2ecf20Sopenharmony_ci if (cache_len) { 3988c2ecf20Sopenharmony_ci req->cache_dma = dma_map_single(priv->dev, req->cache, 3998c2ecf20Sopenharmony_ci cache_len, DMA_TO_DEVICE); 4008c2ecf20Sopenharmony_ci if (dma_mapping_error(priv->dev, req->cache_dma)) 4018c2ecf20Sopenharmony_ci return -EINVAL; 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci req->cache_sz = cache_len; 4048c2ecf20Sopenharmony_ci first_cdesc = safexcel_add_cdesc(priv, ring, 1, 4058c2ecf20Sopenharmony_ci (cache_len == len), 4068c2ecf20Sopenharmony_ci req->cache_dma, cache_len, 4078c2ecf20Sopenharmony_ci len, ctx->base.ctxr_dma, 4088c2ecf20Sopenharmony_ci &dmmy); 4098c2ecf20Sopenharmony_ci if (IS_ERR(first_cdesc)) { 4108c2ecf20Sopenharmony_ci ret = PTR_ERR(first_cdesc); 4118c2ecf20Sopenharmony_ci goto unmap_cache; 4128c2ecf20Sopenharmony_ci } 4138c2ecf20Sopenharmony_ci n_cdesc++; 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci queued -= cache_len; 4168c2ecf20Sopenharmony_ci if (!queued) 4178c2ecf20Sopenharmony_ci goto send_command; 4188c2ecf20Sopenharmony_ci } 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci /* Now handle the current ahash request buffer(s) */ 4218c2ecf20Sopenharmony_ci req->nents = dma_map_sg(priv->dev, areq->src, 4228c2ecf20Sopenharmony_ci sg_nents_for_len(areq->src, 4238c2ecf20Sopenharmony_ci areq->nbytes), 4248c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 4258c2ecf20Sopenharmony_ci if (!req->nents) { 4268c2ecf20Sopenharmony_ci ret = -ENOMEM; 4278c2ecf20Sopenharmony_ci goto cdesc_rollback; 4288c2ecf20Sopenharmony_ci } 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ci for_each_sg(areq->src, sg, req->nents, i) { 4318c2ecf20Sopenharmony_ci int sglen = sg_dma_len(sg); 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci if (unlikely(sglen <= skip)) { 4348c2ecf20Sopenharmony_ci skip -= sglen; 4358c2ecf20Sopenharmony_ci continue; 4368c2ecf20Sopenharmony_ci } 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci /* Do not overflow the request */ 4398c2ecf20Sopenharmony_ci if ((queued + skip) <= sglen) 4408c2ecf20Sopenharmony_ci sglen = queued; 4418c2ecf20Sopenharmony_ci else 4428c2ecf20Sopenharmony_ci sglen -= skip; 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci cdesc = safexcel_add_cdesc(priv, ring, !n_cdesc, 4458c2ecf20Sopenharmony_ci !(queued - sglen), 4468c2ecf20Sopenharmony_ci sg_dma_address(sg) + skip, sglen, 4478c2ecf20Sopenharmony_ci len, ctx->base.ctxr_dma, &dmmy); 4488c2ecf20Sopenharmony_ci if (IS_ERR(cdesc)) { 4498c2ecf20Sopenharmony_ci ret = PTR_ERR(cdesc); 4508c2ecf20Sopenharmony_ci goto unmap_sg; 4518c2ecf20Sopenharmony_ci } 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci if (!n_cdesc) 4548c2ecf20Sopenharmony_ci first_cdesc = cdesc; 4558c2ecf20Sopenharmony_ci n_cdesc++; 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ci queued -= sglen; 4588c2ecf20Sopenharmony_ci if (!queued) 4598c2ecf20Sopenharmony_ci break; 4608c2ecf20Sopenharmony_ci skip = 0; 4618c2ecf20Sopenharmony_ci } 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_cisend_command: 4648c2ecf20Sopenharmony_ci /* Setup the context options */ 4658c2ecf20Sopenharmony_ci safexcel_context_control(ctx, req, first_cdesc); 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci /* Add the token */ 4688c2ecf20Sopenharmony_ci safexcel_hash_token(first_cdesc, len, req->digest_sz, ctx->cbcmac); 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci req->result_dma = dma_map_single(priv->dev, req->state, req->digest_sz, 4718c2ecf20Sopenharmony_ci DMA_FROM_DEVICE); 4728c2ecf20Sopenharmony_ci if (dma_mapping_error(priv->dev, req->result_dma)) { 4738c2ecf20Sopenharmony_ci ret = -EINVAL; 4748c2ecf20Sopenharmony_ci goto unmap_sg; 4758c2ecf20Sopenharmony_ci } 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci /* Add a result descriptor */ 4788c2ecf20Sopenharmony_ci rdesc = safexcel_add_rdesc(priv, ring, 1, 1, req->result_dma, 4798c2ecf20Sopenharmony_ci req->digest_sz); 4808c2ecf20Sopenharmony_ci if (IS_ERR(rdesc)) { 4818c2ecf20Sopenharmony_ci ret = PTR_ERR(rdesc); 4828c2ecf20Sopenharmony_ci goto unmap_result; 4838c2ecf20Sopenharmony_ci } 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci safexcel_rdr_req_set(priv, ring, rdesc, &areq->base); 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci req->processed += len - extra; 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci *commands = n_cdesc; 4908c2ecf20Sopenharmony_ci *results = 1; 4918c2ecf20Sopenharmony_ci return 0; 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ciunmap_result: 4948c2ecf20Sopenharmony_ci dma_unmap_single(priv->dev, req->result_dma, req->digest_sz, 4958c2ecf20Sopenharmony_ci DMA_FROM_DEVICE); 4968c2ecf20Sopenharmony_ciunmap_sg: 4978c2ecf20Sopenharmony_ci if (req->nents) { 4988c2ecf20Sopenharmony_ci dma_unmap_sg(priv->dev, areq->src, req->nents, DMA_TO_DEVICE); 4998c2ecf20Sopenharmony_ci req->nents = 0; 5008c2ecf20Sopenharmony_ci } 5018c2ecf20Sopenharmony_cicdesc_rollback: 5028c2ecf20Sopenharmony_ci for (i = 0; i < n_cdesc; i++) 5038c2ecf20Sopenharmony_ci safexcel_ring_rollback_wptr(priv, &priv->ring[ring].cdr); 5048c2ecf20Sopenharmony_ciunmap_cache: 5058c2ecf20Sopenharmony_ci if (req->cache_dma) { 5068c2ecf20Sopenharmony_ci dma_unmap_single(priv->dev, req->cache_dma, req->cache_sz, 5078c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 5088c2ecf20Sopenharmony_ci req->cache_dma = 0; 5098c2ecf20Sopenharmony_ci req->cache_sz = 0; 5108c2ecf20Sopenharmony_ci } 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ci return ret; 5138c2ecf20Sopenharmony_ci} 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_cistatic int safexcel_handle_inv_result(struct safexcel_crypto_priv *priv, 5168c2ecf20Sopenharmony_ci int ring, 5178c2ecf20Sopenharmony_ci struct crypto_async_request *async, 5188c2ecf20Sopenharmony_ci bool *should_complete, int *ret) 5198c2ecf20Sopenharmony_ci{ 5208c2ecf20Sopenharmony_ci struct safexcel_result_desc *rdesc; 5218c2ecf20Sopenharmony_ci struct ahash_request *areq = ahash_request_cast(async); 5228c2ecf20Sopenharmony_ci struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); 5238c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(ahash); 5248c2ecf20Sopenharmony_ci int enq_ret; 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci *ret = 0; 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr); 5298c2ecf20Sopenharmony_ci if (IS_ERR(rdesc)) { 5308c2ecf20Sopenharmony_ci dev_err(priv->dev, 5318c2ecf20Sopenharmony_ci "hash: invalidate: could not retrieve the result descriptor\n"); 5328c2ecf20Sopenharmony_ci *ret = PTR_ERR(rdesc); 5338c2ecf20Sopenharmony_ci } else { 5348c2ecf20Sopenharmony_ci *ret = safexcel_rdesc_check_errors(priv, rdesc); 5358c2ecf20Sopenharmony_ci } 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci safexcel_complete(priv, ring); 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci if (ctx->base.exit_inv) { 5408c2ecf20Sopenharmony_ci dma_pool_free(priv->context_pool, ctx->base.ctxr, 5418c2ecf20Sopenharmony_ci ctx->base.ctxr_dma); 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci *should_complete = true; 5448c2ecf20Sopenharmony_ci return 1; 5458c2ecf20Sopenharmony_ci } 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci ring = safexcel_select_ring(priv); 5488c2ecf20Sopenharmony_ci ctx->base.ring = ring; 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci spin_lock_bh(&priv->ring[ring].queue_lock); 5518c2ecf20Sopenharmony_ci enq_ret = crypto_enqueue_request(&priv->ring[ring].queue, async); 5528c2ecf20Sopenharmony_ci spin_unlock_bh(&priv->ring[ring].queue_lock); 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci if (enq_ret != -EINPROGRESS) 5558c2ecf20Sopenharmony_ci *ret = enq_ret; 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci queue_work(priv->ring[ring].workqueue, 5588c2ecf20Sopenharmony_ci &priv->ring[ring].work_data.work); 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ci *should_complete = false; 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci return 1; 5638c2ecf20Sopenharmony_ci} 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_cistatic int safexcel_handle_result(struct safexcel_crypto_priv *priv, int ring, 5668c2ecf20Sopenharmony_ci struct crypto_async_request *async, 5678c2ecf20Sopenharmony_ci bool *should_complete, int *ret) 5688c2ecf20Sopenharmony_ci{ 5698c2ecf20Sopenharmony_ci struct ahash_request *areq = ahash_request_cast(async); 5708c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx(areq); 5718c2ecf20Sopenharmony_ci int err; 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ci BUG_ON(!(priv->flags & EIP197_TRC_CACHE) && req->needs_inv); 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci if (req->needs_inv) { 5768c2ecf20Sopenharmony_ci req->needs_inv = false; 5778c2ecf20Sopenharmony_ci err = safexcel_handle_inv_result(priv, ring, async, 5788c2ecf20Sopenharmony_ci should_complete, ret); 5798c2ecf20Sopenharmony_ci } else { 5808c2ecf20Sopenharmony_ci err = safexcel_handle_req_result(priv, ring, async, 5818c2ecf20Sopenharmony_ci should_complete, ret); 5828c2ecf20Sopenharmony_ci } 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci return err; 5858c2ecf20Sopenharmony_ci} 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_cistatic int safexcel_ahash_send_inv(struct crypto_async_request *async, 5888c2ecf20Sopenharmony_ci int ring, int *commands, int *results) 5898c2ecf20Sopenharmony_ci{ 5908c2ecf20Sopenharmony_ci struct ahash_request *areq = ahash_request_cast(async); 5918c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 5928c2ecf20Sopenharmony_ci int ret; 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_ci ret = safexcel_invalidate_cache(async, ctx->base.priv, 5958c2ecf20Sopenharmony_ci ctx->base.ctxr_dma, ring); 5968c2ecf20Sopenharmony_ci if (unlikely(ret)) 5978c2ecf20Sopenharmony_ci return ret; 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci *commands = 1; 6008c2ecf20Sopenharmony_ci *results = 1; 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_ci return 0; 6038c2ecf20Sopenharmony_ci} 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_cistatic int safexcel_ahash_send(struct crypto_async_request *async, 6068c2ecf20Sopenharmony_ci int ring, int *commands, int *results) 6078c2ecf20Sopenharmony_ci{ 6088c2ecf20Sopenharmony_ci struct ahash_request *areq = ahash_request_cast(async); 6098c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx(areq); 6108c2ecf20Sopenharmony_ci int ret; 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci if (req->needs_inv) 6138c2ecf20Sopenharmony_ci ret = safexcel_ahash_send_inv(async, ring, commands, results); 6148c2ecf20Sopenharmony_ci else 6158c2ecf20Sopenharmony_ci ret = safexcel_ahash_send_req(async, ring, commands, results); 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_ci return ret; 6188c2ecf20Sopenharmony_ci} 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_cistatic int safexcel_ahash_exit_inv(struct crypto_tfm *tfm) 6218c2ecf20Sopenharmony_ci{ 6228c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 6238c2ecf20Sopenharmony_ci struct safexcel_crypto_priv *priv = ctx->base.priv; 6248c2ecf20Sopenharmony_ci EIP197_REQUEST_ON_STACK(req, ahash, EIP197_AHASH_REQ_SIZE); 6258c2ecf20Sopenharmony_ci struct safexcel_ahash_req *rctx = ahash_request_ctx(req); 6268c2ecf20Sopenharmony_ci struct safexcel_inv_result result = {}; 6278c2ecf20Sopenharmony_ci int ring = ctx->base.ring; 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_ci memset(req, 0, EIP197_AHASH_REQ_SIZE); 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci /* create invalidation request */ 6328c2ecf20Sopenharmony_ci init_completion(&result.completion); 6338c2ecf20Sopenharmony_ci ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, 6348c2ecf20Sopenharmony_ci safexcel_inv_complete, &result); 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci ahash_request_set_tfm(req, __crypto_ahash_cast(tfm)); 6378c2ecf20Sopenharmony_ci ctx = crypto_tfm_ctx(req->base.tfm); 6388c2ecf20Sopenharmony_ci ctx->base.exit_inv = true; 6398c2ecf20Sopenharmony_ci rctx->needs_inv = true; 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci spin_lock_bh(&priv->ring[ring].queue_lock); 6428c2ecf20Sopenharmony_ci crypto_enqueue_request(&priv->ring[ring].queue, &req->base); 6438c2ecf20Sopenharmony_ci spin_unlock_bh(&priv->ring[ring].queue_lock); 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci queue_work(priv->ring[ring].workqueue, 6468c2ecf20Sopenharmony_ci &priv->ring[ring].work_data.work); 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci wait_for_completion(&result.completion); 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_ci if (result.error) { 6518c2ecf20Sopenharmony_ci dev_warn(priv->dev, "hash: completion error (%d)\n", 6528c2ecf20Sopenharmony_ci result.error); 6538c2ecf20Sopenharmony_ci return result.error; 6548c2ecf20Sopenharmony_ci } 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci return 0; 6578c2ecf20Sopenharmony_ci} 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_ci/* safexcel_ahash_cache: cache data until at least one request can be sent to 6608c2ecf20Sopenharmony_ci * the engine, aka. when there is at least 1 block size in the pipe. 6618c2ecf20Sopenharmony_ci */ 6628c2ecf20Sopenharmony_cistatic int safexcel_ahash_cache(struct ahash_request *areq) 6638c2ecf20Sopenharmony_ci{ 6648c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx(areq); 6658c2ecf20Sopenharmony_ci u64 cache_len; 6668c2ecf20Sopenharmony_ci 6678c2ecf20Sopenharmony_ci /* cache_len: everything accepted by the driver but not sent yet, 6688c2ecf20Sopenharmony_ci * tot sz handled by update() - last req sz - tot sz handled by send() 6698c2ecf20Sopenharmony_ci */ 6708c2ecf20Sopenharmony_ci cache_len = safexcel_queued_len(req); 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_ci /* 6738c2ecf20Sopenharmony_ci * In case there isn't enough bytes to proceed (less than a 6748c2ecf20Sopenharmony_ci * block size), cache the data until we have enough. 6758c2ecf20Sopenharmony_ci */ 6768c2ecf20Sopenharmony_ci if (cache_len + areq->nbytes <= HASH_CACHE_SIZE) { 6778c2ecf20Sopenharmony_ci sg_pcopy_to_buffer(areq->src, sg_nents(areq->src), 6788c2ecf20Sopenharmony_ci req->cache + cache_len, 6798c2ecf20Sopenharmony_ci areq->nbytes, 0); 6808c2ecf20Sopenharmony_ci return 0; 6818c2ecf20Sopenharmony_ci } 6828c2ecf20Sopenharmony_ci 6838c2ecf20Sopenharmony_ci /* We couldn't cache all the data */ 6848c2ecf20Sopenharmony_ci return -E2BIG; 6858c2ecf20Sopenharmony_ci} 6868c2ecf20Sopenharmony_ci 6878c2ecf20Sopenharmony_cistatic int safexcel_ahash_enqueue(struct ahash_request *areq) 6888c2ecf20Sopenharmony_ci{ 6898c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 6908c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx(areq); 6918c2ecf20Sopenharmony_ci struct safexcel_crypto_priv *priv = ctx->base.priv; 6928c2ecf20Sopenharmony_ci int ret, ring; 6938c2ecf20Sopenharmony_ci 6948c2ecf20Sopenharmony_ci req->needs_inv = false; 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_ci if (ctx->base.ctxr) { 6978c2ecf20Sopenharmony_ci if (priv->flags & EIP197_TRC_CACHE && !ctx->base.needs_inv && 6988c2ecf20Sopenharmony_ci /* invalidate for *any* non-XCBC continuation */ 6998c2ecf20Sopenharmony_ci ((req->not_first && !req->xcbcmac) || 7008c2ecf20Sopenharmony_ci /* invalidate if (i)digest changed */ 7018c2ecf20Sopenharmony_ci memcmp(ctx->base.ctxr->data, req->state, req->state_sz) || 7028c2ecf20Sopenharmony_ci /* invalidate for HMAC finish with odigest changed */ 7038c2ecf20Sopenharmony_ci (req->finish && req->hmac && 7048c2ecf20Sopenharmony_ci memcmp(ctx->base.ctxr->data + (req->state_sz>>2), 7058c2ecf20Sopenharmony_ci &ctx->base.opad, req->state_sz)))) 7068c2ecf20Sopenharmony_ci /* 7078c2ecf20Sopenharmony_ci * We're still setting needs_inv here, even though it is 7088c2ecf20Sopenharmony_ci * cleared right away, because the needs_inv flag can be 7098c2ecf20Sopenharmony_ci * set in other functions and we want to keep the same 7108c2ecf20Sopenharmony_ci * logic. 7118c2ecf20Sopenharmony_ci */ 7128c2ecf20Sopenharmony_ci ctx->base.needs_inv = true; 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_ci if (ctx->base.needs_inv) { 7158c2ecf20Sopenharmony_ci ctx->base.needs_inv = false; 7168c2ecf20Sopenharmony_ci req->needs_inv = true; 7178c2ecf20Sopenharmony_ci } 7188c2ecf20Sopenharmony_ci } else { 7198c2ecf20Sopenharmony_ci ctx->base.ring = safexcel_select_ring(priv); 7208c2ecf20Sopenharmony_ci ctx->base.ctxr = dma_pool_zalloc(priv->context_pool, 7218c2ecf20Sopenharmony_ci EIP197_GFP_FLAGS(areq->base), 7228c2ecf20Sopenharmony_ci &ctx->base.ctxr_dma); 7238c2ecf20Sopenharmony_ci if (!ctx->base.ctxr) 7248c2ecf20Sopenharmony_ci return -ENOMEM; 7258c2ecf20Sopenharmony_ci } 7268c2ecf20Sopenharmony_ci req->not_first = true; 7278c2ecf20Sopenharmony_ci 7288c2ecf20Sopenharmony_ci ring = ctx->base.ring; 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_ci spin_lock_bh(&priv->ring[ring].queue_lock); 7318c2ecf20Sopenharmony_ci ret = crypto_enqueue_request(&priv->ring[ring].queue, &areq->base); 7328c2ecf20Sopenharmony_ci spin_unlock_bh(&priv->ring[ring].queue_lock); 7338c2ecf20Sopenharmony_ci 7348c2ecf20Sopenharmony_ci queue_work(priv->ring[ring].workqueue, 7358c2ecf20Sopenharmony_ci &priv->ring[ring].work_data.work); 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_ci return ret; 7388c2ecf20Sopenharmony_ci} 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_cistatic int safexcel_ahash_update(struct ahash_request *areq) 7418c2ecf20Sopenharmony_ci{ 7428c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx(areq); 7438c2ecf20Sopenharmony_ci int ret; 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_ci /* If the request is 0 length, do nothing */ 7468c2ecf20Sopenharmony_ci if (!areq->nbytes) 7478c2ecf20Sopenharmony_ci return 0; 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci /* Add request to the cache if it fits */ 7508c2ecf20Sopenharmony_ci ret = safexcel_ahash_cache(areq); 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_ci /* Update total request length */ 7538c2ecf20Sopenharmony_ci req->len += areq->nbytes; 7548c2ecf20Sopenharmony_ci 7558c2ecf20Sopenharmony_ci /* If not all data could fit into the cache, go process the excess. 7568c2ecf20Sopenharmony_ci * Also go process immediately for an HMAC IV precompute, which 7578c2ecf20Sopenharmony_ci * will never be finished at all, but needs to be processed anyway. 7588c2ecf20Sopenharmony_ci */ 7598c2ecf20Sopenharmony_ci if ((ret && !req->finish) || req->last_req) 7608c2ecf20Sopenharmony_ci return safexcel_ahash_enqueue(areq); 7618c2ecf20Sopenharmony_ci 7628c2ecf20Sopenharmony_ci return 0; 7638c2ecf20Sopenharmony_ci} 7648c2ecf20Sopenharmony_ci 7658c2ecf20Sopenharmony_cistatic int safexcel_ahash_final(struct ahash_request *areq) 7668c2ecf20Sopenharmony_ci{ 7678c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx(areq); 7688c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 7698c2ecf20Sopenharmony_ci 7708c2ecf20Sopenharmony_ci req->finish = true; 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_ci if (unlikely(!req->len && !areq->nbytes)) { 7738c2ecf20Sopenharmony_ci /* 7748c2ecf20Sopenharmony_ci * If we have an overall 0 length *hash* request: 7758c2ecf20Sopenharmony_ci * The HW cannot do 0 length hash, so we provide the correct 7768c2ecf20Sopenharmony_ci * result directly here. 7778c2ecf20Sopenharmony_ci */ 7788c2ecf20Sopenharmony_ci if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_MD5) 7798c2ecf20Sopenharmony_ci memcpy(areq->result, md5_zero_message_hash, 7808c2ecf20Sopenharmony_ci MD5_DIGEST_SIZE); 7818c2ecf20Sopenharmony_ci else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA1) 7828c2ecf20Sopenharmony_ci memcpy(areq->result, sha1_zero_message_hash, 7838c2ecf20Sopenharmony_ci SHA1_DIGEST_SIZE); 7848c2ecf20Sopenharmony_ci else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA224) 7858c2ecf20Sopenharmony_ci memcpy(areq->result, sha224_zero_message_hash, 7868c2ecf20Sopenharmony_ci SHA224_DIGEST_SIZE); 7878c2ecf20Sopenharmony_ci else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA256) 7888c2ecf20Sopenharmony_ci memcpy(areq->result, sha256_zero_message_hash, 7898c2ecf20Sopenharmony_ci SHA256_DIGEST_SIZE); 7908c2ecf20Sopenharmony_ci else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA384) 7918c2ecf20Sopenharmony_ci memcpy(areq->result, sha384_zero_message_hash, 7928c2ecf20Sopenharmony_ci SHA384_DIGEST_SIZE); 7938c2ecf20Sopenharmony_ci else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA512) 7948c2ecf20Sopenharmony_ci memcpy(areq->result, sha512_zero_message_hash, 7958c2ecf20Sopenharmony_ci SHA512_DIGEST_SIZE); 7968c2ecf20Sopenharmony_ci else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SM3) { 7978c2ecf20Sopenharmony_ci memcpy(areq->result, 7988c2ecf20Sopenharmony_ci EIP197_SM3_ZEROM_HASH, SM3_DIGEST_SIZE); 7998c2ecf20Sopenharmony_ci } 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ci return 0; 8028c2ecf20Sopenharmony_ci } else if (unlikely(req->digest == CONTEXT_CONTROL_DIGEST_XCM && 8038c2ecf20Sopenharmony_ci ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_MD5 && 8048c2ecf20Sopenharmony_ci req->len == sizeof(u32) && !areq->nbytes)) { 8058c2ecf20Sopenharmony_ci /* Zero length CRC32 */ 8068c2ecf20Sopenharmony_ci memcpy(areq->result, &ctx->base.ipad, sizeof(u32)); 8078c2ecf20Sopenharmony_ci return 0; 8088c2ecf20Sopenharmony_ci } else if (unlikely(ctx->cbcmac && req->len == AES_BLOCK_SIZE && 8098c2ecf20Sopenharmony_ci !areq->nbytes)) { 8108c2ecf20Sopenharmony_ci /* Zero length CBC MAC */ 8118c2ecf20Sopenharmony_ci memset(areq->result, 0, AES_BLOCK_SIZE); 8128c2ecf20Sopenharmony_ci return 0; 8138c2ecf20Sopenharmony_ci } else if (unlikely(req->xcbcmac && req->len == AES_BLOCK_SIZE && 8148c2ecf20Sopenharmony_ci !areq->nbytes)) { 8158c2ecf20Sopenharmony_ci /* Zero length (X)CBC/CMAC */ 8168c2ecf20Sopenharmony_ci int i; 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_ci for (i = 0; i < AES_BLOCK_SIZE / sizeof(u32); i++) { 8198c2ecf20Sopenharmony_ci u32 *result = (void *)areq->result; 8208c2ecf20Sopenharmony_ci 8218c2ecf20Sopenharmony_ci /* K3 */ 8228c2ecf20Sopenharmony_ci result[i] = swab32(ctx->base.ipad.word[i + 4]); 8238c2ecf20Sopenharmony_ci } 8248c2ecf20Sopenharmony_ci areq->result[0] ^= 0x80; // 10- padding 8258c2ecf20Sopenharmony_ci crypto_cipher_encrypt_one(ctx->kaes, areq->result, areq->result); 8268c2ecf20Sopenharmony_ci return 0; 8278c2ecf20Sopenharmony_ci } else if (unlikely(req->hmac && 8288c2ecf20Sopenharmony_ci (req->len == req->block_sz) && 8298c2ecf20Sopenharmony_ci !areq->nbytes)) { 8308c2ecf20Sopenharmony_ci /* 8318c2ecf20Sopenharmony_ci * If we have an overall 0 length *HMAC* request: 8328c2ecf20Sopenharmony_ci * For HMAC, we need to finalize the inner digest 8338c2ecf20Sopenharmony_ci * and then perform the outer hash. 8348c2ecf20Sopenharmony_ci */ 8358c2ecf20Sopenharmony_ci 8368c2ecf20Sopenharmony_ci /* generate pad block in the cache */ 8378c2ecf20Sopenharmony_ci /* start with a hash block of all zeroes */ 8388c2ecf20Sopenharmony_ci memset(req->cache, 0, req->block_sz); 8398c2ecf20Sopenharmony_ci /* set the first byte to 0x80 to 'append a 1 bit' */ 8408c2ecf20Sopenharmony_ci req->cache[0] = 0x80; 8418c2ecf20Sopenharmony_ci /* add the length in bits in the last 2 bytes */ 8428c2ecf20Sopenharmony_ci if (req->len_is_le) { 8438c2ecf20Sopenharmony_ci /* Little endian length word (e.g. MD5) */ 8448c2ecf20Sopenharmony_ci req->cache[req->block_sz-8] = (req->block_sz << 3) & 8458c2ecf20Sopenharmony_ci 255; 8468c2ecf20Sopenharmony_ci req->cache[req->block_sz-7] = (req->block_sz >> 5); 8478c2ecf20Sopenharmony_ci } else { 8488c2ecf20Sopenharmony_ci /* Big endian length word (e.g. any SHA) */ 8498c2ecf20Sopenharmony_ci req->cache[req->block_sz-2] = (req->block_sz >> 5); 8508c2ecf20Sopenharmony_ci req->cache[req->block_sz-1] = (req->block_sz << 3) & 8518c2ecf20Sopenharmony_ci 255; 8528c2ecf20Sopenharmony_ci } 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_ci req->len += req->block_sz; /* plus 1 hash block */ 8558c2ecf20Sopenharmony_ci 8568c2ecf20Sopenharmony_ci /* Set special zero-length HMAC flag */ 8578c2ecf20Sopenharmony_ci req->hmac_zlen = true; 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_ci /* Finalize HMAC */ 8608c2ecf20Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_HMAC; 8618c2ecf20Sopenharmony_ci } else if (req->hmac) { 8628c2ecf20Sopenharmony_ci /* Finalize HMAC */ 8638c2ecf20Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_HMAC; 8648c2ecf20Sopenharmony_ci } 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_ci return safexcel_ahash_enqueue(areq); 8678c2ecf20Sopenharmony_ci} 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_cistatic int safexcel_ahash_finup(struct ahash_request *areq) 8708c2ecf20Sopenharmony_ci{ 8718c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx(areq); 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_ci req->finish = true; 8748c2ecf20Sopenharmony_ci 8758c2ecf20Sopenharmony_ci safexcel_ahash_update(areq); 8768c2ecf20Sopenharmony_ci return safexcel_ahash_final(areq); 8778c2ecf20Sopenharmony_ci} 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_cistatic int safexcel_ahash_export(struct ahash_request *areq, void *out) 8808c2ecf20Sopenharmony_ci{ 8818c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx(areq); 8828c2ecf20Sopenharmony_ci struct safexcel_ahash_export_state *export = out; 8838c2ecf20Sopenharmony_ci 8848c2ecf20Sopenharmony_ci export->len = req->len; 8858c2ecf20Sopenharmony_ci export->processed = req->processed; 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_ci export->digest = req->digest; 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_ci memcpy(export->state, req->state, req->state_sz); 8908c2ecf20Sopenharmony_ci memcpy(export->cache, req->cache, HASH_CACHE_SIZE); 8918c2ecf20Sopenharmony_ci 8928c2ecf20Sopenharmony_ci return 0; 8938c2ecf20Sopenharmony_ci} 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_cistatic int safexcel_ahash_import(struct ahash_request *areq, const void *in) 8968c2ecf20Sopenharmony_ci{ 8978c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx(areq); 8988c2ecf20Sopenharmony_ci const struct safexcel_ahash_export_state *export = in; 8998c2ecf20Sopenharmony_ci int ret; 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_ci ret = crypto_ahash_init(areq); 9028c2ecf20Sopenharmony_ci if (ret) 9038c2ecf20Sopenharmony_ci return ret; 9048c2ecf20Sopenharmony_ci 9058c2ecf20Sopenharmony_ci req->len = export->len; 9068c2ecf20Sopenharmony_ci req->processed = export->processed; 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_ci req->digest = export->digest; 9098c2ecf20Sopenharmony_ci 9108c2ecf20Sopenharmony_ci memcpy(req->cache, export->cache, HASH_CACHE_SIZE); 9118c2ecf20Sopenharmony_ci memcpy(req->state, export->state, req->state_sz); 9128c2ecf20Sopenharmony_ci 9138c2ecf20Sopenharmony_ci return 0; 9148c2ecf20Sopenharmony_ci} 9158c2ecf20Sopenharmony_ci 9168c2ecf20Sopenharmony_cistatic int safexcel_ahash_cra_init(struct crypto_tfm *tfm) 9178c2ecf20Sopenharmony_ci{ 9188c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 9198c2ecf20Sopenharmony_ci struct safexcel_alg_template *tmpl = 9208c2ecf20Sopenharmony_ci container_of(__crypto_ahash_alg(tfm->__crt_alg), 9218c2ecf20Sopenharmony_ci struct safexcel_alg_template, alg.ahash); 9228c2ecf20Sopenharmony_ci 9238c2ecf20Sopenharmony_ci ctx->base.priv = tmpl->priv; 9248c2ecf20Sopenharmony_ci ctx->base.send = safexcel_ahash_send; 9258c2ecf20Sopenharmony_ci ctx->base.handle_result = safexcel_handle_result; 9268c2ecf20Sopenharmony_ci ctx->fb_do_setkey = false; 9278c2ecf20Sopenharmony_ci 9288c2ecf20Sopenharmony_ci crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), 9298c2ecf20Sopenharmony_ci sizeof(struct safexcel_ahash_req)); 9308c2ecf20Sopenharmony_ci return 0; 9318c2ecf20Sopenharmony_ci} 9328c2ecf20Sopenharmony_ci 9338c2ecf20Sopenharmony_cistatic int safexcel_sha1_init(struct ahash_request *areq) 9348c2ecf20Sopenharmony_ci{ 9358c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 9368c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx(areq); 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_ci memset(req, 0, sizeof(*req)); 9398c2ecf20Sopenharmony_ci 9408c2ecf20Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1; 9418c2ecf20Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 9428c2ecf20Sopenharmony_ci req->state_sz = SHA1_DIGEST_SIZE; 9438c2ecf20Sopenharmony_ci req->digest_sz = SHA1_DIGEST_SIZE; 9448c2ecf20Sopenharmony_ci req->block_sz = SHA1_BLOCK_SIZE; 9458c2ecf20Sopenharmony_ci 9468c2ecf20Sopenharmony_ci return 0; 9478c2ecf20Sopenharmony_ci} 9488c2ecf20Sopenharmony_ci 9498c2ecf20Sopenharmony_cistatic int safexcel_sha1_digest(struct ahash_request *areq) 9508c2ecf20Sopenharmony_ci{ 9518c2ecf20Sopenharmony_ci int ret = safexcel_sha1_init(areq); 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ci if (ret) 9548c2ecf20Sopenharmony_ci return ret; 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_ci return safexcel_ahash_finup(areq); 9578c2ecf20Sopenharmony_ci} 9588c2ecf20Sopenharmony_ci 9598c2ecf20Sopenharmony_cistatic void safexcel_ahash_cra_exit(struct crypto_tfm *tfm) 9608c2ecf20Sopenharmony_ci{ 9618c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 9628c2ecf20Sopenharmony_ci struct safexcel_crypto_priv *priv = ctx->base.priv; 9638c2ecf20Sopenharmony_ci int ret; 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_ci /* context not allocated, skip invalidation */ 9668c2ecf20Sopenharmony_ci if (!ctx->base.ctxr) 9678c2ecf20Sopenharmony_ci return; 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_ci if (priv->flags & EIP197_TRC_CACHE) { 9708c2ecf20Sopenharmony_ci ret = safexcel_ahash_exit_inv(tfm); 9718c2ecf20Sopenharmony_ci if (ret) 9728c2ecf20Sopenharmony_ci dev_warn(priv->dev, "hash: invalidation error %d\n", ret); 9738c2ecf20Sopenharmony_ci } else { 9748c2ecf20Sopenharmony_ci dma_pool_free(priv->context_pool, ctx->base.ctxr, 9758c2ecf20Sopenharmony_ci ctx->base.ctxr_dma); 9768c2ecf20Sopenharmony_ci } 9778c2ecf20Sopenharmony_ci} 9788c2ecf20Sopenharmony_ci 9798c2ecf20Sopenharmony_cistruct safexcel_alg_template safexcel_alg_sha1 = { 9808c2ecf20Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 9818c2ecf20Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA1, 9828c2ecf20Sopenharmony_ci .alg.ahash = { 9838c2ecf20Sopenharmony_ci .init = safexcel_sha1_init, 9848c2ecf20Sopenharmony_ci .update = safexcel_ahash_update, 9858c2ecf20Sopenharmony_ci .final = safexcel_ahash_final, 9868c2ecf20Sopenharmony_ci .finup = safexcel_ahash_finup, 9878c2ecf20Sopenharmony_ci .digest = safexcel_sha1_digest, 9888c2ecf20Sopenharmony_ci .export = safexcel_ahash_export, 9898c2ecf20Sopenharmony_ci .import = safexcel_ahash_import, 9908c2ecf20Sopenharmony_ci .halg = { 9918c2ecf20Sopenharmony_ci .digestsize = SHA1_DIGEST_SIZE, 9928c2ecf20Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 9938c2ecf20Sopenharmony_ci .base = { 9948c2ecf20Sopenharmony_ci .cra_name = "sha1", 9958c2ecf20Sopenharmony_ci .cra_driver_name = "safexcel-sha1", 9968c2ecf20Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 9978c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 9988c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 9998c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 10008c2ecf20Sopenharmony_ci .cra_blocksize = SHA1_BLOCK_SIZE, 10018c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 10028c2ecf20Sopenharmony_ci .cra_init = safexcel_ahash_cra_init, 10038c2ecf20Sopenharmony_ci .cra_exit = safexcel_ahash_cra_exit, 10048c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 10058c2ecf20Sopenharmony_ci }, 10068c2ecf20Sopenharmony_ci }, 10078c2ecf20Sopenharmony_ci }, 10088c2ecf20Sopenharmony_ci}; 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_cistatic int safexcel_hmac_sha1_init(struct ahash_request *areq) 10118c2ecf20Sopenharmony_ci{ 10128c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 10138c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx(areq); 10148c2ecf20Sopenharmony_ci 10158c2ecf20Sopenharmony_ci memset(req, 0, sizeof(*req)); 10168c2ecf20Sopenharmony_ci 10178c2ecf20Sopenharmony_ci /* Start from ipad precompute */ 10188c2ecf20Sopenharmony_ci memcpy(req->state, &ctx->base.ipad, SHA1_DIGEST_SIZE); 10198c2ecf20Sopenharmony_ci /* Already processed the key^ipad part now! */ 10208c2ecf20Sopenharmony_ci req->len = SHA1_BLOCK_SIZE; 10218c2ecf20Sopenharmony_ci req->processed = SHA1_BLOCK_SIZE; 10228c2ecf20Sopenharmony_ci 10238c2ecf20Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1; 10248c2ecf20Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 10258c2ecf20Sopenharmony_ci req->state_sz = SHA1_DIGEST_SIZE; 10268c2ecf20Sopenharmony_ci req->digest_sz = SHA1_DIGEST_SIZE; 10278c2ecf20Sopenharmony_ci req->block_sz = SHA1_BLOCK_SIZE; 10288c2ecf20Sopenharmony_ci req->hmac = true; 10298c2ecf20Sopenharmony_ci 10308c2ecf20Sopenharmony_ci return 0; 10318c2ecf20Sopenharmony_ci} 10328c2ecf20Sopenharmony_ci 10338c2ecf20Sopenharmony_cistatic int safexcel_hmac_sha1_digest(struct ahash_request *areq) 10348c2ecf20Sopenharmony_ci{ 10358c2ecf20Sopenharmony_ci int ret = safexcel_hmac_sha1_init(areq); 10368c2ecf20Sopenharmony_ci 10378c2ecf20Sopenharmony_ci if (ret) 10388c2ecf20Sopenharmony_ci return ret; 10398c2ecf20Sopenharmony_ci 10408c2ecf20Sopenharmony_ci return safexcel_ahash_finup(areq); 10418c2ecf20Sopenharmony_ci} 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_cistruct safexcel_ahash_result { 10448c2ecf20Sopenharmony_ci struct completion completion; 10458c2ecf20Sopenharmony_ci int error; 10468c2ecf20Sopenharmony_ci}; 10478c2ecf20Sopenharmony_ci 10488c2ecf20Sopenharmony_cistatic void safexcel_ahash_complete(struct crypto_async_request *req, int error) 10498c2ecf20Sopenharmony_ci{ 10508c2ecf20Sopenharmony_ci struct safexcel_ahash_result *result = req->data; 10518c2ecf20Sopenharmony_ci 10528c2ecf20Sopenharmony_ci if (error == -EINPROGRESS) 10538c2ecf20Sopenharmony_ci return; 10548c2ecf20Sopenharmony_ci 10558c2ecf20Sopenharmony_ci result->error = error; 10568c2ecf20Sopenharmony_ci complete(&result->completion); 10578c2ecf20Sopenharmony_ci} 10588c2ecf20Sopenharmony_ci 10598c2ecf20Sopenharmony_cistatic int safexcel_hmac_init_pad(struct ahash_request *areq, 10608c2ecf20Sopenharmony_ci unsigned int blocksize, const u8 *key, 10618c2ecf20Sopenharmony_ci unsigned int keylen, u8 *ipad, u8 *opad) 10628c2ecf20Sopenharmony_ci{ 10638c2ecf20Sopenharmony_ci struct safexcel_ahash_result result; 10648c2ecf20Sopenharmony_ci struct scatterlist sg; 10658c2ecf20Sopenharmony_ci int ret, i; 10668c2ecf20Sopenharmony_ci u8 *keydup; 10678c2ecf20Sopenharmony_ci 10688c2ecf20Sopenharmony_ci if (keylen <= blocksize) { 10698c2ecf20Sopenharmony_ci memcpy(ipad, key, keylen); 10708c2ecf20Sopenharmony_ci } else { 10718c2ecf20Sopenharmony_ci keydup = kmemdup(key, keylen, GFP_KERNEL); 10728c2ecf20Sopenharmony_ci if (!keydup) 10738c2ecf20Sopenharmony_ci return -ENOMEM; 10748c2ecf20Sopenharmony_ci 10758c2ecf20Sopenharmony_ci ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_BACKLOG, 10768c2ecf20Sopenharmony_ci safexcel_ahash_complete, &result); 10778c2ecf20Sopenharmony_ci sg_init_one(&sg, keydup, keylen); 10788c2ecf20Sopenharmony_ci ahash_request_set_crypt(areq, &sg, ipad, keylen); 10798c2ecf20Sopenharmony_ci init_completion(&result.completion); 10808c2ecf20Sopenharmony_ci 10818c2ecf20Sopenharmony_ci ret = crypto_ahash_digest(areq); 10828c2ecf20Sopenharmony_ci if (ret == -EINPROGRESS || ret == -EBUSY) { 10838c2ecf20Sopenharmony_ci wait_for_completion_interruptible(&result.completion); 10848c2ecf20Sopenharmony_ci ret = result.error; 10858c2ecf20Sopenharmony_ci } 10868c2ecf20Sopenharmony_ci 10878c2ecf20Sopenharmony_ci /* Avoid leaking */ 10888c2ecf20Sopenharmony_ci kfree_sensitive(keydup); 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_ci if (ret) 10918c2ecf20Sopenharmony_ci return ret; 10928c2ecf20Sopenharmony_ci 10938c2ecf20Sopenharmony_ci keylen = crypto_ahash_digestsize(crypto_ahash_reqtfm(areq)); 10948c2ecf20Sopenharmony_ci } 10958c2ecf20Sopenharmony_ci 10968c2ecf20Sopenharmony_ci memset(ipad + keylen, 0, blocksize - keylen); 10978c2ecf20Sopenharmony_ci memcpy(opad, ipad, blocksize); 10988c2ecf20Sopenharmony_ci 10998c2ecf20Sopenharmony_ci for (i = 0; i < blocksize; i++) { 11008c2ecf20Sopenharmony_ci ipad[i] ^= HMAC_IPAD_VALUE; 11018c2ecf20Sopenharmony_ci opad[i] ^= HMAC_OPAD_VALUE; 11028c2ecf20Sopenharmony_ci } 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_ci return 0; 11058c2ecf20Sopenharmony_ci} 11068c2ecf20Sopenharmony_ci 11078c2ecf20Sopenharmony_cistatic int safexcel_hmac_init_iv(struct ahash_request *areq, 11088c2ecf20Sopenharmony_ci unsigned int blocksize, u8 *pad, void *state) 11098c2ecf20Sopenharmony_ci{ 11108c2ecf20Sopenharmony_ci struct safexcel_ahash_result result; 11118c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req; 11128c2ecf20Sopenharmony_ci struct scatterlist sg; 11138c2ecf20Sopenharmony_ci int ret; 11148c2ecf20Sopenharmony_ci 11158c2ecf20Sopenharmony_ci ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_BACKLOG, 11168c2ecf20Sopenharmony_ci safexcel_ahash_complete, &result); 11178c2ecf20Sopenharmony_ci sg_init_one(&sg, pad, blocksize); 11188c2ecf20Sopenharmony_ci ahash_request_set_crypt(areq, &sg, pad, blocksize); 11198c2ecf20Sopenharmony_ci init_completion(&result.completion); 11208c2ecf20Sopenharmony_ci 11218c2ecf20Sopenharmony_ci ret = crypto_ahash_init(areq); 11228c2ecf20Sopenharmony_ci if (ret) 11238c2ecf20Sopenharmony_ci return ret; 11248c2ecf20Sopenharmony_ci 11258c2ecf20Sopenharmony_ci req = ahash_request_ctx(areq); 11268c2ecf20Sopenharmony_ci req->hmac = true; 11278c2ecf20Sopenharmony_ci req->last_req = true; 11288c2ecf20Sopenharmony_ci 11298c2ecf20Sopenharmony_ci ret = crypto_ahash_update(areq); 11308c2ecf20Sopenharmony_ci if (ret && ret != -EINPROGRESS && ret != -EBUSY) 11318c2ecf20Sopenharmony_ci return ret; 11328c2ecf20Sopenharmony_ci 11338c2ecf20Sopenharmony_ci wait_for_completion_interruptible(&result.completion); 11348c2ecf20Sopenharmony_ci if (result.error) 11358c2ecf20Sopenharmony_ci return result.error; 11368c2ecf20Sopenharmony_ci 11378c2ecf20Sopenharmony_ci return crypto_ahash_export(areq, state); 11388c2ecf20Sopenharmony_ci} 11398c2ecf20Sopenharmony_ci 11408c2ecf20Sopenharmony_cistatic int __safexcel_hmac_setkey(const char *alg, const u8 *key, 11418c2ecf20Sopenharmony_ci unsigned int keylen, 11428c2ecf20Sopenharmony_ci void *istate, void *ostate) 11438c2ecf20Sopenharmony_ci{ 11448c2ecf20Sopenharmony_ci struct ahash_request *areq; 11458c2ecf20Sopenharmony_ci struct crypto_ahash *tfm; 11468c2ecf20Sopenharmony_ci unsigned int blocksize; 11478c2ecf20Sopenharmony_ci u8 *ipad, *opad; 11488c2ecf20Sopenharmony_ci int ret; 11498c2ecf20Sopenharmony_ci 11508c2ecf20Sopenharmony_ci tfm = crypto_alloc_ahash(alg, 0, 0); 11518c2ecf20Sopenharmony_ci if (IS_ERR(tfm)) 11528c2ecf20Sopenharmony_ci return PTR_ERR(tfm); 11538c2ecf20Sopenharmony_ci 11548c2ecf20Sopenharmony_ci areq = ahash_request_alloc(tfm, GFP_KERNEL); 11558c2ecf20Sopenharmony_ci if (!areq) { 11568c2ecf20Sopenharmony_ci ret = -ENOMEM; 11578c2ecf20Sopenharmony_ci goto free_ahash; 11588c2ecf20Sopenharmony_ci } 11598c2ecf20Sopenharmony_ci 11608c2ecf20Sopenharmony_ci crypto_ahash_clear_flags(tfm, ~0); 11618c2ecf20Sopenharmony_ci blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); 11628c2ecf20Sopenharmony_ci 11638c2ecf20Sopenharmony_ci ipad = kcalloc(2, blocksize, GFP_KERNEL); 11648c2ecf20Sopenharmony_ci if (!ipad) { 11658c2ecf20Sopenharmony_ci ret = -ENOMEM; 11668c2ecf20Sopenharmony_ci goto free_request; 11678c2ecf20Sopenharmony_ci } 11688c2ecf20Sopenharmony_ci 11698c2ecf20Sopenharmony_ci opad = ipad + blocksize; 11708c2ecf20Sopenharmony_ci 11718c2ecf20Sopenharmony_ci ret = safexcel_hmac_init_pad(areq, blocksize, key, keylen, ipad, opad); 11728c2ecf20Sopenharmony_ci if (ret) 11738c2ecf20Sopenharmony_ci goto free_ipad; 11748c2ecf20Sopenharmony_ci 11758c2ecf20Sopenharmony_ci ret = safexcel_hmac_init_iv(areq, blocksize, ipad, istate); 11768c2ecf20Sopenharmony_ci if (ret) 11778c2ecf20Sopenharmony_ci goto free_ipad; 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_ci ret = safexcel_hmac_init_iv(areq, blocksize, opad, ostate); 11808c2ecf20Sopenharmony_ci 11818c2ecf20Sopenharmony_cifree_ipad: 11828c2ecf20Sopenharmony_ci kfree(ipad); 11838c2ecf20Sopenharmony_cifree_request: 11848c2ecf20Sopenharmony_ci ahash_request_free(areq); 11858c2ecf20Sopenharmony_cifree_ahash: 11868c2ecf20Sopenharmony_ci crypto_free_ahash(tfm); 11878c2ecf20Sopenharmony_ci 11888c2ecf20Sopenharmony_ci return ret; 11898c2ecf20Sopenharmony_ci} 11908c2ecf20Sopenharmony_ci 11918c2ecf20Sopenharmony_ciint safexcel_hmac_setkey(struct safexcel_context *base, const u8 *key, 11928c2ecf20Sopenharmony_ci unsigned int keylen, const char *alg, 11938c2ecf20Sopenharmony_ci unsigned int state_sz) 11948c2ecf20Sopenharmony_ci{ 11958c2ecf20Sopenharmony_ci struct safexcel_crypto_priv *priv = base->priv; 11968c2ecf20Sopenharmony_ci struct safexcel_ahash_export_state istate, ostate; 11978c2ecf20Sopenharmony_ci int ret; 11988c2ecf20Sopenharmony_ci 11998c2ecf20Sopenharmony_ci ret = __safexcel_hmac_setkey(alg, key, keylen, &istate, &ostate); 12008c2ecf20Sopenharmony_ci if (ret) 12018c2ecf20Sopenharmony_ci return ret; 12028c2ecf20Sopenharmony_ci 12038c2ecf20Sopenharmony_ci if (priv->flags & EIP197_TRC_CACHE && base->ctxr && 12048c2ecf20Sopenharmony_ci (memcmp(&base->ipad, istate.state, state_sz) || 12058c2ecf20Sopenharmony_ci memcmp(&base->opad, ostate.state, state_sz))) 12068c2ecf20Sopenharmony_ci base->needs_inv = true; 12078c2ecf20Sopenharmony_ci 12088c2ecf20Sopenharmony_ci memcpy(&base->ipad, &istate.state, state_sz); 12098c2ecf20Sopenharmony_ci memcpy(&base->opad, &ostate.state, state_sz); 12108c2ecf20Sopenharmony_ci 12118c2ecf20Sopenharmony_ci return 0; 12128c2ecf20Sopenharmony_ci} 12138c2ecf20Sopenharmony_ci 12148c2ecf20Sopenharmony_cistatic int safexcel_hmac_alg_setkey(struct crypto_ahash *tfm, const u8 *key, 12158c2ecf20Sopenharmony_ci unsigned int keylen, const char *alg, 12168c2ecf20Sopenharmony_ci unsigned int state_sz) 12178c2ecf20Sopenharmony_ci{ 12188c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 12198c2ecf20Sopenharmony_ci 12208c2ecf20Sopenharmony_ci return safexcel_hmac_setkey(&ctx->base, key, keylen, alg, state_sz); 12218c2ecf20Sopenharmony_ci} 12228c2ecf20Sopenharmony_ci 12238c2ecf20Sopenharmony_cistatic int safexcel_hmac_sha1_setkey(struct crypto_ahash *tfm, const u8 *key, 12248c2ecf20Sopenharmony_ci unsigned int keylen) 12258c2ecf20Sopenharmony_ci{ 12268c2ecf20Sopenharmony_ci return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha1", 12278c2ecf20Sopenharmony_ci SHA1_DIGEST_SIZE); 12288c2ecf20Sopenharmony_ci} 12298c2ecf20Sopenharmony_ci 12308c2ecf20Sopenharmony_cistruct safexcel_alg_template safexcel_alg_hmac_sha1 = { 12318c2ecf20Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 12328c2ecf20Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA1, 12338c2ecf20Sopenharmony_ci .alg.ahash = { 12348c2ecf20Sopenharmony_ci .init = safexcel_hmac_sha1_init, 12358c2ecf20Sopenharmony_ci .update = safexcel_ahash_update, 12368c2ecf20Sopenharmony_ci .final = safexcel_ahash_final, 12378c2ecf20Sopenharmony_ci .finup = safexcel_ahash_finup, 12388c2ecf20Sopenharmony_ci .digest = safexcel_hmac_sha1_digest, 12398c2ecf20Sopenharmony_ci .setkey = safexcel_hmac_sha1_setkey, 12408c2ecf20Sopenharmony_ci .export = safexcel_ahash_export, 12418c2ecf20Sopenharmony_ci .import = safexcel_ahash_import, 12428c2ecf20Sopenharmony_ci .halg = { 12438c2ecf20Sopenharmony_ci .digestsize = SHA1_DIGEST_SIZE, 12448c2ecf20Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 12458c2ecf20Sopenharmony_ci .base = { 12468c2ecf20Sopenharmony_ci .cra_name = "hmac(sha1)", 12478c2ecf20Sopenharmony_ci .cra_driver_name = "safexcel-hmac-sha1", 12488c2ecf20Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 12498c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 12508c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 12518c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 12528c2ecf20Sopenharmony_ci .cra_blocksize = SHA1_BLOCK_SIZE, 12538c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 12548c2ecf20Sopenharmony_ci .cra_init = safexcel_ahash_cra_init, 12558c2ecf20Sopenharmony_ci .cra_exit = safexcel_ahash_cra_exit, 12568c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 12578c2ecf20Sopenharmony_ci }, 12588c2ecf20Sopenharmony_ci }, 12598c2ecf20Sopenharmony_ci }, 12608c2ecf20Sopenharmony_ci}; 12618c2ecf20Sopenharmony_ci 12628c2ecf20Sopenharmony_cistatic int safexcel_sha256_init(struct ahash_request *areq) 12638c2ecf20Sopenharmony_ci{ 12648c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 12658c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx(areq); 12668c2ecf20Sopenharmony_ci 12678c2ecf20Sopenharmony_ci memset(req, 0, sizeof(*req)); 12688c2ecf20Sopenharmony_ci 12698c2ecf20Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256; 12708c2ecf20Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 12718c2ecf20Sopenharmony_ci req->state_sz = SHA256_DIGEST_SIZE; 12728c2ecf20Sopenharmony_ci req->digest_sz = SHA256_DIGEST_SIZE; 12738c2ecf20Sopenharmony_ci req->block_sz = SHA256_BLOCK_SIZE; 12748c2ecf20Sopenharmony_ci 12758c2ecf20Sopenharmony_ci return 0; 12768c2ecf20Sopenharmony_ci} 12778c2ecf20Sopenharmony_ci 12788c2ecf20Sopenharmony_cistatic int safexcel_sha256_digest(struct ahash_request *areq) 12798c2ecf20Sopenharmony_ci{ 12808c2ecf20Sopenharmony_ci int ret = safexcel_sha256_init(areq); 12818c2ecf20Sopenharmony_ci 12828c2ecf20Sopenharmony_ci if (ret) 12838c2ecf20Sopenharmony_ci return ret; 12848c2ecf20Sopenharmony_ci 12858c2ecf20Sopenharmony_ci return safexcel_ahash_finup(areq); 12868c2ecf20Sopenharmony_ci} 12878c2ecf20Sopenharmony_ci 12888c2ecf20Sopenharmony_cistruct safexcel_alg_template safexcel_alg_sha256 = { 12898c2ecf20Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 12908c2ecf20Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA2_256, 12918c2ecf20Sopenharmony_ci .alg.ahash = { 12928c2ecf20Sopenharmony_ci .init = safexcel_sha256_init, 12938c2ecf20Sopenharmony_ci .update = safexcel_ahash_update, 12948c2ecf20Sopenharmony_ci .final = safexcel_ahash_final, 12958c2ecf20Sopenharmony_ci .finup = safexcel_ahash_finup, 12968c2ecf20Sopenharmony_ci .digest = safexcel_sha256_digest, 12978c2ecf20Sopenharmony_ci .export = safexcel_ahash_export, 12988c2ecf20Sopenharmony_ci .import = safexcel_ahash_import, 12998c2ecf20Sopenharmony_ci .halg = { 13008c2ecf20Sopenharmony_ci .digestsize = SHA256_DIGEST_SIZE, 13018c2ecf20Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 13028c2ecf20Sopenharmony_ci .base = { 13038c2ecf20Sopenharmony_ci .cra_name = "sha256", 13048c2ecf20Sopenharmony_ci .cra_driver_name = "safexcel-sha256", 13058c2ecf20Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 13068c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 13078c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 13088c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 13098c2ecf20Sopenharmony_ci .cra_blocksize = SHA256_BLOCK_SIZE, 13108c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 13118c2ecf20Sopenharmony_ci .cra_init = safexcel_ahash_cra_init, 13128c2ecf20Sopenharmony_ci .cra_exit = safexcel_ahash_cra_exit, 13138c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 13148c2ecf20Sopenharmony_ci }, 13158c2ecf20Sopenharmony_ci }, 13168c2ecf20Sopenharmony_ci }, 13178c2ecf20Sopenharmony_ci}; 13188c2ecf20Sopenharmony_ci 13198c2ecf20Sopenharmony_cistatic int safexcel_sha224_init(struct ahash_request *areq) 13208c2ecf20Sopenharmony_ci{ 13218c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 13228c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx(areq); 13238c2ecf20Sopenharmony_ci 13248c2ecf20Sopenharmony_ci memset(req, 0, sizeof(*req)); 13258c2ecf20Sopenharmony_ci 13268c2ecf20Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224; 13278c2ecf20Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 13288c2ecf20Sopenharmony_ci req->state_sz = SHA256_DIGEST_SIZE; 13298c2ecf20Sopenharmony_ci req->digest_sz = SHA256_DIGEST_SIZE; 13308c2ecf20Sopenharmony_ci req->block_sz = SHA256_BLOCK_SIZE; 13318c2ecf20Sopenharmony_ci 13328c2ecf20Sopenharmony_ci return 0; 13338c2ecf20Sopenharmony_ci} 13348c2ecf20Sopenharmony_ci 13358c2ecf20Sopenharmony_cistatic int safexcel_sha224_digest(struct ahash_request *areq) 13368c2ecf20Sopenharmony_ci{ 13378c2ecf20Sopenharmony_ci int ret = safexcel_sha224_init(areq); 13388c2ecf20Sopenharmony_ci 13398c2ecf20Sopenharmony_ci if (ret) 13408c2ecf20Sopenharmony_ci return ret; 13418c2ecf20Sopenharmony_ci 13428c2ecf20Sopenharmony_ci return safexcel_ahash_finup(areq); 13438c2ecf20Sopenharmony_ci} 13448c2ecf20Sopenharmony_ci 13458c2ecf20Sopenharmony_cistruct safexcel_alg_template safexcel_alg_sha224 = { 13468c2ecf20Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 13478c2ecf20Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA2_256, 13488c2ecf20Sopenharmony_ci .alg.ahash = { 13498c2ecf20Sopenharmony_ci .init = safexcel_sha224_init, 13508c2ecf20Sopenharmony_ci .update = safexcel_ahash_update, 13518c2ecf20Sopenharmony_ci .final = safexcel_ahash_final, 13528c2ecf20Sopenharmony_ci .finup = safexcel_ahash_finup, 13538c2ecf20Sopenharmony_ci .digest = safexcel_sha224_digest, 13548c2ecf20Sopenharmony_ci .export = safexcel_ahash_export, 13558c2ecf20Sopenharmony_ci .import = safexcel_ahash_import, 13568c2ecf20Sopenharmony_ci .halg = { 13578c2ecf20Sopenharmony_ci .digestsize = SHA224_DIGEST_SIZE, 13588c2ecf20Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 13598c2ecf20Sopenharmony_ci .base = { 13608c2ecf20Sopenharmony_ci .cra_name = "sha224", 13618c2ecf20Sopenharmony_ci .cra_driver_name = "safexcel-sha224", 13628c2ecf20Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 13638c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 13648c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 13658c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 13668c2ecf20Sopenharmony_ci .cra_blocksize = SHA224_BLOCK_SIZE, 13678c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 13688c2ecf20Sopenharmony_ci .cra_init = safexcel_ahash_cra_init, 13698c2ecf20Sopenharmony_ci .cra_exit = safexcel_ahash_cra_exit, 13708c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 13718c2ecf20Sopenharmony_ci }, 13728c2ecf20Sopenharmony_ci }, 13738c2ecf20Sopenharmony_ci }, 13748c2ecf20Sopenharmony_ci}; 13758c2ecf20Sopenharmony_ci 13768c2ecf20Sopenharmony_cistatic int safexcel_hmac_sha224_setkey(struct crypto_ahash *tfm, const u8 *key, 13778c2ecf20Sopenharmony_ci unsigned int keylen) 13788c2ecf20Sopenharmony_ci{ 13798c2ecf20Sopenharmony_ci return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha224", 13808c2ecf20Sopenharmony_ci SHA256_DIGEST_SIZE); 13818c2ecf20Sopenharmony_ci} 13828c2ecf20Sopenharmony_ci 13838c2ecf20Sopenharmony_cistatic int safexcel_hmac_sha224_init(struct ahash_request *areq) 13848c2ecf20Sopenharmony_ci{ 13858c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 13868c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx(areq); 13878c2ecf20Sopenharmony_ci 13888c2ecf20Sopenharmony_ci memset(req, 0, sizeof(*req)); 13898c2ecf20Sopenharmony_ci 13908c2ecf20Sopenharmony_ci /* Start from ipad precompute */ 13918c2ecf20Sopenharmony_ci memcpy(req->state, &ctx->base.ipad, SHA256_DIGEST_SIZE); 13928c2ecf20Sopenharmony_ci /* Already processed the key^ipad part now! */ 13938c2ecf20Sopenharmony_ci req->len = SHA256_BLOCK_SIZE; 13948c2ecf20Sopenharmony_ci req->processed = SHA256_BLOCK_SIZE; 13958c2ecf20Sopenharmony_ci 13968c2ecf20Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224; 13978c2ecf20Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 13988c2ecf20Sopenharmony_ci req->state_sz = SHA256_DIGEST_SIZE; 13998c2ecf20Sopenharmony_ci req->digest_sz = SHA256_DIGEST_SIZE; 14008c2ecf20Sopenharmony_ci req->block_sz = SHA256_BLOCK_SIZE; 14018c2ecf20Sopenharmony_ci req->hmac = true; 14028c2ecf20Sopenharmony_ci 14038c2ecf20Sopenharmony_ci return 0; 14048c2ecf20Sopenharmony_ci} 14058c2ecf20Sopenharmony_ci 14068c2ecf20Sopenharmony_cistatic int safexcel_hmac_sha224_digest(struct ahash_request *areq) 14078c2ecf20Sopenharmony_ci{ 14088c2ecf20Sopenharmony_ci int ret = safexcel_hmac_sha224_init(areq); 14098c2ecf20Sopenharmony_ci 14108c2ecf20Sopenharmony_ci if (ret) 14118c2ecf20Sopenharmony_ci return ret; 14128c2ecf20Sopenharmony_ci 14138c2ecf20Sopenharmony_ci return safexcel_ahash_finup(areq); 14148c2ecf20Sopenharmony_ci} 14158c2ecf20Sopenharmony_ci 14168c2ecf20Sopenharmony_cistruct safexcel_alg_template safexcel_alg_hmac_sha224 = { 14178c2ecf20Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 14188c2ecf20Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA2_256, 14198c2ecf20Sopenharmony_ci .alg.ahash = { 14208c2ecf20Sopenharmony_ci .init = safexcel_hmac_sha224_init, 14218c2ecf20Sopenharmony_ci .update = safexcel_ahash_update, 14228c2ecf20Sopenharmony_ci .final = safexcel_ahash_final, 14238c2ecf20Sopenharmony_ci .finup = safexcel_ahash_finup, 14248c2ecf20Sopenharmony_ci .digest = safexcel_hmac_sha224_digest, 14258c2ecf20Sopenharmony_ci .setkey = safexcel_hmac_sha224_setkey, 14268c2ecf20Sopenharmony_ci .export = safexcel_ahash_export, 14278c2ecf20Sopenharmony_ci .import = safexcel_ahash_import, 14288c2ecf20Sopenharmony_ci .halg = { 14298c2ecf20Sopenharmony_ci .digestsize = SHA224_DIGEST_SIZE, 14308c2ecf20Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 14318c2ecf20Sopenharmony_ci .base = { 14328c2ecf20Sopenharmony_ci .cra_name = "hmac(sha224)", 14338c2ecf20Sopenharmony_ci .cra_driver_name = "safexcel-hmac-sha224", 14348c2ecf20Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 14358c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 14368c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 14378c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 14388c2ecf20Sopenharmony_ci .cra_blocksize = SHA224_BLOCK_SIZE, 14398c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 14408c2ecf20Sopenharmony_ci .cra_init = safexcel_ahash_cra_init, 14418c2ecf20Sopenharmony_ci .cra_exit = safexcel_ahash_cra_exit, 14428c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 14438c2ecf20Sopenharmony_ci }, 14448c2ecf20Sopenharmony_ci }, 14458c2ecf20Sopenharmony_ci }, 14468c2ecf20Sopenharmony_ci}; 14478c2ecf20Sopenharmony_ci 14488c2ecf20Sopenharmony_cistatic int safexcel_hmac_sha256_setkey(struct crypto_ahash *tfm, const u8 *key, 14498c2ecf20Sopenharmony_ci unsigned int keylen) 14508c2ecf20Sopenharmony_ci{ 14518c2ecf20Sopenharmony_ci return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha256", 14528c2ecf20Sopenharmony_ci SHA256_DIGEST_SIZE); 14538c2ecf20Sopenharmony_ci} 14548c2ecf20Sopenharmony_ci 14558c2ecf20Sopenharmony_cistatic int safexcel_hmac_sha256_init(struct ahash_request *areq) 14568c2ecf20Sopenharmony_ci{ 14578c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 14588c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx(areq); 14598c2ecf20Sopenharmony_ci 14608c2ecf20Sopenharmony_ci memset(req, 0, sizeof(*req)); 14618c2ecf20Sopenharmony_ci 14628c2ecf20Sopenharmony_ci /* Start from ipad precompute */ 14638c2ecf20Sopenharmony_ci memcpy(req->state, &ctx->base.ipad, SHA256_DIGEST_SIZE); 14648c2ecf20Sopenharmony_ci /* Already processed the key^ipad part now! */ 14658c2ecf20Sopenharmony_ci req->len = SHA256_BLOCK_SIZE; 14668c2ecf20Sopenharmony_ci req->processed = SHA256_BLOCK_SIZE; 14678c2ecf20Sopenharmony_ci 14688c2ecf20Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256; 14698c2ecf20Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 14708c2ecf20Sopenharmony_ci req->state_sz = SHA256_DIGEST_SIZE; 14718c2ecf20Sopenharmony_ci req->digest_sz = SHA256_DIGEST_SIZE; 14728c2ecf20Sopenharmony_ci req->block_sz = SHA256_BLOCK_SIZE; 14738c2ecf20Sopenharmony_ci req->hmac = true; 14748c2ecf20Sopenharmony_ci 14758c2ecf20Sopenharmony_ci return 0; 14768c2ecf20Sopenharmony_ci} 14778c2ecf20Sopenharmony_ci 14788c2ecf20Sopenharmony_cistatic int safexcel_hmac_sha256_digest(struct ahash_request *areq) 14798c2ecf20Sopenharmony_ci{ 14808c2ecf20Sopenharmony_ci int ret = safexcel_hmac_sha256_init(areq); 14818c2ecf20Sopenharmony_ci 14828c2ecf20Sopenharmony_ci if (ret) 14838c2ecf20Sopenharmony_ci return ret; 14848c2ecf20Sopenharmony_ci 14858c2ecf20Sopenharmony_ci return safexcel_ahash_finup(areq); 14868c2ecf20Sopenharmony_ci} 14878c2ecf20Sopenharmony_ci 14888c2ecf20Sopenharmony_cistruct safexcel_alg_template safexcel_alg_hmac_sha256 = { 14898c2ecf20Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 14908c2ecf20Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA2_256, 14918c2ecf20Sopenharmony_ci .alg.ahash = { 14928c2ecf20Sopenharmony_ci .init = safexcel_hmac_sha256_init, 14938c2ecf20Sopenharmony_ci .update = safexcel_ahash_update, 14948c2ecf20Sopenharmony_ci .final = safexcel_ahash_final, 14958c2ecf20Sopenharmony_ci .finup = safexcel_ahash_finup, 14968c2ecf20Sopenharmony_ci .digest = safexcel_hmac_sha256_digest, 14978c2ecf20Sopenharmony_ci .setkey = safexcel_hmac_sha256_setkey, 14988c2ecf20Sopenharmony_ci .export = safexcel_ahash_export, 14998c2ecf20Sopenharmony_ci .import = safexcel_ahash_import, 15008c2ecf20Sopenharmony_ci .halg = { 15018c2ecf20Sopenharmony_ci .digestsize = SHA256_DIGEST_SIZE, 15028c2ecf20Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 15038c2ecf20Sopenharmony_ci .base = { 15048c2ecf20Sopenharmony_ci .cra_name = "hmac(sha256)", 15058c2ecf20Sopenharmony_ci .cra_driver_name = "safexcel-hmac-sha256", 15068c2ecf20Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 15078c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 15088c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 15098c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 15108c2ecf20Sopenharmony_ci .cra_blocksize = SHA256_BLOCK_SIZE, 15118c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 15128c2ecf20Sopenharmony_ci .cra_init = safexcel_ahash_cra_init, 15138c2ecf20Sopenharmony_ci .cra_exit = safexcel_ahash_cra_exit, 15148c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 15158c2ecf20Sopenharmony_ci }, 15168c2ecf20Sopenharmony_ci }, 15178c2ecf20Sopenharmony_ci }, 15188c2ecf20Sopenharmony_ci}; 15198c2ecf20Sopenharmony_ci 15208c2ecf20Sopenharmony_cistatic int safexcel_sha512_init(struct ahash_request *areq) 15218c2ecf20Sopenharmony_ci{ 15228c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 15238c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx(areq); 15248c2ecf20Sopenharmony_ci 15258c2ecf20Sopenharmony_ci memset(req, 0, sizeof(*req)); 15268c2ecf20Sopenharmony_ci 15278c2ecf20Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512; 15288c2ecf20Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 15298c2ecf20Sopenharmony_ci req->state_sz = SHA512_DIGEST_SIZE; 15308c2ecf20Sopenharmony_ci req->digest_sz = SHA512_DIGEST_SIZE; 15318c2ecf20Sopenharmony_ci req->block_sz = SHA512_BLOCK_SIZE; 15328c2ecf20Sopenharmony_ci 15338c2ecf20Sopenharmony_ci return 0; 15348c2ecf20Sopenharmony_ci} 15358c2ecf20Sopenharmony_ci 15368c2ecf20Sopenharmony_cistatic int safexcel_sha512_digest(struct ahash_request *areq) 15378c2ecf20Sopenharmony_ci{ 15388c2ecf20Sopenharmony_ci int ret = safexcel_sha512_init(areq); 15398c2ecf20Sopenharmony_ci 15408c2ecf20Sopenharmony_ci if (ret) 15418c2ecf20Sopenharmony_ci return ret; 15428c2ecf20Sopenharmony_ci 15438c2ecf20Sopenharmony_ci return safexcel_ahash_finup(areq); 15448c2ecf20Sopenharmony_ci} 15458c2ecf20Sopenharmony_ci 15468c2ecf20Sopenharmony_cistruct safexcel_alg_template safexcel_alg_sha512 = { 15478c2ecf20Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 15488c2ecf20Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA2_512, 15498c2ecf20Sopenharmony_ci .alg.ahash = { 15508c2ecf20Sopenharmony_ci .init = safexcel_sha512_init, 15518c2ecf20Sopenharmony_ci .update = safexcel_ahash_update, 15528c2ecf20Sopenharmony_ci .final = safexcel_ahash_final, 15538c2ecf20Sopenharmony_ci .finup = safexcel_ahash_finup, 15548c2ecf20Sopenharmony_ci .digest = safexcel_sha512_digest, 15558c2ecf20Sopenharmony_ci .export = safexcel_ahash_export, 15568c2ecf20Sopenharmony_ci .import = safexcel_ahash_import, 15578c2ecf20Sopenharmony_ci .halg = { 15588c2ecf20Sopenharmony_ci .digestsize = SHA512_DIGEST_SIZE, 15598c2ecf20Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 15608c2ecf20Sopenharmony_ci .base = { 15618c2ecf20Sopenharmony_ci .cra_name = "sha512", 15628c2ecf20Sopenharmony_ci .cra_driver_name = "safexcel-sha512", 15638c2ecf20Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 15648c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 15658c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 15668c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 15678c2ecf20Sopenharmony_ci .cra_blocksize = SHA512_BLOCK_SIZE, 15688c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 15698c2ecf20Sopenharmony_ci .cra_init = safexcel_ahash_cra_init, 15708c2ecf20Sopenharmony_ci .cra_exit = safexcel_ahash_cra_exit, 15718c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 15728c2ecf20Sopenharmony_ci }, 15738c2ecf20Sopenharmony_ci }, 15748c2ecf20Sopenharmony_ci }, 15758c2ecf20Sopenharmony_ci}; 15768c2ecf20Sopenharmony_ci 15778c2ecf20Sopenharmony_cistatic int safexcel_sha384_init(struct ahash_request *areq) 15788c2ecf20Sopenharmony_ci{ 15798c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 15808c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx(areq); 15818c2ecf20Sopenharmony_ci 15828c2ecf20Sopenharmony_ci memset(req, 0, sizeof(*req)); 15838c2ecf20Sopenharmony_ci 15848c2ecf20Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384; 15858c2ecf20Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 15868c2ecf20Sopenharmony_ci req->state_sz = SHA512_DIGEST_SIZE; 15878c2ecf20Sopenharmony_ci req->digest_sz = SHA512_DIGEST_SIZE; 15888c2ecf20Sopenharmony_ci req->block_sz = SHA512_BLOCK_SIZE; 15898c2ecf20Sopenharmony_ci 15908c2ecf20Sopenharmony_ci return 0; 15918c2ecf20Sopenharmony_ci} 15928c2ecf20Sopenharmony_ci 15938c2ecf20Sopenharmony_cistatic int safexcel_sha384_digest(struct ahash_request *areq) 15948c2ecf20Sopenharmony_ci{ 15958c2ecf20Sopenharmony_ci int ret = safexcel_sha384_init(areq); 15968c2ecf20Sopenharmony_ci 15978c2ecf20Sopenharmony_ci if (ret) 15988c2ecf20Sopenharmony_ci return ret; 15998c2ecf20Sopenharmony_ci 16008c2ecf20Sopenharmony_ci return safexcel_ahash_finup(areq); 16018c2ecf20Sopenharmony_ci} 16028c2ecf20Sopenharmony_ci 16038c2ecf20Sopenharmony_cistruct safexcel_alg_template safexcel_alg_sha384 = { 16048c2ecf20Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 16058c2ecf20Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA2_512, 16068c2ecf20Sopenharmony_ci .alg.ahash = { 16078c2ecf20Sopenharmony_ci .init = safexcel_sha384_init, 16088c2ecf20Sopenharmony_ci .update = safexcel_ahash_update, 16098c2ecf20Sopenharmony_ci .final = safexcel_ahash_final, 16108c2ecf20Sopenharmony_ci .finup = safexcel_ahash_finup, 16118c2ecf20Sopenharmony_ci .digest = safexcel_sha384_digest, 16128c2ecf20Sopenharmony_ci .export = safexcel_ahash_export, 16138c2ecf20Sopenharmony_ci .import = safexcel_ahash_import, 16148c2ecf20Sopenharmony_ci .halg = { 16158c2ecf20Sopenharmony_ci .digestsize = SHA384_DIGEST_SIZE, 16168c2ecf20Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 16178c2ecf20Sopenharmony_ci .base = { 16188c2ecf20Sopenharmony_ci .cra_name = "sha384", 16198c2ecf20Sopenharmony_ci .cra_driver_name = "safexcel-sha384", 16208c2ecf20Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 16218c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 16228c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 16238c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 16248c2ecf20Sopenharmony_ci .cra_blocksize = SHA384_BLOCK_SIZE, 16258c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 16268c2ecf20Sopenharmony_ci .cra_init = safexcel_ahash_cra_init, 16278c2ecf20Sopenharmony_ci .cra_exit = safexcel_ahash_cra_exit, 16288c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 16298c2ecf20Sopenharmony_ci }, 16308c2ecf20Sopenharmony_ci }, 16318c2ecf20Sopenharmony_ci }, 16328c2ecf20Sopenharmony_ci}; 16338c2ecf20Sopenharmony_ci 16348c2ecf20Sopenharmony_cistatic int safexcel_hmac_sha512_setkey(struct crypto_ahash *tfm, const u8 *key, 16358c2ecf20Sopenharmony_ci unsigned int keylen) 16368c2ecf20Sopenharmony_ci{ 16378c2ecf20Sopenharmony_ci return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha512", 16388c2ecf20Sopenharmony_ci SHA512_DIGEST_SIZE); 16398c2ecf20Sopenharmony_ci} 16408c2ecf20Sopenharmony_ci 16418c2ecf20Sopenharmony_cistatic int safexcel_hmac_sha512_init(struct ahash_request *areq) 16428c2ecf20Sopenharmony_ci{ 16438c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 16448c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx(areq); 16458c2ecf20Sopenharmony_ci 16468c2ecf20Sopenharmony_ci memset(req, 0, sizeof(*req)); 16478c2ecf20Sopenharmony_ci 16488c2ecf20Sopenharmony_ci /* Start from ipad precompute */ 16498c2ecf20Sopenharmony_ci memcpy(req->state, &ctx->base.ipad, SHA512_DIGEST_SIZE); 16508c2ecf20Sopenharmony_ci /* Already processed the key^ipad part now! */ 16518c2ecf20Sopenharmony_ci req->len = SHA512_BLOCK_SIZE; 16528c2ecf20Sopenharmony_ci req->processed = SHA512_BLOCK_SIZE; 16538c2ecf20Sopenharmony_ci 16548c2ecf20Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512; 16558c2ecf20Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 16568c2ecf20Sopenharmony_ci req->state_sz = SHA512_DIGEST_SIZE; 16578c2ecf20Sopenharmony_ci req->digest_sz = SHA512_DIGEST_SIZE; 16588c2ecf20Sopenharmony_ci req->block_sz = SHA512_BLOCK_SIZE; 16598c2ecf20Sopenharmony_ci req->hmac = true; 16608c2ecf20Sopenharmony_ci 16618c2ecf20Sopenharmony_ci return 0; 16628c2ecf20Sopenharmony_ci} 16638c2ecf20Sopenharmony_ci 16648c2ecf20Sopenharmony_cistatic int safexcel_hmac_sha512_digest(struct ahash_request *areq) 16658c2ecf20Sopenharmony_ci{ 16668c2ecf20Sopenharmony_ci int ret = safexcel_hmac_sha512_init(areq); 16678c2ecf20Sopenharmony_ci 16688c2ecf20Sopenharmony_ci if (ret) 16698c2ecf20Sopenharmony_ci return ret; 16708c2ecf20Sopenharmony_ci 16718c2ecf20Sopenharmony_ci return safexcel_ahash_finup(areq); 16728c2ecf20Sopenharmony_ci} 16738c2ecf20Sopenharmony_ci 16748c2ecf20Sopenharmony_cistruct safexcel_alg_template safexcel_alg_hmac_sha512 = { 16758c2ecf20Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 16768c2ecf20Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA2_512, 16778c2ecf20Sopenharmony_ci .alg.ahash = { 16788c2ecf20Sopenharmony_ci .init = safexcel_hmac_sha512_init, 16798c2ecf20Sopenharmony_ci .update = safexcel_ahash_update, 16808c2ecf20Sopenharmony_ci .final = safexcel_ahash_final, 16818c2ecf20Sopenharmony_ci .finup = safexcel_ahash_finup, 16828c2ecf20Sopenharmony_ci .digest = safexcel_hmac_sha512_digest, 16838c2ecf20Sopenharmony_ci .setkey = safexcel_hmac_sha512_setkey, 16848c2ecf20Sopenharmony_ci .export = safexcel_ahash_export, 16858c2ecf20Sopenharmony_ci .import = safexcel_ahash_import, 16868c2ecf20Sopenharmony_ci .halg = { 16878c2ecf20Sopenharmony_ci .digestsize = SHA512_DIGEST_SIZE, 16888c2ecf20Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 16898c2ecf20Sopenharmony_ci .base = { 16908c2ecf20Sopenharmony_ci .cra_name = "hmac(sha512)", 16918c2ecf20Sopenharmony_ci .cra_driver_name = "safexcel-hmac-sha512", 16928c2ecf20Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 16938c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 16948c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 16958c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 16968c2ecf20Sopenharmony_ci .cra_blocksize = SHA512_BLOCK_SIZE, 16978c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 16988c2ecf20Sopenharmony_ci .cra_init = safexcel_ahash_cra_init, 16998c2ecf20Sopenharmony_ci .cra_exit = safexcel_ahash_cra_exit, 17008c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 17018c2ecf20Sopenharmony_ci }, 17028c2ecf20Sopenharmony_ci }, 17038c2ecf20Sopenharmony_ci }, 17048c2ecf20Sopenharmony_ci}; 17058c2ecf20Sopenharmony_ci 17068c2ecf20Sopenharmony_cistatic int safexcel_hmac_sha384_setkey(struct crypto_ahash *tfm, const u8 *key, 17078c2ecf20Sopenharmony_ci unsigned int keylen) 17088c2ecf20Sopenharmony_ci{ 17098c2ecf20Sopenharmony_ci return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha384", 17108c2ecf20Sopenharmony_ci SHA512_DIGEST_SIZE); 17118c2ecf20Sopenharmony_ci} 17128c2ecf20Sopenharmony_ci 17138c2ecf20Sopenharmony_cistatic int safexcel_hmac_sha384_init(struct ahash_request *areq) 17148c2ecf20Sopenharmony_ci{ 17158c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 17168c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx(areq); 17178c2ecf20Sopenharmony_ci 17188c2ecf20Sopenharmony_ci memset(req, 0, sizeof(*req)); 17198c2ecf20Sopenharmony_ci 17208c2ecf20Sopenharmony_ci /* Start from ipad precompute */ 17218c2ecf20Sopenharmony_ci memcpy(req->state, &ctx->base.ipad, SHA512_DIGEST_SIZE); 17228c2ecf20Sopenharmony_ci /* Already processed the key^ipad part now! */ 17238c2ecf20Sopenharmony_ci req->len = SHA512_BLOCK_SIZE; 17248c2ecf20Sopenharmony_ci req->processed = SHA512_BLOCK_SIZE; 17258c2ecf20Sopenharmony_ci 17268c2ecf20Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384; 17278c2ecf20Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 17288c2ecf20Sopenharmony_ci req->state_sz = SHA512_DIGEST_SIZE; 17298c2ecf20Sopenharmony_ci req->digest_sz = SHA512_DIGEST_SIZE; 17308c2ecf20Sopenharmony_ci req->block_sz = SHA512_BLOCK_SIZE; 17318c2ecf20Sopenharmony_ci req->hmac = true; 17328c2ecf20Sopenharmony_ci 17338c2ecf20Sopenharmony_ci return 0; 17348c2ecf20Sopenharmony_ci} 17358c2ecf20Sopenharmony_ci 17368c2ecf20Sopenharmony_cistatic int safexcel_hmac_sha384_digest(struct ahash_request *areq) 17378c2ecf20Sopenharmony_ci{ 17388c2ecf20Sopenharmony_ci int ret = safexcel_hmac_sha384_init(areq); 17398c2ecf20Sopenharmony_ci 17408c2ecf20Sopenharmony_ci if (ret) 17418c2ecf20Sopenharmony_ci return ret; 17428c2ecf20Sopenharmony_ci 17438c2ecf20Sopenharmony_ci return safexcel_ahash_finup(areq); 17448c2ecf20Sopenharmony_ci} 17458c2ecf20Sopenharmony_ci 17468c2ecf20Sopenharmony_cistruct safexcel_alg_template safexcel_alg_hmac_sha384 = { 17478c2ecf20Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 17488c2ecf20Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA2_512, 17498c2ecf20Sopenharmony_ci .alg.ahash = { 17508c2ecf20Sopenharmony_ci .init = safexcel_hmac_sha384_init, 17518c2ecf20Sopenharmony_ci .update = safexcel_ahash_update, 17528c2ecf20Sopenharmony_ci .final = safexcel_ahash_final, 17538c2ecf20Sopenharmony_ci .finup = safexcel_ahash_finup, 17548c2ecf20Sopenharmony_ci .digest = safexcel_hmac_sha384_digest, 17558c2ecf20Sopenharmony_ci .setkey = safexcel_hmac_sha384_setkey, 17568c2ecf20Sopenharmony_ci .export = safexcel_ahash_export, 17578c2ecf20Sopenharmony_ci .import = safexcel_ahash_import, 17588c2ecf20Sopenharmony_ci .halg = { 17598c2ecf20Sopenharmony_ci .digestsize = SHA384_DIGEST_SIZE, 17608c2ecf20Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 17618c2ecf20Sopenharmony_ci .base = { 17628c2ecf20Sopenharmony_ci .cra_name = "hmac(sha384)", 17638c2ecf20Sopenharmony_ci .cra_driver_name = "safexcel-hmac-sha384", 17648c2ecf20Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 17658c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 17668c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 17678c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 17688c2ecf20Sopenharmony_ci .cra_blocksize = SHA384_BLOCK_SIZE, 17698c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 17708c2ecf20Sopenharmony_ci .cra_init = safexcel_ahash_cra_init, 17718c2ecf20Sopenharmony_ci .cra_exit = safexcel_ahash_cra_exit, 17728c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 17738c2ecf20Sopenharmony_ci }, 17748c2ecf20Sopenharmony_ci }, 17758c2ecf20Sopenharmony_ci }, 17768c2ecf20Sopenharmony_ci}; 17778c2ecf20Sopenharmony_ci 17788c2ecf20Sopenharmony_cistatic int safexcel_md5_init(struct ahash_request *areq) 17798c2ecf20Sopenharmony_ci{ 17808c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 17818c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx(areq); 17828c2ecf20Sopenharmony_ci 17838c2ecf20Sopenharmony_ci memset(req, 0, sizeof(*req)); 17848c2ecf20Sopenharmony_ci 17858c2ecf20Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_MD5; 17868c2ecf20Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 17878c2ecf20Sopenharmony_ci req->state_sz = MD5_DIGEST_SIZE; 17888c2ecf20Sopenharmony_ci req->digest_sz = MD5_DIGEST_SIZE; 17898c2ecf20Sopenharmony_ci req->block_sz = MD5_HMAC_BLOCK_SIZE; 17908c2ecf20Sopenharmony_ci 17918c2ecf20Sopenharmony_ci return 0; 17928c2ecf20Sopenharmony_ci} 17938c2ecf20Sopenharmony_ci 17948c2ecf20Sopenharmony_cistatic int safexcel_md5_digest(struct ahash_request *areq) 17958c2ecf20Sopenharmony_ci{ 17968c2ecf20Sopenharmony_ci int ret = safexcel_md5_init(areq); 17978c2ecf20Sopenharmony_ci 17988c2ecf20Sopenharmony_ci if (ret) 17998c2ecf20Sopenharmony_ci return ret; 18008c2ecf20Sopenharmony_ci 18018c2ecf20Sopenharmony_ci return safexcel_ahash_finup(areq); 18028c2ecf20Sopenharmony_ci} 18038c2ecf20Sopenharmony_ci 18048c2ecf20Sopenharmony_cistruct safexcel_alg_template safexcel_alg_md5 = { 18058c2ecf20Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 18068c2ecf20Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_MD5, 18078c2ecf20Sopenharmony_ci .alg.ahash = { 18088c2ecf20Sopenharmony_ci .init = safexcel_md5_init, 18098c2ecf20Sopenharmony_ci .update = safexcel_ahash_update, 18108c2ecf20Sopenharmony_ci .final = safexcel_ahash_final, 18118c2ecf20Sopenharmony_ci .finup = safexcel_ahash_finup, 18128c2ecf20Sopenharmony_ci .digest = safexcel_md5_digest, 18138c2ecf20Sopenharmony_ci .export = safexcel_ahash_export, 18148c2ecf20Sopenharmony_ci .import = safexcel_ahash_import, 18158c2ecf20Sopenharmony_ci .halg = { 18168c2ecf20Sopenharmony_ci .digestsize = MD5_DIGEST_SIZE, 18178c2ecf20Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 18188c2ecf20Sopenharmony_ci .base = { 18198c2ecf20Sopenharmony_ci .cra_name = "md5", 18208c2ecf20Sopenharmony_ci .cra_driver_name = "safexcel-md5", 18218c2ecf20Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 18228c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 18238c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 18248c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 18258c2ecf20Sopenharmony_ci .cra_blocksize = MD5_HMAC_BLOCK_SIZE, 18268c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 18278c2ecf20Sopenharmony_ci .cra_init = safexcel_ahash_cra_init, 18288c2ecf20Sopenharmony_ci .cra_exit = safexcel_ahash_cra_exit, 18298c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 18308c2ecf20Sopenharmony_ci }, 18318c2ecf20Sopenharmony_ci }, 18328c2ecf20Sopenharmony_ci }, 18338c2ecf20Sopenharmony_ci}; 18348c2ecf20Sopenharmony_ci 18358c2ecf20Sopenharmony_cistatic int safexcel_hmac_md5_init(struct ahash_request *areq) 18368c2ecf20Sopenharmony_ci{ 18378c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 18388c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx(areq); 18398c2ecf20Sopenharmony_ci 18408c2ecf20Sopenharmony_ci memset(req, 0, sizeof(*req)); 18418c2ecf20Sopenharmony_ci 18428c2ecf20Sopenharmony_ci /* Start from ipad precompute */ 18438c2ecf20Sopenharmony_ci memcpy(req->state, &ctx->base.ipad, MD5_DIGEST_SIZE); 18448c2ecf20Sopenharmony_ci /* Already processed the key^ipad part now! */ 18458c2ecf20Sopenharmony_ci req->len = MD5_HMAC_BLOCK_SIZE; 18468c2ecf20Sopenharmony_ci req->processed = MD5_HMAC_BLOCK_SIZE; 18478c2ecf20Sopenharmony_ci 18488c2ecf20Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_MD5; 18498c2ecf20Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 18508c2ecf20Sopenharmony_ci req->state_sz = MD5_DIGEST_SIZE; 18518c2ecf20Sopenharmony_ci req->digest_sz = MD5_DIGEST_SIZE; 18528c2ecf20Sopenharmony_ci req->block_sz = MD5_HMAC_BLOCK_SIZE; 18538c2ecf20Sopenharmony_ci req->len_is_le = true; /* MD5 is little endian! ... */ 18548c2ecf20Sopenharmony_ci req->hmac = true; 18558c2ecf20Sopenharmony_ci 18568c2ecf20Sopenharmony_ci return 0; 18578c2ecf20Sopenharmony_ci} 18588c2ecf20Sopenharmony_ci 18598c2ecf20Sopenharmony_cistatic int safexcel_hmac_md5_setkey(struct crypto_ahash *tfm, const u8 *key, 18608c2ecf20Sopenharmony_ci unsigned int keylen) 18618c2ecf20Sopenharmony_ci{ 18628c2ecf20Sopenharmony_ci return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-md5", 18638c2ecf20Sopenharmony_ci MD5_DIGEST_SIZE); 18648c2ecf20Sopenharmony_ci} 18658c2ecf20Sopenharmony_ci 18668c2ecf20Sopenharmony_cistatic int safexcel_hmac_md5_digest(struct ahash_request *areq) 18678c2ecf20Sopenharmony_ci{ 18688c2ecf20Sopenharmony_ci int ret = safexcel_hmac_md5_init(areq); 18698c2ecf20Sopenharmony_ci 18708c2ecf20Sopenharmony_ci if (ret) 18718c2ecf20Sopenharmony_ci return ret; 18728c2ecf20Sopenharmony_ci 18738c2ecf20Sopenharmony_ci return safexcel_ahash_finup(areq); 18748c2ecf20Sopenharmony_ci} 18758c2ecf20Sopenharmony_ci 18768c2ecf20Sopenharmony_cistruct safexcel_alg_template safexcel_alg_hmac_md5 = { 18778c2ecf20Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 18788c2ecf20Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_MD5, 18798c2ecf20Sopenharmony_ci .alg.ahash = { 18808c2ecf20Sopenharmony_ci .init = safexcel_hmac_md5_init, 18818c2ecf20Sopenharmony_ci .update = safexcel_ahash_update, 18828c2ecf20Sopenharmony_ci .final = safexcel_ahash_final, 18838c2ecf20Sopenharmony_ci .finup = safexcel_ahash_finup, 18848c2ecf20Sopenharmony_ci .digest = safexcel_hmac_md5_digest, 18858c2ecf20Sopenharmony_ci .setkey = safexcel_hmac_md5_setkey, 18868c2ecf20Sopenharmony_ci .export = safexcel_ahash_export, 18878c2ecf20Sopenharmony_ci .import = safexcel_ahash_import, 18888c2ecf20Sopenharmony_ci .halg = { 18898c2ecf20Sopenharmony_ci .digestsize = MD5_DIGEST_SIZE, 18908c2ecf20Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 18918c2ecf20Sopenharmony_ci .base = { 18928c2ecf20Sopenharmony_ci .cra_name = "hmac(md5)", 18938c2ecf20Sopenharmony_ci .cra_driver_name = "safexcel-hmac-md5", 18948c2ecf20Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 18958c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 18968c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 18978c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 18988c2ecf20Sopenharmony_ci .cra_blocksize = MD5_HMAC_BLOCK_SIZE, 18998c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 19008c2ecf20Sopenharmony_ci .cra_init = safexcel_ahash_cra_init, 19018c2ecf20Sopenharmony_ci .cra_exit = safexcel_ahash_cra_exit, 19028c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 19038c2ecf20Sopenharmony_ci }, 19048c2ecf20Sopenharmony_ci }, 19058c2ecf20Sopenharmony_ci }, 19068c2ecf20Sopenharmony_ci}; 19078c2ecf20Sopenharmony_ci 19088c2ecf20Sopenharmony_cistatic int safexcel_crc32_cra_init(struct crypto_tfm *tfm) 19098c2ecf20Sopenharmony_ci{ 19108c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 19118c2ecf20Sopenharmony_ci int ret = safexcel_ahash_cra_init(tfm); 19128c2ecf20Sopenharmony_ci 19138c2ecf20Sopenharmony_ci /* Default 'key' is all zeroes */ 19148c2ecf20Sopenharmony_ci memset(&ctx->base.ipad, 0, sizeof(u32)); 19158c2ecf20Sopenharmony_ci return ret; 19168c2ecf20Sopenharmony_ci} 19178c2ecf20Sopenharmony_ci 19188c2ecf20Sopenharmony_cistatic int safexcel_crc32_init(struct ahash_request *areq) 19198c2ecf20Sopenharmony_ci{ 19208c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 19218c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx(areq); 19228c2ecf20Sopenharmony_ci 19238c2ecf20Sopenharmony_ci memset(req, 0, sizeof(*req)); 19248c2ecf20Sopenharmony_ci 19258c2ecf20Sopenharmony_ci /* Start from loaded key */ 19268c2ecf20Sopenharmony_ci req->state[0] = cpu_to_le32(~ctx->base.ipad.word[0]); 19278c2ecf20Sopenharmony_ci /* Set processed to non-zero to enable invalidation detection */ 19288c2ecf20Sopenharmony_ci req->len = sizeof(u32); 19298c2ecf20Sopenharmony_ci req->processed = sizeof(u32); 19308c2ecf20Sopenharmony_ci 19318c2ecf20Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_CRC32; 19328c2ecf20Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_XCM; 19338c2ecf20Sopenharmony_ci req->state_sz = sizeof(u32); 19348c2ecf20Sopenharmony_ci req->digest_sz = sizeof(u32); 19358c2ecf20Sopenharmony_ci req->block_sz = sizeof(u32); 19368c2ecf20Sopenharmony_ci 19378c2ecf20Sopenharmony_ci return 0; 19388c2ecf20Sopenharmony_ci} 19398c2ecf20Sopenharmony_ci 19408c2ecf20Sopenharmony_cistatic int safexcel_crc32_setkey(struct crypto_ahash *tfm, const u8 *key, 19418c2ecf20Sopenharmony_ci unsigned int keylen) 19428c2ecf20Sopenharmony_ci{ 19438c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 19448c2ecf20Sopenharmony_ci 19458c2ecf20Sopenharmony_ci if (keylen != sizeof(u32)) 19468c2ecf20Sopenharmony_ci return -EINVAL; 19478c2ecf20Sopenharmony_ci 19488c2ecf20Sopenharmony_ci memcpy(&ctx->base.ipad, key, sizeof(u32)); 19498c2ecf20Sopenharmony_ci return 0; 19508c2ecf20Sopenharmony_ci} 19518c2ecf20Sopenharmony_ci 19528c2ecf20Sopenharmony_cistatic int safexcel_crc32_digest(struct ahash_request *areq) 19538c2ecf20Sopenharmony_ci{ 19548c2ecf20Sopenharmony_ci return safexcel_crc32_init(areq) ?: safexcel_ahash_finup(areq); 19558c2ecf20Sopenharmony_ci} 19568c2ecf20Sopenharmony_ci 19578c2ecf20Sopenharmony_cistruct safexcel_alg_template safexcel_alg_crc32 = { 19588c2ecf20Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 19598c2ecf20Sopenharmony_ci .algo_mask = 0, 19608c2ecf20Sopenharmony_ci .alg.ahash = { 19618c2ecf20Sopenharmony_ci .init = safexcel_crc32_init, 19628c2ecf20Sopenharmony_ci .update = safexcel_ahash_update, 19638c2ecf20Sopenharmony_ci .final = safexcel_ahash_final, 19648c2ecf20Sopenharmony_ci .finup = safexcel_ahash_finup, 19658c2ecf20Sopenharmony_ci .digest = safexcel_crc32_digest, 19668c2ecf20Sopenharmony_ci .setkey = safexcel_crc32_setkey, 19678c2ecf20Sopenharmony_ci .export = safexcel_ahash_export, 19688c2ecf20Sopenharmony_ci .import = safexcel_ahash_import, 19698c2ecf20Sopenharmony_ci .halg = { 19708c2ecf20Sopenharmony_ci .digestsize = sizeof(u32), 19718c2ecf20Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 19728c2ecf20Sopenharmony_ci .base = { 19738c2ecf20Sopenharmony_ci .cra_name = "crc32", 19748c2ecf20Sopenharmony_ci .cra_driver_name = "safexcel-crc32", 19758c2ecf20Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 19768c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_OPTIONAL_KEY | 19778c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 19788c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 19798c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 19808c2ecf20Sopenharmony_ci .cra_blocksize = 1, 19818c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 19828c2ecf20Sopenharmony_ci .cra_init = safexcel_crc32_cra_init, 19838c2ecf20Sopenharmony_ci .cra_exit = safexcel_ahash_cra_exit, 19848c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 19858c2ecf20Sopenharmony_ci }, 19868c2ecf20Sopenharmony_ci }, 19878c2ecf20Sopenharmony_ci }, 19888c2ecf20Sopenharmony_ci}; 19898c2ecf20Sopenharmony_ci 19908c2ecf20Sopenharmony_cistatic int safexcel_cbcmac_init(struct ahash_request *areq) 19918c2ecf20Sopenharmony_ci{ 19928c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 19938c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx(areq); 19948c2ecf20Sopenharmony_ci 19958c2ecf20Sopenharmony_ci memset(req, 0, sizeof(*req)); 19968c2ecf20Sopenharmony_ci 19978c2ecf20Sopenharmony_ci /* Start from loaded keys */ 19988c2ecf20Sopenharmony_ci memcpy(req->state, &ctx->base.ipad, ctx->key_sz); 19998c2ecf20Sopenharmony_ci /* Set processed to non-zero to enable invalidation detection */ 20008c2ecf20Sopenharmony_ci req->len = AES_BLOCK_SIZE; 20018c2ecf20Sopenharmony_ci req->processed = AES_BLOCK_SIZE; 20028c2ecf20Sopenharmony_ci 20038c2ecf20Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_XCM; 20048c2ecf20Sopenharmony_ci req->state_sz = ctx->key_sz; 20058c2ecf20Sopenharmony_ci req->digest_sz = AES_BLOCK_SIZE; 20068c2ecf20Sopenharmony_ci req->block_sz = AES_BLOCK_SIZE; 20078c2ecf20Sopenharmony_ci req->xcbcmac = true; 20088c2ecf20Sopenharmony_ci 20098c2ecf20Sopenharmony_ci return 0; 20108c2ecf20Sopenharmony_ci} 20118c2ecf20Sopenharmony_ci 20128c2ecf20Sopenharmony_cistatic int safexcel_cbcmac_setkey(struct crypto_ahash *tfm, const u8 *key, 20138c2ecf20Sopenharmony_ci unsigned int len) 20148c2ecf20Sopenharmony_ci{ 20158c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 20168c2ecf20Sopenharmony_ci struct crypto_aes_ctx aes; 20178c2ecf20Sopenharmony_ci int ret, i; 20188c2ecf20Sopenharmony_ci 20198c2ecf20Sopenharmony_ci ret = aes_expandkey(&aes, key, len); 20208c2ecf20Sopenharmony_ci if (ret) 20218c2ecf20Sopenharmony_ci return ret; 20228c2ecf20Sopenharmony_ci 20238c2ecf20Sopenharmony_ci memset(&ctx->base.ipad, 0, 2 * AES_BLOCK_SIZE); 20248c2ecf20Sopenharmony_ci for (i = 0; i < len / sizeof(u32); i++) 20258c2ecf20Sopenharmony_ci ctx->base.ipad.be[i + 8] = cpu_to_be32(aes.key_enc[i]); 20268c2ecf20Sopenharmony_ci 20278c2ecf20Sopenharmony_ci if (len == AES_KEYSIZE_192) { 20288c2ecf20Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC192; 20298c2ecf20Sopenharmony_ci ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE; 20308c2ecf20Sopenharmony_ci } else if (len == AES_KEYSIZE_256) { 20318c2ecf20Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC256; 20328c2ecf20Sopenharmony_ci ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE; 20338c2ecf20Sopenharmony_ci } else { 20348c2ecf20Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128; 20358c2ecf20Sopenharmony_ci ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE; 20368c2ecf20Sopenharmony_ci } 20378c2ecf20Sopenharmony_ci ctx->cbcmac = true; 20388c2ecf20Sopenharmony_ci 20398c2ecf20Sopenharmony_ci memzero_explicit(&aes, sizeof(aes)); 20408c2ecf20Sopenharmony_ci return 0; 20418c2ecf20Sopenharmony_ci} 20428c2ecf20Sopenharmony_ci 20438c2ecf20Sopenharmony_cistatic int safexcel_cbcmac_digest(struct ahash_request *areq) 20448c2ecf20Sopenharmony_ci{ 20458c2ecf20Sopenharmony_ci return safexcel_cbcmac_init(areq) ?: safexcel_ahash_finup(areq); 20468c2ecf20Sopenharmony_ci} 20478c2ecf20Sopenharmony_ci 20488c2ecf20Sopenharmony_cistruct safexcel_alg_template safexcel_alg_cbcmac = { 20498c2ecf20Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 20508c2ecf20Sopenharmony_ci .algo_mask = 0, 20518c2ecf20Sopenharmony_ci .alg.ahash = { 20528c2ecf20Sopenharmony_ci .init = safexcel_cbcmac_init, 20538c2ecf20Sopenharmony_ci .update = safexcel_ahash_update, 20548c2ecf20Sopenharmony_ci .final = safexcel_ahash_final, 20558c2ecf20Sopenharmony_ci .finup = safexcel_ahash_finup, 20568c2ecf20Sopenharmony_ci .digest = safexcel_cbcmac_digest, 20578c2ecf20Sopenharmony_ci .setkey = safexcel_cbcmac_setkey, 20588c2ecf20Sopenharmony_ci .export = safexcel_ahash_export, 20598c2ecf20Sopenharmony_ci .import = safexcel_ahash_import, 20608c2ecf20Sopenharmony_ci .halg = { 20618c2ecf20Sopenharmony_ci .digestsize = AES_BLOCK_SIZE, 20628c2ecf20Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 20638c2ecf20Sopenharmony_ci .base = { 20648c2ecf20Sopenharmony_ci .cra_name = "cbcmac(aes)", 20658c2ecf20Sopenharmony_ci .cra_driver_name = "safexcel-cbcmac-aes", 20668c2ecf20Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 20678c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 20688c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 20698c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 20708c2ecf20Sopenharmony_ci .cra_blocksize = 1, 20718c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 20728c2ecf20Sopenharmony_ci .cra_init = safexcel_ahash_cra_init, 20738c2ecf20Sopenharmony_ci .cra_exit = safexcel_ahash_cra_exit, 20748c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 20758c2ecf20Sopenharmony_ci }, 20768c2ecf20Sopenharmony_ci }, 20778c2ecf20Sopenharmony_ci }, 20788c2ecf20Sopenharmony_ci}; 20798c2ecf20Sopenharmony_ci 20808c2ecf20Sopenharmony_cistatic int safexcel_xcbcmac_setkey(struct crypto_ahash *tfm, const u8 *key, 20818c2ecf20Sopenharmony_ci unsigned int len) 20828c2ecf20Sopenharmony_ci{ 20838c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 20848c2ecf20Sopenharmony_ci struct crypto_aes_ctx aes; 20858c2ecf20Sopenharmony_ci u32 key_tmp[3 * AES_BLOCK_SIZE / sizeof(u32)]; 20868c2ecf20Sopenharmony_ci int ret, i; 20878c2ecf20Sopenharmony_ci 20888c2ecf20Sopenharmony_ci ret = aes_expandkey(&aes, key, len); 20898c2ecf20Sopenharmony_ci if (ret) 20908c2ecf20Sopenharmony_ci return ret; 20918c2ecf20Sopenharmony_ci 20928c2ecf20Sopenharmony_ci /* precompute the XCBC key material */ 20938c2ecf20Sopenharmony_ci crypto_cipher_clear_flags(ctx->kaes, CRYPTO_TFM_REQ_MASK); 20948c2ecf20Sopenharmony_ci crypto_cipher_set_flags(ctx->kaes, crypto_ahash_get_flags(tfm) & 20958c2ecf20Sopenharmony_ci CRYPTO_TFM_REQ_MASK); 20968c2ecf20Sopenharmony_ci ret = crypto_cipher_setkey(ctx->kaes, key, len); 20978c2ecf20Sopenharmony_ci if (ret) 20988c2ecf20Sopenharmony_ci return ret; 20998c2ecf20Sopenharmony_ci 21008c2ecf20Sopenharmony_ci crypto_cipher_encrypt_one(ctx->kaes, (u8 *)key_tmp + 2 * AES_BLOCK_SIZE, 21018c2ecf20Sopenharmony_ci "\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1"); 21028c2ecf20Sopenharmony_ci crypto_cipher_encrypt_one(ctx->kaes, (u8 *)key_tmp, 21038c2ecf20Sopenharmony_ci "\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2"); 21048c2ecf20Sopenharmony_ci crypto_cipher_encrypt_one(ctx->kaes, (u8 *)key_tmp + AES_BLOCK_SIZE, 21058c2ecf20Sopenharmony_ci "\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3"); 21068c2ecf20Sopenharmony_ci for (i = 0; i < 3 * AES_BLOCK_SIZE / sizeof(u32); i++) 21078c2ecf20Sopenharmony_ci ctx->base.ipad.word[i] = swab32(key_tmp[i]); 21088c2ecf20Sopenharmony_ci 21098c2ecf20Sopenharmony_ci crypto_cipher_clear_flags(ctx->kaes, CRYPTO_TFM_REQ_MASK); 21108c2ecf20Sopenharmony_ci crypto_cipher_set_flags(ctx->kaes, crypto_ahash_get_flags(tfm) & 21118c2ecf20Sopenharmony_ci CRYPTO_TFM_REQ_MASK); 21128c2ecf20Sopenharmony_ci ret = crypto_cipher_setkey(ctx->kaes, 21138c2ecf20Sopenharmony_ci (u8 *)key_tmp + 2 * AES_BLOCK_SIZE, 21148c2ecf20Sopenharmony_ci AES_MIN_KEY_SIZE); 21158c2ecf20Sopenharmony_ci if (ret) 21168c2ecf20Sopenharmony_ci return ret; 21178c2ecf20Sopenharmony_ci 21188c2ecf20Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128; 21198c2ecf20Sopenharmony_ci ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE; 21208c2ecf20Sopenharmony_ci ctx->cbcmac = false; 21218c2ecf20Sopenharmony_ci 21228c2ecf20Sopenharmony_ci memzero_explicit(&aes, sizeof(aes)); 21238c2ecf20Sopenharmony_ci return 0; 21248c2ecf20Sopenharmony_ci} 21258c2ecf20Sopenharmony_ci 21268c2ecf20Sopenharmony_cistatic int safexcel_xcbcmac_cra_init(struct crypto_tfm *tfm) 21278c2ecf20Sopenharmony_ci{ 21288c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 21298c2ecf20Sopenharmony_ci 21308c2ecf20Sopenharmony_ci safexcel_ahash_cra_init(tfm); 21318c2ecf20Sopenharmony_ci ctx->kaes = crypto_alloc_cipher("aes", 0, 0); 21328c2ecf20Sopenharmony_ci return PTR_ERR_OR_ZERO(ctx->kaes); 21338c2ecf20Sopenharmony_ci} 21348c2ecf20Sopenharmony_ci 21358c2ecf20Sopenharmony_cistatic void safexcel_xcbcmac_cra_exit(struct crypto_tfm *tfm) 21368c2ecf20Sopenharmony_ci{ 21378c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 21388c2ecf20Sopenharmony_ci 21398c2ecf20Sopenharmony_ci crypto_free_cipher(ctx->kaes); 21408c2ecf20Sopenharmony_ci safexcel_ahash_cra_exit(tfm); 21418c2ecf20Sopenharmony_ci} 21428c2ecf20Sopenharmony_ci 21438c2ecf20Sopenharmony_cistruct safexcel_alg_template safexcel_alg_xcbcmac = { 21448c2ecf20Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 21458c2ecf20Sopenharmony_ci .algo_mask = 0, 21468c2ecf20Sopenharmony_ci .alg.ahash = { 21478c2ecf20Sopenharmony_ci .init = safexcel_cbcmac_init, 21488c2ecf20Sopenharmony_ci .update = safexcel_ahash_update, 21498c2ecf20Sopenharmony_ci .final = safexcel_ahash_final, 21508c2ecf20Sopenharmony_ci .finup = safexcel_ahash_finup, 21518c2ecf20Sopenharmony_ci .digest = safexcel_cbcmac_digest, 21528c2ecf20Sopenharmony_ci .setkey = safexcel_xcbcmac_setkey, 21538c2ecf20Sopenharmony_ci .export = safexcel_ahash_export, 21548c2ecf20Sopenharmony_ci .import = safexcel_ahash_import, 21558c2ecf20Sopenharmony_ci .halg = { 21568c2ecf20Sopenharmony_ci .digestsize = AES_BLOCK_SIZE, 21578c2ecf20Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 21588c2ecf20Sopenharmony_ci .base = { 21598c2ecf20Sopenharmony_ci .cra_name = "xcbc(aes)", 21608c2ecf20Sopenharmony_ci .cra_driver_name = "safexcel-xcbc-aes", 21618c2ecf20Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 21628c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 21638c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 21648c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 21658c2ecf20Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 21668c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 21678c2ecf20Sopenharmony_ci .cra_init = safexcel_xcbcmac_cra_init, 21688c2ecf20Sopenharmony_ci .cra_exit = safexcel_xcbcmac_cra_exit, 21698c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 21708c2ecf20Sopenharmony_ci }, 21718c2ecf20Sopenharmony_ci }, 21728c2ecf20Sopenharmony_ci }, 21738c2ecf20Sopenharmony_ci}; 21748c2ecf20Sopenharmony_ci 21758c2ecf20Sopenharmony_cistatic int safexcel_cmac_setkey(struct crypto_ahash *tfm, const u8 *key, 21768c2ecf20Sopenharmony_ci unsigned int len) 21778c2ecf20Sopenharmony_ci{ 21788c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 21798c2ecf20Sopenharmony_ci struct crypto_aes_ctx aes; 21808c2ecf20Sopenharmony_ci __be64 consts[4]; 21818c2ecf20Sopenharmony_ci u64 _const[2]; 21828c2ecf20Sopenharmony_ci u8 msb_mask, gfmask; 21838c2ecf20Sopenharmony_ci int ret, i; 21848c2ecf20Sopenharmony_ci 21858c2ecf20Sopenharmony_ci ret = aes_expandkey(&aes, key, len); 21868c2ecf20Sopenharmony_ci if (ret) 21878c2ecf20Sopenharmony_ci return ret; 21888c2ecf20Sopenharmony_ci 21898c2ecf20Sopenharmony_ci for (i = 0; i < len / sizeof(u32); i++) 21908c2ecf20Sopenharmony_ci ctx->base.ipad.word[i + 8] = swab32(aes.key_enc[i]); 21918c2ecf20Sopenharmony_ci 21928c2ecf20Sopenharmony_ci /* precompute the CMAC key material */ 21938c2ecf20Sopenharmony_ci crypto_cipher_clear_flags(ctx->kaes, CRYPTO_TFM_REQ_MASK); 21948c2ecf20Sopenharmony_ci crypto_cipher_set_flags(ctx->kaes, crypto_ahash_get_flags(tfm) & 21958c2ecf20Sopenharmony_ci CRYPTO_TFM_REQ_MASK); 21968c2ecf20Sopenharmony_ci ret = crypto_cipher_setkey(ctx->kaes, key, len); 21978c2ecf20Sopenharmony_ci if (ret) 21988c2ecf20Sopenharmony_ci return ret; 21998c2ecf20Sopenharmony_ci 22008c2ecf20Sopenharmony_ci /* code below borrowed from crypto/cmac.c */ 22018c2ecf20Sopenharmony_ci /* encrypt the zero block */ 22028c2ecf20Sopenharmony_ci memset(consts, 0, AES_BLOCK_SIZE); 22038c2ecf20Sopenharmony_ci crypto_cipher_encrypt_one(ctx->kaes, (u8 *)consts, (u8 *)consts); 22048c2ecf20Sopenharmony_ci 22058c2ecf20Sopenharmony_ci gfmask = 0x87; 22068c2ecf20Sopenharmony_ci _const[0] = be64_to_cpu(consts[1]); 22078c2ecf20Sopenharmony_ci _const[1] = be64_to_cpu(consts[0]); 22088c2ecf20Sopenharmony_ci 22098c2ecf20Sopenharmony_ci /* gf(2^128) multiply zero-ciphertext with u and u^2 */ 22108c2ecf20Sopenharmony_ci for (i = 0; i < 4; i += 2) { 22118c2ecf20Sopenharmony_ci msb_mask = ((s64)_const[1] >> 63) & gfmask; 22128c2ecf20Sopenharmony_ci _const[1] = (_const[1] << 1) | (_const[0] >> 63); 22138c2ecf20Sopenharmony_ci _const[0] = (_const[0] << 1) ^ msb_mask; 22148c2ecf20Sopenharmony_ci 22158c2ecf20Sopenharmony_ci consts[i + 0] = cpu_to_be64(_const[1]); 22168c2ecf20Sopenharmony_ci consts[i + 1] = cpu_to_be64(_const[0]); 22178c2ecf20Sopenharmony_ci } 22188c2ecf20Sopenharmony_ci /* end of code borrowed from crypto/cmac.c */ 22198c2ecf20Sopenharmony_ci 22208c2ecf20Sopenharmony_ci for (i = 0; i < 2 * AES_BLOCK_SIZE / sizeof(u32); i++) 22218c2ecf20Sopenharmony_ci ctx->base.ipad.be[i] = cpu_to_be32(((u32 *)consts)[i]); 22228c2ecf20Sopenharmony_ci 22238c2ecf20Sopenharmony_ci if (len == AES_KEYSIZE_192) { 22248c2ecf20Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC192; 22258c2ecf20Sopenharmony_ci ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE; 22268c2ecf20Sopenharmony_ci } else if (len == AES_KEYSIZE_256) { 22278c2ecf20Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC256; 22288c2ecf20Sopenharmony_ci ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE; 22298c2ecf20Sopenharmony_ci } else { 22308c2ecf20Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128; 22318c2ecf20Sopenharmony_ci ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE; 22328c2ecf20Sopenharmony_ci } 22338c2ecf20Sopenharmony_ci ctx->cbcmac = false; 22348c2ecf20Sopenharmony_ci 22358c2ecf20Sopenharmony_ci memzero_explicit(&aes, sizeof(aes)); 22368c2ecf20Sopenharmony_ci return 0; 22378c2ecf20Sopenharmony_ci} 22388c2ecf20Sopenharmony_ci 22398c2ecf20Sopenharmony_cistruct safexcel_alg_template safexcel_alg_cmac = { 22408c2ecf20Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 22418c2ecf20Sopenharmony_ci .algo_mask = 0, 22428c2ecf20Sopenharmony_ci .alg.ahash = { 22438c2ecf20Sopenharmony_ci .init = safexcel_cbcmac_init, 22448c2ecf20Sopenharmony_ci .update = safexcel_ahash_update, 22458c2ecf20Sopenharmony_ci .final = safexcel_ahash_final, 22468c2ecf20Sopenharmony_ci .finup = safexcel_ahash_finup, 22478c2ecf20Sopenharmony_ci .digest = safexcel_cbcmac_digest, 22488c2ecf20Sopenharmony_ci .setkey = safexcel_cmac_setkey, 22498c2ecf20Sopenharmony_ci .export = safexcel_ahash_export, 22508c2ecf20Sopenharmony_ci .import = safexcel_ahash_import, 22518c2ecf20Sopenharmony_ci .halg = { 22528c2ecf20Sopenharmony_ci .digestsize = AES_BLOCK_SIZE, 22538c2ecf20Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 22548c2ecf20Sopenharmony_ci .base = { 22558c2ecf20Sopenharmony_ci .cra_name = "cmac(aes)", 22568c2ecf20Sopenharmony_ci .cra_driver_name = "safexcel-cmac-aes", 22578c2ecf20Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 22588c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 22598c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 22608c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 22618c2ecf20Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 22628c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 22638c2ecf20Sopenharmony_ci .cra_init = safexcel_xcbcmac_cra_init, 22648c2ecf20Sopenharmony_ci .cra_exit = safexcel_xcbcmac_cra_exit, 22658c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 22668c2ecf20Sopenharmony_ci }, 22678c2ecf20Sopenharmony_ci }, 22688c2ecf20Sopenharmony_ci }, 22698c2ecf20Sopenharmony_ci}; 22708c2ecf20Sopenharmony_ci 22718c2ecf20Sopenharmony_cistatic int safexcel_sm3_init(struct ahash_request *areq) 22728c2ecf20Sopenharmony_ci{ 22738c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 22748c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx(areq); 22758c2ecf20Sopenharmony_ci 22768c2ecf20Sopenharmony_ci memset(req, 0, sizeof(*req)); 22778c2ecf20Sopenharmony_ci 22788c2ecf20Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SM3; 22798c2ecf20Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 22808c2ecf20Sopenharmony_ci req->state_sz = SM3_DIGEST_SIZE; 22818c2ecf20Sopenharmony_ci req->digest_sz = SM3_DIGEST_SIZE; 22828c2ecf20Sopenharmony_ci req->block_sz = SM3_BLOCK_SIZE; 22838c2ecf20Sopenharmony_ci 22848c2ecf20Sopenharmony_ci return 0; 22858c2ecf20Sopenharmony_ci} 22868c2ecf20Sopenharmony_ci 22878c2ecf20Sopenharmony_cistatic int safexcel_sm3_digest(struct ahash_request *areq) 22888c2ecf20Sopenharmony_ci{ 22898c2ecf20Sopenharmony_ci int ret = safexcel_sm3_init(areq); 22908c2ecf20Sopenharmony_ci 22918c2ecf20Sopenharmony_ci if (ret) 22928c2ecf20Sopenharmony_ci return ret; 22938c2ecf20Sopenharmony_ci 22948c2ecf20Sopenharmony_ci return safexcel_ahash_finup(areq); 22958c2ecf20Sopenharmony_ci} 22968c2ecf20Sopenharmony_ci 22978c2ecf20Sopenharmony_cistruct safexcel_alg_template safexcel_alg_sm3 = { 22988c2ecf20Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 22998c2ecf20Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SM3, 23008c2ecf20Sopenharmony_ci .alg.ahash = { 23018c2ecf20Sopenharmony_ci .init = safexcel_sm3_init, 23028c2ecf20Sopenharmony_ci .update = safexcel_ahash_update, 23038c2ecf20Sopenharmony_ci .final = safexcel_ahash_final, 23048c2ecf20Sopenharmony_ci .finup = safexcel_ahash_finup, 23058c2ecf20Sopenharmony_ci .digest = safexcel_sm3_digest, 23068c2ecf20Sopenharmony_ci .export = safexcel_ahash_export, 23078c2ecf20Sopenharmony_ci .import = safexcel_ahash_import, 23088c2ecf20Sopenharmony_ci .halg = { 23098c2ecf20Sopenharmony_ci .digestsize = SM3_DIGEST_SIZE, 23108c2ecf20Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 23118c2ecf20Sopenharmony_ci .base = { 23128c2ecf20Sopenharmony_ci .cra_name = "sm3", 23138c2ecf20Sopenharmony_ci .cra_driver_name = "safexcel-sm3", 23148c2ecf20Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 23158c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 23168c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 23178c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 23188c2ecf20Sopenharmony_ci .cra_blocksize = SM3_BLOCK_SIZE, 23198c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 23208c2ecf20Sopenharmony_ci .cra_init = safexcel_ahash_cra_init, 23218c2ecf20Sopenharmony_ci .cra_exit = safexcel_ahash_cra_exit, 23228c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 23238c2ecf20Sopenharmony_ci }, 23248c2ecf20Sopenharmony_ci }, 23258c2ecf20Sopenharmony_ci }, 23268c2ecf20Sopenharmony_ci}; 23278c2ecf20Sopenharmony_ci 23288c2ecf20Sopenharmony_cistatic int safexcel_hmac_sm3_setkey(struct crypto_ahash *tfm, const u8 *key, 23298c2ecf20Sopenharmony_ci unsigned int keylen) 23308c2ecf20Sopenharmony_ci{ 23318c2ecf20Sopenharmony_ci return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sm3", 23328c2ecf20Sopenharmony_ci SM3_DIGEST_SIZE); 23338c2ecf20Sopenharmony_ci} 23348c2ecf20Sopenharmony_ci 23358c2ecf20Sopenharmony_cistatic int safexcel_hmac_sm3_init(struct ahash_request *areq) 23368c2ecf20Sopenharmony_ci{ 23378c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 23388c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx(areq); 23398c2ecf20Sopenharmony_ci 23408c2ecf20Sopenharmony_ci memset(req, 0, sizeof(*req)); 23418c2ecf20Sopenharmony_ci 23428c2ecf20Sopenharmony_ci /* Start from ipad precompute */ 23438c2ecf20Sopenharmony_ci memcpy(req->state, &ctx->base.ipad, SM3_DIGEST_SIZE); 23448c2ecf20Sopenharmony_ci /* Already processed the key^ipad part now! */ 23458c2ecf20Sopenharmony_ci req->len = SM3_BLOCK_SIZE; 23468c2ecf20Sopenharmony_ci req->processed = SM3_BLOCK_SIZE; 23478c2ecf20Sopenharmony_ci 23488c2ecf20Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SM3; 23498c2ecf20Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 23508c2ecf20Sopenharmony_ci req->state_sz = SM3_DIGEST_SIZE; 23518c2ecf20Sopenharmony_ci req->digest_sz = SM3_DIGEST_SIZE; 23528c2ecf20Sopenharmony_ci req->block_sz = SM3_BLOCK_SIZE; 23538c2ecf20Sopenharmony_ci req->hmac = true; 23548c2ecf20Sopenharmony_ci 23558c2ecf20Sopenharmony_ci return 0; 23568c2ecf20Sopenharmony_ci} 23578c2ecf20Sopenharmony_ci 23588c2ecf20Sopenharmony_cistatic int safexcel_hmac_sm3_digest(struct ahash_request *areq) 23598c2ecf20Sopenharmony_ci{ 23608c2ecf20Sopenharmony_ci int ret = safexcel_hmac_sm3_init(areq); 23618c2ecf20Sopenharmony_ci 23628c2ecf20Sopenharmony_ci if (ret) 23638c2ecf20Sopenharmony_ci return ret; 23648c2ecf20Sopenharmony_ci 23658c2ecf20Sopenharmony_ci return safexcel_ahash_finup(areq); 23668c2ecf20Sopenharmony_ci} 23678c2ecf20Sopenharmony_ci 23688c2ecf20Sopenharmony_cistruct safexcel_alg_template safexcel_alg_hmac_sm3 = { 23698c2ecf20Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 23708c2ecf20Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SM3, 23718c2ecf20Sopenharmony_ci .alg.ahash = { 23728c2ecf20Sopenharmony_ci .init = safexcel_hmac_sm3_init, 23738c2ecf20Sopenharmony_ci .update = safexcel_ahash_update, 23748c2ecf20Sopenharmony_ci .final = safexcel_ahash_final, 23758c2ecf20Sopenharmony_ci .finup = safexcel_ahash_finup, 23768c2ecf20Sopenharmony_ci .digest = safexcel_hmac_sm3_digest, 23778c2ecf20Sopenharmony_ci .setkey = safexcel_hmac_sm3_setkey, 23788c2ecf20Sopenharmony_ci .export = safexcel_ahash_export, 23798c2ecf20Sopenharmony_ci .import = safexcel_ahash_import, 23808c2ecf20Sopenharmony_ci .halg = { 23818c2ecf20Sopenharmony_ci .digestsize = SM3_DIGEST_SIZE, 23828c2ecf20Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 23838c2ecf20Sopenharmony_ci .base = { 23848c2ecf20Sopenharmony_ci .cra_name = "hmac(sm3)", 23858c2ecf20Sopenharmony_ci .cra_driver_name = "safexcel-hmac-sm3", 23868c2ecf20Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 23878c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 23888c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 23898c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 23908c2ecf20Sopenharmony_ci .cra_blocksize = SM3_BLOCK_SIZE, 23918c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 23928c2ecf20Sopenharmony_ci .cra_init = safexcel_ahash_cra_init, 23938c2ecf20Sopenharmony_ci .cra_exit = safexcel_ahash_cra_exit, 23948c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 23958c2ecf20Sopenharmony_ci }, 23968c2ecf20Sopenharmony_ci }, 23978c2ecf20Sopenharmony_ci }, 23988c2ecf20Sopenharmony_ci}; 23998c2ecf20Sopenharmony_ci 24008c2ecf20Sopenharmony_cistatic int safexcel_sha3_224_init(struct ahash_request *areq) 24018c2ecf20Sopenharmony_ci{ 24028c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 24038c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 24048c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx(areq); 24058c2ecf20Sopenharmony_ci 24068c2ecf20Sopenharmony_ci memset(req, 0, sizeof(*req)); 24078c2ecf20Sopenharmony_ci 24088c2ecf20Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_224; 24098c2ecf20Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_INITIAL; 24108c2ecf20Sopenharmony_ci req->state_sz = SHA3_224_DIGEST_SIZE; 24118c2ecf20Sopenharmony_ci req->digest_sz = SHA3_224_DIGEST_SIZE; 24128c2ecf20Sopenharmony_ci req->block_sz = SHA3_224_BLOCK_SIZE; 24138c2ecf20Sopenharmony_ci ctx->do_fallback = false; 24148c2ecf20Sopenharmony_ci ctx->fb_init_done = false; 24158c2ecf20Sopenharmony_ci return 0; 24168c2ecf20Sopenharmony_ci} 24178c2ecf20Sopenharmony_ci 24188c2ecf20Sopenharmony_cistatic int safexcel_sha3_fbcheck(struct ahash_request *req) 24198c2ecf20Sopenharmony_ci{ 24208c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 24218c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 24228c2ecf20Sopenharmony_ci struct ahash_request *subreq = ahash_request_ctx(req); 24238c2ecf20Sopenharmony_ci int ret = 0; 24248c2ecf20Sopenharmony_ci 24258c2ecf20Sopenharmony_ci if (ctx->do_fallback) { 24268c2ecf20Sopenharmony_ci ahash_request_set_tfm(subreq, ctx->fback); 24278c2ecf20Sopenharmony_ci ahash_request_set_callback(subreq, req->base.flags, 24288c2ecf20Sopenharmony_ci req->base.complete, req->base.data); 24298c2ecf20Sopenharmony_ci ahash_request_set_crypt(subreq, req->src, req->result, 24308c2ecf20Sopenharmony_ci req->nbytes); 24318c2ecf20Sopenharmony_ci if (!ctx->fb_init_done) { 24328c2ecf20Sopenharmony_ci if (ctx->fb_do_setkey) { 24338c2ecf20Sopenharmony_ci /* Set fallback cipher HMAC key */ 24348c2ecf20Sopenharmony_ci u8 key[SHA3_224_BLOCK_SIZE]; 24358c2ecf20Sopenharmony_ci 24368c2ecf20Sopenharmony_ci memcpy(key, &ctx->base.ipad, 24378c2ecf20Sopenharmony_ci crypto_ahash_blocksize(ctx->fback) / 2); 24388c2ecf20Sopenharmony_ci memcpy(key + 24398c2ecf20Sopenharmony_ci crypto_ahash_blocksize(ctx->fback) / 2, 24408c2ecf20Sopenharmony_ci &ctx->base.opad, 24418c2ecf20Sopenharmony_ci crypto_ahash_blocksize(ctx->fback) / 2); 24428c2ecf20Sopenharmony_ci ret = crypto_ahash_setkey(ctx->fback, key, 24438c2ecf20Sopenharmony_ci crypto_ahash_blocksize(ctx->fback)); 24448c2ecf20Sopenharmony_ci memzero_explicit(key, 24458c2ecf20Sopenharmony_ci crypto_ahash_blocksize(ctx->fback)); 24468c2ecf20Sopenharmony_ci ctx->fb_do_setkey = false; 24478c2ecf20Sopenharmony_ci } 24488c2ecf20Sopenharmony_ci ret = ret ?: crypto_ahash_init(subreq); 24498c2ecf20Sopenharmony_ci ctx->fb_init_done = true; 24508c2ecf20Sopenharmony_ci } 24518c2ecf20Sopenharmony_ci } 24528c2ecf20Sopenharmony_ci return ret; 24538c2ecf20Sopenharmony_ci} 24548c2ecf20Sopenharmony_ci 24558c2ecf20Sopenharmony_cistatic int safexcel_sha3_update(struct ahash_request *req) 24568c2ecf20Sopenharmony_ci{ 24578c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 24588c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 24598c2ecf20Sopenharmony_ci struct ahash_request *subreq = ahash_request_ctx(req); 24608c2ecf20Sopenharmony_ci 24618c2ecf20Sopenharmony_ci ctx->do_fallback = true; 24628c2ecf20Sopenharmony_ci return safexcel_sha3_fbcheck(req) ?: crypto_ahash_update(subreq); 24638c2ecf20Sopenharmony_ci} 24648c2ecf20Sopenharmony_ci 24658c2ecf20Sopenharmony_cistatic int safexcel_sha3_final(struct ahash_request *req) 24668c2ecf20Sopenharmony_ci{ 24678c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 24688c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 24698c2ecf20Sopenharmony_ci struct ahash_request *subreq = ahash_request_ctx(req); 24708c2ecf20Sopenharmony_ci 24718c2ecf20Sopenharmony_ci ctx->do_fallback = true; 24728c2ecf20Sopenharmony_ci return safexcel_sha3_fbcheck(req) ?: crypto_ahash_final(subreq); 24738c2ecf20Sopenharmony_ci} 24748c2ecf20Sopenharmony_ci 24758c2ecf20Sopenharmony_cistatic int safexcel_sha3_finup(struct ahash_request *req) 24768c2ecf20Sopenharmony_ci{ 24778c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 24788c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 24798c2ecf20Sopenharmony_ci struct ahash_request *subreq = ahash_request_ctx(req); 24808c2ecf20Sopenharmony_ci 24818c2ecf20Sopenharmony_ci ctx->do_fallback |= !req->nbytes; 24828c2ecf20Sopenharmony_ci if (ctx->do_fallback) 24838c2ecf20Sopenharmony_ci /* Update or ex/import happened or len 0, cannot use the HW */ 24848c2ecf20Sopenharmony_ci return safexcel_sha3_fbcheck(req) ?: 24858c2ecf20Sopenharmony_ci crypto_ahash_finup(subreq); 24868c2ecf20Sopenharmony_ci else 24878c2ecf20Sopenharmony_ci return safexcel_ahash_finup(req); 24888c2ecf20Sopenharmony_ci} 24898c2ecf20Sopenharmony_ci 24908c2ecf20Sopenharmony_cistatic int safexcel_sha3_digest_fallback(struct ahash_request *req) 24918c2ecf20Sopenharmony_ci{ 24928c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 24938c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 24948c2ecf20Sopenharmony_ci struct ahash_request *subreq = ahash_request_ctx(req); 24958c2ecf20Sopenharmony_ci 24968c2ecf20Sopenharmony_ci ctx->do_fallback = true; 24978c2ecf20Sopenharmony_ci ctx->fb_init_done = false; 24988c2ecf20Sopenharmony_ci return safexcel_sha3_fbcheck(req) ?: crypto_ahash_finup(subreq); 24998c2ecf20Sopenharmony_ci} 25008c2ecf20Sopenharmony_ci 25018c2ecf20Sopenharmony_cistatic int safexcel_sha3_224_digest(struct ahash_request *req) 25028c2ecf20Sopenharmony_ci{ 25038c2ecf20Sopenharmony_ci if (req->nbytes) 25048c2ecf20Sopenharmony_ci return safexcel_sha3_224_init(req) ?: safexcel_ahash_finup(req); 25058c2ecf20Sopenharmony_ci 25068c2ecf20Sopenharmony_ci /* HW cannot do zero length hash, use fallback instead */ 25078c2ecf20Sopenharmony_ci return safexcel_sha3_digest_fallback(req); 25088c2ecf20Sopenharmony_ci} 25098c2ecf20Sopenharmony_ci 25108c2ecf20Sopenharmony_cistatic int safexcel_sha3_export(struct ahash_request *req, void *out) 25118c2ecf20Sopenharmony_ci{ 25128c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 25138c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 25148c2ecf20Sopenharmony_ci struct ahash_request *subreq = ahash_request_ctx(req); 25158c2ecf20Sopenharmony_ci 25168c2ecf20Sopenharmony_ci ctx->do_fallback = true; 25178c2ecf20Sopenharmony_ci return safexcel_sha3_fbcheck(req) ?: crypto_ahash_export(subreq, out); 25188c2ecf20Sopenharmony_ci} 25198c2ecf20Sopenharmony_ci 25208c2ecf20Sopenharmony_cistatic int safexcel_sha3_import(struct ahash_request *req, const void *in) 25218c2ecf20Sopenharmony_ci{ 25228c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 25238c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 25248c2ecf20Sopenharmony_ci struct ahash_request *subreq = ahash_request_ctx(req); 25258c2ecf20Sopenharmony_ci 25268c2ecf20Sopenharmony_ci ctx->do_fallback = true; 25278c2ecf20Sopenharmony_ci return safexcel_sha3_fbcheck(req) ?: crypto_ahash_import(subreq, in); 25288c2ecf20Sopenharmony_ci // return safexcel_ahash_import(req, in); 25298c2ecf20Sopenharmony_ci} 25308c2ecf20Sopenharmony_ci 25318c2ecf20Sopenharmony_cistatic int safexcel_sha3_cra_init(struct crypto_tfm *tfm) 25328c2ecf20Sopenharmony_ci{ 25338c2ecf20Sopenharmony_ci struct crypto_ahash *ahash = __crypto_ahash_cast(tfm); 25348c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 25358c2ecf20Sopenharmony_ci 25368c2ecf20Sopenharmony_ci safexcel_ahash_cra_init(tfm); 25378c2ecf20Sopenharmony_ci 25388c2ecf20Sopenharmony_ci /* Allocate fallback implementation */ 25398c2ecf20Sopenharmony_ci ctx->fback = crypto_alloc_ahash(crypto_tfm_alg_name(tfm), 0, 25408c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 25418c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK); 25428c2ecf20Sopenharmony_ci if (IS_ERR(ctx->fback)) 25438c2ecf20Sopenharmony_ci return PTR_ERR(ctx->fback); 25448c2ecf20Sopenharmony_ci 25458c2ecf20Sopenharmony_ci /* Update statesize from fallback algorithm! */ 25468c2ecf20Sopenharmony_ci crypto_hash_alg_common(ahash)->statesize = 25478c2ecf20Sopenharmony_ci crypto_ahash_statesize(ctx->fback); 25488c2ecf20Sopenharmony_ci crypto_ahash_set_reqsize(ahash, max(sizeof(struct safexcel_ahash_req), 25498c2ecf20Sopenharmony_ci sizeof(struct ahash_request) + 25508c2ecf20Sopenharmony_ci crypto_ahash_reqsize(ctx->fback))); 25518c2ecf20Sopenharmony_ci return 0; 25528c2ecf20Sopenharmony_ci} 25538c2ecf20Sopenharmony_ci 25548c2ecf20Sopenharmony_cistatic void safexcel_sha3_cra_exit(struct crypto_tfm *tfm) 25558c2ecf20Sopenharmony_ci{ 25568c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 25578c2ecf20Sopenharmony_ci 25588c2ecf20Sopenharmony_ci crypto_free_ahash(ctx->fback); 25598c2ecf20Sopenharmony_ci safexcel_ahash_cra_exit(tfm); 25608c2ecf20Sopenharmony_ci} 25618c2ecf20Sopenharmony_ci 25628c2ecf20Sopenharmony_cistruct safexcel_alg_template safexcel_alg_sha3_224 = { 25638c2ecf20Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 25648c2ecf20Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA3, 25658c2ecf20Sopenharmony_ci .alg.ahash = { 25668c2ecf20Sopenharmony_ci .init = safexcel_sha3_224_init, 25678c2ecf20Sopenharmony_ci .update = safexcel_sha3_update, 25688c2ecf20Sopenharmony_ci .final = safexcel_sha3_final, 25698c2ecf20Sopenharmony_ci .finup = safexcel_sha3_finup, 25708c2ecf20Sopenharmony_ci .digest = safexcel_sha3_224_digest, 25718c2ecf20Sopenharmony_ci .export = safexcel_sha3_export, 25728c2ecf20Sopenharmony_ci .import = safexcel_sha3_import, 25738c2ecf20Sopenharmony_ci .halg = { 25748c2ecf20Sopenharmony_ci .digestsize = SHA3_224_DIGEST_SIZE, 25758c2ecf20Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 25768c2ecf20Sopenharmony_ci .base = { 25778c2ecf20Sopenharmony_ci .cra_name = "sha3-224", 25788c2ecf20Sopenharmony_ci .cra_driver_name = "safexcel-sha3-224", 25798c2ecf20Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 25808c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 25818c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY | 25828c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 25838c2ecf20Sopenharmony_ci .cra_blocksize = SHA3_224_BLOCK_SIZE, 25848c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 25858c2ecf20Sopenharmony_ci .cra_init = safexcel_sha3_cra_init, 25868c2ecf20Sopenharmony_ci .cra_exit = safexcel_sha3_cra_exit, 25878c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 25888c2ecf20Sopenharmony_ci }, 25898c2ecf20Sopenharmony_ci }, 25908c2ecf20Sopenharmony_ci }, 25918c2ecf20Sopenharmony_ci}; 25928c2ecf20Sopenharmony_ci 25938c2ecf20Sopenharmony_cistatic int safexcel_sha3_256_init(struct ahash_request *areq) 25948c2ecf20Sopenharmony_ci{ 25958c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 25968c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 25978c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx(areq); 25988c2ecf20Sopenharmony_ci 25998c2ecf20Sopenharmony_ci memset(req, 0, sizeof(*req)); 26008c2ecf20Sopenharmony_ci 26018c2ecf20Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_256; 26028c2ecf20Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_INITIAL; 26038c2ecf20Sopenharmony_ci req->state_sz = SHA3_256_DIGEST_SIZE; 26048c2ecf20Sopenharmony_ci req->digest_sz = SHA3_256_DIGEST_SIZE; 26058c2ecf20Sopenharmony_ci req->block_sz = SHA3_256_BLOCK_SIZE; 26068c2ecf20Sopenharmony_ci ctx->do_fallback = false; 26078c2ecf20Sopenharmony_ci ctx->fb_init_done = false; 26088c2ecf20Sopenharmony_ci return 0; 26098c2ecf20Sopenharmony_ci} 26108c2ecf20Sopenharmony_ci 26118c2ecf20Sopenharmony_cistatic int safexcel_sha3_256_digest(struct ahash_request *req) 26128c2ecf20Sopenharmony_ci{ 26138c2ecf20Sopenharmony_ci if (req->nbytes) 26148c2ecf20Sopenharmony_ci return safexcel_sha3_256_init(req) ?: safexcel_ahash_finup(req); 26158c2ecf20Sopenharmony_ci 26168c2ecf20Sopenharmony_ci /* HW cannot do zero length hash, use fallback instead */ 26178c2ecf20Sopenharmony_ci return safexcel_sha3_digest_fallback(req); 26188c2ecf20Sopenharmony_ci} 26198c2ecf20Sopenharmony_ci 26208c2ecf20Sopenharmony_cistruct safexcel_alg_template safexcel_alg_sha3_256 = { 26218c2ecf20Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 26228c2ecf20Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA3, 26238c2ecf20Sopenharmony_ci .alg.ahash = { 26248c2ecf20Sopenharmony_ci .init = safexcel_sha3_256_init, 26258c2ecf20Sopenharmony_ci .update = safexcel_sha3_update, 26268c2ecf20Sopenharmony_ci .final = safexcel_sha3_final, 26278c2ecf20Sopenharmony_ci .finup = safexcel_sha3_finup, 26288c2ecf20Sopenharmony_ci .digest = safexcel_sha3_256_digest, 26298c2ecf20Sopenharmony_ci .export = safexcel_sha3_export, 26308c2ecf20Sopenharmony_ci .import = safexcel_sha3_import, 26318c2ecf20Sopenharmony_ci .halg = { 26328c2ecf20Sopenharmony_ci .digestsize = SHA3_256_DIGEST_SIZE, 26338c2ecf20Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 26348c2ecf20Sopenharmony_ci .base = { 26358c2ecf20Sopenharmony_ci .cra_name = "sha3-256", 26368c2ecf20Sopenharmony_ci .cra_driver_name = "safexcel-sha3-256", 26378c2ecf20Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 26388c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 26398c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY | 26408c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 26418c2ecf20Sopenharmony_ci .cra_blocksize = SHA3_256_BLOCK_SIZE, 26428c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 26438c2ecf20Sopenharmony_ci .cra_init = safexcel_sha3_cra_init, 26448c2ecf20Sopenharmony_ci .cra_exit = safexcel_sha3_cra_exit, 26458c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 26468c2ecf20Sopenharmony_ci }, 26478c2ecf20Sopenharmony_ci }, 26488c2ecf20Sopenharmony_ci }, 26498c2ecf20Sopenharmony_ci}; 26508c2ecf20Sopenharmony_ci 26518c2ecf20Sopenharmony_cistatic int safexcel_sha3_384_init(struct ahash_request *areq) 26528c2ecf20Sopenharmony_ci{ 26538c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 26548c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 26558c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx(areq); 26568c2ecf20Sopenharmony_ci 26578c2ecf20Sopenharmony_ci memset(req, 0, sizeof(*req)); 26588c2ecf20Sopenharmony_ci 26598c2ecf20Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_384; 26608c2ecf20Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_INITIAL; 26618c2ecf20Sopenharmony_ci req->state_sz = SHA3_384_DIGEST_SIZE; 26628c2ecf20Sopenharmony_ci req->digest_sz = SHA3_384_DIGEST_SIZE; 26638c2ecf20Sopenharmony_ci req->block_sz = SHA3_384_BLOCK_SIZE; 26648c2ecf20Sopenharmony_ci ctx->do_fallback = false; 26658c2ecf20Sopenharmony_ci ctx->fb_init_done = false; 26668c2ecf20Sopenharmony_ci return 0; 26678c2ecf20Sopenharmony_ci} 26688c2ecf20Sopenharmony_ci 26698c2ecf20Sopenharmony_cistatic int safexcel_sha3_384_digest(struct ahash_request *req) 26708c2ecf20Sopenharmony_ci{ 26718c2ecf20Sopenharmony_ci if (req->nbytes) 26728c2ecf20Sopenharmony_ci return safexcel_sha3_384_init(req) ?: safexcel_ahash_finup(req); 26738c2ecf20Sopenharmony_ci 26748c2ecf20Sopenharmony_ci /* HW cannot do zero length hash, use fallback instead */ 26758c2ecf20Sopenharmony_ci return safexcel_sha3_digest_fallback(req); 26768c2ecf20Sopenharmony_ci} 26778c2ecf20Sopenharmony_ci 26788c2ecf20Sopenharmony_cistruct safexcel_alg_template safexcel_alg_sha3_384 = { 26798c2ecf20Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 26808c2ecf20Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA3, 26818c2ecf20Sopenharmony_ci .alg.ahash = { 26828c2ecf20Sopenharmony_ci .init = safexcel_sha3_384_init, 26838c2ecf20Sopenharmony_ci .update = safexcel_sha3_update, 26848c2ecf20Sopenharmony_ci .final = safexcel_sha3_final, 26858c2ecf20Sopenharmony_ci .finup = safexcel_sha3_finup, 26868c2ecf20Sopenharmony_ci .digest = safexcel_sha3_384_digest, 26878c2ecf20Sopenharmony_ci .export = safexcel_sha3_export, 26888c2ecf20Sopenharmony_ci .import = safexcel_sha3_import, 26898c2ecf20Sopenharmony_ci .halg = { 26908c2ecf20Sopenharmony_ci .digestsize = SHA3_384_DIGEST_SIZE, 26918c2ecf20Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 26928c2ecf20Sopenharmony_ci .base = { 26938c2ecf20Sopenharmony_ci .cra_name = "sha3-384", 26948c2ecf20Sopenharmony_ci .cra_driver_name = "safexcel-sha3-384", 26958c2ecf20Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 26968c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 26978c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY | 26988c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 26998c2ecf20Sopenharmony_ci .cra_blocksize = SHA3_384_BLOCK_SIZE, 27008c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 27018c2ecf20Sopenharmony_ci .cra_init = safexcel_sha3_cra_init, 27028c2ecf20Sopenharmony_ci .cra_exit = safexcel_sha3_cra_exit, 27038c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 27048c2ecf20Sopenharmony_ci }, 27058c2ecf20Sopenharmony_ci }, 27068c2ecf20Sopenharmony_ci }, 27078c2ecf20Sopenharmony_ci}; 27088c2ecf20Sopenharmony_ci 27098c2ecf20Sopenharmony_cistatic int safexcel_sha3_512_init(struct ahash_request *areq) 27108c2ecf20Sopenharmony_ci{ 27118c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 27128c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 27138c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx(areq); 27148c2ecf20Sopenharmony_ci 27158c2ecf20Sopenharmony_ci memset(req, 0, sizeof(*req)); 27168c2ecf20Sopenharmony_ci 27178c2ecf20Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_512; 27188c2ecf20Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_INITIAL; 27198c2ecf20Sopenharmony_ci req->state_sz = SHA3_512_DIGEST_SIZE; 27208c2ecf20Sopenharmony_ci req->digest_sz = SHA3_512_DIGEST_SIZE; 27218c2ecf20Sopenharmony_ci req->block_sz = SHA3_512_BLOCK_SIZE; 27228c2ecf20Sopenharmony_ci ctx->do_fallback = false; 27238c2ecf20Sopenharmony_ci ctx->fb_init_done = false; 27248c2ecf20Sopenharmony_ci return 0; 27258c2ecf20Sopenharmony_ci} 27268c2ecf20Sopenharmony_ci 27278c2ecf20Sopenharmony_cistatic int safexcel_sha3_512_digest(struct ahash_request *req) 27288c2ecf20Sopenharmony_ci{ 27298c2ecf20Sopenharmony_ci if (req->nbytes) 27308c2ecf20Sopenharmony_ci return safexcel_sha3_512_init(req) ?: safexcel_ahash_finup(req); 27318c2ecf20Sopenharmony_ci 27328c2ecf20Sopenharmony_ci /* HW cannot do zero length hash, use fallback instead */ 27338c2ecf20Sopenharmony_ci return safexcel_sha3_digest_fallback(req); 27348c2ecf20Sopenharmony_ci} 27358c2ecf20Sopenharmony_ci 27368c2ecf20Sopenharmony_cistruct safexcel_alg_template safexcel_alg_sha3_512 = { 27378c2ecf20Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 27388c2ecf20Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA3, 27398c2ecf20Sopenharmony_ci .alg.ahash = { 27408c2ecf20Sopenharmony_ci .init = safexcel_sha3_512_init, 27418c2ecf20Sopenharmony_ci .update = safexcel_sha3_update, 27428c2ecf20Sopenharmony_ci .final = safexcel_sha3_final, 27438c2ecf20Sopenharmony_ci .finup = safexcel_sha3_finup, 27448c2ecf20Sopenharmony_ci .digest = safexcel_sha3_512_digest, 27458c2ecf20Sopenharmony_ci .export = safexcel_sha3_export, 27468c2ecf20Sopenharmony_ci .import = safexcel_sha3_import, 27478c2ecf20Sopenharmony_ci .halg = { 27488c2ecf20Sopenharmony_ci .digestsize = SHA3_512_DIGEST_SIZE, 27498c2ecf20Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 27508c2ecf20Sopenharmony_ci .base = { 27518c2ecf20Sopenharmony_ci .cra_name = "sha3-512", 27528c2ecf20Sopenharmony_ci .cra_driver_name = "safexcel-sha3-512", 27538c2ecf20Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 27548c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 27558c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY | 27568c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 27578c2ecf20Sopenharmony_ci .cra_blocksize = SHA3_512_BLOCK_SIZE, 27588c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 27598c2ecf20Sopenharmony_ci .cra_init = safexcel_sha3_cra_init, 27608c2ecf20Sopenharmony_ci .cra_exit = safexcel_sha3_cra_exit, 27618c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 27628c2ecf20Sopenharmony_ci }, 27638c2ecf20Sopenharmony_ci }, 27648c2ecf20Sopenharmony_ci }, 27658c2ecf20Sopenharmony_ci}; 27668c2ecf20Sopenharmony_ci 27678c2ecf20Sopenharmony_cistatic int safexcel_hmac_sha3_cra_init(struct crypto_tfm *tfm, const char *alg) 27688c2ecf20Sopenharmony_ci{ 27698c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 27708c2ecf20Sopenharmony_ci int ret; 27718c2ecf20Sopenharmony_ci 27728c2ecf20Sopenharmony_ci ret = safexcel_sha3_cra_init(tfm); 27738c2ecf20Sopenharmony_ci if (ret) 27748c2ecf20Sopenharmony_ci return ret; 27758c2ecf20Sopenharmony_ci 27768c2ecf20Sopenharmony_ci /* Allocate precalc basic digest implementation */ 27778c2ecf20Sopenharmony_ci ctx->shpre = crypto_alloc_shash(alg, 0, CRYPTO_ALG_NEED_FALLBACK); 27788c2ecf20Sopenharmony_ci if (IS_ERR(ctx->shpre)) 27798c2ecf20Sopenharmony_ci return PTR_ERR(ctx->shpre); 27808c2ecf20Sopenharmony_ci 27818c2ecf20Sopenharmony_ci ctx->shdesc = kmalloc(sizeof(*ctx->shdesc) + 27828c2ecf20Sopenharmony_ci crypto_shash_descsize(ctx->shpre), GFP_KERNEL); 27838c2ecf20Sopenharmony_ci if (!ctx->shdesc) { 27848c2ecf20Sopenharmony_ci crypto_free_shash(ctx->shpre); 27858c2ecf20Sopenharmony_ci return -ENOMEM; 27868c2ecf20Sopenharmony_ci } 27878c2ecf20Sopenharmony_ci ctx->shdesc->tfm = ctx->shpre; 27888c2ecf20Sopenharmony_ci return 0; 27898c2ecf20Sopenharmony_ci} 27908c2ecf20Sopenharmony_ci 27918c2ecf20Sopenharmony_cistatic void safexcel_hmac_sha3_cra_exit(struct crypto_tfm *tfm) 27928c2ecf20Sopenharmony_ci{ 27938c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 27948c2ecf20Sopenharmony_ci 27958c2ecf20Sopenharmony_ci crypto_free_ahash(ctx->fback); 27968c2ecf20Sopenharmony_ci crypto_free_shash(ctx->shpre); 27978c2ecf20Sopenharmony_ci kfree(ctx->shdesc); 27988c2ecf20Sopenharmony_ci safexcel_ahash_cra_exit(tfm); 27998c2ecf20Sopenharmony_ci} 28008c2ecf20Sopenharmony_ci 28018c2ecf20Sopenharmony_cistatic int safexcel_hmac_sha3_setkey(struct crypto_ahash *tfm, const u8 *key, 28028c2ecf20Sopenharmony_ci unsigned int keylen) 28038c2ecf20Sopenharmony_ci{ 28048c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 28058c2ecf20Sopenharmony_ci int ret = 0; 28068c2ecf20Sopenharmony_ci 28078c2ecf20Sopenharmony_ci if (keylen > crypto_ahash_blocksize(tfm)) { 28088c2ecf20Sopenharmony_ci /* 28098c2ecf20Sopenharmony_ci * If the key is larger than the blocksize, then hash it 28108c2ecf20Sopenharmony_ci * first using our fallback cipher 28118c2ecf20Sopenharmony_ci */ 28128c2ecf20Sopenharmony_ci ret = crypto_shash_digest(ctx->shdesc, key, keylen, 28138c2ecf20Sopenharmony_ci ctx->base.ipad.byte); 28148c2ecf20Sopenharmony_ci keylen = crypto_shash_digestsize(ctx->shpre); 28158c2ecf20Sopenharmony_ci 28168c2ecf20Sopenharmony_ci /* 28178c2ecf20Sopenharmony_ci * If the digest is larger than half the blocksize, we need to 28188c2ecf20Sopenharmony_ci * move the rest to opad due to the way our HMAC infra works. 28198c2ecf20Sopenharmony_ci */ 28208c2ecf20Sopenharmony_ci if (keylen > crypto_ahash_blocksize(tfm) / 2) 28218c2ecf20Sopenharmony_ci /* Buffers overlap, need to use memmove iso memcpy! */ 28228c2ecf20Sopenharmony_ci memmove(&ctx->base.opad, 28238c2ecf20Sopenharmony_ci ctx->base.ipad.byte + 28248c2ecf20Sopenharmony_ci crypto_ahash_blocksize(tfm) / 2, 28258c2ecf20Sopenharmony_ci keylen - crypto_ahash_blocksize(tfm) / 2); 28268c2ecf20Sopenharmony_ci } else { 28278c2ecf20Sopenharmony_ci /* 28288c2ecf20Sopenharmony_ci * Copy the key to our ipad & opad buffers 28298c2ecf20Sopenharmony_ci * Note that ipad and opad each contain one half of the key, 28308c2ecf20Sopenharmony_ci * to match the existing HMAC driver infrastructure. 28318c2ecf20Sopenharmony_ci */ 28328c2ecf20Sopenharmony_ci if (keylen <= crypto_ahash_blocksize(tfm) / 2) { 28338c2ecf20Sopenharmony_ci memcpy(&ctx->base.ipad, key, keylen); 28348c2ecf20Sopenharmony_ci } else { 28358c2ecf20Sopenharmony_ci memcpy(&ctx->base.ipad, key, 28368c2ecf20Sopenharmony_ci crypto_ahash_blocksize(tfm) / 2); 28378c2ecf20Sopenharmony_ci memcpy(&ctx->base.opad, 28388c2ecf20Sopenharmony_ci key + crypto_ahash_blocksize(tfm) / 2, 28398c2ecf20Sopenharmony_ci keylen - crypto_ahash_blocksize(tfm) / 2); 28408c2ecf20Sopenharmony_ci } 28418c2ecf20Sopenharmony_ci } 28428c2ecf20Sopenharmony_ci 28438c2ecf20Sopenharmony_ci /* Pad key with zeroes */ 28448c2ecf20Sopenharmony_ci if (keylen <= crypto_ahash_blocksize(tfm) / 2) { 28458c2ecf20Sopenharmony_ci memset(ctx->base.ipad.byte + keylen, 0, 28468c2ecf20Sopenharmony_ci crypto_ahash_blocksize(tfm) / 2 - keylen); 28478c2ecf20Sopenharmony_ci memset(&ctx->base.opad, 0, crypto_ahash_blocksize(tfm) / 2); 28488c2ecf20Sopenharmony_ci } else { 28498c2ecf20Sopenharmony_ci memset(ctx->base.opad.byte + keylen - 28508c2ecf20Sopenharmony_ci crypto_ahash_blocksize(tfm) / 2, 0, 28518c2ecf20Sopenharmony_ci crypto_ahash_blocksize(tfm) - keylen); 28528c2ecf20Sopenharmony_ci } 28538c2ecf20Sopenharmony_ci 28548c2ecf20Sopenharmony_ci /* If doing fallback, still need to set the new key! */ 28558c2ecf20Sopenharmony_ci ctx->fb_do_setkey = true; 28568c2ecf20Sopenharmony_ci return ret; 28578c2ecf20Sopenharmony_ci} 28588c2ecf20Sopenharmony_ci 28598c2ecf20Sopenharmony_cistatic int safexcel_hmac_sha3_224_init(struct ahash_request *areq) 28608c2ecf20Sopenharmony_ci{ 28618c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 28628c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 28638c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx(areq); 28648c2ecf20Sopenharmony_ci 28658c2ecf20Sopenharmony_ci memset(req, 0, sizeof(*req)); 28668c2ecf20Sopenharmony_ci 28678c2ecf20Sopenharmony_ci /* Copy (half of) the key */ 28688c2ecf20Sopenharmony_ci memcpy(req->state, &ctx->base.ipad, SHA3_224_BLOCK_SIZE / 2); 28698c2ecf20Sopenharmony_ci /* Start of HMAC should have len == processed == blocksize */ 28708c2ecf20Sopenharmony_ci req->len = SHA3_224_BLOCK_SIZE; 28718c2ecf20Sopenharmony_ci req->processed = SHA3_224_BLOCK_SIZE; 28728c2ecf20Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_224; 28738c2ecf20Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_HMAC; 28748c2ecf20Sopenharmony_ci req->state_sz = SHA3_224_BLOCK_SIZE / 2; 28758c2ecf20Sopenharmony_ci req->digest_sz = SHA3_224_DIGEST_SIZE; 28768c2ecf20Sopenharmony_ci req->block_sz = SHA3_224_BLOCK_SIZE; 28778c2ecf20Sopenharmony_ci req->hmac = true; 28788c2ecf20Sopenharmony_ci ctx->do_fallback = false; 28798c2ecf20Sopenharmony_ci ctx->fb_init_done = false; 28808c2ecf20Sopenharmony_ci return 0; 28818c2ecf20Sopenharmony_ci} 28828c2ecf20Sopenharmony_ci 28838c2ecf20Sopenharmony_cistatic int safexcel_hmac_sha3_224_digest(struct ahash_request *req) 28848c2ecf20Sopenharmony_ci{ 28858c2ecf20Sopenharmony_ci if (req->nbytes) 28868c2ecf20Sopenharmony_ci return safexcel_hmac_sha3_224_init(req) ?: 28878c2ecf20Sopenharmony_ci safexcel_ahash_finup(req); 28888c2ecf20Sopenharmony_ci 28898c2ecf20Sopenharmony_ci /* HW cannot do zero length HMAC, use fallback instead */ 28908c2ecf20Sopenharmony_ci return safexcel_sha3_digest_fallback(req); 28918c2ecf20Sopenharmony_ci} 28928c2ecf20Sopenharmony_ci 28938c2ecf20Sopenharmony_cistatic int safexcel_hmac_sha3_224_cra_init(struct crypto_tfm *tfm) 28948c2ecf20Sopenharmony_ci{ 28958c2ecf20Sopenharmony_ci return safexcel_hmac_sha3_cra_init(tfm, "sha3-224"); 28968c2ecf20Sopenharmony_ci} 28978c2ecf20Sopenharmony_ci 28988c2ecf20Sopenharmony_cistruct safexcel_alg_template safexcel_alg_hmac_sha3_224 = { 28998c2ecf20Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 29008c2ecf20Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA3, 29018c2ecf20Sopenharmony_ci .alg.ahash = { 29028c2ecf20Sopenharmony_ci .init = safexcel_hmac_sha3_224_init, 29038c2ecf20Sopenharmony_ci .update = safexcel_sha3_update, 29048c2ecf20Sopenharmony_ci .final = safexcel_sha3_final, 29058c2ecf20Sopenharmony_ci .finup = safexcel_sha3_finup, 29068c2ecf20Sopenharmony_ci .digest = safexcel_hmac_sha3_224_digest, 29078c2ecf20Sopenharmony_ci .setkey = safexcel_hmac_sha3_setkey, 29088c2ecf20Sopenharmony_ci .export = safexcel_sha3_export, 29098c2ecf20Sopenharmony_ci .import = safexcel_sha3_import, 29108c2ecf20Sopenharmony_ci .halg = { 29118c2ecf20Sopenharmony_ci .digestsize = SHA3_224_DIGEST_SIZE, 29128c2ecf20Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 29138c2ecf20Sopenharmony_ci .base = { 29148c2ecf20Sopenharmony_ci .cra_name = "hmac(sha3-224)", 29158c2ecf20Sopenharmony_ci .cra_driver_name = "safexcel-hmac-sha3-224", 29168c2ecf20Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 29178c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 29188c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY | 29198c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 29208c2ecf20Sopenharmony_ci .cra_blocksize = SHA3_224_BLOCK_SIZE, 29218c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 29228c2ecf20Sopenharmony_ci .cra_init = safexcel_hmac_sha3_224_cra_init, 29238c2ecf20Sopenharmony_ci .cra_exit = safexcel_hmac_sha3_cra_exit, 29248c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 29258c2ecf20Sopenharmony_ci }, 29268c2ecf20Sopenharmony_ci }, 29278c2ecf20Sopenharmony_ci }, 29288c2ecf20Sopenharmony_ci}; 29298c2ecf20Sopenharmony_ci 29308c2ecf20Sopenharmony_cistatic int safexcel_hmac_sha3_256_init(struct ahash_request *areq) 29318c2ecf20Sopenharmony_ci{ 29328c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 29338c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 29348c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx(areq); 29358c2ecf20Sopenharmony_ci 29368c2ecf20Sopenharmony_ci memset(req, 0, sizeof(*req)); 29378c2ecf20Sopenharmony_ci 29388c2ecf20Sopenharmony_ci /* Copy (half of) the key */ 29398c2ecf20Sopenharmony_ci memcpy(req->state, &ctx->base.ipad, SHA3_256_BLOCK_SIZE / 2); 29408c2ecf20Sopenharmony_ci /* Start of HMAC should have len == processed == blocksize */ 29418c2ecf20Sopenharmony_ci req->len = SHA3_256_BLOCK_SIZE; 29428c2ecf20Sopenharmony_ci req->processed = SHA3_256_BLOCK_SIZE; 29438c2ecf20Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_256; 29448c2ecf20Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_HMAC; 29458c2ecf20Sopenharmony_ci req->state_sz = SHA3_256_BLOCK_SIZE / 2; 29468c2ecf20Sopenharmony_ci req->digest_sz = SHA3_256_DIGEST_SIZE; 29478c2ecf20Sopenharmony_ci req->block_sz = SHA3_256_BLOCK_SIZE; 29488c2ecf20Sopenharmony_ci req->hmac = true; 29498c2ecf20Sopenharmony_ci ctx->do_fallback = false; 29508c2ecf20Sopenharmony_ci ctx->fb_init_done = false; 29518c2ecf20Sopenharmony_ci return 0; 29528c2ecf20Sopenharmony_ci} 29538c2ecf20Sopenharmony_ci 29548c2ecf20Sopenharmony_cistatic int safexcel_hmac_sha3_256_digest(struct ahash_request *req) 29558c2ecf20Sopenharmony_ci{ 29568c2ecf20Sopenharmony_ci if (req->nbytes) 29578c2ecf20Sopenharmony_ci return safexcel_hmac_sha3_256_init(req) ?: 29588c2ecf20Sopenharmony_ci safexcel_ahash_finup(req); 29598c2ecf20Sopenharmony_ci 29608c2ecf20Sopenharmony_ci /* HW cannot do zero length HMAC, use fallback instead */ 29618c2ecf20Sopenharmony_ci return safexcel_sha3_digest_fallback(req); 29628c2ecf20Sopenharmony_ci} 29638c2ecf20Sopenharmony_ci 29648c2ecf20Sopenharmony_cistatic int safexcel_hmac_sha3_256_cra_init(struct crypto_tfm *tfm) 29658c2ecf20Sopenharmony_ci{ 29668c2ecf20Sopenharmony_ci return safexcel_hmac_sha3_cra_init(tfm, "sha3-256"); 29678c2ecf20Sopenharmony_ci} 29688c2ecf20Sopenharmony_ci 29698c2ecf20Sopenharmony_cistruct safexcel_alg_template safexcel_alg_hmac_sha3_256 = { 29708c2ecf20Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 29718c2ecf20Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA3, 29728c2ecf20Sopenharmony_ci .alg.ahash = { 29738c2ecf20Sopenharmony_ci .init = safexcel_hmac_sha3_256_init, 29748c2ecf20Sopenharmony_ci .update = safexcel_sha3_update, 29758c2ecf20Sopenharmony_ci .final = safexcel_sha3_final, 29768c2ecf20Sopenharmony_ci .finup = safexcel_sha3_finup, 29778c2ecf20Sopenharmony_ci .digest = safexcel_hmac_sha3_256_digest, 29788c2ecf20Sopenharmony_ci .setkey = safexcel_hmac_sha3_setkey, 29798c2ecf20Sopenharmony_ci .export = safexcel_sha3_export, 29808c2ecf20Sopenharmony_ci .import = safexcel_sha3_import, 29818c2ecf20Sopenharmony_ci .halg = { 29828c2ecf20Sopenharmony_ci .digestsize = SHA3_256_DIGEST_SIZE, 29838c2ecf20Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 29848c2ecf20Sopenharmony_ci .base = { 29858c2ecf20Sopenharmony_ci .cra_name = "hmac(sha3-256)", 29868c2ecf20Sopenharmony_ci .cra_driver_name = "safexcel-hmac-sha3-256", 29878c2ecf20Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 29888c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 29898c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY | 29908c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 29918c2ecf20Sopenharmony_ci .cra_blocksize = SHA3_256_BLOCK_SIZE, 29928c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 29938c2ecf20Sopenharmony_ci .cra_init = safexcel_hmac_sha3_256_cra_init, 29948c2ecf20Sopenharmony_ci .cra_exit = safexcel_hmac_sha3_cra_exit, 29958c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 29968c2ecf20Sopenharmony_ci }, 29978c2ecf20Sopenharmony_ci }, 29988c2ecf20Sopenharmony_ci }, 29998c2ecf20Sopenharmony_ci}; 30008c2ecf20Sopenharmony_ci 30018c2ecf20Sopenharmony_cistatic int safexcel_hmac_sha3_384_init(struct ahash_request *areq) 30028c2ecf20Sopenharmony_ci{ 30038c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 30048c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 30058c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx(areq); 30068c2ecf20Sopenharmony_ci 30078c2ecf20Sopenharmony_ci memset(req, 0, sizeof(*req)); 30088c2ecf20Sopenharmony_ci 30098c2ecf20Sopenharmony_ci /* Copy (half of) the key */ 30108c2ecf20Sopenharmony_ci memcpy(req->state, &ctx->base.ipad, SHA3_384_BLOCK_SIZE / 2); 30118c2ecf20Sopenharmony_ci /* Start of HMAC should have len == processed == blocksize */ 30128c2ecf20Sopenharmony_ci req->len = SHA3_384_BLOCK_SIZE; 30138c2ecf20Sopenharmony_ci req->processed = SHA3_384_BLOCK_SIZE; 30148c2ecf20Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_384; 30158c2ecf20Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_HMAC; 30168c2ecf20Sopenharmony_ci req->state_sz = SHA3_384_BLOCK_SIZE / 2; 30178c2ecf20Sopenharmony_ci req->digest_sz = SHA3_384_DIGEST_SIZE; 30188c2ecf20Sopenharmony_ci req->block_sz = SHA3_384_BLOCK_SIZE; 30198c2ecf20Sopenharmony_ci req->hmac = true; 30208c2ecf20Sopenharmony_ci ctx->do_fallback = false; 30218c2ecf20Sopenharmony_ci ctx->fb_init_done = false; 30228c2ecf20Sopenharmony_ci return 0; 30238c2ecf20Sopenharmony_ci} 30248c2ecf20Sopenharmony_ci 30258c2ecf20Sopenharmony_cistatic int safexcel_hmac_sha3_384_digest(struct ahash_request *req) 30268c2ecf20Sopenharmony_ci{ 30278c2ecf20Sopenharmony_ci if (req->nbytes) 30288c2ecf20Sopenharmony_ci return safexcel_hmac_sha3_384_init(req) ?: 30298c2ecf20Sopenharmony_ci safexcel_ahash_finup(req); 30308c2ecf20Sopenharmony_ci 30318c2ecf20Sopenharmony_ci /* HW cannot do zero length HMAC, use fallback instead */ 30328c2ecf20Sopenharmony_ci return safexcel_sha3_digest_fallback(req); 30338c2ecf20Sopenharmony_ci} 30348c2ecf20Sopenharmony_ci 30358c2ecf20Sopenharmony_cistatic int safexcel_hmac_sha3_384_cra_init(struct crypto_tfm *tfm) 30368c2ecf20Sopenharmony_ci{ 30378c2ecf20Sopenharmony_ci return safexcel_hmac_sha3_cra_init(tfm, "sha3-384"); 30388c2ecf20Sopenharmony_ci} 30398c2ecf20Sopenharmony_ci 30408c2ecf20Sopenharmony_cistruct safexcel_alg_template safexcel_alg_hmac_sha3_384 = { 30418c2ecf20Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 30428c2ecf20Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA3, 30438c2ecf20Sopenharmony_ci .alg.ahash = { 30448c2ecf20Sopenharmony_ci .init = safexcel_hmac_sha3_384_init, 30458c2ecf20Sopenharmony_ci .update = safexcel_sha3_update, 30468c2ecf20Sopenharmony_ci .final = safexcel_sha3_final, 30478c2ecf20Sopenharmony_ci .finup = safexcel_sha3_finup, 30488c2ecf20Sopenharmony_ci .digest = safexcel_hmac_sha3_384_digest, 30498c2ecf20Sopenharmony_ci .setkey = safexcel_hmac_sha3_setkey, 30508c2ecf20Sopenharmony_ci .export = safexcel_sha3_export, 30518c2ecf20Sopenharmony_ci .import = safexcel_sha3_import, 30528c2ecf20Sopenharmony_ci .halg = { 30538c2ecf20Sopenharmony_ci .digestsize = SHA3_384_DIGEST_SIZE, 30548c2ecf20Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 30558c2ecf20Sopenharmony_ci .base = { 30568c2ecf20Sopenharmony_ci .cra_name = "hmac(sha3-384)", 30578c2ecf20Sopenharmony_ci .cra_driver_name = "safexcel-hmac-sha3-384", 30588c2ecf20Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 30598c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 30608c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY | 30618c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 30628c2ecf20Sopenharmony_ci .cra_blocksize = SHA3_384_BLOCK_SIZE, 30638c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 30648c2ecf20Sopenharmony_ci .cra_init = safexcel_hmac_sha3_384_cra_init, 30658c2ecf20Sopenharmony_ci .cra_exit = safexcel_hmac_sha3_cra_exit, 30668c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 30678c2ecf20Sopenharmony_ci }, 30688c2ecf20Sopenharmony_ci }, 30698c2ecf20Sopenharmony_ci }, 30708c2ecf20Sopenharmony_ci}; 30718c2ecf20Sopenharmony_ci 30728c2ecf20Sopenharmony_cistatic int safexcel_hmac_sha3_512_init(struct ahash_request *areq) 30738c2ecf20Sopenharmony_ci{ 30748c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 30758c2ecf20Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 30768c2ecf20Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx(areq); 30778c2ecf20Sopenharmony_ci 30788c2ecf20Sopenharmony_ci memset(req, 0, sizeof(*req)); 30798c2ecf20Sopenharmony_ci 30808c2ecf20Sopenharmony_ci /* Copy (half of) the key */ 30818c2ecf20Sopenharmony_ci memcpy(req->state, &ctx->base.ipad, SHA3_512_BLOCK_SIZE / 2); 30828c2ecf20Sopenharmony_ci /* Start of HMAC should have len == processed == blocksize */ 30838c2ecf20Sopenharmony_ci req->len = SHA3_512_BLOCK_SIZE; 30848c2ecf20Sopenharmony_ci req->processed = SHA3_512_BLOCK_SIZE; 30858c2ecf20Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_512; 30868c2ecf20Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_HMAC; 30878c2ecf20Sopenharmony_ci req->state_sz = SHA3_512_BLOCK_SIZE / 2; 30888c2ecf20Sopenharmony_ci req->digest_sz = SHA3_512_DIGEST_SIZE; 30898c2ecf20Sopenharmony_ci req->block_sz = SHA3_512_BLOCK_SIZE; 30908c2ecf20Sopenharmony_ci req->hmac = true; 30918c2ecf20Sopenharmony_ci ctx->do_fallback = false; 30928c2ecf20Sopenharmony_ci ctx->fb_init_done = false; 30938c2ecf20Sopenharmony_ci return 0; 30948c2ecf20Sopenharmony_ci} 30958c2ecf20Sopenharmony_ci 30968c2ecf20Sopenharmony_cistatic int safexcel_hmac_sha3_512_digest(struct ahash_request *req) 30978c2ecf20Sopenharmony_ci{ 30988c2ecf20Sopenharmony_ci if (req->nbytes) 30998c2ecf20Sopenharmony_ci return safexcel_hmac_sha3_512_init(req) ?: 31008c2ecf20Sopenharmony_ci safexcel_ahash_finup(req); 31018c2ecf20Sopenharmony_ci 31028c2ecf20Sopenharmony_ci /* HW cannot do zero length HMAC, use fallback instead */ 31038c2ecf20Sopenharmony_ci return safexcel_sha3_digest_fallback(req); 31048c2ecf20Sopenharmony_ci} 31058c2ecf20Sopenharmony_ci 31068c2ecf20Sopenharmony_cistatic int safexcel_hmac_sha3_512_cra_init(struct crypto_tfm *tfm) 31078c2ecf20Sopenharmony_ci{ 31088c2ecf20Sopenharmony_ci return safexcel_hmac_sha3_cra_init(tfm, "sha3-512"); 31098c2ecf20Sopenharmony_ci} 31108c2ecf20Sopenharmony_cistruct safexcel_alg_template safexcel_alg_hmac_sha3_512 = { 31118c2ecf20Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 31128c2ecf20Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA3, 31138c2ecf20Sopenharmony_ci .alg.ahash = { 31148c2ecf20Sopenharmony_ci .init = safexcel_hmac_sha3_512_init, 31158c2ecf20Sopenharmony_ci .update = safexcel_sha3_update, 31168c2ecf20Sopenharmony_ci .final = safexcel_sha3_final, 31178c2ecf20Sopenharmony_ci .finup = safexcel_sha3_finup, 31188c2ecf20Sopenharmony_ci .digest = safexcel_hmac_sha3_512_digest, 31198c2ecf20Sopenharmony_ci .setkey = safexcel_hmac_sha3_setkey, 31208c2ecf20Sopenharmony_ci .export = safexcel_sha3_export, 31218c2ecf20Sopenharmony_ci .import = safexcel_sha3_import, 31228c2ecf20Sopenharmony_ci .halg = { 31238c2ecf20Sopenharmony_ci .digestsize = SHA3_512_DIGEST_SIZE, 31248c2ecf20Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 31258c2ecf20Sopenharmony_ci .base = { 31268c2ecf20Sopenharmony_ci .cra_name = "hmac(sha3-512)", 31278c2ecf20Sopenharmony_ci .cra_driver_name = "safexcel-hmac-sha3-512", 31288c2ecf20Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 31298c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 31308c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY | 31318c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 31328c2ecf20Sopenharmony_ci .cra_blocksize = SHA3_512_BLOCK_SIZE, 31338c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 31348c2ecf20Sopenharmony_ci .cra_init = safexcel_hmac_sha3_512_cra_init, 31358c2ecf20Sopenharmony_ci .cra_exit = safexcel_hmac_sha3_cra_exit, 31368c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 31378c2ecf20Sopenharmony_ci }, 31388c2ecf20Sopenharmony_ci }, 31398c2ecf20Sopenharmony_ci }, 31408c2ecf20Sopenharmony_ci}; 3141