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 #include "safexcel.h" 181b44c5a6SAntoine Ténart 191b44c5a6SAntoine Ténart struct safexcel_ahash_ctx { 201b44c5a6SAntoine Ténart struct safexcel_context base; 211b44c5a6SAntoine Ténart struct safexcel_crypto_priv *priv; 221b44c5a6SAntoine Ténart 231b44c5a6SAntoine Ténart u32 alg; 241b44c5a6SAntoine Ténart 2573f36ea7SAntoine Tenart u32 ipad[SHA256_DIGEST_SIZE / sizeof(u32)]; 2673f36ea7SAntoine Tenart u32 opad[SHA256_DIGEST_SIZE / sizeof(u32)]; 271b44c5a6SAntoine Ténart }; 281b44c5a6SAntoine Ténart 291b44c5a6SAntoine Ténart struct safexcel_ahash_req { 301b44c5a6SAntoine Ténart bool last_req; 311b44c5a6SAntoine Ténart bool finish; 321b44c5a6SAntoine Ténart bool hmac; 331eb7b403SOfer Heifetz bool needs_inv; 341b44c5a6SAntoine Ténart 35c957f8b3SAntoine Ténart int nents; 36b8592027SOfer Heifetz dma_addr_t result_dma; 37c957f8b3SAntoine Ténart 38b869648cSAntoine Tenart u32 digest; 39b869648cSAntoine Tenart 401b44c5a6SAntoine Ténart u8 state_sz; /* expected sate size, only set once */ 412973633eSAntoine Ténart u32 state[SHA256_DIGEST_SIZE / sizeof(u32)] __aligned(sizeof(u32)); 421b44c5a6SAntoine Ténart 431b44c5a6SAntoine Ténart u64 len; 441b44c5a6SAntoine Ténart u64 processed; 451b44c5a6SAntoine Ténart 461b44c5a6SAntoine Ténart u8 cache[SHA256_BLOCK_SIZE] __aligned(sizeof(u32)); 47cff9a175SAntoine Tenart dma_addr_t cache_dma; 48cff9a175SAntoine Tenart unsigned int cache_sz; 49cff9a175SAntoine Tenart 501b44c5a6SAntoine Ténart u8 cache_next[SHA256_BLOCK_SIZE] __aligned(sizeof(u32)); 511b44c5a6SAntoine Ténart }; 521b44c5a6SAntoine Ténart 531b44c5a6SAntoine Ténart struct safexcel_ahash_export_state { 541b44c5a6SAntoine Ténart u64 len; 551b44c5a6SAntoine Ténart u64 processed; 561b44c5a6SAntoine Ténart 57b869648cSAntoine Tenart u32 digest; 58b869648cSAntoine Tenart 591b44c5a6SAntoine Ténart u32 state[SHA256_DIGEST_SIZE / sizeof(u32)]; 601b44c5a6SAntoine Ténart u8 cache[SHA256_BLOCK_SIZE]; 611b44c5a6SAntoine Ténart }; 621b44c5a6SAntoine Ténart 631b44c5a6SAntoine Ténart static void safexcel_hash_token(struct safexcel_command_desc *cdesc, 641b44c5a6SAntoine Ténart u32 input_length, u32 result_length) 651b44c5a6SAntoine Ténart { 661b44c5a6SAntoine Ténart struct safexcel_token *token = 671b44c5a6SAntoine Ténart (struct safexcel_token *)cdesc->control_data.token; 681b44c5a6SAntoine Ténart 691b44c5a6SAntoine Ténart token[0].opcode = EIP197_TOKEN_OPCODE_DIRECTION; 701b44c5a6SAntoine Ténart token[0].packet_length = input_length; 711b44c5a6SAntoine Ténart token[0].stat = EIP197_TOKEN_STAT_LAST_HASH; 721b44c5a6SAntoine Ténart token[0].instructions = EIP197_TOKEN_INS_TYPE_HASH; 731b44c5a6SAntoine Ténart 741b44c5a6SAntoine Ténart token[1].opcode = EIP197_TOKEN_OPCODE_INSERT; 751b44c5a6SAntoine Ténart token[1].packet_length = result_length; 761b44c5a6SAntoine Ténart token[1].stat = EIP197_TOKEN_STAT_LAST_HASH | 771b44c5a6SAntoine Ténart EIP197_TOKEN_STAT_LAST_PACKET; 781b44c5a6SAntoine Ténart token[1].instructions = EIP197_TOKEN_INS_TYPE_OUTPUT | 791b44c5a6SAntoine Ténart EIP197_TOKEN_INS_INSERT_HASH_DIGEST; 801b44c5a6SAntoine Ténart } 811b44c5a6SAntoine Ténart 821b44c5a6SAntoine Ténart static void safexcel_context_control(struct safexcel_ahash_ctx *ctx, 831b44c5a6SAntoine Ténart struct safexcel_ahash_req *req, 841b44c5a6SAntoine Ténart struct safexcel_command_desc *cdesc, 851b44c5a6SAntoine Ténart unsigned int digestsize, 861b44c5a6SAntoine Ténart unsigned int blocksize) 871b44c5a6SAntoine Ténart { 881b44c5a6SAntoine Ténart int i; 891b44c5a6SAntoine Ténart 901b44c5a6SAntoine Ténart cdesc->control_data.control0 |= CONTEXT_CONTROL_TYPE_HASH_OUT; 911b44c5a6SAntoine Ténart cdesc->control_data.control0 |= ctx->alg; 92b869648cSAntoine Tenart cdesc->control_data.control0 |= req->digest; 931b44c5a6SAntoine Ténart 94b869648cSAntoine Tenart if (req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) { 951b44c5a6SAntoine Ténart if (req->processed) { 961b44c5a6SAntoine Ténart if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA1) 971b44c5a6SAntoine Ténart cdesc->control_data.control0 |= CONTEXT_CONTROL_SIZE(6); 981b44c5a6SAntoine Ténart else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA224 || 991b44c5a6SAntoine Ténart ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA256) 1001b44c5a6SAntoine Ténart cdesc->control_data.control0 |= CONTEXT_CONTROL_SIZE(9); 1011b44c5a6SAntoine Ténart 1021b44c5a6SAntoine Ténart cdesc->control_data.control1 |= CONTEXT_CONTROL_DIGEST_CNT; 1031b44c5a6SAntoine Ténart } else { 1041b44c5a6SAntoine Ténart cdesc->control_data.control0 |= CONTEXT_CONTROL_RESTART_HASH; 1051b44c5a6SAntoine Ténart } 1061b44c5a6SAntoine Ténart 1071b44c5a6SAntoine Ténart if (!req->finish) 1081b44c5a6SAntoine Ténart cdesc->control_data.control0 |= CONTEXT_CONTROL_NO_FINISH_HASH; 1091b44c5a6SAntoine Ténart 1101b44c5a6SAntoine Ténart /* 1111b44c5a6SAntoine Ténart * Copy the input digest if needed, and setup the context 1121b44c5a6SAntoine Ténart * fields. Do this now as we need it to setup the first command 1131b44c5a6SAntoine Ténart * descriptor. 1141b44c5a6SAntoine Ténart */ 1151b44c5a6SAntoine Ténart if (req->processed) { 1161b44c5a6SAntoine Ténart for (i = 0; i < digestsize / sizeof(u32); i++) 1171b44c5a6SAntoine Ténart ctx->base.ctxr->data[i] = cpu_to_le32(req->state[i]); 1181b44c5a6SAntoine Ténart 1191b44c5a6SAntoine Ténart if (req->finish) 1201b44c5a6SAntoine Ténart ctx->base.ctxr->data[i] = cpu_to_le32(req->processed / blocksize); 1211b44c5a6SAntoine Ténart } 122b869648cSAntoine Tenart } else if (req->digest == CONTEXT_CONTROL_DIGEST_HMAC) { 1234505bb02SAntoine Tenart cdesc->control_data.control0 |= CONTEXT_CONTROL_SIZE(2 * req->state_sz / sizeof(u32)); 1241b44c5a6SAntoine Ténart 1254505bb02SAntoine Tenart memcpy(ctx->base.ctxr->data, ctx->ipad, req->state_sz); 1264505bb02SAntoine Tenart memcpy(ctx->base.ctxr->data + req->state_sz / sizeof(u32), 1274505bb02SAntoine Tenart ctx->opad, req->state_sz); 1281b44c5a6SAntoine Ténart } 1291b44c5a6SAntoine Ténart } 1301b44c5a6SAntoine Ténart 1311eb7b403SOfer Heifetz static int safexcel_handle_req_result(struct safexcel_crypto_priv *priv, int ring, 1321b44c5a6SAntoine Ténart struct crypto_async_request *async, 1331b44c5a6SAntoine Ténart bool *should_complete, int *ret) 1341b44c5a6SAntoine Ténart { 1351b44c5a6SAntoine Ténart struct safexcel_result_desc *rdesc; 1361b44c5a6SAntoine Ténart struct ahash_request *areq = ahash_request_cast(async); 1371b44c5a6SAntoine Ténart struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); 1381b44c5a6SAntoine Ténart struct safexcel_ahash_req *sreq = ahash_request_ctx(areq); 1392973633eSAntoine Ténart int cache_len; 1401b44c5a6SAntoine Ténart 1411b44c5a6SAntoine Ténart *ret = 0; 1421b44c5a6SAntoine Ténart 1431b44c5a6SAntoine Ténart spin_lock_bh(&priv->ring[ring].egress_lock); 1441b44c5a6SAntoine Ténart rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr); 1451b44c5a6SAntoine Ténart if (IS_ERR(rdesc)) { 1461b44c5a6SAntoine Ténart dev_err(priv->dev, 1471b44c5a6SAntoine Ténart "hash: result: could not retrieve the result descriptor\n"); 1481b44c5a6SAntoine Ténart *ret = PTR_ERR(rdesc); 149bdfd1909SAntoine Tenart } else { 150bdfd1909SAntoine Tenart *ret = safexcel_rdesc_check_errors(priv, rdesc); 1511b44c5a6SAntoine Ténart } 1521b44c5a6SAntoine Ténart 1531b44c5a6SAntoine Ténart safexcel_complete(priv, ring); 1541b44c5a6SAntoine Ténart spin_unlock_bh(&priv->ring[ring].egress_lock); 1551b44c5a6SAntoine Ténart 156c957f8b3SAntoine Ténart if (sreq->nents) { 157c957f8b3SAntoine Ténart dma_unmap_sg(priv->dev, areq->src, sreq->nents, DMA_TO_DEVICE); 158c957f8b3SAntoine Ténart sreq->nents = 0; 159c957f8b3SAntoine Ténart } 1601b44c5a6SAntoine Ténart 161b8592027SOfer Heifetz if (sreq->result_dma) { 162b8592027SOfer Heifetz dma_unmap_single(priv->dev, sreq->result_dma, sreq->state_sz, 163b8592027SOfer Heifetz DMA_FROM_DEVICE); 164b8592027SOfer Heifetz sreq->result_dma = 0; 165b8592027SOfer Heifetz } 166b8592027SOfer Heifetz 167cff9a175SAntoine Tenart if (sreq->cache_dma) { 168cff9a175SAntoine Tenart dma_unmap_single(priv->dev, sreq->cache_dma, sreq->cache_sz, 169cff9a175SAntoine Tenart DMA_TO_DEVICE); 170cff9a175SAntoine Tenart sreq->cache_dma = 0; 171cff9a175SAntoine Tenart } 1721b44c5a6SAntoine Ténart 173b89a8159SAntoine Tenart if (sreq->finish) 174b89a8159SAntoine Tenart memcpy(areq->result, sreq->state, 175b89a8159SAntoine Tenart crypto_ahash_digestsize(ahash)); 176b89a8159SAntoine Tenart 1771b44c5a6SAntoine Ténart cache_len = sreq->len - sreq->processed; 1781b44c5a6SAntoine Ténart if (cache_len) 1791b44c5a6SAntoine Ténart memcpy(sreq->cache, sreq->cache_next, cache_len); 1801b44c5a6SAntoine Ténart 1811b44c5a6SAntoine Ténart *should_complete = true; 1821b44c5a6SAntoine Ténart 1831b44c5a6SAntoine Ténart return 1; 1841b44c5a6SAntoine Ténart } 1851b44c5a6SAntoine Ténart 1861eb7b403SOfer Heifetz static int safexcel_ahash_send_req(struct crypto_async_request *async, int ring, 1871eb7b403SOfer Heifetz struct safexcel_request *request, 1881eb7b403SOfer Heifetz int *commands, int *results) 1891b44c5a6SAntoine Ténart { 1901b44c5a6SAntoine Ténart struct ahash_request *areq = ahash_request_cast(async); 1911b44c5a6SAntoine Ténart struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); 1921b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 1931b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 1941b44c5a6SAntoine Ténart struct safexcel_crypto_priv *priv = ctx->priv; 1951b44c5a6SAntoine Ténart struct safexcel_command_desc *cdesc, *first_cdesc = NULL; 1961b44c5a6SAntoine Ténart struct safexcel_result_desc *rdesc; 1971b44c5a6SAntoine Ténart struct scatterlist *sg; 198c957f8b3SAntoine Ténart int i, queued, len, cache_len, extra, n_cdesc = 0, ret = 0; 1991b44c5a6SAntoine Ténart 2001b44c5a6SAntoine Ténart queued = len = req->len - req->processed; 201666a9c70SAntoine Tenart if (queued <= crypto_ahash_blocksize(ahash)) 2021b44c5a6SAntoine Ténart cache_len = queued; 2031b44c5a6SAntoine Ténart else 2041b44c5a6SAntoine Ténart cache_len = queued - areq->nbytes; 2051b44c5a6SAntoine Ténart 206809778e0SAntoine Ténart if (!req->last_req) { 207809778e0SAntoine Ténart /* If this is not the last request and the queued data does not 208809778e0SAntoine Ténart * fit into full blocks, cache it for the next send() call. 2091b44c5a6SAntoine Ténart */ 2101b44c5a6SAntoine Ténart extra = queued & (crypto_ahash_blocksize(ahash) - 1); 211809778e0SAntoine Ténart if (!extra) 212809778e0SAntoine Ténart /* If this is not the last request and the queued data 213809778e0SAntoine Ténart * is a multiple of a block, cache the last one for now. 214809778e0SAntoine Ténart */ 215c1a8fa6eSAntoine Tenart extra = crypto_ahash_blocksize(ahash); 216809778e0SAntoine Ténart 217809778e0SAntoine Ténart if (extra) { 2181b44c5a6SAntoine Ténart sg_pcopy_to_buffer(areq->src, sg_nents(areq->src), 219809778e0SAntoine Ténart req->cache_next, extra, 220809778e0SAntoine Ténart areq->nbytes - extra); 2211b44c5a6SAntoine Ténart 2221b44c5a6SAntoine Ténart queued -= extra; 2231b44c5a6SAntoine Ténart len -= extra; 224809778e0SAntoine Ténart 225809778e0SAntoine Ténart if (!queued) { 226809778e0SAntoine Ténart *commands = 0; 227809778e0SAntoine Ténart *results = 0; 228809778e0SAntoine Ténart return 0; 229809778e0SAntoine Ténart } 230809778e0SAntoine Ténart } 2311b44c5a6SAntoine Ténart } 2321b44c5a6SAntoine Ténart 2331b44c5a6SAntoine Ténart spin_lock_bh(&priv->ring[ring].egress_lock); 2341b44c5a6SAntoine Ténart 2351b44c5a6SAntoine Ténart /* Add a command descriptor for the cached data, if any */ 2361b44c5a6SAntoine Ténart if (cache_len) { 237cff9a175SAntoine Tenart req->cache_dma = dma_map_single(priv->dev, req->cache, 2381b44c5a6SAntoine Ténart cache_len, DMA_TO_DEVICE); 239efa94457Sweiyongjun \(A\) if (dma_mapping_error(priv->dev, req->cache_dma)) { 240efa94457Sweiyongjun \(A\) spin_unlock_bh(&priv->ring[ring].egress_lock); 241cff9a175SAntoine Tenart return -EINVAL; 242efa94457Sweiyongjun \(A\) } 2431b44c5a6SAntoine Ténart 244cff9a175SAntoine Tenart req->cache_sz = cache_len; 2451b44c5a6SAntoine Ténart first_cdesc = safexcel_add_cdesc(priv, ring, 1, 2461b44c5a6SAntoine Ténart (cache_len == len), 247cff9a175SAntoine Tenart req->cache_dma, cache_len, len, 2481b44c5a6SAntoine Ténart ctx->base.ctxr_dma); 2491b44c5a6SAntoine Ténart if (IS_ERR(first_cdesc)) { 2501b44c5a6SAntoine Ténart ret = PTR_ERR(first_cdesc); 2511b44c5a6SAntoine Ténart goto unmap_cache; 2521b44c5a6SAntoine Ténart } 2531b44c5a6SAntoine Ténart n_cdesc++; 2541b44c5a6SAntoine Ténart 2551b44c5a6SAntoine Ténart queued -= cache_len; 2561b44c5a6SAntoine Ténart if (!queued) 2571b44c5a6SAntoine Ténart goto send_command; 2581b44c5a6SAntoine Ténart } 2591b44c5a6SAntoine Ténart 2601b44c5a6SAntoine Ténart /* Now handle the current ahash request buffer(s) */ 261c957f8b3SAntoine Ténart req->nents = dma_map_sg(priv->dev, areq->src, 2621b44c5a6SAntoine Ténart sg_nents_for_len(areq->src, areq->nbytes), 2631b44c5a6SAntoine Ténart DMA_TO_DEVICE); 264c957f8b3SAntoine Ténart if (!req->nents) { 2651b44c5a6SAntoine Ténart ret = -ENOMEM; 2661b44c5a6SAntoine Ténart goto cdesc_rollback; 2671b44c5a6SAntoine Ténart } 2681b44c5a6SAntoine Ténart 269c957f8b3SAntoine Ténart for_each_sg(areq->src, sg, req->nents, i) { 2701b44c5a6SAntoine Ténart int sglen = sg_dma_len(sg); 2711b44c5a6SAntoine Ténart 2721b44c5a6SAntoine Ténart /* Do not overflow the request */ 2731b44c5a6SAntoine Ténart if (queued - sglen < 0) 2741b44c5a6SAntoine Ténart sglen = queued; 2751b44c5a6SAntoine Ténart 2761b44c5a6SAntoine Ténart cdesc = safexcel_add_cdesc(priv, ring, !n_cdesc, 2771b44c5a6SAntoine Ténart !(queued - sglen), sg_dma_address(sg), 2781b44c5a6SAntoine Ténart sglen, len, ctx->base.ctxr_dma); 2791b44c5a6SAntoine Ténart if (IS_ERR(cdesc)) { 2801b44c5a6SAntoine Ténart ret = PTR_ERR(cdesc); 28157433b58SAntoine Tenart goto unmap_sg; 2821b44c5a6SAntoine Ténart } 2831b44c5a6SAntoine Ténart n_cdesc++; 2841b44c5a6SAntoine Ténart 2851b44c5a6SAntoine Ténart if (n_cdesc == 1) 2861b44c5a6SAntoine Ténart first_cdesc = cdesc; 2871b44c5a6SAntoine Ténart 2881b44c5a6SAntoine Ténart queued -= sglen; 2891b44c5a6SAntoine Ténart if (!queued) 2901b44c5a6SAntoine Ténart break; 2911b44c5a6SAntoine Ténart } 2921b44c5a6SAntoine Ténart 2931b44c5a6SAntoine Ténart send_command: 2941b44c5a6SAntoine Ténart /* Setup the context options */ 2951b44c5a6SAntoine Ténart safexcel_context_control(ctx, req, first_cdesc, req->state_sz, 2961b44c5a6SAntoine Ténart crypto_ahash_blocksize(ahash)); 2971b44c5a6SAntoine Ténart 2981b44c5a6SAntoine Ténart /* Add the token */ 2991b44c5a6SAntoine Ténart safexcel_hash_token(first_cdesc, len, req->state_sz); 3001b44c5a6SAntoine Ténart 301b8592027SOfer Heifetz req->result_dma = dma_map_single(priv->dev, req->state, req->state_sz, 302b8592027SOfer Heifetz DMA_FROM_DEVICE); 303b8592027SOfer Heifetz if (dma_mapping_error(priv->dev, req->result_dma)) { 3041b44c5a6SAntoine Ténart ret = -EINVAL; 30557433b58SAntoine Tenart goto unmap_sg; 3061b44c5a6SAntoine Ténart } 3071b44c5a6SAntoine Ténart 3081b44c5a6SAntoine Ténart /* Add a result descriptor */ 309b8592027SOfer Heifetz rdesc = safexcel_add_rdesc(priv, ring, 1, 1, req->result_dma, 3101b44c5a6SAntoine Ténart req->state_sz); 3111b44c5a6SAntoine Ténart if (IS_ERR(rdesc)) { 3121b44c5a6SAntoine Ténart ret = PTR_ERR(rdesc); 31357240a78SAntoine Tenart goto unmap_result; 3141b44c5a6SAntoine Ténart } 3151b44c5a6SAntoine Ténart 3161b44c5a6SAntoine Ténart spin_unlock_bh(&priv->ring[ring].egress_lock); 3171b44c5a6SAntoine Ténart 31897858434SAntoine Ténart req->processed += len; 31997858434SAntoine Ténart request->req = &areq->base; 32097858434SAntoine Ténart 3211b44c5a6SAntoine Ténart *commands = n_cdesc; 3221b44c5a6SAntoine Ténart *results = 1; 3231b44c5a6SAntoine Ténart return 0; 3241b44c5a6SAntoine Ténart 32557240a78SAntoine Tenart unmap_result: 32657433b58SAntoine Tenart dma_unmap_single(priv->dev, req->result_dma, req->state_sz, 32757433b58SAntoine Tenart DMA_FROM_DEVICE); 32857433b58SAntoine Tenart unmap_sg: 32957240a78SAntoine Tenart dma_unmap_sg(priv->dev, areq->src, req->nents, DMA_TO_DEVICE); 3301b44c5a6SAntoine Ténart cdesc_rollback: 3311b44c5a6SAntoine Ténart for (i = 0; i < n_cdesc; i++) 3321b44c5a6SAntoine Ténart safexcel_ring_rollback_wptr(priv, &priv->ring[ring].cdr); 3331b44c5a6SAntoine Ténart unmap_cache: 334cff9a175SAntoine Tenart if (req->cache_dma) { 335cff9a175SAntoine Tenart dma_unmap_single(priv->dev, req->cache_dma, req->cache_sz, 336cff9a175SAntoine Tenart DMA_TO_DEVICE); 337cff9a175SAntoine Tenart req->cache_sz = 0; 3381b44c5a6SAntoine Ténart } 3391b44c5a6SAntoine Ténart 3401b44c5a6SAntoine Ténart spin_unlock_bh(&priv->ring[ring].egress_lock); 3411b44c5a6SAntoine Ténart return ret; 3421b44c5a6SAntoine Ténart } 3431b44c5a6SAntoine Ténart 3441b44c5a6SAntoine Ténart static inline bool safexcel_ahash_needs_inv_get(struct ahash_request *areq) 3451b44c5a6SAntoine Ténart { 3461b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 3471b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 3481b44c5a6SAntoine Ténart struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); 3491b44c5a6SAntoine Ténart unsigned int state_w_sz = req->state_sz / sizeof(u32); 3501b44c5a6SAntoine Ténart int i; 3511b44c5a6SAntoine Ténart 3521b44c5a6SAntoine Ténart for (i = 0; i < state_w_sz; i++) 3531b44c5a6SAntoine Ténart if (ctx->base.ctxr->data[i] != cpu_to_le32(req->state[i])) 3541b44c5a6SAntoine Ténart return true; 3551b44c5a6SAntoine Ténart 3561b44c5a6SAntoine Ténart if (ctx->base.ctxr->data[state_w_sz] != 3571b44c5a6SAntoine Ténart cpu_to_le32(req->processed / crypto_ahash_blocksize(ahash))) 3581b44c5a6SAntoine Ténart return true; 3591b44c5a6SAntoine Ténart 3601b44c5a6SAntoine Ténart return false; 3611b44c5a6SAntoine Ténart } 3621b44c5a6SAntoine Ténart 3631b44c5a6SAntoine Ténart static int safexcel_handle_inv_result(struct safexcel_crypto_priv *priv, 3641b44c5a6SAntoine Ténart int ring, 3651b44c5a6SAntoine Ténart struct crypto_async_request *async, 3661b44c5a6SAntoine Ténart bool *should_complete, int *ret) 3671b44c5a6SAntoine Ténart { 3681b44c5a6SAntoine Ténart struct safexcel_result_desc *rdesc; 3691b44c5a6SAntoine Ténart struct ahash_request *areq = ahash_request_cast(async); 3701b44c5a6SAntoine Ténart struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); 3711b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(ahash); 3721b44c5a6SAntoine Ténart int enq_ret; 3731b44c5a6SAntoine Ténart 3741b44c5a6SAntoine Ténart *ret = 0; 3751b44c5a6SAntoine Ténart 3761b44c5a6SAntoine Ténart spin_lock_bh(&priv->ring[ring].egress_lock); 3771b44c5a6SAntoine Ténart rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr); 3781b44c5a6SAntoine Ténart if (IS_ERR(rdesc)) { 3791b44c5a6SAntoine Ténart dev_err(priv->dev, 3801b44c5a6SAntoine Ténart "hash: invalidate: could not retrieve the result descriptor\n"); 3811b44c5a6SAntoine Ténart *ret = PTR_ERR(rdesc); 3821b44c5a6SAntoine Ténart } else if (rdesc->result_data.error_code) { 3831b44c5a6SAntoine Ténart dev_err(priv->dev, 3841b44c5a6SAntoine Ténart "hash: invalidate: result descriptor error (%d)\n", 3851b44c5a6SAntoine Ténart rdesc->result_data.error_code); 3861b44c5a6SAntoine Ténart *ret = -EINVAL; 3871b44c5a6SAntoine Ténart } 3881b44c5a6SAntoine Ténart 3891b44c5a6SAntoine Ténart safexcel_complete(priv, ring); 3901b44c5a6SAntoine Ténart spin_unlock_bh(&priv->ring[ring].egress_lock); 3911b44c5a6SAntoine Ténart 3921b44c5a6SAntoine Ténart if (ctx->base.exit_inv) { 3931b44c5a6SAntoine Ténart dma_pool_free(priv->context_pool, ctx->base.ctxr, 3941b44c5a6SAntoine Ténart ctx->base.ctxr_dma); 3951b44c5a6SAntoine Ténart 3961b44c5a6SAntoine Ténart *should_complete = true; 3971b44c5a6SAntoine Ténart return 1; 3981b44c5a6SAntoine Ténart } 3991b44c5a6SAntoine Ténart 40086671abbSAntoine Ténart ring = safexcel_select_ring(priv); 40186671abbSAntoine Ténart ctx->base.ring = ring; 4021b44c5a6SAntoine Ténart 40386671abbSAntoine Ténart spin_lock_bh(&priv->ring[ring].queue_lock); 40486671abbSAntoine Ténart enq_ret = crypto_enqueue_request(&priv->ring[ring].queue, async); 40586671abbSAntoine Ténart spin_unlock_bh(&priv->ring[ring].queue_lock); 4061b44c5a6SAntoine Ténart 4071b44c5a6SAntoine Ténart if (enq_ret != -EINPROGRESS) 4081b44c5a6SAntoine Ténart *ret = enq_ret; 4091b44c5a6SAntoine Ténart 4108472e778SAntoine Ténart queue_work(priv->ring[ring].workqueue, 4118472e778SAntoine Ténart &priv->ring[ring].work_data.work); 41286671abbSAntoine Ténart 4131b44c5a6SAntoine Ténart *should_complete = false; 4141b44c5a6SAntoine Ténart 4151b44c5a6SAntoine Ténart return 1; 4161b44c5a6SAntoine Ténart } 4171b44c5a6SAntoine Ténart 4181eb7b403SOfer Heifetz static int safexcel_handle_result(struct safexcel_crypto_priv *priv, int ring, 4191eb7b403SOfer Heifetz struct crypto_async_request *async, 4201eb7b403SOfer Heifetz bool *should_complete, int *ret) 4211eb7b403SOfer Heifetz { 4221eb7b403SOfer Heifetz struct ahash_request *areq = ahash_request_cast(async); 4231eb7b403SOfer Heifetz struct safexcel_ahash_req *req = ahash_request_ctx(areq); 4241eb7b403SOfer Heifetz int err; 4251eb7b403SOfer Heifetz 426871df319SAntoine Ténart BUG_ON(priv->version == EIP97 && req->needs_inv); 427871df319SAntoine Ténart 4281eb7b403SOfer Heifetz if (req->needs_inv) { 4291eb7b403SOfer Heifetz req->needs_inv = false; 4301eb7b403SOfer Heifetz err = safexcel_handle_inv_result(priv, ring, async, 4311eb7b403SOfer Heifetz should_complete, ret); 4321eb7b403SOfer Heifetz } else { 4331eb7b403SOfer Heifetz err = safexcel_handle_req_result(priv, ring, async, 4341eb7b403SOfer Heifetz should_complete, ret); 4351eb7b403SOfer Heifetz } 4361eb7b403SOfer Heifetz 4371eb7b403SOfer Heifetz return err; 4381eb7b403SOfer Heifetz } 4391eb7b403SOfer Heifetz 4401b44c5a6SAntoine Ténart static int safexcel_ahash_send_inv(struct crypto_async_request *async, 4411b44c5a6SAntoine Ténart int ring, struct safexcel_request *request, 4421b44c5a6SAntoine Ténart int *commands, int *results) 4431b44c5a6SAntoine Ténart { 4441b44c5a6SAntoine Ténart struct ahash_request *areq = ahash_request_cast(async); 4451b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 4461b44c5a6SAntoine Ténart int ret; 4471b44c5a6SAntoine Ténart 4485290ad6eSOfer Heifetz ret = safexcel_invalidate_cache(async, ctx->priv, 4491b44c5a6SAntoine Ténart ctx->base.ctxr_dma, ring, request); 4501b44c5a6SAntoine Ténart if (unlikely(ret)) 4511b44c5a6SAntoine Ténart return ret; 4521b44c5a6SAntoine Ténart 4531b44c5a6SAntoine Ténart *commands = 1; 4541b44c5a6SAntoine Ténart *results = 1; 4551b44c5a6SAntoine Ténart 4561b44c5a6SAntoine Ténart return 0; 4571b44c5a6SAntoine Ténart } 4581b44c5a6SAntoine Ténart 4591eb7b403SOfer Heifetz static int safexcel_ahash_send(struct crypto_async_request *async, 4601eb7b403SOfer Heifetz int ring, struct safexcel_request *request, 4611eb7b403SOfer Heifetz int *commands, int *results) 4621eb7b403SOfer Heifetz { 4631eb7b403SOfer Heifetz struct ahash_request *areq = ahash_request_cast(async); 4641eb7b403SOfer Heifetz struct safexcel_ahash_req *req = ahash_request_ctx(areq); 4651eb7b403SOfer Heifetz int ret; 4661eb7b403SOfer Heifetz 4671eb7b403SOfer Heifetz if (req->needs_inv) 4681eb7b403SOfer Heifetz ret = safexcel_ahash_send_inv(async, ring, request, 4691eb7b403SOfer Heifetz commands, results); 4701eb7b403SOfer Heifetz else 4711eb7b403SOfer Heifetz ret = safexcel_ahash_send_req(async, ring, request, 4721eb7b403SOfer Heifetz commands, results); 4731eb7b403SOfer Heifetz return ret; 4741eb7b403SOfer Heifetz } 4751eb7b403SOfer Heifetz 4761b44c5a6SAntoine Ténart static int safexcel_ahash_exit_inv(struct crypto_tfm *tfm) 4771b44c5a6SAntoine Ténart { 4781b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 4791b44c5a6SAntoine Ténart struct safexcel_crypto_priv *priv = ctx->priv; 48061824806SAntoine Tenart EIP197_REQUEST_ON_STACK(req, ahash, EIP197_AHASH_REQ_SIZE); 4817cad2fabSAntoine Ténart struct safexcel_ahash_req *rctx = ahash_request_ctx(req); 4823e1166b9SArnd Bergmann struct safexcel_inv_result result = {}; 48386671abbSAntoine Ténart int ring = ctx->base.ring; 4841b44c5a6SAntoine Ténart 4857cad2fabSAntoine Ténart memset(req, 0, sizeof(struct ahash_request)); 4861b44c5a6SAntoine Ténart 4871b44c5a6SAntoine Ténart /* create invalidation request */ 4881b44c5a6SAntoine Ténart init_completion(&result.completion); 4897cad2fabSAntoine Ténart ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, 4901b44c5a6SAntoine Ténart safexcel_inv_complete, &result); 4911b44c5a6SAntoine Ténart 4927cad2fabSAntoine Ténart ahash_request_set_tfm(req, __crypto_ahash_cast(tfm)); 4937cad2fabSAntoine Ténart ctx = crypto_tfm_ctx(req->base.tfm); 4941b44c5a6SAntoine Ténart ctx->base.exit_inv = true; 4951eb7b403SOfer Heifetz rctx->needs_inv = true; 4961b44c5a6SAntoine Ténart 49786671abbSAntoine Ténart spin_lock_bh(&priv->ring[ring].queue_lock); 4987cad2fabSAntoine Ténart crypto_enqueue_request(&priv->ring[ring].queue, &req->base); 49986671abbSAntoine Ténart spin_unlock_bh(&priv->ring[ring].queue_lock); 5001b44c5a6SAntoine Ténart 5018472e778SAntoine Ténart queue_work(priv->ring[ring].workqueue, 5028472e778SAntoine Ténart &priv->ring[ring].work_data.work); 5031b44c5a6SAntoine Ténart 504b7007dbcSAntoine Tenart wait_for_completion(&result.completion); 5051b44c5a6SAntoine Ténart 5061b44c5a6SAntoine Ténart if (result.error) { 5071b44c5a6SAntoine Ténart dev_warn(priv->dev, "hash: completion error (%d)\n", 5081b44c5a6SAntoine Ténart result.error); 5091b44c5a6SAntoine Ténart return result.error; 5101b44c5a6SAntoine Ténart } 5111b44c5a6SAntoine Ténart 5121b44c5a6SAntoine Ténart return 0; 5131b44c5a6SAntoine Ténart } 5141b44c5a6SAntoine Ténart 515cc75f5ceSAntoine Ténart /* safexcel_ahash_cache: cache data until at least one request can be sent to 516cc75f5ceSAntoine Ténart * the engine, aka. when there is at least 1 block size in the pipe. 517cc75f5ceSAntoine Ténart */ 5181b44c5a6SAntoine Ténart static int safexcel_ahash_cache(struct ahash_request *areq) 5191b44c5a6SAntoine Ténart { 5201b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 5211b44c5a6SAntoine Ténart struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); 5221b44c5a6SAntoine Ténart int queued, cache_len; 5231b44c5a6SAntoine Ténart 524cc75f5ceSAntoine Ténart /* cache_len: everyting accepted by the driver but not sent yet, 525cc75f5ceSAntoine Ténart * tot sz handled by update() - last req sz - tot sz handled by send() 526cc75f5ceSAntoine Ténart */ 5271b44c5a6SAntoine Ténart cache_len = req->len - areq->nbytes - req->processed; 528cc75f5ceSAntoine Ténart /* queued: everything accepted by the driver which will be handled by 529cc75f5ceSAntoine Ténart * the next send() calls. 530cc75f5ceSAntoine Ténart * tot sz handled by update() - tot sz handled by send() 531cc75f5ceSAntoine Ténart */ 5321b44c5a6SAntoine Ténart queued = req->len - req->processed; 5331b44c5a6SAntoine Ténart 5341b44c5a6SAntoine Ténart /* 5351b44c5a6SAntoine Ténart * In case there isn't enough bytes to proceed (less than a 5361b44c5a6SAntoine Ténart * block size), cache the data until we have enough. 5371b44c5a6SAntoine Ténart */ 5381b44c5a6SAntoine Ténart if (cache_len + areq->nbytes <= crypto_ahash_blocksize(ahash)) { 5391b44c5a6SAntoine Ténart sg_pcopy_to_buffer(areq->src, sg_nents(areq->src), 5401b44c5a6SAntoine Ténart req->cache + cache_len, 5411b44c5a6SAntoine Ténart areq->nbytes, 0); 5421b44c5a6SAntoine Ténart return areq->nbytes; 5431b44c5a6SAntoine Ténart } 5441b44c5a6SAntoine Ténart 545dfbcc08fSAntoine Ténart /* We couldn't cache all the data */ 5461b44c5a6SAntoine Ténart return -E2BIG; 5471b44c5a6SAntoine Ténart } 5481b44c5a6SAntoine Ténart 5491b44c5a6SAntoine Ténart static int safexcel_ahash_enqueue(struct ahash_request *areq) 5501b44c5a6SAntoine Ténart { 5511b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 5521b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 5531b44c5a6SAntoine Ténart struct safexcel_crypto_priv *priv = ctx->priv; 55486671abbSAntoine Ténart int ret, ring; 5551b44c5a6SAntoine Ténart 5561eb7b403SOfer Heifetz req->needs_inv = false; 5571b44c5a6SAntoine Ténart 558c4daf4ccSOfer Heifetz if (ctx->base.ctxr) { 559871df319SAntoine Ténart if (priv->version == EIP197 && 560871df319SAntoine Ténart !ctx->base.needs_inv && req->processed && 561b869648cSAntoine Tenart req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) 562c4daf4ccSOfer Heifetz /* We're still setting needs_inv here, even though it is 563c4daf4ccSOfer Heifetz * cleared right away, because the needs_inv flag can be 564c4daf4ccSOfer Heifetz * set in other functions and we want to keep the same 565c4daf4ccSOfer Heifetz * logic. 566c4daf4ccSOfer Heifetz */ 5671b44c5a6SAntoine Ténart ctx->base.needs_inv = safexcel_ahash_needs_inv_get(areq); 5681b44c5a6SAntoine Ténart 5691eb7b403SOfer Heifetz if (ctx->base.needs_inv) { 5701eb7b403SOfer Heifetz ctx->base.needs_inv = false; 5711eb7b403SOfer Heifetz req->needs_inv = true; 5721eb7b403SOfer Heifetz } 5731b44c5a6SAntoine Ténart } else { 5741b44c5a6SAntoine Ténart ctx->base.ring = safexcel_select_ring(priv); 5751b44c5a6SAntoine Ténart ctx->base.ctxr = dma_pool_zalloc(priv->context_pool, 5761b44c5a6SAntoine Ténart EIP197_GFP_FLAGS(areq->base), 5771b44c5a6SAntoine Ténart &ctx->base.ctxr_dma); 5781b44c5a6SAntoine Ténart if (!ctx->base.ctxr) 5791b44c5a6SAntoine Ténart return -ENOMEM; 5801b44c5a6SAntoine Ténart } 5811b44c5a6SAntoine Ténart 58286671abbSAntoine Ténart ring = ctx->base.ring; 5831b44c5a6SAntoine Ténart 58486671abbSAntoine Ténart spin_lock_bh(&priv->ring[ring].queue_lock); 58586671abbSAntoine Ténart ret = crypto_enqueue_request(&priv->ring[ring].queue, &areq->base); 58686671abbSAntoine Ténart spin_unlock_bh(&priv->ring[ring].queue_lock); 58786671abbSAntoine Ténart 5888472e778SAntoine Ténart queue_work(priv->ring[ring].workqueue, 5898472e778SAntoine Ténart &priv->ring[ring].work_data.work); 5901b44c5a6SAntoine Ténart 5911b44c5a6SAntoine Ténart return ret; 5921b44c5a6SAntoine Ténart } 5931b44c5a6SAntoine Ténart 5941b44c5a6SAntoine Ténart static int safexcel_ahash_update(struct ahash_request *areq) 5951b44c5a6SAntoine Ténart { 5961b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 5971b44c5a6SAntoine Ténart struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); 5981b44c5a6SAntoine Ténart 5991b44c5a6SAntoine Ténart /* If the request is 0 length, do nothing */ 6001b44c5a6SAntoine Ténart if (!areq->nbytes) 6011b44c5a6SAntoine Ténart return 0; 6021b44c5a6SAntoine Ténart 6031b44c5a6SAntoine Ténart req->len += areq->nbytes; 6041b44c5a6SAntoine Ténart 6051b44c5a6SAntoine Ténart safexcel_ahash_cache(areq); 6061b44c5a6SAntoine Ténart 6071b44c5a6SAntoine Ténart /* 6081b44c5a6SAntoine Ténart * We're not doing partial updates when performing an hmac request. 6091b44c5a6SAntoine Ténart * Everything will be handled by the final() call. 6101b44c5a6SAntoine Ténart */ 611b869648cSAntoine Tenart if (req->digest == CONTEXT_CONTROL_DIGEST_HMAC) 6121b44c5a6SAntoine Ténart return 0; 6131b44c5a6SAntoine Ténart 6141b44c5a6SAntoine Ténart if (req->hmac) 6151b44c5a6SAntoine Ténart return safexcel_ahash_enqueue(areq); 6161b44c5a6SAntoine Ténart 6171b44c5a6SAntoine Ténart if (!req->last_req && 6181b44c5a6SAntoine Ténart req->len - req->processed > crypto_ahash_blocksize(ahash)) 6191b44c5a6SAntoine Ténart return safexcel_ahash_enqueue(areq); 6201b44c5a6SAntoine Ténart 6211b44c5a6SAntoine Ténart return 0; 6221b44c5a6SAntoine Ténart } 6231b44c5a6SAntoine Ténart 6241b44c5a6SAntoine Ténart static int safexcel_ahash_final(struct ahash_request *areq) 6251b44c5a6SAntoine Ténart { 6261b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 6271b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 6281b44c5a6SAntoine Ténart 6291b44c5a6SAntoine Ténart req->last_req = true; 6301b44c5a6SAntoine Ténart req->finish = true; 6311b44c5a6SAntoine Ténart 6321b44c5a6SAntoine Ténart /* If we have an overall 0 length request */ 6331b44c5a6SAntoine Ténart if (!(req->len + areq->nbytes)) { 6341b44c5a6SAntoine Ténart if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA1) 6351b44c5a6SAntoine Ténart memcpy(areq->result, sha1_zero_message_hash, 6361b44c5a6SAntoine Ténart SHA1_DIGEST_SIZE); 6371b44c5a6SAntoine Ténart else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA224) 6381b44c5a6SAntoine Ténart memcpy(areq->result, sha224_zero_message_hash, 6391b44c5a6SAntoine Ténart SHA224_DIGEST_SIZE); 6401b44c5a6SAntoine Ténart else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA256) 6411b44c5a6SAntoine Ténart memcpy(areq->result, sha256_zero_message_hash, 6421b44c5a6SAntoine Ténart SHA256_DIGEST_SIZE); 6431b44c5a6SAntoine Ténart 6441b44c5a6SAntoine Ténart return 0; 6451b44c5a6SAntoine Ténart } 6461b44c5a6SAntoine Ténart 6471b44c5a6SAntoine Ténart return safexcel_ahash_enqueue(areq); 6481b44c5a6SAntoine Ténart } 6491b44c5a6SAntoine Ténart 6501b44c5a6SAntoine Ténart static int safexcel_ahash_finup(struct ahash_request *areq) 6511b44c5a6SAntoine Ténart { 6521b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 6531b44c5a6SAntoine Ténart 6541b44c5a6SAntoine Ténart req->last_req = true; 6551b44c5a6SAntoine Ténart req->finish = true; 6561b44c5a6SAntoine Ténart 6571b44c5a6SAntoine Ténart safexcel_ahash_update(areq); 6581b44c5a6SAntoine Ténart return safexcel_ahash_final(areq); 6591b44c5a6SAntoine Ténart } 6601b44c5a6SAntoine Ténart 6611b44c5a6SAntoine Ténart static int safexcel_ahash_export(struct ahash_request *areq, void *out) 6621b44c5a6SAntoine Ténart { 6631b44c5a6SAntoine Ténart struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); 6641b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 6651b44c5a6SAntoine Ténart struct safexcel_ahash_export_state *export = out; 6661b44c5a6SAntoine Ténart 6671b44c5a6SAntoine Ténart export->len = req->len; 6681b44c5a6SAntoine Ténart export->processed = req->processed; 6691b44c5a6SAntoine Ténart 670b869648cSAntoine Tenart export->digest = req->digest; 671b869648cSAntoine Tenart 6721b44c5a6SAntoine Ténart memcpy(export->state, req->state, req->state_sz); 6731b44c5a6SAntoine Ténart memcpy(export->cache, req->cache, crypto_ahash_blocksize(ahash)); 6741b44c5a6SAntoine Ténart 6751b44c5a6SAntoine Ténart return 0; 6761b44c5a6SAntoine Ténart } 6771b44c5a6SAntoine Ténart 6781b44c5a6SAntoine Ténart static int safexcel_ahash_import(struct ahash_request *areq, const void *in) 6791b44c5a6SAntoine Ténart { 6801b44c5a6SAntoine Ténart struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); 6811b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 6821b44c5a6SAntoine Ténart const struct safexcel_ahash_export_state *export = in; 6831b44c5a6SAntoine Ténart int ret; 6841b44c5a6SAntoine Ténart 6851b44c5a6SAntoine Ténart ret = crypto_ahash_init(areq); 6861b44c5a6SAntoine Ténart if (ret) 6871b44c5a6SAntoine Ténart return ret; 6881b44c5a6SAntoine Ténart 6891b44c5a6SAntoine Ténart req->len = export->len; 6901b44c5a6SAntoine Ténart req->processed = export->processed; 6911b44c5a6SAntoine Ténart 692b869648cSAntoine Tenart req->digest = export->digest; 693b869648cSAntoine Tenart 6941b44c5a6SAntoine Ténart memcpy(req->cache, export->cache, crypto_ahash_blocksize(ahash)); 6951b44c5a6SAntoine Ténart memcpy(req->state, export->state, req->state_sz); 6961b44c5a6SAntoine Ténart 6971b44c5a6SAntoine Ténart return 0; 6981b44c5a6SAntoine Ténart } 6991b44c5a6SAntoine Ténart 7001b44c5a6SAntoine Ténart static int safexcel_ahash_cra_init(struct crypto_tfm *tfm) 7011b44c5a6SAntoine Ténart { 7021b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 7031b44c5a6SAntoine Ténart struct safexcel_alg_template *tmpl = 7041b44c5a6SAntoine Ténart container_of(__crypto_ahash_alg(tfm->__crt_alg), 7051b44c5a6SAntoine Ténart struct safexcel_alg_template, alg.ahash); 7061b44c5a6SAntoine Ténart 7071b44c5a6SAntoine Ténart ctx->priv = tmpl->priv; 7081eb7b403SOfer Heifetz ctx->base.send = safexcel_ahash_send; 7091eb7b403SOfer Heifetz ctx->base.handle_result = safexcel_handle_result; 7101b44c5a6SAntoine Ténart 7111b44c5a6SAntoine Ténart crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), 7121b44c5a6SAntoine Ténart sizeof(struct safexcel_ahash_req)); 7131b44c5a6SAntoine Ténart return 0; 7141b44c5a6SAntoine Ténart } 7151b44c5a6SAntoine Ténart 7161b44c5a6SAntoine Ténart static int safexcel_sha1_init(struct ahash_request *areq) 7171b44c5a6SAntoine Ténart { 7181b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 7191b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 7201b44c5a6SAntoine Ténart 7211b44c5a6SAntoine Ténart memset(req, 0, sizeof(*req)); 7221b44c5a6SAntoine Ténart 7231b44c5a6SAntoine Ténart req->state[0] = SHA1_H0; 7241b44c5a6SAntoine Ténart req->state[1] = SHA1_H1; 7251b44c5a6SAntoine Ténart req->state[2] = SHA1_H2; 7261b44c5a6SAntoine Ténart req->state[3] = SHA1_H3; 7271b44c5a6SAntoine Ténart req->state[4] = SHA1_H4; 7281b44c5a6SAntoine Ténart 7291b44c5a6SAntoine Ténart ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1; 730b869648cSAntoine Tenart req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 7311b44c5a6SAntoine Ténart req->state_sz = SHA1_DIGEST_SIZE; 7321b44c5a6SAntoine Ténart 7331b44c5a6SAntoine Ténart return 0; 7341b44c5a6SAntoine Ténart } 7351b44c5a6SAntoine Ténart 7361b44c5a6SAntoine Ténart static int safexcel_sha1_digest(struct ahash_request *areq) 7371b44c5a6SAntoine Ténart { 7381b44c5a6SAntoine Ténart int ret = safexcel_sha1_init(areq); 7391b44c5a6SAntoine Ténart 7401b44c5a6SAntoine Ténart if (ret) 7411b44c5a6SAntoine Ténart return ret; 7421b44c5a6SAntoine Ténart 7431b44c5a6SAntoine Ténart return safexcel_ahash_finup(areq); 7441b44c5a6SAntoine Ténart } 7451b44c5a6SAntoine Ténart 7461b44c5a6SAntoine Ténart static void safexcel_ahash_cra_exit(struct crypto_tfm *tfm) 7471b44c5a6SAntoine Ténart { 7481b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 7491b44c5a6SAntoine Ténart struct safexcel_crypto_priv *priv = ctx->priv; 7501b44c5a6SAntoine Ténart int ret; 7511b44c5a6SAntoine Ténart 7521b44c5a6SAntoine Ténart /* context not allocated, skip invalidation */ 7531b44c5a6SAntoine Ténart if (!ctx->base.ctxr) 7541b44c5a6SAntoine Ténart return; 7551b44c5a6SAntoine Ténart 756871df319SAntoine Ténart if (priv->version == EIP197) { 7571b44c5a6SAntoine Ténart ret = safexcel_ahash_exit_inv(tfm); 7581b44c5a6SAntoine Ténart if (ret) 7591b44c5a6SAntoine Ténart dev_warn(priv->dev, "hash: invalidation error %d\n", ret); 760871df319SAntoine Ténart } else { 761871df319SAntoine Ténart dma_pool_free(priv->context_pool, ctx->base.ctxr, 762871df319SAntoine Ténart ctx->base.ctxr_dma); 763871df319SAntoine Ténart } 7641b44c5a6SAntoine Ténart } 7651b44c5a6SAntoine Ténart 7661b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha1 = { 7671b44c5a6SAntoine Ténart .type = SAFEXCEL_ALG_TYPE_AHASH, 7681b44c5a6SAntoine Ténart .alg.ahash = { 7691b44c5a6SAntoine Ténart .init = safexcel_sha1_init, 7701b44c5a6SAntoine Ténart .update = safexcel_ahash_update, 7711b44c5a6SAntoine Ténart .final = safexcel_ahash_final, 7721b44c5a6SAntoine Ténart .finup = safexcel_ahash_finup, 7731b44c5a6SAntoine Ténart .digest = safexcel_sha1_digest, 7741b44c5a6SAntoine Ténart .export = safexcel_ahash_export, 7751b44c5a6SAntoine Ténart .import = safexcel_ahash_import, 7761b44c5a6SAntoine Ténart .halg = { 7771b44c5a6SAntoine Ténart .digestsize = SHA1_DIGEST_SIZE, 7781b44c5a6SAntoine Ténart .statesize = sizeof(struct safexcel_ahash_export_state), 7791b44c5a6SAntoine Ténart .base = { 7801b44c5a6SAntoine Ténart .cra_name = "sha1", 7811b44c5a6SAntoine Ténart .cra_driver_name = "safexcel-sha1", 7821b44c5a6SAntoine Ténart .cra_priority = 300, 7831b44c5a6SAntoine Ténart .cra_flags = CRYPTO_ALG_ASYNC | 7841b44c5a6SAntoine Ténart CRYPTO_ALG_KERN_DRIVER_ONLY, 7851b44c5a6SAntoine Ténart .cra_blocksize = SHA1_BLOCK_SIZE, 7861b44c5a6SAntoine Ténart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 7871b44c5a6SAntoine Ténart .cra_init = safexcel_ahash_cra_init, 7881b44c5a6SAntoine Ténart .cra_exit = safexcel_ahash_cra_exit, 7891b44c5a6SAntoine Ténart .cra_module = THIS_MODULE, 7901b44c5a6SAntoine Ténart }, 7911b44c5a6SAntoine Ténart }, 7921b44c5a6SAntoine Ténart }, 7931b44c5a6SAntoine Ténart }; 7941b44c5a6SAntoine Ténart 7951b44c5a6SAntoine Ténart static int safexcel_hmac_sha1_init(struct ahash_request *areq) 7961b44c5a6SAntoine Ténart { 797b869648cSAntoine Tenart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 7981b44c5a6SAntoine Ténart 7991b44c5a6SAntoine Ténart safexcel_sha1_init(areq); 800b869648cSAntoine Tenart req->digest = CONTEXT_CONTROL_DIGEST_HMAC; 8011b44c5a6SAntoine Ténart return 0; 8021b44c5a6SAntoine Ténart } 8031b44c5a6SAntoine Ténart 8041b44c5a6SAntoine Ténart static int safexcel_hmac_sha1_digest(struct ahash_request *areq) 8051b44c5a6SAntoine Ténart { 8061b44c5a6SAntoine Ténart int ret = safexcel_hmac_sha1_init(areq); 8071b44c5a6SAntoine Ténart 8081b44c5a6SAntoine Ténart if (ret) 8091b44c5a6SAntoine Ténart return ret; 8101b44c5a6SAntoine Ténart 8111b44c5a6SAntoine Ténart return safexcel_ahash_finup(areq); 8121b44c5a6SAntoine Ténart } 8131b44c5a6SAntoine Ténart 8141b44c5a6SAntoine Ténart struct safexcel_ahash_result { 8151b44c5a6SAntoine Ténart struct completion completion; 8161b44c5a6SAntoine Ténart int error; 8171b44c5a6SAntoine Ténart }; 8181b44c5a6SAntoine Ténart 8191b44c5a6SAntoine Ténart static void safexcel_ahash_complete(struct crypto_async_request *req, int error) 8201b44c5a6SAntoine Ténart { 8211b44c5a6SAntoine Ténart struct safexcel_ahash_result *result = req->data; 8221b44c5a6SAntoine Ténart 8231b44c5a6SAntoine Ténart if (error == -EINPROGRESS) 8241b44c5a6SAntoine Ténart return; 8251b44c5a6SAntoine Ténart 8261b44c5a6SAntoine Ténart result->error = error; 8271b44c5a6SAntoine Ténart complete(&result->completion); 8281b44c5a6SAntoine Ténart } 8291b44c5a6SAntoine Ténart 8301b44c5a6SAntoine Ténart static int safexcel_hmac_init_pad(struct ahash_request *areq, 8311b44c5a6SAntoine Ténart unsigned int blocksize, const u8 *key, 8321b44c5a6SAntoine Ténart unsigned int keylen, u8 *ipad, u8 *opad) 8331b44c5a6SAntoine Ténart { 8341b44c5a6SAntoine Ténart struct safexcel_ahash_result result; 8351b44c5a6SAntoine Ténart struct scatterlist sg; 8361b44c5a6SAntoine Ténart int ret, i; 8371b44c5a6SAntoine Ténart u8 *keydup; 8381b44c5a6SAntoine Ténart 8391b44c5a6SAntoine Ténart if (keylen <= blocksize) { 8401b44c5a6SAntoine Ténart memcpy(ipad, key, keylen); 8411b44c5a6SAntoine Ténart } else { 8421b44c5a6SAntoine Ténart keydup = kmemdup(key, keylen, GFP_KERNEL); 8431b44c5a6SAntoine Ténart if (!keydup) 8441b44c5a6SAntoine Ténart return -ENOMEM; 8451b44c5a6SAntoine Ténart 8461b44c5a6SAntoine Ténart ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_BACKLOG, 8471b44c5a6SAntoine Ténart safexcel_ahash_complete, &result); 8481b44c5a6SAntoine Ténart sg_init_one(&sg, keydup, keylen); 8491b44c5a6SAntoine Ténart ahash_request_set_crypt(areq, &sg, ipad, keylen); 8501b44c5a6SAntoine Ténart init_completion(&result.completion); 8511b44c5a6SAntoine Ténart 8521b44c5a6SAntoine Ténart ret = crypto_ahash_digest(areq); 8534dc5475aSAntoine Tenart if (ret == -EINPROGRESS || ret == -EBUSY) { 8541b44c5a6SAntoine Ténart wait_for_completion_interruptible(&result.completion); 8551b44c5a6SAntoine Ténart ret = result.error; 8561b44c5a6SAntoine Ténart } 8571b44c5a6SAntoine Ténart 8581b44c5a6SAntoine Ténart /* Avoid leaking */ 8591b44c5a6SAntoine Ténart memzero_explicit(keydup, keylen); 8601b44c5a6SAntoine Ténart kfree(keydup); 8611b44c5a6SAntoine Ténart 8621b44c5a6SAntoine Ténart if (ret) 8631b44c5a6SAntoine Ténart return ret; 8641b44c5a6SAntoine Ténart 8651b44c5a6SAntoine Ténart keylen = crypto_ahash_digestsize(crypto_ahash_reqtfm(areq)); 8661b44c5a6SAntoine Ténart } 8671b44c5a6SAntoine Ténart 8681b44c5a6SAntoine Ténart memset(ipad + keylen, 0, blocksize - keylen); 8691b44c5a6SAntoine Ténart memcpy(opad, ipad, blocksize); 8701b44c5a6SAntoine Ténart 8711b44c5a6SAntoine Ténart for (i = 0; i < blocksize; i++) { 872aed3731eSAntoine Ténart ipad[i] ^= HMAC_IPAD_VALUE; 873aed3731eSAntoine Ténart opad[i] ^= HMAC_OPAD_VALUE; 8741b44c5a6SAntoine Ténart } 8751b44c5a6SAntoine Ténart 8761b44c5a6SAntoine Ténart return 0; 8771b44c5a6SAntoine Ténart } 8781b44c5a6SAntoine Ténart 8791b44c5a6SAntoine Ténart static int safexcel_hmac_init_iv(struct ahash_request *areq, 8801b44c5a6SAntoine Ténart unsigned int blocksize, u8 *pad, void *state) 8811b44c5a6SAntoine Ténart { 8821b44c5a6SAntoine Ténart struct safexcel_ahash_result result; 8831b44c5a6SAntoine Ténart struct safexcel_ahash_req *req; 8841b44c5a6SAntoine Ténart struct scatterlist sg; 8851b44c5a6SAntoine Ténart int ret; 8861b44c5a6SAntoine Ténart 8871b44c5a6SAntoine Ténart ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_BACKLOG, 8881b44c5a6SAntoine Ténart safexcel_ahash_complete, &result); 8891b44c5a6SAntoine Ténart sg_init_one(&sg, pad, blocksize); 8901b44c5a6SAntoine Ténart ahash_request_set_crypt(areq, &sg, pad, blocksize); 8911b44c5a6SAntoine Ténart init_completion(&result.completion); 8921b44c5a6SAntoine Ténart 8931b44c5a6SAntoine Ténart ret = crypto_ahash_init(areq); 8941b44c5a6SAntoine Ténart if (ret) 8951b44c5a6SAntoine Ténart return ret; 8961b44c5a6SAntoine Ténart 8971b44c5a6SAntoine Ténart req = ahash_request_ctx(areq); 8981b44c5a6SAntoine Ténart req->hmac = true; 8991b44c5a6SAntoine Ténart req->last_req = true; 9001b44c5a6SAntoine Ténart 9011b44c5a6SAntoine Ténart ret = crypto_ahash_update(areq); 90212bf4142SOfer Heifetz if (ret && ret != -EINPROGRESS && ret != -EBUSY) 9031b44c5a6SAntoine Ténart return ret; 9041b44c5a6SAntoine Ténart 9051b44c5a6SAntoine Ténart wait_for_completion_interruptible(&result.completion); 9061b44c5a6SAntoine Ténart if (result.error) 9071b44c5a6SAntoine Ténart return result.error; 9081b44c5a6SAntoine Ténart 9091b44c5a6SAntoine Ténart return crypto_ahash_export(areq, state); 9101b44c5a6SAntoine Ténart } 9111b44c5a6SAntoine Ténart 9121b44c5a6SAntoine Ténart static int safexcel_hmac_setkey(const char *alg, const u8 *key, 9131b44c5a6SAntoine Ténart unsigned int keylen, void *istate, void *ostate) 9141b44c5a6SAntoine Ténart { 9151b44c5a6SAntoine Ténart struct ahash_request *areq; 9161b44c5a6SAntoine Ténart struct crypto_ahash *tfm; 9171b44c5a6SAntoine Ténart unsigned int blocksize; 9181b44c5a6SAntoine Ténart u8 *ipad, *opad; 9191b44c5a6SAntoine Ténart int ret; 9201b44c5a6SAntoine Ténart 9211b44c5a6SAntoine Ténart tfm = crypto_alloc_ahash(alg, CRYPTO_ALG_TYPE_AHASH, 9221b44c5a6SAntoine Ténart CRYPTO_ALG_TYPE_AHASH_MASK); 9231b44c5a6SAntoine Ténart if (IS_ERR(tfm)) 9241b44c5a6SAntoine Ténart return PTR_ERR(tfm); 9251b44c5a6SAntoine Ténart 9261b44c5a6SAntoine Ténart areq = ahash_request_alloc(tfm, GFP_KERNEL); 9271b44c5a6SAntoine Ténart if (!areq) { 9281b44c5a6SAntoine Ténart ret = -ENOMEM; 9291b44c5a6SAntoine Ténart goto free_ahash; 9301b44c5a6SAntoine Ténart } 9311b44c5a6SAntoine Ténart 9321b44c5a6SAntoine Ténart crypto_ahash_clear_flags(tfm, ~0); 9331b44c5a6SAntoine Ténart blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); 9341b44c5a6SAntoine Ténart 9351b44c5a6SAntoine Ténart ipad = kzalloc(2 * blocksize, GFP_KERNEL); 9361b44c5a6SAntoine Ténart if (!ipad) { 9371b44c5a6SAntoine Ténart ret = -ENOMEM; 9381b44c5a6SAntoine Ténart goto free_request; 9391b44c5a6SAntoine Ténart } 9401b44c5a6SAntoine Ténart 9411b44c5a6SAntoine Ténart opad = ipad + blocksize; 9421b44c5a6SAntoine Ténart 9431b44c5a6SAntoine Ténart ret = safexcel_hmac_init_pad(areq, blocksize, key, keylen, ipad, opad); 9441b44c5a6SAntoine Ténart if (ret) 9451b44c5a6SAntoine Ténart goto free_ipad; 9461b44c5a6SAntoine Ténart 9471b44c5a6SAntoine Ténart ret = safexcel_hmac_init_iv(areq, blocksize, ipad, istate); 9481b44c5a6SAntoine Ténart if (ret) 9491b44c5a6SAntoine Ténart goto free_ipad; 9501b44c5a6SAntoine Ténart 9511b44c5a6SAntoine Ténart ret = safexcel_hmac_init_iv(areq, blocksize, opad, ostate); 9521b44c5a6SAntoine Ténart 9531b44c5a6SAntoine Ténart free_ipad: 9541b44c5a6SAntoine Ténart kfree(ipad); 9551b44c5a6SAntoine Ténart free_request: 9561b44c5a6SAntoine Ténart ahash_request_free(areq); 9571b44c5a6SAntoine Ténart free_ahash: 9581b44c5a6SAntoine Ténart crypto_free_ahash(tfm); 9591b44c5a6SAntoine Ténart 9601b44c5a6SAntoine Ténart return ret; 9611b44c5a6SAntoine Ténart } 9621b44c5a6SAntoine Ténart 96373f36ea7SAntoine Tenart static int safexcel_hmac_alg_setkey(struct crypto_ahash *tfm, const u8 *key, 96473f36ea7SAntoine Tenart unsigned int keylen, const char *alg, 96573f36ea7SAntoine Tenart unsigned int state_sz) 9661b44c5a6SAntoine Ténart { 9671b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 968871df319SAntoine Ténart struct safexcel_crypto_priv *priv = ctx->priv; 9691b44c5a6SAntoine Ténart struct safexcel_ahash_export_state istate, ostate; 9701b44c5a6SAntoine Ténart int ret, i; 9711b44c5a6SAntoine Ténart 97273f36ea7SAntoine Tenart ret = safexcel_hmac_setkey(alg, key, keylen, &istate, &ostate); 9731b44c5a6SAntoine Ténart if (ret) 9741b44c5a6SAntoine Ténart return ret; 9751b44c5a6SAntoine Ténart 976871df319SAntoine Ténart if (priv->version == EIP197 && ctx->base.ctxr) { 97773f36ea7SAntoine Tenart for (i = 0; i < state_sz / sizeof(u32); i++) { 9781b44c5a6SAntoine Ténart if (ctx->ipad[i] != le32_to_cpu(istate.state[i]) || 9791b44c5a6SAntoine Ténart ctx->opad[i] != le32_to_cpu(ostate.state[i])) { 9801b44c5a6SAntoine Ténart ctx->base.needs_inv = true; 9811b44c5a6SAntoine Ténart break; 9821b44c5a6SAntoine Ténart } 9831b44c5a6SAntoine Ténart } 984c4daf4ccSOfer Heifetz } 9851b44c5a6SAntoine Ténart 98673f36ea7SAntoine Tenart memcpy(ctx->ipad, &istate.state, state_sz); 98773f36ea7SAntoine Tenart memcpy(ctx->opad, &ostate.state, state_sz); 98842ef3bedSAntoine Ténart 9891b44c5a6SAntoine Ténart return 0; 9901b44c5a6SAntoine Ténart } 9911b44c5a6SAntoine Ténart 99273f36ea7SAntoine Tenart static int safexcel_hmac_sha1_setkey(struct crypto_ahash *tfm, const u8 *key, 99373f36ea7SAntoine Tenart unsigned int keylen) 99473f36ea7SAntoine Tenart { 99573f36ea7SAntoine Tenart return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha1", 99673f36ea7SAntoine Tenart SHA1_DIGEST_SIZE); 99773f36ea7SAntoine Tenart } 99873f36ea7SAntoine Tenart 9991b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_hmac_sha1 = { 10001b44c5a6SAntoine Ténart .type = SAFEXCEL_ALG_TYPE_AHASH, 10011b44c5a6SAntoine Ténart .alg.ahash = { 10021b44c5a6SAntoine Ténart .init = safexcel_hmac_sha1_init, 10031b44c5a6SAntoine Ténart .update = safexcel_ahash_update, 10041b44c5a6SAntoine Ténart .final = safexcel_ahash_final, 10051b44c5a6SAntoine Ténart .finup = safexcel_ahash_finup, 10061b44c5a6SAntoine Ténart .digest = safexcel_hmac_sha1_digest, 10071b44c5a6SAntoine Ténart .setkey = safexcel_hmac_sha1_setkey, 10081b44c5a6SAntoine Ténart .export = safexcel_ahash_export, 10091b44c5a6SAntoine Ténart .import = safexcel_ahash_import, 10101b44c5a6SAntoine Ténart .halg = { 10111b44c5a6SAntoine Ténart .digestsize = SHA1_DIGEST_SIZE, 10121b44c5a6SAntoine Ténart .statesize = sizeof(struct safexcel_ahash_export_state), 10131b44c5a6SAntoine Ténart .base = { 10141b44c5a6SAntoine Ténart .cra_name = "hmac(sha1)", 10151b44c5a6SAntoine Ténart .cra_driver_name = "safexcel-hmac-sha1", 10161b44c5a6SAntoine Ténart .cra_priority = 300, 10171b44c5a6SAntoine Ténart .cra_flags = CRYPTO_ALG_ASYNC | 10181b44c5a6SAntoine Ténart CRYPTO_ALG_KERN_DRIVER_ONLY, 10191b44c5a6SAntoine Ténart .cra_blocksize = SHA1_BLOCK_SIZE, 10201b44c5a6SAntoine Ténart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 10211b44c5a6SAntoine Ténart .cra_init = safexcel_ahash_cra_init, 10221b44c5a6SAntoine Ténart .cra_exit = safexcel_ahash_cra_exit, 10231b44c5a6SAntoine Ténart .cra_module = THIS_MODULE, 10241b44c5a6SAntoine Ténart }, 10251b44c5a6SAntoine Ténart }, 10261b44c5a6SAntoine Ténart }, 10271b44c5a6SAntoine Ténart }; 10281b44c5a6SAntoine Ténart 10291b44c5a6SAntoine Ténart static int safexcel_sha256_init(struct ahash_request *areq) 10301b44c5a6SAntoine Ténart { 10311b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 10321b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 10331b44c5a6SAntoine Ténart 10341b44c5a6SAntoine Ténart memset(req, 0, sizeof(*req)); 10351b44c5a6SAntoine Ténart 10361b44c5a6SAntoine Ténart req->state[0] = SHA256_H0; 10371b44c5a6SAntoine Ténart req->state[1] = SHA256_H1; 10381b44c5a6SAntoine Ténart req->state[2] = SHA256_H2; 10391b44c5a6SAntoine Ténart req->state[3] = SHA256_H3; 10401b44c5a6SAntoine Ténart req->state[4] = SHA256_H4; 10411b44c5a6SAntoine Ténart req->state[5] = SHA256_H5; 10421b44c5a6SAntoine Ténart req->state[6] = SHA256_H6; 10431b44c5a6SAntoine Ténart req->state[7] = SHA256_H7; 10441b44c5a6SAntoine Ténart 10451b44c5a6SAntoine Ténart ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256; 1046b869648cSAntoine Tenart req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 10471b44c5a6SAntoine Ténart req->state_sz = SHA256_DIGEST_SIZE; 10481b44c5a6SAntoine Ténart 10491b44c5a6SAntoine Ténart return 0; 10501b44c5a6SAntoine Ténart } 10511b44c5a6SAntoine Ténart 10521b44c5a6SAntoine Ténart static int safexcel_sha256_digest(struct ahash_request *areq) 10531b44c5a6SAntoine Ténart { 10541b44c5a6SAntoine Ténart int ret = safexcel_sha256_init(areq); 10551b44c5a6SAntoine Ténart 10561b44c5a6SAntoine Ténart if (ret) 10571b44c5a6SAntoine Ténart return ret; 10581b44c5a6SAntoine Ténart 10591b44c5a6SAntoine Ténart return safexcel_ahash_finup(areq); 10601b44c5a6SAntoine Ténart } 10611b44c5a6SAntoine Ténart 10621b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha256 = { 10631b44c5a6SAntoine Ténart .type = SAFEXCEL_ALG_TYPE_AHASH, 10641b44c5a6SAntoine Ténart .alg.ahash = { 10651b44c5a6SAntoine Ténart .init = safexcel_sha256_init, 10661b44c5a6SAntoine Ténart .update = safexcel_ahash_update, 10671b44c5a6SAntoine Ténart .final = safexcel_ahash_final, 10681b44c5a6SAntoine Ténart .finup = safexcel_ahash_finup, 10691b44c5a6SAntoine Ténart .digest = safexcel_sha256_digest, 10701b44c5a6SAntoine Ténart .export = safexcel_ahash_export, 10711b44c5a6SAntoine Ténart .import = safexcel_ahash_import, 10721b44c5a6SAntoine Ténart .halg = { 10731b44c5a6SAntoine Ténart .digestsize = SHA256_DIGEST_SIZE, 10741b44c5a6SAntoine Ténart .statesize = sizeof(struct safexcel_ahash_export_state), 10751b44c5a6SAntoine Ténart .base = { 10761b44c5a6SAntoine Ténart .cra_name = "sha256", 10771b44c5a6SAntoine Ténart .cra_driver_name = "safexcel-sha256", 10781b44c5a6SAntoine Ténart .cra_priority = 300, 10791b44c5a6SAntoine Ténart .cra_flags = CRYPTO_ALG_ASYNC | 10801b44c5a6SAntoine Ténart CRYPTO_ALG_KERN_DRIVER_ONLY, 10811b44c5a6SAntoine Ténart .cra_blocksize = SHA256_BLOCK_SIZE, 10821b44c5a6SAntoine Ténart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 10831b44c5a6SAntoine Ténart .cra_init = safexcel_ahash_cra_init, 10841b44c5a6SAntoine Ténart .cra_exit = safexcel_ahash_cra_exit, 10851b44c5a6SAntoine Ténart .cra_module = THIS_MODULE, 10861b44c5a6SAntoine Ténart }, 10871b44c5a6SAntoine Ténart }, 10881b44c5a6SAntoine Ténart }, 10891b44c5a6SAntoine Ténart }; 10901b44c5a6SAntoine Ténart 10911b44c5a6SAntoine Ténart static int safexcel_sha224_init(struct ahash_request *areq) 10921b44c5a6SAntoine Ténart { 10931b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 10941b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 10951b44c5a6SAntoine Ténart 10961b44c5a6SAntoine Ténart memset(req, 0, sizeof(*req)); 10971b44c5a6SAntoine Ténart 10981b44c5a6SAntoine Ténart req->state[0] = SHA224_H0; 10991b44c5a6SAntoine Ténart req->state[1] = SHA224_H1; 11001b44c5a6SAntoine Ténart req->state[2] = SHA224_H2; 11011b44c5a6SAntoine Ténart req->state[3] = SHA224_H3; 11021b44c5a6SAntoine Ténart req->state[4] = SHA224_H4; 11031b44c5a6SAntoine Ténart req->state[5] = SHA224_H5; 11041b44c5a6SAntoine Ténart req->state[6] = SHA224_H6; 11051b44c5a6SAntoine Ténart req->state[7] = SHA224_H7; 11061b44c5a6SAntoine Ténart 11071b44c5a6SAntoine Ténart ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224; 1108b869648cSAntoine Tenart req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 11091b44c5a6SAntoine Ténart req->state_sz = SHA256_DIGEST_SIZE; 11101b44c5a6SAntoine Ténart 11111b44c5a6SAntoine Ténart return 0; 11121b44c5a6SAntoine Ténart } 11131b44c5a6SAntoine Ténart 11141b44c5a6SAntoine Ténart static int safexcel_sha224_digest(struct ahash_request *areq) 11151b44c5a6SAntoine Ténart { 11161b44c5a6SAntoine Ténart int ret = safexcel_sha224_init(areq); 11171b44c5a6SAntoine Ténart 11181b44c5a6SAntoine Ténart if (ret) 11191b44c5a6SAntoine Ténart return ret; 11201b44c5a6SAntoine Ténart 11211b44c5a6SAntoine Ténart return safexcel_ahash_finup(areq); 11221b44c5a6SAntoine Ténart } 11231b44c5a6SAntoine Ténart 11241b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha224 = { 11251b44c5a6SAntoine Ténart .type = SAFEXCEL_ALG_TYPE_AHASH, 11261b44c5a6SAntoine Ténart .alg.ahash = { 11271b44c5a6SAntoine Ténart .init = safexcel_sha224_init, 11281b44c5a6SAntoine Ténart .update = safexcel_ahash_update, 11291b44c5a6SAntoine Ténart .final = safexcel_ahash_final, 11301b44c5a6SAntoine Ténart .finup = safexcel_ahash_finup, 11311b44c5a6SAntoine Ténart .digest = safexcel_sha224_digest, 11321b44c5a6SAntoine Ténart .export = safexcel_ahash_export, 11331b44c5a6SAntoine Ténart .import = safexcel_ahash_import, 11341b44c5a6SAntoine Ténart .halg = { 11351b44c5a6SAntoine Ténart .digestsize = SHA224_DIGEST_SIZE, 11361b44c5a6SAntoine Ténart .statesize = sizeof(struct safexcel_ahash_export_state), 11371b44c5a6SAntoine Ténart .base = { 11381b44c5a6SAntoine Ténart .cra_name = "sha224", 11391b44c5a6SAntoine Ténart .cra_driver_name = "safexcel-sha224", 11401b44c5a6SAntoine Ténart .cra_priority = 300, 11411b44c5a6SAntoine Ténart .cra_flags = CRYPTO_ALG_ASYNC | 11421b44c5a6SAntoine Ténart CRYPTO_ALG_KERN_DRIVER_ONLY, 11431b44c5a6SAntoine Ténart .cra_blocksize = SHA224_BLOCK_SIZE, 11441b44c5a6SAntoine Ténart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 11451b44c5a6SAntoine Ténart .cra_init = safexcel_ahash_cra_init, 11461b44c5a6SAntoine Ténart .cra_exit = safexcel_ahash_cra_exit, 11471b44c5a6SAntoine Ténart .cra_module = THIS_MODULE, 11481b44c5a6SAntoine Ténart }, 11491b44c5a6SAntoine Ténart }, 11501b44c5a6SAntoine Ténart }, 11511b44c5a6SAntoine Ténart }; 115273f36ea7SAntoine Tenart 11533ad618d8SAntoine Tenart static int safexcel_hmac_sha224_setkey(struct crypto_ahash *tfm, const u8 *key, 11543ad618d8SAntoine Tenart unsigned int keylen) 11553ad618d8SAntoine Tenart { 11563ad618d8SAntoine Tenart return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha224", 11573ad618d8SAntoine Tenart SHA256_DIGEST_SIZE); 11583ad618d8SAntoine Tenart } 11593ad618d8SAntoine Tenart 11603ad618d8SAntoine Tenart static int safexcel_hmac_sha224_init(struct ahash_request *areq) 11613ad618d8SAntoine Tenart { 11623ad618d8SAntoine Tenart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 11633ad618d8SAntoine Tenart 11643ad618d8SAntoine Tenart safexcel_sha224_init(areq); 11653ad618d8SAntoine Tenart req->digest = CONTEXT_CONTROL_DIGEST_HMAC; 11663ad618d8SAntoine Tenart return 0; 11673ad618d8SAntoine Tenart } 11683ad618d8SAntoine Tenart 11693ad618d8SAntoine Tenart static int safexcel_hmac_sha224_digest(struct ahash_request *areq) 11703ad618d8SAntoine Tenart { 11713ad618d8SAntoine Tenart int ret = safexcel_hmac_sha224_init(areq); 11723ad618d8SAntoine Tenart 11733ad618d8SAntoine Tenart if (ret) 11743ad618d8SAntoine Tenart return ret; 11753ad618d8SAntoine Tenart 11763ad618d8SAntoine Tenart return safexcel_ahash_finup(areq); 11773ad618d8SAntoine Tenart } 11783ad618d8SAntoine Tenart 11793ad618d8SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha224 = { 11803ad618d8SAntoine Tenart .type = SAFEXCEL_ALG_TYPE_AHASH, 11813ad618d8SAntoine Tenart .alg.ahash = { 11823ad618d8SAntoine Tenart .init = safexcel_hmac_sha224_init, 11833ad618d8SAntoine Tenart .update = safexcel_ahash_update, 11843ad618d8SAntoine Tenart .final = safexcel_ahash_final, 11853ad618d8SAntoine Tenart .finup = safexcel_ahash_finup, 11863ad618d8SAntoine Tenart .digest = safexcel_hmac_sha224_digest, 11873ad618d8SAntoine Tenart .setkey = safexcel_hmac_sha224_setkey, 11883ad618d8SAntoine Tenart .export = safexcel_ahash_export, 11893ad618d8SAntoine Tenart .import = safexcel_ahash_import, 11903ad618d8SAntoine Tenart .halg = { 11913ad618d8SAntoine Tenart .digestsize = SHA224_DIGEST_SIZE, 11923ad618d8SAntoine Tenart .statesize = sizeof(struct safexcel_ahash_export_state), 11933ad618d8SAntoine Tenart .base = { 11943ad618d8SAntoine Tenart .cra_name = "hmac(sha224)", 11953ad618d8SAntoine Tenart .cra_driver_name = "safexcel-hmac-sha224", 11963ad618d8SAntoine Tenart .cra_priority = 300, 11973ad618d8SAntoine Tenart .cra_flags = CRYPTO_ALG_ASYNC | 11983ad618d8SAntoine Tenart CRYPTO_ALG_KERN_DRIVER_ONLY, 11993ad618d8SAntoine Tenart .cra_blocksize = SHA224_BLOCK_SIZE, 12003ad618d8SAntoine Tenart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 12013ad618d8SAntoine Tenart .cra_init = safexcel_ahash_cra_init, 12023ad618d8SAntoine Tenart .cra_exit = safexcel_ahash_cra_exit, 12033ad618d8SAntoine Tenart .cra_module = THIS_MODULE, 12043ad618d8SAntoine Tenart }, 12053ad618d8SAntoine Tenart }, 12063ad618d8SAntoine Tenart }, 12073ad618d8SAntoine Tenart }; 12083ad618d8SAntoine Tenart 120973f36ea7SAntoine Tenart static int safexcel_hmac_sha256_setkey(struct crypto_ahash *tfm, const u8 *key, 121073f36ea7SAntoine Tenart unsigned int keylen) 121173f36ea7SAntoine Tenart { 121273f36ea7SAntoine Tenart return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha256", 121373f36ea7SAntoine Tenart SHA256_DIGEST_SIZE); 121473f36ea7SAntoine Tenart } 121573f36ea7SAntoine Tenart 121673f36ea7SAntoine Tenart static int safexcel_hmac_sha256_init(struct ahash_request *areq) 121773f36ea7SAntoine Tenart { 121873f36ea7SAntoine Tenart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 121973f36ea7SAntoine Tenart 122073f36ea7SAntoine Tenart safexcel_sha256_init(areq); 122173f36ea7SAntoine Tenart req->digest = CONTEXT_CONTROL_DIGEST_HMAC; 122273f36ea7SAntoine Tenart return 0; 122373f36ea7SAntoine Tenart } 122473f36ea7SAntoine Tenart 122573f36ea7SAntoine Tenart static int safexcel_hmac_sha256_digest(struct ahash_request *areq) 122673f36ea7SAntoine Tenart { 122773f36ea7SAntoine Tenart int ret = safexcel_hmac_sha256_init(areq); 122873f36ea7SAntoine Tenart 122973f36ea7SAntoine Tenart if (ret) 123073f36ea7SAntoine Tenart return ret; 123173f36ea7SAntoine Tenart 123273f36ea7SAntoine Tenart return safexcel_ahash_finup(areq); 123373f36ea7SAntoine Tenart } 123473f36ea7SAntoine Tenart 123573f36ea7SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha256 = { 123673f36ea7SAntoine Tenart .type = SAFEXCEL_ALG_TYPE_AHASH, 123773f36ea7SAntoine Tenart .alg.ahash = { 123873f36ea7SAntoine Tenart .init = safexcel_hmac_sha256_init, 123973f36ea7SAntoine Tenart .update = safexcel_ahash_update, 124073f36ea7SAntoine Tenart .final = safexcel_ahash_final, 124173f36ea7SAntoine Tenart .finup = safexcel_ahash_finup, 124273f36ea7SAntoine Tenart .digest = safexcel_hmac_sha256_digest, 124373f36ea7SAntoine Tenart .setkey = safexcel_hmac_sha256_setkey, 124473f36ea7SAntoine Tenart .export = safexcel_ahash_export, 124573f36ea7SAntoine Tenart .import = safexcel_ahash_import, 124673f36ea7SAntoine Tenart .halg = { 124773f36ea7SAntoine Tenart .digestsize = SHA256_DIGEST_SIZE, 124873f36ea7SAntoine Tenart .statesize = sizeof(struct safexcel_ahash_export_state), 124973f36ea7SAntoine Tenart .base = { 125073f36ea7SAntoine Tenart .cra_name = "hmac(sha256)", 125173f36ea7SAntoine Tenart .cra_driver_name = "safexcel-hmac-sha256", 125273f36ea7SAntoine Tenart .cra_priority = 300, 125373f36ea7SAntoine Tenart .cra_flags = CRYPTO_ALG_ASYNC | 125473f36ea7SAntoine Tenart CRYPTO_ALG_KERN_DRIVER_ONLY, 125573f36ea7SAntoine Tenart .cra_blocksize = SHA256_BLOCK_SIZE, 125673f36ea7SAntoine Tenart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 125773f36ea7SAntoine Tenart .cra_init = safexcel_ahash_cra_init, 125873f36ea7SAntoine Tenart .cra_exit = safexcel_ahash_cra_exit, 125973f36ea7SAntoine Tenart .cra_module = THIS_MODULE, 126073f36ea7SAntoine Tenart }, 126173f36ea7SAntoine Tenart }, 126273f36ea7SAntoine Tenart }, 126373f36ea7SAntoine Tenart }; 1264