162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2017 Marvell 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Antoine Tenart <antoine.tenart@free-electrons.com> 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <crypto/aes.h> 962306a36Sopenharmony_ci#include <crypto/hmac.h> 1062306a36Sopenharmony_ci#include <crypto/md5.h> 1162306a36Sopenharmony_ci#include <crypto/sha1.h> 1262306a36Sopenharmony_ci#include <crypto/sha2.h> 1362306a36Sopenharmony_ci#include <crypto/sha3.h> 1462306a36Sopenharmony_ci#include <crypto/skcipher.h> 1562306a36Sopenharmony_ci#include <crypto/sm3.h> 1662306a36Sopenharmony_ci#include <crypto/internal/cipher.h> 1762306a36Sopenharmony_ci#include <linux/device.h> 1862306a36Sopenharmony_ci#include <linux/dma-mapping.h> 1962306a36Sopenharmony_ci#include <linux/dmapool.h> 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#include "safexcel.h" 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistruct safexcel_ahash_ctx { 2462306a36Sopenharmony_ci struct safexcel_context base; 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci u32 alg; 2762306a36Sopenharmony_ci u8 key_sz; 2862306a36Sopenharmony_ci bool cbcmac; 2962306a36Sopenharmony_ci bool do_fallback; 3062306a36Sopenharmony_ci bool fb_init_done; 3162306a36Sopenharmony_ci bool fb_do_setkey; 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci struct crypto_aes_ctx *aes; 3462306a36Sopenharmony_ci struct crypto_ahash *fback; 3562306a36Sopenharmony_ci struct crypto_shash *shpre; 3662306a36Sopenharmony_ci struct shash_desc *shdesc; 3762306a36Sopenharmony_ci}; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistruct safexcel_ahash_req { 4062306a36Sopenharmony_ci bool last_req; 4162306a36Sopenharmony_ci bool finish; 4262306a36Sopenharmony_ci bool hmac; 4362306a36Sopenharmony_ci bool needs_inv; 4462306a36Sopenharmony_ci bool hmac_zlen; 4562306a36Sopenharmony_ci bool len_is_le; 4662306a36Sopenharmony_ci bool not_first; 4762306a36Sopenharmony_ci bool xcbcmac; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci int nents; 5062306a36Sopenharmony_ci dma_addr_t result_dma; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci u32 digest; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci u8 state_sz; /* expected state size, only set once */ 5562306a36Sopenharmony_ci u8 block_sz; /* block size, only set once */ 5662306a36Sopenharmony_ci u8 digest_sz; /* output digest size, only set once */ 5762306a36Sopenharmony_ci __le32 state[SHA3_512_BLOCK_SIZE / 5862306a36Sopenharmony_ci sizeof(__le32)] __aligned(sizeof(__le32)); 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci u64 len; 6162306a36Sopenharmony_ci u64 processed; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci u8 cache[HASH_CACHE_SIZE] __aligned(sizeof(u32)); 6462306a36Sopenharmony_ci dma_addr_t cache_dma; 6562306a36Sopenharmony_ci unsigned int cache_sz; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci u8 cache_next[HASH_CACHE_SIZE] __aligned(sizeof(u32)); 6862306a36Sopenharmony_ci}; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cistatic inline u64 safexcel_queued_len(struct safexcel_ahash_req *req) 7162306a36Sopenharmony_ci{ 7262306a36Sopenharmony_ci return req->len - req->processed; 7362306a36Sopenharmony_ci} 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_cistatic void safexcel_hash_token(struct safexcel_command_desc *cdesc, 7662306a36Sopenharmony_ci u32 input_length, u32 result_length, 7762306a36Sopenharmony_ci bool cbcmac) 7862306a36Sopenharmony_ci{ 7962306a36Sopenharmony_ci struct safexcel_token *token = 8062306a36Sopenharmony_ci (struct safexcel_token *)cdesc->control_data.token; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci token[0].opcode = EIP197_TOKEN_OPCODE_DIRECTION; 8362306a36Sopenharmony_ci token[0].packet_length = input_length; 8462306a36Sopenharmony_ci token[0].instructions = EIP197_TOKEN_INS_TYPE_HASH; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci input_length &= 15; 8762306a36Sopenharmony_ci if (unlikely(cbcmac && input_length)) { 8862306a36Sopenharmony_ci token[0].stat = 0; 8962306a36Sopenharmony_ci token[1].opcode = EIP197_TOKEN_OPCODE_INSERT; 9062306a36Sopenharmony_ci token[1].packet_length = 16 - input_length; 9162306a36Sopenharmony_ci token[1].stat = EIP197_TOKEN_STAT_LAST_HASH; 9262306a36Sopenharmony_ci token[1].instructions = EIP197_TOKEN_INS_TYPE_HASH; 9362306a36Sopenharmony_ci } else { 9462306a36Sopenharmony_ci token[0].stat = EIP197_TOKEN_STAT_LAST_HASH; 9562306a36Sopenharmony_ci eip197_noop_token(&token[1]); 9662306a36Sopenharmony_ci } 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci token[2].opcode = EIP197_TOKEN_OPCODE_INSERT; 9962306a36Sopenharmony_ci token[2].stat = EIP197_TOKEN_STAT_LAST_HASH | 10062306a36Sopenharmony_ci EIP197_TOKEN_STAT_LAST_PACKET; 10162306a36Sopenharmony_ci token[2].packet_length = result_length; 10262306a36Sopenharmony_ci token[2].instructions = EIP197_TOKEN_INS_TYPE_OUTPUT | 10362306a36Sopenharmony_ci EIP197_TOKEN_INS_INSERT_HASH_DIGEST; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci eip197_noop_token(&token[3]); 10662306a36Sopenharmony_ci} 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_cistatic void safexcel_context_control(struct safexcel_ahash_ctx *ctx, 10962306a36Sopenharmony_ci struct safexcel_ahash_req *req, 11062306a36Sopenharmony_ci struct safexcel_command_desc *cdesc) 11162306a36Sopenharmony_ci{ 11262306a36Sopenharmony_ci struct safexcel_crypto_priv *priv = ctx->base.priv; 11362306a36Sopenharmony_ci u64 count = 0; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci cdesc->control_data.control0 = ctx->alg; 11662306a36Sopenharmony_ci cdesc->control_data.control1 = 0; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci /* 11962306a36Sopenharmony_ci * Copy the input digest if needed, and setup the context 12062306a36Sopenharmony_ci * fields. Do this now as we need it to setup the first command 12162306a36Sopenharmony_ci * descriptor. 12262306a36Sopenharmony_ci */ 12362306a36Sopenharmony_ci if (unlikely(req->digest == CONTEXT_CONTROL_DIGEST_XCM)) { 12462306a36Sopenharmony_ci if (req->xcbcmac) 12562306a36Sopenharmony_ci memcpy(ctx->base.ctxr->data, &ctx->base.ipad, ctx->key_sz); 12662306a36Sopenharmony_ci else 12762306a36Sopenharmony_ci memcpy(ctx->base.ctxr->data, req->state, req->state_sz); 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci if (!req->finish && req->xcbcmac) 13062306a36Sopenharmony_ci cdesc->control_data.control0 |= 13162306a36Sopenharmony_ci CONTEXT_CONTROL_DIGEST_XCM | 13262306a36Sopenharmony_ci CONTEXT_CONTROL_TYPE_HASH_OUT | 13362306a36Sopenharmony_ci CONTEXT_CONTROL_NO_FINISH_HASH | 13462306a36Sopenharmony_ci CONTEXT_CONTROL_SIZE(req->state_sz / 13562306a36Sopenharmony_ci sizeof(u32)); 13662306a36Sopenharmony_ci else 13762306a36Sopenharmony_ci cdesc->control_data.control0 |= 13862306a36Sopenharmony_ci CONTEXT_CONTROL_DIGEST_XCM | 13962306a36Sopenharmony_ci CONTEXT_CONTROL_TYPE_HASH_OUT | 14062306a36Sopenharmony_ci CONTEXT_CONTROL_SIZE(req->state_sz / 14162306a36Sopenharmony_ci sizeof(u32)); 14262306a36Sopenharmony_ci return; 14362306a36Sopenharmony_ci } else if (!req->processed) { 14462306a36Sopenharmony_ci /* First - and possibly only - block of basic hash only */ 14562306a36Sopenharmony_ci if (req->finish) 14662306a36Sopenharmony_ci cdesc->control_data.control0 |= req->digest | 14762306a36Sopenharmony_ci CONTEXT_CONTROL_TYPE_HASH_OUT | 14862306a36Sopenharmony_ci CONTEXT_CONTROL_RESTART_HASH | 14962306a36Sopenharmony_ci /* ensure its not 0! */ 15062306a36Sopenharmony_ci CONTEXT_CONTROL_SIZE(1); 15162306a36Sopenharmony_ci else 15262306a36Sopenharmony_ci cdesc->control_data.control0 |= req->digest | 15362306a36Sopenharmony_ci CONTEXT_CONTROL_TYPE_HASH_OUT | 15462306a36Sopenharmony_ci CONTEXT_CONTROL_RESTART_HASH | 15562306a36Sopenharmony_ci CONTEXT_CONTROL_NO_FINISH_HASH | 15662306a36Sopenharmony_ci /* ensure its not 0! */ 15762306a36Sopenharmony_ci CONTEXT_CONTROL_SIZE(1); 15862306a36Sopenharmony_ci return; 15962306a36Sopenharmony_ci } 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci /* Hash continuation or HMAC, setup (inner) digest from state */ 16262306a36Sopenharmony_ci memcpy(ctx->base.ctxr->data, req->state, req->state_sz); 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci if (req->finish) { 16562306a36Sopenharmony_ci /* Compute digest count for hash/HMAC finish operations */ 16662306a36Sopenharmony_ci if ((req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) || 16762306a36Sopenharmony_ci req->hmac_zlen || (req->processed != req->block_sz)) { 16862306a36Sopenharmony_ci count = req->processed / EIP197_COUNTER_BLOCK_SIZE; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci /* This is a hardware limitation, as the 17162306a36Sopenharmony_ci * counter must fit into an u32. This represents 17262306a36Sopenharmony_ci * a fairly big amount of input data, so we 17362306a36Sopenharmony_ci * shouldn't see this. 17462306a36Sopenharmony_ci */ 17562306a36Sopenharmony_ci if (unlikely(count & 0xffffffff00000000ULL)) { 17662306a36Sopenharmony_ci dev_warn(priv->dev, 17762306a36Sopenharmony_ci "Input data is too big\n"); 17862306a36Sopenharmony_ci return; 17962306a36Sopenharmony_ci } 18062306a36Sopenharmony_ci } 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci if ((req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) || 18362306a36Sopenharmony_ci /* Special case: zero length HMAC */ 18462306a36Sopenharmony_ci req->hmac_zlen || 18562306a36Sopenharmony_ci /* PE HW < 4.4 cannot do HMAC continue, fake using hash */ 18662306a36Sopenharmony_ci (req->processed != req->block_sz)) { 18762306a36Sopenharmony_ci /* Basic hash continue operation, need digest + cnt */ 18862306a36Sopenharmony_ci cdesc->control_data.control0 |= 18962306a36Sopenharmony_ci CONTEXT_CONTROL_SIZE((req->state_sz >> 2) + 1) | 19062306a36Sopenharmony_ci CONTEXT_CONTROL_TYPE_HASH_OUT | 19162306a36Sopenharmony_ci CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 19262306a36Sopenharmony_ci /* For zero-len HMAC, don't finalize, already padded! */ 19362306a36Sopenharmony_ci if (req->hmac_zlen) 19462306a36Sopenharmony_ci cdesc->control_data.control0 |= 19562306a36Sopenharmony_ci CONTEXT_CONTROL_NO_FINISH_HASH; 19662306a36Sopenharmony_ci cdesc->control_data.control1 |= 19762306a36Sopenharmony_ci CONTEXT_CONTROL_DIGEST_CNT; 19862306a36Sopenharmony_ci ctx->base.ctxr->data[req->state_sz >> 2] = 19962306a36Sopenharmony_ci cpu_to_le32(count); 20062306a36Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci /* Clear zero-length HMAC flag for next operation! */ 20362306a36Sopenharmony_ci req->hmac_zlen = false; 20462306a36Sopenharmony_ci } else { /* HMAC */ 20562306a36Sopenharmony_ci /* Need outer digest for HMAC finalization */ 20662306a36Sopenharmony_ci memcpy(ctx->base.ctxr->data + (req->state_sz >> 2), 20762306a36Sopenharmony_ci &ctx->base.opad, req->state_sz); 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci /* Single pass HMAC - no digest count */ 21062306a36Sopenharmony_ci cdesc->control_data.control0 |= 21162306a36Sopenharmony_ci CONTEXT_CONTROL_SIZE(req->state_sz >> 1) | 21262306a36Sopenharmony_ci CONTEXT_CONTROL_TYPE_HASH_OUT | 21362306a36Sopenharmony_ci CONTEXT_CONTROL_DIGEST_HMAC; 21462306a36Sopenharmony_ci } 21562306a36Sopenharmony_ci } else { /* Hash continuation, do not finish yet */ 21662306a36Sopenharmony_ci cdesc->control_data.control0 |= 21762306a36Sopenharmony_ci CONTEXT_CONTROL_SIZE(req->state_sz >> 2) | 21862306a36Sopenharmony_ci CONTEXT_CONTROL_DIGEST_PRECOMPUTED | 21962306a36Sopenharmony_ci CONTEXT_CONTROL_TYPE_HASH_OUT | 22062306a36Sopenharmony_ci CONTEXT_CONTROL_NO_FINISH_HASH; 22162306a36Sopenharmony_ci } 22262306a36Sopenharmony_ci} 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_cistatic int safexcel_ahash_enqueue(struct ahash_request *areq); 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_cistatic int safexcel_handle_req_result(struct safexcel_crypto_priv *priv, 22762306a36Sopenharmony_ci int ring, 22862306a36Sopenharmony_ci struct crypto_async_request *async, 22962306a36Sopenharmony_ci bool *should_complete, int *ret) 23062306a36Sopenharmony_ci{ 23162306a36Sopenharmony_ci struct safexcel_result_desc *rdesc; 23262306a36Sopenharmony_ci struct ahash_request *areq = ahash_request_cast(async); 23362306a36Sopenharmony_ci struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); 23462306a36Sopenharmony_ci struct safexcel_ahash_req *sreq = ahash_request_ctx_dma(areq); 23562306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(ahash); 23662306a36Sopenharmony_ci u64 cache_len; 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci *ret = 0; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr); 24162306a36Sopenharmony_ci if (IS_ERR(rdesc)) { 24262306a36Sopenharmony_ci dev_err(priv->dev, 24362306a36Sopenharmony_ci "hash: result: could not retrieve the result descriptor\n"); 24462306a36Sopenharmony_ci *ret = PTR_ERR(rdesc); 24562306a36Sopenharmony_ci } else { 24662306a36Sopenharmony_ci *ret = safexcel_rdesc_check_errors(priv, rdesc); 24762306a36Sopenharmony_ci } 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci safexcel_complete(priv, ring); 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci if (sreq->nents) { 25262306a36Sopenharmony_ci dma_unmap_sg(priv->dev, areq->src, sreq->nents, DMA_TO_DEVICE); 25362306a36Sopenharmony_ci sreq->nents = 0; 25462306a36Sopenharmony_ci } 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci if (sreq->result_dma) { 25762306a36Sopenharmony_ci dma_unmap_single(priv->dev, sreq->result_dma, sreq->digest_sz, 25862306a36Sopenharmony_ci DMA_FROM_DEVICE); 25962306a36Sopenharmony_ci sreq->result_dma = 0; 26062306a36Sopenharmony_ci } 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci if (sreq->cache_dma) { 26362306a36Sopenharmony_ci dma_unmap_single(priv->dev, sreq->cache_dma, sreq->cache_sz, 26462306a36Sopenharmony_ci DMA_TO_DEVICE); 26562306a36Sopenharmony_ci sreq->cache_dma = 0; 26662306a36Sopenharmony_ci sreq->cache_sz = 0; 26762306a36Sopenharmony_ci } 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci if (sreq->finish) { 27062306a36Sopenharmony_ci if (sreq->hmac && 27162306a36Sopenharmony_ci (sreq->digest != CONTEXT_CONTROL_DIGEST_HMAC)) { 27262306a36Sopenharmony_ci /* Faking HMAC using hash - need to do outer hash */ 27362306a36Sopenharmony_ci memcpy(sreq->cache, sreq->state, 27462306a36Sopenharmony_ci crypto_ahash_digestsize(ahash)); 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci memcpy(sreq->state, &ctx->base.opad, sreq->digest_sz); 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci sreq->len = sreq->block_sz + 27962306a36Sopenharmony_ci crypto_ahash_digestsize(ahash); 28062306a36Sopenharmony_ci sreq->processed = sreq->block_sz; 28162306a36Sopenharmony_ci sreq->hmac = 0; 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci if (priv->flags & EIP197_TRC_CACHE) 28462306a36Sopenharmony_ci ctx->base.needs_inv = true; 28562306a36Sopenharmony_ci areq->nbytes = 0; 28662306a36Sopenharmony_ci safexcel_ahash_enqueue(areq); 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci *should_complete = false; /* Not done yet */ 28962306a36Sopenharmony_ci return 1; 29062306a36Sopenharmony_ci } 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci if (unlikely(sreq->digest == CONTEXT_CONTROL_DIGEST_XCM && 29362306a36Sopenharmony_ci ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_CRC32)) { 29462306a36Sopenharmony_ci /* Undo final XOR with 0xffffffff ...*/ 29562306a36Sopenharmony_ci *(__le32 *)areq->result = ~sreq->state[0]; 29662306a36Sopenharmony_ci } else { 29762306a36Sopenharmony_ci memcpy(areq->result, sreq->state, 29862306a36Sopenharmony_ci crypto_ahash_digestsize(ahash)); 29962306a36Sopenharmony_ci } 30062306a36Sopenharmony_ci } 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci cache_len = safexcel_queued_len(sreq); 30362306a36Sopenharmony_ci if (cache_len) 30462306a36Sopenharmony_ci memcpy(sreq->cache, sreq->cache_next, cache_len); 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci *should_complete = true; 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci return 1; 30962306a36Sopenharmony_ci} 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_cistatic int safexcel_ahash_send_req(struct crypto_async_request *async, int ring, 31262306a36Sopenharmony_ci int *commands, int *results) 31362306a36Sopenharmony_ci{ 31462306a36Sopenharmony_ci struct ahash_request *areq = ahash_request_cast(async); 31562306a36Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq); 31662306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 31762306a36Sopenharmony_ci struct safexcel_crypto_priv *priv = ctx->base.priv; 31862306a36Sopenharmony_ci struct safexcel_command_desc *cdesc, *first_cdesc = NULL; 31962306a36Sopenharmony_ci struct safexcel_result_desc *rdesc; 32062306a36Sopenharmony_ci struct scatterlist *sg; 32162306a36Sopenharmony_ci struct safexcel_token *dmmy; 32262306a36Sopenharmony_ci int i, extra = 0, n_cdesc = 0, ret = 0, cache_len, skip = 0; 32362306a36Sopenharmony_ci u64 queued, len; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci queued = safexcel_queued_len(req); 32662306a36Sopenharmony_ci if (queued <= HASH_CACHE_SIZE) 32762306a36Sopenharmony_ci cache_len = queued; 32862306a36Sopenharmony_ci else 32962306a36Sopenharmony_ci cache_len = queued - areq->nbytes; 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci if (!req->finish && !req->last_req) { 33262306a36Sopenharmony_ci /* If this is not the last request and the queued data does not 33362306a36Sopenharmony_ci * fit into full cache blocks, cache it for the next send call. 33462306a36Sopenharmony_ci */ 33562306a36Sopenharmony_ci extra = queued & (HASH_CACHE_SIZE - 1); 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci /* If this is not the last request and the queued data 33862306a36Sopenharmony_ci * is a multiple of a block, cache the last one for now. 33962306a36Sopenharmony_ci */ 34062306a36Sopenharmony_ci if (!extra) 34162306a36Sopenharmony_ci extra = HASH_CACHE_SIZE; 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci sg_pcopy_to_buffer(areq->src, sg_nents(areq->src), 34462306a36Sopenharmony_ci req->cache_next, extra, 34562306a36Sopenharmony_ci areq->nbytes - extra); 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci queued -= extra; 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci if (!queued) { 35062306a36Sopenharmony_ci *commands = 0; 35162306a36Sopenharmony_ci *results = 0; 35262306a36Sopenharmony_ci return 0; 35362306a36Sopenharmony_ci } 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci extra = 0; 35662306a36Sopenharmony_ci } 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci if (unlikely(req->xcbcmac && req->processed > AES_BLOCK_SIZE)) { 35962306a36Sopenharmony_ci if (unlikely(cache_len < AES_BLOCK_SIZE)) { 36062306a36Sopenharmony_ci /* 36162306a36Sopenharmony_ci * Cache contains less than 1 full block, complete. 36262306a36Sopenharmony_ci */ 36362306a36Sopenharmony_ci extra = AES_BLOCK_SIZE - cache_len; 36462306a36Sopenharmony_ci if (queued > cache_len) { 36562306a36Sopenharmony_ci /* More data follows: borrow bytes */ 36662306a36Sopenharmony_ci u64 tmp = queued - cache_len; 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci skip = min_t(u64, tmp, extra); 36962306a36Sopenharmony_ci sg_pcopy_to_buffer(areq->src, 37062306a36Sopenharmony_ci sg_nents(areq->src), 37162306a36Sopenharmony_ci req->cache + cache_len, 37262306a36Sopenharmony_ci skip, 0); 37362306a36Sopenharmony_ci } 37462306a36Sopenharmony_ci extra -= skip; 37562306a36Sopenharmony_ci memset(req->cache + cache_len + skip, 0, extra); 37662306a36Sopenharmony_ci if (!ctx->cbcmac && extra) { 37762306a36Sopenharmony_ci // 10- padding for XCBCMAC & CMAC 37862306a36Sopenharmony_ci req->cache[cache_len + skip] = 0x80; 37962306a36Sopenharmony_ci // HW will use K2 iso K3 - compensate! 38062306a36Sopenharmony_ci for (i = 0; i < AES_BLOCK_SIZE / 4; i++) { 38162306a36Sopenharmony_ci u32 *cache = (void *)req->cache; 38262306a36Sopenharmony_ci u32 *ipad = ctx->base.ipad.word; 38362306a36Sopenharmony_ci u32 x; 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci x = ipad[i] ^ ipad[i + 4]; 38662306a36Sopenharmony_ci cache[i] ^= swab32(x); 38762306a36Sopenharmony_ci } 38862306a36Sopenharmony_ci } 38962306a36Sopenharmony_ci cache_len = AES_BLOCK_SIZE; 39062306a36Sopenharmony_ci queued = queued + extra; 39162306a36Sopenharmony_ci } 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci /* XCBC continue: XOR previous result into 1st word */ 39462306a36Sopenharmony_ci crypto_xor(req->cache, (const u8 *)req->state, AES_BLOCK_SIZE); 39562306a36Sopenharmony_ci } 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci len = queued; 39862306a36Sopenharmony_ci /* Add a command descriptor for the cached data, if any */ 39962306a36Sopenharmony_ci if (cache_len) { 40062306a36Sopenharmony_ci req->cache_dma = dma_map_single(priv->dev, req->cache, 40162306a36Sopenharmony_ci cache_len, DMA_TO_DEVICE); 40262306a36Sopenharmony_ci if (dma_mapping_error(priv->dev, req->cache_dma)) 40362306a36Sopenharmony_ci return -EINVAL; 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci req->cache_sz = cache_len; 40662306a36Sopenharmony_ci first_cdesc = safexcel_add_cdesc(priv, ring, 1, 40762306a36Sopenharmony_ci (cache_len == len), 40862306a36Sopenharmony_ci req->cache_dma, cache_len, 40962306a36Sopenharmony_ci len, ctx->base.ctxr_dma, 41062306a36Sopenharmony_ci &dmmy); 41162306a36Sopenharmony_ci if (IS_ERR(first_cdesc)) { 41262306a36Sopenharmony_ci ret = PTR_ERR(first_cdesc); 41362306a36Sopenharmony_ci goto unmap_cache; 41462306a36Sopenharmony_ci } 41562306a36Sopenharmony_ci n_cdesc++; 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci queued -= cache_len; 41862306a36Sopenharmony_ci if (!queued) 41962306a36Sopenharmony_ci goto send_command; 42062306a36Sopenharmony_ci } 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci /* Now handle the current ahash request buffer(s) */ 42362306a36Sopenharmony_ci req->nents = dma_map_sg(priv->dev, areq->src, 42462306a36Sopenharmony_ci sg_nents_for_len(areq->src, 42562306a36Sopenharmony_ci areq->nbytes), 42662306a36Sopenharmony_ci DMA_TO_DEVICE); 42762306a36Sopenharmony_ci if (!req->nents) { 42862306a36Sopenharmony_ci ret = -ENOMEM; 42962306a36Sopenharmony_ci goto cdesc_rollback; 43062306a36Sopenharmony_ci } 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci for_each_sg(areq->src, sg, req->nents, i) { 43362306a36Sopenharmony_ci int sglen = sg_dma_len(sg); 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci if (unlikely(sglen <= skip)) { 43662306a36Sopenharmony_ci skip -= sglen; 43762306a36Sopenharmony_ci continue; 43862306a36Sopenharmony_ci } 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci /* Do not overflow the request */ 44162306a36Sopenharmony_ci if ((queued + skip) <= sglen) 44262306a36Sopenharmony_ci sglen = queued; 44362306a36Sopenharmony_ci else 44462306a36Sopenharmony_ci sglen -= skip; 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci cdesc = safexcel_add_cdesc(priv, ring, !n_cdesc, 44762306a36Sopenharmony_ci !(queued - sglen), 44862306a36Sopenharmony_ci sg_dma_address(sg) + skip, sglen, 44962306a36Sopenharmony_ci len, ctx->base.ctxr_dma, &dmmy); 45062306a36Sopenharmony_ci if (IS_ERR(cdesc)) { 45162306a36Sopenharmony_ci ret = PTR_ERR(cdesc); 45262306a36Sopenharmony_ci goto unmap_sg; 45362306a36Sopenharmony_ci } 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci if (!n_cdesc) 45662306a36Sopenharmony_ci first_cdesc = cdesc; 45762306a36Sopenharmony_ci n_cdesc++; 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci queued -= sglen; 46062306a36Sopenharmony_ci if (!queued) 46162306a36Sopenharmony_ci break; 46262306a36Sopenharmony_ci skip = 0; 46362306a36Sopenharmony_ci } 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_cisend_command: 46662306a36Sopenharmony_ci /* Setup the context options */ 46762306a36Sopenharmony_ci safexcel_context_control(ctx, req, first_cdesc); 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci /* Add the token */ 47062306a36Sopenharmony_ci safexcel_hash_token(first_cdesc, len, req->digest_sz, ctx->cbcmac); 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci req->result_dma = dma_map_single(priv->dev, req->state, req->digest_sz, 47362306a36Sopenharmony_ci DMA_FROM_DEVICE); 47462306a36Sopenharmony_ci if (dma_mapping_error(priv->dev, req->result_dma)) { 47562306a36Sopenharmony_ci ret = -EINVAL; 47662306a36Sopenharmony_ci goto unmap_sg; 47762306a36Sopenharmony_ci } 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci /* Add a result descriptor */ 48062306a36Sopenharmony_ci rdesc = safexcel_add_rdesc(priv, ring, 1, 1, req->result_dma, 48162306a36Sopenharmony_ci req->digest_sz); 48262306a36Sopenharmony_ci if (IS_ERR(rdesc)) { 48362306a36Sopenharmony_ci ret = PTR_ERR(rdesc); 48462306a36Sopenharmony_ci goto unmap_result; 48562306a36Sopenharmony_ci } 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci safexcel_rdr_req_set(priv, ring, rdesc, &areq->base); 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci req->processed += len - extra; 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci *commands = n_cdesc; 49262306a36Sopenharmony_ci *results = 1; 49362306a36Sopenharmony_ci return 0; 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ciunmap_result: 49662306a36Sopenharmony_ci dma_unmap_single(priv->dev, req->result_dma, req->digest_sz, 49762306a36Sopenharmony_ci DMA_FROM_DEVICE); 49862306a36Sopenharmony_ciunmap_sg: 49962306a36Sopenharmony_ci if (req->nents) { 50062306a36Sopenharmony_ci dma_unmap_sg(priv->dev, areq->src, req->nents, DMA_TO_DEVICE); 50162306a36Sopenharmony_ci req->nents = 0; 50262306a36Sopenharmony_ci } 50362306a36Sopenharmony_cicdesc_rollback: 50462306a36Sopenharmony_ci for (i = 0; i < n_cdesc; i++) 50562306a36Sopenharmony_ci safexcel_ring_rollback_wptr(priv, &priv->ring[ring].cdr); 50662306a36Sopenharmony_ciunmap_cache: 50762306a36Sopenharmony_ci if (req->cache_dma) { 50862306a36Sopenharmony_ci dma_unmap_single(priv->dev, req->cache_dma, req->cache_sz, 50962306a36Sopenharmony_ci DMA_TO_DEVICE); 51062306a36Sopenharmony_ci req->cache_dma = 0; 51162306a36Sopenharmony_ci req->cache_sz = 0; 51262306a36Sopenharmony_ci } 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci return ret; 51562306a36Sopenharmony_ci} 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_cistatic int safexcel_handle_inv_result(struct safexcel_crypto_priv *priv, 51862306a36Sopenharmony_ci int ring, 51962306a36Sopenharmony_ci struct crypto_async_request *async, 52062306a36Sopenharmony_ci bool *should_complete, int *ret) 52162306a36Sopenharmony_ci{ 52262306a36Sopenharmony_ci struct safexcel_result_desc *rdesc; 52362306a36Sopenharmony_ci struct ahash_request *areq = ahash_request_cast(async); 52462306a36Sopenharmony_ci struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); 52562306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(ahash); 52662306a36Sopenharmony_ci int enq_ret; 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci *ret = 0; 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr); 53162306a36Sopenharmony_ci if (IS_ERR(rdesc)) { 53262306a36Sopenharmony_ci dev_err(priv->dev, 53362306a36Sopenharmony_ci "hash: invalidate: could not retrieve the result descriptor\n"); 53462306a36Sopenharmony_ci *ret = PTR_ERR(rdesc); 53562306a36Sopenharmony_ci } else { 53662306a36Sopenharmony_ci *ret = safexcel_rdesc_check_errors(priv, rdesc); 53762306a36Sopenharmony_ci } 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci safexcel_complete(priv, ring); 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci if (ctx->base.exit_inv) { 54262306a36Sopenharmony_ci dma_pool_free(priv->context_pool, ctx->base.ctxr, 54362306a36Sopenharmony_ci ctx->base.ctxr_dma); 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci *should_complete = true; 54662306a36Sopenharmony_ci return 1; 54762306a36Sopenharmony_ci } 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci ring = safexcel_select_ring(priv); 55062306a36Sopenharmony_ci ctx->base.ring = ring; 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci spin_lock_bh(&priv->ring[ring].queue_lock); 55362306a36Sopenharmony_ci enq_ret = crypto_enqueue_request(&priv->ring[ring].queue, async); 55462306a36Sopenharmony_ci spin_unlock_bh(&priv->ring[ring].queue_lock); 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci if (enq_ret != -EINPROGRESS) 55762306a36Sopenharmony_ci *ret = enq_ret; 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci queue_work(priv->ring[ring].workqueue, 56062306a36Sopenharmony_ci &priv->ring[ring].work_data.work); 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci *should_complete = false; 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ci return 1; 56562306a36Sopenharmony_ci} 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_cistatic int safexcel_handle_result(struct safexcel_crypto_priv *priv, int ring, 56862306a36Sopenharmony_ci struct crypto_async_request *async, 56962306a36Sopenharmony_ci bool *should_complete, int *ret) 57062306a36Sopenharmony_ci{ 57162306a36Sopenharmony_ci struct ahash_request *areq = ahash_request_cast(async); 57262306a36Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq); 57362306a36Sopenharmony_ci int err; 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci BUG_ON(!(priv->flags & EIP197_TRC_CACHE) && req->needs_inv); 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci if (req->needs_inv) { 57862306a36Sopenharmony_ci req->needs_inv = false; 57962306a36Sopenharmony_ci err = safexcel_handle_inv_result(priv, ring, async, 58062306a36Sopenharmony_ci should_complete, ret); 58162306a36Sopenharmony_ci } else { 58262306a36Sopenharmony_ci err = safexcel_handle_req_result(priv, ring, async, 58362306a36Sopenharmony_ci should_complete, ret); 58462306a36Sopenharmony_ci } 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci return err; 58762306a36Sopenharmony_ci} 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_cistatic int safexcel_ahash_send_inv(struct crypto_async_request *async, 59062306a36Sopenharmony_ci int ring, int *commands, int *results) 59162306a36Sopenharmony_ci{ 59262306a36Sopenharmony_ci struct ahash_request *areq = ahash_request_cast(async); 59362306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 59462306a36Sopenharmony_ci int ret; 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ci ret = safexcel_invalidate_cache(async, ctx->base.priv, 59762306a36Sopenharmony_ci ctx->base.ctxr_dma, ring); 59862306a36Sopenharmony_ci if (unlikely(ret)) 59962306a36Sopenharmony_ci return ret; 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci *commands = 1; 60262306a36Sopenharmony_ci *results = 1; 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci return 0; 60562306a36Sopenharmony_ci} 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_cistatic int safexcel_ahash_send(struct crypto_async_request *async, 60862306a36Sopenharmony_ci int ring, int *commands, int *results) 60962306a36Sopenharmony_ci{ 61062306a36Sopenharmony_ci struct ahash_request *areq = ahash_request_cast(async); 61162306a36Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq); 61262306a36Sopenharmony_ci int ret; 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci if (req->needs_inv) 61562306a36Sopenharmony_ci ret = safexcel_ahash_send_inv(async, ring, commands, results); 61662306a36Sopenharmony_ci else 61762306a36Sopenharmony_ci ret = safexcel_ahash_send_req(async, ring, commands, results); 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci return ret; 62062306a36Sopenharmony_ci} 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_cistatic int safexcel_ahash_exit_inv(struct crypto_tfm *tfm) 62362306a36Sopenharmony_ci{ 62462306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 62562306a36Sopenharmony_ci struct safexcel_crypto_priv *priv = ctx->base.priv; 62662306a36Sopenharmony_ci EIP197_REQUEST_ON_STACK(req, ahash, EIP197_AHASH_REQ_SIZE); 62762306a36Sopenharmony_ci struct safexcel_ahash_req *rctx = ahash_request_ctx_dma(req); 62862306a36Sopenharmony_ci DECLARE_CRYPTO_WAIT(result); 62962306a36Sopenharmony_ci int ring = ctx->base.ring; 63062306a36Sopenharmony_ci int err; 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci memset(req, 0, EIP197_AHASH_REQ_SIZE); 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci /* create invalidation request */ 63562306a36Sopenharmony_ci init_completion(&result.completion); 63662306a36Sopenharmony_ci ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, 63762306a36Sopenharmony_ci crypto_req_done, &result); 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_ci ahash_request_set_tfm(req, __crypto_ahash_cast(tfm)); 64062306a36Sopenharmony_ci ctx = crypto_tfm_ctx(req->base.tfm); 64162306a36Sopenharmony_ci ctx->base.exit_inv = true; 64262306a36Sopenharmony_ci rctx->needs_inv = true; 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci spin_lock_bh(&priv->ring[ring].queue_lock); 64562306a36Sopenharmony_ci crypto_enqueue_request(&priv->ring[ring].queue, &req->base); 64662306a36Sopenharmony_ci spin_unlock_bh(&priv->ring[ring].queue_lock); 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci queue_work(priv->ring[ring].workqueue, 64962306a36Sopenharmony_ci &priv->ring[ring].work_data.work); 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_ci err = crypto_wait_req(-EINPROGRESS, &result); 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_ci if (err) { 65462306a36Sopenharmony_ci dev_warn(priv->dev, "hash: completion error (%d)\n", err); 65562306a36Sopenharmony_ci return err; 65662306a36Sopenharmony_ci } 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci return 0; 65962306a36Sopenharmony_ci} 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci/* safexcel_ahash_cache: cache data until at least one request can be sent to 66262306a36Sopenharmony_ci * the engine, aka. when there is at least 1 block size in the pipe. 66362306a36Sopenharmony_ci */ 66462306a36Sopenharmony_cistatic int safexcel_ahash_cache(struct ahash_request *areq) 66562306a36Sopenharmony_ci{ 66662306a36Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq); 66762306a36Sopenharmony_ci u64 cache_len; 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_ci /* cache_len: everything accepted by the driver but not sent yet, 67062306a36Sopenharmony_ci * tot sz handled by update() - last req sz - tot sz handled by send() 67162306a36Sopenharmony_ci */ 67262306a36Sopenharmony_ci cache_len = safexcel_queued_len(req); 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_ci /* 67562306a36Sopenharmony_ci * In case there isn't enough bytes to proceed (less than a 67662306a36Sopenharmony_ci * block size), cache the data until we have enough. 67762306a36Sopenharmony_ci */ 67862306a36Sopenharmony_ci if (cache_len + areq->nbytes <= HASH_CACHE_SIZE) { 67962306a36Sopenharmony_ci sg_pcopy_to_buffer(areq->src, sg_nents(areq->src), 68062306a36Sopenharmony_ci req->cache + cache_len, 68162306a36Sopenharmony_ci areq->nbytes, 0); 68262306a36Sopenharmony_ci return 0; 68362306a36Sopenharmony_ci } 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_ci /* We couldn't cache all the data */ 68662306a36Sopenharmony_ci return -E2BIG; 68762306a36Sopenharmony_ci} 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_cistatic int safexcel_ahash_enqueue(struct ahash_request *areq) 69062306a36Sopenharmony_ci{ 69162306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 69262306a36Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq); 69362306a36Sopenharmony_ci struct safexcel_crypto_priv *priv = ctx->base.priv; 69462306a36Sopenharmony_ci int ret, ring; 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci req->needs_inv = false; 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci if (ctx->base.ctxr) { 69962306a36Sopenharmony_ci if (priv->flags & EIP197_TRC_CACHE && !ctx->base.needs_inv && 70062306a36Sopenharmony_ci /* invalidate for *any* non-XCBC continuation */ 70162306a36Sopenharmony_ci ((req->not_first && !req->xcbcmac) || 70262306a36Sopenharmony_ci /* invalidate if (i)digest changed */ 70362306a36Sopenharmony_ci memcmp(ctx->base.ctxr->data, req->state, req->state_sz) || 70462306a36Sopenharmony_ci /* invalidate for HMAC finish with odigest changed */ 70562306a36Sopenharmony_ci (req->finish && req->hmac && 70662306a36Sopenharmony_ci memcmp(ctx->base.ctxr->data + (req->state_sz>>2), 70762306a36Sopenharmony_ci &ctx->base.opad, req->state_sz)))) 70862306a36Sopenharmony_ci /* 70962306a36Sopenharmony_ci * We're still setting needs_inv here, even though it is 71062306a36Sopenharmony_ci * cleared right away, because the needs_inv flag can be 71162306a36Sopenharmony_ci * set in other functions and we want to keep the same 71262306a36Sopenharmony_ci * logic. 71362306a36Sopenharmony_ci */ 71462306a36Sopenharmony_ci ctx->base.needs_inv = true; 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci if (ctx->base.needs_inv) { 71762306a36Sopenharmony_ci ctx->base.needs_inv = false; 71862306a36Sopenharmony_ci req->needs_inv = true; 71962306a36Sopenharmony_ci } 72062306a36Sopenharmony_ci } else { 72162306a36Sopenharmony_ci ctx->base.ring = safexcel_select_ring(priv); 72262306a36Sopenharmony_ci ctx->base.ctxr = dma_pool_zalloc(priv->context_pool, 72362306a36Sopenharmony_ci EIP197_GFP_FLAGS(areq->base), 72462306a36Sopenharmony_ci &ctx->base.ctxr_dma); 72562306a36Sopenharmony_ci if (!ctx->base.ctxr) 72662306a36Sopenharmony_ci return -ENOMEM; 72762306a36Sopenharmony_ci } 72862306a36Sopenharmony_ci req->not_first = true; 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci ring = ctx->base.ring; 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci spin_lock_bh(&priv->ring[ring].queue_lock); 73362306a36Sopenharmony_ci ret = crypto_enqueue_request(&priv->ring[ring].queue, &areq->base); 73462306a36Sopenharmony_ci spin_unlock_bh(&priv->ring[ring].queue_lock); 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci queue_work(priv->ring[ring].workqueue, 73762306a36Sopenharmony_ci &priv->ring[ring].work_data.work); 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci return ret; 74062306a36Sopenharmony_ci} 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_cistatic int safexcel_ahash_update(struct ahash_request *areq) 74362306a36Sopenharmony_ci{ 74462306a36Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq); 74562306a36Sopenharmony_ci int ret; 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ci /* If the request is 0 length, do nothing */ 74862306a36Sopenharmony_ci if (!areq->nbytes) 74962306a36Sopenharmony_ci return 0; 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_ci /* Add request to the cache if it fits */ 75262306a36Sopenharmony_ci ret = safexcel_ahash_cache(areq); 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci /* Update total request length */ 75562306a36Sopenharmony_ci req->len += areq->nbytes; 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci /* If not all data could fit into the cache, go process the excess. 75862306a36Sopenharmony_ci * Also go process immediately for an HMAC IV precompute, which 75962306a36Sopenharmony_ci * will never be finished at all, but needs to be processed anyway. 76062306a36Sopenharmony_ci */ 76162306a36Sopenharmony_ci if ((ret && !req->finish) || req->last_req) 76262306a36Sopenharmony_ci return safexcel_ahash_enqueue(areq); 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci return 0; 76562306a36Sopenharmony_ci} 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_cistatic int safexcel_ahash_final(struct ahash_request *areq) 76862306a36Sopenharmony_ci{ 76962306a36Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq); 77062306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_ci req->finish = true; 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_ci if (unlikely(!req->len && !areq->nbytes)) { 77562306a36Sopenharmony_ci /* 77662306a36Sopenharmony_ci * If we have an overall 0 length *hash* request: 77762306a36Sopenharmony_ci * The HW cannot do 0 length hash, so we provide the correct 77862306a36Sopenharmony_ci * result directly here. 77962306a36Sopenharmony_ci */ 78062306a36Sopenharmony_ci if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_MD5) 78162306a36Sopenharmony_ci memcpy(areq->result, md5_zero_message_hash, 78262306a36Sopenharmony_ci MD5_DIGEST_SIZE); 78362306a36Sopenharmony_ci else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA1) 78462306a36Sopenharmony_ci memcpy(areq->result, sha1_zero_message_hash, 78562306a36Sopenharmony_ci SHA1_DIGEST_SIZE); 78662306a36Sopenharmony_ci else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA224) 78762306a36Sopenharmony_ci memcpy(areq->result, sha224_zero_message_hash, 78862306a36Sopenharmony_ci SHA224_DIGEST_SIZE); 78962306a36Sopenharmony_ci else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA256) 79062306a36Sopenharmony_ci memcpy(areq->result, sha256_zero_message_hash, 79162306a36Sopenharmony_ci SHA256_DIGEST_SIZE); 79262306a36Sopenharmony_ci else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA384) 79362306a36Sopenharmony_ci memcpy(areq->result, sha384_zero_message_hash, 79462306a36Sopenharmony_ci SHA384_DIGEST_SIZE); 79562306a36Sopenharmony_ci else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA512) 79662306a36Sopenharmony_ci memcpy(areq->result, sha512_zero_message_hash, 79762306a36Sopenharmony_ci SHA512_DIGEST_SIZE); 79862306a36Sopenharmony_ci else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SM3) { 79962306a36Sopenharmony_ci memcpy(areq->result, 80062306a36Sopenharmony_ci EIP197_SM3_ZEROM_HASH, SM3_DIGEST_SIZE); 80162306a36Sopenharmony_ci } 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_ci return 0; 80462306a36Sopenharmony_ci } else if (unlikely(req->digest == CONTEXT_CONTROL_DIGEST_XCM && 80562306a36Sopenharmony_ci ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_MD5 && 80662306a36Sopenharmony_ci req->len == sizeof(u32) && !areq->nbytes)) { 80762306a36Sopenharmony_ci /* Zero length CRC32 */ 80862306a36Sopenharmony_ci memcpy(areq->result, &ctx->base.ipad, sizeof(u32)); 80962306a36Sopenharmony_ci return 0; 81062306a36Sopenharmony_ci } else if (unlikely(ctx->cbcmac && req->len == AES_BLOCK_SIZE && 81162306a36Sopenharmony_ci !areq->nbytes)) { 81262306a36Sopenharmony_ci /* Zero length CBC MAC */ 81362306a36Sopenharmony_ci memset(areq->result, 0, AES_BLOCK_SIZE); 81462306a36Sopenharmony_ci return 0; 81562306a36Sopenharmony_ci } else if (unlikely(req->xcbcmac && req->len == AES_BLOCK_SIZE && 81662306a36Sopenharmony_ci !areq->nbytes)) { 81762306a36Sopenharmony_ci /* Zero length (X)CBC/CMAC */ 81862306a36Sopenharmony_ci int i; 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_ci for (i = 0; i < AES_BLOCK_SIZE / sizeof(u32); i++) { 82162306a36Sopenharmony_ci u32 *result = (void *)areq->result; 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci /* K3 */ 82462306a36Sopenharmony_ci result[i] = swab32(ctx->base.ipad.word[i + 4]); 82562306a36Sopenharmony_ci } 82662306a36Sopenharmony_ci areq->result[0] ^= 0x80; // 10- padding 82762306a36Sopenharmony_ci aes_encrypt(ctx->aes, areq->result, areq->result); 82862306a36Sopenharmony_ci return 0; 82962306a36Sopenharmony_ci } else if (unlikely(req->hmac && 83062306a36Sopenharmony_ci (req->len == req->block_sz) && 83162306a36Sopenharmony_ci !areq->nbytes)) { 83262306a36Sopenharmony_ci /* 83362306a36Sopenharmony_ci * If we have an overall 0 length *HMAC* request: 83462306a36Sopenharmony_ci * For HMAC, we need to finalize the inner digest 83562306a36Sopenharmony_ci * and then perform the outer hash. 83662306a36Sopenharmony_ci */ 83762306a36Sopenharmony_ci 83862306a36Sopenharmony_ci /* generate pad block in the cache */ 83962306a36Sopenharmony_ci /* start with a hash block of all zeroes */ 84062306a36Sopenharmony_ci memset(req->cache, 0, req->block_sz); 84162306a36Sopenharmony_ci /* set the first byte to 0x80 to 'append a 1 bit' */ 84262306a36Sopenharmony_ci req->cache[0] = 0x80; 84362306a36Sopenharmony_ci /* add the length in bits in the last 2 bytes */ 84462306a36Sopenharmony_ci if (req->len_is_le) { 84562306a36Sopenharmony_ci /* Little endian length word (e.g. MD5) */ 84662306a36Sopenharmony_ci req->cache[req->block_sz-8] = (req->block_sz << 3) & 84762306a36Sopenharmony_ci 255; 84862306a36Sopenharmony_ci req->cache[req->block_sz-7] = (req->block_sz >> 5); 84962306a36Sopenharmony_ci } else { 85062306a36Sopenharmony_ci /* Big endian length word (e.g. any SHA) */ 85162306a36Sopenharmony_ci req->cache[req->block_sz-2] = (req->block_sz >> 5); 85262306a36Sopenharmony_ci req->cache[req->block_sz-1] = (req->block_sz << 3) & 85362306a36Sopenharmony_ci 255; 85462306a36Sopenharmony_ci } 85562306a36Sopenharmony_ci 85662306a36Sopenharmony_ci req->len += req->block_sz; /* plus 1 hash block */ 85762306a36Sopenharmony_ci 85862306a36Sopenharmony_ci /* Set special zero-length HMAC flag */ 85962306a36Sopenharmony_ci req->hmac_zlen = true; 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ci /* Finalize HMAC */ 86262306a36Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_HMAC; 86362306a36Sopenharmony_ci } else if (req->hmac) { 86462306a36Sopenharmony_ci /* Finalize HMAC */ 86562306a36Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_HMAC; 86662306a36Sopenharmony_ci } 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_ci return safexcel_ahash_enqueue(areq); 86962306a36Sopenharmony_ci} 87062306a36Sopenharmony_ci 87162306a36Sopenharmony_cistatic int safexcel_ahash_finup(struct ahash_request *areq) 87262306a36Sopenharmony_ci{ 87362306a36Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq); 87462306a36Sopenharmony_ci 87562306a36Sopenharmony_ci req->finish = true; 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_ci safexcel_ahash_update(areq); 87862306a36Sopenharmony_ci return safexcel_ahash_final(areq); 87962306a36Sopenharmony_ci} 88062306a36Sopenharmony_ci 88162306a36Sopenharmony_cistatic int safexcel_ahash_export(struct ahash_request *areq, void *out) 88262306a36Sopenharmony_ci{ 88362306a36Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq); 88462306a36Sopenharmony_ci struct safexcel_ahash_export_state *export = out; 88562306a36Sopenharmony_ci 88662306a36Sopenharmony_ci export->len = req->len; 88762306a36Sopenharmony_ci export->processed = req->processed; 88862306a36Sopenharmony_ci 88962306a36Sopenharmony_ci export->digest = req->digest; 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_ci memcpy(export->state, req->state, req->state_sz); 89262306a36Sopenharmony_ci memcpy(export->cache, req->cache, HASH_CACHE_SIZE); 89362306a36Sopenharmony_ci 89462306a36Sopenharmony_ci return 0; 89562306a36Sopenharmony_ci} 89662306a36Sopenharmony_ci 89762306a36Sopenharmony_cistatic int safexcel_ahash_import(struct ahash_request *areq, const void *in) 89862306a36Sopenharmony_ci{ 89962306a36Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq); 90062306a36Sopenharmony_ci const struct safexcel_ahash_export_state *export = in; 90162306a36Sopenharmony_ci int ret; 90262306a36Sopenharmony_ci 90362306a36Sopenharmony_ci ret = crypto_ahash_init(areq); 90462306a36Sopenharmony_ci if (ret) 90562306a36Sopenharmony_ci return ret; 90662306a36Sopenharmony_ci 90762306a36Sopenharmony_ci req->len = export->len; 90862306a36Sopenharmony_ci req->processed = export->processed; 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_ci req->digest = export->digest; 91162306a36Sopenharmony_ci 91262306a36Sopenharmony_ci memcpy(req->cache, export->cache, HASH_CACHE_SIZE); 91362306a36Sopenharmony_ci memcpy(req->state, export->state, req->state_sz); 91462306a36Sopenharmony_ci 91562306a36Sopenharmony_ci return 0; 91662306a36Sopenharmony_ci} 91762306a36Sopenharmony_ci 91862306a36Sopenharmony_cistatic int safexcel_ahash_cra_init(struct crypto_tfm *tfm) 91962306a36Sopenharmony_ci{ 92062306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 92162306a36Sopenharmony_ci struct safexcel_alg_template *tmpl = 92262306a36Sopenharmony_ci container_of(__crypto_ahash_alg(tfm->__crt_alg), 92362306a36Sopenharmony_ci struct safexcel_alg_template, alg.ahash); 92462306a36Sopenharmony_ci 92562306a36Sopenharmony_ci ctx->base.priv = tmpl->priv; 92662306a36Sopenharmony_ci ctx->base.send = safexcel_ahash_send; 92762306a36Sopenharmony_ci ctx->base.handle_result = safexcel_handle_result; 92862306a36Sopenharmony_ci ctx->fb_do_setkey = false; 92962306a36Sopenharmony_ci 93062306a36Sopenharmony_ci crypto_ahash_set_reqsize_dma(__crypto_ahash_cast(tfm), 93162306a36Sopenharmony_ci sizeof(struct safexcel_ahash_req)); 93262306a36Sopenharmony_ci return 0; 93362306a36Sopenharmony_ci} 93462306a36Sopenharmony_ci 93562306a36Sopenharmony_cistatic int safexcel_sha1_init(struct ahash_request *areq) 93662306a36Sopenharmony_ci{ 93762306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 93862306a36Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq); 93962306a36Sopenharmony_ci 94062306a36Sopenharmony_ci memset(req, 0, sizeof(*req)); 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1; 94362306a36Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 94462306a36Sopenharmony_ci req->state_sz = SHA1_DIGEST_SIZE; 94562306a36Sopenharmony_ci req->digest_sz = SHA1_DIGEST_SIZE; 94662306a36Sopenharmony_ci req->block_sz = SHA1_BLOCK_SIZE; 94762306a36Sopenharmony_ci 94862306a36Sopenharmony_ci return 0; 94962306a36Sopenharmony_ci} 95062306a36Sopenharmony_ci 95162306a36Sopenharmony_cistatic int safexcel_sha1_digest(struct ahash_request *areq) 95262306a36Sopenharmony_ci{ 95362306a36Sopenharmony_ci int ret = safexcel_sha1_init(areq); 95462306a36Sopenharmony_ci 95562306a36Sopenharmony_ci if (ret) 95662306a36Sopenharmony_ci return ret; 95762306a36Sopenharmony_ci 95862306a36Sopenharmony_ci return safexcel_ahash_finup(areq); 95962306a36Sopenharmony_ci} 96062306a36Sopenharmony_ci 96162306a36Sopenharmony_cistatic void safexcel_ahash_cra_exit(struct crypto_tfm *tfm) 96262306a36Sopenharmony_ci{ 96362306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 96462306a36Sopenharmony_ci struct safexcel_crypto_priv *priv = ctx->base.priv; 96562306a36Sopenharmony_ci int ret; 96662306a36Sopenharmony_ci 96762306a36Sopenharmony_ci /* context not allocated, skip invalidation */ 96862306a36Sopenharmony_ci if (!ctx->base.ctxr) 96962306a36Sopenharmony_ci return; 97062306a36Sopenharmony_ci 97162306a36Sopenharmony_ci if (priv->flags & EIP197_TRC_CACHE) { 97262306a36Sopenharmony_ci ret = safexcel_ahash_exit_inv(tfm); 97362306a36Sopenharmony_ci if (ret) 97462306a36Sopenharmony_ci dev_warn(priv->dev, "hash: invalidation error %d\n", ret); 97562306a36Sopenharmony_ci } else { 97662306a36Sopenharmony_ci dma_pool_free(priv->context_pool, ctx->base.ctxr, 97762306a36Sopenharmony_ci ctx->base.ctxr_dma); 97862306a36Sopenharmony_ci } 97962306a36Sopenharmony_ci} 98062306a36Sopenharmony_ci 98162306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_sha1 = { 98262306a36Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 98362306a36Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA1, 98462306a36Sopenharmony_ci .alg.ahash = { 98562306a36Sopenharmony_ci .init = safexcel_sha1_init, 98662306a36Sopenharmony_ci .update = safexcel_ahash_update, 98762306a36Sopenharmony_ci .final = safexcel_ahash_final, 98862306a36Sopenharmony_ci .finup = safexcel_ahash_finup, 98962306a36Sopenharmony_ci .digest = safexcel_sha1_digest, 99062306a36Sopenharmony_ci .export = safexcel_ahash_export, 99162306a36Sopenharmony_ci .import = safexcel_ahash_import, 99262306a36Sopenharmony_ci .halg = { 99362306a36Sopenharmony_ci .digestsize = SHA1_DIGEST_SIZE, 99462306a36Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 99562306a36Sopenharmony_ci .base = { 99662306a36Sopenharmony_ci .cra_name = "sha1", 99762306a36Sopenharmony_ci .cra_driver_name = "safexcel-sha1", 99862306a36Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 99962306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 100062306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 100162306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 100262306a36Sopenharmony_ci .cra_blocksize = SHA1_BLOCK_SIZE, 100362306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 100462306a36Sopenharmony_ci .cra_init = safexcel_ahash_cra_init, 100562306a36Sopenharmony_ci .cra_exit = safexcel_ahash_cra_exit, 100662306a36Sopenharmony_ci .cra_module = THIS_MODULE, 100762306a36Sopenharmony_ci }, 100862306a36Sopenharmony_ci }, 100962306a36Sopenharmony_ci }, 101062306a36Sopenharmony_ci}; 101162306a36Sopenharmony_ci 101262306a36Sopenharmony_cistatic int safexcel_hmac_sha1_init(struct ahash_request *areq) 101362306a36Sopenharmony_ci{ 101462306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 101562306a36Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq); 101662306a36Sopenharmony_ci 101762306a36Sopenharmony_ci memset(req, 0, sizeof(*req)); 101862306a36Sopenharmony_ci 101962306a36Sopenharmony_ci /* Start from ipad precompute */ 102062306a36Sopenharmony_ci memcpy(req->state, &ctx->base.ipad, SHA1_DIGEST_SIZE); 102162306a36Sopenharmony_ci /* Already processed the key^ipad part now! */ 102262306a36Sopenharmony_ci req->len = SHA1_BLOCK_SIZE; 102362306a36Sopenharmony_ci req->processed = SHA1_BLOCK_SIZE; 102462306a36Sopenharmony_ci 102562306a36Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1; 102662306a36Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 102762306a36Sopenharmony_ci req->state_sz = SHA1_DIGEST_SIZE; 102862306a36Sopenharmony_ci req->digest_sz = SHA1_DIGEST_SIZE; 102962306a36Sopenharmony_ci req->block_sz = SHA1_BLOCK_SIZE; 103062306a36Sopenharmony_ci req->hmac = true; 103162306a36Sopenharmony_ci 103262306a36Sopenharmony_ci return 0; 103362306a36Sopenharmony_ci} 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_cistatic int safexcel_hmac_sha1_digest(struct ahash_request *areq) 103662306a36Sopenharmony_ci{ 103762306a36Sopenharmony_ci int ret = safexcel_hmac_sha1_init(areq); 103862306a36Sopenharmony_ci 103962306a36Sopenharmony_ci if (ret) 104062306a36Sopenharmony_ci return ret; 104162306a36Sopenharmony_ci 104262306a36Sopenharmony_ci return safexcel_ahash_finup(areq); 104362306a36Sopenharmony_ci} 104462306a36Sopenharmony_ci 104562306a36Sopenharmony_cistatic int safexcel_hmac_init_pad(struct ahash_request *areq, 104662306a36Sopenharmony_ci unsigned int blocksize, const u8 *key, 104762306a36Sopenharmony_ci unsigned int keylen, u8 *ipad, u8 *opad) 104862306a36Sopenharmony_ci{ 104962306a36Sopenharmony_ci DECLARE_CRYPTO_WAIT(result); 105062306a36Sopenharmony_ci struct scatterlist sg; 105162306a36Sopenharmony_ci int ret, i; 105262306a36Sopenharmony_ci u8 *keydup; 105362306a36Sopenharmony_ci 105462306a36Sopenharmony_ci if (keylen <= blocksize) { 105562306a36Sopenharmony_ci memcpy(ipad, key, keylen); 105662306a36Sopenharmony_ci } else { 105762306a36Sopenharmony_ci keydup = kmemdup(key, keylen, GFP_KERNEL); 105862306a36Sopenharmony_ci if (!keydup) 105962306a36Sopenharmony_ci return -ENOMEM; 106062306a36Sopenharmony_ci 106162306a36Sopenharmony_ci ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_BACKLOG, 106262306a36Sopenharmony_ci crypto_req_done, &result); 106362306a36Sopenharmony_ci sg_init_one(&sg, keydup, keylen); 106462306a36Sopenharmony_ci ahash_request_set_crypt(areq, &sg, ipad, keylen); 106562306a36Sopenharmony_ci 106662306a36Sopenharmony_ci ret = crypto_ahash_digest(areq); 106762306a36Sopenharmony_ci ret = crypto_wait_req(ret, &result); 106862306a36Sopenharmony_ci 106962306a36Sopenharmony_ci /* Avoid leaking */ 107062306a36Sopenharmony_ci kfree_sensitive(keydup); 107162306a36Sopenharmony_ci 107262306a36Sopenharmony_ci if (ret) 107362306a36Sopenharmony_ci return ret; 107462306a36Sopenharmony_ci 107562306a36Sopenharmony_ci keylen = crypto_ahash_digestsize(crypto_ahash_reqtfm(areq)); 107662306a36Sopenharmony_ci } 107762306a36Sopenharmony_ci 107862306a36Sopenharmony_ci memset(ipad + keylen, 0, blocksize - keylen); 107962306a36Sopenharmony_ci memcpy(opad, ipad, blocksize); 108062306a36Sopenharmony_ci 108162306a36Sopenharmony_ci for (i = 0; i < blocksize; i++) { 108262306a36Sopenharmony_ci ipad[i] ^= HMAC_IPAD_VALUE; 108362306a36Sopenharmony_ci opad[i] ^= HMAC_OPAD_VALUE; 108462306a36Sopenharmony_ci } 108562306a36Sopenharmony_ci 108662306a36Sopenharmony_ci return 0; 108762306a36Sopenharmony_ci} 108862306a36Sopenharmony_ci 108962306a36Sopenharmony_cistatic int safexcel_hmac_init_iv(struct ahash_request *areq, 109062306a36Sopenharmony_ci unsigned int blocksize, u8 *pad, void *state) 109162306a36Sopenharmony_ci{ 109262306a36Sopenharmony_ci struct safexcel_ahash_req *req; 109362306a36Sopenharmony_ci DECLARE_CRYPTO_WAIT(result); 109462306a36Sopenharmony_ci struct scatterlist sg; 109562306a36Sopenharmony_ci int ret; 109662306a36Sopenharmony_ci 109762306a36Sopenharmony_ci ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_BACKLOG, 109862306a36Sopenharmony_ci crypto_req_done, &result); 109962306a36Sopenharmony_ci sg_init_one(&sg, pad, blocksize); 110062306a36Sopenharmony_ci ahash_request_set_crypt(areq, &sg, pad, blocksize); 110162306a36Sopenharmony_ci 110262306a36Sopenharmony_ci ret = crypto_ahash_init(areq); 110362306a36Sopenharmony_ci if (ret) 110462306a36Sopenharmony_ci return ret; 110562306a36Sopenharmony_ci 110662306a36Sopenharmony_ci req = ahash_request_ctx_dma(areq); 110762306a36Sopenharmony_ci req->hmac = true; 110862306a36Sopenharmony_ci req->last_req = true; 110962306a36Sopenharmony_ci 111062306a36Sopenharmony_ci ret = crypto_ahash_update(areq); 111162306a36Sopenharmony_ci ret = crypto_wait_req(ret, &result); 111262306a36Sopenharmony_ci 111362306a36Sopenharmony_ci return ret ?: crypto_ahash_export(areq, state); 111462306a36Sopenharmony_ci} 111562306a36Sopenharmony_ci 111662306a36Sopenharmony_cistatic int __safexcel_hmac_setkey(const char *alg, const u8 *key, 111762306a36Sopenharmony_ci unsigned int keylen, 111862306a36Sopenharmony_ci void *istate, void *ostate) 111962306a36Sopenharmony_ci{ 112062306a36Sopenharmony_ci struct ahash_request *areq; 112162306a36Sopenharmony_ci struct crypto_ahash *tfm; 112262306a36Sopenharmony_ci unsigned int blocksize; 112362306a36Sopenharmony_ci u8 *ipad, *opad; 112462306a36Sopenharmony_ci int ret; 112562306a36Sopenharmony_ci 112662306a36Sopenharmony_ci tfm = crypto_alloc_ahash(alg, 0, 0); 112762306a36Sopenharmony_ci if (IS_ERR(tfm)) 112862306a36Sopenharmony_ci return PTR_ERR(tfm); 112962306a36Sopenharmony_ci 113062306a36Sopenharmony_ci areq = ahash_request_alloc(tfm, GFP_KERNEL); 113162306a36Sopenharmony_ci if (!areq) { 113262306a36Sopenharmony_ci ret = -ENOMEM; 113362306a36Sopenharmony_ci goto free_ahash; 113462306a36Sopenharmony_ci } 113562306a36Sopenharmony_ci 113662306a36Sopenharmony_ci crypto_ahash_clear_flags(tfm, ~0); 113762306a36Sopenharmony_ci blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); 113862306a36Sopenharmony_ci 113962306a36Sopenharmony_ci ipad = kcalloc(2, blocksize, GFP_KERNEL); 114062306a36Sopenharmony_ci if (!ipad) { 114162306a36Sopenharmony_ci ret = -ENOMEM; 114262306a36Sopenharmony_ci goto free_request; 114362306a36Sopenharmony_ci } 114462306a36Sopenharmony_ci 114562306a36Sopenharmony_ci opad = ipad + blocksize; 114662306a36Sopenharmony_ci 114762306a36Sopenharmony_ci ret = safexcel_hmac_init_pad(areq, blocksize, key, keylen, ipad, opad); 114862306a36Sopenharmony_ci if (ret) 114962306a36Sopenharmony_ci goto free_ipad; 115062306a36Sopenharmony_ci 115162306a36Sopenharmony_ci ret = safexcel_hmac_init_iv(areq, blocksize, ipad, istate); 115262306a36Sopenharmony_ci if (ret) 115362306a36Sopenharmony_ci goto free_ipad; 115462306a36Sopenharmony_ci 115562306a36Sopenharmony_ci ret = safexcel_hmac_init_iv(areq, blocksize, opad, ostate); 115662306a36Sopenharmony_ci 115762306a36Sopenharmony_cifree_ipad: 115862306a36Sopenharmony_ci kfree(ipad); 115962306a36Sopenharmony_cifree_request: 116062306a36Sopenharmony_ci ahash_request_free(areq); 116162306a36Sopenharmony_cifree_ahash: 116262306a36Sopenharmony_ci crypto_free_ahash(tfm); 116362306a36Sopenharmony_ci 116462306a36Sopenharmony_ci return ret; 116562306a36Sopenharmony_ci} 116662306a36Sopenharmony_ci 116762306a36Sopenharmony_ciint safexcel_hmac_setkey(struct safexcel_context *base, const u8 *key, 116862306a36Sopenharmony_ci unsigned int keylen, const char *alg, 116962306a36Sopenharmony_ci unsigned int state_sz) 117062306a36Sopenharmony_ci{ 117162306a36Sopenharmony_ci struct safexcel_crypto_priv *priv = base->priv; 117262306a36Sopenharmony_ci struct safexcel_ahash_export_state istate, ostate; 117362306a36Sopenharmony_ci int ret; 117462306a36Sopenharmony_ci 117562306a36Sopenharmony_ci ret = __safexcel_hmac_setkey(alg, key, keylen, &istate, &ostate); 117662306a36Sopenharmony_ci if (ret) 117762306a36Sopenharmony_ci return ret; 117862306a36Sopenharmony_ci 117962306a36Sopenharmony_ci if (priv->flags & EIP197_TRC_CACHE && base->ctxr && 118062306a36Sopenharmony_ci (memcmp(&base->ipad, istate.state, state_sz) || 118162306a36Sopenharmony_ci memcmp(&base->opad, ostate.state, state_sz))) 118262306a36Sopenharmony_ci base->needs_inv = true; 118362306a36Sopenharmony_ci 118462306a36Sopenharmony_ci memcpy(&base->ipad, &istate.state, state_sz); 118562306a36Sopenharmony_ci memcpy(&base->opad, &ostate.state, state_sz); 118662306a36Sopenharmony_ci 118762306a36Sopenharmony_ci return 0; 118862306a36Sopenharmony_ci} 118962306a36Sopenharmony_ci 119062306a36Sopenharmony_cistatic int safexcel_hmac_alg_setkey(struct crypto_ahash *tfm, const u8 *key, 119162306a36Sopenharmony_ci unsigned int keylen, const char *alg, 119262306a36Sopenharmony_ci unsigned int state_sz) 119362306a36Sopenharmony_ci{ 119462306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 119562306a36Sopenharmony_ci 119662306a36Sopenharmony_ci return safexcel_hmac_setkey(&ctx->base, key, keylen, alg, state_sz); 119762306a36Sopenharmony_ci} 119862306a36Sopenharmony_ci 119962306a36Sopenharmony_cistatic int safexcel_hmac_sha1_setkey(struct crypto_ahash *tfm, const u8 *key, 120062306a36Sopenharmony_ci unsigned int keylen) 120162306a36Sopenharmony_ci{ 120262306a36Sopenharmony_ci return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha1", 120362306a36Sopenharmony_ci SHA1_DIGEST_SIZE); 120462306a36Sopenharmony_ci} 120562306a36Sopenharmony_ci 120662306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_hmac_sha1 = { 120762306a36Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 120862306a36Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA1, 120962306a36Sopenharmony_ci .alg.ahash = { 121062306a36Sopenharmony_ci .init = safexcel_hmac_sha1_init, 121162306a36Sopenharmony_ci .update = safexcel_ahash_update, 121262306a36Sopenharmony_ci .final = safexcel_ahash_final, 121362306a36Sopenharmony_ci .finup = safexcel_ahash_finup, 121462306a36Sopenharmony_ci .digest = safexcel_hmac_sha1_digest, 121562306a36Sopenharmony_ci .setkey = safexcel_hmac_sha1_setkey, 121662306a36Sopenharmony_ci .export = safexcel_ahash_export, 121762306a36Sopenharmony_ci .import = safexcel_ahash_import, 121862306a36Sopenharmony_ci .halg = { 121962306a36Sopenharmony_ci .digestsize = SHA1_DIGEST_SIZE, 122062306a36Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 122162306a36Sopenharmony_ci .base = { 122262306a36Sopenharmony_ci .cra_name = "hmac(sha1)", 122362306a36Sopenharmony_ci .cra_driver_name = "safexcel-hmac-sha1", 122462306a36Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 122562306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 122662306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 122762306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 122862306a36Sopenharmony_ci .cra_blocksize = SHA1_BLOCK_SIZE, 122962306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 123062306a36Sopenharmony_ci .cra_init = safexcel_ahash_cra_init, 123162306a36Sopenharmony_ci .cra_exit = safexcel_ahash_cra_exit, 123262306a36Sopenharmony_ci .cra_module = THIS_MODULE, 123362306a36Sopenharmony_ci }, 123462306a36Sopenharmony_ci }, 123562306a36Sopenharmony_ci }, 123662306a36Sopenharmony_ci}; 123762306a36Sopenharmony_ci 123862306a36Sopenharmony_cistatic int safexcel_sha256_init(struct ahash_request *areq) 123962306a36Sopenharmony_ci{ 124062306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 124162306a36Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq); 124262306a36Sopenharmony_ci 124362306a36Sopenharmony_ci memset(req, 0, sizeof(*req)); 124462306a36Sopenharmony_ci 124562306a36Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256; 124662306a36Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 124762306a36Sopenharmony_ci req->state_sz = SHA256_DIGEST_SIZE; 124862306a36Sopenharmony_ci req->digest_sz = SHA256_DIGEST_SIZE; 124962306a36Sopenharmony_ci req->block_sz = SHA256_BLOCK_SIZE; 125062306a36Sopenharmony_ci 125162306a36Sopenharmony_ci return 0; 125262306a36Sopenharmony_ci} 125362306a36Sopenharmony_ci 125462306a36Sopenharmony_cistatic int safexcel_sha256_digest(struct ahash_request *areq) 125562306a36Sopenharmony_ci{ 125662306a36Sopenharmony_ci int ret = safexcel_sha256_init(areq); 125762306a36Sopenharmony_ci 125862306a36Sopenharmony_ci if (ret) 125962306a36Sopenharmony_ci return ret; 126062306a36Sopenharmony_ci 126162306a36Sopenharmony_ci return safexcel_ahash_finup(areq); 126262306a36Sopenharmony_ci} 126362306a36Sopenharmony_ci 126462306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_sha256 = { 126562306a36Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 126662306a36Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA2_256, 126762306a36Sopenharmony_ci .alg.ahash = { 126862306a36Sopenharmony_ci .init = safexcel_sha256_init, 126962306a36Sopenharmony_ci .update = safexcel_ahash_update, 127062306a36Sopenharmony_ci .final = safexcel_ahash_final, 127162306a36Sopenharmony_ci .finup = safexcel_ahash_finup, 127262306a36Sopenharmony_ci .digest = safexcel_sha256_digest, 127362306a36Sopenharmony_ci .export = safexcel_ahash_export, 127462306a36Sopenharmony_ci .import = safexcel_ahash_import, 127562306a36Sopenharmony_ci .halg = { 127662306a36Sopenharmony_ci .digestsize = SHA256_DIGEST_SIZE, 127762306a36Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 127862306a36Sopenharmony_ci .base = { 127962306a36Sopenharmony_ci .cra_name = "sha256", 128062306a36Sopenharmony_ci .cra_driver_name = "safexcel-sha256", 128162306a36Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 128262306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 128362306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 128462306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 128562306a36Sopenharmony_ci .cra_blocksize = SHA256_BLOCK_SIZE, 128662306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 128762306a36Sopenharmony_ci .cra_init = safexcel_ahash_cra_init, 128862306a36Sopenharmony_ci .cra_exit = safexcel_ahash_cra_exit, 128962306a36Sopenharmony_ci .cra_module = THIS_MODULE, 129062306a36Sopenharmony_ci }, 129162306a36Sopenharmony_ci }, 129262306a36Sopenharmony_ci }, 129362306a36Sopenharmony_ci}; 129462306a36Sopenharmony_ci 129562306a36Sopenharmony_cistatic int safexcel_sha224_init(struct ahash_request *areq) 129662306a36Sopenharmony_ci{ 129762306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 129862306a36Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq); 129962306a36Sopenharmony_ci 130062306a36Sopenharmony_ci memset(req, 0, sizeof(*req)); 130162306a36Sopenharmony_ci 130262306a36Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224; 130362306a36Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 130462306a36Sopenharmony_ci req->state_sz = SHA256_DIGEST_SIZE; 130562306a36Sopenharmony_ci req->digest_sz = SHA256_DIGEST_SIZE; 130662306a36Sopenharmony_ci req->block_sz = SHA256_BLOCK_SIZE; 130762306a36Sopenharmony_ci 130862306a36Sopenharmony_ci return 0; 130962306a36Sopenharmony_ci} 131062306a36Sopenharmony_ci 131162306a36Sopenharmony_cistatic int safexcel_sha224_digest(struct ahash_request *areq) 131262306a36Sopenharmony_ci{ 131362306a36Sopenharmony_ci int ret = safexcel_sha224_init(areq); 131462306a36Sopenharmony_ci 131562306a36Sopenharmony_ci if (ret) 131662306a36Sopenharmony_ci return ret; 131762306a36Sopenharmony_ci 131862306a36Sopenharmony_ci return safexcel_ahash_finup(areq); 131962306a36Sopenharmony_ci} 132062306a36Sopenharmony_ci 132162306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_sha224 = { 132262306a36Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 132362306a36Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA2_256, 132462306a36Sopenharmony_ci .alg.ahash = { 132562306a36Sopenharmony_ci .init = safexcel_sha224_init, 132662306a36Sopenharmony_ci .update = safexcel_ahash_update, 132762306a36Sopenharmony_ci .final = safexcel_ahash_final, 132862306a36Sopenharmony_ci .finup = safexcel_ahash_finup, 132962306a36Sopenharmony_ci .digest = safexcel_sha224_digest, 133062306a36Sopenharmony_ci .export = safexcel_ahash_export, 133162306a36Sopenharmony_ci .import = safexcel_ahash_import, 133262306a36Sopenharmony_ci .halg = { 133362306a36Sopenharmony_ci .digestsize = SHA224_DIGEST_SIZE, 133462306a36Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 133562306a36Sopenharmony_ci .base = { 133662306a36Sopenharmony_ci .cra_name = "sha224", 133762306a36Sopenharmony_ci .cra_driver_name = "safexcel-sha224", 133862306a36Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 133962306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 134062306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 134162306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 134262306a36Sopenharmony_ci .cra_blocksize = SHA224_BLOCK_SIZE, 134362306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 134462306a36Sopenharmony_ci .cra_init = safexcel_ahash_cra_init, 134562306a36Sopenharmony_ci .cra_exit = safexcel_ahash_cra_exit, 134662306a36Sopenharmony_ci .cra_module = THIS_MODULE, 134762306a36Sopenharmony_ci }, 134862306a36Sopenharmony_ci }, 134962306a36Sopenharmony_ci }, 135062306a36Sopenharmony_ci}; 135162306a36Sopenharmony_ci 135262306a36Sopenharmony_cistatic int safexcel_hmac_sha224_setkey(struct crypto_ahash *tfm, const u8 *key, 135362306a36Sopenharmony_ci unsigned int keylen) 135462306a36Sopenharmony_ci{ 135562306a36Sopenharmony_ci return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha224", 135662306a36Sopenharmony_ci SHA256_DIGEST_SIZE); 135762306a36Sopenharmony_ci} 135862306a36Sopenharmony_ci 135962306a36Sopenharmony_cistatic int safexcel_hmac_sha224_init(struct ahash_request *areq) 136062306a36Sopenharmony_ci{ 136162306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 136262306a36Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq); 136362306a36Sopenharmony_ci 136462306a36Sopenharmony_ci memset(req, 0, sizeof(*req)); 136562306a36Sopenharmony_ci 136662306a36Sopenharmony_ci /* Start from ipad precompute */ 136762306a36Sopenharmony_ci memcpy(req->state, &ctx->base.ipad, SHA256_DIGEST_SIZE); 136862306a36Sopenharmony_ci /* Already processed the key^ipad part now! */ 136962306a36Sopenharmony_ci req->len = SHA256_BLOCK_SIZE; 137062306a36Sopenharmony_ci req->processed = SHA256_BLOCK_SIZE; 137162306a36Sopenharmony_ci 137262306a36Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224; 137362306a36Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 137462306a36Sopenharmony_ci req->state_sz = SHA256_DIGEST_SIZE; 137562306a36Sopenharmony_ci req->digest_sz = SHA256_DIGEST_SIZE; 137662306a36Sopenharmony_ci req->block_sz = SHA256_BLOCK_SIZE; 137762306a36Sopenharmony_ci req->hmac = true; 137862306a36Sopenharmony_ci 137962306a36Sopenharmony_ci return 0; 138062306a36Sopenharmony_ci} 138162306a36Sopenharmony_ci 138262306a36Sopenharmony_cistatic int safexcel_hmac_sha224_digest(struct ahash_request *areq) 138362306a36Sopenharmony_ci{ 138462306a36Sopenharmony_ci int ret = safexcel_hmac_sha224_init(areq); 138562306a36Sopenharmony_ci 138662306a36Sopenharmony_ci if (ret) 138762306a36Sopenharmony_ci return ret; 138862306a36Sopenharmony_ci 138962306a36Sopenharmony_ci return safexcel_ahash_finup(areq); 139062306a36Sopenharmony_ci} 139162306a36Sopenharmony_ci 139262306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_hmac_sha224 = { 139362306a36Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 139462306a36Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA2_256, 139562306a36Sopenharmony_ci .alg.ahash = { 139662306a36Sopenharmony_ci .init = safexcel_hmac_sha224_init, 139762306a36Sopenharmony_ci .update = safexcel_ahash_update, 139862306a36Sopenharmony_ci .final = safexcel_ahash_final, 139962306a36Sopenharmony_ci .finup = safexcel_ahash_finup, 140062306a36Sopenharmony_ci .digest = safexcel_hmac_sha224_digest, 140162306a36Sopenharmony_ci .setkey = safexcel_hmac_sha224_setkey, 140262306a36Sopenharmony_ci .export = safexcel_ahash_export, 140362306a36Sopenharmony_ci .import = safexcel_ahash_import, 140462306a36Sopenharmony_ci .halg = { 140562306a36Sopenharmony_ci .digestsize = SHA224_DIGEST_SIZE, 140662306a36Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 140762306a36Sopenharmony_ci .base = { 140862306a36Sopenharmony_ci .cra_name = "hmac(sha224)", 140962306a36Sopenharmony_ci .cra_driver_name = "safexcel-hmac-sha224", 141062306a36Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 141162306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 141262306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 141362306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 141462306a36Sopenharmony_ci .cra_blocksize = SHA224_BLOCK_SIZE, 141562306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 141662306a36Sopenharmony_ci .cra_init = safexcel_ahash_cra_init, 141762306a36Sopenharmony_ci .cra_exit = safexcel_ahash_cra_exit, 141862306a36Sopenharmony_ci .cra_module = THIS_MODULE, 141962306a36Sopenharmony_ci }, 142062306a36Sopenharmony_ci }, 142162306a36Sopenharmony_ci }, 142262306a36Sopenharmony_ci}; 142362306a36Sopenharmony_ci 142462306a36Sopenharmony_cistatic int safexcel_hmac_sha256_setkey(struct crypto_ahash *tfm, const u8 *key, 142562306a36Sopenharmony_ci unsigned int keylen) 142662306a36Sopenharmony_ci{ 142762306a36Sopenharmony_ci return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha256", 142862306a36Sopenharmony_ci SHA256_DIGEST_SIZE); 142962306a36Sopenharmony_ci} 143062306a36Sopenharmony_ci 143162306a36Sopenharmony_cistatic int safexcel_hmac_sha256_init(struct ahash_request *areq) 143262306a36Sopenharmony_ci{ 143362306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 143462306a36Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq); 143562306a36Sopenharmony_ci 143662306a36Sopenharmony_ci memset(req, 0, sizeof(*req)); 143762306a36Sopenharmony_ci 143862306a36Sopenharmony_ci /* Start from ipad precompute */ 143962306a36Sopenharmony_ci memcpy(req->state, &ctx->base.ipad, SHA256_DIGEST_SIZE); 144062306a36Sopenharmony_ci /* Already processed the key^ipad part now! */ 144162306a36Sopenharmony_ci req->len = SHA256_BLOCK_SIZE; 144262306a36Sopenharmony_ci req->processed = SHA256_BLOCK_SIZE; 144362306a36Sopenharmony_ci 144462306a36Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256; 144562306a36Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 144662306a36Sopenharmony_ci req->state_sz = SHA256_DIGEST_SIZE; 144762306a36Sopenharmony_ci req->digest_sz = SHA256_DIGEST_SIZE; 144862306a36Sopenharmony_ci req->block_sz = SHA256_BLOCK_SIZE; 144962306a36Sopenharmony_ci req->hmac = true; 145062306a36Sopenharmony_ci 145162306a36Sopenharmony_ci return 0; 145262306a36Sopenharmony_ci} 145362306a36Sopenharmony_ci 145462306a36Sopenharmony_cistatic int safexcel_hmac_sha256_digest(struct ahash_request *areq) 145562306a36Sopenharmony_ci{ 145662306a36Sopenharmony_ci int ret = safexcel_hmac_sha256_init(areq); 145762306a36Sopenharmony_ci 145862306a36Sopenharmony_ci if (ret) 145962306a36Sopenharmony_ci return ret; 146062306a36Sopenharmony_ci 146162306a36Sopenharmony_ci return safexcel_ahash_finup(areq); 146262306a36Sopenharmony_ci} 146362306a36Sopenharmony_ci 146462306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_hmac_sha256 = { 146562306a36Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 146662306a36Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA2_256, 146762306a36Sopenharmony_ci .alg.ahash = { 146862306a36Sopenharmony_ci .init = safexcel_hmac_sha256_init, 146962306a36Sopenharmony_ci .update = safexcel_ahash_update, 147062306a36Sopenharmony_ci .final = safexcel_ahash_final, 147162306a36Sopenharmony_ci .finup = safexcel_ahash_finup, 147262306a36Sopenharmony_ci .digest = safexcel_hmac_sha256_digest, 147362306a36Sopenharmony_ci .setkey = safexcel_hmac_sha256_setkey, 147462306a36Sopenharmony_ci .export = safexcel_ahash_export, 147562306a36Sopenharmony_ci .import = safexcel_ahash_import, 147662306a36Sopenharmony_ci .halg = { 147762306a36Sopenharmony_ci .digestsize = SHA256_DIGEST_SIZE, 147862306a36Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 147962306a36Sopenharmony_ci .base = { 148062306a36Sopenharmony_ci .cra_name = "hmac(sha256)", 148162306a36Sopenharmony_ci .cra_driver_name = "safexcel-hmac-sha256", 148262306a36Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 148362306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 148462306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 148562306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 148662306a36Sopenharmony_ci .cra_blocksize = SHA256_BLOCK_SIZE, 148762306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 148862306a36Sopenharmony_ci .cra_init = safexcel_ahash_cra_init, 148962306a36Sopenharmony_ci .cra_exit = safexcel_ahash_cra_exit, 149062306a36Sopenharmony_ci .cra_module = THIS_MODULE, 149162306a36Sopenharmony_ci }, 149262306a36Sopenharmony_ci }, 149362306a36Sopenharmony_ci }, 149462306a36Sopenharmony_ci}; 149562306a36Sopenharmony_ci 149662306a36Sopenharmony_cistatic int safexcel_sha512_init(struct ahash_request *areq) 149762306a36Sopenharmony_ci{ 149862306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 149962306a36Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq); 150062306a36Sopenharmony_ci 150162306a36Sopenharmony_ci memset(req, 0, sizeof(*req)); 150262306a36Sopenharmony_ci 150362306a36Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512; 150462306a36Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 150562306a36Sopenharmony_ci req->state_sz = SHA512_DIGEST_SIZE; 150662306a36Sopenharmony_ci req->digest_sz = SHA512_DIGEST_SIZE; 150762306a36Sopenharmony_ci req->block_sz = SHA512_BLOCK_SIZE; 150862306a36Sopenharmony_ci 150962306a36Sopenharmony_ci return 0; 151062306a36Sopenharmony_ci} 151162306a36Sopenharmony_ci 151262306a36Sopenharmony_cistatic int safexcel_sha512_digest(struct ahash_request *areq) 151362306a36Sopenharmony_ci{ 151462306a36Sopenharmony_ci int ret = safexcel_sha512_init(areq); 151562306a36Sopenharmony_ci 151662306a36Sopenharmony_ci if (ret) 151762306a36Sopenharmony_ci return ret; 151862306a36Sopenharmony_ci 151962306a36Sopenharmony_ci return safexcel_ahash_finup(areq); 152062306a36Sopenharmony_ci} 152162306a36Sopenharmony_ci 152262306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_sha512 = { 152362306a36Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 152462306a36Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA2_512, 152562306a36Sopenharmony_ci .alg.ahash = { 152662306a36Sopenharmony_ci .init = safexcel_sha512_init, 152762306a36Sopenharmony_ci .update = safexcel_ahash_update, 152862306a36Sopenharmony_ci .final = safexcel_ahash_final, 152962306a36Sopenharmony_ci .finup = safexcel_ahash_finup, 153062306a36Sopenharmony_ci .digest = safexcel_sha512_digest, 153162306a36Sopenharmony_ci .export = safexcel_ahash_export, 153262306a36Sopenharmony_ci .import = safexcel_ahash_import, 153362306a36Sopenharmony_ci .halg = { 153462306a36Sopenharmony_ci .digestsize = SHA512_DIGEST_SIZE, 153562306a36Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 153662306a36Sopenharmony_ci .base = { 153762306a36Sopenharmony_ci .cra_name = "sha512", 153862306a36Sopenharmony_ci .cra_driver_name = "safexcel-sha512", 153962306a36Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 154062306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 154162306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 154262306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 154362306a36Sopenharmony_ci .cra_blocksize = SHA512_BLOCK_SIZE, 154462306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 154562306a36Sopenharmony_ci .cra_init = safexcel_ahash_cra_init, 154662306a36Sopenharmony_ci .cra_exit = safexcel_ahash_cra_exit, 154762306a36Sopenharmony_ci .cra_module = THIS_MODULE, 154862306a36Sopenharmony_ci }, 154962306a36Sopenharmony_ci }, 155062306a36Sopenharmony_ci }, 155162306a36Sopenharmony_ci}; 155262306a36Sopenharmony_ci 155362306a36Sopenharmony_cistatic int safexcel_sha384_init(struct ahash_request *areq) 155462306a36Sopenharmony_ci{ 155562306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 155662306a36Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq); 155762306a36Sopenharmony_ci 155862306a36Sopenharmony_ci memset(req, 0, sizeof(*req)); 155962306a36Sopenharmony_ci 156062306a36Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384; 156162306a36Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 156262306a36Sopenharmony_ci req->state_sz = SHA512_DIGEST_SIZE; 156362306a36Sopenharmony_ci req->digest_sz = SHA512_DIGEST_SIZE; 156462306a36Sopenharmony_ci req->block_sz = SHA512_BLOCK_SIZE; 156562306a36Sopenharmony_ci 156662306a36Sopenharmony_ci return 0; 156762306a36Sopenharmony_ci} 156862306a36Sopenharmony_ci 156962306a36Sopenharmony_cistatic int safexcel_sha384_digest(struct ahash_request *areq) 157062306a36Sopenharmony_ci{ 157162306a36Sopenharmony_ci int ret = safexcel_sha384_init(areq); 157262306a36Sopenharmony_ci 157362306a36Sopenharmony_ci if (ret) 157462306a36Sopenharmony_ci return ret; 157562306a36Sopenharmony_ci 157662306a36Sopenharmony_ci return safexcel_ahash_finup(areq); 157762306a36Sopenharmony_ci} 157862306a36Sopenharmony_ci 157962306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_sha384 = { 158062306a36Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 158162306a36Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA2_512, 158262306a36Sopenharmony_ci .alg.ahash = { 158362306a36Sopenharmony_ci .init = safexcel_sha384_init, 158462306a36Sopenharmony_ci .update = safexcel_ahash_update, 158562306a36Sopenharmony_ci .final = safexcel_ahash_final, 158662306a36Sopenharmony_ci .finup = safexcel_ahash_finup, 158762306a36Sopenharmony_ci .digest = safexcel_sha384_digest, 158862306a36Sopenharmony_ci .export = safexcel_ahash_export, 158962306a36Sopenharmony_ci .import = safexcel_ahash_import, 159062306a36Sopenharmony_ci .halg = { 159162306a36Sopenharmony_ci .digestsize = SHA384_DIGEST_SIZE, 159262306a36Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 159362306a36Sopenharmony_ci .base = { 159462306a36Sopenharmony_ci .cra_name = "sha384", 159562306a36Sopenharmony_ci .cra_driver_name = "safexcel-sha384", 159662306a36Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 159762306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 159862306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 159962306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 160062306a36Sopenharmony_ci .cra_blocksize = SHA384_BLOCK_SIZE, 160162306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 160262306a36Sopenharmony_ci .cra_init = safexcel_ahash_cra_init, 160362306a36Sopenharmony_ci .cra_exit = safexcel_ahash_cra_exit, 160462306a36Sopenharmony_ci .cra_module = THIS_MODULE, 160562306a36Sopenharmony_ci }, 160662306a36Sopenharmony_ci }, 160762306a36Sopenharmony_ci }, 160862306a36Sopenharmony_ci}; 160962306a36Sopenharmony_ci 161062306a36Sopenharmony_cistatic int safexcel_hmac_sha512_setkey(struct crypto_ahash *tfm, const u8 *key, 161162306a36Sopenharmony_ci unsigned int keylen) 161262306a36Sopenharmony_ci{ 161362306a36Sopenharmony_ci return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha512", 161462306a36Sopenharmony_ci SHA512_DIGEST_SIZE); 161562306a36Sopenharmony_ci} 161662306a36Sopenharmony_ci 161762306a36Sopenharmony_cistatic int safexcel_hmac_sha512_init(struct ahash_request *areq) 161862306a36Sopenharmony_ci{ 161962306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 162062306a36Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq); 162162306a36Sopenharmony_ci 162262306a36Sopenharmony_ci memset(req, 0, sizeof(*req)); 162362306a36Sopenharmony_ci 162462306a36Sopenharmony_ci /* Start from ipad precompute */ 162562306a36Sopenharmony_ci memcpy(req->state, &ctx->base.ipad, SHA512_DIGEST_SIZE); 162662306a36Sopenharmony_ci /* Already processed the key^ipad part now! */ 162762306a36Sopenharmony_ci req->len = SHA512_BLOCK_SIZE; 162862306a36Sopenharmony_ci req->processed = SHA512_BLOCK_SIZE; 162962306a36Sopenharmony_ci 163062306a36Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512; 163162306a36Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 163262306a36Sopenharmony_ci req->state_sz = SHA512_DIGEST_SIZE; 163362306a36Sopenharmony_ci req->digest_sz = SHA512_DIGEST_SIZE; 163462306a36Sopenharmony_ci req->block_sz = SHA512_BLOCK_SIZE; 163562306a36Sopenharmony_ci req->hmac = true; 163662306a36Sopenharmony_ci 163762306a36Sopenharmony_ci return 0; 163862306a36Sopenharmony_ci} 163962306a36Sopenharmony_ci 164062306a36Sopenharmony_cistatic int safexcel_hmac_sha512_digest(struct ahash_request *areq) 164162306a36Sopenharmony_ci{ 164262306a36Sopenharmony_ci int ret = safexcel_hmac_sha512_init(areq); 164362306a36Sopenharmony_ci 164462306a36Sopenharmony_ci if (ret) 164562306a36Sopenharmony_ci return ret; 164662306a36Sopenharmony_ci 164762306a36Sopenharmony_ci return safexcel_ahash_finup(areq); 164862306a36Sopenharmony_ci} 164962306a36Sopenharmony_ci 165062306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_hmac_sha512 = { 165162306a36Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 165262306a36Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA2_512, 165362306a36Sopenharmony_ci .alg.ahash = { 165462306a36Sopenharmony_ci .init = safexcel_hmac_sha512_init, 165562306a36Sopenharmony_ci .update = safexcel_ahash_update, 165662306a36Sopenharmony_ci .final = safexcel_ahash_final, 165762306a36Sopenharmony_ci .finup = safexcel_ahash_finup, 165862306a36Sopenharmony_ci .digest = safexcel_hmac_sha512_digest, 165962306a36Sopenharmony_ci .setkey = safexcel_hmac_sha512_setkey, 166062306a36Sopenharmony_ci .export = safexcel_ahash_export, 166162306a36Sopenharmony_ci .import = safexcel_ahash_import, 166262306a36Sopenharmony_ci .halg = { 166362306a36Sopenharmony_ci .digestsize = SHA512_DIGEST_SIZE, 166462306a36Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 166562306a36Sopenharmony_ci .base = { 166662306a36Sopenharmony_ci .cra_name = "hmac(sha512)", 166762306a36Sopenharmony_ci .cra_driver_name = "safexcel-hmac-sha512", 166862306a36Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 166962306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 167062306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 167162306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 167262306a36Sopenharmony_ci .cra_blocksize = SHA512_BLOCK_SIZE, 167362306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 167462306a36Sopenharmony_ci .cra_init = safexcel_ahash_cra_init, 167562306a36Sopenharmony_ci .cra_exit = safexcel_ahash_cra_exit, 167662306a36Sopenharmony_ci .cra_module = THIS_MODULE, 167762306a36Sopenharmony_ci }, 167862306a36Sopenharmony_ci }, 167962306a36Sopenharmony_ci }, 168062306a36Sopenharmony_ci}; 168162306a36Sopenharmony_ci 168262306a36Sopenharmony_cistatic int safexcel_hmac_sha384_setkey(struct crypto_ahash *tfm, const u8 *key, 168362306a36Sopenharmony_ci unsigned int keylen) 168462306a36Sopenharmony_ci{ 168562306a36Sopenharmony_ci return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha384", 168662306a36Sopenharmony_ci SHA512_DIGEST_SIZE); 168762306a36Sopenharmony_ci} 168862306a36Sopenharmony_ci 168962306a36Sopenharmony_cistatic int safexcel_hmac_sha384_init(struct ahash_request *areq) 169062306a36Sopenharmony_ci{ 169162306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 169262306a36Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq); 169362306a36Sopenharmony_ci 169462306a36Sopenharmony_ci memset(req, 0, sizeof(*req)); 169562306a36Sopenharmony_ci 169662306a36Sopenharmony_ci /* Start from ipad precompute */ 169762306a36Sopenharmony_ci memcpy(req->state, &ctx->base.ipad, SHA512_DIGEST_SIZE); 169862306a36Sopenharmony_ci /* Already processed the key^ipad part now! */ 169962306a36Sopenharmony_ci req->len = SHA512_BLOCK_SIZE; 170062306a36Sopenharmony_ci req->processed = SHA512_BLOCK_SIZE; 170162306a36Sopenharmony_ci 170262306a36Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384; 170362306a36Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 170462306a36Sopenharmony_ci req->state_sz = SHA512_DIGEST_SIZE; 170562306a36Sopenharmony_ci req->digest_sz = SHA512_DIGEST_SIZE; 170662306a36Sopenharmony_ci req->block_sz = SHA512_BLOCK_SIZE; 170762306a36Sopenharmony_ci req->hmac = true; 170862306a36Sopenharmony_ci 170962306a36Sopenharmony_ci return 0; 171062306a36Sopenharmony_ci} 171162306a36Sopenharmony_ci 171262306a36Sopenharmony_cistatic int safexcel_hmac_sha384_digest(struct ahash_request *areq) 171362306a36Sopenharmony_ci{ 171462306a36Sopenharmony_ci int ret = safexcel_hmac_sha384_init(areq); 171562306a36Sopenharmony_ci 171662306a36Sopenharmony_ci if (ret) 171762306a36Sopenharmony_ci return ret; 171862306a36Sopenharmony_ci 171962306a36Sopenharmony_ci return safexcel_ahash_finup(areq); 172062306a36Sopenharmony_ci} 172162306a36Sopenharmony_ci 172262306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_hmac_sha384 = { 172362306a36Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 172462306a36Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA2_512, 172562306a36Sopenharmony_ci .alg.ahash = { 172662306a36Sopenharmony_ci .init = safexcel_hmac_sha384_init, 172762306a36Sopenharmony_ci .update = safexcel_ahash_update, 172862306a36Sopenharmony_ci .final = safexcel_ahash_final, 172962306a36Sopenharmony_ci .finup = safexcel_ahash_finup, 173062306a36Sopenharmony_ci .digest = safexcel_hmac_sha384_digest, 173162306a36Sopenharmony_ci .setkey = safexcel_hmac_sha384_setkey, 173262306a36Sopenharmony_ci .export = safexcel_ahash_export, 173362306a36Sopenharmony_ci .import = safexcel_ahash_import, 173462306a36Sopenharmony_ci .halg = { 173562306a36Sopenharmony_ci .digestsize = SHA384_DIGEST_SIZE, 173662306a36Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 173762306a36Sopenharmony_ci .base = { 173862306a36Sopenharmony_ci .cra_name = "hmac(sha384)", 173962306a36Sopenharmony_ci .cra_driver_name = "safexcel-hmac-sha384", 174062306a36Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 174162306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 174262306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 174362306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 174462306a36Sopenharmony_ci .cra_blocksize = SHA384_BLOCK_SIZE, 174562306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 174662306a36Sopenharmony_ci .cra_init = safexcel_ahash_cra_init, 174762306a36Sopenharmony_ci .cra_exit = safexcel_ahash_cra_exit, 174862306a36Sopenharmony_ci .cra_module = THIS_MODULE, 174962306a36Sopenharmony_ci }, 175062306a36Sopenharmony_ci }, 175162306a36Sopenharmony_ci }, 175262306a36Sopenharmony_ci}; 175362306a36Sopenharmony_ci 175462306a36Sopenharmony_cistatic int safexcel_md5_init(struct ahash_request *areq) 175562306a36Sopenharmony_ci{ 175662306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 175762306a36Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq); 175862306a36Sopenharmony_ci 175962306a36Sopenharmony_ci memset(req, 0, sizeof(*req)); 176062306a36Sopenharmony_ci 176162306a36Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_MD5; 176262306a36Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 176362306a36Sopenharmony_ci req->state_sz = MD5_DIGEST_SIZE; 176462306a36Sopenharmony_ci req->digest_sz = MD5_DIGEST_SIZE; 176562306a36Sopenharmony_ci req->block_sz = MD5_HMAC_BLOCK_SIZE; 176662306a36Sopenharmony_ci 176762306a36Sopenharmony_ci return 0; 176862306a36Sopenharmony_ci} 176962306a36Sopenharmony_ci 177062306a36Sopenharmony_cistatic int safexcel_md5_digest(struct ahash_request *areq) 177162306a36Sopenharmony_ci{ 177262306a36Sopenharmony_ci int ret = safexcel_md5_init(areq); 177362306a36Sopenharmony_ci 177462306a36Sopenharmony_ci if (ret) 177562306a36Sopenharmony_ci return ret; 177662306a36Sopenharmony_ci 177762306a36Sopenharmony_ci return safexcel_ahash_finup(areq); 177862306a36Sopenharmony_ci} 177962306a36Sopenharmony_ci 178062306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_md5 = { 178162306a36Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 178262306a36Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_MD5, 178362306a36Sopenharmony_ci .alg.ahash = { 178462306a36Sopenharmony_ci .init = safexcel_md5_init, 178562306a36Sopenharmony_ci .update = safexcel_ahash_update, 178662306a36Sopenharmony_ci .final = safexcel_ahash_final, 178762306a36Sopenharmony_ci .finup = safexcel_ahash_finup, 178862306a36Sopenharmony_ci .digest = safexcel_md5_digest, 178962306a36Sopenharmony_ci .export = safexcel_ahash_export, 179062306a36Sopenharmony_ci .import = safexcel_ahash_import, 179162306a36Sopenharmony_ci .halg = { 179262306a36Sopenharmony_ci .digestsize = MD5_DIGEST_SIZE, 179362306a36Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 179462306a36Sopenharmony_ci .base = { 179562306a36Sopenharmony_ci .cra_name = "md5", 179662306a36Sopenharmony_ci .cra_driver_name = "safexcel-md5", 179762306a36Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 179862306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 179962306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 180062306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 180162306a36Sopenharmony_ci .cra_blocksize = MD5_HMAC_BLOCK_SIZE, 180262306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 180362306a36Sopenharmony_ci .cra_init = safexcel_ahash_cra_init, 180462306a36Sopenharmony_ci .cra_exit = safexcel_ahash_cra_exit, 180562306a36Sopenharmony_ci .cra_module = THIS_MODULE, 180662306a36Sopenharmony_ci }, 180762306a36Sopenharmony_ci }, 180862306a36Sopenharmony_ci }, 180962306a36Sopenharmony_ci}; 181062306a36Sopenharmony_ci 181162306a36Sopenharmony_cistatic int safexcel_hmac_md5_init(struct ahash_request *areq) 181262306a36Sopenharmony_ci{ 181362306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 181462306a36Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq); 181562306a36Sopenharmony_ci 181662306a36Sopenharmony_ci memset(req, 0, sizeof(*req)); 181762306a36Sopenharmony_ci 181862306a36Sopenharmony_ci /* Start from ipad precompute */ 181962306a36Sopenharmony_ci memcpy(req->state, &ctx->base.ipad, MD5_DIGEST_SIZE); 182062306a36Sopenharmony_ci /* Already processed the key^ipad part now! */ 182162306a36Sopenharmony_ci req->len = MD5_HMAC_BLOCK_SIZE; 182262306a36Sopenharmony_ci req->processed = MD5_HMAC_BLOCK_SIZE; 182362306a36Sopenharmony_ci 182462306a36Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_MD5; 182562306a36Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 182662306a36Sopenharmony_ci req->state_sz = MD5_DIGEST_SIZE; 182762306a36Sopenharmony_ci req->digest_sz = MD5_DIGEST_SIZE; 182862306a36Sopenharmony_ci req->block_sz = MD5_HMAC_BLOCK_SIZE; 182962306a36Sopenharmony_ci req->len_is_le = true; /* MD5 is little endian! ... */ 183062306a36Sopenharmony_ci req->hmac = true; 183162306a36Sopenharmony_ci 183262306a36Sopenharmony_ci return 0; 183362306a36Sopenharmony_ci} 183462306a36Sopenharmony_ci 183562306a36Sopenharmony_cistatic int safexcel_hmac_md5_setkey(struct crypto_ahash *tfm, const u8 *key, 183662306a36Sopenharmony_ci unsigned int keylen) 183762306a36Sopenharmony_ci{ 183862306a36Sopenharmony_ci return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-md5", 183962306a36Sopenharmony_ci MD5_DIGEST_SIZE); 184062306a36Sopenharmony_ci} 184162306a36Sopenharmony_ci 184262306a36Sopenharmony_cistatic int safexcel_hmac_md5_digest(struct ahash_request *areq) 184362306a36Sopenharmony_ci{ 184462306a36Sopenharmony_ci int ret = safexcel_hmac_md5_init(areq); 184562306a36Sopenharmony_ci 184662306a36Sopenharmony_ci if (ret) 184762306a36Sopenharmony_ci return ret; 184862306a36Sopenharmony_ci 184962306a36Sopenharmony_ci return safexcel_ahash_finup(areq); 185062306a36Sopenharmony_ci} 185162306a36Sopenharmony_ci 185262306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_hmac_md5 = { 185362306a36Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 185462306a36Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_MD5, 185562306a36Sopenharmony_ci .alg.ahash = { 185662306a36Sopenharmony_ci .init = safexcel_hmac_md5_init, 185762306a36Sopenharmony_ci .update = safexcel_ahash_update, 185862306a36Sopenharmony_ci .final = safexcel_ahash_final, 185962306a36Sopenharmony_ci .finup = safexcel_ahash_finup, 186062306a36Sopenharmony_ci .digest = safexcel_hmac_md5_digest, 186162306a36Sopenharmony_ci .setkey = safexcel_hmac_md5_setkey, 186262306a36Sopenharmony_ci .export = safexcel_ahash_export, 186362306a36Sopenharmony_ci .import = safexcel_ahash_import, 186462306a36Sopenharmony_ci .halg = { 186562306a36Sopenharmony_ci .digestsize = MD5_DIGEST_SIZE, 186662306a36Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 186762306a36Sopenharmony_ci .base = { 186862306a36Sopenharmony_ci .cra_name = "hmac(md5)", 186962306a36Sopenharmony_ci .cra_driver_name = "safexcel-hmac-md5", 187062306a36Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 187162306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 187262306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 187362306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 187462306a36Sopenharmony_ci .cra_blocksize = MD5_HMAC_BLOCK_SIZE, 187562306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 187662306a36Sopenharmony_ci .cra_init = safexcel_ahash_cra_init, 187762306a36Sopenharmony_ci .cra_exit = safexcel_ahash_cra_exit, 187862306a36Sopenharmony_ci .cra_module = THIS_MODULE, 187962306a36Sopenharmony_ci }, 188062306a36Sopenharmony_ci }, 188162306a36Sopenharmony_ci }, 188262306a36Sopenharmony_ci}; 188362306a36Sopenharmony_ci 188462306a36Sopenharmony_cistatic int safexcel_crc32_cra_init(struct crypto_tfm *tfm) 188562306a36Sopenharmony_ci{ 188662306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 188762306a36Sopenharmony_ci int ret = safexcel_ahash_cra_init(tfm); 188862306a36Sopenharmony_ci 188962306a36Sopenharmony_ci /* Default 'key' is all zeroes */ 189062306a36Sopenharmony_ci memset(&ctx->base.ipad, 0, sizeof(u32)); 189162306a36Sopenharmony_ci return ret; 189262306a36Sopenharmony_ci} 189362306a36Sopenharmony_ci 189462306a36Sopenharmony_cistatic int safexcel_crc32_init(struct ahash_request *areq) 189562306a36Sopenharmony_ci{ 189662306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 189762306a36Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq); 189862306a36Sopenharmony_ci 189962306a36Sopenharmony_ci memset(req, 0, sizeof(*req)); 190062306a36Sopenharmony_ci 190162306a36Sopenharmony_ci /* Start from loaded key */ 190262306a36Sopenharmony_ci req->state[0] = cpu_to_le32(~ctx->base.ipad.word[0]); 190362306a36Sopenharmony_ci /* Set processed to non-zero to enable invalidation detection */ 190462306a36Sopenharmony_ci req->len = sizeof(u32); 190562306a36Sopenharmony_ci req->processed = sizeof(u32); 190662306a36Sopenharmony_ci 190762306a36Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_CRC32; 190862306a36Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_XCM; 190962306a36Sopenharmony_ci req->state_sz = sizeof(u32); 191062306a36Sopenharmony_ci req->digest_sz = sizeof(u32); 191162306a36Sopenharmony_ci req->block_sz = sizeof(u32); 191262306a36Sopenharmony_ci 191362306a36Sopenharmony_ci return 0; 191462306a36Sopenharmony_ci} 191562306a36Sopenharmony_ci 191662306a36Sopenharmony_cistatic int safexcel_crc32_setkey(struct crypto_ahash *tfm, const u8 *key, 191762306a36Sopenharmony_ci unsigned int keylen) 191862306a36Sopenharmony_ci{ 191962306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 192062306a36Sopenharmony_ci 192162306a36Sopenharmony_ci if (keylen != sizeof(u32)) 192262306a36Sopenharmony_ci return -EINVAL; 192362306a36Sopenharmony_ci 192462306a36Sopenharmony_ci memcpy(&ctx->base.ipad, key, sizeof(u32)); 192562306a36Sopenharmony_ci return 0; 192662306a36Sopenharmony_ci} 192762306a36Sopenharmony_ci 192862306a36Sopenharmony_cistatic int safexcel_crc32_digest(struct ahash_request *areq) 192962306a36Sopenharmony_ci{ 193062306a36Sopenharmony_ci return safexcel_crc32_init(areq) ?: safexcel_ahash_finup(areq); 193162306a36Sopenharmony_ci} 193262306a36Sopenharmony_ci 193362306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_crc32 = { 193462306a36Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 193562306a36Sopenharmony_ci .algo_mask = 0, 193662306a36Sopenharmony_ci .alg.ahash = { 193762306a36Sopenharmony_ci .init = safexcel_crc32_init, 193862306a36Sopenharmony_ci .update = safexcel_ahash_update, 193962306a36Sopenharmony_ci .final = safexcel_ahash_final, 194062306a36Sopenharmony_ci .finup = safexcel_ahash_finup, 194162306a36Sopenharmony_ci .digest = safexcel_crc32_digest, 194262306a36Sopenharmony_ci .setkey = safexcel_crc32_setkey, 194362306a36Sopenharmony_ci .export = safexcel_ahash_export, 194462306a36Sopenharmony_ci .import = safexcel_ahash_import, 194562306a36Sopenharmony_ci .halg = { 194662306a36Sopenharmony_ci .digestsize = sizeof(u32), 194762306a36Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 194862306a36Sopenharmony_ci .base = { 194962306a36Sopenharmony_ci .cra_name = "crc32", 195062306a36Sopenharmony_ci .cra_driver_name = "safexcel-crc32", 195162306a36Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 195262306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_OPTIONAL_KEY | 195362306a36Sopenharmony_ci CRYPTO_ALG_ASYNC | 195462306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 195562306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 195662306a36Sopenharmony_ci .cra_blocksize = 1, 195762306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 195862306a36Sopenharmony_ci .cra_init = safexcel_crc32_cra_init, 195962306a36Sopenharmony_ci .cra_exit = safexcel_ahash_cra_exit, 196062306a36Sopenharmony_ci .cra_module = THIS_MODULE, 196162306a36Sopenharmony_ci }, 196262306a36Sopenharmony_ci }, 196362306a36Sopenharmony_ci }, 196462306a36Sopenharmony_ci}; 196562306a36Sopenharmony_ci 196662306a36Sopenharmony_cistatic int safexcel_cbcmac_init(struct ahash_request *areq) 196762306a36Sopenharmony_ci{ 196862306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 196962306a36Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq); 197062306a36Sopenharmony_ci 197162306a36Sopenharmony_ci memset(req, 0, sizeof(*req)); 197262306a36Sopenharmony_ci 197362306a36Sopenharmony_ci /* Start from loaded keys */ 197462306a36Sopenharmony_ci memcpy(req->state, &ctx->base.ipad, ctx->key_sz); 197562306a36Sopenharmony_ci /* Set processed to non-zero to enable invalidation detection */ 197662306a36Sopenharmony_ci req->len = AES_BLOCK_SIZE; 197762306a36Sopenharmony_ci req->processed = AES_BLOCK_SIZE; 197862306a36Sopenharmony_ci 197962306a36Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_XCM; 198062306a36Sopenharmony_ci req->state_sz = ctx->key_sz; 198162306a36Sopenharmony_ci req->digest_sz = AES_BLOCK_SIZE; 198262306a36Sopenharmony_ci req->block_sz = AES_BLOCK_SIZE; 198362306a36Sopenharmony_ci req->xcbcmac = true; 198462306a36Sopenharmony_ci 198562306a36Sopenharmony_ci return 0; 198662306a36Sopenharmony_ci} 198762306a36Sopenharmony_ci 198862306a36Sopenharmony_cistatic int safexcel_cbcmac_setkey(struct crypto_ahash *tfm, const u8 *key, 198962306a36Sopenharmony_ci unsigned int len) 199062306a36Sopenharmony_ci{ 199162306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 199262306a36Sopenharmony_ci struct crypto_aes_ctx aes; 199362306a36Sopenharmony_ci int ret, i; 199462306a36Sopenharmony_ci 199562306a36Sopenharmony_ci ret = aes_expandkey(&aes, key, len); 199662306a36Sopenharmony_ci if (ret) 199762306a36Sopenharmony_ci return ret; 199862306a36Sopenharmony_ci 199962306a36Sopenharmony_ci memset(&ctx->base.ipad, 0, 2 * AES_BLOCK_SIZE); 200062306a36Sopenharmony_ci for (i = 0; i < len / sizeof(u32); i++) 200162306a36Sopenharmony_ci ctx->base.ipad.be[i + 8] = cpu_to_be32(aes.key_enc[i]); 200262306a36Sopenharmony_ci 200362306a36Sopenharmony_ci if (len == AES_KEYSIZE_192) { 200462306a36Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC192; 200562306a36Sopenharmony_ci ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE; 200662306a36Sopenharmony_ci } else if (len == AES_KEYSIZE_256) { 200762306a36Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC256; 200862306a36Sopenharmony_ci ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE; 200962306a36Sopenharmony_ci } else { 201062306a36Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128; 201162306a36Sopenharmony_ci ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE; 201262306a36Sopenharmony_ci } 201362306a36Sopenharmony_ci ctx->cbcmac = true; 201462306a36Sopenharmony_ci 201562306a36Sopenharmony_ci memzero_explicit(&aes, sizeof(aes)); 201662306a36Sopenharmony_ci return 0; 201762306a36Sopenharmony_ci} 201862306a36Sopenharmony_ci 201962306a36Sopenharmony_cistatic int safexcel_cbcmac_digest(struct ahash_request *areq) 202062306a36Sopenharmony_ci{ 202162306a36Sopenharmony_ci return safexcel_cbcmac_init(areq) ?: safexcel_ahash_finup(areq); 202262306a36Sopenharmony_ci} 202362306a36Sopenharmony_ci 202462306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_cbcmac = { 202562306a36Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 202662306a36Sopenharmony_ci .algo_mask = 0, 202762306a36Sopenharmony_ci .alg.ahash = { 202862306a36Sopenharmony_ci .init = safexcel_cbcmac_init, 202962306a36Sopenharmony_ci .update = safexcel_ahash_update, 203062306a36Sopenharmony_ci .final = safexcel_ahash_final, 203162306a36Sopenharmony_ci .finup = safexcel_ahash_finup, 203262306a36Sopenharmony_ci .digest = safexcel_cbcmac_digest, 203362306a36Sopenharmony_ci .setkey = safexcel_cbcmac_setkey, 203462306a36Sopenharmony_ci .export = safexcel_ahash_export, 203562306a36Sopenharmony_ci .import = safexcel_ahash_import, 203662306a36Sopenharmony_ci .halg = { 203762306a36Sopenharmony_ci .digestsize = AES_BLOCK_SIZE, 203862306a36Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 203962306a36Sopenharmony_ci .base = { 204062306a36Sopenharmony_ci .cra_name = "cbcmac(aes)", 204162306a36Sopenharmony_ci .cra_driver_name = "safexcel-cbcmac-aes", 204262306a36Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 204362306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 204462306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 204562306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 204662306a36Sopenharmony_ci .cra_blocksize = 1, 204762306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 204862306a36Sopenharmony_ci .cra_init = safexcel_ahash_cra_init, 204962306a36Sopenharmony_ci .cra_exit = safexcel_ahash_cra_exit, 205062306a36Sopenharmony_ci .cra_module = THIS_MODULE, 205162306a36Sopenharmony_ci }, 205262306a36Sopenharmony_ci }, 205362306a36Sopenharmony_ci }, 205462306a36Sopenharmony_ci}; 205562306a36Sopenharmony_ci 205662306a36Sopenharmony_cistatic int safexcel_xcbcmac_setkey(struct crypto_ahash *tfm, const u8 *key, 205762306a36Sopenharmony_ci unsigned int len) 205862306a36Sopenharmony_ci{ 205962306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 206062306a36Sopenharmony_ci u32 key_tmp[3 * AES_BLOCK_SIZE / sizeof(u32)]; 206162306a36Sopenharmony_ci int ret, i; 206262306a36Sopenharmony_ci 206362306a36Sopenharmony_ci ret = aes_expandkey(ctx->aes, key, len); 206462306a36Sopenharmony_ci if (ret) 206562306a36Sopenharmony_ci return ret; 206662306a36Sopenharmony_ci 206762306a36Sopenharmony_ci /* precompute the XCBC key material */ 206862306a36Sopenharmony_ci aes_encrypt(ctx->aes, (u8 *)key_tmp + 2 * AES_BLOCK_SIZE, 206962306a36Sopenharmony_ci "\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1"); 207062306a36Sopenharmony_ci aes_encrypt(ctx->aes, (u8 *)key_tmp, 207162306a36Sopenharmony_ci "\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2"); 207262306a36Sopenharmony_ci aes_encrypt(ctx->aes, (u8 *)key_tmp + AES_BLOCK_SIZE, 207362306a36Sopenharmony_ci "\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3"); 207462306a36Sopenharmony_ci for (i = 0; i < 3 * AES_BLOCK_SIZE / sizeof(u32); i++) 207562306a36Sopenharmony_ci ctx->base.ipad.word[i] = swab32(key_tmp[i]); 207662306a36Sopenharmony_ci 207762306a36Sopenharmony_ci ret = aes_expandkey(ctx->aes, 207862306a36Sopenharmony_ci (u8 *)key_tmp + 2 * AES_BLOCK_SIZE, 207962306a36Sopenharmony_ci AES_MIN_KEY_SIZE); 208062306a36Sopenharmony_ci if (ret) 208162306a36Sopenharmony_ci return ret; 208262306a36Sopenharmony_ci 208362306a36Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128; 208462306a36Sopenharmony_ci ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE; 208562306a36Sopenharmony_ci ctx->cbcmac = false; 208662306a36Sopenharmony_ci 208762306a36Sopenharmony_ci return 0; 208862306a36Sopenharmony_ci} 208962306a36Sopenharmony_ci 209062306a36Sopenharmony_cistatic int safexcel_xcbcmac_cra_init(struct crypto_tfm *tfm) 209162306a36Sopenharmony_ci{ 209262306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 209362306a36Sopenharmony_ci 209462306a36Sopenharmony_ci safexcel_ahash_cra_init(tfm); 209562306a36Sopenharmony_ci ctx->aes = kmalloc(sizeof(*ctx->aes), GFP_KERNEL); 209662306a36Sopenharmony_ci return PTR_ERR_OR_ZERO(ctx->aes); 209762306a36Sopenharmony_ci} 209862306a36Sopenharmony_ci 209962306a36Sopenharmony_cistatic void safexcel_xcbcmac_cra_exit(struct crypto_tfm *tfm) 210062306a36Sopenharmony_ci{ 210162306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 210262306a36Sopenharmony_ci 210362306a36Sopenharmony_ci kfree(ctx->aes); 210462306a36Sopenharmony_ci safexcel_ahash_cra_exit(tfm); 210562306a36Sopenharmony_ci} 210662306a36Sopenharmony_ci 210762306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_xcbcmac = { 210862306a36Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 210962306a36Sopenharmony_ci .algo_mask = 0, 211062306a36Sopenharmony_ci .alg.ahash = { 211162306a36Sopenharmony_ci .init = safexcel_cbcmac_init, 211262306a36Sopenharmony_ci .update = safexcel_ahash_update, 211362306a36Sopenharmony_ci .final = safexcel_ahash_final, 211462306a36Sopenharmony_ci .finup = safexcel_ahash_finup, 211562306a36Sopenharmony_ci .digest = safexcel_cbcmac_digest, 211662306a36Sopenharmony_ci .setkey = safexcel_xcbcmac_setkey, 211762306a36Sopenharmony_ci .export = safexcel_ahash_export, 211862306a36Sopenharmony_ci .import = safexcel_ahash_import, 211962306a36Sopenharmony_ci .halg = { 212062306a36Sopenharmony_ci .digestsize = AES_BLOCK_SIZE, 212162306a36Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 212262306a36Sopenharmony_ci .base = { 212362306a36Sopenharmony_ci .cra_name = "xcbc(aes)", 212462306a36Sopenharmony_ci .cra_driver_name = "safexcel-xcbc-aes", 212562306a36Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 212662306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 212762306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 212862306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 212962306a36Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 213062306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 213162306a36Sopenharmony_ci .cra_init = safexcel_xcbcmac_cra_init, 213262306a36Sopenharmony_ci .cra_exit = safexcel_xcbcmac_cra_exit, 213362306a36Sopenharmony_ci .cra_module = THIS_MODULE, 213462306a36Sopenharmony_ci }, 213562306a36Sopenharmony_ci }, 213662306a36Sopenharmony_ci }, 213762306a36Sopenharmony_ci}; 213862306a36Sopenharmony_ci 213962306a36Sopenharmony_cistatic int safexcel_cmac_setkey(struct crypto_ahash *tfm, const u8 *key, 214062306a36Sopenharmony_ci unsigned int len) 214162306a36Sopenharmony_ci{ 214262306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 214362306a36Sopenharmony_ci __be64 consts[4]; 214462306a36Sopenharmony_ci u64 _const[2]; 214562306a36Sopenharmony_ci u8 msb_mask, gfmask; 214662306a36Sopenharmony_ci int ret, i; 214762306a36Sopenharmony_ci 214862306a36Sopenharmony_ci /* precompute the CMAC key material */ 214962306a36Sopenharmony_ci ret = aes_expandkey(ctx->aes, key, len); 215062306a36Sopenharmony_ci if (ret) 215162306a36Sopenharmony_ci return ret; 215262306a36Sopenharmony_ci 215362306a36Sopenharmony_ci for (i = 0; i < len / sizeof(u32); i++) 215462306a36Sopenharmony_ci ctx->base.ipad.word[i + 8] = swab32(ctx->aes->key_enc[i]); 215562306a36Sopenharmony_ci 215662306a36Sopenharmony_ci /* code below borrowed from crypto/cmac.c */ 215762306a36Sopenharmony_ci /* encrypt the zero block */ 215862306a36Sopenharmony_ci memset(consts, 0, AES_BLOCK_SIZE); 215962306a36Sopenharmony_ci aes_encrypt(ctx->aes, (u8 *)consts, (u8 *)consts); 216062306a36Sopenharmony_ci 216162306a36Sopenharmony_ci gfmask = 0x87; 216262306a36Sopenharmony_ci _const[0] = be64_to_cpu(consts[1]); 216362306a36Sopenharmony_ci _const[1] = be64_to_cpu(consts[0]); 216462306a36Sopenharmony_ci 216562306a36Sopenharmony_ci /* gf(2^128) multiply zero-ciphertext with u and u^2 */ 216662306a36Sopenharmony_ci for (i = 0; i < 4; i += 2) { 216762306a36Sopenharmony_ci msb_mask = ((s64)_const[1] >> 63) & gfmask; 216862306a36Sopenharmony_ci _const[1] = (_const[1] << 1) | (_const[0] >> 63); 216962306a36Sopenharmony_ci _const[0] = (_const[0] << 1) ^ msb_mask; 217062306a36Sopenharmony_ci 217162306a36Sopenharmony_ci consts[i + 0] = cpu_to_be64(_const[1]); 217262306a36Sopenharmony_ci consts[i + 1] = cpu_to_be64(_const[0]); 217362306a36Sopenharmony_ci } 217462306a36Sopenharmony_ci /* end of code borrowed from crypto/cmac.c */ 217562306a36Sopenharmony_ci 217662306a36Sopenharmony_ci for (i = 0; i < 2 * AES_BLOCK_SIZE / sizeof(u32); i++) 217762306a36Sopenharmony_ci ctx->base.ipad.be[i] = cpu_to_be32(((u32 *)consts)[i]); 217862306a36Sopenharmony_ci 217962306a36Sopenharmony_ci if (len == AES_KEYSIZE_192) { 218062306a36Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC192; 218162306a36Sopenharmony_ci ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE; 218262306a36Sopenharmony_ci } else if (len == AES_KEYSIZE_256) { 218362306a36Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC256; 218462306a36Sopenharmony_ci ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE; 218562306a36Sopenharmony_ci } else { 218662306a36Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128; 218762306a36Sopenharmony_ci ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE; 218862306a36Sopenharmony_ci } 218962306a36Sopenharmony_ci ctx->cbcmac = false; 219062306a36Sopenharmony_ci 219162306a36Sopenharmony_ci return 0; 219262306a36Sopenharmony_ci} 219362306a36Sopenharmony_ci 219462306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_cmac = { 219562306a36Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 219662306a36Sopenharmony_ci .algo_mask = 0, 219762306a36Sopenharmony_ci .alg.ahash = { 219862306a36Sopenharmony_ci .init = safexcel_cbcmac_init, 219962306a36Sopenharmony_ci .update = safexcel_ahash_update, 220062306a36Sopenharmony_ci .final = safexcel_ahash_final, 220162306a36Sopenharmony_ci .finup = safexcel_ahash_finup, 220262306a36Sopenharmony_ci .digest = safexcel_cbcmac_digest, 220362306a36Sopenharmony_ci .setkey = safexcel_cmac_setkey, 220462306a36Sopenharmony_ci .export = safexcel_ahash_export, 220562306a36Sopenharmony_ci .import = safexcel_ahash_import, 220662306a36Sopenharmony_ci .halg = { 220762306a36Sopenharmony_ci .digestsize = AES_BLOCK_SIZE, 220862306a36Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 220962306a36Sopenharmony_ci .base = { 221062306a36Sopenharmony_ci .cra_name = "cmac(aes)", 221162306a36Sopenharmony_ci .cra_driver_name = "safexcel-cmac-aes", 221262306a36Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 221362306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 221462306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 221562306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 221662306a36Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 221762306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 221862306a36Sopenharmony_ci .cra_init = safexcel_xcbcmac_cra_init, 221962306a36Sopenharmony_ci .cra_exit = safexcel_xcbcmac_cra_exit, 222062306a36Sopenharmony_ci .cra_module = THIS_MODULE, 222162306a36Sopenharmony_ci }, 222262306a36Sopenharmony_ci }, 222362306a36Sopenharmony_ci }, 222462306a36Sopenharmony_ci}; 222562306a36Sopenharmony_ci 222662306a36Sopenharmony_cistatic int safexcel_sm3_init(struct ahash_request *areq) 222762306a36Sopenharmony_ci{ 222862306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 222962306a36Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq); 223062306a36Sopenharmony_ci 223162306a36Sopenharmony_ci memset(req, 0, sizeof(*req)); 223262306a36Sopenharmony_ci 223362306a36Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SM3; 223462306a36Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 223562306a36Sopenharmony_ci req->state_sz = SM3_DIGEST_SIZE; 223662306a36Sopenharmony_ci req->digest_sz = SM3_DIGEST_SIZE; 223762306a36Sopenharmony_ci req->block_sz = SM3_BLOCK_SIZE; 223862306a36Sopenharmony_ci 223962306a36Sopenharmony_ci return 0; 224062306a36Sopenharmony_ci} 224162306a36Sopenharmony_ci 224262306a36Sopenharmony_cistatic int safexcel_sm3_digest(struct ahash_request *areq) 224362306a36Sopenharmony_ci{ 224462306a36Sopenharmony_ci int ret = safexcel_sm3_init(areq); 224562306a36Sopenharmony_ci 224662306a36Sopenharmony_ci if (ret) 224762306a36Sopenharmony_ci return ret; 224862306a36Sopenharmony_ci 224962306a36Sopenharmony_ci return safexcel_ahash_finup(areq); 225062306a36Sopenharmony_ci} 225162306a36Sopenharmony_ci 225262306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_sm3 = { 225362306a36Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 225462306a36Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SM3, 225562306a36Sopenharmony_ci .alg.ahash = { 225662306a36Sopenharmony_ci .init = safexcel_sm3_init, 225762306a36Sopenharmony_ci .update = safexcel_ahash_update, 225862306a36Sopenharmony_ci .final = safexcel_ahash_final, 225962306a36Sopenharmony_ci .finup = safexcel_ahash_finup, 226062306a36Sopenharmony_ci .digest = safexcel_sm3_digest, 226162306a36Sopenharmony_ci .export = safexcel_ahash_export, 226262306a36Sopenharmony_ci .import = safexcel_ahash_import, 226362306a36Sopenharmony_ci .halg = { 226462306a36Sopenharmony_ci .digestsize = SM3_DIGEST_SIZE, 226562306a36Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 226662306a36Sopenharmony_ci .base = { 226762306a36Sopenharmony_ci .cra_name = "sm3", 226862306a36Sopenharmony_ci .cra_driver_name = "safexcel-sm3", 226962306a36Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 227062306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 227162306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 227262306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 227362306a36Sopenharmony_ci .cra_blocksize = SM3_BLOCK_SIZE, 227462306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 227562306a36Sopenharmony_ci .cra_init = safexcel_ahash_cra_init, 227662306a36Sopenharmony_ci .cra_exit = safexcel_ahash_cra_exit, 227762306a36Sopenharmony_ci .cra_module = THIS_MODULE, 227862306a36Sopenharmony_ci }, 227962306a36Sopenharmony_ci }, 228062306a36Sopenharmony_ci }, 228162306a36Sopenharmony_ci}; 228262306a36Sopenharmony_ci 228362306a36Sopenharmony_cistatic int safexcel_hmac_sm3_setkey(struct crypto_ahash *tfm, const u8 *key, 228462306a36Sopenharmony_ci unsigned int keylen) 228562306a36Sopenharmony_ci{ 228662306a36Sopenharmony_ci return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sm3", 228762306a36Sopenharmony_ci SM3_DIGEST_SIZE); 228862306a36Sopenharmony_ci} 228962306a36Sopenharmony_ci 229062306a36Sopenharmony_cistatic int safexcel_hmac_sm3_init(struct ahash_request *areq) 229162306a36Sopenharmony_ci{ 229262306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 229362306a36Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq); 229462306a36Sopenharmony_ci 229562306a36Sopenharmony_ci memset(req, 0, sizeof(*req)); 229662306a36Sopenharmony_ci 229762306a36Sopenharmony_ci /* Start from ipad precompute */ 229862306a36Sopenharmony_ci memcpy(req->state, &ctx->base.ipad, SM3_DIGEST_SIZE); 229962306a36Sopenharmony_ci /* Already processed the key^ipad part now! */ 230062306a36Sopenharmony_ci req->len = SM3_BLOCK_SIZE; 230162306a36Sopenharmony_ci req->processed = SM3_BLOCK_SIZE; 230262306a36Sopenharmony_ci 230362306a36Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SM3; 230462306a36Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 230562306a36Sopenharmony_ci req->state_sz = SM3_DIGEST_SIZE; 230662306a36Sopenharmony_ci req->digest_sz = SM3_DIGEST_SIZE; 230762306a36Sopenharmony_ci req->block_sz = SM3_BLOCK_SIZE; 230862306a36Sopenharmony_ci req->hmac = true; 230962306a36Sopenharmony_ci 231062306a36Sopenharmony_ci return 0; 231162306a36Sopenharmony_ci} 231262306a36Sopenharmony_ci 231362306a36Sopenharmony_cistatic int safexcel_hmac_sm3_digest(struct ahash_request *areq) 231462306a36Sopenharmony_ci{ 231562306a36Sopenharmony_ci int ret = safexcel_hmac_sm3_init(areq); 231662306a36Sopenharmony_ci 231762306a36Sopenharmony_ci if (ret) 231862306a36Sopenharmony_ci return ret; 231962306a36Sopenharmony_ci 232062306a36Sopenharmony_ci return safexcel_ahash_finup(areq); 232162306a36Sopenharmony_ci} 232262306a36Sopenharmony_ci 232362306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_hmac_sm3 = { 232462306a36Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 232562306a36Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SM3, 232662306a36Sopenharmony_ci .alg.ahash = { 232762306a36Sopenharmony_ci .init = safexcel_hmac_sm3_init, 232862306a36Sopenharmony_ci .update = safexcel_ahash_update, 232962306a36Sopenharmony_ci .final = safexcel_ahash_final, 233062306a36Sopenharmony_ci .finup = safexcel_ahash_finup, 233162306a36Sopenharmony_ci .digest = safexcel_hmac_sm3_digest, 233262306a36Sopenharmony_ci .setkey = safexcel_hmac_sm3_setkey, 233362306a36Sopenharmony_ci .export = safexcel_ahash_export, 233462306a36Sopenharmony_ci .import = safexcel_ahash_import, 233562306a36Sopenharmony_ci .halg = { 233662306a36Sopenharmony_ci .digestsize = SM3_DIGEST_SIZE, 233762306a36Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 233862306a36Sopenharmony_ci .base = { 233962306a36Sopenharmony_ci .cra_name = "hmac(sm3)", 234062306a36Sopenharmony_ci .cra_driver_name = "safexcel-hmac-sm3", 234162306a36Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 234262306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 234362306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 234462306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 234562306a36Sopenharmony_ci .cra_blocksize = SM3_BLOCK_SIZE, 234662306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 234762306a36Sopenharmony_ci .cra_init = safexcel_ahash_cra_init, 234862306a36Sopenharmony_ci .cra_exit = safexcel_ahash_cra_exit, 234962306a36Sopenharmony_ci .cra_module = THIS_MODULE, 235062306a36Sopenharmony_ci }, 235162306a36Sopenharmony_ci }, 235262306a36Sopenharmony_ci }, 235362306a36Sopenharmony_ci}; 235462306a36Sopenharmony_ci 235562306a36Sopenharmony_cistatic int safexcel_sha3_224_init(struct ahash_request *areq) 235662306a36Sopenharmony_ci{ 235762306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 235862306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 235962306a36Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq); 236062306a36Sopenharmony_ci 236162306a36Sopenharmony_ci memset(req, 0, sizeof(*req)); 236262306a36Sopenharmony_ci 236362306a36Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_224; 236462306a36Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_INITIAL; 236562306a36Sopenharmony_ci req->state_sz = SHA3_224_DIGEST_SIZE; 236662306a36Sopenharmony_ci req->digest_sz = SHA3_224_DIGEST_SIZE; 236762306a36Sopenharmony_ci req->block_sz = SHA3_224_BLOCK_SIZE; 236862306a36Sopenharmony_ci ctx->do_fallback = false; 236962306a36Sopenharmony_ci ctx->fb_init_done = false; 237062306a36Sopenharmony_ci return 0; 237162306a36Sopenharmony_ci} 237262306a36Sopenharmony_ci 237362306a36Sopenharmony_cistatic int safexcel_sha3_fbcheck(struct ahash_request *req) 237462306a36Sopenharmony_ci{ 237562306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 237662306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 237762306a36Sopenharmony_ci struct ahash_request *subreq = ahash_request_ctx_dma(req); 237862306a36Sopenharmony_ci int ret = 0; 237962306a36Sopenharmony_ci 238062306a36Sopenharmony_ci if (ctx->do_fallback) { 238162306a36Sopenharmony_ci ahash_request_set_tfm(subreq, ctx->fback); 238262306a36Sopenharmony_ci ahash_request_set_callback(subreq, req->base.flags, 238362306a36Sopenharmony_ci req->base.complete, req->base.data); 238462306a36Sopenharmony_ci ahash_request_set_crypt(subreq, req->src, req->result, 238562306a36Sopenharmony_ci req->nbytes); 238662306a36Sopenharmony_ci if (!ctx->fb_init_done) { 238762306a36Sopenharmony_ci if (ctx->fb_do_setkey) { 238862306a36Sopenharmony_ci /* Set fallback cipher HMAC key */ 238962306a36Sopenharmony_ci u8 key[SHA3_224_BLOCK_SIZE]; 239062306a36Sopenharmony_ci 239162306a36Sopenharmony_ci memcpy(key, &ctx->base.ipad, 239262306a36Sopenharmony_ci crypto_ahash_blocksize(ctx->fback) / 2); 239362306a36Sopenharmony_ci memcpy(key + 239462306a36Sopenharmony_ci crypto_ahash_blocksize(ctx->fback) / 2, 239562306a36Sopenharmony_ci &ctx->base.opad, 239662306a36Sopenharmony_ci crypto_ahash_blocksize(ctx->fback) / 2); 239762306a36Sopenharmony_ci ret = crypto_ahash_setkey(ctx->fback, key, 239862306a36Sopenharmony_ci crypto_ahash_blocksize(ctx->fback)); 239962306a36Sopenharmony_ci memzero_explicit(key, 240062306a36Sopenharmony_ci crypto_ahash_blocksize(ctx->fback)); 240162306a36Sopenharmony_ci ctx->fb_do_setkey = false; 240262306a36Sopenharmony_ci } 240362306a36Sopenharmony_ci ret = ret ?: crypto_ahash_init(subreq); 240462306a36Sopenharmony_ci ctx->fb_init_done = true; 240562306a36Sopenharmony_ci } 240662306a36Sopenharmony_ci } 240762306a36Sopenharmony_ci return ret; 240862306a36Sopenharmony_ci} 240962306a36Sopenharmony_ci 241062306a36Sopenharmony_cistatic int safexcel_sha3_update(struct ahash_request *req) 241162306a36Sopenharmony_ci{ 241262306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 241362306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 241462306a36Sopenharmony_ci struct ahash_request *subreq = ahash_request_ctx_dma(req); 241562306a36Sopenharmony_ci 241662306a36Sopenharmony_ci ctx->do_fallback = true; 241762306a36Sopenharmony_ci return safexcel_sha3_fbcheck(req) ?: crypto_ahash_update(subreq); 241862306a36Sopenharmony_ci} 241962306a36Sopenharmony_ci 242062306a36Sopenharmony_cistatic int safexcel_sha3_final(struct ahash_request *req) 242162306a36Sopenharmony_ci{ 242262306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 242362306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 242462306a36Sopenharmony_ci struct ahash_request *subreq = ahash_request_ctx_dma(req); 242562306a36Sopenharmony_ci 242662306a36Sopenharmony_ci ctx->do_fallback = true; 242762306a36Sopenharmony_ci return safexcel_sha3_fbcheck(req) ?: crypto_ahash_final(subreq); 242862306a36Sopenharmony_ci} 242962306a36Sopenharmony_ci 243062306a36Sopenharmony_cistatic int safexcel_sha3_finup(struct ahash_request *req) 243162306a36Sopenharmony_ci{ 243262306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 243362306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 243462306a36Sopenharmony_ci struct ahash_request *subreq = ahash_request_ctx_dma(req); 243562306a36Sopenharmony_ci 243662306a36Sopenharmony_ci ctx->do_fallback |= !req->nbytes; 243762306a36Sopenharmony_ci if (ctx->do_fallback) 243862306a36Sopenharmony_ci /* Update or ex/import happened or len 0, cannot use the HW */ 243962306a36Sopenharmony_ci return safexcel_sha3_fbcheck(req) ?: 244062306a36Sopenharmony_ci crypto_ahash_finup(subreq); 244162306a36Sopenharmony_ci else 244262306a36Sopenharmony_ci return safexcel_ahash_finup(req); 244362306a36Sopenharmony_ci} 244462306a36Sopenharmony_ci 244562306a36Sopenharmony_cistatic int safexcel_sha3_digest_fallback(struct ahash_request *req) 244662306a36Sopenharmony_ci{ 244762306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 244862306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 244962306a36Sopenharmony_ci struct ahash_request *subreq = ahash_request_ctx_dma(req); 245062306a36Sopenharmony_ci 245162306a36Sopenharmony_ci ctx->do_fallback = true; 245262306a36Sopenharmony_ci ctx->fb_init_done = false; 245362306a36Sopenharmony_ci return safexcel_sha3_fbcheck(req) ?: crypto_ahash_finup(subreq); 245462306a36Sopenharmony_ci} 245562306a36Sopenharmony_ci 245662306a36Sopenharmony_cistatic int safexcel_sha3_224_digest(struct ahash_request *req) 245762306a36Sopenharmony_ci{ 245862306a36Sopenharmony_ci if (req->nbytes) 245962306a36Sopenharmony_ci return safexcel_sha3_224_init(req) ?: safexcel_ahash_finup(req); 246062306a36Sopenharmony_ci 246162306a36Sopenharmony_ci /* HW cannot do zero length hash, use fallback instead */ 246262306a36Sopenharmony_ci return safexcel_sha3_digest_fallback(req); 246362306a36Sopenharmony_ci} 246462306a36Sopenharmony_ci 246562306a36Sopenharmony_cistatic int safexcel_sha3_export(struct ahash_request *req, void *out) 246662306a36Sopenharmony_ci{ 246762306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 246862306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 246962306a36Sopenharmony_ci struct ahash_request *subreq = ahash_request_ctx_dma(req); 247062306a36Sopenharmony_ci 247162306a36Sopenharmony_ci ctx->do_fallback = true; 247262306a36Sopenharmony_ci return safexcel_sha3_fbcheck(req) ?: crypto_ahash_export(subreq, out); 247362306a36Sopenharmony_ci} 247462306a36Sopenharmony_ci 247562306a36Sopenharmony_cistatic int safexcel_sha3_import(struct ahash_request *req, const void *in) 247662306a36Sopenharmony_ci{ 247762306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 247862306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 247962306a36Sopenharmony_ci struct ahash_request *subreq = ahash_request_ctx_dma(req); 248062306a36Sopenharmony_ci 248162306a36Sopenharmony_ci ctx->do_fallback = true; 248262306a36Sopenharmony_ci return safexcel_sha3_fbcheck(req) ?: crypto_ahash_import(subreq, in); 248362306a36Sopenharmony_ci // return safexcel_ahash_import(req, in); 248462306a36Sopenharmony_ci} 248562306a36Sopenharmony_ci 248662306a36Sopenharmony_cistatic int safexcel_sha3_cra_init(struct crypto_tfm *tfm) 248762306a36Sopenharmony_ci{ 248862306a36Sopenharmony_ci struct crypto_ahash *ahash = __crypto_ahash_cast(tfm); 248962306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 249062306a36Sopenharmony_ci 249162306a36Sopenharmony_ci safexcel_ahash_cra_init(tfm); 249262306a36Sopenharmony_ci 249362306a36Sopenharmony_ci /* Allocate fallback implementation */ 249462306a36Sopenharmony_ci ctx->fback = crypto_alloc_ahash(crypto_tfm_alg_name(tfm), 0, 249562306a36Sopenharmony_ci CRYPTO_ALG_ASYNC | 249662306a36Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK); 249762306a36Sopenharmony_ci if (IS_ERR(ctx->fback)) 249862306a36Sopenharmony_ci return PTR_ERR(ctx->fback); 249962306a36Sopenharmony_ci 250062306a36Sopenharmony_ci /* Update statesize from fallback algorithm! */ 250162306a36Sopenharmony_ci crypto_hash_alg_common(ahash)->statesize = 250262306a36Sopenharmony_ci crypto_ahash_statesize(ctx->fback); 250362306a36Sopenharmony_ci crypto_ahash_set_reqsize_dma( 250462306a36Sopenharmony_ci ahash, max(sizeof(struct safexcel_ahash_req), 250562306a36Sopenharmony_ci sizeof(struct ahash_request) + 250662306a36Sopenharmony_ci crypto_ahash_reqsize(ctx->fback))); 250762306a36Sopenharmony_ci return 0; 250862306a36Sopenharmony_ci} 250962306a36Sopenharmony_ci 251062306a36Sopenharmony_cistatic void safexcel_sha3_cra_exit(struct crypto_tfm *tfm) 251162306a36Sopenharmony_ci{ 251262306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 251362306a36Sopenharmony_ci 251462306a36Sopenharmony_ci crypto_free_ahash(ctx->fback); 251562306a36Sopenharmony_ci safexcel_ahash_cra_exit(tfm); 251662306a36Sopenharmony_ci} 251762306a36Sopenharmony_ci 251862306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_sha3_224 = { 251962306a36Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 252062306a36Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA3, 252162306a36Sopenharmony_ci .alg.ahash = { 252262306a36Sopenharmony_ci .init = safexcel_sha3_224_init, 252362306a36Sopenharmony_ci .update = safexcel_sha3_update, 252462306a36Sopenharmony_ci .final = safexcel_sha3_final, 252562306a36Sopenharmony_ci .finup = safexcel_sha3_finup, 252662306a36Sopenharmony_ci .digest = safexcel_sha3_224_digest, 252762306a36Sopenharmony_ci .export = safexcel_sha3_export, 252862306a36Sopenharmony_ci .import = safexcel_sha3_import, 252962306a36Sopenharmony_ci .halg = { 253062306a36Sopenharmony_ci .digestsize = SHA3_224_DIGEST_SIZE, 253162306a36Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 253262306a36Sopenharmony_ci .base = { 253362306a36Sopenharmony_ci .cra_name = "sha3-224", 253462306a36Sopenharmony_ci .cra_driver_name = "safexcel-sha3-224", 253562306a36Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 253662306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 253762306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY | 253862306a36Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 253962306a36Sopenharmony_ci .cra_blocksize = SHA3_224_BLOCK_SIZE, 254062306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 254162306a36Sopenharmony_ci .cra_init = safexcel_sha3_cra_init, 254262306a36Sopenharmony_ci .cra_exit = safexcel_sha3_cra_exit, 254362306a36Sopenharmony_ci .cra_module = THIS_MODULE, 254462306a36Sopenharmony_ci }, 254562306a36Sopenharmony_ci }, 254662306a36Sopenharmony_ci }, 254762306a36Sopenharmony_ci}; 254862306a36Sopenharmony_ci 254962306a36Sopenharmony_cistatic int safexcel_sha3_256_init(struct ahash_request *areq) 255062306a36Sopenharmony_ci{ 255162306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 255262306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 255362306a36Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq); 255462306a36Sopenharmony_ci 255562306a36Sopenharmony_ci memset(req, 0, sizeof(*req)); 255662306a36Sopenharmony_ci 255762306a36Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_256; 255862306a36Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_INITIAL; 255962306a36Sopenharmony_ci req->state_sz = SHA3_256_DIGEST_SIZE; 256062306a36Sopenharmony_ci req->digest_sz = SHA3_256_DIGEST_SIZE; 256162306a36Sopenharmony_ci req->block_sz = SHA3_256_BLOCK_SIZE; 256262306a36Sopenharmony_ci ctx->do_fallback = false; 256362306a36Sopenharmony_ci ctx->fb_init_done = false; 256462306a36Sopenharmony_ci return 0; 256562306a36Sopenharmony_ci} 256662306a36Sopenharmony_ci 256762306a36Sopenharmony_cistatic int safexcel_sha3_256_digest(struct ahash_request *req) 256862306a36Sopenharmony_ci{ 256962306a36Sopenharmony_ci if (req->nbytes) 257062306a36Sopenharmony_ci return safexcel_sha3_256_init(req) ?: safexcel_ahash_finup(req); 257162306a36Sopenharmony_ci 257262306a36Sopenharmony_ci /* HW cannot do zero length hash, use fallback instead */ 257362306a36Sopenharmony_ci return safexcel_sha3_digest_fallback(req); 257462306a36Sopenharmony_ci} 257562306a36Sopenharmony_ci 257662306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_sha3_256 = { 257762306a36Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 257862306a36Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA3, 257962306a36Sopenharmony_ci .alg.ahash = { 258062306a36Sopenharmony_ci .init = safexcel_sha3_256_init, 258162306a36Sopenharmony_ci .update = safexcel_sha3_update, 258262306a36Sopenharmony_ci .final = safexcel_sha3_final, 258362306a36Sopenharmony_ci .finup = safexcel_sha3_finup, 258462306a36Sopenharmony_ci .digest = safexcel_sha3_256_digest, 258562306a36Sopenharmony_ci .export = safexcel_sha3_export, 258662306a36Sopenharmony_ci .import = safexcel_sha3_import, 258762306a36Sopenharmony_ci .halg = { 258862306a36Sopenharmony_ci .digestsize = SHA3_256_DIGEST_SIZE, 258962306a36Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 259062306a36Sopenharmony_ci .base = { 259162306a36Sopenharmony_ci .cra_name = "sha3-256", 259262306a36Sopenharmony_ci .cra_driver_name = "safexcel-sha3-256", 259362306a36Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 259462306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 259562306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY | 259662306a36Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 259762306a36Sopenharmony_ci .cra_blocksize = SHA3_256_BLOCK_SIZE, 259862306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 259962306a36Sopenharmony_ci .cra_init = safexcel_sha3_cra_init, 260062306a36Sopenharmony_ci .cra_exit = safexcel_sha3_cra_exit, 260162306a36Sopenharmony_ci .cra_module = THIS_MODULE, 260262306a36Sopenharmony_ci }, 260362306a36Sopenharmony_ci }, 260462306a36Sopenharmony_ci }, 260562306a36Sopenharmony_ci}; 260662306a36Sopenharmony_ci 260762306a36Sopenharmony_cistatic int safexcel_sha3_384_init(struct ahash_request *areq) 260862306a36Sopenharmony_ci{ 260962306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 261062306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 261162306a36Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq); 261262306a36Sopenharmony_ci 261362306a36Sopenharmony_ci memset(req, 0, sizeof(*req)); 261462306a36Sopenharmony_ci 261562306a36Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_384; 261662306a36Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_INITIAL; 261762306a36Sopenharmony_ci req->state_sz = SHA3_384_DIGEST_SIZE; 261862306a36Sopenharmony_ci req->digest_sz = SHA3_384_DIGEST_SIZE; 261962306a36Sopenharmony_ci req->block_sz = SHA3_384_BLOCK_SIZE; 262062306a36Sopenharmony_ci ctx->do_fallback = false; 262162306a36Sopenharmony_ci ctx->fb_init_done = false; 262262306a36Sopenharmony_ci return 0; 262362306a36Sopenharmony_ci} 262462306a36Sopenharmony_ci 262562306a36Sopenharmony_cistatic int safexcel_sha3_384_digest(struct ahash_request *req) 262662306a36Sopenharmony_ci{ 262762306a36Sopenharmony_ci if (req->nbytes) 262862306a36Sopenharmony_ci return safexcel_sha3_384_init(req) ?: safexcel_ahash_finup(req); 262962306a36Sopenharmony_ci 263062306a36Sopenharmony_ci /* HW cannot do zero length hash, use fallback instead */ 263162306a36Sopenharmony_ci return safexcel_sha3_digest_fallback(req); 263262306a36Sopenharmony_ci} 263362306a36Sopenharmony_ci 263462306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_sha3_384 = { 263562306a36Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 263662306a36Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA3, 263762306a36Sopenharmony_ci .alg.ahash = { 263862306a36Sopenharmony_ci .init = safexcel_sha3_384_init, 263962306a36Sopenharmony_ci .update = safexcel_sha3_update, 264062306a36Sopenharmony_ci .final = safexcel_sha3_final, 264162306a36Sopenharmony_ci .finup = safexcel_sha3_finup, 264262306a36Sopenharmony_ci .digest = safexcel_sha3_384_digest, 264362306a36Sopenharmony_ci .export = safexcel_sha3_export, 264462306a36Sopenharmony_ci .import = safexcel_sha3_import, 264562306a36Sopenharmony_ci .halg = { 264662306a36Sopenharmony_ci .digestsize = SHA3_384_DIGEST_SIZE, 264762306a36Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 264862306a36Sopenharmony_ci .base = { 264962306a36Sopenharmony_ci .cra_name = "sha3-384", 265062306a36Sopenharmony_ci .cra_driver_name = "safexcel-sha3-384", 265162306a36Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 265262306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 265362306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY | 265462306a36Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 265562306a36Sopenharmony_ci .cra_blocksize = SHA3_384_BLOCK_SIZE, 265662306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 265762306a36Sopenharmony_ci .cra_init = safexcel_sha3_cra_init, 265862306a36Sopenharmony_ci .cra_exit = safexcel_sha3_cra_exit, 265962306a36Sopenharmony_ci .cra_module = THIS_MODULE, 266062306a36Sopenharmony_ci }, 266162306a36Sopenharmony_ci }, 266262306a36Sopenharmony_ci }, 266362306a36Sopenharmony_ci}; 266462306a36Sopenharmony_ci 266562306a36Sopenharmony_cistatic int safexcel_sha3_512_init(struct ahash_request *areq) 266662306a36Sopenharmony_ci{ 266762306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 266862306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 266962306a36Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq); 267062306a36Sopenharmony_ci 267162306a36Sopenharmony_ci memset(req, 0, sizeof(*req)); 267262306a36Sopenharmony_ci 267362306a36Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_512; 267462306a36Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_INITIAL; 267562306a36Sopenharmony_ci req->state_sz = SHA3_512_DIGEST_SIZE; 267662306a36Sopenharmony_ci req->digest_sz = SHA3_512_DIGEST_SIZE; 267762306a36Sopenharmony_ci req->block_sz = SHA3_512_BLOCK_SIZE; 267862306a36Sopenharmony_ci ctx->do_fallback = false; 267962306a36Sopenharmony_ci ctx->fb_init_done = false; 268062306a36Sopenharmony_ci return 0; 268162306a36Sopenharmony_ci} 268262306a36Sopenharmony_ci 268362306a36Sopenharmony_cistatic int safexcel_sha3_512_digest(struct ahash_request *req) 268462306a36Sopenharmony_ci{ 268562306a36Sopenharmony_ci if (req->nbytes) 268662306a36Sopenharmony_ci return safexcel_sha3_512_init(req) ?: safexcel_ahash_finup(req); 268762306a36Sopenharmony_ci 268862306a36Sopenharmony_ci /* HW cannot do zero length hash, use fallback instead */ 268962306a36Sopenharmony_ci return safexcel_sha3_digest_fallback(req); 269062306a36Sopenharmony_ci} 269162306a36Sopenharmony_ci 269262306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_sha3_512 = { 269362306a36Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 269462306a36Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA3, 269562306a36Sopenharmony_ci .alg.ahash = { 269662306a36Sopenharmony_ci .init = safexcel_sha3_512_init, 269762306a36Sopenharmony_ci .update = safexcel_sha3_update, 269862306a36Sopenharmony_ci .final = safexcel_sha3_final, 269962306a36Sopenharmony_ci .finup = safexcel_sha3_finup, 270062306a36Sopenharmony_ci .digest = safexcel_sha3_512_digest, 270162306a36Sopenharmony_ci .export = safexcel_sha3_export, 270262306a36Sopenharmony_ci .import = safexcel_sha3_import, 270362306a36Sopenharmony_ci .halg = { 270462306a36Sopenharmony_ci .digestsize = SHA3_512_DIGEST_SIZE, 270562306a36Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 270662306a36Sopenharmony_ci .base = { 270762306a36Sopenharmony_ci .cra_name = "sha3-512", 270862306a36Sopenharmony_ci .cra_driver_name = "safexcel-sha3-512", 270962306a36Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 271062306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 271162306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY | 271262306a36Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 271362306a36Sopenharmony_ci .cra_blocksize = SHA3_512_BLOCK_SIZE, 271462306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 271562306a36Sopenharmony_ci .cra_init = safexcel_sha3_cra_init, 271662306a36Sopenharmony_ci .cra_exit = safexcel_sha3_cra_exit, 271762306a36Sopenharmony_ci .cra_module = THIS_MODULE, 271862306a36Sopenharmony_ci }, 271962306a36Sopenharmony_ci }, 272062306a36Sopenharmony_ci }, 272162306a36Sopenharmony_ci}; 272262306a36Sopenharmony_ci 272362306a36Sopenharmony_cistatic int safexcel_hmac_sha3_cra_init(struct crypto_tfm *tfm, const char *alg) 272462306a36Sopenharmony_ci{ 272562306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 272662306a36Sopenharmony_ci int ret; 272762306a36Sopenharmony_ci 272862306a36Sopenharmony_ci ret = safexcel_sha3_cra_init(tfm); 272962306a36Sopenharmony_ci if (ret) 273062306a36Sopenharmony_ci return ret; 273162306a36Sopenharmony_ci 273262306a36Sopenharmony_ci /* Allocate precalc basic digest implementation */ 273362306a36Sopenharmony_ci ctx->shpre = crypto_alloc_shash(alg, 0, CRYPTO_ALG_NEED_FALLBACK); 273462306a36Sopenharmony_ci if (IS_ERR(ctx->shpre)) 273562306a36Sopenharmony_ci return PTR_ERR(ctx->shpre); 273662306a36Sopenharmony_ci 273762306a36Sopenharmony_ci ctx->shdesc = kmalloc(sizeof(*ctx->shdesc) + 273862306a36Sopenharmony_ci crypto_shash_descsize(ctx->shpre), GFP_KERNEL); 273962306a36Sopenharmony_ci if (!ctx->shdesc) { 274062306a36Sopenharmony_ci crypto_free_shash(ctx->shpre); 274162306a36Sopenharmony_ci return -ENOMEM; 274262306a36Sopenharmony_ci } 274362306a36Sopenharmony_ci ctx->shdesc->tfm = ctx->shpre; 274462306a36Sopenharmony_ci return 0; 274562306a36Sopenharmony_ci} 274662306a36Sopenharmony_ci 274762306a36Sopenharmony_cistatic void safexcel_hmac_sha3_cra_exit(struct crypto_tfm *tfm) 274862306a36Sopenharmony_ci{ 274962306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 275062306a36Sopenharmony_ci 275162306a36Sopenharmony_ci crypto_free_ahash(ctx->fback); 275262306a36Sopenharmony_ci crypto_free_shash(ctx->shpre); 275362306a36Sopenharmony_ci kfree(ctx->shdesc); 275462306a36Sopenharmony_ci safexcel_ahash_cra_exit(tfm); 275562306a36Sopenharmony_ci} 275662306a36Sopenharmony_ci 275762306a36Sopenharmony_cistatic int safexcel_hmac_sha3_setkey(struct crypto_ahash *tfm, const u8 *key, 275862306a36Sopenharmony_ci unsigned int keylen) 275962306a36Sopenharmony_ci{ 276062306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 276162306a36Sopenharmony_ci int ret = 0; 276262306a36Sopenharmony_ci 276362306a36Sopenharmony_ci if (keylen > crypto_ahash_blocksize(tfm)) { 276462306a36Sopenharmony_ci /* 276562306a36Sopenharmony_ci * If the key is larger than the blocksize, then hash it 276662306a36Sopenharmony_ci * first using our fallback cipher 276762306a36Sopenharmony_ci */ 276862306a36Sopenharmony_ci ret = crypto_shash_digest(ctx->shdesc, key, keylen, 276962306a36Sopenharmony_ci ctx->base.ipad.byte); 277062306a36Sopenharmony_ci keylen = crypto_shash_digestsize(ctx->shpre); 277162306a36Sopenharmony_ci 277262306a36Sopenharmony_ci /* 277362306a36Sopenharmony_ci * If the digest is larger than half the blocksize, we need to 277462306a36Sopenharmony_ci * move the rest to opad due to the way our HMAC infra works. 277562306a36Sopenharmony_ci */ 277662306a36Sopenharmony_ci if (keylen > crypto_ahash_blocksize(tfm) / 2) 277762306a36Sopenharmony_ci /* Buffers overlap, need to use memmove iso memcpy! */ 277862306a36Sopenharmony_ci memmove(&ctx->base.opad, 277962306a36Sopenharmony_ci ctx->base.ipad.byte + 278062306a36Sopenharmony_ci crypto_ahash_blocksize(tfm) / 2, 278162306a36Sopenharmony_ci keylen - crypto_ahash_blocksize(tfm) / 2); 278262306a36Sopenharmony_ci } else { 278362306a36Sopenharmony_ci /* 278462306a36Sopenharmony_ci * Copy the key to our ipad & opad buffers 278562306a36Sopenharmony_ci * Note that ipad and opad each contain one half of the key, 278662306a36Sopenharmony_ci * to match the existing HMAC driver infrastructure. 278762306a36Sopenharmony_ci */ 278862306a36Sopenharmony_ci if (keylen <= crypto_ahash_blocksize(tfm) / 2) { 278962306a36Sopenharmony_ci memcpy(&ctx->base.ipad, key, keylen); 279062306a36Sopenharmony_ci } else { 279162306a36Sopenharmony_ci memcpy(&ctx->base.ipad, key, 279262306a36Sopenharmony_ci crypto_ahash_blocksize(tfm) / 2); 279362306a36Sopenharmony_ci memcpy(&ctx->base.opad, 279462306a36Sopenharmony_ci key + crypto_ahash_blocksize(tfm) / 2, 279562306a36Sopenharmony_ci keylen - crypto_ahash_blocksize(tfm) / 2); 279662306a36Sopenharmony_ci } 279762306a36Sopenharmony_ci } 279862306a36Sopenharmony_ci 279962306a36Sopenharmony_ci /* Pad key with zeroes */ 280062306a36Sopenharmony_ci if (keylen <= crypto_ahash_blocksize(tfm) / 2) { 280162306a36Sopenharmony_ci memset(ctx->base.ipad.byte + keylen, 0, 280262306a36Sopenharmony_ci crypto_ahash_blocksize(tfm) / 2 - keylen); 280362306a36Sopenharmony_ci memset(&ctx->base.opad, 0, crypto_ahash_blocksize(tfm) / 2); 280462306a36Sopenharmony_ci } else { 280562306a36Sopenharmony_ci memset(ctx->base.opad.byte + keylen - 280662306a36Sopenharmony_ci crypto_ahash_blocksize(tfm) / 2, 0, 280762306a36Sopenharmony_ci crypto_ahash_blocksize(tfm) - keylen); 280862306a36Sopenharmony_ci } 280962306a36Sopenharmony_ci 281062306a36Sopenharmony_ci /* If doing fallback, still need to set the new key! */ 281162306a36Sopenharmony_ci ctx->fb_do_setkey = true; 281262306a36Sopenharmony_ci return ret; 281362306a36Sopenharmony_ci} 281462306a36Sopenharmony_ci 281562306a36Sopenharmony_cistatic int safexcel_hmac_sha3_224_init(struct ahash_request *areq) 281662306a36Sopenharmony_ci{ 281762306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 281862306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 281962306a36Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq); 282062306a36Sopenharmony_ci 282162306a36Sopenharmony_ci memset(req, 0, sizeof(*req)); 282262306a36Sopenharmony_ci 282362306a36Sopenharmony_ci /* Copy (half of) the key */ 282462306a36Sopenharmony_ci memcpy(req->state, &ctx->base.ipad, SHA3_224_BLOCK_SIZE / 2); 282562306a36Sopenharmony_ci /* Start of HMAC should have len == processed == blocksize */ 282662306a36Sopenharmony_ci req->len = SHA3_224_BLOCK_SIZE; 282762306a36Sopenharmony_ci req->processed = SHA3_224_BLOCK_SIZE; 282862306a36Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_224; 282962306a36Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_HMAC; 283062306a36Sopenharmony_ci req->state_sz = SHA3_224_BLOCK_SIZE / 2; 283162306a36Sopenharmony_ci req->digest_sz = SHA3_224_DIGEST_SIZE; 283262306a36Sopenharmony_ci req->block_sz = SHA3_224_BLOCK_SIZE; 283362306a36Sopenharmony_ci req->hmac = true; 283462306a36Sopenharmony_ci ctx->do_fallback = false; 283562306a36Sopenharmony_ci ctx->fb_init_done = false; 283662306a36Sopenharmony_ci return 0; 283762306a36Sopenharmony_ci} 283862306a36Sopenharmony_ci 283962306a36Sopenharmony_cistatic int safexcel_hmac_sha3_224_digest(struct ahash_request *req) 284062306a36Sopenharmony_ci{ 284162306a36Sopenharmony_ci if (req->nbytes) 284262306a36Sopenharmony_ci return safexcel_hmac_sha3_224_init(req) ?: 284362306a36Sopenharmony_ci safexcel_ahash_finup(req); 284462306a36Sopenharmony_ci 284562306a36Sopenharmony_ci /* HW cannot do zero length HMAC, use fallback instead */ 284662306a36Sopenharmony_ci return safexcel_sha3_digest_fallback(req); 284762306a36Sopenharmony_ci} 284862306a36Sopenharmony_ci 284962306a36Sopenharmony_cistatic int safexcel_hmac_sha3_224_cra_init(struct crypto_tfm *tfm) 285062306a36Sopenharmony_ci{ 285162306a36Sopenharmony_ci return safexcel_hmac_sha3_cra_init(tfm, "sha3-224"); 285262306a36Sopenharmony_ci} 285362306a36Sopenharmony_ci 285462306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_hmac_sha3_224 = { 285562306a36Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 285662306a36Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA3, 285762306a36Sopenharmony_ci .alg.ahash = { 285862306a36Sopenharmony_ci .init = safexcel_hmac_sha3_224_init, 285962306a36Sopenharmony_ci .update = safexcel_sha3_update, 286062306a36Sopenharmony_ci .final = safexcel_sha3_final, 286162306a36Sopenharmony_ci .finup = safexcel_sha3_finup, 286262306a36Sopenharmony_ci .digest = safexcel_hmac_sha3_224_digest, 286362306a36Sopenharmony_ci .setkey = safexcel_hmac_sha3_setkey, 286462306a36Sopenharmony_ci .export = safexcel_sha3_export, 286562306a36Sopenharmony_ci .import = safexcel_sha3_import, 286662306a36Sopenharmony_ci .halg = { 286762306a36Sopenharmony_ci .digestsize = SHA3_224_DIGEST_SIZE, 286862306a36Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 286962306a36Sopenharmony_ci .base = { 287062306a36Sopenharmony_ci .cra_name = "hmac(sha3-224)", 287162306a36Sopenharmony_ci .cra_driver_name = "safexcel-hmac-sha3-224", 287262306a36Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 287362306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 287462306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY | 287562306a36Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 287662306a36Sopenharmony_ci .cra_blocksize = SHA3_224_BLOCK_SIZE, 287762306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 287862306a36Sopenharmony_ci .cra_init = safexcel_hmac_sha3_224_cra_init, 287962306a36Sopenharmony_ci .cra_exit = safexcel_hmac_sha3_cra_exit, 288062306a36Sopenharmony_ci .cra_module = THIS_MODULE, 288162306a36Sopenharmony_ci }, 288262306a36Sopenharmony_ci }, 288362306a36Sopenharmony_ci }, 288462306a36Sopenharmony_ci}; 288562306a36Sopenharmony_ci 288662306a36Sopenharmony_cistatic int safexcel_hmac_sha3_256_init(struct ahash_request *areq) 288762306a36Sopenharmony_ci{ 288862306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 288962306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 289062306a36Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq); 289162306a36Sopenharmony_ci 289262306a36Sopenharmony_ci memset(req, 0, sizeof(*req)); 289362306a36Sopenharmony_ci 289462306a36Sopenharmony_ci /* Copy (half of) the key */ 289562306a36Sopenharmony_ci memcpy(req->state, &ctx->base.ipad, SHA3_256_BLOCK_SIZE / 2); 289662306a36Sopenharmony_ci /* Start of HMAC should have len == processed == blocksize */ 289762306a36Sopenharmony_ci req->len = SHA3_256_BLOCK_SIZE; 289862306a36Sopenharmony_ci req->processed = SHA3_256_BLOCK_SIZE; 289962306a36Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_256; 290062306a36Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_HMAC; 290162306a36Sopenharmony_ci req->state_sz = SHA3_256_BLOCK_SIZE / 2; 290262306a36Sopenharmony_ci req->digest_sz = SHA3_256_DIGEST_SIZE; 290362306a36Sopenharmony_ci req->block_sz = SHA3_256_BLOCK_SIZE; 290462306a36Sopenharmony_ci req->hmac = true; 290562306a36Sopenharmony_ci ctx->do_fallback = false; 290662306a36Sopenharmony_ci ctx->fb_init_done = false; 290762306a36Sopenharmony_ci return 0; 290862306a36Sopenharmony_ci} 290962306a36Sopenharmony_ci 291062306a36Sopenharmony_cistatic int safexcel_hmac_sha3_256_digest(struct ahash_request *req) 291162306a36Sopenharmony_ci{ 291262306a36Sopenharmony_ci if (req->nbytes) 291362306a36Sopenharmony_ci return safexcel_hmac_sha3_256_init(req) ?: 291462306a36Sopenharmony_ci safexcel_ahash_finup(req); 291562306a36Sopenharmony_ci 291662306a36Sopenharmony_ci /* HW cannot do zero length HMAC, use fallback instead */ 291762306a36Sopenharmony_ci return safexcel_sha3_digest_fallback(req); 291862306a36Sopenharmony_ci} 291962306a36Sopenharmony_ci 292062306a36Sopenharmony_cistatic int safexcel_hmac_sha3_256_cra_init(struct crypto_tfm *tfm) 292162306a36Sopenharmony_ci{ 292262306a36Sopenharmony_ci return safexcel_hmac_sha3_cra_init(tfm, "sha3-256"); 292362306a36Sopenharmony_ci} 292462306a36Sopenharmony_ci 292562306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_hmac_sha3_256 = { 292662306a36Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 292762306a36Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA3, 292862306a36Sopenharmony_ci .alg.ahash = { 292962306a36Sopenharmony_ci .init = safexcel_hmac_sha3_256_init, 293062306a36Sopenharmony_ci .update = safexcel_sha3_update, 293162306a36Sopenharmony_ci .final = safexcel_sha3_final, 293262306a36Sopenharmony_ci .finup = safexcel_sha3_finup, 293362306a36Sopenharmony_ci .digest = safexcel_hmac_sha3_256_digest, 293462306a36Sopenharmony_ci .setkey = safexcel_hmac_sha3_setkey, 293562306a36Sopenharmony_ci .export = safexcel_sha3_export, 293662306a36Sopenharmony_ci .import = safexcel_sha3_import, 293762306a36Sopenharmony_ci .halg = { 293862306a36Sopenharmony_ci .digestsize = SHA3_256_DIGEST_SIZE, 293962306a36Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 294062306a36Sopenharmony_ci .base = { 294162306a36Sopenharmony_ci .cra_name = "hmac(sha3-256)", 294262306a36Sopenharmony_ci .cra_driver_name = "safexcel-hmac-sha3-256", 294362306a36Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 294462306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 294562306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY | 294662306a36Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 294762306a36Sopenharmony_ci .cra_blocksize = SHA3_256_BLOCK_SIZE, 294862306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 294962306a36Sopenharmony_ci .cra_init = safexcel_hmac_sha3_256_cra_init, 295062306a36Sopenharmony_ci .cra_exit = safexcel_hmac_sha3_cra_exit, 295162306a36Sopenharmony_ci .cra_module = THIS_MODULE, 295262306a36Sopenharmony_ci }, 295362306a36Sopenharmony_ci }, 295462306a36Sopenharmony_ci }, 295562306a36Sopenharmony_ci}; 295662306a36Sopenharmony_ci 295762306a36Sopenharmony_cistatic int safexcel_hmac_sha3_384_init(struct ahash_request *areq) 295862306a36Sopenharmony_ci{ 295962306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 296062306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 296162306a36Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq); 296262306a36Sopenharmony_ci 296362306a36Sopenharmony_ci memset(req, 0, sizeof(*req)); 296462306a36Sopenharmony_ci 296562306a36Sopenharmony_ci /* Copy (half of) the key */ 296662306a36Sopenharmony_ci memcpy(req->state, &ctx->base.ipad, SHA3_384_BLOCK_SIZE / 2); 296762306a36Sopenharmony_ci /* Start of HMAC should have len == processed == blocksize */ 296862306a36Sopenharmony_ci req->len = SHA3_384_BLOCK_SIZE; 296962306a36Sopenharmony_ci req->processed = SHA3_384_BLOCK_SIZE; 297062306a36Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_384; 297162306a36Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_HMAC; 297262306a36Sopenharmony_ci req->state_sz = SHA3_384_BLOCK_SIZE / 2; 297362306a36Sopenharmony_ci req->digest_sz = SHA3_384_DIGEST_SIZE; 297462306a36Sopenharmony_ci req->block_sz = SHA3_384_BLOCK_SIZE; 297562306a36Sopenharmony_ci req->hmac = true; 297662306a36Sopenharmony_ci ctx->do_fallback = false; 297762306a36Sopenharmony_ci ctx->fb_init_done = false; 297862306a36Sopenharmony_ci return 0; 297962306a36Sopenharmony_ci} 298062306a36Sopenharmony_ci 298162306a36Sopenharmony_cistatic int safexcel_hmac_sha3_384_digest(struct ahash_request *req) 298262306a36Sopenharmony_ci{ 298362306a36Sopenharmony_ci if (req->nbytes) 298462306a36Sopenharmony_ci return safexcel_hmac_sha3_384_init(req) ?: 298562306a36Sopenharmony_ci safexcel_ahash_finup(req); 298662306a36Sopenharmony_ci 298762306a36Sopenharmony_ci /* HW cannot do zero length HMAC, use fallback instead */ 298862306a36Sopenharmony_ci return safexcel_sha3_digest_fallback(req); 298962306a36Sopenharmony_ci} 299062306a36Sopenharmony_ci 299162306a36Sopenharmony_cistatic int safexcel_hmac_sha3_384_cra_init(struct crypto_tfm *tfm) 299262306a36Sopenharmony_ci{ 299362306a36Sopenharmony_ci return safexcel_hmac_sha3_cra_init(tfm, "sha3-384"); 299462306a36Sopenharmony_ci} 299562306a36Sopenharmony_ci 299662306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_hmac_sha3_384 = { 299762306a36Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 299862306a36Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA3, 299962306a36Sopenharmony_ci .alg.ahash = { 300062306a36Sopenharmony_ci .init = safexcel_hmac_sha3_384_init, 300162306a36Sopenharmony_ci .update = safexcel_sha3_update, 300262306a36Sopenharmony_ci .final = safexcel_sha3_final, 300362306a36Sopenharmony_ci .finup = safexcel_sha3_finup, 300462306a36Sopenharmony_ci .digest = safexcel_hmac_sha3_384_digest, 300562306a36Sopenharmony_ci .setkey = safexcel_hmac_sha3_setkey, 300662306a36Sopenharmony_ci .export = safexcel_sha3_export, 300762306a36Sopenharmony_ci .import = safexcel_sha3_import, 300862306a36Sopenharmony_ci .halg = { 300962306a36Sopenharmony_ci .digestsize = SHA3_384_DIGEST_SIZE, 301062306a36Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 301162306a36Sopenharmony_ci .base = { 301262306a36Sopenharmony_ci .cra_name = "hmac(sha3-384)", 301362306a36Sopenharmony_ci .cra_driver_name = "safexcel-hmac-sha3-384", 301462306a36Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 301562306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 301662306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY | 301762306a36Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 301862306a36Sopenharmony_ci .cra_blocksize = SHA3_384_BLOCK_SIZE, 301962306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 302062306a36Sopenharmony_ci .cra_init = safexcel_hmac_sha3_384_cra_init, 302162306a36Sopenharmony_ci .cra_exit = safexcel_hmac_sha3_cra_exit, 302262306a36Sopenharmony_ci .cra_module = THIS_MODULE, 302362306a36Sopenharmony_ci }, 302462306a36Sopenharmony_ci }, 302562306a36Sopenharmony_ci }, 302662306a36Sopenharmony_ci}; 302762306a36Sopenharmony_ci 302862306a36Sopenharmony_cistatic int safexcel_hmac_sha3_512_init(struct ahash_request *areq) 302962306a36Sopenharmony_ci{ 303062306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 303162306a36Sopenharmony_ci struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 303262306a36Sopenharmony_ci struct safexcel_ahash_req *req = ahash_request_ctx_dma(areq); 303362306a36Sopenharmony_ci 303462306a36Sopenharmony_ci memset(req, 0, sizeof(*req)); 303562306a36Sopenharmony_ci 303662306a36Sopenharmony_ci /* Copy (half of) the key */ 303762306a36Sopenharmony_ci memcpy(req->state, &ctx->base.ipad, SHA3_512_BLOCK_SIZE / 2); 303862306a36Sopenharmony_ci /* Start of HMAC should have len == processed == blocksize */ 303962306a36Sopenharmony_ci req->len = SHA3_512_BLOCK_SIZE; 304062306a36Sopenharmony_ci req->processed = SHA3_512_BLOCK_SIZE; 304162306a36Sopenharmony_ci ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_512; 304262306a36Sopenharmony_ci req->digest = CONTEXT_CONTROL_DIGEST_HMAC; 304362306a36Sopenharmony_ci req->state_sz = SHA3_512_BLOCK_SIZE / 2; 304462306a36Sopenharmony_ci req->digest_sz = SHA3_512_DIGEST_SIZE; 304562306a36Sopenharmony_ci req->block_sz = SHA3_512_BLOCK_SIZE; 304662306a36Sopenharmony_ci req->hmac = true; 304762306a36Sopenharmony_ci ctx->do_fallback = false; 304862306a36Sopenharmony_ci ctx->fb_init_done = false; 304962306a36Sopenharmony_ci return 0; 305062306a36Sopenharmony_ci} 305162306a36Sopenharmony_ci 305262306a36Sopenharmony_cistatic int safexcel_hmac_sha3_512_digest(struct ahash_request *req) 305362306a36Sopenharmony_ci{ 305462306a36Sopenharmony_ci if (req->nbytes) 305562306a36Sopenharmony_ci return safexcel_hmac_sha3_512_init(req) ?: 305662306a36Sopenharmony_ci safexcel_ahash_finup(req); 305762306a36Sopenharmony_ci 305862306a36Sopenharmony_ci /* HW cannot do zero length HMAC, use fallback instead */ 305962306a36Sopenharmony_ci return safexcel_sha3_digest_fallback(req); 306062306a36Sopenharmony_ci} 306162306a36Sopenharmony_ci 306262306a36Sopenharmony_cistatic int safexcel_hmac_sha3_512_cra_init(struct crypto_tfm *tfm) 306362306a36Sopenharmony_ci{ 306462306a36Sopenharmony_ci return safexcel_hmac_sha3_cra_init(tfm, "sha3-512"); 306562306a36Sopenharmony_ci} 306662306a36Sopenharmony_cistruct safexcel_alg_template safexcel_alg_hmac_sha3_512 = { 306762306a36Sopenharmony_ci .type = SAFEXCEL_ALG_TYPE_AHASH, 306862306a36Sopenharmony_ci .algo_mask = SAFEXCEL_ALG_SHA3, 306962306a36Sopenharmony_ci .alg.ahash = { 307062306a36Sopenharmony_ci .init = safexcel_hmac_sha3_512_init, 307162306a36Sopenharmony_ci .update = safexcel_sha3_update, 307262306a36Sopenharmony_ci .final = safexcel_sha3_final, 307362306a36Sopenharmony_ci .finup = safexcel_sha3_finup, 307462306a36Sopenharmony_ci .digest = safexcel_hmac_sha3_512_digest, 307562306a36Sopenharmony_ci .setkey = safexcel_hmac_sha3_setkey, 307662306a36Sopenharmony_ci .export = safexcel_sha3_export, 307762306a36Sopenharmony_ci .import = safexcel_sha3_import, 307862306a36Sopenharmony_ci .halg = { 307962306a36Sopenharmony_ci .digestsize = SHA3_512_DIGEST_SIZE, 308062306a36Sopenharmony_ci .statesize = sizeof(struct safexcel_ahash_export_state), 308162306a36Sopenharmony_ci .base = { 308262306a36Sopenharmony_ci .cra_name = "hmac(sha3-512)", 308362306a36Sopenharmony_ci .cra_driver_name = "safexcel-hmac-sha3-512", 308462306a36Sopenharmony_ci .cra_priority = SAFEXCEL_CRA_PRIORITY, 308562306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 308662306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY | 308762306a36Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 308862306a36Sopenharmony_ci .cra_blocksize = SHA3_512_BLOCK_SIZE, 308962306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 309062306a36Sopenharmony_ci .cra_init = safexcel_hmac_sha3_512_cra_init, 309162306a36Sopenharmony_ci .cra_exit = safexcel_hmac_sha3_cra_exit, 309262306a36Sopenharmony_ci .cra_module = THIS_MODULE, 309362306a36Sopenharmony_ci }, 309462306a36Sopenharmony_ci }, 309562306a36Sopenharmony_ci }, 309662306a36Sopenharmony_ci}; 3097