1301422e3SAntoine Tenart // SPDX-License-Identifier: GPL-2.0 21b44c5a6SAntoine Ténart /* 31b44c5a6SAntoine Ténart * Copyright (C) 2017 Marvell 41b44c5a6SAntoine Ténart * 51b44c5a6SAntoine Ténart * Antoine Tenart <antoine.tenart@free-electrons.com> 61b44c5a6SAntoine Ténart */ 71b44c5a6SAntoine Ténart 8aed3731eSAntoine Ténart #include <crypto/hmac.h> 9293f89cfSOfer Heifetz #include <crypto/md5.h> 101b44c5a6SAntoine Ténart #include <crypto/sha.h> 111b44c5a6SAntoine Ténart #include <linux/device.h> 121b44c5a6SAntoine Ténart #include <linux/dma-mapping.h> 131b44c5a6SAntoine Ténart #include <linux/dmapool.h> 141b44c5a6SAntoine Ténart 151b44c5a6SAntoine Ténart #include "safexcel.h" 161b44c5a6SAntoine Ténart 171b44c5a6SAntoine Ténart struct safexcel_ahash_ctx { 181b44c5a6SAntoine Ténart struct safexcel_context base; 191b44c5a6SAntoine Ténart struct safexcel_crypto_priv *priv; 201b44c5a6SAntoine Ténart 211b44c5a6SAntoine Ténart u32 alg; 221b44c5a6SAntoine Ténart 230de54fb1SAntoine Tenart u32 ipad[SHA512_DIGEST_SIZE / sizeof(u32)]; 240de54fb1SAntoine Tenart u32 opad[SHA512_DIGEST_SIZE / sizeof(u32)]; 251b44c5a6SAntoine Ténart }; 261b44c5a6SAntoine Ténart 271b44c5a6SAntoine Ténart struct safexcel_ahash_req { 281b44c5a6SAntoine Ténart bool last_req; 291b44c5a6SAntoine Ténart bool finish; 301b44c5a6SAntoine Ténart bool hmac; 311eb7b403SOfer Heifetz bool needs_inv; 3285b36ee8SPascal van Leeuwen bool hmac_zlen; 3385b36ee8SPascal van Leeuwen bool len_is_le; 341b44c5a6SAntoine Ténart 35c957f8b3SAntoine Ténart int nents; 36b8592027SOfer Heifetz dma_addr_t result_dma; 37c957f8b3SAntoine Ténart 38b869648cSAntoine Tenart u32 digest; 39b869648cSAntoine Tenart 4041abed7dSPascal van Leeuwen u8 state_sz; /* expected state size, only set once */ 4141abed7dSPascal van Leeuwen u8 block_sz; /* block size, only set once */ 42b460edb6SAntoine Tenart u32 state[SHA512_DIGEST_SIZE / sizeof(u32)] __aligned(sizeof(u32)); 431b44c5a6SAntoine Ténart 4431fb084cSPascal van Leeuwen u64 len; 4531fb084cSPascal van Leeuwen u64 processed; 461b44c5a6SAntoine Ténart 4741abed7dSPascal van Leeuwen u8 cache[HASH_CACHE_SIZE] __aligned(sizeof(u32)); 48cff9a175SAntoine Tenart dma_addr_t cache_dma; 49cff9a175SAntoine Tenart unsigned int cache_sz; 50cff9a175SAntoine Tenart 5141abed7dSPascal van Leeuwen u8 cache_next[HASH_CACHE_SIZE] __aligned(sizeof(u32)); 521b44c5a6SAntoine Ténart }; 531b44c5a6SAntoine Ténart 54b460edb6SAntoine Tenart static inline u64 safexcel_queued_len(struct safexcel_ahash_req *req) 55b460edb6SAntoine Tenart { 5631fb084cSPascal van Leeuwen return req->len - req->processed; 57b460edb6SAntoine Tenart } 58b460edb6SAntoine Tenart 591b44c5a6SAntoine Ténart static void safexcel_hash_token(struct safexcel_command_desc *cdesc, 601b44c5a6SAntoine Ténart u32 input_length, u32 result_length) 611b44c5a6SAntoine Ténart { 621b44c5a6SAntoine Ténart struct safexcel_token *token = 631b44c5a6SAntoine Ténart (struct safexcel_token *)cdesc->control_data.token; 641b44c5a6SAntoine Ténart 651b44c5a6SAntoine Ténart token[0].opcode = EIP197_TOKEN_OPCODE_DIRECTION; 661b44c5a6SAntoine Ténart token[0].packet_length = input_length; 671b44c5a6SAntoine Ténart token[0].stat = EIP197_TOKEN_STAT_LAST_HASH; 681b44c5a6SAntoine Ténart token[0].instructions = EIP197_TOKEN_INS_TYPE_HASH; 691b44c5a6SAntoine Ténart 701b44c5a6SAntoine Ténart token[1].opcode = EIP197_TOKEN_OPCODE_INSERT; 711b44c5a6SAntoine Ténart token[1].packet_length = result_length; 721b44c5a6SAntoine Ténart token[1].stat = EIP197_TOKEN_STAT_LAST_HASH | 731b44c5a6SAntoine Ténart EIP197_TOKEN_STAT_LAST_PACKET; 741b44c5a6SAntoine Ténart token[1].instructions = EIP197_TOKEN_INS_TYPE_OUTPUT | 751b44c5a6SAntoine Ténart EIP197_TOKEN_INS_INSERT_HASH_DIGEST; 761b44c5a6SAntoine Ténart } 771b44c5a6SAntoine Ténart 781b44c5a6SAntoine Ténart static void safexcel_context_control(struct safexcel_ahash_ctx *ctx, 791b44c5a6SAntoine Ténart struct safexcel_ahash_req *req, 8041abed7dSPascal van Leeuwen struct safexcel_command_desc *cdesc) 811b44c5a6SAntoine Ténart { 82b460edb6SAntoine Tenart struct safexcel_crypto_priv *priv = ctx->priv; 8341abed7dSPascal van Leeuwen u64 count = 0; 841b44c5a6SAntoine Ténart 851b44c5a6SAntoine Ténart cdesc->control_data.control0 |= ctx->alg; 86dc5268b6SPascal van Leeuwen 871b44c5a6SAntoine Ténart /* 881b44c5a6SAntoine Ténart * Copy the input digest if needed, and setup the context 891b44c5a6SAntoine Ténart * fields. Do this now as we need it to setup the first command 901b44c5a6SAntoine Ténart * descriptor. 911b44c5a6SAntoine Ténart */ 9231fb084cSPascal van Leeuwen if (!req->processed) { 9341abed7dSPascal van Leeuwen /* First - and possibly only - block of basic hash only */ 9441abed7dSPascal van Leeuwen if (req->finish) { 9541abed7dSPascal van Leeuwen cdesc->control_data.control0 |= 9641abed7dSPascal van Leeuwen CONTEXT_CONTROL_TYPE_HASH_OUT | 9741abed7dSPascal van Leeuwen CONTEXT_CONTROL_RESTART_HASH | 9841abed7dSPascal van Leeuwen /* ensure its not 0! */ 9941abed7dSPascal van Leeuwen CONTEXT_CONTROL_SIZE(1); 10041abed7dSPascal van Leeuwen } else { 10141abed7dSPascal van Leeuwen cdesc->control_data.control0 |= 10241abed7dSPascal van Leeuwen CONTEXT_CONTROL_TYPE_HASH_OUT | 10341abed7dSPascal van Leeuwen CONTEXT_CONTROL_RESTART_HASH | 10441abed7dSPascal van Leeuwen CONTEXT_CONTROL_NO_FINISH_HASH | 10541abed7dSPascal van Leeuwen /* ensure its not 0! */ 10641abed7dSPascal van Leeuwen CONTEXT_CONTROL_SIZE(1); 10741abed7dSPascal van Leeuwen } 10841abed7dSPascal van Leeuwen return; 10941abed7dSPascal van Leeuwen } 11041abed7dSPascal van Leeuwen 11141abed7dSPascal van Leeuwen /* Hash continuation or HMAC, setup (inner) digest from state */ 11241abed7dSPascal van Leeuwen memcpy(ctx->base.ctxr->data, req->state, req->state_sz); 1131b44c5a6SAntoine Ténart 114b460edb6SAntoine Tenart if (req->finish) { 11541abed7dSPascal van Leeuwen /* Compute digest count for hash/HMAC finish operations */ 11641abed7dSPascal van Leeuwen if ((req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) || 11731fb084cSPascal van Leeuwen req->hmac_zlen || (req->processed != req->block_sz)) { 11831fb084cSPascal van Leeuwen count = req->processed / EIP197_COUNTER_BLOCK_SIZE; 119b460edb6SAntoine Tenart 12041abed7dSPascal van Leeuwen /* This is a hardware limitation, as the 121b460edb6SAntoine Tenart * counter must fit into an u32. This represents 12241abed7dSPascal van Leeuwen * a fairly big amount of input data, so we 123b460edb6SAntoine Tenart * shouldn't see this. 124b460edb6SAntoine Tenart */ 12541abed7dSPascal van Leeuwen if (unlikely(count & 0xffffffff00000000ULL)) { 126b460edb6SAntoine Tenart dev_warn(priv->dev, 127b460edb6SAntoine Tenart "Input data is too big\n"); 128b460edb6SAntoine Tenart return; 129b460edb6SAntoine Tenart } 130b460edb6SAntoine Tenart } 1311b44c5a6SAntoine Ténart 13241abed7dSPascal van Leeuwen if ((req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) || 13385b36ee8SPascal van Leeuwen /* Special case: zero length HMAC */ 13485b36ee8SPascal van Leeuwen req->hmac_zlen || 13541abed7dSPascal van Leeuwen /* PE HW < 4.4 cannot do HMAC continue, fake using hash */ 13631fb084cSPascal van Leeuwen (req->processed != req->block_sz)) { 13741abed7dSPascal van Leeuwen /* Basic hash continue operation, need digest + cnt */ 13841abed7dSPascal van Leeuwen cdesc->control_data.control0 |= 13941abed7dSPascal van Leeuwen CONTEXT_CONTROL_SIZE((req->state_sz >> 2) + 1) | 14041abed7dSPascal van Leeuwen CONTEXT_CONTROL_TYPE_HASH_OUT | 14141abed7dSPascal van Leeuwen CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 14285b36ee8SPascal van Leeuwen /* For zero-len HMAC, don't finalize, already padded! */ 14385b36ee8SPascal van Leeuwen if (req->hmac_zlen) 14485b36ee8SPascal van Leeuwen cdesc->control_data.control0 |= 14585b36ee8SPascal van Leeuwen CONTEXT_CONTROL_NO_FINISH_HASH; 14641abed7dSPascal van Leeuwen cdesc->control_data.control1 |= 14741abed7dSPascal van Leeuwen CONTEXT_CONTROL_DIGEST_CNT; 14841abed7dSPascal van Leeuwen ctx->base.ctxr->data[req->state_sz >> 2] = 14941abed7dSPascal van Leeuwen cpu_to_le32(count); 15041abed7dSPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 15185b36ee8SPascal van Leeuwen 15285b36ee8SPascal van Leeuwen /* Clear zero-length HMAC flag for next operation! */ 15385b36ee8SPascal van Leeuwen req->hmac_zlen = false; 15441abed7dSPascal van Leeuwen } else { /* HMAC */ 15541abed7dSPascal van Leeuwen /* Need outer digest for HMAC finalization */ 15641abed7dSPascal van Leeuwen memcpy(ctx->base.ctxr->data + (req->state_sz >> 2), 1574505bb02SAntoine Tenart ctx->opad, req->state_sz); 15841abed7dSPascal van Leeuwen 15941abed7dSPascal van Leeuwen /* Single pass HMAC - no digest count */ 16041abed7dSPascal van Leeuwen cdesc->control_data.control0 |= 16141abed7dSPascal van Leeuwen CONTEXT_CONTROL_SIZE(req->state_sz >> 1) | 16241abed7dSPascal van Leeuwen CONTEXT_CONTROL_TYPE_HASH_OUT | 16341abed7dSPascal van Leeuwen CONTEXT_CONTROL_DIGEST_HMAC; 16441abed7dSPascal van Leeuwen } 16541abed7dSPascal van Leeuwen } else { /* Hash continuation, do not finish yet */ 16641abed7dSPascal van Leeuwen cdesc->control_data.control0 |= 16741abed7dSPascal van Leeuwen CONTEXT_CONTROL_SIZE(req->state_sz >> 2) | 16841abed7dSPascal van Leeuwen CONTEXT_CONTROL_DIGEST_PRECOMPUTED | 16941abed7dSPascal van Leeuwen CONTEXT_CONTROL_TYPE_HASH_OUT | 17041abed7dSPascal van Leeuwen CONTEXT_CONTROL_NO_FINISH_HASH; 1711b44c5a6SAntoine Ténart } 1721b44c5a6SAntoine Ténart } 1731b44c5a6SAntoine Ténart 17441abed7dSPascal van Leeuwen static int safexcel_ahash_enqueue(struct ahash_request *areq); 17541abed7dSPascal van Leeuwen 17641abed7dSPascal van Leeuwen static int safexcel_handle_req_result(struct safexcel_crypto_priv *priv, 17741abed7dSPascal van Leeuwen int ring, 1781b44c5a6SAntoine Ténart struct crypto_async_request *async, 1791b44c5a6SAntoine Ténart bool *should_complete, int *ret) 1801b44c5a6SAntoine Ténart { 1811b44c5a6SAntoine Ténart struct safexcel_result_desc *rdesc; 1821b44c5a6SAntoine Ténart struct ahash_request *areq = ahash_request_cast(async); 1831b44c5a6SAntoine Ténart struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); 1841b44c5a6SAntoine Ténart struct safexcel_ahash_req *sreq = ahash_request_ctx(areq); 18541abed7dSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(ahash); 186b460edb6SAntoine Tenart u64 cache_len; 1871b44c5a6SAntoine Ténart 1881b44c5a6SAntoine Ténart *ret = 0; 1891b44c5a6SAntoine Ténart 1901b44c5a6SAntoine Ténart rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr); 1911b44c5a6SAntoine Ténart if (IS_ERR(rdesc)) { 1921b44c5a6SAntoine Ténart dev_err(priv->dev, 1931b44c5a6SAntoine Ténart "hash: result: could not retrieve the result descriptor\n"); 1941b44c5a6SAntoine Ténart *ret = PTR_ERR(rdesc); 195bdfd1909SAntoine Tenart } else { 196bdfd1909SAntoine Tenart *ret = safexcel_rdesc_check_errors(priv, rdesc); 1971b44c5a6SAntoine Ténart } 1981b44c5a6SAntoine Ténart 1991b44c5a6SAntoine Ténart safexcel_complete(priv, ring); 2001b44c5a6SAntoine Ténart 201c957f8b3SAntoine Ténart if (sreq->nents) { 202c957f8b3SAntoine Ténart dma_unmap_sg(priv->dev, areq->src, sreq->nents, DMA_TO_DEVICE); 203c957f8b3SAntoine Ténart sreq->nents = 0; 204c957f8b3SAntoine Ténart } 2051b44c5a6SAntoine Ténart 206b8592027SOfer Heifetz if (sreq->result_dma) { 207b8592027SOfer Heifetz dma_unmap_single(priv->dev, sreq->result_dma, sreq->state_sz, 208b8592027SOfer Heifetz DMA_FROM_DEVICE); 209b8592027SOfer Heifetz sreq->result_dma = 0; 210b8592027SOfer Heifetz } 211b8592027SOfer Heifetz 212cff9a175SAntoine Tenart if (sreq->cache_dma) { 213cff9a175SAntoine Tenart dma_unmap_single(priv->dev, sreq->cache_dma, sreq->cache_sz, 214cff9a175SAntoine Tenart DMA_TO_DEVICE); 215cff9a175SAntoine Tenart sreq->cache_dma = 0; 216aa524286SAntoine Tenart sreq->cache_sz = 0; 217cff9a175SAntoine Tenart } 2181b44c5a6SAntoine Ténart 21941abed7dSPascal van Leeuwen if (sreq->finish) { 22041abed7dSPascal van Leeuwen if (sreq->hmac && 22141abed7dSPascal van Leeuwen (sreq->digest != CONTEXT_CONTROL_DIGEST_HMAC)) { 22241abed7dSPascal van Leeuwen /* Faking HMAC using hash - need to do outer hash */ 22341abed7dSPascal van Leeuwen memcpy(sreq->cache, sreq->state, 22441abed7dSPascal van Leeuwen crypto_ahash_digestsize(ahash)); 22541abed7dSPascal van Leeuwen 22641abed7dSPascal van Leeuwen memcpy(sreq->state, ctx->opad, sreq->state_sz); 22741abed7dSPascal van Leeuwen 22831fb084cSPascal van Leeuwen sreq->len = sreq->block_sz + 22941abed7dSPascal van Leeuwen crypto_ahash_digestsize(ahash); 23031fb084cSPascal van Leeuwen sreq->processed = sreq->block_sz; 23141abed7dSPascal van Leeuwen sreq->hmac = 0; 23241abed7dSPascal van Leeuwen 23341abed7dSPascal van Leeuwen ctx->base.needs_inv = true; 23441abed7dSPascal van Leeuwen areq->nbytes = 0; 23541abed7dSPascal van Leeuwen safexcel_ahash_enqueue(areq); 23641abed7dSPascal van Leeuwen 23741abed7dSPascal van Leeuwen *should_complete = false; /* Not done yet */ 23841abed7dSPascal van Leeuwen return 1; 23941abed7dSPascal van Leeuwen } 24041abed7dSPascal van Leeuwen 241b89a8159SAntoine Tenart memcpy(areq->result, sreq->state, 242b89a8159SAntoine Tenart crypto_ahash_digestsize(ahash)); 24341abed7dSPascal van Leeuwen } 244b89a8159SAntoine Tenart 245b460edb6SAntoine Tenart cache_len = safexcel_queued_len(sreq); 2461b44c5a6SAntoine Ténart if (cache_len) 2471b44c5a6SAntoine Ténart memcpy(sreq->cache, sreq->cache_next, cache_len); 2481b44c5a6SAntoine Ténart 2491b44c5a6SAntoine Ténart *should_complete = true; 2501b44c5a6SAntoine Ténart 2511b44c5a6SAntoine Ténart return 1; 2521b44c5a6SAntoine Ténart } 2531b44c5a6SAntoine Ténart 2541eb7b403SOfer Heifetz static int safexcel_ahash_send_req(struct crypto_async_request *async, int ring, 2551eb7b403SOfer Heifetz int *commands, int *results) 2561b44c5a6SAntoine Ténart { 2571b44c5a6SAntoine Ténart struct ahash_request *areq = ahash_request_cast(async); 2581b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 2591b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 2601b44c5a6SAntoine Ténart struct safexcel_crypto_priv *priv = ctx->priv; 2611b44c5a6SAntoine Ténart struct safexcel_command_desc *cdesc, *first_cdesc = NULL; 2621b44c5a6SAntoine Ténart struct safexcel_result_desc *rdesc; 2631b44c5a6SAntoine Ténart struct scatterlist *sg; 264082ec2d4SAntoine Tenart int i, extra = 0, n_cdesc = 0, ret = 0; 26541abed7dSPascal van Leeuwen u64 queued, len, cache_len; 2661b44c5a6SAntoine Ténart 267b460edb6SAntoine Tenart queued = len = safexcel_queued_len(req); 26841abed7dSPascal van Leeuwen if (queued <= HASH_CACHE_SIZE) 2691b44c5a6SAntoine Ténart cache_len = queued; 2701b44c5a6SAntoine Ténart else 2711b44c5a6SAntoine Ténart cache_len = queued - areq->nbytes; 2721b44c5a6SAntoine Ténart 27341abed7dSPascal van Leeuwen if (!req->finish && !req->last_req) { 274809778e0SAntoine Ténart /* If this is not the last request and the queued data does not 27541abed7dSPascal van Leeuwen * fit into full cache blocks, cache it for the next send call. 2761b44c5a6SAntoine Ténart */ 27741abed7dSPascal van Leeuwen extra = queued & (HASH_CACHE_SIZE - 1); 278082ec2d4SAntoine Tenart 279809778e0SAntoine Ténart /* If this is not the last request and the queued data 280809778e0SAntoine Ténart * is a multiple of a block, cache the last one for now. 281809778e0SAntoine Ténart */ 282dd4306a6SAntoine Tenart if (!extra) 28341abed7dSPascal van Leeuwen extra = HASH_CACHE_SIZE; 284809778e0SAntoine Ténart 2851b44c5a6SAntoine Ténart sg_pcopy_to_buffer(areq->src, sg_nents(areq->src), 286809778e0SAntoine Ténart req->cache_next, extra, 287809778e0SAntoine Ténart areq->nbytes - extra); 2881b44c5a6SAntoine Ténart 2891b44c5a6SAntoine Ténart queued -= extra; 2901b44c5a6SAntoine Ténart len -= extra; 291dc5268b6SPascal van Leeuwen 292dc5268b6SPascal van Leeuwen if (!queued) { 293dc5268b6SPascal van Leeuwen *commands = 0; 294dc5268b6SPascal van Leeuwen *results = 0; 295dc5268b6SPascal van Leeuwen return 0; 296dc5268b6SPascal van Leeuwen } 297809778e0SAntoine Ténart } 2981b44c5a6SAntoine Ténart 2991b44c5a6SAntoine Ténart /* Add a command descriptor for the cached data, if any */ 3001b44c5a6SAntoine Ténart if (cache_len) { 301cff9a175SAntoine Tenart req->cache_dma = dma_map_single(priv->dev, req->cache, 3021b44c5a6SAntoine Ténart cache_len, DMA_TO_DEVICE); 3039744fec9SOfer Heifetz if (dma_mapping_error(priv->dev, req->cache_dma)) 304cff9a175SAntoine Tenart return -EINVAL; 3051b44c5a6SAntoine Ténart 306cff9a175SAntoine Tenart req->cache_sz = cache_len; 3071b44c5a6SAntoine Ténart first_cdesc = safexcel_add_cdesc(priv, ring, 1, 3081b44c5a6SAntoine Ténart (cache_len == len), 309cff9a175SAntoine Tenart req->cache_dma, cache_len, len, 3101b44c5a6SAntoine Ténart ctx->base.ctxr_dma); 3111b44c5a6SAntoine Ténart if (IS_ERR(first_cdesc)) { 3121b44c5a6SAntoine Ténart ret = PTR_ERR(first_cdesc); 3131b44c5a6SAntoine Ténart goto unmap_cache; 3141b44c5a6SAntoine Ténart } 3151b44c5a6SAntoine Ténart n_cdesc++; 3161b44c5a6SAntoine Ténart 3171b44c5a6SAntoine Ténart queued -= cache_len; 3181b44c5a6SAntoine Ténart if (!queued) 3191b44c5a6SAntoine Ténart goto send_command; 3201b44c5a6SAntoine Ténart } 3211b44c5a6SAntoine Ténart 32241abed7dSPascal van Leeuwen /* Skip descriptor generation for zero-length requests */ 32341abed7dSPascal van Leeuwen if (!areq->nbytes) 32441abed7dSPascal van Leeuwen goto send_command; 32541abed7dSPascal van Leeuwen 3261b44c5a6SAntoine Ténart /* Now handle the current ahash request buffer(s) */ 32741abed7dSPascal van Leeuwen req->nents = dma_map_sg(priv->dev, areq->src, 32841abed7dSPascal van Leeuwen sg_nents_for_len(areq->src, 32941abed7dSPascal van Leeuwen areq->nbytes), 3301b44c5a6SAntoine Ténart DMA_TO_DEVICE); 331c957f8b3SAntoine Ténart if (!req->nents) { 3321b44c5a6SAntoine Ténart ret = -ENOMEM; 3331b44c5a6SAntoine Ténart goto cdesc_rollback; 3341b44c5a6SAntoine Ténart } 3351b44c5a6SAntoine Ténart 336c957f8b3SAntoine Ténart for_each_sg(areq->src, sg, req->nents, i) { 3371b44c5a6SAntoine Ténart int sglen = sg_dma_len(sg); 3381b44c5a6SAntoine Ténart 3391b44c5a6SAntoine Ténart /* Do not overflow the request */ 340b460edb6SAntoine Tenart if (queued < sglen) 3411b44c5a6SAntoine Ténart sglen = queued; 3421b44c5a6SAntoine Ténart 3431b44c5a6SAntoine Ténart cdesc = safexcel_add_cdesc(priv, ring, !n_cdesc, 34441abed7dSPascal van Leeuwen !(queued - sglen), 34541abed7dSPascal van Leeuwen sg_dma_address(sg), 3461b44c5a6SAntoine Ténart sglen, len, ctx->base.ctxr_dma); 3471b44c5a6SAntoine Ténart if (IS_ERR(cdesc)) { 3481b44c5a6SAntoine Ténart ret = PTR_ERR(cdesc); 34957433b58SAntoine Tenart goto unmap_sg; 3501b44c5a6SAntoine Ténart } 3511b44c5a6SAntoine Ténart n_cdesc++; 3521b44c5a6SAntoine Ténart 3531b44c5a6SAntoine Ténart if (n_cdesc == 1) 3541b44c5a6SAntoine Ténart first_cdesc = cdesc; 3551b44c5a6SAntoine Ténart 3561b44c5a6SAntoine Ténart queued -= sglen; 3571b44c5a6SAntoine Ténart if (!queued) 3581b44c5a6SAntoine Ténart break; 3591b44c5a6SAntoine Ténart } 3601b44c5a6SAntoine Ténart 3611b44c5a6SAntoine Ténart send_command: 3621b44c5a6SAntoine Ténart /* Setup the context options */ 36341abed7dSPascal van Leeuwen safexcel_context_control(ctx, req, first_cdesc); 3641b44c5a6SAntoine Ténart 3651b44c5a6SAntoine Ténart /* Add the token */ 3661b44c5a6SAntoine Ténart safexcel_hash_token(first_cdesc, len, req->state_sz); 3671b44c5a6SAntoine Ténart 368b8592027SOfer Heifetz req->result_dma = dma_map_single(priv->dev, req->state, req->state_sz, 369b8592027SOfer Heifetz DMA_FROM_DEVICE); 370b8592027SOfer Heifetz if (dma_mapping_error(priv->dev, req->result_dma)) { 3711b44c5a6SAntoine Ténart ret = -EINVAL; 37257433b58SAntoine Tenart goto unmap_sg; 3731b44c5a6SAntoine Ténart } 3741b44c5a6SAntoine Ténart 3751b44c5a6SAntoine Ténart /* Add a result descriptor */ 376b8592027SOfer Heifetz rdesc = safexcel_add_rdesc(priv, ring, 1, 1, req->result_dma, 3771b44c5a6SAntoine Ténart req->state_sz); 3781b44c5a6SAntoine Ténart if (IS_ERR(rdesc)) { 3791b44c5a6SAntoine Ténart ret = PTR_ERR(rdesc); 38057240a78SAntoine Tenart goto unmap_result; 3811b44c5a6SAntoine Ténart } 3821b44c5a6SAntoine Ténart 3839744fec9SOfer Heifetz safexcel_rdr_req_set(priv, ring, rdesc, &areq->base); 3841b44c5a6SAntoine Ténart 38531fb084cSPascal van Leeuwen req->processed += len; 386b460edb6SAntoine Tenart 3871b44c5a6SAntoine Ténart *commands = n_cdesc; 3881b44c5a6SAntoine Ténart *results = 1; 3891b44c5a6SAntoine Ténart return 0; 3901b44c5a6SAntoine Ténart 39157240a78SAntoine Tenart unmap_result: 39257433b58SAntoine Tenart dma_unmap_single(priv->dev, req->result_dma, req->state_sz, 39357433b58SAntoine Tenart DMA_FROM_DEVICE); 39457433b58SAntoine Tenart unmap_sg: 39557240a78SAntoine Tenart dma_unmap_sg(priv->dev, areq->src, req->nents, DMA_TO_DEVICE); 3961b44c5a6SAntoine Ténart cdesc_rollback: 3971b44c5a6SAntoine Ténart for (i = 0; i < n_cdesc; i++) 3981b44c5a6SAntoine Ténart safexcel_ring_rollback_wptr(priv, &priv->ring[ring].cdr); 3991b44c5a6SAntoine Ténart unmap_cache: 400cff9a175SAntoine Tenart if (req->cache_dma) { 401cff9a175SAntoine Tenart dma_unmap_single(priv->dev, req->cache_dma, req->cache_sz, 402cff9a175SAntoine Tenart DMA_TO_DEVICE); 403aa524286SAntoine Tenart req->cache_dma = 0; 404cff9a175SAntoine Tenart req->cache_sz = 0; 4051b44c5a6SAntoine Ténart } 4061b44c5a6SAntoine Ténart 4071b44c5a6SAntoine Ténart return ret; 4081b44c5a6SAntoine Ténart } 4091b44c5a6SAntoine Ténart 4101b44c5a6SAntoine Ténart static int safexcel_handle_inv_result(struct safexcel_crypto_priv *priv, 4111b44c5a6SAntoine Ténart int ring, 4121b44c5a6SAntoine Ténart struct crypto_async_request *async, 4131b44c5a6SAntoine Ténart bool *should_complete, int *ret) 4141b44c5a6SAntoine Ténart { 4151b44c5a6SAntoine Ténart struct safexcel_result_desc *rdesc; 4161b44c5a6SAntoine Ténart struct ahash_request *areq = ahash_request_cast(async); 4171b44c5a6SAntoine Ténart struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); 4181b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(ahash); 4191b44c5a6SAntoine Ténart int enq_ret; 4201b44c5a6SAntoine Ténart 4211b44c5a6SAntoine Ténart *ret = 0; 4221b44c5a6SAntoine Ténart 4231b44c5a6SAntoine Ténart rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr); 4241b44c5a6SAntoine Ténart if (IS_ERR(rdesc)) { 4251b44c5a6SAntoine Ténart dev_err(priv->dev, 4261b44c5a6SAntoine Ténart "hash: invalidate: could not retrieve the result descriptor\n"); 4271b44c5a6SAntoine Ténart *ret = PTR_ERR(rdesc); 428cda3e73aSAntoine Tenart } else { 429cda3e73aSAntoine Tenart *ret = safexcel_rdesc_check_errors(priv, rdesc); 4301b44c5a6SAntoine Ténart } 4311b44c5a6SAntoine Ténart 4321b44c5a6SAntoine Ténart safexcel_complete(priv, ring); 4331b44c5a6SAntoine Ténart 4341b44c5a6SAntoine Ténart if (ctx->base.exit_inv) { 4351b44c5a6SAntoine Ténart dma_pool_free(priv->context_pool, ctx->base.ctxr, 4361b44c5a6SAntoine Ténart ctx->base.ctxr_dma); 4371b44c5a6SAntoine Ténart 4381b44c5a6SAntoine Ténart *should_complete = true; 4391b44c5a6SAntoine Ténart return 1; 4401b44c5a6SAntoine Ténart } 4411b44c5a6SAntoine Ténart 44286671abbSAntoine Ténart ring = safexcel_select_ring(priv); 44386671abbSAntoine Ténart ctx->base.ring = ring; 4441b44c5a6SAntoine Ténart 44586671abbSAntoine Ténart spin_lock_bh(&priv->ring[ring].queue_lock); 44686671abbSAntoine Ténart enq_ret = crypto_enqueue_request(&priv->ring[ring].queue, async); 44786671abbSAntoine Ténart spin_unlock_bh(&priv->ring[ring].queue_lock); 4481b44c5a6SAntoine Ténart 4491b44c5a6SAntoine Ténart if (enq_ret != -EINPROGRESS) 4501b44c5a6SAntoine Ténart *ret = enq_ret; 4511b44c5a6SAntoine Ténart 4528472e778SAntoine Ténart queue_work(priv->ring[ring].workqueue, 4538472e778SAntoine Ténart &priv->ring[ring].work_data.work); 45486671abbSAntoine Ténart 4551b44c5a6SAntoine Ténart *should_complete = false; 4561b44c5a6SAntoine Ténart 4571b44c5a6SAntoine Ténart return 1; 4581b44c5a6SAntoine Ténart } 4591b44c5a6SAntoine Ténart 4601eb7b403SOfer Heifetz static int safexcel_handle_result(struct safexcel_crypto_priv *priv, int ring, 4611eb7b403SOfer Heifetz struct crypto_async_request *async, 4621eb7b403SOfer Heifetz bool *should_complete, int *ret) 4631eb7b403SOfer Heifetz { 4641eb7b403SOfer Heifetz struct ahash_request *areq = ahash_request_cast(async); 4651eb7b403SOfer Heifetz struct safexcel_ahash_req *req = ahash_request_ctx(areq); 4661eb7b403SOfer Heifetz int err; 4671eb7b403SOfer Heifetz 46853c83e91SAntoine Tenart BUG_ON(!(priv->flags & EIP197_TRC_CACHE) && req->needs_inv); 469871df319SAntoine Ténart 4701eb7b403SOfer Heifetz if (req->needs_inv) { 4711eb7b403SOfer Heifetz req->needs_inv = false; 4721eb7b403SOfer Heifetz err = safexcel_handle_inv_result(priv, ring, async, 4731eb7b403SOfer Heifetz should_complete, ret); 4741eb7b403SOfer Heifetz } else { 4751eb7b403SOfer Heifetz err = safexcel_handle_req_result(priv, ring, async, 4761eb7b403SOfer Heifetz should_complete, ret); 4771eb7b403SOfer Heifetz } 4781eb7b403SOfer Heifetz 4791eb7b403SOfer Heifetz return err; 4801eb7b403SOfer Heifetz } 4811eb7b403SOfer Heifetz 4821b44c5a6SAntoine Ténart static int safexcel_ahash_send_inv(struct crypto_async_request *async, 4839744fec9SOfer Heifetz int ring, int *commands, int *results) 4841b44c5a6SAntoine Ténart { 4851b44c5a6SAntoine Ténart struct ahash_request *areq = ahash_request_cast(async); 4861b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 4871b44c5a6SAntoine Ténart int ret; 4881b44c5a6SAntoine Ténart 4895290ad6eSOfer Heifetz ret = safexcel_invalidate_cache(async, ctx->priv, 4909744fec9SOfer Heifetz ctx->base.ctxr_dma, ring); 4911b44c5a6SAntoine Ténart if (unlikely(ret)) 4921b44c5a6SAntoine Ténart return ret; 4931b44c5a6SAntoine Ténart 4941b44c5a6SAntoine Ténart *commands = 1; 4951b44c5a6SAntoine Ténart *results = 1; 4961b44c5a6SAntoine Ténart 4971b44c5a6SAntoine Ténart return 0; 4981b44c5a6SAntoine Ténart } 4991b44c5a6SAntoine Ténart 5001eb7b403SOfer Heifetz static int safexcel_ahash_send(struct crypto_async_request *async, 5019744fec9SOfer Heifetz int ring, int *commands, int *results) 5021eb7b403SOfer Heifetz { 5031eb7b403SOfer Heifetz struct ahash_request *areq = ahash_request_cast(async); 5041eb7b403SOfer Heifetz struct safexcel_ahash_req *req = ahash_request_ctx(areq); 5051eb7b403SOfer Heifetz int ret; 5061eb7b403SOfer Heifetz 5071eb7b403SOfer Heifetz if (req->needs_inv) 5089744fec9SOfer Heifetz ret = safexcel_ahash_send_inv(async, ring, commands, results); 5091eb7b403SOfer Heifetz else 5109744fec9SOfer Heifetz ret = safexcel_ahash_send_req(async, ring, commands, results); 5119744fec9SOfer Heifetz 5121eb7b403SOfer Heifetz return ret; 5131eb7b403SOfer Heifetz } 5141eb7b403SOfer Heifetz 5151b44c5a6SAntoine Ténart static int safexcel_ahash_exit_inv(struct crypto_tfm *tfm) 5161b44c5a6SAntoine Ténart { 5171b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 5181b44c5a6SAntoine Ténart struct safexcel_crypto_priv *priv = ctx->priv; 51961824806SAntoine Tenart EIP197_REQUEST_ON_STACK(req, ahash, EIP197_AHASH_REQ_SIZE); 5207cad2fabSAntoine Ténart struct safexcel_ahash_req *rctx = ahash_request_ctx(req); 5213e1166b9SArnd Bergmann struct safexcel_inv_result result = {}; 52286671abbSAntoine Ténart int ring = ctx->base.ring; 5231b44c5a6SAntoine Ténart 524b926213dSAntoine Tenart memset(req, 0, EIP197_AHASH_REQ_SIZE); 5251b44c5a6SAntoine Ténart 5261b44c5a6SAntoine Ténart /* create invalidation request */ 5271b44c5a6SAntoine Ténart init_completion(&result.completion); 5287cad2fabSAntoine Ténart ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, 5291b44c5a6SAntoine Ténart safexcel_inv_complete, &result); 5301b44c5a6SAntoine Ténart 5317cad2fabSAntoine Ténart ahash_request_set_tfm(req, __crypto_ahash_cast(tfm)); 5327cad2fabSAntoine Ténart ctx = crypto_tfm_ctx(req->base.tfm); 5331b44c5a6SAntoine Ténart ctx->base.exit_inv = true; 5341eb7b403SOfer Heifetz rctx->needs_inv = true; 5351b44c5a6SAntoine Ténart 53686671abbSAntoine Ténart spin_lock_bh(&priv->ring[ring].queue_lock); 5377cad2fabSAntoine Ténart crypto_enqueue_request(&priv->ring[ring].queue, &req->base); 53886671abbSAntoine Ténart spin_unlock_bh(&priv->ring[ring].queue_lock); 5391b44c5a6SAntoine Ténart 5408472e778SAntoine Ténart queue_work(priv->ring[ring].workqueue, 5418472e778SAntoine Ténart &priv->ring[ring].work_data.work); 5421b44c5a6SAntoine Ténart 543b7007dbcSAntoine Tenart wait_for_completion(&result.completion); 5441b44c5a6SAntoine Ténart 5451b44c5a6SAntoine Ténart if (result.error) { 5461b44c5a6SAntoine Ténart dev_warn(priv->dev, "hash: completion error (%d)\n", 5471b44c5a6SAntoine Ténart result.error); 5481b44c5a6SAntoine Ténart return result.error; 5491b44c5a6SAntoine Ténart } 5501b44c5a6SAntoine Ténart 5511b44c5a6SAntoine Ténart return 0; 5521b44c5a6SAntoine Ténart } 5531b44c5a6SAntoine Ténart 554cc75f5ceSAntoine Ténart /* safexcel_ahash_cache: cache data until at least one request can be sent to 555cc75f5ceSAntoine Ténart * the engine, aka. when there is at least 1 block size in the pipe. 556cc75f5ceSAntoine Ténart */ 55741abed7dSPascal van Leeuwen static int safexcel_ahash_cache(struct ahash_request *areq) 5581b44c5a6SAntoine Ténart { 5591b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 56041abed7dSPascal van Leeuwen u64 cache_len; 5611b44c5a6SAntoine Ténart 562b460edb6SAntoine Tenart /* cache_len: everything accepted by the driver but not sent yet, 563b460edb6SAntoine Tenart * tot sz handled by update() - last req sz - tot sz handled by send() 564b460edb6SAntoine Tenart */ 56541abed7dSPascal van Leeuwen cache_len = safexcel_queued_len(req); 5661b44c5a6SAntoine Ténart 5671b44c5a6SAntoine Ténart /* 5681b44c5a6SAntoine Ténart * In case there isn't enough bytes to proceed (less than a 5691b44c5a6SAntoine Ténart * block size), cache the data until we have enough. 5701b44c5a6SAntoine Ténart */ 57141abed7dSPascal van Leeuwen if (cache_len + areq->nbytes <= HASH_CACHE_SIZE) { 5721b44c5a6SAntoine Ténart sg_pcopy_to_buffer(areq->src, sg_nents(areq->src), 5731b44c5a6SAntoine Ténart req->cache + cache_len, 5741b44c5a6SAntoine Ténart areq->nbytes, 0); 57541abed7dSPascal van Leeuwen return 0; 5761b44c5a6SAntoine Ténart } 5771b44c5a6SAntoine Ténart 578dfbcc08fSAntoine Ténart /* We couldn't cache all the data */ 5791b44c5a6SAntoine Ténart return -E2BIG; 5801b44c5a6SAntoine Ténart } 5811b44c5a6SAntoine Ténart 5821b44c5a6SAntoine Ténart static int safexcel_ahash_enqueue(struct ahash_request *areq) 5831b44c5a6SAntoine Ténart { 5841b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 5851b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 5861b44c5a6SAntoine Ténart struct safexcel_crypto_priv *priv = ctx->priv; 58786671abbSAntoine Ténart int ret, ring; 5881b44c5a6SAntoine Ténart 5891eb7b403SOfer Heifetz req->needs_inv = false; 5901b44c5a6SAntoine Ténart 591c4daf4ccSOfer Heifetz if (ctx->base.ctxr) { 59253c83e91SAntoine Tenart if (priv->flags & EIP197_TRC_CACHE && !ctx->base.needs_inv && 59331fb084cSPascal van Leeuwen req->processed && 59441abed7dSPascal van Leeuwen (/* invalidate for basic hash continuation finish */ 59541abed7dSPascal van Leeuwen (req->finish && 59641abed7dSPascal van Leeuwen (req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED)) || 59741abed7dSPascal van Leeuwen /* invalidate if (i)digest changed */ 59841abed7dSPascal van Leeuwen memcmp(ctx->base.ctxr->data, req->state, req->state_sz) || 59941abed7dSPascal van Leeuwen /* invalidate for HMAC continuation finish */ 60031fb084cSPascal van Leeuwen (req->finish && (req->processed != req->block_sz)) || 60141abed7dSPascal van Leeuwen /* invalidate for HMAC finish with odigest changed */ 60241abed7dSPascal van Leeuwen (req->finish && 60341abed7dSPascal van Leeuwen memcmp(ctx->base.ctxr->data + (req->state_sz>>2), 60441abed7dSPascal van Leeuwen ctx->opad, req->state_sz)))) 60541abed7dSPascal van Leeuwen /* 60641abed7dSPascal van Leeuwen * We're still setting needs_inv here, even though it is 607c4daf4ccSOfer Heifetz * cleared right away, because the needs_inv flag can be 608c4daf4ccSOfer Heifetz * set in other functions and we want to keep the same 609c4daf4ccSOfer Heifetz * logic. 610c4daf4ccSOfer Heifetz */ 61141abed7dSPascal van Leeuwen ctx->base.needs_inv = true; 6121b44c5a6SAntoine Ténart 6131eb7b403SOfer Heifetz if (ctx->base.needs_inv) { 6141eb7b403SOfer Heifetz ctx->base.needs_inv = false; 6151eb7b403SOfer Heifetz req->needs_inv = true; 6161eb7b403SOfer Heifetz } 6171b44c5a6SAntoine Ténart } else { 6181b44c5a6SAntoine Ténart ctx->base.ring = safexcel_select_ring(priv); 6191b44c5a6SAntoine Ténart ctx->base.ctxr = dma_pool_zalloc(priv->context_pool, 6201b44c5a6SAntoine Ténart EIP197_GFP_FLAGS(areq->base), 6211b44c5a6SAntoine Ténart &ctx->base.ctxr_dma); 6221b44c5a6SAntoine Ténart if (!ctx->base.ctxr) 6231b44c5a6SAntoine Ténart return -ENOMEM; 6241b44c5a6SAntoine Ténart } 6251b44c5a6SAntoine Ténart 62686671abbSAntoine Ténart ring = ctx->base.ring; 6271b44c5a6SAntoine Ténart 62886671abbSAntoine Ténart spin_lock_bh(&priv->ring[ring].queue_lock); 62986671abbSAntoine Ténart ret = crypto_enqueue_request(&priv->ring[ring].queue, &areq->base); 63086671abbSAntoine Ténart spin_unlock_bh(&priv->ring[ring].queue_lock); 63186671abbSAntoine Ténart 6328472e778SAntoine Ténart queue_work(priv->ring[ring].workqueue, 6338472e778SAntoine Ténart &priv->ring[ring].work_data.work); 6341b44c5a6SAntoine Ténart 6351b44c5a6SAntoine Ténart return ret; 6361b44c5a6SAntoine Ténart } 6371b44c5a6SAntoine Ténart 6381b44c5a6SAntoine Ténart static int safexcel_ahash_update(struct ahash_request *areq) 6391b44c5a6SAntoine Ténart { 6401b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 64141abed7dSPascal van Leeuwen int ret; 6421b44c5a6SAntoine Ténart 6431b44c5a6SAntoine Ténart /* If the request is 0 length, do nothing */ 6441b44c5a6SAntoine Ténart if (!areq->nbytes) 6451b44c5a6SAntoine Ténart return 0; 6461b44c5a6SAntoine Ténart 64741abed7dSPascal van Leeuwen /* Add request to the cache if it fits */ 64841abed7dSPascal van Leeuwen ret = safexcel_ahash_cache(areq); 64941abed7dSPascal van Leeuwen 65041abed7dSPascal van Leeuwen /* Update total request length */ 65131fb084cSPascal van Leeuwen req->len += areq->nbytes; 6521b44c5a6SAntoine Ténart 65341abed7dSPascal van Leeuwen /* If not all data could fit into the cache, go process the excess. 65441abed7dSPascal van Leeuwen * Also go process immediately for an HMAC IV precompute, which 65541abed7dSPascal van Leeuwen * will never be finished at all, but needs to be processed anyway. 6561b44c5a6SAntoine Ténart */ 65741abed7dSPascal van Leeuwen if ((ret && !req->finish) || req->last_req) 6581b44c5a6SAntoine Ténart return safexcel_ahash_enqueue(areq); 6591b44c5a6SAntoine Ténart 6601b44c5a6SAntoine Ténart return 0; 6611b44c5a6SAntoine Ténart } 6621b44c5a6SAntoine Ténart 6631b44c5a6SAntoine Ténart static int safexcel_ahash_final(struct ahash_request *areq) 6641b44c5a6SAntoine Ténart { 6651b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 6661b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 6671b44c5a6SAntoine Ténart 6681b44c5a6SAntoine Ténart req->finish = true; 6691b44c5a6SAntoine Ténart 67031fb084cSPascal van Leeuwen if (unlikely(!req->len && !areq->nbytes)) { 67185695b09SPascal van Leeuwen /* 67285695b09SPascal van Leeuwen * If we have an overall 0 length *hash* request: 67385695b09SPascal van Leeuwen * The HW cannot do 0 length hash, so we provide the correct 67485695b09SPascal van Leeuwen * result directly here. 67585695b09SPascal van Leeuwen */ 676293f89cfSOfer Heifetz if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_MD5) 677293f89cfSOfer Heifetz memcpy(areq->result, md5_zero_message_hash, 678293f89cfSOfer Heifetz MD5_DIGEST_SIZE); 679293f89cfSOfer Heifetz else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA1) 6801b44c5a6SAntoine Ténart memcpy(areq->result, sha1_zero_message_hash, 6811b44c5a6SAntoine Ténart SHA1_DIGEST_SIZE); 6821b44c5a6SAntoine Ténart else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA224) 6831b44c5a6SAntoine Ténart memcpy(areq->result, sha224_zero_message_hash, 6841b44c5a6SAntoine Ténart SHA224_DIGEST_SIZE); 6851b44c5a6SAntoine Ténart else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA256) 6861b44c5a6SAntoine Ténart memcpy(areq->result, sha256_zero_message_hash, 6871b44c5a6SAntoine Ténart SHA256_DIGEST_SIZE); 6889e46eafdSAntoine Tenart else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA384) 6899e46eafdSAntoine Tenart memcpy(areq->result, sha384_zero_message_hash, 6909e46eafdSAntoine Tenart SHA384_DIGEST_SIZE); 691b460edb6SAntoine Tenart else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA512) 692b460edb6SAntoine Tenart memcpy(areq->result, sha512_zero_message_hash, 693b460edb6SAntoine Tenart SHA512_DIGEST_SIZE); 6941b44c5a6SAntoine Ténart 6951b44c5a6SAntoine Ténart return 0; 69631fb084cSPascal van Leeuwen } else if (unlikely(req->hmac && 69731fb084cSPascal van Leeuwen (req->len == req->block_sz) && 69841abed7dSPascal van Leeuwen !areq->nbytes)) { 69985b36ee8SPascal van Leeuwen /* 70085b36ee8SPascal van Leeuwen * If we have an overall 0 length *HMAC* request: 70185b36ee8SPascal van Leeuwen * For HMAC, we need to finalize the inner digest 70285b36ee8SPascal van Leeuwen * and then perform the outer hash. 70385b36ee8SPascal van Leeuwen */ 70485b36ee8SPascal van Leeuwen 70585b36ee8SPascal van Leeuwen /* generate pad block in the cache */ 70685b36ee8SPascal van Leeuwen /* start with a hash block of all zeroes */ 70785b36ee8SPascal van Leeuwen memset(req->cache, 0, req->block_sz); 70885b36ee8SPascal van Leeuwen /* set the first byte to 0x80 to 'append a 1 bit' */ 70985b36ee8SPascal van Leeuwen req->cache[0] = 0x80; 71085b36ee8SPascal van Leeuwen /* add the length in bits in the last 2 bytes */ 71185b36ee8SPascal van Leeuwen if (req->len_is_le) { 71285b36ee8SPascal van Leeuwen /* Little endian length word (e.g. MD5) */ 71385b36ee8SPascal van Leeuwen req->cache[req->block_sz-8] = (req->block_sz << 3) & 71485b36ee8SPascal van Leeuwen 255; 71585b36ee8SPascal van Leeuwen req->cache[req->block_sz-7] = (req->block_sz >> 5); 71685b36ee8SPascal van Leeuwen } else { 71785b36ee8SPascal van Leeuwen /* Big endian length word (e.g. any SHA) */ 71885b36ee8SPascal van Leeuwen req->cache[req->block_sz-2] = (req->block_sz >> 5); 71985b36ee8SPascal van Leeuwen req->cache[req->block_sz-1] = (req->block_sz << 3) & 72085b36ee8SPascal van Leeuwen 255; 72185b36ee8SPascal van Leeuwen } 72285b36ee8SPascal van Leeuwen 72331fb084cSPascal van Leeuwen req->len += req->block_sz; /* plus 1 hash block */ 72485b36ee8SPascal van Leeuwen 72585b36ee8SPascal van Leeuwen /* Set special zero-length HMAC flag */ 72685b36ee8SPascal van Leeuwen req->hmac_zlen = true; 72785b36ee8SPascal van Leeuwen 72885b36ee8SPascal van Leeuwen /* Finalize HMAC */ 72985b36ee8SPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_HMAC; 73041abed7dSPascal van Leeuwen } else if (req->hmac) { 73141abed7dSPascal van Leeuwen /* Finalize HMAC */ 73241abed7dSPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_HMAC; 7331b44c5a6SAntoine Ténart } 7341b44c5a6SAntoine Ténart 7351b44c5a6SAntoine Ténart return safexcel_ahash_enqueue(areq); 7361b44c5a6SAntoine Ténart } 7371b44c5a6SAntoine Ténart 7381b44c5a6SAntoine Ténart static int safexcel_ahash_finup(struct ahash_request *areq) 7391b44c5a6SAntoine Ténart { 7401b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 7411b44c5a6SAntoine Ténart 7421b44c5a6SAntoine Ténart req->finish = true; 7431b44c5a6SAntoine Ténart 7441b44c5a6SAntoine Ténart safexcel_ahash_update(areq); 7451b44c5a6SAntoine Ténart return safexcel_ahash_final(areq); 7461b44c5a6SAntoine Ténart } 7471b44c5a6SAntoine Ténart 7481b44c5a6SAntoine Ténart static int safexcel_ahash_export(struct ahash_request *areq, void *out) 7491b44c5a6SAntoine Ténart { 7501b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 7511b44c5a6SAntoine Ténart struct safexcel_ahash_export_state *export = out; 7521b44c5a6SAntoine Ténart 75331fb084cSPascal van Leeuwen export->len = req->len; 75431fb084cSPascal van Leeuwen export->processed = req->processed; 7551b44c5a6SAntoine Ténart 756b869648cSAntoine Tenart export->digest = req->digest; 757b869648cSAntoine Tenart 7581b44c5a6SAntoine Ténart memcpy(export->state, req->state, req->state_sz); 75941abed7dSPascal van Leeuwen memcpy(export->cache, req->cache, HASH_CACHE_SIZE); 7601b44c5a6SAntoine Ténart 7611b44c5a6SAntoine Ténart return 0; 7621b44c5a6SAntoine Ténart } 7631b44c5a6SAntoine Ténart 7641b44c5a6SAntoine Ténart static int safexcel_ahash_import(struct ahash_request *areq, const void *in) 7651b44c5a6SAntoine Ténart { 7661b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 7671b44c5a6SAntoine Ténart const struct safexcel_ahash_export_state *export = in; 7681b44c5a6SAntoine Ténart int ret; 7691b44c5a6SAntoine Ténart 7701b44c5a6SAntoine Ténart ret = crypto_ahash_init(areq); 7711b44c5a6SAntoine Ténart if (ret) 7721b44c5a6SAntoine Ténart return ret; 7731b44c5a6SAntoine Ténart 77431fb084cSPascal van Leeuwen req->len = export->len; 77531fb084cSPascal van Leeuwen req->processed = export->processed; 7761b44c5a6SAntoine Ténart 777b869648cSAntoine Tenart req->digest = export->digest; 778b869648cSAntoine Tenart 77941abed7dSPascal van Leeuwen memcpy(req->cache, export->cache, HASH_CACHE_SIZE); 7801b44c5a6SAntoine Ténart memcpy(req->state, export->state, req->state_sz); 7811b44c5a6SAntoine Ténart 7821b44c5a6SAntoine Ténart return 0; 7831b44c5a6SAntoine Ténart } 7841b44c5a6SAntoine Ténart 7851b44c5a6SAntoine Ténart static int safexcel_ahash_cra_init(struct crypto_tfm *tfm) 7861b44c5a6SAntoine Ténart { 7871b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 7881b44c5a6SAntoine Ténart struct safexcel_alg_template *tmpl = 7891b44c5a6SAntoine Ténart container_of(__crypto_ahash_alg(tfm->__crt_alg), 7901b44c5a6SAntoine Ténart struct safexcel_alg_template, alg.ahash); 7911b44c5a6SAntoine Ténart 7921b44c5a6SAntoine Ténart ctx->priv = tmpl->priv; 7931eb7b403SOfer Heifetz ctx->base.send = safexcel_ahash_send; 7941eb7b403SOfer Heifetz ctx->base.handle_result = safexcel_handle_result; 7951b44c5a6SAntoine Ténart 7961b44c5a6SAntoine Ténart crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), 7971b44c5a6SAntoine Ténart sizeof(struct safexcel_ahash_req)); 7981b44c5a6SAntoine Ténart return 0; 7991b44c5a6SAntoine Ténart } 8001b44c5a6SAntoine Ténart 8011b44c5a6SAntoine Ténart static int safexcel_sha1_init(struct ahash_request *areq) 8021b44c5a6SAntoine Ténart { 8031b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 8041b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 8051b44c5a6SAntoine Ténart 8061b44c5a6SAntoine Ténart memset(req, 0, sizeof(*req)); 8071b44c5a6SAntoine Ténart 8081b44c5a6SAntoine Ténart ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1; 809b869648cSAntoine Tenart req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 8101b44c5a6SAntoine Ténart req->state_sz = SHA1_DIGEST_SIZE; 81141abed7dSPascal van Leeuwen req->block_sz = SHA1_BLOCK_SIZE; 8121b44c5a6SAntoine Ténart 8131b44c5a6SAntoine Ténart return 0; 8141b44c5a6SAntoine Ténart } 8151b44c5a6SAntoine Ténart 8161b44c5a6SAntoine Ténart static int safexcel_sha1_digest(struct ahash_request *areq) 8171b44c5a6SAntoine Ténart { 8181b44c5a6SAntoine Ténart int ret = safexcel_sha1_init(areq); 8191b44c5a6SAntoine Ténart 8201b44c5a6SAntoine Ténart if (ret) 8211b44c5a6SAntoine Ténart return ret; 8221b44c5a6SAntoine Ténart 8231b44c5a6SAntoine Ténart return safexcel_ahash_finup(areq); 8241b44c5a6SAntoine Ténart } 8251b44c5a6SAntoine Ténart 8261b44c5a6SAntoine Ténart static void safexcel_ahash_cra_exit(struct crypto_tfm *tfm) 8271b44c5a6SAntoine Ténart { 8281b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 8291b44c5a6SAntoine Ténart struct safexcel_crypto_priv *priv = ctx->priv; 8301b44c5a6SAntoine Ténart int ret; 8311b44c5a6SAntoine Ténart 8321b44c5a6SAntoine Ténart /* context not allocated, skip invalidation */ 8331b44c5a6SAntoine Ténart if (!ctx->base.ctxr) 8341b44c5a6SAntoine Ténart return; 8351b44c5a6SAntoine Ténart 83653c83e91SAntoine Tenart if (priv->flags & EIP197_TRC_CACHE) { 8371b44c5a6SAntoine Ténart ret = safexcel_ahash_exit_inv(tfm); 8381b44c5a6SAntoine Ténart if (ret) 8391b44c5a6SAntoine Ténart dev_warn(priv->dev, "hash: invalidation error %d\n", ret); 840871df319SAntoine Ténart } else { 841871df319SAntoine Ténart dma_pool_free(priv->context_pool, ctx->base.ctxr, 842871df319SAntoine Ténart ctx->base.ctxr_dma); 843871df319SAntoine Ténart } 8441b44c5a6SAntoine Ténart } 8451b44c5a6SAntoine Ténart 8461b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha1 = { 8471b44c5a6SAntoine Ténart .type = SAFEXCEL_ALG_TYPE_AHASH, 848062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA1, 8491b44c5a6SAntoine Ténart .alg.ahash = { 8501b44c5a6SAntoine Ténart .init = safexcel_sha1_init, 8511b44c5a6SAntoine Ténart .update = safexcel_ahash_update, 8521b44c5a6SAntoine Ténart .final = safexcel_ahash_final, 8531b44c5a6SAntoine Ténart .finup = safexcel_ahash_finup, 8541b44c5a6SAntoine Ténart .digest = safexcel_sha1_digest, 8551b44c5a6SAntoine Ténart .export = safexcel_ahash_export, 8561b44c5a6SAntoine Ténart .import = safexcel_ahash_import, 8571b44c5a6SAntoine Ténart .halg = { 8581b44c5a6SAntoine Ténart .digestsize = SHA1_DIGEST_SIZE, 8591b44c5a6SAntoine Ténart .statesize = sizeof(struct safexcel_ahash_export_state), 8601b44c5a6SAntoine Ténart .base = { 8611b44c5a6SAntoine Ténart .cra_name = "sha1", 8621b44c5a6SAntoine Ténart .cra_driver_name = "safexcel-sha1", 863aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 8641b44c5a6SAntoine Ténart .cra_flags = CRYPTO_ALG_ASYNC | 8651b44c5a6SAntoine Ténart CRYPTO_ALG_KERN_DRIVER_ONLY, 8661b44c5a6SAntoine Ténart .cra_blocksize = SHA1_BLOCK_SIZE, 8671b44c5a6SAntoine Ténart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 8681b44c5a6SAntoine Ténart .cra_init = safexcel_ahash_cra_init, 8691b44c5a6SAntoine Ténart .cra_exit = safexcel_ahash_cra_exit, 8701b44c5a6SAntoine Ténart .cra_module = THIS_MODULE, 8711b44c5a6SAntoine Ténart }, 8721b44c5a6SAntoine Ténart }, 8731b44c5a6SAntoine Ténart }, 8741b44c5a6SAntoine Ténart }; 8751b44c5a6SAntoine Ténart 8761b44c5a6SAntoine Ténart static int safexcel_hmac_sha1_init(struct ahash_request *areq) 8771b44c5a6SAntoine Ténart { 87841abed7dSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 879b869648cSAntoine Tenart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 8801b44c5a6SAntoine Ténart 88141abed7dSPascal van Leeuwen memset(req, 0, sizeof(*req)); 88241abed7dSPascal van Leeuwen 88341abed7dSPascal van Leeuwen /* Start from ipad precompute */ 88441abed7dSPascal van Leeuwen memcpy(req->state, ctx->ipad, SHA1_DIGEST_SIZE); 88541abed7dSPascal van Leeuwen /* Already processed the key^ipad part now! */ 88631fb084cSPascal van Leeuwen req->len = SHA1_BLOCK_SIZE; 88731fb084cSPascal van Leeuwen req->processed = SHA1_BLOCK_SIZE; 88841abed7dSPascal van Leeuwen 88941abed7dSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1; 89041abed7dSPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 89141abed7dSPascal van Leeuwen req->state_sz = SHA1_DIGEST_SIZE; 89241abed7dSPascal van Leeuwen req->block_sz = SHA1_BLOCK_SIZE; 89341abed7dSPascal van Leeuwen req->hmac = true; 89441abed7dSPascal van Leeuwen 8951b44c5a6SAntoine Ténart return 0; 8961b44c5a6SAntoine Ténart } 8971b44c5a6SAntoine Ténart 8981b44c5a6SAntoine Ténart static int safexcel_hmac_sha1_digest(struct ahash_request *areq) 8991b44c5a6SAntoine Ténart { 9001b44c5a6SAntoine Ténart int ret = safexcel_hmac_sha1_init(areq); 9011b44c5a6SAntoine Ténart 9021b44c5a6SAntoine Ténart if (ret) 9031b44c5a6SAntoine Ténart return ret; 9041b44c5a6SAntoine Ténart 9051b44c5a6SAntoine Ténart return safexcel_ahash_finup(areq); 9061b44c5a6SAntoine Ténart } 9071b44c5a6SAntoine Ténart 9081b44c5a6SAntoine Ténart struct safexcel_ahash_result { 9091b44c5a6SAntoine Ténart struct completion completion; 9101b44c5a6SAntoine Ténart int error; 9111b44c5a6SAntoine Ténart }; 9121b44c5a6SAntoine Ténart 9131b44c5a6SAntoine Ténart static void safexcel_ahash_complete(struct crypto_async_request *req, int error) 9141b44c5a6SAntoine Ténart { 9151b44c5a6SAntoine Ténart struct safexcel_ahash_result *result = req->data; 9161b44c5a6SAntoine Ténart 9171b44c5a6SAntoine Ténart if (error == -EINPROGRESS) 9181b44c5a6SAntoine Ténart return; 9191b44c5a6SAntoine Ténart 9201b44c5a6SAntoine Ténart result->error = error; 9211b44c5a6SAntoine Ténart complete(&result->completion); 9221b44c5a6SAntoine Ténart } 9231b44c5a6SAntoine Ténart 9241b44c5a6SAntoine Ténart static int safexcel_hmac_init_pad(struct ahash_request *areq, 9251b44c5a6SAntoine Ténart unsigned int blocksize, const u8 *key, 9261b44c5a6SAntoine Ténart unsigned int keylen, u8 *ipad, u8 *opad) 9271b44c5a6SAntoine Ténart { 9281b44c5a6SAntoine Ténart struct safexcel_ahash_result result; 9291b44c5a6SAntoine Ténart struct scatterlist sg; 9301b44c5a6SAntoine Ténart int ret, i; 9311b44c5a6SAntoine Ténart u8 *keydup; 9321b44c5a6SAntoine Ténart 9331b44c5a6SAntoine Ténart if (keylen <= blocksize) { 9341b44c5a6SAntoine Ténart memcpy(ipad, key, keylen); 9351b44c5a6SAntoine Ténart } else { 9361b44c5a6SAntoine Ténart keydup = kmemdup(key, keylen, GFP_KERNEL); 9371b44c5a6SAntoine Ténart if (!keydup) 9381b44c5a6SAntoine Ténart return -ENOMEM; 9391b44c5a6SAntoine Ténart 9401b44c5a6SAntoine Ténart ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_BACKLOG, 9411b44c5a6SAntoine Ténart safexcel_ahash_complete, &result); 9421b44c5a6SAntoine Ténart sg_init_one(&sg, keydup, keylen); 9431b44c5a6SAntoine Ténart ahash_request_set_crypt(areq, &sg, ipad, keylen); 9441b44c5a6SAntoine Ténart init_completion(&result.completion); 9451b44c5a6SAntoine Ténart 9461b44c5a6SAntoine Ténart ret = crypto_ahash_digest(areq); 9474dc5475aSAntoine Tenart if (ret == -EINPROGRESS || ret == -EBUSY) { 9481b44c5a6SAntoine Ténart wait_for_completion_interruptible(&result.completion); 9491b44c5a6SAntoine Ténart ret = result.error; 9501b44c5a6SAntoine Ténart } 9511b44c5a6SAntoine Ténart 9521b44c5a6SAntoine Ténart /* Avoid leaking */ 9531b44c5a6SAntoine Ténart memzero_explicit(keydup, keylen); 9541b44c5a6SAntoine Ténart kfree(keydup); 9551b44c5a6SAntoine Ténart 9561b44c5a6SAntoine Ténart if (ret) 9571b44c5a6SAntoine Ténart return ret; 9581b44c5a6SAntoine Ténart 9591b44c5a6SAntoine Ténart keylen = crypto_ahash_digestsize(crypto_ahash_reqtfm(areq)); 9601b44c5a6SAntoine Ténart } 9611b44c5a6SAntoine Ténart 9621b44c5a6SAntoine Ténart memset(ipad + keylen, 0, blocksize - keylen); 9631b44c5a6SAntoine Ténart memcpy(opad, ipad, blocksize); 9641b44c5a6SAntoine Ténart 9651b44c5a6SAntoine Ténart for (i = 0; i < blocksize; i++) { 966aed3731eSAntoine Ténart ipad[i] ^= HMAC_IPAD_VALUE; 967aed3731eSAntoine Ténart opad[i] ^= HMAC_OPAD_VALUE; 9681b44c5a6SAntoine Ténart } 9691b44c5a6SAntoine Ténart 9701b44c5a6SAntoine Ténart return 0; 9711b44c5a6SAntoine Ténart } 9721b44c5a6SAntoine Ténart 9731b44c5a6SAntoine Ténart static int safexcel_hmac_init_iv(struct ahash_request *areq, 9741b44c5a6SAntoine Ténart unsigned int blocksize, u8 *pad, void *state) 9751b44c5a6SAntoine Ténart { 9761b44c5a6SAntoine Ténart struct safexcel_ahash_result result; 9771b44c5a6SAntoine Ténart struct safexcel_ahash_req *req; 9781b44c5a6SAntoine Ténart struct scatterlist sg; 9791b44c5a6SAntoine Ténart int ret; 9801b44c5a6SAntoine Ténart 9811b44c5a6SAntoine Ténart ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_BACKLOG, 9821b44c5a6SAntoine Ténart safexcel_ahash_complete, &result); 9831b44c5a6SAntoine Ténart sg_init_one(&sg, pad, blocksize); 9841b44c5a6SAntoine Ténart ahash_request_set_crypt(areq, &sg, pad, blocksize); 9851b44c5a6SAntoine Ténart init_completion(&result.completion); 9861b44c5a6SAntoine Ténart 9871b44c5a6SAntoine Ténart ret = crypto_ahash_init(areq); 9881b44c5a6SAntoine Ténart if (ret) 9891b44c5a6SAntoine Ténart return ret; 9901b44c5a6SAntoine Ténart 9911b44c5a6SAntoine Ténart req = ahash_request_ctx(areq); 9921b44c5a6SAntoine Ténart req->hmac = true; 9931b44c5a6SAntoine Ténart req->last_req = true; 9941b44c5a6SAntoine Ténart 9951b44c5a6SAntoine Ténart ret = crypto_ahash_update(areq); 99612bf4142SOfer Heifetz if (ret && ret != -EINPROGRESS && ret != -EBUSY) 9971b44c5a6SAntoine Ténart return ret; 9981b44c5a6SAntoine Ténart 9991b44c5a6SAntoine Ténart wait_for_completion_interruptible(&result.completion); 10001b44c5a6SAntoine Ténart if (result.error) 10011b44c5a6SAntoine Ténart return result.error; 10021b44c5a6SAntoine Ténart 10031b44c5a6SAntoine Ténart return crypto_ahash_export(areq, state); 10041b44c5a6SAntoine Ténart } 10051b44c5a6SAntoine Ténart 1006f6beaea3SAntoine Tenart int safexcel_hmac_setkey(const char *alg, const u8 *key, unsigned int keylen, 1007f6beaea3SAntoine Tenart void *istate, void *ostate) 10081b44c5a6SAntoine Ténart { 10091b44c5a6SAntoine Ténart struct ahash_request *areq; 10101b44c5a6SAntoine Ténart struct crypto_ahash *tfm; 10111b44c5a6SAntoine Ténart unsigned int blocksize; 10121b44c5a6SAntoine Ténart u8 *ipad, *opad; 10131b44c5a6SAntoine Ténart int ret; 10141b44c5a6SAntoine Ténart 101585d7311fSEric Biggers tfm = crypto_alloc_ahash(alg, 0, 0); 10161b44c5a6SAntoine Ténart if (IS_ERR(tfm)) 10171b44c5a6SAntoine Ténart return PTR_ERR(tfm); 10181b44c5a6SAntoine Ténart 10191b44c5a6SAntoine Ténart areq = ahash_request_alloc(tfm, GFP_KERNEL); 10201b44c5a6SAntoine Ténart if (!areq) { 10211b44c5a6SAntoine Ténart ret = -ENOMEM; 10221b44c5a6SAntoine Ténart goto free_ahash; 10231b44c5a6SAntoine Ténart } 10241b44c5a6SAntoine Ténart 10251b44c5a6SAntoine Ténart crypto_ahash_clear_flags(tfm, ~0); 10261b44c5a6SAntoine Ténart blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); 10271b44c5a6SAntoine Ténart 10286396bb22SKees Cook ipad = kcalloc(2, blocksize, GFP_KERNEL); 10291b44c5a6SAntoine Ténart if (!ipad) { 10301b44c5a6SAntoine Ténart ret = -ENOMEM; 10311b44c5a6SAntoine Ténart goto free_request; 10321b44c5a6SAntoine Ténart } 10331b44c5a6SAntoine Ténart 10341b44c5a6SAntoine Ténart opad = ipad + blocksize; 10351b44c5a6SAntoine Ténart 10361b44c5a6SAntoine Ténart ret = safexcel_hmac_init_pad(areq, blocksize, key, keylen, ipad, opad); 10371b44c5a6SAntoine Ténart if (ret) 10381b44c5a6SAntoine Ténart goto free_ipad; 10391b44c5a6SAntoine Ténart 10401b44c5a6SAntoine Ténart ret = safexcel_hmac_init_iv(areq, blocksize, ipad, istate); 10411b44c5a6SAntoine Ténart if (ret) 10421b44c5a6SAntoine Ténart goto free_ipad; 10431b44c5a6SAntoine Ténart 10441b44c5a6SAntoine Ténart ret = safexcel_hmac_init_iv(areq, blocksize, opad, ostate); 10451b44c5a6SAntoine Ténart 10461b44c5a6SAntoine Ténart free_ipad: 10471b44c5a6SAntoine Ténart kfree(ipad); 10481b44c5a6SAntoine Ténart free_request: 10491b44c5a6SAntoine Ténart ahash_request_free(areq); 10501b44c5a6SAntoine Ténart free_ahash: 10511b44c5a6SAntoine Ténart crypto_free_ahash(tfm); 10521b44c5a6SAntoine Ténart 10531b44c5a6SAntoine Ténart return ret; 10541b44c5a6SAntoine Ténart } 10551b44c5a6SAntoine Ténart 105673f36ea7SAntoine Tenart static int safexcel_hmac_alg_setkey(struct crypto_ahash *tfm, const u8 *key, 105773f36ea7SAntoine Tenart unsigned int keylen, const char *alg, 105873f36ea7SAntoine Tenart unsigned int state_sz) 10591b44c5a6SAntoine Ténart { 10601b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 1061871df319SAntoine Ténart struct safexcel_crypto_priv *priv = ctx->priv; 10621b44c5a6SAntoine Ténart struct safexcel_ahash_export_state istate, ostate; 106341abed7dSPascal van Leeuwen int ret; 10641b44c5a6SAntoine Ténart 106573f36ea7SAntoine Tenart ret = safexcel_hmac_setkey(alg, key, keylen, &istate, &ostate); 10661b44c5a6SAntoine Ténart if (ret) 10671b44c5a6SAntoine Ténart return ret; 10681b44c5a6SAntoine Ténart 106941abed7dSPascal van Leeuwen if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr && 107041abed7dSPascal van Leeuwen (memcmp(ctx->ipad, istate.state, state_sz) || 107141abed7dSPascal van Leeuwen memcmp(ctx->opad, ostate.state, state_sz))) 10721b44c5a6SAntoine Ténart ctx->base.needs_inv = true; 10731b44c5a6SAntoine Ténart 107473f36ea7SAntoine Tenart memcpy(ctx->ipad, &istate.state, state_sz); 107573f36ea7SAntoine Tenart memcpy(ctx->opad, &ostate.state, state_sz); 107642ef3bedSAntoine Ténart 10771b44c5a6SAntoine Ténart return 0; 10781b44c5a6SAntoine Ténart } 10791b44c5a6SAntoine Ténart 108073f36ea7SAntoine Tenart static int safexcel_hmac_sha1_setkey(struct crypto_ahash *tfm, const u8 *key, 108173f36ea7SAntoine Tenart unsigned int keylen) 108273f36ea7SAntoine Tenart { 108373f36ea7SAntoine Tenart return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha1", 108473f36ea7SAntoine Tenart SHA1_DIGEST_SIZE); 108573f36ea7SAntoine Tenart } 108673f36ea7SAntoine Tenart 10871b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_hmac_sha1 = { 10881b44c5a6SAntoine Ténart .type = SAFEXCEL_ALG_TYPE_AHASH, 1089062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA1, 10901b44c5a6SAntoine Ténart .alg.ahash = { 10911b44c5a6SAntoine Ténart .init = safexcel_hmac_sha1_init, 10921b44c5a6SAntoine Ténart .update = safexcel_ahash_update, 10931b44c5a6SAntoine Ténart .final = safexcel_ahash_final, 10941b44c5a6SAntoine Ténart .finup = safexcel_ahash_finup, 10951b44c5a6SAntoine Ténart .digest = safexcel_hmac_sha1_digest, 10961b44c5a6SAntoine Ténart .setkey = safexcel_hmac_sha1_setkey, 10971b44c5a6SAntoine Ténart .export = safexcel_ahash_export, 10981b44c5a6SAntoine Ténart .import = safexcel_ahash_import, 10991b44c5a6SAntoine Ténart .halg = { 11001b44c5a6SAntoine Ténart .digestsize = SHA1_DIGEST_SIZE, 11011b44c5a6SAntoine Ténart .statesize = sizeof(struct safexcel_ahash_export_state), 11021b44c5a6SAntoine Ténart .base = { 11031b44c5a6SAntoine Ténart .cra_name = "hmac(sha1)", 11041b44c5a6SAntoine Ténart .cra_driver_name = "safexcel-hmac-sha1", 1105aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 11061b44c5a6SAntoine Ténart .cra_flags = CRYPTO_ALG_ASYNC | 11071b44c5a6SAntoine Ténart CRYPTO_ALG_KERN_DRIVER_ONLY, 11081b44c5a6SAntoine Ténart .cra_blocksize = SHA1_BLOCK_SIZE, 11091b44c5a6SAntoine Ténart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 11101b44c5a6SAntoine Ténart .cra_init = safexcel_ahash_cra_init, 11111b44c5a6SAntoine Ténart .cra_exit = safexcel_ahash_cra_exit, 11121b44c5a6SAntoine Ténart .cra_module = THIS_MODULE, 11131b44c5a6SAntoine Ténart }, 11141b44c5a6SAntoine Ténart }, 11151b44c5a6SAntoine Ténart }, 11161b44c5a6SAntoine Ténart }; 11171b44c5a6SAntoine Ténart 11181b44c5a6SAntoine Ténart static int safexcel_sha256_init(struct ahash_request *areq) 11191b44c5a6SAntoine Ténart { 11201b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 11211b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 11221b44c5a6SAntoine Ténart 11231b44c5a6SAntoine Ténart memset(req, 0, sizeof(*req)); 11241b44c5a6SAntoine Ténart 11251b44c5a6SAntoine Ténart ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256; 1126b869648cSAntoine Tenart req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 11271b44c5a6SAntoine Ténart req->state_sz = SHA256_DIGEST_SIZE; 112841abed7dSPascal van Leeuwen req->block_sz = SHA256_BLOCK_SIZE; 11291b44c5a6SAntoine Ténart 11301b44c5a6SAntoine Ténart return 0; 11311b44c5a6SAntoine Ténart } 11321b44c5a6SAntoine Ténart 11331b44c5a6SAntoine Ténart static int safexcel_sha256_digest(struct ahash_request *areq) 11341b44c5a6SAntoine Ténart { 11351b44c5a6SAntoine Ténart int ret = safexcel_sha256_init(areq); 11361b44c5a6SAntoine Ténart 11371b44c5a6SAntoine Ténart if (ret) 11381b44c5a6SAntoine Ténart return ret; 11391b44c5a6SAntoine Ténart 11401b44c5a6SAntoine Ténart return safexcel_ahash_finup(areq); 11411b44c5a6SAntoine Ténart } 11421b44c5a6SAntoine Ténart 11431b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha256 = { 11441b44c5a6SAntoine Ténart .type = SAFEXCEL_ALG_TYPE_AHASH, 1145062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA2_256, 11461b44c5a6SAntoine Ténart .alg.ahash = { 11471b44c5a6SAntoine Ténart .init = safexcel_sha256_init, 11481b44c5a6SAntoine Ténart .update = safexcel_ahash_update, 11491b44c5a6SAntoine Ténart .final = safexcel_ahash_final, 11501b44c5a6SAntoine Ténart .finup = safexcel_ahash_finup, 11511b44c5a6SAntoine Ténart .digest = safexcel_sha256_digest, 11521b44c5a6SAntoine Ténart .export = safexcel_ahash_export, 11531b44c5a6SAntoine Ténart .import = safexcel_ahash_import, 11541b44c5a6SAntoine Ténart .halg = { 11551b44c5a6SAntoine Ténart .digestsize = SHA256_DIGEST_SIZE, 11561b44c5a6SAntoine Ténart .statesize = sizeof(struct safexcel_ahash_export_state), 11571b44c5a6SAntoine Ténart .base = { 11581b44c5a6SAntoine Ténart .cra_name = "sha256", 11591b44c5a6SAntoine Ténart .cra_driver_name = "safexcel-sha256", 1160aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 11611b44c5a6SAntoine Ténart .cra_flags = CRYPTO_ALG_ASYNC | 11621b44c5a6SAntoine Ténart CRYPTO_ALG_KERN_DRIVER_ONLY, 11631b44c5a6SAntoine Ténart .cra_blocksize = SHA256_BLOCK_SIZE, 11641b44c5a6SAntoine Ténart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 11651b44c5a6SAntoine Ténart .cra_init = safexcel_ahash_cra_init, 11661b44c5a6SAntoine Ténart .cra_exit = safexcel_ahash_cra_exit, 11671b44c5a6SAntoine Ténart .cra_module = THIS_MODULE, 11681b44c5a6SAntoine Ténart }, 11691b44c5a6SAntoine Ténart }, 11701b44c5a6SAntoine Ténart }, 11711b44c5a6SAntoine Ténart }; 11721b44c5a6SAntoine Ténart 11731b44c5a6SAntoine Ténart static int safexcel_sha224_init(struct ahash_request *areq) 11741b44c5a6SAntoine Ténart { 11751b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 11761b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 11771b44c5a6SAntoine Ténart 11781b44c5a6SAntoine Ténart memset(req, 0, sizeof(*req)); 11791b44c5a6SAntoine Ténart 11801b44c5a6SAntoine Ténart ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224; 1181b869648cSAntoine Tenart req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 11821b44c5a6SAntoine Ténart req->state_sz = SHA256_DIGEST_SIZE; 118341abed7dSPascal van Leeuwen req->block_sz = SHA256_BLOCK_SIZE; 11841b44c5a6SAntoine Ténart 11851b44c5a6SAntoine Ténart return 0; 11861b44c5a6SAntoine Ténart } 11871b44c5a6SAntoine Ténart 11881b44c5a6SAntoine Ténart static int safexcel_sha224_digest(struct ahash_request *areq) 11891b44c5a6SAntoine Ténart { 11901b44c5a6SAntoine Ténart int ret = safexcel_sha224_init(areq); 11911b44c5a6SAntoine Ténart 11921b44c5a6SAntoine Ténart if (ret) 11931b44c5a6SAntoine Ténart return ret; 11941b44c5a6SAntoine Ténart 11951b44c5a6SAntoine Ténart return safexcel_ahash_finup(areq); 11961b44c5a6SAntoine Ténart } 11971b44c5a6SAntoine Ténart 11981b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha224 = { 11991b44c5a6SAntoine Ténart .type = SAFEXCEL_ALG_TYPE_AHASH, 1200062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA2_256, 12011b44c5a6SAntoine Ténart .alg.ahash = { 12021b44c5a6SAntoine Ténart .init = safexcel_sha224_init, 12031b44c5a6SAntoine Ténart .update = safexcel_ahash_update, 12041b44c5a6SAntoine Ténart .final = safexcel_ahash_final, 12051b44c5a6SAntoine Ténart .finup = safexcel_ahash_finup, 12061b44c5a6SAntoine Ténart .digest = safexcel_sha224_digest, 12071b44c5a6SAntoine Ténart .export = safexcel_ahash_export, 12081b44c5a6SAntoine Ténart .import = safexcel_ahash_import, 12091b44c5a6SAntoine Ténart .halg = { 12101b44c5a6SAntoine Ténart .digestsize = SHA224_DIGEST_SIZE, 12111b44c5a6SAntoine Ténart .statesize = sizeof(struct safexcel_ahash_export_state), 12121b44c5a6SAntoine Ténart .base = { 12131b44c5a6SAntoine Ténart .cra_name = "sha224", 12141b44c5a6SAntoine Ténart .cra_driver_name = "safexcel-sha224", 1215aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 12161b44c5a6SAntoine Ténart .cra_flags = CRYPTO_ALG_ASYNC | 12171b44c5a6SAntoine Ténart CRYPTO_ALG_KERN_DRIVER_ONLY, 12181b44c5a6SAntoine Ténart .cra_blocksize = SHA224_BLOCK_SIZE, 12191b44c5a6SAntoine Ténart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 12201b44c5a6SAntoine Ténart .cra_init = safexcel_ahash_cra_init, 12211b44c5a6SAntoine Ténart .cra_exit = safexcel_ahash_cra_exit, 12221b44c5a6SAntoine Ténart .cra_module = THIS_MODULE, 12231b44c5a6SAntoine Ténart }, 12241b44c5a6SAntoine Ténart }, 12251b44c5a6SAntoine Ténart }, 12261b44c5a6SAntoine Ténart }; 122773f36ea7SAntoine Tenart 12283ad618d8SAntoine Tenart static int safexcel_hmac_sha224_setkey(struct crypto_ahash *tfm, const u8 *key, 12293ad618d8SAntoine Tenart unsigned int keylen) 12303ad618d8SAntoine Tenart { 12313ad618d8SAntoine Tenart return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha224", 12323ad618d8SAntoine Tenart SHA256_DIGEST_SIZE); 12333ad618d8SAntoine Tenart } 12343ad618d8SAntoine Tenart 12353ad618d8SAntoine Tenart static int safexcel_hmac_sha224_init(struct ahash_request *areq) 12363ad618d8SAntoine Tenart { 123741abed7dSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 12383ad618d8SAntoine Tenart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 12393ad618d8SAntoine Tenart 124041abed7dSPascal van Leeuwen memset(req, 0, sizeof(*req)); 124141abed7dSPascal van Leeuwen 124241abed7dSPascal van Leeuwen /* Start from ipad precompute */ 124341abed7dSPascal van Leeuwen memcpy(req->state, ctx->ipad, SHA256_DIGEST_SIZE); 124441abed7dSPascal van Leeuwen /* Already processed the key^ipad part now! */ 124531fb084cSPascal van Leeuwen req->len = SHA256_BLOCK_SIZE; 124631fb084cSPascal van Leeuwen req->processed = SHA256_BLOCK_SIZE; 124741abed7dSPascal van Leeuwen 124841abed7dSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224; 124941abed7dSPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 125041abed7dSPascal van Leeuwen req->state_sz = SHA256_DIGEST_SIZE; 125141abed7dSPascal van Leeuwen req->block_sz = SHA256_BLOCK_SIZE; 125241abed7dSPascal van Leeuwen req->hmac = true; 125341abed7dSPascal van Leeuwen 12543ad618d8SAntoine Tenart return 0; 12553ad618d8SAntoine Tenart } 12563ad618d8SAntoine Tenart 12573ad618d8SAntoine Tenart static int safexcel_hmac_sha224_digest(struct ahash_request *areq) 12583ad618d8SAntoine Tenart { 12593ad618d8SAntoine Tenart int ret = safexcel_hmac_sha224_init(areq); 12603ad618d8SAntoine Tenart 12613ad618d8SAntoine Tenart if (ret) 12623ad618d8SAntoine Tenart return ret; 12633ad618d8SAntoine Tenart 12643ad618d8SAntoine Tenart return safexcel_ahash_finup(areq); 12653ad618d8SAntoine Tenart } 12663ad618d8SAntoine Tenart 12673ad618d8SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha224 = { 12683ad618d8SAntoine Tenart .type = SAFEXCEL_ALG_TYPE_AHASH, 1269062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA2_256, 12703ad618d8SAntoine Tenart .alg.ahash = { 12713ad618d8SAntoine Tenart .init = safexcel_hmac_sha224_init, 12723ad618d8SAntoine Tenart .update = safexcel_ahash_update, 12733ad618d8SAntoine Tenart .final = safexcel_ahash_final, 12743ad618d8SAntoine Tenart .finup = safexcel_ahash_finup, 12753ad618d8SAntoine Tenart .digest = safexcel_hmac_sha224_digest, 12763ad618d8SAntoine Tenart .setkey = safexcel_hmac_sha224_setkey, 12773ad618d8SAntoine Tenart .export = safexcel_ahash_export, 12783ad618d8SAntoine Tenart .import = safexcel_ahash_import, 12793ad618d8SAntoine Tenart .halg = { 12803ad618d8SAntoine Tenart .digestsize = SHA224_DIGEST_SIZE, 12813ad618d8SAntoine Tenart .statesize = sizeof(struct safexcel_ahash_export_state), 12823ad618d8SAntoine Tenart .base = { 12833ad618d8SAntoine Tenart .cra_name = "hmac(sha224)", 12843ad618d8SAntoine Tenart .cra_driver_name = "safexcel-hmac-sha224", 1285aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 12863ad618d8SAntoine Tenart .cra_flags = CRYPTO_ALG_ASYNC | 12873ad618d8SAntoine Tenart CRYPTO_ALG_KERN_DRIVER_ONLY, 12883ad618d8SAntoine Tenart .cra_blocksize = SHA224_BLOCK_SIZE, 12893ad618d8SAntoine Tenart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 12903ad618d8SAntoine Tenart .cra_init = safexcel_ahash_cra_init, 12913ad618d8SAntoine Tenart .cra_exit = safexcel_ahash_cra_exit, 12923ad618d8SAntoine Tenart .cra_module = THIS_MODULE, 12933ad618d8SAntoine Tenart }, 12943ad618d8SAntoine Tenart }, 12953ad618d8SAntoine Tenart }, 12963ad618d8SAntoine Tenart }; 12973ad618d8SAntoine Tenart 129873f36ea7SAntoine Tenart static int safexcel_hmac_sha256_setkey(struct crypto_ahash *tfm, const u8 *key, 129973f36ea7SAntoine Tenart unsigned int keylen) 130073f36ea7SAntoine Tenart { 130173f36ea7SAntoine Tenart return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha256", 130273f36ea7SAntoine Tenart SHA256_DIGEST_SIZE); 130373f36ea7SAntoine Tenart } 130473f36ea7SAntoine Tenart 130573f36ea7SAntoine Tenart static int safexcel_hmac_sha256_init(struct ahash_request *areq) 130673f36ea7SAntoine Tenart { 130741abed7dSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 130873f36ea7SAntoine Tenart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 130973f36ea7SAntoine Tenart 131041abed7dSPascal van Leeuwen memset(req, 0, sizeof(*req)); 131141abed7dSPascal van Leeuwen 131241abed7dSPascal van Leeuwen /* Start from ipad precompute */ 131341abed7dSPascal van Leeuwen memcpy(req->state, ctx->ipad, SHA256_DIGEST_SIZE); 131441abed7dSPascal van Leeuwen /* Already processed the key^ipad part now! */ 131531fb084cSPascal van Leeuwen req->len = SHA256_BLOCK_SIZE; 131631fb084cSPascal van Leeuwen req->processed = SHA256_BLOCK_SIZE; 131741abed7dSPascal van Leeuwen 131841abed7dSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256; 131941abed7dSPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 132041abed7dSPascal van Leeuwen req->state_sz = SHA256_DIGEST_SIZE; 132141abed7dSPascal van Leeuwen req->block_sz = SHA256_BLOCK_SIZE; 132241abed7dSPascal van Leeuwen req->hmac = true; 132341abed7dSPascal van Leeuwen 132473f36ea7SAntoine Tenart return 0; 132573f36ea7SAntoine Tenart } 132673f36ea7SAntoine Tenart 132773f36ea7SAntoine Tenart static int safexcel_hmac_sha256_digest(struct ahash_request *areq) 132873f36ea7SAntoine Tenart { 132973f36ea7SAntoine Tenart int ret = safexcel_hmac_sha256_init(areq); 133073f36ea7SAntoine Tenart 133173f36ea7SAntoine Tenart if (ret) 133273f36ea7SAntoine Tenart return ret; 133373f36ea7SAntoine Tenart 133473f36ea7SAntoine Tenart return safexcel_ahash_finup(areq); 133573f36ea7SAntoine Tenart } 133673f36ea7SAntoine Tenart 133773f36ea7SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha256 = { 133873f36ea7SAntoine Tenart .type = SAFEXCEL_ALG_TYPE_AHASH, 1339062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA2_256, 134073f36ea7SAntoine Tenart .alg.ahash = { 134173f36ea7SAntoine Tenart .init = safexcel_hmac_sha256_init, 134273f36ea7SAntoine Tenart .update = safexcel_ahash_update, 134373f36ea7SAntoine Tenart .final = safexcel_ahash_final, 134473f36ea7SAntoine Tenart .finup = safexcel_ahash_finup, 134573f36ea7SAntoine Tenart .digest = safexcel_hmac_sha256_digest, 134673f36ea7SAntoine Tenart .setkey = safexcel_hmac_sha256_setkey, 134773f36ea7SAntoine Tenart .export = safexcel_ahash_export, 134873f36ea7SAntoine Tenart .import = safexcel_ahash_import, 134973f36ea7SAntoine Tenart .halg = { 135073f36ea7SAntoine Tenart .digestsize = SHA256_DIGEST_SIZE, 135173f36ea7SAntoine Tenart .statesize = sizeof(struct safexcel_ahash_export_state), 135273f36ea7SAntoine Tenart .base = { 135373f36ea7SAntoine Tenart .cra_name = "hmac(sha256)", 135473f36ea7SAntoine Tenart .cra_driver_name = "safexcel-hmac-sha256", 1355aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 135673f36ea7SAntoine Tenart .cra_flags = CRYPTO_ALG_ASYNC | 135773f36ea7SAntoine Tenart CRYPTO_ALG_KERN_DRIVER_ONLY, 135873f36ea7SAntoine Tenart .cra_blocksize = SHA256_BLOCK_SIZE, 135973f36ea7SAntoine Tenart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 136073f36ea7SAntoine Tenart .cra_init = safexcel_ahash_cra_init, 136173f36ea7SAntoine Tenart .cra_exit = safexcel_ahash_cra_exit, 136273f36ea7SAntoine Tenart .cra_module = THIS_MODULE, 136373f36ea7SAntoine Tenart }, 136473f36ea7SAntoine Tenart }, 136573f36ea7SAntoine Tenart }, 136673f36ea7SAntoine Tenart }; 1367b460edb6SAntoine Tenart 1368b460edb6SAntoine Tenart static int safexcel_sha512_init(struct ahash_request *areq) 1369b460edb6SAntoine Tenart { 1370b460edb6SAntoine Tenart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 1371b460edb6SAntoine Tenart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 1372b460edb6SAntoine Tenart 1373b460edb6SAntoine Tenart memset(req, 0, sizeof(*req)); 1374b460edb6SAntoine Tenart 1375b460edb6SAntoine Tenart ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512; 1376b460edb6SAntoine Tenart req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 1377b460edb6SAntoine Tenart req->state_sz = SHA512_DIGEST_SIZE; 137841abed7dSPascal van Leeuwen req->block_sz = SHA512_BLOCK_SIZE; 1379b460edb6SAntoine Tenart 1380b460edb6SAntoine Tenart return 0; 1381b460edb6SAntoine Tenart } 1382b460edb6SAntoine Tenart 1383b460edb6SAntoine Tenart static int safexcel_sha512_digest(struct ahash_request *areq) 1384b460edb6SAntoine Tenart { 1385b460edb6SAntoine Tenart int ret = safexcel_sha512_init(areq); 1386b460edb6SAntoine Tenart 1387b460edb6SAntoine Tenart if (ret) 1388b460edb6SAntoine Tenart return ret; 1389b460edb6SAntoine Tenart 1390b460edb6SAntoine Tenart return safexcel_ahash_finup(areq); 1391b460edb6SAntoine Tenart } 1392b460edb6SAntoine Tenart 1393b460edb6SAntoine Tenart struct safexcel_alg_template safexcel_alg_sha512 = { 1394b460edb6SAntoine Tenart .type = SAFEXCEL_ALG_TYPE_AHASH, 1395062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA2_512, 1396b460edb6SAntoine Tenart .alg.ahash = { 1397b460edb6SAntoine Tenart .init = safexcel_sha512_init, 1398b460edb6SAntoine Tenart .update = safexcel_ahash_update, 1399b460edb6SAntoine Tenart .final = safexcel_ahash_final, 1400b460edb6SAntoine Tenart .finup = safexcel_ahash_finup, 1401b460edb6SAntoine Tenart .digest = safexcel_sha512_digest, 1402b460edb6SAntoine Tenart .export = safexcel_ahash_export, 1403b460edb6SAntoine Tenart .import = safexcel_ahash_import, 1404b460edb6SAntoine Tenart .halg = { 1405b460edb6SAntoine Tenart .digestsize = SHA512_DIGEST_SIZE, 1406b460edb6SAntoine Tenart .statesize = sizeof(struct safexcel_ahash_export_state), 1407b460edb6SAntoine Tenart .base = { 1408b460edb6SAntoine Tenart .cra_name = "sha512", 1409b460edb6SAntoine Tenart .cra_driver_name = "safexcel-sha512", 1410aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 1411b460edb6SAntoine Tenart .cra_flags = CRYPTO_ALG_ASYNC | 1412b460edb6SAntoine Tenart CRYPTO_ALG_KERN_DRIVER_ONLY, 1413b460edb6SAntoine Tenart .cra_blocksize = SHA512_BLOCK_SIZE, 1414b460edb6SAntoine Tenart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 1415b460edb6SAntoine Tenart .cra_init = safexcel_ahash_cra_init, 1416b460edb6SAntoine Tenart .cra_exit = safexcel_ahash_cra_exit, 1417b460edb6SAntoine Tenart .cra_module = THIS_MODULE, 1418b460edb6SAntoine Tenart }, 1419b460edb6SAntoine Tenart }, 1420b460edb6SAntoine Tenart }, 1421b460edb6SAntoine Tenart }; 14220de54fb1SAntoine Tenart 14239e46eafdSAntoine Tenart static int safexcel_sha384_init(struct ahash_request *areq) 14249e46eafdSAntoine Tenart { 14259e46eafdSAntoine Tenart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 14269e46eafdSAntoine Tenart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 14279e46eafdSAntoine Tenart 14289e46eafdSAntoine Tenart memset(req, 0, sizeof(*req)); 14299e46eafdSAntoine Tenart 14309e46eafdSAntoine Tenart ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384; 14319e46eafdSAntoine Tenart req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 14329e46eafdSAntoine Tenart req->state_sz = SHA512_DIGEST_SIZE; 143341abed7dSPascal van Leeuwen req->block_sz = SHA512_BLOCK_SIZE; 14349e46eafdSAntoine Tenart 14359e46eafdSAntoine Tenart return 0; 14369e46eafdSAntoine Tenart } 14379e46eafdSAntoine Tenart 14389e46eafdSAntoine Tenart static int safexcel_sha384_digest(struct ahash_request *areq) 14399e46eafdSAntoine Tenart { 14409e46eafdSAntoine Tenart int ret = safexcel_sha384_init(areq); 14419e46eafdSAntoine Tenart 14429e46eafdSAntoine Tenart if (ret) 14439e46eafdSAntoine Tenart return ret; 14449e46eafdSAntoine Tenart 14459e46eafdSAntoine Tenart return safexcel_ahash_finup(areq); 14469e46eafdSAntoine Tenart } 14479e46eafdSAntoine Tenart 14489e46eafdSAntoine Tenart struct safexcel_alg_template safexcel_alg_sha384 = { 14499e46eafdSAntoine Tenart .type = SAFEXCEL_ALG_TYPE_AHASH, 1450062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA2_512, 14519e46eafdSAntoine Tenart .alg.ahash = { 14529e46eafdSAntoine Tenart .init = safexcel_sha384_init, 14539e46eafdSAntoine Tenart .update = safexcel_ahash_update, 14549e46eafdSAntoine Tenart .final = safexcel_ahash_final, 14559e46eafdSAntoine Tenart .finup = safexcel_ahash_finup, 14569e46eafdSAntoine Tenart .digest = safexcel_sha384_digest, 14579e46eafdSAntoine Tenart .export = safexcel_ahash_export, 14589e46eafdSAntoine Tenart .import = safexcel_ahash_import, 14599e46eafdSAntoine Tenart .halg = { 14609e46eafdSAntoine Tenart .digestsize = SHA384_DIGEST_SIZE, 14619e46eafdSAntoine Tenart .statesize = sizeof(struct safexcel_ahash_export_state), 14629e46eafdSAntoine Tenart .base = { 14639e46eafdSAntoine Tenart .cra_name = "sha384", 14649e46eafdSAntoine Tenart .cra_driver_name = "safexcel-sha384", 1465aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 14669e46eafdSAntoine Tenart .cra_flags = CRYPTO_ALG_ASYNC | 14679e46eafdSAntoine Tenart CRYPTO_ALG_KERN_DRIVER_ONLY, 14689e46eafdSAntoine Tenart .cra_blocksize = SHA384_BLOCK_SIZE, 14699e46eafdSAntoine Tenart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 14709e46eafdSAntoine Tenart .cra_init = safexcel_ahash_cra_init, 14719e46eafdSAntoine Tenart .cra_exit = safexcel_ahash_cra_exit, 14729e46eafdSAntoine Tenart .cra_module = THIS_MODULE, 14739e46eafdSAntoine Tenart }, 14749e46eafdSAntoine Tenart }, 14759e46eafdSAntoine Tenart }, 14769e46eafdSAntoine Tenart }; 14779e46eafdSAntoine Tenart 14780de54fb1SAntoine Tenart static int safexcel_hmac_sha512_setkey(struct crypto_ahash *tfm, const u8 *key, 14790de54fb1SAntoine Tenart unsigned int keylen) 14800de54fb1SAntoine Tenart { 14810de54fb1SAntoine Tenart return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha512", 14820de54fb1SAntoine Tenart SHA512_DIGEST_SIZE); 14830de54fb1SAntoine Tenart } 14840de54fb1SAntoine Tenart 14850de54fb1SAntoine Tenart static int safexcel_hmac_sha512_init(struct ahash_request *areq) 14860de54fb1SAntoine Tenart { 148741abed7dSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 14880de54fb1SAntoine Tenart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 14890de54fb1SAntoine Tenart 149041abed7dSPascal van Leeuwen memset(req, 0, sizeof(*req)); 149141abed7dSPascal van Leeuwen 149241abed7dSPascal van Leeuwen /* Start from ipad precompute */ 149341abed7dSPascal van Leeuwen memcpy(req->state, ctx->ipad, SHA512_DIGEST_SIZE); 149441abed7dSPascal van Leeuwen /* Already processed the key^ipad part now! */ 149531fb084cSPascal van Leeuwen req->len = SHA512_BLOCK_SIZE; 149631fb084cSPascal van Leeuwen req->processed = SHA512_BLOCK_SIZE; 149741abed7dSPascal van Leeuwen 149841abed7dSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512; 149941abed7dSPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 150041abed7dSPascal van Leeuwen req->state_sz = SHA512_DIGEST_SIZE; 150141abed7dSPascal van Leeuwen req->block_sz = SHA512_BLOCK_SIZE; 150241abed7dSPascal van Leeuwen req->hmac = true; 150341abed7dSPascal van Leeuwen 15040de54fb1SAntoine Tenart return 0; 15050de54fb1SAntoine Tenart } 15060de54fb1SAntoine Tenart 15070de54fb1SAntoine Tenart static int safexcel_hmac_sha512_digest(struct ahash_request *areq) 15080de54fb1SAntoine Tenart { 15090de54fb1SAntoine Tenart int ret = safexcel_hmac_sha512_init(areq); 15100de54fb1SAntoine Tenart 15110de54fb1SAntoine Tenart if (ret) 15120de54fb1SAntoine Tenart return ret; 15130de54fb1SAntoine Tenart 15140de54fb1SAntoine Tenart return safexcel_ahash_finup(areq); 15150de54fb1SAntoine Tenart } 15160de54fb1SAntoine Tenart 15170de54fb1SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha512 = { 15180de54fb1SAntoine Tenart .type = SAFEXCEL_ALG_TYPE_AHASH, 1519062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA2_512, 15200de54fb1SAntoine Tenart .alg.ahash = { 15210de54fb1SAntoine Tenart .init = safexcel_hmac_sha512_init, 15220de54fb1SAntoine Tenart .update = safexcel_ahash_update, 15230de54fb1SAntoine Tenart .final = safexcel_ahash_final, 15240de54fb1SAntoine Tenart .finup = safexcel_ahash_finup, 15250de54fb1SAntoine Tenart .digest = safexcel_hmac_sha512_digest, 15260de54fb1SAntoine Tenart .setkey = safexcel_hmac_sha512_setkey, 15270de54fb1SAntoine Tenart .export = safexcel_ahash_export, 15280de54fb1SAntoine Tenart .import = safexcel_ahash_import, 15290de54fb1SAntoine Tenart .halg = { 15300de54fb1SAntoine Tenart .digestsize = SHA512_DIGEST_SIZE, 15310de54fb1SAntoine Tenart .statesize = sizeof(struct safexcel_ahash_export_state), 15320de54fb1SAntoine Tenart .base = { 15330de54fb1SAntoine Tenart .cra_name = "hmac(sha512)", 15340de54fb1SAntoine Tenart .cra_driver_name = "safexcel-hmac-sha512", 1535aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 15360de54fb1SAntoine Tenart .cra_flags = CRYPTO_ALG_ASYNC | 15370de54fb1SAntoine Tenart CRYPTO_ALG_KERN_DRIVER_ONLY, 15380de54fb1SAntoine Tenart .cra_blocksize = SHA512_BLOCK_SIZE, 15390de54fb1SAntoine Tenart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 15400de54fb1SAntoine Tenart .cra_init = safexcel_ahash_cra_init, 15410de54fb1SAntoine Tenart .cra_exit = safexcel_ahash_cra_exit, 15420de54fb1SAntoine Tenart .cra_module = THIS_MODULE, 15430de54fb1SAntoine Tenart }, 15440de54fb1SAntoine Tenart }, 15450de54fb1SAntoine Tenart }, 15460de54fb1SAntoine Tenart }; 15471f5d5d98SAntoine Tenart 15481f5d5d98SAntoine Tenart static int safexcel_hmac_sha384_setkey(struct crypto_ahash *tfm, const u8 *key, 15491f5d5d98SAntoine Tenart unsigned int keylen) 15501f5d5d98SAntoine Tenart { 15511f5d5d98SAntoine Tenart return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha384", 15521f5d5d98SAntoine Tenart SHA512_DIGEST_SIZE); 15531f5d5d98SAntoine Tenart } 15541f5d5d98SAntoine Tenart 15551f5d5d98SAntoine Tenart static int safexcel_hmac_sha384_init(struct ahash_request *areq) 15561f5d5d98SAntoine Tenart { 155741abed7dSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 15581f5d5d98SAntoine Tenart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 15591f5d5d98SAntoine Tenart 156041abed7dSPascal van Leeuwen memset(req, 0, sizeof(*req)); 156141abed7dSPascal van Leeuwen 156241abed7dSPascal van Leeuwen /* Start from ipad precompute */ 156341abed7dSPascal van Leeuwen memcpy(req->state, ctx->ipad, SHA512_DIGEST_SIZE); 156441abed7dSPascal van Leeuwen /* Already processed the key^ipad part now! */ 156531fb084cSPascal van Leeuwen req->len = SHA512_BLOCK_SIZE; 156631fb084cSPascal van Leeuwen req->processed = SHA512_BLOCK_SIZE; 156741abed7dSPascal van Leeuwen 156841abed7dSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384; 156941abed7dSPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 157041abed7dSPascal van Leeuwen req->state_sz = SHA512_DIGEST_SIZE; 157141abed7dSPascal van Leeuwen req->block_sz = SHA512_BLOCK_SIZE; 157241abed7dSPascal van Leeuwen req->hmac = true; 157341abed7dSPascal van Leeuwen 15741f5d5d98SAntoine Tenart return 0; 15751f5d5d98SAntoine Tenart } 15761f5d5d98SAntoine Tenart 15771f5d5d98SAntoine Tenart static int safexcel_hmac_sha384_digest(struct ahash_request *areq) 15781f5d5d98SAntoine Tenart { 15791f5d5d98SAntoine Tenart int ret = safexcel_hmac_sha384_init(areq); 15801f5d5d98SAntoine Tenart 15811f5d5d98SAntoine Tenart if (ret) 15821f5d5d98SAntoine Tenart return ret; 15831f5d5d98SAntoine Tenart 15841f5d5d98SAntoine Tenart return safexcel_ahash_finup(areq); 15851f5d5d98SAntoine Tenart } 15861f5d5d98SAntoine Tenart 15871f5d5d98SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha384 = { 15881f5d5d98SAntoine Tenart .type = SAFEXCEL_ALG_TYPE_AHASH, 1589062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA2_512, 15901f5d5d98SAntoine Tenart .alg.ahash = { 15911f5d5d98SAntoine Tenart .init = safexcel_hmac_sha384_init, 15921f5d5d98SAntoine Tenart .update = safexcel_ahash_update, 15931f5d5d98SAntoine Tenart .final = safexcel_ahash_final, 15941f5d5d98SAntoine Tenart .finup = safexcel_ahash_finup, 15951f5d5d98SAntoine Tenart .digest = safexcel_hmac_sha384_digest, 15961f5d5d98SAntoine Tenart .setkey = safexcel_hmac_sha384_setkey, 15971f5d5d98SAntoine Tenart .export = safexcel_ahash_export, 15981f5d5d98SAntoine Tenart .import = safexcel_ahash_import, 15991f5d5d98SAntoine Tenart .halg = { 16001f5d5d98SAntoine Tenart .digestsize = SHA384_DIGEST_SIZE, 16011f5d5d98SAntoine Tenart .statesize = sizeof(struct safexcel_ahash_export_state), 16021f5d5d98SAntoine Tenart .base = { 16031f5d5d98SAntoine Tenart .cra_name = "hmac(sha384)", 16041f5d5d98SAntoine Tenart .cra_driver_name = "safexcel-hmac-sha384", 1605aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 16061f5d5d98SAntoine Tenart .cra_flags = CRYPTO_ALG_ASYNC | 16071f5d5d98SAntoine Tenart CRYPTO_ALG_KERN_DRIVER_ONLY, 16081f5d5d98SAntoine Tenart .cra_blocksize = SHA384_BLOCK_SIZE, 16091f5d5d98SAntoine Tenart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 16101f5d5d98SAntoine Tenart .cra_init = safexcel_ahash_cra_init, 16111f5d5d98SAntoine Tenart .cra_exit = safexcel_ahash_cra_exit, 16121f5d5d98SAntoine Tenart .cra_module = THIS_MODULE, 16131f5d5d98SAntoine Tenart }, 16141f5d5d98SAntoine Tenart }, 16151f5d5d98SAntoine Tenart }, 16161f5d5d98SAntoine Tenart }; 1617293f89cfSOfer Heifetz 1618293f89cfSOfer Heifetz static int safexcel_md5_init(struct ahash_request *areq) 1619293f89cfSOfer Heifetz { 1620293f89cfSOfer Heifetz struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 1621293f89cfSOfer Heifetz struct safexcel_ahash_req *req = ahash_request_ctx(areq); 1622293f89cfSOfer Heifetz 1623293f89cfSOfer Heifetz memset(req, 0, sizeof(*req)); 1624293f89cfSOfer Heifetz 1625293f89cfSOfer Heifetz ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_MD5; 1626293f89cfSOfer Heifetz req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 1627293f89cfSOfer Heifetz req->state_sz = MD5_DIGEST_SIZE; 162841abed7dSPascal van Leeuwen req->block_sz = MD5_HMAC_BLOCK_SIZE; 1629293f89cfSOfer Heifetz 1630293f89cfSOfer Heifetz return 0; 1631293f89cfSOfer Heifetz } 1632293f89cfSOfer Heifetz 1633293f89cfSOfer Heifetz static int safexcel_md5_digest(struct ahash_request *areq) 1634293f89cfSOfer Heifetz { 1635293f89cfSOfer Heifetz int ret = safexcel_md5_init(areq); 1636293f89cfSOfer Heifetz 1637293f89cfSOfer Heifetz if (ret) 1638293f89cfSOfer Heifetz return ret; 1639293f89cfSOfer Heifetz 1640293f89cfSOfer Heifetz return safexcel_ahash_finup(areq); 1641293f89cfSOfer Heifetz } 1642293f89cfSOfer Heifetz 1643293f89cfSOfer Heifetz struct safexcel_alg_template safexcel_alg_md5 = { 1644293f89cfSOfer Heifetz .type = SAFEXCEL_ALG_TYPE_AHASH, 1645062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_MD5, 1646293f89cfSOfer Heifetz .alg.ahash = { 1647293f89cfSOfer Heifetz .init = safexcel_md5_init, 1648293f89cfSOfer Heifetz .update = safexcel_ahash_update, 1649293f89cfSOfer Heifetz .final = safexcel_ahash_final, 1650293f89cfSOfer Heifetz .finup = safexcel_ahash_finup, 1651293f89cfSOfer Heifetz .digest = safexcel_md5_digest, 1652293f89cfSOfer Heifetz .export = safexcel_ahash_export, 1653293f89cfSOfer Heifetz .import = safexcel_ahash_import, 1654293f89cfSOfer Heifetz .halg = { 1655293f89cfSOfer Heifetz .digestsize = MD5_DIGEST_SIZE, 1656293f89cfSOfer Heifetz .statesize = sizeof(struct safexcel_ahash_export_state), 1657293f89cfSOfer Heifetz .base = { 1658293f89cfSOfer Heifetz .cra_name = "md5", 1659293f89cfSOfer Heifetz .cra_driver_name = "safexcel-md5", 1660aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 1661293f89cfSOfer Heifetz .cra_flags = CRYPTO_ALG_ASYNC | 1662293f89cfSOfer Heifetz CRYPTO_ALG_KERN_DRIVER_ONLY, 1663293f89cfSOfer Heifetz .cra_blocksize = MD5_HMAC_BLOCK_SIZE, 1664293f89cfSOfer Heifetz .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 1665293f89cfSOfer Heifetz .cra_init = safexcel_ahash_cra_init, 1666293f89cfSOfer Heifetz .cra_exit = safexcel_ahash_cra_exit, 1667293f89cfSOfer Heifetz .cra_module = THIS_MODULE, 1668293f89cfSOfer Heifetz }, 1669293f89cfSOfer Heifetz }, 1670293f89cfSOfer Heifetz }, 1671293f89cfSOfer Heifetz }; 1672b471e4b9SOfer Heifetz 1673b471e4b9SOfer Heifetz static int safexcel_hmac_md5_init(struct ahash_request *areq) 1674b471e4b9SOfer Heifetz { 167541abed7dSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 1676b471e4b9SOfer Heifetz struct safexcel_ahash_req *req = ahash_request_ctx(areq); 1677b471e4b9SOfer Heifetz 167841abed7dSPascal van Leeuwen memset(req, 0, sizeof(*req)); 167941abed7dSPascal van Leeuwen 168041abed7dSPascal van Leeuwen /* Start from ipad precompute */ 168141abed7dSPascal van Leeuwen memcpy(req->state, ctx->ipad, MD5_DIGEST_SIZE); 168241abed7dSPascal van Leeuwen /* Already processed the key^ipad part now! */ 168331fb084cSPascal van Leeuwen req->len = MD5_HMAC_BLOCK_SIZE; 168431fb084cSPascal van Leeuwen req->processed = MD5_HMAC_BLOCK_SIZE; 168541abed7dSPascal van Leeuwen 168641abed7dSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_MD5; 168741abed7dSPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 168841abed7dSPascal van Leeuwen req->state_sz = MD5_DIGEST_SIZE; 168941abed7dSPascal van Leeuwen req->block_sz = MD5_HMAC_BLOCK_SIZE; 169085b36ee8SPascal van Leeuwen req->len_is_le = true; /* MD5 is little endian! ... */ 169141abed7dSPascal van Leeuwen req->hmac = true; 169241abed7dSPascal van Leeuwen 1693b471e4b9SOfer Heifetz return 0; 1694b471e4b9SOfer Heifetz } 1695b471e4b9SOfer Heifetz 1696b471e4b9SOfer Heifetz static int safexcel_hmac_md5_setkey(struct crypto_ahash *tfm, const u8 *key, 1697b471e4b9SOfer Heifetz unsigned int keylen) 1698b471e4b9SOfer Heifetz { 1699b471e4b9SOfer Heifetz return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-md5", 1700b471e4b9SOfer Heifetz MD5_DIGEST_SIZE); 1701b471e4b9SOfer Heifetz } 1702b471e4b9SOfer Heifetz 1703b471e4b9SOfer Heifetz static int safexcel_hmac_md5_digest(struct ahash_request *areq) 1704b471e4b9SOfer Heifetz { 1705b471e4b9SOfer Heifetz int ret = safexcel_hmac_md5_init(areq); 1706b471e4b9SOfer Heifetz 1707b471e4b9SOfer Heifetz if (ret) 1708b471e4b9SOfer Heifetz return ret; 1709b471e4b9SOfer Heifetz 1710b471e4b9SOfer Heifetz return safexcel_ahash_finup(areq); 1711b471e4b9SOfer Heifetz } 1712b471e4b9SOfer Heifetz 1713b471e4b9SOfer Heifetz struct safexcel_alg_template safexcel_alg_hmac_md5 = { 1714b471e4b9SOfer Heifetz .type = SAFEXCEL_ALG_TYPE_AHASH, 1715062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_MD5, 1716b471e4b9SOfer Heifetz .alg.ahash = { 1717b471e4b9SOfer Heifetz .init = safexcel_hmac_md5_init, 1718b471e4b9SOfer Heifetz .update = safexcel_ahash_update, 1719b471e4b9SOfer Heifetz .final = safexcel_ahash_final, 1720b471e4b9SOfer Heifetz .finup = safexcel_ahash_finup, 1721b471e4b9SOfer Heifetz .digest = safexcel_hmac_md5_digest, 1722b471e4b9SOfer Heifetz .setkey = safexcel_hmac_md5_setkey, 1723b471e4b9SOfer Heifetz .export = safexcel_ahash_export, 1724b471e4b9SOfer Heifetz .import = safexcel_ahash_import, 1725b471e4b9SOfer Heifetz .halg = { 1726b471e4b9SOfer Heifetz .digestsize = MD5_DIGEST_SIZE, 1727b471e4b9SOfer Heifetz .statesize = sizeof(struct safexcel_ahash_export_state), 1728b471e4b9SOfer Heifetz .base = { 1729b471e4b9SOfer Heifetz .cra_name = "hmac(md5)", 1730b471e4b9SOfer Heifetz .cra_driver_name = "safexcel-hmac-md5", 1731aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 1732b471e4b9SOfer Heifetz .cra_flags = CRYPTO_ALG_ASYNC | 1733b471e4b9SOfer Heifetz CRYPTO_ALG_KERN_DRIVER_ONLY, 1734b471e4b9SOfer Heifetz .cra_blocksize = MD5_HMAC_BLOCK_SIZE, 1735b471e4b9SOfer Heifetz .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 1736b471e4b9SOfer Heifetz .cra_init = safexcel_ahash_cra_init, 1737b471e4b9SOfer Heifetz .cra_exit = safexcel_ahash_cra_exit, 1738b471e4b9SOfer Heifetz .cra_module = THIS_MODULE, 1739b471e4b9SOfer Heifetz }, 1740b471e4b9SOfer Heifetz }, 1741b471e4b9SOfer Heifetz }, 1742b471e4b9SOfer Heifetz }; 1743