11b44c5a6SAntoine Ténart /* 21b44c5a6SAntoine Ténart * Copyright (C) 2017 Marvell 31b44c5a6SAntoine Ténart * 41b44c5a6SAntoine Ténart * Antoine Tenart <antoine.tenart@free-electrons.com> 51b44c5a6SAntoine Ténart * 61b44c5a6SAntoine Ténart * This file is licensed under the terms of the GNU General Public 71b44c5a6SAntoine Ténart * License version 2. This program is licensed "as is" without any 81b44c5a6SAntoine Ténart * warranty of any kind, whether express or implied. 91b44c5a6SAntoine Ténart */ 101b44c5a6SAntoine Ténart 11aed3731eSAntoine Ténart #include <crypto/hmac.h> 121b44c5a6SAntoine Ténart #include <crypto/sha.h> 131b44c5a6SAntoine Ténart #include <linux/device.h> 141b44c5a6SAntoine Ténart #include <linux/dma-mapping.h> 151b44c5a6SAntoine Ténart #include <linux/dmapool.h> 161b44c5a6SAntoine Ténart 171b44c5a6SAntoine Ténart 181b44c5a6SAntoine Ténart #include "safexcel.h" 191b44c5a6SAntoine Ténart 201b44c5a6SAntoine Ténart struct safexcel_ahash_ctx { 211b44c5a6SAntoine Ténart struct safexcel_context base; 221b44c5a6SAntoine Ténart struct safexcel_crypto_priv *priv; 231b44c5a6SAntoine Ténart 241b44c5a6SAntoine Ténart u32 alg; 251b44c5a6SAntoine Ténart u32 digest; 261b44c5a6SAntoine Ténart 271b44c5a6SAntoine Ténart u32 ipad[SHA1_DIGEST_SIZE / sizeof(u32)]; 281b44c5a6SAntoine Ténart u32 opad[SHA1_DIGEST_SIZE / sizeof(u32)]; 291b44c5a6SAntoine Ténart }; 301b44c5a6SAntoine Ténart 311b44c5a6SAntoine Ténart struct safexcel_ahash_req { 321b44c5a6SAntoine Ténart bool last_req; 331b44c5a6SAntoine Ténart bool finish; 341b44c5a6SAntoine Ténart bool hmac; 351b44c5a6SAntoine Ténart 361b44c5a6SAntoine Ténart u8 state_sz; /* expected sate size, only set once */ 371b44c5a6SAntoine Ténart u32 state[SHA256_DIGEST_SIZE / sizeof(u32)]; 381b44c5a6SAntoine Ténart 391b44c5a6SAntoine Ténart u64 len; 401b44c5a6SAntoine Ténart u64 processed; 411b44c5a6SAntoine Ténart 421b44c5a6SAntoine Ténart u8 cache[SHA256_BLOCK_SIZE] __aligned(sizeof(u32)); 431b44c5a6SAntoine Ténart u8 cache_next[SHA256_BLOCK_SIZE] __aligned(sizeof(u32)); 441b44c5a6SAntoine Ténart }; 451b44c5a6SAntoine Ténart 461b44c5a6SAntoine Ténart struct safexcel_ahash_export_state { 471b44c5a6SAntoine Ténart u64 len; 481b44c5a6SAntoine Ténart u64 processed; 491b44c5a6SAntoine Ténart 501b44c5a6SAntoine Ténart u32 state[SHA256_DIGEST_SIZE / sizeof(u32)]; 511b44c5a6SAntoine Ténart u8 cache[SHA256_BLOCK_SIZE]; 521b44c5a6SAntoine Ténart }; 531b44c5a6SAntoine Ténart 541b44c5a6SAntoine Ténart static void safexcel_hash_token(struct safexcel_command_desc *cdesc, 551b44c5a6SAntoine Ténart u32 input_length, u32 result_length) 561b44c5a6SAntoine Ténart { 571b44c5a6SAntoine Ténart struct safexcel_token *token = 581b44c5a6SAntoine Ténart (struct safexcel_token *)cdesc->control_data.token; 591b44c5a6SAntoine Ténart 601b44c5a6SAntoine Ténart token[0].opcode = EIP197_TOKEN_OPCODE_DIRECTION; 611b44c5a6SAntoine Ténart token[0].packet_length = input_length; 621b44c5a6SAntoine Ténart token[0].stat = EIP197_TOKEN_STAT_LAST_HASH; 631b44c5a6SAntoine Ténart token[0].instructions = EIP197_TOKEN_INS_TYPE_HASH; 641b44c5a6SAntoine Ténart 651b44c5a6SAntoine Ténart token[1].opcode = EIP197_TOKEN_OPCODE_INSERT; 661b44c5a6SAntoine Ténart token[1].packet_length = result_length; 671b44c5a6SAntoine Ténart token[1].stat = EIP197_TOKEN_STAT_LAST_HASH | 681b44c5a6SAntoine Ténart EIP197_TOKEN_STAT_LAST_PACKET; 691b44c5a6SAntoine Ténart token[1].instructions = EIP197_TOKEN_INS_TYPE_OUTPUT | 701b44c5a6SAntoine Ténart EIP197_TOKEN_INS_INSERT_HASH_DIGEST; 711b44c5a6SAntoine Ténart } 721b44c5a6SAntoine Ténart 731b44c5a6SAntoine Ténart static void safexcel_context_control(struct safexcel_ahash_ctx *ctx, 741b44c5a6SAntoine Ténart struct safexcel_ahash_req *req, 751b44c5a6SAntoine Ténart struct safexcel_command_desc *cdesc, 761b44c5a6SAntoine Ténart unsigned int digestsize, 771b44c5a6SAntoine Ténart unsigned int blocksize) 781b44c5a6SAntoine Ténart { 791b44c5a6SAntoine Ténart int i; 801b44c5a6SAntoine Ténart 811b44c5a6SAntoine Ténart cdesc->control_data.control0 |= CONTEXT_CONTROL_TYPE_HASH_OUT; 821b44c5a6SAntoine Ténart cdesc->control_data.control0 |= ctx->alg; 831b44c5a6SAntoine Ténart cdesc->control_data.control0 |= ctx->digest; 841b44c5a6SAntoine Ténart 851b44c5a6SAntoine Ténart if (ctx->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) { 861b44c5a6SAntoine Ténart if (req->processed) { 871b44c5a6SAntoine Ténart if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA1) 881b44c5a6SAntoine Ténart cdesc->control_data.control0 |= CONTEXT_CONTROL_SIZE(6); 891b44c5a6SAntoine Ténart else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA224 || 901b44c5a6SAntoine Ténart ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA256) 911b44c5a6SAntoine Ténart cdesc->control_data.control0 |= CONTEXT_CONTROL_SIZE(9); 921b44c5a6SAntoine Ténart 931b44c5a6SAntoine Ténart cdesc->control_data.control1 |= CONTEXT_CONTROL_DIGEST_CNT; 941b44c5a6SAntoine Ténart } else { 951b44c5a6SAntoine Ténart cdesc->control_data.control0 |= CONTEXT_CONTROL_RESTART_HASH; 961b44c5a6SAntoine Ténart } 971b44c5a6SAntoine Ténart 981b44c5a6SAntoine Ténart if (!req->finish) 991b44c5a6SAntoine Ténart cdesc->control_data.control0 |= CONTEXT_CONTROL_NO_FINISH_HASH; 1001b44c5a6SAntoine Ténart 1011b44c5a6SAntoine Ténart /* 1021b44c5a6SAntoine Ténart * Copy the input digest if needed, and setup the context 1031b44c5a6SAntoine Ténart * fields. Do this now as we need it to setup the first command 1041b44c5a6SAntoine Ténart * descriptor. 1051b44c5a6SAntoine Ténart */ 1061b44c5a6SAntoine Ténart if (req->processed) { 1071b44c5a6SAntoine Ténart for (i = 0; i < digestsize / sizeof(u32); i++) 1081b44c5a6SAntoine Ténart ctx->base.ctxr->data[i] = cpu_to_le32(req->state[i]); 1091b44c5a6SAntoine Ténart 1101b44c5a6SAntoine Ténart if (req->finish) 1111b44c5a6SAntoine Ténart ctx->base.ctxr->data[i] = cpu_to_le32(req->processed / blocksize); 1121b44c5a6SAntoine Ténart } 1131b44c5a6SAntoine Ténart } else if (ctx->digest == CONTEXT_CONTROL_DIGEST_HMAC) { 1141b44c5a6SAntoine Ténart cdesc->control_data.control0 |= CONTEXT_CONTROL_SIZE(10); 1151b44c5a6SAntoine Ténart 1161b44c5a6SAntoine Ténart memcpy(ctx->base.ctxr->data, ctx->ipad, digestsize); 1171b44c5a6SAntoine Ténart memcpy(ctx->base.ctxr->data + digestsize / sizeof(u32), 1181b44c5a6SAntoine Ténart ctx->opad, digestsize); 1191b44c5a6SAntoine Ténart } 1201b44c5a6SAntoine Ténart } 1211b44c5a6SAntoine Ténart 1221b44c5a6SAntoine Ténart static int safexcel_handle_result(struct safexcel_crypto_priv *priv, int ring, 1231b44c5a6SAntoine Ténart struct crypto_async_request *async, 1241b44c5a6SAntoine Ténart bool *should_complete, int *ret) 1251b44c5a6SAntoine Ténart { 1261b44c5a6SAntoine Ténart struct safexcel_result_desc *rdesc; 1271b44c5a6SAntoine Ténart struct ahash_request *areq = ahash_request_cast(async); 1281b44c5a6SAntoine Ténart struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); 1291b44c5a6SAntoine Ténart struct safexcel_ahash_req *sreq = ahash_request_ctx(areq); 1301b44c5a6SAntoine Ténart int cache_len, result_sz = sreq->state_sz; 1311b44c5a6SAntoine Ténart 1321b44c5a6SAntoine Ténart *ret = 0; 1331b44c5a6SAntoine Ténart 1341b44c5a6SAntoine Ténart spin_lock_bh(&priv->ring[ring].egress_lock); 1351b44c5a6SAntoine Ténart rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr); 1361b44c5a6SAntoine Ténart if (IS_ERR(rdesc)) { 1371b44c5a6SAntoine Ténart dev_err(priv->dev, 1381b44c5a6SAntoine Ténart "hash: result: could not retrieve the result descriptor\n"); 1391b44c5a6SAntoine Ténart *ret = PTR_ERR(rdesc); 1401b44c5a6SAntoine Ténart } else if (rdesc->result_data.error_code) { 1411b44c5a6SAntoine Ténart dev_err(priv->dev, 1421b44c5a6SAntoine Ténart "hash: result: result descriptor error (%d)\n", 1431b44c5a6SAntoine Ténart rdesc->result_data.error_code); 1441b44c5a6SAntoine Ténart *ret = -EINVAL; 1451b44c5a6SAntoine Ténart } 1461b44c5a6SAntoine Ténart 1471b44c5a6SAntoine Ténart safexcel_complete(priv, ring); 1481b44c5a6SAntoine Ténart spin_unlock_bh(&priv->ring[ring].egress_lock); 1491b44c5a6SAntoine Ténart 1501b44c5a6SAntoine Ténart if (sreq->finish) 1511b44c5a6SAntoine Ténart result_sz = crypto_ahash_digestsize(ahash); 1521b44c5a6SAntoine Ténart memcpy(sreq->state, areq->result, result_sz); 1531b44c5a6SAntoine Ténart 1541b44c5a6SAntoine Ténart dma_unmap_sg(priv->dev, areq->src, 1551b44c5a6SAntoine Ténart sg_nents_for_len(areq->src, areq->nbytes), DMA_TO_DEVICE); 1561b44c5a6SAntoine Ténart 1571b44c5a6SAntoine Ténart safexcel_free_context(priv, async, sreq->state_sz); 1581b44c5a6SAntoine Ténart 1591b44c5a6SAntoine Ténart cache_len = sreq->len - sreq->processed; 1601b44c5a6SAntoine Ténart if (cache_len) 1611b44c5a6SAntoine Ténart memcpy(sreq->cache, sreq->cache_next, cache_len); 1621b44c5a6SAntoine Ténart 1631b44c5a6SAntoine Ténart *should_complete = true; 1641b44c5a6SAntoine Ténart 1651b44c5a6SAntoine Ténart return 1; 1661b44c5a6SAntoine Ténart } 1671b44c5a6SAntoine Ténart 1681b44c5a6SAntoine Ténart static int safexcel_ahash_send(struct crypto_async_request *async, int ring, 1691b44c5a6SAntoine Ténart struct safexcel_request *request, int *commands, 1701b44c5a6SAntoine Ténart int *results) 1711b44c5a6SAntoine Ténart { 1721b44c5a6SAntoine Ténart struct ahash_request *areq = ahash_request_cast(async); 1731b44c5a6SAntoine Ténart struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); 1741b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 1751b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 1761b44c5a6SAntoine Ténart struct safexcel_crypto_priv *priv = ctx->priv; 1771b44c5a6SAntoine Ténart struct safexcel_command_desc *cdesc, *first_cdesc = NULL; 1781b44c5a6SAntoine Ténart struct safexcel_result_desc *rdesc; 1791b44c5a6SAntoine Ténart struct scatterlist *sg; 1801b44c5a6SAntoine Ténart int i, nents, queued, len, cache_len, extra, n_cdesc = 0, ret = 0; 1811b44c5a6SAntoine Ténart 1821b44c5a6SAntoine Ténart queued = len = req->len - req->processed; 1831b44c5a6SAntoine Ténart if (queued < crypto_ahash_blocksize(ahash)) 1841b44c5a6SAntoine Ténart cache_len = queued; 1851b44c5a6SAntoine Ténart else 1861b44c5a6SAntoine Ténart cache_len = queued - areq->nbytes; 1871b44c5a6SAntoine Ténart 1881b44c5a6SAntoine Ténart /* 1891b44c5a6SAntoine Ténart * If this is not the last request and the queued data does not fit 1901b44c5a6SAntoine Ténart * into full blocks, cache it for the next send() call. 1911b44c5a6SAntoine Ténart */ 1921b44c5a6SAntoine Ténart extra = queued & (crypto_ahash_blocksize(ahash) - 1); 1931b44c5a6SAntoine Ténart if (!req->last_req && extra) { 1941b44c5a6SAntoine Ténart sg_pcopy_to_buffer(areq->src, sg_nents(areq->src), 1951b44c5a6SAntoine Ténart req->cache_next, extra, areq->nbytes - extra); 1961b44c5a6SAntoine Ténart 1971b44c5a6SAntoine Ténart queued -= extra; 1981b44c5a6SAntoine Ténart len -= extra; 1991b44c5a6SAntoine Ténart } 2001b44c5a6SAntoine Ténart 2011b44c5a6SAntoine Ténart spin_lock_bh(&priv->ring[ring].egress_lock); 2021b44c5a6SAntoine Ténart 2031b44c5a6SAntoine Ténart /* Add a command descriptor for the cached data, if any */ 2041b44c5a6SAntoine Ténart if (cache_len) { 2051b44c5a6SAntoine Ténart ctx->base.cache = kzalloc(cache_len, EIP197_GFP_FLAGS(*async)); 2061b44c5a6SAntoine Ténart if (!ctx->base.cache) { 2071b44c5a6SAntoine Ténart ret = -ENOMEM; 2081b44c5a6SAntoine Ténart goto unlock; 2091b44c5a6SAntoine Ténart } 2101b44c5a6SAntoine Ténart memcpy(ctx->base.cache, req->cache, cache_len); 2111b44c5a6SAntoine Ténart ctx->base.cache_dma = dma_map_single(priv->dev, ctx->base.cache, 2121b44c5a6SAntoine Ténart cache_len, DMA_TO_DEVICE); 2131b44c5a6SAntoine Ténart if (dma_mapping_error(priv->dev, ctx->base.cache_dma)) { 2141b44c5a6SAntoine Ténart ret = -EINVAL; 2151b44c5a6SAntoine Ténart goto free_cache; 2161b44c5a6SAntoine Ténart } 2171b44c5a6SAntoine Ténart 2181b44c5a6SAntoine Ténart ctx->base.cache_sz = cache_len; 2191b44c5a6SAntoine Ténart first_cdesc = safexcel_add_cdesc(priv, ring, 1, 2201b44c5a6SAntoine Ténart (cache_len == len), 2211b44c5a6SAntoine Ténart ctx->base.cache_dma, 2221b44c5a6SAntoine Ténart cache_len, len, 2231b44c5a6SAntoine Ténart ctx->base.ctxr_dma); 2241b44c5a6SAntoine Ténart if (IS_ERR(first_cdesc)) { 2251b44c5a6SAntoine Ténart ret = PTR_ERR(first_cdesc); 2261b44c5a6SAntoine Ténart goto unmap_cache; 2271b44c5a6SAntoine Ténart } 2281b44c5a6SAntoine Ténart n_cdesc++; 2291b44c5a6SAntoine Ténart 2301b44c5a6SAntoine Ténart queued -= cache_len; 2311b44c5a6SAntoine Ténart if (!queued) 2321b44c5a6SAntoine Ténart goto send_command; 2331b44c5a6SAntoine Ténart } 2341b44c5a6SAntoine Ténart 2351b44c5a6SAntoine Ténart /* Now handle the current ahash request buffer(s) */ 2361b44c5a6SAntoine Ténart nents = dma_map_sg(priv->dev, areq->src, 2371b44c5a6SAntoine Ténart sg_nents_for_len(areq->src, areq->nbytes), 2381b44c5a6SAntoine Ténart DMA_TO_DEVICE); 2391b44c5a6SAntoine Ténart if (!nents) { 2401b44c5a6SAntoine Ténart ret = -ENOMEM; 2411b44c5a6SAntoine Ténart goto cdesc_rollback; 2421b44c5a6SAntoine Ténart } 2431b44c5a6SAntoine Ténart 2441b44c5a6SAntoine Ténart for_each_sg(areq->src, sg, nents, i) { 2451b44c5a6SAntoine Ténart int sglen = sg_dma_len(sg); 2461b44c5a6SAntoine Ténart 2471b44c5a6SAntoine Ténart /* Do not overflow the request */ 2481b44c5a6SAntoine Ténart if (queued - sglen < 0) 2491b44c5a6SAntoine Ténart sglen = queued; 2501b44c5a6SAntoine Ténart 2511b44c5a6SAntoine Ténart cdesc = safexcel_add_cdesc(priv, ring, !n_cdesc, 2521b44c5a6SAntoine Ténart !(queued - sglen), sg_dma_address(sg), 2531b44c5a6SAntoine Ténart sglen, len, ctx->base.ctxr_dma); 2541b44c5a6SAntoine Ténart if (IS_ERR(cdesc)) { 2551b44c5a6SAntoine Ténart ret = PTR_ERR(cdesc); 2561b44c5a6SAntoine Ténart goto cdesc_rollback; 2571b44c5a6SAntoine Ténart } 2581b44c5a6SAntoine Ténart n_cdesc++; 2591b44c5a6SAntoine Ténart 2601b44c5a6SAntoine Ténart if (n_cdesc == 1) 2611b44c5a6SAntoine Ténart first_cdesc = cdesc; 2621b44c5a6SAntoine Ténart 2631b44c5a6SAntoine Ténart queued -= sglen; 2641b44c5a6SAntoine Ténart if (!queued) 2651b44c5a6SAntoine Ténart break; 2661b44c5a6SAntoine Ténart } 2671b44c5a6SAntoine Ténart 2681b44c5a6SAntoine Ténart send_command: 2691b44c5a6SAntoine Ténart /* Setup the context options */ 2701b44c5a6SAntoine Ténart safexcel_context_control(ctx, req, first_cdesc, req->state_sz, 2711b44c5a6SAntoine Ténart crypto_ahash_blocksize(ahash)); 2721b44c5a6SAntoine Ténart 2731b44c5a6SAntoine Ténart /* Add the token */ 2741b44c5a6SAntoine Ténart safexcel_hash_token(first_cdesc, len, req->state_sz); 2751b44c5a6SAntoine Ténart 2761b44c5a6SAntoine Ténart ctx->base.result_dma = dma_map_single(priv->dev, areq->result, 2771b44c5a6SAntoine Ténart req->state_sz, DMA_FROM_DEVICE); 2781b44c5a6SAntoine Ténart if (dma_mapping_error(priv->dev, ctx->base.result_dma)) { 2791b44c5a6SAntoine Ténart ret = -EINVAL; 2801b44c5a6SAntoine Ténart goto cdesc_rollback; 2811b44c5a6SAntoine Ténart } 2821b44c5a6SAntoine Ténart 2831b44c5a6SAntoine Ténart /* Add a result descriptor */ 2841b44c5a6SAntoine Ténart rdesc = safexcel_add_rdesc(priv, ring, 1, 1, ctx->base.result_dma, 2851b44c5a6SAntoine Ténart req->state_sz); 2861b44c5a6SAntoine Ténart if (IS_ERR(rdesc)) { 2871b44c5a6SAntoine Ténart ret = PTR_ERR(rdesc); 2881b44c5a6SAntoine Ténart goto cdesc_rollback; 2891b44c5a6SAntoine Ténart } 2901b44c5a6SAntoine Ténart 2911b44c5a6SAntoine Ténart spin_unlock_bh(&priv->ring[ring].egress_lock); 2921b44c5a6SAntoine Ténart 29397858434SAntoine Ténart req->processed += len; 29497858434SAntoine Ténart request->req = &areq->base; 29597858434SAntoine Ténart ctx->base.handle_result = safexcel_handle_result; 29697858434SAntoine Ténart 2971b44c5a6SAntoine Ténart *commands = n_cdesc; 2981b44c5a6SAntoine Ténart *results = 1; 2991b44c5a6SAntoine Ténart return 0; 3001b44c5a6SAntoine Ténart 3011b44c5a6SAntoine Ténart cdesc_rollback: 3021b44c5a6SAntoine Ténart for (i = 0; i < n_cdesc; i++) 3031b44c5a6SAntoine Ténart safexcel_ring_rollback_wptr(priv, &priv->ring[ring].cdr); 3041b44c5a6SAntoine Ténart unmap_cache: 3051b44c5a6SAntoine Ténart if (ctx->base.cache_dma) { 3061b44c5a6SAntoine Ténart dma_unmap_single(priv->dev, ctx->base.cache_dma, 3071b44c5a6SAntoine Ténart ctx->base.cache_sz, DMA_TO_DEVICE); 3081b44c5a6SAntoine Ténart ctx->base.cache_sz = 0; 3091b44c5a6SAntoine Ténart } 3101b44c5a6SAntoine Ténart free_cache: 3111b44c5a6SAntoine Ténart if (ctx->base.cache) { 3121b44c5a6SAntoine Ténart kfree(ctx->base.cache); 3131b44c5a6SAntoine Ténart ctx->base.cache = NULL; 3141b44c5a6SAntoine Ténart } 3151b44c5a6SAntoine Ténart 3161b44c5a6SAntoine Ténart unlock: 3171b44c5a6SAntoine Ténart spin_unlock_bh(&priv->ring[ring].egress_lock); 3181b44c5a6SAntoine Ténart return ret; 3191b44c5a6SAntoine Ténart } 3201b44c5a6SAntoine Ténart 3211b44c5a6SAntoine Ténart static inline bool safexcel_ahash_needs_inv_get(struct ahash_request *areq) 3221b44c5a6SAntoine Ténart { 3231b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 3241b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 3251b44c5a6SAntoine Ténart struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); 3261b44c5a6SAntoine Ténart unsigned int state_w_sz = req->state_sz / sizeof(u32); 3271b44c5a6SAntoine Ténart int i; 3281b44c5a6SAntoine Ténart 3291b44c5a6SAntoine Ténart for (i = 0; i < state_w_sz; i++) 3301b44c5a6SAntoine Ténart if (ctx->base.ctxr->data[i] != cpu_to_le32(req->state[i])) 3311b44c5a6SAntoine Ténart return true; 3321b44c5a6SAntoine Ténart 3331b44c5a6SAntoine Ténart if (ctx->base.ctxr->data[state_w_sz] != 3341b44c5a6SAntoine Ténart cpu_to_le32(req->processed / crypto_ahash_blocksize(ahash))) 3351b44c5a6SAntoine Ténart return true; 3361b44c5a6SAntoine Ténart 3371b44c5a6SAntoine Ténart return false; 3381b44c5a6SAntoine Ténart } 3391b44c5a6SAntoine Ténart 3401b44c5a6SAntoine Ténart static int safexcel_handle_inv_result(struct safexcel_crypto_priv *priv, 3411b44c5a6SAntoine Ténart int ring, 3421b44c5a6SAntoine Ténart struct crypto_async_request *async, 3431b44c5a6SAntoine Ténart bool *should_complete, int *ret) 3441b44c5a6SAntoine Ténart { 3451b44c5a6SAntoine Ténart struct safexcel_result_desc *rdesc; 3461b44c5a6SAntoine Ténart struct ahash_request *areq = ahash_request_cast(async); 3471b44c5a6SAntoine Ténart struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); 3481b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(ahash); 3491b44c5a6SAntoine Ténart int enq_ret; 3501b44c5a6SAntoine Ténart 3511b44c5a6SAntoine Ténart *ret = 0; 3521b44c5a6SAntoine Ténart 3531b44c5a6SAntoine Ténart spin_lock_bh(&priv->ring[ring].egress_lock); 3541b44c5a6SAntoine Ténart rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr); 3551b44c5a6SAntoine Ténart if (IS_ERR(rdesc)) { 3561b44c5a6SAntoine Ténart dev_err(priv->dev, 3571b44c5a6SAntoine Ténart "hash: invalidate: could not retrieve the result descriptor\n"); 3581b44c5a6SAntoine Ténart *ret = PTR_ERR(rdesc); 3591b44c5a6SAntoine Ténart } else if (rdesc->result_data.error_code) { 3601b44c5a6SAntoine Ténart dev_err(priv->dev, 3611b44c5a6SAntoine Ténart "hash: invalidate: result descriptor error (%d)\n", 3621b44c5a6SAntoine Ténart rdesc->result_data.error_code); 3631b44c5a6SAntoine Ténart *ret = -EINVAL; 3641b44c5a6SAntoine Ténart } 3651b44c5a6SAntoine Ténart 3661b44c5a6SAntoine Ténart safexcel_complete(priv, ring); 3671b44c5a6SAntoine Ténart spin_unlock_bh(&priv->ring[ring].egress_lock); 3681b44c5a6SAntoine Ténart 3691b44c5a6SAntoine Ténart if (ctx->base.exit_inv) { 3701b44c5a6SAntoine Ténart dma_pool_free(priv->context_pool, ctx->base.ctxr, 3711b44c5a6SAntoine Ténart ctx->base.ctxr_dma); 3721b44c5a6SAntoine Ténart 3731b44c5a6SAntoine Ténart *should_complete = true; 3741b44c5a6SAntoine Ténart return 1; 3751b44c5a6SAntoine Ténart } 3761b44c5a6SAntoine Ténart 37786671abbSAntoine Ténart ring = safexcel_select_ring(priv); 37886671abbSAntoine Ténart ctx->base.ring = ring; 3791b44c5a6SAntoine Ténart ctx->base.needs_inv = false; 3801b44c5a6SAntoine Ténart ctx->base.send = safexcel_ahash_send; 3811b44c5a6SAntoine Ténart 38286671abbSAntoine Ténart spin_lock_bh(&priv->ring[ring].queue_lock); 38386671abbSAntoine Ténart enq_ret = crypto_enqueue_request(&priv->ring[ring].queue, async); 38486671abbSAntoine Ténart spin_unlock_bh(&priv->ring[ring].queue_lock); 3851b44c5a6SAntoine Ténart 3861b44c5a6SAntoine Ténart if (enq_ret != -EINPROGRESS) 3871b44c5a6SAntoine Ténart *ret = enq_ret; 3881b44c5a6SAntoine Ténart 38986671abbSAntoine Ténart if (!priv->ring[ring].need_dequeue) 39086671abbSAntoine Ténart safexcel_dequeue(priv, ring); 39186671abbSAntoine Ténart 3921b44c5a6SAntoine Ténart *should_complete = false; 3931b44c5a6SAntoine Ténart 3941b44c5a6SAntoine Ténart return 1; 3951b44c5a6SAntoine Ténart } 3961b44c5a6SAntoine Ténart 3971b44c5a6SAntoine Ténart static int safexcel_ahash_send_inv(struct crypto_async_request *async, 3981b44c5a6SAntoine Ténart int ring, struct safexcel_request *request, 3991b44c5a6SAntoine Ténart int *commands, int *results) 4001b44c5a6SAntoine Ténart { 4011b44c5a6SAntoine Ténart struct ahash_request *areq = ahash_request_cast(async); 4021b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 4031b44c5a6SAntoine Ténart int ret; 4041b44c5a6SAntoine Ténart 4051b44c5a6SAntoine Ténart ctx->base.handle_result = safexcel_handle_inv_result; 4061b44c5a6SAntoine Ténart ret = safexcel_invalidate_cache(async, &ctx->base, ctx->priv, 4071b44c5a6SAntoine Ténart ctx->base.ctxr_dma, ring, request); 4081b44c5a6SAntoine Ténart if (unlikely(ret)) 4091b44c5a6SAntoine Ténart return ret; 4101b44c5a6SAntoine Ténart 4111b44c5a6SAntoine Ténart *commands = 1; 4121b44c5a6SAntoine Ténart *results = 1; 4131b44c5a6SAntoine Ténart 4141b44c5a6SAntoine Ténart return 0; 4151b44c5a6SAntoine Ténart } 4161b44c5a6SAntoine Ténart 4171b44c5a6SAntoine Ténart static int safexcel_ahash_exit_inv(struct crypto_tfm *tfm) 4181b44c5a6SAntoine Ténart { 4191b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 4201b44c5a6SAntoine Ténart struct safexcel_crypto_priv *priv = ctx->priv; 4211b44c5a6SAntoine Ténart struct ahash_request req; 4221b44c5a6SAntoine Ténart struct safexcel_inv_result result = { 0 }; 42386671abbSAntoine Ténart int ring = ctx->base.ring; 4241b44c5a6SAntoine Ténart 4251b44c5a6SAntoine Ténart memset(&req, 0, sizeof(struct ahash_request)); 4261b44c5a6SAntoine Ténart 4271b44c5a6SAntoine Ténart /* create invalidation request */ 4281b44c5a6SAntoine Ténart init_completion(&result.completion); 4291b44c5a6SAntoine Ténart ahash_request_set_callback(&req, CRYPTO_TFM_REQ_MAY_BACKLOG, 4301b44c5a6SAntoine Ténart safexcel_inv_complete, &result); 4311b44c5a6SAntoine Ténart 4321b44c5a6SAntoine Ténart ahash_request_set_tfm(&req, __crypto_ahash_cast(tfm)); 4331b44c5a6SAntoine Ténart ctx = crypto_tfm_ctx(req.base.tfm); 4341b44c5a6SAntoine Ténart ctx->base.exit_inv = true; 4351b44c5a6SAntoine Ténart ctx->base.send = safexcel_ahash_send_inv; 4361b44c5a6SAntoine Ténart 43786671abbSAntoine Ténart spin_lock_bh(&priv->ring[ring].queue_lock); 43886671abbSAntoine Ténart crypto_enqueue_request(&priv->ring[ring].queue, &req.base); 43986671abbSAntoine Ténart spin_unlock_bh(&priv->ring[ring].queue_lock); 4401b44c5a6SAntoine Ténart 44186671abbSAntoine Ténart if (!priv->ring[ring].need_dequeue) 44286671abbSAntoine Ténart safexcel_dequeue(priv, ring); 4431b44c5a6SAntoine Ténart 4441b44c5a6SAntoine Ténart wait_for_completion_interruptible(&result.completion); 4451b44c5a6SAntoine Ténart 4461b44c5a6SAntoine Ténart if (result.error) { 4471b44c5a6SAntoine Ténart dev_warn(priv->dev, "hash: completion error (%d)\n", 4481b44c5a6SAntoine Ténart result.error); 4491b44c5a6SAntoine Ténart return result.error; 4501b44c5a6SAntoine Ténart } 4511b44c5a6SAntoine Ténart 4521b44c5a6SAntoine Ténart return 0; 4531b44c5a6SAntoine Ténart } 4541b44c5a6SAntoine Ténart 4551b44c5a6SAntoine Ténart static int safexcel_ahash_cache(struct ahash_request *areq) 4561b44c5a6SAntoine Ténart { 4571b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 4581b44c5a6SAntoine Ténart struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); 4591b44c5a6SAntoine Ténart int queued, cache_len; 4601b44c5a6SAntoine Ténart 4611b44c5a6SAntoine Ténart cache_len = req->len - areq->nbytes - req->processed; 4621b44c5a6SAntoine Ténart queued = req->len - req->processed; 4631b44c5a6SAntoine Ténart 4641b44c5a6SAntoine Ténart /* 4651b44c5a6SAntoine Ténart * In case there isn't enough bytes to proceed (less than a 4661b44c5a6SAntoine Ténart * block size), cache the data until we have enough. 4671b44c5a6SAntoine Ténart */ 4681b44c5a6SAntoine Ténart if (cache_len + areq->nbytes <= crypto_ahash_blocksize(ahash)) { 4691b44c5a6SAntoine Ténart sg_pcopy_to_buffer(areq->src, sg_nents(areq->src), 4701b44c5a6SAntoine Ténart req->cache + cache_len, 4711b44c5a6SAntoine Ténart areq->nbytes, 0); 4721b44c5a6SAntoine Ténart return areq->nbytes; 4731b44c5a6SAntoine Ténart } 4741b44c5a6SAntoine Ténart 4751b44c5a6SAntoine Ténart /* We could'nt cache all the data */ 4761b44c5a6SAntoine Ténart return -E2BIG; 4771b44c5a6SAntoine Ténart } 4781b44c5a6SAntoine Ténart 4791b44c5a6SAntoine Ténart static int safexcel_ahash_enqueue(struct ahash_request *areq) 4801b44c5a6SAntoine Ténart { 4811b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 4821b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 4831b44c5a6SAntoine Ténart struct safexcel_crypto_priv *priv = ctx->priv; 48486671abbSAntoine Ténart int ret, ring; 4851b44c5a6SAntoine Ténart 4861b44c5a6SAntoine Ténart ctx->base.send = safexcel_ahash_send; 4871b44c5a6SAntoine Ténart 4881b44c5a6SAntoine Ténart if (req->processed && ctx->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) 4891b44c5a6SAntoine Ténart ctx->base.needs_inv = safexcel_ahash_needs_inv_get(areq); 4901b44c5a6SAntoine Ténart 4911b44c5a6SAntoine Ténart if (ctx->base.ctxr) { 4921b44c5a6SAntoine Ténart if (ctx->base.needs_inv) 4931b44c5a6SAntoine Ténart ctx->base.send = safexcel_ahash_send_inv; 4941b44c5a6SAntoine Ténart } else { 4951b44c5a6SAntoine Ténart ctx->base.ring = safexcel_select_ring(priv); 4961b44c5a6SAntoine Ténart ctx->base.ctxr = dma_pool_zalloc(priv->context_pool, 4971b44c5a6SAntoine Ténart EIP197_GFP_FLAGS(areq->base), 4981b44c5a6SAntoine Ténart &ctx->base.ctxr_dma); 4991b44c5a6SAntoine Ténart if (!ctx->base.ctxr) 5001b44c5a6SAntoine Ténart return -ENOMEM; 5011b44c5a6SAntoine Ténart } 5021b44c5a6SAntoine Ténart 50386671abbSAntoine Ténart ring = ctx->base.ring; 5041b44c5a6SAntoine Ténart 50586671abbSAntoine Ténart spin_lock_bh(&priv->ring[ring].queue_lock); 50686671abbSAntoine Ténart ret = crypto_enqueue_request(&priv->ring[ring].queue, &areq->base); 50786671abbSAntoine Ténart spin_unlock_bh(&priv->ring[ring].queue_lock); 50886671abbSAntoine Ténart 50986671abbSAntoine Ténart if (!priv->ring[ring].need_dequeue) 51086671abbSAntoine Ténart safexcel_dequeue(priv, ring); 5111b44c5a6SAntoine Ténart 5121b44c5a6SAntoine Ténart return ret; 5131b44c5a6SAntoine Ténart } 5141b44c5a6SAntoine Ténart 5151b44c5a6SAntoine Ténart static int safexcel_ahash_update(struct ahash_request *areq) 5161b44c5a6SAntoine Ténart { 5171b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 5181b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 5191b44c5a6SAntoine Ténart struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); 5201b44c5a6SAntoine Ténart 5211b44c5a6SAntoine Ténart /* If the request is 0 length, do nothing */ 5221b44c5a6SAntoine Ténart if (!areq->nbytes) 5231b44c5a6SAntoine Ténart return 0; 5241b44c5a6SAntoine Ténart 5251b44c5a6SAntoine Ténart req->len += areq->nbytes; 5261b44c5a6SAntoine Ténart 5271b44c5a6SAntoine Ténart safexcel_ahash_cache(areq); 5281b44c5a6SAntoine Ténart 5291b44c5a6SAntoine Ténart /* 5301b44c5a6SAntoine Ténart * We're not doing partial updates when performing an hmac request. 5311b44c5a6SAntoine Ténart * Everything will be handled by the final() call. 5321b44c5a6SAntoine Ténart */ 5331b44c5a6SAntoine Ténart if (ctx->digest == CONTEXT_CONTROL_DIGEST_HMAC) 5341b44c5a6SAntoine Ténart return 0; 5351b44c5a6SAntoine Ténart 5361b44c5a6SAntoine Ténart if (req->hmac) 5371b44c5a6SAntoine Ténart return safexcel_ahash_enqueue(areq); 5381b44c5a6SAntoine Ténart 5391b44c5a6SAntoine Ténart if (!req->last_req && 5401b44c5a6SAntoine Ténart req->len - req->processed > crypto_ahash_blocksize(ahash)) 5411b44c5a6SAntoine Ténart return safexcel_ahash_enqueue(areq); 5421b44c5a6SAntoine Ténart 5431b44c5a6SAntoine Ténart return 0; 5441b44c5a6SAntoine Ténart } 5451b44c5a6SAntoine Ténart 5461b44c5a6SAntoine Ténart static int safexcel_ahash_final(struct ahash_request *areq) 5471b44c5a6SAntoine Ténart { 5481b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 5491b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 5501b44c5a6SAntoine Ténart 5511b44c5a6SAntoine Ténart req->last_req = true; 5521b44c5a6SAntoine Ténart req->finish = true; 5531b44c5a6SAntoine Ténart 5541b44c5a6SAntoine Ténart /* If we have an overall 0 length request */ 5551b44c5a6SAntoine Ténart if (!(req->len + areq->nbytes)) { 5561b44c5a6SAntoine Ténart if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA1) 5571b44c5a6SAntoine Ténart memcpy(areq->result, sha1_zero_message_hash, 5581b44c5a6SAntoine Ténart SHA1_DIGEST_SIZE); 5591b44c5a6SAntoine Ténart else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA224) 5601b44c5a6SAntoine Ténart memcpy(areq->result, sha224_zero_message_hash, 5611b44c5a6SAntoine Ténart SHA224_DIGEST_SIZE); 5621b44c5a6SAntoine Ténart else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA256) 5631b44c5a6SAntoine Ténart memcpy(areq->result, sha256_zero_message_hash, 5641b44c5a6SAntoine Ténart SHA256_DIGEST_SIZE); 5651b44c5a6SAntoine Ténart 5661b44c5a6SAntoine Ténart return 0; 5671b44c5a6SAntoine Ténart } 5681b44c5a6SAntoine Ténart 5691b44c5a6SAntoine Ténart return safexcel_ahash_enqueue(areq); 5701b44c5a6SAntoine Ténart } 5711b44c5a6SAntoine Ténart 5721b44c5a6SAntoine Ténart static int safexcel_ahash_finup(struct ahash_request *areq) 5731b44c5a6SAntoine Ténart { 5741b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 5751b44c5a6SAntoine Ténart 5761b44c5a6SAntoine Ténart req->last_req = true; 5771b44c5a6SAntoine Ténart req->finish = true; 5781b44c5a6SAntoine Ténart 5791b44c5a6SAntoine Ténart safexcel_ahash_update(areq); 5801b44c5a6SAntoine Ténart return safexcel_ahash_final(areq); 5811b44c5a6SAntoine Ténart } 5821b44c5a6SAntoine Ténart 5831b44c5a6SAntoine Ténart static int safexcel_ahash_export(struct ahash_request *areq, void *out) 5841b44c5a6SAntoine Ténart { 5851b44c5a6SAntoine Ténart struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); 5861b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 5871b44c5a6SAntoine Ténart struct safexcel_ahash_export_state *export = out; 5881b44c5a6SAntoine Ténart 5891b44c5a6SAntoine Ténart export->len = req->len; 5901b44c5a6SAntoine Ténart export->processed = req->processed; 5911b44c5a6SAntoine Ténart 5921b44c5a6SAntoine Ténart memcpy(export->state, req->state, req->state_sz); 5931b44c5a6SAntoine Ténart memset(export->cache, 0, crypto_ahash_blocksize(ahash)); 5941b44c5a6SAntoine Ténart memcpy(export->cache, req->cache, crypto_ahash_blocksize(ahash)); 5951b44c5a6SAntoine Ténart 5961b44c5a6SAntoine Ténart return 0; 5971b44c5a6SAntoine Ténart } 5981b44c5a6SAntoine Ténart 5991b44c5a6SAntoine Ténart static int safexcel_ahash_import(struct ahash_request *areq, const void *in) 6001b44c5a6SAntoine Ténart { 6011b44c5a6SAntoine Ténart struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); 6021b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 6031b44c5a6SAntoine Ténart const struct safexcel_ahash_export_state *export = in; 6041b44c5a6SAntoine Ténart int ret; 6051b44c5a6SAntoine Ténart 6061b44c5a6SAntoine Ténart ret = crypto_ahash_init(areq); 6071b44c5a6SAntoine Ténart if (ret) 6081b44c5a6SAntoine Ténart return ret; 6091b44c5a6SAntoine Ténart 6101b44c5a6SAntoine Ténart req->len = export->len; 6111b44c5a6SAntoine Ténart req->processed = export->processed; 6121b44c5a6SAntoine Ténart 6131b44c5a6SAntoine Ténart memcpy(req->cache, export->cache, crypto_ahash_blocksize(ahash)); 6141b44c5a6SAntoine Ténart memcpy(req->state, export->state, req->state_sz); 6151b44c5a6SAntoine Ténart 6161b44c5a6SAntoine Ténart return 0; 6171b44c5a6SAntoine Ténart } 6181b44c5a6SAntoine Ténart 6191b44c5a6SAntoine Ténart static int safexcel_ahash_cra_init(struct crypto_tfm *tfm) 6201b44c5a6SAntoine Ténart { 6211b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 6221b44c5a6SAntoine Ténart struct safexcel_alg_template *tmpl = 6231b44c5a6SAntoine Ténart container_of(__crypto_ahash_alg(tfm->__crt_alg), 6241b44c5a6SAntoine Ténart struct safexcel_alg_template, alg.ahash); 6251b44c5a6SAntoine Ténart 6261b44c5a6SAntoine Ténart ctx->priv = tmpl->priv; 6271b44c5a6SAntoine Ténart 6281b44c5a6SAntoine Ténart crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), 6291b44c5a6SAntoine Ténart sizeof(struct safexcel_ahash_req)); 6301b44c5a6SAntoine Ténart return 0; 6311b44c5a6SAntoine Ténart } 6321b44c5a6SAntoine Ténart 6331b44c5a6SAntoine Ténart static int safexcel_sha1_init(struct ahash_request *areq) 6341b44c5a6SAntoine Ténart { 6351b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 6361b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 6371b44c5a6SAntoine Ténart 6381b44c5a6SAntoine Ténart memset(req, 0, sizeof(*req)); 6391b44c5a6SAntoine Ténart 6401b44c5a6SAntoine Ténart req->state[0] = SHA1_H0; 6411b44c5a6SAntoine Ténart req->state[1] = SHA1_H1; 6421b44c5a6SAntoine Ténart req->state[2] = SHA1_H2; 6431b44c5a6SAntoine Ténart req->state[3] = SHA1_H3; 6441b44c5a6SAntoine Ténart req->state[4] = SHA1_H4; 6451b44c5a6SAntoine Ténart 6461b44c5a6SAntoine Ténart ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1; 6471b44c5a6SAntoine Ténart ctx->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 6481b44c5a6SAntoine Ténart req->state_sz = SHA1_DIGEST_SIZE; 6491b44c5a6SAntoine Ténart 6501b44c5a6SAntoine Ténart return 0; 6511b44c5a6SAntoine Ténart } 6521b44c5a6SAntoine Ténart 6531b44c5a6SAntoine Ténart static int safexcel_sha1_digest(struct ahash_request *areq) 6541b44c5a6SAntoine Ténart { 6551b44c5a6SAntoine Ténart int ret = safexcel_sha1_init(areq); 6561b44c5a6SAntoine Ténart 6571b44c5a6SAntoine Ténart if (ret) 6581b44c5a6SAntoine Ténart return ret; 6591b44c5a6SAntoine Ténart 6601b44c5a6SAntoine Ténart return safexcel_ahash_finup(areq); 6611b44c5a6SAntoine Ténart } 6621b44c5a6SAntoine Ténart 6631b44c5a6SAntoine Ténart static void safexcel_ahash_cra_exit(struct crypto_tfm *tfm) 6641b44c5a6SAntoine Ténart { 6651b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 6661b44c5a6SAntoine Ténart struct safexcel_crypto_priv *priv = ctx->priv; 6671b44c5a6SAntoine Ténart int ret; 6681b44c5a6SAntoine Ténart 6691b44c5a6SAntoine Ténart /* context not allocated, skip invalidation */ 6701b44c5a6SAntoine Ténart if (!ctx->base.ctxr) 6711b44c5a6SAntoine Ténart return; 6721b44c5a6SAntoine Ténart 6731b44c5a6SAntoine Ténart ret = safexcel_ahash_exit_inv(tfm); 6741b44c5a6SAntoine Ténart if (ret) 6751b44c5a6SAntoine Ténart dev_warn(priv->dev, "hash: invalidation error %d\n", ret); 6761b44c5a6SAntoine Ténart } 6771b44c5a6SAntoine Ténart 6781b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha1 = { 6791b44c5a6SAntoine Ténart .type = SAFEXCEL_ALG_TYPE_AHASH, 6801b44c5a6SAntoine Ténart .alg.ahash = { 6811b44c5a6SAntoine Ténart .init = safexcel_sha1_init, 6821b44c5a6SAntoine Ténart .update = safexcel_ahash_update, 6831b44c5a6SAntoine Ténart .final = safexcel_ahash_final, 6841b44c5a6SAntoine Ténart .finup = safexcel_ahash_finup, 6851b44c5a6SAntoine Ténart .digest = safexcel_sha1_digest, 6861b44c5a6SAntoine Ténart .export = safexcel_ahash_export, 6871b44c5a6SAntoine Ténart .import = safexcel_ahash_import, 6881b44c5a6SAntoine Ténart .halg = { 6891b44c5a6SAntoine Ténart .digestsize = SHA1_DIGEST_SIZE, 6901b44c5a6SAntoine Ténart .statesize = sizeof(struct safexcel_ahash_export_state), 6911b44c5a6SAntoine Ténart .base = { 6921b44c5a6SAntoine Ténart .cra_name = "sha1", 6931b44c5a6SAntoine Ténart .cra_driver_name = "safexcel-sha1", 6941b44c5a6SAntoine Ténart .cra_priority = 300, 6951b44c5a6SAntoine Ténart .cra_flags = CRYPTO_ALG_ASYNC | 6961b44c5a6SAntoine Ténart CRYPTO_ALG_KERN_DRIVER_ONLY, 6971b44c5a6SAntoine Ténart .cra_blocksize = SHA1_BLOCK_SIZE, 6981b44c5a6SAntoine Ténart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 6991b44c5a6SAntoine Ténart .cra_init = safexcel_ahash_cra_init, 7001b44c5a6SAntoine Ténart .cra_exit = safexcel_ahash_cra_exit, 7011b44c5a6SAntoine Ténart .cra_module = THIS_MODULE, 7021b44c5a6SAntoine Ténart }, 7031b44c5a6SAntoine Ténart }, 7041b44c5a6SAntoine Ténart }, 7051b44c5a6SAntoine Ténart }; 7061b44c5a6SAntoine Ténart 7071b44c5a6SAntoine Ténart static int safexcel_hmac_sha1_init(struct ahash_request *areq) 7081b44c5a6SAntoine Ténart { 7091b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 7101b44c5a6SAntoine Ténart 7111b44c5a6SAntoine Ténart safexcel_sha1_init(areq); 7121b44c5a6SAntoine Ténart ctx->digest = CONTEXT_CONTROL_DIGEST_HMAC; 7131b44c5a6SAntoine Ténart return 0; 7141b44c5a6SAntoine Ténart } 7151b44c5a6SAntoine Ténart 7161b44c5a6SAntoine Ténart static int safexcel_hmac_sha1_digest(struct ahash_request *areq) 7171b44c5a6SAntoine Ténart { 7181b44c5a6SAntoine Ténart int ret = safexcel_hmac_sha1_init(areq); 7191b44c5a6SAntoine Ténart 7201b44c5a6SAntoine Ténart if (ret) 7211b44c5a6SAntoine Ténart return ret; 7221b44c5a6SAntoine Ténart 7231b44c5a6SAntoine Ténart return safexcel_ahash_finup(areq); 7241b44c5a6SAntoine Ténart } 7251b44c5a6SAntoine Ténart 7261b44c5a6SAntoine Ténart struct safexcel_ahash_result { 7271b44c5a6SAntoine Ténart struct completion completion; 7281b44c5a6SAntoine Ténart int error; 7291b44c5a6SAntoine Ténart }; 7301b44c5a6SAntoine Ténart 7311b44c5a6SAntoine Ténart static void safexcel_ahash_complete(struct crypto_async_request *req, int error) 7321b44c5a6SAntoine Ténart { 7331b44c5a6SAntoine Ténart struct safexcel_ahash_result *result = req->data; 7341b44c5a6SAntoine Ténart 7351b44c5a6SAntoine Ténart if (error == -EINPROGRESS) 7361b44c5a6SAntoine Ténart return; 7371b44c5a6SAntoine Ténart 7381b44c5a6SAntoine Ténart result->error = error; 7391b44c5a6SAntoine Ténart complete(&result->completion); 7401b44c5a6SAntoine Ténart } 7411b44c5a6SAntoine Ténart 7421b44c5a6SAntoine Ténart static int safexcel_hmac_init_pad(struct ahash_request *areq, 7431b44c5a6SAntoine Ténart unsigned int blocksize, const u8 *key, 7441b44c5a6SAntoine Ténart unsigned int keylen, u8 *ipad, u8 *opad) 7451b44c5a6SAntoine Ténart { 7461b44c5a6SAntoine Ténart struct safexcel_ahash_result result; 7471b44c5a6SAntoine Ténart struct scatterlist sg; 7481b44c5a6SAntoine Ténart int ret, i; 7491b44c5a6SAntoine Ténart u8 *keydup; 7501b44c5a6SAntoine Ténart 7511b44c5a6SAntoine Ténart if (keylen <= blocksize) { 7521b44c5a6SAntoine Ténart memcpy(ipad, key, keylen); 7531b44c5a6SAntoine Ténart } else { 7541b44c5a6SAntoine Ténart keydup = kmemdup(key, keylen, GFP_KERNEL); 7551b44c5a6SAntoine Ténart if (!keydup) 7561b44c5a6SAntoine Ténart return -ENOMEM; 7571b44c5a6SAntoine Ténart 7581b44c5a6SAntoine Ténart ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_BACKLOG, 7591b44c5a6SAntoine Ténart safexcel_ahash_complete, &result); 7601b44c5a6SAntoine Ténart sg_init_one(&sg, keydup, keylen); 7611b44c5a6SAntoine Ténart ahash_request_set_crypt(areq, &sg, ipad, keylen); 7621b44c5a6SAntoine Ténart init_completion(&result.completion); 7631b44c5a6SAntoine Ténart 7641b44c5a6SAntoine Ténart ret = crypto_ahash_digest(areq); 7651b44c5a6SAntoine Ténart if (ret == -EINPROGRESS) { 7661b44c5a6SAntoine Ténart wait_for_completion_interruptible(&result.completion); 7671b44c5a6SAntoine Ténart ret = result.error; 7681b44c5a6SAntoine Ténart } 7691b44c5a6SAntoine Ténart 7701b44c5a6SAntoine Ténart /* Avoid leaking */ 7711b44c5a6SAntoine Ténart memzero_explicit(keydup, keylen); 7721b44c5a6SAntoine Ténart kfree(keydup); 7731b44c5a6SAntoine Ténart 7741b44c5a6SAntoine Ténart if (ret) 7751b44c5a6SAntoine Ténart return ret; 7761b44c5a6SAntoine Ténart 7771b44c5a6SAntoine Ténart keylen = crypto_ahash_digestsize(crypto_ahash_reqtfm(areq)); 7781b44c5a6SAntoine Ténart } 7791b44c5a6SAntoine Ténart 7801b44c5a6SAntoine Ténart memset(ipad + keylen, 0, blocksize - keylen); 7811b44c5a6SAntoine Ténart memcpy(opad, ipad, blocksize); 7821b44c5a6SAntoine Ténart 7831b44c5a6SAntoine Ténart for (i = 0; i < blocksize; i++) { 784aed3731eSAntoine Ténart ipad[i] ^= HMAC_IPAD_VALUE; 785aed3731eSAntoine Ténart opad[i] ^= HMAC_OPAD_VALUE; 7861b44c5a6SAntoine Ténart } 7871b44c5a6SAntoine Ténart 7881b44c5a6SAntoine Ténart return 0; 7891b44c5a6SAntoine Ténart } 7901b44c5a6SAntoine Ténart 7911b44c5a6SAntoine Ténart static int safexcel_hmac_init_iv(struct ahash_request *areq, 7921b44c5a6SAntoine Ténart unsigned int blocksize, u8 *pad, void *state) 7931b44c5a6SAntoine Ténart { 7941b44c5a6SAntoine Ténart struct safexcel_ahash_result result; 7951b44c5a6SAntoine Ténart struct safexcel_ahash_req *req; 7961b44c5a6SAntoine Ténart struct scatterlist sg; 7971b44c5a6SAntoine Ténart int ret; 7981b44c5a6SAntoine Ténart 7991b44c5a6SAntoine Ténart ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_BACKLOG, 8001b44c5a6SAntoine Ténart safexcel_ahash_complete, &result); 8011b44c5a6SAntoine Ténart sg_init_one(&sg, pad, blocksize); 8021b44c5a6SAntoine Ténart ahash_request_set_crypt(areq, &sg, pad, blocksize); 8031b44c5a6SAntoine Ténart init_completion(&result.completion); 8041b44c5a6SAntoine Ténart 8051b44c5a6SAntoine Ténart ret = crypto_ahash_init(areq); 8061b44c5a6SAntoine Ténart if (ret) 8071b44c5a6SAntoine Ténart return ret; 8081b44c5a6SAntoine Ténart 8091b44c5a6SAntoine Ténart req = ahash_request_ctx(areq); 8101b44c5a6SAntoine Ténart req->hmac = true; 8111b44c5a6SAntoine Ténart req->last_req = true; 8121b44c5a6SAntoine Ténart 8131b44c5a6SAntoine Ténart ret = crypto_ahash_update(areq); 8141b44c5a6SAntoine Ténart if (ret && ret != -EINPROGRESS) 8151b44c5a6SAntoine Ténart return ret; 8161b44c5a6SAntoine Ténart 8171b44c5a6SAntoine Ténart wait_for_completion_interruptible(&result.completion); 8181b44c5a6SAntoine Ténart if (result.error) 8191b44c5a6SAntoine Ténart return result.error; 8201b44c5a6SAntoine Ténart 8211b44c5a6SAntoine Ténart return crypto_ahash_export(areq, state); 8221b44c5a6SAntoine Ténart } 8231b44c5a6SAntoine Ténart 8241b44c5a6SAntoine Ténart static int safexcel_hmac_setkey(const char *alg, const u8 *key, 8251b44c5a6SAntoine Ténart unsigned int keylen, void *istate, void *ostate) 8261b44c5a6SAntoine Ténart { 8271b44c5a6SAntoine Ténart struct ahash_request *areq; 8281b44c5a6SAntoine Ténart struct crypto_ahash *tfm; 8291b44c5a6SAntoine Ténart unsigned int blocksize; 8301b44c5a6SAntoine Ténart u8 *ipad, *opad; 8311b44c5a6SAntoine Ténart int ret; 8321b44c5a6SAntoine Ténart 8331b44c5a6SAntoine Ténart tfm = crypto_alloc_ahash(alg, CRYPTO_ALG_TYPE_AHASH, 8341b44c5a6SAntoine Ténart CRYPTO_ALG_TYPE_AHASH_MASK); 8351b44c5a6SAntoine Ténart if (IS_ERR(tfm)) 8361b44c5a6SAntoine Ténart return PTR_ERR(tfm); 8371b44c5a6SAntoine Ténart 8381b44c5a6SAntoine Ténart areq = ahash_request_alloc(tfm, GFP_KERNEL); 8391b44c5a6SAntoine Ténart if (!areq) { 8401b44c5a6SAntoine Ténart ret = -ENOMEM; 8411b44c5a6SAntoine Ténart goto free_ahash; 8421b44c5a6SAntoine Ténart } 8431b44c5a6SAntoine Ténart 8441b44c5a6SAntoine Ténart crypto_ahash_clear_flags(tfm, ~0); 8451b44c5a6SAntoine Ténart blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); 8461b44c5a6SAntoine Ténart 8471b44c5a6SAntoine Ténart ipad = kzalloc(2 * blocksize, GFP_KERNEL); 8481b44c5a6SAntoine Ténart if (!ipad) { 8491b44c5a6SAntoine Ténart ret = -ENOMEM; 8501b44c5a6SAntoine Ténart goto free_request; 8511b44c5a6SAntoine Ténart } 8521b44c5a6SAntoine Ténart 8531b44c5a6SAntoine Ténart opad = ipad + blocksize; 8541b44c5a6SAntoine Ténart 8551b44c5a6SAntoine Ténart ret = safexcel_hmac_init_pad(areq, blocksize, key, keylen, ipad, opad); 8561b44c5a6SAntoine Ténart if (ret) 8571b44c5a6SAntoine Ténart goto free_ipad; 8581b44c5a6SAntoine Ténart 8591b44c5a6SAntoine Ténart ret = safexcel_hmac_init_iv(areq, blocksize, ipad, istate); 8601b44c5a6SAntoine Ténart if (ret) 8611b44c5a6SAntoine Ténart goto free_ipad; 8621b44c5a6SAntoine Ténart 8631b44c5a6SAntoine Ténart ret = safexcel_hmac_init_iv(areq, blocksize, opad, ostate); 8641b44c5a6SAntoine Ténart 8651b44c5a6SAntoine Ténart free_ipad: 8661b44c5a6SAntoine Ténart kfree(ipad); 8671b44c5a6SAntoine Ténart free_request: 8681b44c5a6SAntoine Ténart ahash_request_free(areq); 8691b44c5a6SAntoine Ténart free_ahash: 8701b44c5a6SAntoine Ténart crypto_free_ahash(tfm); 8711b44c5a6SAntoine Ténart 8721b44c5a6SAntoine Ténart return ret; 8731b44c5a6SAntoine Ténart } 8741b44c5a6SAntoine Ténart 8751b44c5a6SAntoine Ténart static int safexcel_hmac_sha1_setkey(struct crypto_ahash *tfm, const u8 *key, 8761b44c5a6SAntoine Ténart unsigned int keylen) 8771b44c5a6SAntoine Ténart { 8781b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 8791b44c5a6SAntoine Ténart struct safexcel_ahash_export_state istate, ostate; 8801b44c5a6SAntoine Ténart int ret, i; 8811b44c5a6SAntoine Ténart 8821b44c5a6SAntoine Ténart ret = safexcel_hmac_setkey("safexcel-sha1", key, keylen, &istate, &ostate); 8831b44c5a6SAntoine Ténart if (ret) 8841b44c5a6SAntoine Ténart return ret; 8851b44c5a6SAntoine Ténart 8861b44c5a6SAntoine Ténart memcpy(ctx->ipad, &istate.state, SHA1_DIGEST_SIZE); 8871b44c5a6SAntoine Ténart memcpy(ctx->opad, &ostate.state, SHA1_DIGEST_SIZE); 8881b44c5a6SAntoine Ténart 8891b44c5a6SAntoine Ténart for (i = 0; i < ARRAY_SIZE(istate.state); i++) { 8901b44c5a6SAntoine Ténart if (ctx->ipad[i] != le32_to_cpu(istate.state[i]) || 8911b44c5a6SAntoine Ténart ctx->opad[i] != le32_to_cpu(ostate.state[i])) { 8921b44c5a6SAntoine Ténart ctx->base.needs_inv = true; 8931b44c5a6SAntoine Ténart break; 8941b44c5a6SAntoine Ténart } 8951b44c5a6SAntoine Ténart } 8961b44c5a6SAntoine Ténart 8971b44c5a6SAntoine Ténart return 0; 8981b44c5a6SAntoine Ténart } 8991b44c5a6SAntoine Ténart 9001b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_hmac_sha1 = { 9011b44c5a6SAntoine Ténart .type = SAFEXCEL_ALG_TYPE_AHASH, 9021b44c5a6SAntoine Ténart .alg.ahash = { 9031b44c5a6SAntoine Ténart .init = safexcel_hmac_sha1_init, 9041b44c5a6SAntoine Ténart .update = safexcel_ahash_update, 9051b44c5a6SAntoine Ténart .final = safexcel_ahash_final, 9061b44c5a6SAntoine Ténart .finup = safexcel_ahash_finup, 9071b44c5a6SAntoine Ténart .digest = safexcel_hmac_sha1_digest, 9081b44c5a6SAntoine Ténart .setkey = safexcel_hmac_sha1_setkey, 9091b44c5a6SAntoine Ténart .export = safexcel_ahash_export, 9101b44c5a6SAntoine Ténart .import = safexcel_ahash_import, 9111b44c5a6SAntoine Ténart .halg = { 9121b44c5a6SAntoine Ténart .digestsize = SHA1_DIGEST_SIZE, 9131b44c5a6SAntoine Ténart .statesize = sizeof(struct safexcel_ahash_export_state), 9141b44c5a6SAntoine Ténart .base = { 9151b44c5a6SAntoine Ténart .cra_name = "hmac(sha1)", 9161b44c5a6SAntoine Ténart .cra_driver_name = "safexcel-hmac-sha1", 9171b44c5a6SAntoine Ténart .cra_priority = 300, 9181b44c5a6SAntoine Ténart .cra_flags = CRYPTO_ALG_ASYNC | 9191b44c5a6SAntoine Ténart CRYPTO_ALG_KERN_DRIVER_ONLY, 9201b44c5a6SAntoine Ténart .cra_blocksize = SHA1_BLOCK_SIZE, 9211b44c5a6SAntoine Ténart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 9221b44c5a6SAntoine Ténart .cra_init = safexcel_ahash_cra_init, 9231b44c5a6SAntoine Ténart .cra_exit = safexcel_ahash_cra_exit, 9241b44c5a6SAntoine Ténart .cra_module = THIS_MODULE, 9251b44c5a6SAntoine Ténart }, 9261b44c5a6SAntoine Ténart }, 9271b44c5a6SAntoine Ténart }, 9281b44c5a6SAntoine Ténart }; 9291b44c5a6SAntoine Ténart 9301b44c5a6SAntoine Ténart static int safexcel_sha256_init(struct ahash_request *areq) 9311b44c5a6SAntoine Ténart { 9321b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 9331b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 9341b44c5a6SAntoine Ténart 9351b44c5a6SAntoine Ténart memset(req, 0, sizeof(*req)); 9361b44c5a6SAntoine Ténart 9371b44c5a6SAntoine Ténart req->state[0] = SHA256_H0; 9381b44c5a6SAntoine Ténart req->state[1] = SHA256_H1; 9391b44c5a6SAntoine Ténart req->state[2] = SHA256_H2; 9401b44c5a6SAntoine Ténart req->state[3] = SHA256_H3; 9411b44c5a6SAntoine Ténart req->state[4] = SHA256_H4; 9421b44c5a6SAntoine Ténart req->state[5] = SHA256_H5; 9431b44c5a6SAntoine Ténart req->state[6] = SHA256_H6; 9441b44c5a6SAntoine Ténart req->state[7] = SHA256_H7; 9451b44c5a6SAntoine Ténart 9461b44c5a6SAntoine Ténart ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256; 9471b44c5a6SAntoine Ténart ctx->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 9481b44c5a6SAntoine Ténart req->state_sz = SHA256_DIGEST_SIZE; 9491b44c5a6SAntoine Ténart 9501b44c5a6SAntoine Ténart return 0; 9511b44c5a6SAntoine Ténart } 9521b44c5a6SAntoine Ténart 9531b44c5a6SAntoine Ténart static int safexcel_sha256_digest(struct ahash_request *areq) 9541b44c5a6SAntoine Ténart { 9551b44c5a6SAntoine Ténart int ret = safexcel_sha256_init(areq); 9561b44c5a6SAntoine Ténart 9571b44c5a6SAntoine Ténart if (ret) 9581b44c5a6SAntoine Ténart return ret; 9591b44c5a6SAntoine Ténart 9601b44c5a6SAntoine Ténart return safexcel_ahash_finup(areq); 9611b44c5a6SAntoine Ténart } 9621b44c5a6SAntoine Ténart 9631b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha256 = { 9641b44c5a6SAntoine Ténart .type = SAFEXCEL_ALG_TYPE_AHASH, 9651b44c5a6SAntoine Ténart .alg.ahash = { 9661b44c5a6SAntoine Ténart .init = safexcel_sha256_init, 9671b44c5a6SAntoine Ténart .update = safexcel_ahash_update, 9681b44c5a6SAntoine Ténart .final = safexcel_ahash_final, 9691b44c5a6SAntoine Ténart .finup = safexcel_ahash_finup, 9701b44c5a6SAntoine Ténart .digest = safexcel_sha256_digest, 9711b44c5a6SAntoine Ténart .export = safexcel_ahash_export, 9721b44c5a6SAntoine Ténart .import = safexcel_ahash_import, 9731b44c5a6SAntoine Ténart .halg = { 9741b44c5a6SAntoine Ténart .digestsize = SHA256_DIGEST_SIZE, 9751b44c5a6SAntoine Ténart .statesize = sizeof(struct safexcel_ahash_export_state), 9761b44c5a6SAntoine Ténart .base = { 9771b44c5a6SAntoine Ténart .cra_name = "sha256", 9781b44c5a6SAntoine Ténart .cra_driver_name = "safexcel-sha256", 9791b44c5a6SAntoine Ténart .cra_priority = 300, 9801b44c5a6SAntoine Ténart .cra_flags = CRYPTO_ALG_ASYNC | 9811b44c5a6SAntoine Ténart CRYPTO_ALG_KERN_DRIVER_ONLY, 9821b44c5a6SAntoine Ténart .cra_blocksize = SHA256_BLOCK_SIZE, 9831b44c5a6SAntoine Ténart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 9841b44c5a6SAntoine Ténart .cra_init = safexcel_ahash_cra_init, 9851b44c5a6SAntoine Ténart .cra_exit = safexcel_ahash_cra_exit, 9861b44c5a6SAntoine Ténart .cra_module = THIS_MODULE, 9871b44c5a6SAntoine Ténart }, 9881b44c5a6SAntoine Ténart }, 9891b44c5a6SAntoine Ténart }, 9901b44c5a6SAntoine Ténart }; 9911b44c5a6SAntoine Ténart 9921b44c5a6SAntoine Ténart static int safexcel_sha224_init(struct ahash_request *areq) 9931b44c5a6SAntoine Ténart { 9941b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 9951b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 9961b44c5a6SAntoine Ténart 9971b44c5a6SAntoine Ténart memset(req, 0, sizeof(*req)); 9981b44c5a6SAntoine Ténart 9991b44c5a6SAntoine Ténart req->state[0] = SHA224_H0; 10001b44c5a6SAntoine Ténart req->state[1] = SHA224_H1; 10011b44c5a6SAntoine Ténart req->state[2] = SHA224_H2; 10021b44c5a6SAntoine Ténart req->state[3] = SHA224_H3; 10031b44c5a6SAntoine Ténart req->state[4] = SHA224_H4; 10041b44c5a6SAntoine Ténart req->state[5] = SHA224_H5; 10051b44c5a6SAntoine Ténart req->state[6] = SHA224_H6; 10061b44c5a6SAntoine Ténart req->state[7] = SHA224_H7; 10071b44c5a6SAntoine Ténart 10081b44c5a6SAntoine Ténart ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224; 10091b44c5a6SAntoine Ténart ctx->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 10101b44c5a6SAntoine Ténart req->state_sz = SHA256_DIGEST_SIZE; 10111b44c5a6SAntoine Ténart 10121b44c5a6SAntoine Ténart return 0; 10131b44c5a6SAntoine Ténart } 10141b44c5a6SAntoine Ténart 10151b44c5a6SAntoine Ténart static int safexcel_sha224_digest(struct ahash_request *areq) 10161b44c5a6SAntoine Ténart { 10171b44c5a6SAntoine Ténart int ret = safexcel_sha224_init(areq); 10181b44c5a6SAntoine Ténart 10191b44c5a6SAntoine Ténart if (ret) 10201b44c5a6SAntoine Ténart return ret; 10211b44c5a6SAntoine Ténart 10221b44c5a6SAntoine Ténart return safexcel_ahash_finup(areq); 10231b44c5a6SAntoine Ténart } 10241b44c5a6SAntoine Ténart 10251b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha224 = { 10261b44c5a6SAntoine Ténart .type = SAFEXCEL_ALG_TYPE_AHASH, 10271b44c5a6SAntoine Ténart .alg.ahash = { 10281b44c5a6SAntoine Ténart .init = safexcel_sha224_init, 10291b44c5a6SAntoine Ténart .update = safexcel_ahash_update, 10301b44c5a6SAntoine Ténart .final = safexcel_ahash_final, 10311b44c5a6SAntoine Ténart .finup = safexcel_ahash_finup, 10321b44c5a6SAntoine Ténart .digest = safexcel_sha224_digest, 10331b44c5a6SAntoine Ténart .export = safexcel_ahash_export, 10341b44c5a6SAntoine Ténart .import = safexcel_ahash_import, 10351b44c5a6SAntoine Ténart .halg = { 10361b44c5a6SAntoine Ténart .digestsize = SHA224_DIGEST_SIZE, 10371b44c5a6SAntoine Ténart .statesize = sizeof(struct safexcel_ahash_export_state), 10381b44c5a6SAntoine Ténart .base = { 10391b44c5a6SAntoine Ténart .cra_name = "sha224", 10401b44c5a6SAntoine Ténart .cra_driver_name = "safexcel-sha224", 10411b44c5a6SAntoine Ténart .cra_priority = 300, 10421b44c5a6SAntoine Ténart .cra_flags = CRYPTO_ALG_ASYNC | 10431b44c5a6SAntoine Ténart CRYPTO_ALG_KERN_DRIVER_ONLY, 10441b44c5a6SAntoine Ténart .cra_blocksize = SHA224_BLOCK_SIZE, 10451b44c5a6SAntoine Ténart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 10461b44c5a6SAntoine Ténart .cra_init = safexcel_ahash_cra_init, 10471b44c5a6SAntoine Ténart .cra_exit = safexcel_ahash_cra_exit, 10481b44c5a6SAntoine Ténart .cra_module = THIS_MODULE, 10491b44c5a6SAntoine Ténart }, 10501b44c5a6SAntoine Ténart }, 10511b44c5a6SAntoine Ténart }, 10521b44c5a6SAntoine Ténart }; 1053