1301422e3SAntoine Tenart // SPDX-License-Identifier: GPL-2.0 21b44c5a6SAntoine Ténart /* 31b44c5a6SAntoine Ténart * Copyright (C) 2017 Marvell 41b44c5a6SAntoine Ténart * 51b44c5a6SAntoine Ténart * Antoine Tenart <antoine.tenart@free-electrons.com> 61b44c5a6SAntoine Ténart */ 71b44c5a6SAntoine Ténart 8b98687bbSPascal van Leeuwen #include <crypto/aes.h> 9aed3731eSAntoine Ténart #include <crypto/hmac.h> 10293f89cfSOfer Heifetz #include <crypto/md5.h> 111b44c5a6SAntoine Ténart #include <crypto/sha.h> 12aaf5a383SPascal van Leeuwen #include <crypto/sha3.h> 1338f21b4bSPascal van Leeuwen #include <crypto/skcipher.h> 140f2bc131SPascal van Leeuwen #include <crypto/sm3.h> 151b44c5a6SAntoine Ténart #include <linux/device.h> 161b44c5a6SAntoine Ténart #include <linux/dma-mapping.h> 171b44c5a6SAntoine Ténart #include <linux/dmapool.h> 181b44c5a6SAntoine Ténart 191b44c5a6SAntoine Ténart #include "safexcel.h" 201b44c5a6SAntoine Ténart 211b44c5a6SAntoine Ténart struct safexcel_ahash_ctx { 221b44c5a6SAntoine Ténart struct safexcel_context base; 231b44c5a6SAntoine Ténart 241b44c5a6SAntoine Ténart u32 alg; 25b98687bbSPascal van Leeuwen u8 key_sz; 2638f21b4bSPascal van Leeuwen bool cbcmac; 27aaf5a383SPascal van Leeuwen bool do_fallback; 28aaf5a383SPascal van Leeuwen bool fb_init_done; 296c1c09b3SPascal van Leeuwen bool fb_do_setkey; 301b44c5a6SAntoine Ténart 3113a1bb93SPascal van Leeuwen __le32 ipad[SHA3_512_BLOCK_SIZE / sizeof(__le32)]; 3213a1bb93SPascal van Leeuwen __le32 opad[SHA3_512_BLOCK_SIZE / sizeof(__le32)]; 3338f21b4bSPascal van Leeuwen 3438f21b4bSPascal van Leeuwen struct crypto_cipher *kaes; 35aaf5a383SPascal van Leeuwen struct crypto_ahash *fback; 366c1c09b3SPascal van Leeuwen struct crypto_shash *shpre; 376c1c09b3SPascal van Leeuwen struct shash_desc *shdesc; 381b44c5a6SAntoine Ténart }; 391b44c5a6SAntoine Ténart 401b44c5a6SAntoine Ténart struct safexcel_ahash_req { 411b44c5a6SAntoine Ténart bool last_req; 421b44c5a6SAntoine Ténart bool finish; 431b44c5a6SAntoine Ténart bool hmac; 441eb7b403SOfer Heifetz bool needs_inv; 4585b36ee8SPascal van Leeuwen bool hmac_zlen; 4685b36ee8SPascal van Leeuwen bool len_is_le; 47b98687bbSPascal van Leeuwen bool not_first; 48b98687bbSPascal van Leeuwen bool xcbcmac; 491b44c5a6SAntoine Ténart 50c957f8b3SAntoine Ténart int nents; 51b8592027SOfer Heifetz dma_addr_t result_dma; 52c957f8b3SAntoine Ténart 53b869648cSAntoine Tenart u32 digest; 54b869648cSAntoine Tenart 5541abed7dSPascal van Leeuwen u8 state_sz; /* expected state size, only set once */ 5641abed7dSPascal van Leeuwen u8 block_sz; /* block size, only set once */ 576c1c09b3SPascal van Leeuwen u8 digest_sz; /* output digest size, only set once */ 5813a1bb93SPascal van Leeuwen __le32 state[SHA3_512_BLOCK_SIZE / 5913a1bb93SPascal van Leeuwen sizeof(__le32)] __aligned(sizeof(__le32)); 601b44c5a6SAntoine Ténart 6131fb084cSPascal van Leeuwen u64 len; 6231fb084cSPascal van Leeuwen u64 processed; 631b44c5a6SAntoine Ténart 6441abed7dSPascal van Leeuwen u8 cache[HASH_CACHE_SIZE] __aligned(sizeof(u32)); 65cff9a175SAntoine Tenart dma_addr_t cache_dma; 66cff9a175SAntoine Tenart unsigned int cache_sz; 67cff9a175SAntoine Tenart 6841abed7dSPascal van Leeuwen u8 cache_next[HASH_CACHE_SIZE] __aligned(sizeof(u32)); 691b44c5a6SAntoine Ténart }; 701b44c5a6SAntoine Ténart 71b460edb6SAntoine Tenart static inline u64 safexcel_queued_len(struct safexcel_ahash_req *req) 72b460edb6SAntoine Tenart { 7331fb084cSPascal van Leeuwen return req->len - req->processed; 74b460edb6SAntoine Tenart } 75b460edb6SAntoine Tenart 761b44c5a6SAntoine Ténart static void safexcel_hash_token(struct safexcel_command_desc *cdesc, 77b98687bbSPascal van Leeuwen u32 input_length, u32 result_length, 7838f21b4bSPascal van Leeuwen bool cbcmac) 791b44c5a6SAntoine Ténart { 801b44c5a6SAntoine Ténart struct safexcel_token *token = 811b44c5a6SAntoine Ténart (struct safexcel_token *)cdesc->control_data.token; 821b44c5a6SAntoine Ténart 831b44c5a6SAntoine Ténart token[0].opcode = EIP197_TOKEN_OPCODE_DIRECTION; 841b44c5a6SAntoine Ténart token[0].packet_length = input_length; 851b44c5a6SAntoine Ténart token[0].instructions = EIP197_TOKEN_INS_TYPE_HASH; 861b44c5a6SAntoine Ténart 87b98687bbSPascal van Leeuwen input_length &= 15; 8838f21b4bSPascal van Leeuwen if (unlikely(cbcmac && input_length)) { 89098e51e5SPascal van Leeuwen token[0].stat = 0; 901b44c5a6SAntoine Ténart token[1].opcode = EIP197_TOKEN_OPCODE_INSERT; 91b98687bbSPascal van Leeuwen token[1].packet_length = 16 - input_length; 92b98687bbSPascal van Leeuwen token[1].stat = EIP197_TOKEN_STAT_LAST_HASH; 93b98687bbSPascal van Leeuwen token[1].instructions = EIP197_TOKEN_INS_TYPE_HASH; 94b98687bbSPascal van Leeuwen } else { 95b98687bbSPascal van Leeuwen token[0].stat = EIP197_TOKEN_STAT_LAST_HASH; 96098e51e5SPascal van Leeuwen eip197_noop_token(&token[1]); 97b98687bbSPascal van Leeuwen } 98b98687bbSPascal van Leeuwen 99b98687bbSPascal van Leeuwen token[2].opcode = EIP197_TOKEN_OPCODE_INSERT; 100b98687bbSPascal van Leeuwen token[2].stat = EIP197_TOKEN_STAT_LAST_HASH | 1011b44c5a6SAntoine Ténart EIP197_TOKEN_STAT_LAST_PACKET; 102b98687bbSPascal van Leeuwen token[2].packet_length = result_length; 103b98687bbSPascal van Leeuwen token[2].instructions = EIP197_TOKEN_INS_TYPE_OUTPUT | 1041b44c5a6SAntoine Ténart EIP197_TOKEN_INS_INSERT_HASH_DIGEST; 105098e51e5SPascal van Leeuwen 106098e51e5SPascal van Leeuwen eip197_noop_token(&token[3]); 1071b44c5a6SAntoine Ténart } 1081b44c5a6SAntoine Ténart 1091b44c5a6SAntoine Ténart static void safexcel_context_control(struct safexcel_ahash_ctx *ctx, 1101b44c5a6SAntoine Ténart struct safexcel_ahash_req *req, 11141abed7dSPascal van Leeuwen struct safexcel_command_desc *cdesc) 1121b44c5a6SAntoine Ténart { 11318e51895SHerbert Xu struct safexcel_crypto_priv *priv = ctx->base.priv; 11441abed7dSPascal van Leeuwen u64 count = 0; 1151b44c5a6SAntoine Ténart 116a7cf8658SPascal van Leeuwen cdesc->control_data.control0 = ctx->alg; 117098e51e5SPascal van Leeuwen cdesc->control_data.control1 = 0; 118dc5268b6SPascal van Leeuwen 1191b44c5a6SAntoine Ténart /* 1201b44c5a6SAntoine Ténart * Copy the input digest if needed, and setup the context 1211b44c5a6SAntoine Ténart * fields. Do this now as we need it to setup the first command 1221b44c5a6SAntoine Ténart * descriptor. 1231b44c5a6SAntoine Ténart */ 124a7cf8658SPascal van Leeuwen if (unlikely(req->digest == CONTEXT_CONTROL_DIGEST_XCM)) { 125b98687bbSPascal van Leeuwen if (req->xcbcmac) 126b98687bbSPascal van Leeuwen memcpy(ctx->base.ctxr->data, ctx->ipad, ctx->key_sz); 127b98687bbSPascal van Leeuwen else 128b98687bbSPascal van Leeuwen memcpy(ctx->base.ctxr->data, req->state, req->state_sz); 129a7cf8658SPascal van Leeuwen 130b98687bbSPascal van Leeuwen if (!req->finish && req->xcbcmac) 131b98687bbSPascal van Leeuwen cdesc->control_data.control0 |= 132b98687bbSPascal van Leeuwen CONTEXT_CONTROL_DIGEST_XCM | 133a7cf8658SPascal van Leeuwen CONTEXT_CONTROL_TYPE_HASH_OUT | 134b98687bbSPascal van Leeuwen CONTEXT_CONTROL_NO_FINISH_HASH | 135b98687bbSPascal van Leeuwen CONTEXT_CONTROL_SIZE(req->state_sz / 136b98687bbSPascal van Leeuwen sizeof(u32)); 137b98687bbSPascal van Leeuwen else 138b98687bbSPascal van Leeuwen cdesc->control_data.control0 |= 139b98687bbSPascal van Leeuwen CONTEXT_CONTROL_DIGEST_XCM | 140b98687bbSPascal van Leeuwen CONTEXT_CONTROL_TYPE_HASH_OUT | 141b98687bbSPascal van Leeuwen CONTEXT_CONTROL_SIZE(req->state_sz / 142b98687bbSPascal van Leeuwen sizeof(u32)); 143a7cf8658SPascal van Leeuwen return; 144a7cf8658SPascal van Leeuwen } else if (!req->processed) { 14541abed7dSPascal van Leeuwen /* First - and possibly only - block of basic hash only */ 146b98687bbSPascal van Leeuwen if (req->finish) 147a7cf8658SPascal van Leeuwen cdesc->control_data.control0 |= req->digest | 14841abed7dSPascal van Leeuwen CONTEXT_CONTROL_TYPE_HASH_OUT | 14941abed7dSPascal van Leeuwen CONTEXT_CONTROL_RESTART_HASH | 15041abed7dSPascal van Leeuwen /* ensure its not 0! */ 15141abed7dSPascal van Leeuwen CONTEXT_CONTROL_SIZE(1); 152b98687bbSPascal van Leeuwen else 153a7cf8658SPascal van Leeuwen cdesc->control_data.control0 |= req->digest | 15441abed7dSPascal van Leeuwen CONTEXT_CONTROL_TYPE_HASH_OUT | 15541abed7dSPascal van Leeuwen CONTEXT_CONTROL_RESTART_HASH | 15641abed7dSPascal van Leeuwen CONTEXT_CONTROL_NO_FINISH_HASH | 15741abed7dSPascal van Leeuwen /* ensure its not 0! */ 15841abed7dSPascal van Leeuwen CONTEXT_CONTROL_SIZE(1); 15941abed7dSPascal van Leeuwen return; 16041abed7dSPascal van Leeuwen } 16141abed7dSPascal van Leeuwen 16241abed7dSPascal van Leeuwen /* Hash continuation or HMAC, setup (inner) digest from state */ 16341abed7dSPascal van Leeuwen memcpy(ctx->base.ctxr->data, req->state, req->state_sz); 1641b44c5a6SAntoine Ténart 165b460edb6SAntoine Tenart if (req->finish) { 16641abed7dSPascal van Leeuwen /* Compute digest count for hash/HMAC finish operations */ 16741abed7dSPascal van Leeuwen if ((req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) || 16831fb084cSPascal van Leeuwen req->hmac_zlen || (req->processed != req->block_sz)) { 16931fb084cSPascal van Leeuwen count = req->processed / EIP197_COUNTER_BLOCK_SIZE; 170b460edb6SAntoine Tenart 17141abed7dSPascal van Leeuwen /* This is a hardware limitation, as the 172b460edb6SAntoine Tenart * counter must fit into an u32. This represents 17341abed7dSPascal van Leeuwen * a fairly big amount of input data, so we 174b460edb6SAntoine Tenart * shouldn't see this. 175b460edb6SAntoine Tenart */ 17641abed7dSPascal van Leeuwen if (unlikely(count & 0xffffffff00000000ULL)) { 177b460edb6SAntoine Tenart dev_warn(priv->dev, 178b460edb6SAntoine Tenart "Input data is too big\n"); 179b460edb6SAntoine Tenart return; 180b460edb6SAntoine Tenart } 181b460edb6SAntoine Tenart } 1821b44c5a6SAntoine Ténart 18341abed7dSPascal van Leeuwen if ((req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) || 18485b36ee8SPascal van Leeuwen /* Special case: zero length HMAC */ 18585b36ee8SPascal van Leeuwen req->hmac_zlen || 18641abed7dSPascal van Leeuwen /* PE HW < 4.4 cannot do HMAC continue, fake using hash */ 18731fb084cSPascal van Leeuwen (req->processed != req->block_sz)) { 18841abed7dSPascal van Leeuwen /* Basic hash continue operation, need digest + cnt */ 18941abed7dSPascal van Leeuwen cdesc->control_data.control0 |= 19041abed7dSPascal van Leeuwen CONTEXT_CONTROL_SIZE((req->state_sz >> 2) + 1) | 19141abed7dSPascal van Leeuwen CONTEXT_CONTROL_TYPE_HASH_OUT | 19241abed7dSPascal van Leeuwen CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 19385b36ee8SPascal van Leeuwen /* For zero-len HMAC, don't finalize, already padded! */ 19485b36ee8SPascal van Leeuwen if (req->hmac_zlen) 19585b36ee8SPascal van Leeuwen cdesc->control_data.control0 |= 19685b36ee8SPascal van Leeuwen CONTEXT_CONTROL_NO_FINISH_HASH; 19741abed7dSPascal van Leeuwen cdesc->control_data.control1 |= 19841abed7dSPascal van Leeuwen CONTEXT_CONTROL_DIGEST_CNT; 19941abed7dSPascal van Leeuwen ctx->base.ctxr->data[req->state_sz >> 2] = 20041abed7dSPascal van Leeuwen cpu_to_le32(count); 20141abed7dSPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 20285b36ee8SPascal van Leeuwen 20385b36ee8SPascal van Leeuwen /* Clear zero-length HMAC flag for next operation! */ 20485b36ee8SPascal van Leeuwen req->hmac_zlen = false; 20541abed7dSPascal van Leeuwen } else { /* HMAC */ 20641abed7dSPascal van Leeuwen /* Need outer digest for HMAC finalization */ 20741abed7dSPascal van Leeuwen memcpy(ctx->base.ctxr->data + (req->state_sz >> 2), 2084505bb02SAntoine Tenart ctx->opad, req->state_sz); 20941abed7dSPascal van Leeuwen 21041abed7dSPascal van Leeuwen /* Single pass HMAC - no digest count */ 21141abed7dSPascal van Leeuwen cdesc->control_data.control0 |= 21241abed7dSPascal van Leeuwen CONTEXT_CONTROL_SIZE(req->state_sz >> 1) | 21341abed7dSPascal van Leeuwen CONTEXT_CONTROL_TYPE_HASH_OUT | 21441abed7dSPascal van Leeuwen CONTEXT_CONTROL_DIGEST_HMAC; 21541abed7dSPascal van Leeuwen } 21641abed7dSPascal van Leeuwen } else { /* Hash continuation, do not finish yet */ 21741abed7dSPascal van Leeuwen cdesc->control_data.control0 |= 21841abed7dSPascal van Leeuwen CONTEXT_CONTROL_SIZE(req->state_sz >> 2) | 21941abed7dSPascal van Leeuwen CONTEXT_CONTROL_DIGEST_PRECOMPUTED | 22041abed7dSPascal van Leeuwen CONTEXT_CONTROL_TYPE_HASH_OUT | 22141abed7dSPascal van Leeuwen CONTEXT_CONTROL_NO_FINISH_HASH; 2221b44c5a6SAntoine Ténart } 2231b44c5a6SAntoine Ténart } 2241b44c5a6SAntoine Ténart 22541abed7dSPascal van Leeuwen static int safexcel_ahash_enqueue(struct ahash_request *areq); 22641abed7dSPascal van Leeuwen 22741abed7dSPascal van Leeuwen static int safexcel_handle_req_result(struct safexcel_crypto_priv *priv, 22841abed7dSPascal van Leeuwen int ring, 2291b44c5a6SAntoine Ténart struct crypto_async_request *async, 2301b44c5a6SAntoine Ténart bool *should_complete, int *ret) 2311b44c5a6SAntoine Ténart { 2321b44c5a6SAntoine Ténart struct safexcel_result_desc *rdesc; 2331b44c5a6SAntoine Ténart struct ahash_request *areq = ahash_request_cast(async); 2341b44c5a6SAntoine Ténart struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); 2351b44c5a6SAntoine Ténart struct safexcel_ahash_req *sreq = ahash_request_ctx(areq); 23641abed7dSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(ahash); 237b460edb6SAntoine Tenart u64 cache_len; 2381b44c5a6SAntoine Ténart 2391b44c5a6SAntoine Ténart *ret = 0; 2401b44c5a6SAntoine Ténart 2411b44c5a6SAntoine Ténart rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr); 2421b44c5a6SAntoine Ténart if (IS_ERR(rdesc)) { 2431b44c5a6SAntoine Ténart dev_err(priv->dev, 2441b44c5a6SAntoine Ténart "hash: result: could not retrieve the result descriptor\n"); 2451b44c5a6SAntoine Ténart *ret = PTR_ERR(rdesc); 246bdfd1909SAntoine Tenart } else { 247bdfd1909SAntoine Tenart *ret = safexcel_rdesc_check_errors(priv, rdesc); 2481b44c5a6SAntoine Ténart } 2491b44c5a6SAntoine Ténart 2501b44c5a6SAntoine Ténart safexcel_complete(priv, ring); 2511b44c5a6SAntoine Ténart 252c957f8b3SAntoine Ténart if (sreq->nents) { 253c957f8b3SAntoine Ténart dma_unmap_sg(priv->dev, areq->src, sreq->nents, DMA_TO_DEVICE); 254c957f8b3SAntoine Ténart sreq->nents = 0; 255c957f8b3SAntoine Ténart } 2561b44c5a6SAntoine Ténart 257b8592027SOfer Heifetz if (sreq->result_dma) { 2586c1c09b3SPascal van Leeuwen dma_unmap_single(priv->dev, sreq->result_dma, sreq->digest_sz, 259b8592027SOfer Heifetz DMA_FROM_DEVICE); 260b8592027SOfer Heifetz sreq->result_dma = 0; 261b8592027SOfer Heifetz } 262b8592027SOfer Heifetz 263cff9a175SAntoine Tenart if (sreq->cache_dma) { 264cff9a175SAntoine Tenart dma_unmap_single(priv->dev, sreq->cache_dma, sreq->cache_sz, 265cff9a175SAntoine Tenart DMA_TO_DEVICE); 266cff9a175SAntoine Tenart sreq->cache_dma = 0; 267aa524286SAntoine Tenart sreq->cache_sz = 0; 268cff9a175SAntoine Tenart } 2691b44c5a6SAntoine Ténart 27041abed7dSPascal van Leeuwen if (sreq->finish) { 27141abed7dSPascal van Leeuwen if (sreq->hmac && 27241abed7dSPascal van Leeuwen (sreq->digest != CONTEXT_CONTROL_DIGEST_HMAC)) { 27341abed7dSPascal van Leeuwen /* Faking HMAC using hash - need to do outer hash */ 27441abed7dSPascal van Leeuwen memcpy(sreq->cache, sreq->state, 27541abed7dSPascal van Leeuwen crypto_ahash_digestsize(ahash)); 27641abed7dSPascal van Leeuwen 2776c1c09b3SPascal van Leeuwen memcpy(sreq->state, ctx->opad, sreq->digest_sz); 27841abed7dSPascal van Leeuwen 27931fb084cSPascal van Leeuwen sreq->len = sreq->block_sz + 28041abed7dSPascal van Leeuwen crypto_ahash_digestsize(ahash); 28131fb084cSPascal van Leeuwen sreq->processed = sreq->block_sz; 28241abed7dSPascal van Leeuwen sreq->hmac = 0; 28341abed7dSPascal van Leeuwen 284177e358cSPascal van Leeuwen if (priv->flags & EIP197_TRC_CACHE) 28541abed7dSPascal van Leeuwen ctx->base.needs_inv = true; 28641abed7dSPascal van Leeuwen areq->nbytes = 0; 28741abed7dSPascal van Leeuwen safexcel_ahash_enqueue(areq); 28841abed7dSPascal van Leeuwen 28941abed7dSPascal van Leeuwen *should_complete = false; /* Not done yet */ 29041abed7dSPascal van Leeuwen return 1; 29141abed7dSPascal van Leeuwen } 29241abed7dSPascal van Leeuwen 293b98687bbSPascal van Leeuwen if (unlikely(sreq->digest == CONTEXT_CONTROL_DIGEST_XCM && 294b98687bbSPascal van Leeuwen ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_CRC32)) { 295a7cf8658SPascal van Leeuwen /* Undo final XOR with 0xffffffff ...*/ 29613a1bb93SPascal van Leeuwen *(__le32 *)areq->result = ~sreq->state[0]; 297a7cf8658SPascal van Leeuwen } else { 298b89a8159SAntoine Tenart memcpy(areq->result, sreq->state, 299b89a8159SAntoine Tenart crypto_ahash_digestsize(ahash)); 30041abed7dSPascal van Leeuwen } 301a7cf8658SPascal van Leeuwen } 302b89a8159SAntoine Tenart 303b460edb6SAntoine Tenart cache_len = safexcel_queued_len(sreq); 3041b44c5a6SAntoine Ténart if (cache_len) 3051b44c5a6SAntoine Ténart memcpy(sreq->cache, sreq->cache_next, cache_len); 3061b44c5a6SAntoine Ténart 3071b44c5a6SAntoine Ténart *should_complete = true; 3081b44c5a6SAntoine Ténart 3091b44c5a6SAntoine Ténart return 1; 3101b44c5a6SAntoine Ténart } 3111b44c5a6SAntoine Ténart 3121eb7b403SOfer Heifetz static int safexcel_ahash_send_req(struct crypto_async_request *async, int ring, 3131eb7b403SOfer Heifetz int *commands, int *results) 3141b44c5a6SAntoine Ténart { 3151b44c5a6SAntoine Ténart struct ahash_request *areq = ahash_request_cast(async); 3161b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 3171b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 31818e51895SHerbert Xu struct safexcel_crypto_priv *priv = ctx->base.priv; 3191b44c5a6SAntoine Ténart struct safexcel_command_desc *cdesc, *first_cdesc = NULL; 3201b44c5a6SAntoine Ténart struct safexcel_result_desc *rdesc; 3211b44c5a6SAntoine Ténart struct scatterlist *sg; 322098e51e5SPascal van Leeuwen struct safexcel_token *dmmy; 3236c1c09b3SPascal van Leeuwen int i, extra = 0, n_cdesc = 0, ret = 0, cache_len, skip = 0; 324b98687bbSPascal van Leeuwen u64 queued, len; 3251b44c5a6SAntoine Ténart 326b98687bbSPascal van Leeuwen queued = safexcel_queued_len(req); 32741abed7dSPascal van Leeuwen if (queued <= HASH_CACHE_SIZE) 3281b44c5a6SAntoine Ténart cache_len = queued; 3291b44c5a6SAntoine Ténart else 3301b44c5a6SAntoine Ténart cache_len = queued - areq->nbytes; 3311b44c5a6SAntoine Ténart 33241abed7dSPascal van Leeuwen if (!req->finish && !req->last_req) { 333809778e0SAntoine Ténart /* If this is not the last request and the queued data does not 33441abed7dSPascal van Leeuwen * fit into full cache blocks, cache it for the next send call. 3351b44c5a6SAntoine Ténart */ 33641abed7dSPascal van Leeuwen extra = queued & (HASH_CACHE_SIZE - 1); 337082ec2d4SAntoine Tenart 338809778e0SAntoine Ténart /* If this is not the last request and the queued data 339809778e0SAntoine Ténart * is a multiple of a block, cache the last one for now. 340809778e0SAntoine Ténart */ 341dd4306a6SAntoine Tenart if (!extra) 34241abed7dSPascal van Leeuwen extra = HASH_CACHE_SIZE; 343809778e0SAntoine Ténart 3441b44c5a6SAntoine Ténart sg_pcopy_to_buffer(areq->src, sg_nents(areq->src), 345809778e0SAntoine Ténart req->cache_next, extra, 346809778e0SAntoine Ténart areq->nbytes - extra); 3471b44c5a6SAntoine Ténart 3481b44c5a6SAntoine Ténart queued -= extra; 349dc5268b6SPascal van Leeuwen 350dc5268b6SPascal van Leeuwen if (!queued) { 351dc5268b6SPascal van Leeuwen *commands = 0; 352dc5268b6SPascal van Leeuwen *results = 0; 353dc5268b6SPascal van Leeuwen return 0; 354dc5268b6SPascal van Leeuwen } 355b98687bbSPascal van Leeuwen 356b98687bbSPascal van Leeuwen extra = 0; 357809778e0SAntoine Ténart } 3581b44c5a6SAntoine Ténart 359b98687bbSPascal van Leeuwen if (unlikely(req->xcbcmac && req->processed > AES_BLOCK_SIZE)) { 360b98687bbSPascal van Leeuwen if (unlikely(cache_len < AES_BLOCK_SIZE)) { 361b98687bbSPascal van Leeuwen /* 362b98687bbSPascal van Leeuwen * Cache contains less than 1 full block, complete. 363b98687bbSPascal van Leeuwen */ 364b98687bbSPascal van Leeuwen extra = AES_BLOCK_SIZE - cache_len; 365b98687bbSPascal van Leeuwen if (queued > cache_len) { 366b98687bbSPascal van Leeuwen /* More data follows: borrow bytes */ 367b98687bbSPascal van Leeuwen u64 tmp = queued - cache_len; 368b98687bbSPascal van Leeuwen 369b98687bbSPascal van Leeuwen skip = min_t(u64, tmp, extra); 370b98687bbSPascal van Leeuwen sg_pcopy_to_buffer(areq->src, 371b98687bbSPascal van Leeuwen sg_nents(areq->src), 372b98687bbSPascal van Leeuwen req->cache + cache_len, 373b98687bbSPascal van Leeuwen skip, 0); 374b98687bbSPascal van Leeuwen } 375b98687bbSPascal van Leeuwen extra -= skip; 376b98687bbSPascal van Leeuwen memset(req->cache + cache_len + skip, 0, extra); 37738f21b4bSPascal van Leeuwen if (!ctx->cbcmac && extra) { 37838f21b4bSPascal van Leeuwen // 10- padding for XCBCMAC & CMAC 37938f21b4bSPascal van Leeuwen req->cache[cache_len + skip] = 0x80; 38038f21b4bSPascal van Leeuwen // HW will use K2 iso K3 - compensate! 38138f21b4bSPascal van Leeuwen for (i = 0; i < AES_BLOCK_SIZE / sizeof(u32); i++) 38213a1bb93SPascal van Leeuwen ((__be32 *)req->cache)[i] ^= 38313a1bb93SPascal van Leeuwen cpu_to_be32(le32_to_cpu( 38413a1bb93SPascal van Leeuwen ctx->ipad[i] ^ ctx->ipad[i + 4])); 38538f21b4bSPascal van Leeuwen } 386b98687bbSPascal van Leeuwen cache_len = AES_BLOCK_SIZE; 387b98687bbSPascal van Leeuwen queued = queued + extra; 388b98687bbSPascal van Leeuwen } 389b98687bbSPascal van Leeuwen 390b98687bbSPascal van Leeuwen /* XCBC continue: XOR previous result into 1st word */ 391b98687bbSPascal van Leeuwen crypto_xor(req->cache, (const u8 *)req->state, AES_BLOCK_SIZE); 392b98687bbSPascal van Leeuwen } 393b98687bbSPascal van Leeuwen 394b98687bbSPascal van Leeuwen len = queued; 3951b44c5a6SAntoine Ténart /* Add a command descriptor for the cached data, if any */ 3961b44c5a6SAntoine Ténart if (cache_len) { 397cff9a175SAntoine Tenart req->cache_dma = dma_map_single(priv->dev, req->cache, 3981b44c5a6SAntoine Ténart cache_len, DMA_TO_DEVICE); 3999744fec9SOfer Heifetz if (dma_mapping_error(priv->dev, req->cache_dma)) 400cff9a175SAntoine Tenart return -EINVAL; 4011b44c5a6SAntoine Ténart 402cff9a175SAntoine Tenart req->cache_sz = cache_len; 4031b44c5a6SAntoine Ténart first_cdesc = safexcel_add_cdesc(priv, ring, 1, 4041b44c5a6SAntoine Ténart (cache_len == len), 405b98687bbSPascal van Leeuwen req->cache_dma, cache_len, 406098e51e5SPascal van Leeuwen len, ctx->base.ctxr_dma, 407098e51e5SPascal van Leeuwen &dmmy); 4081b44c5a6SAntoine Ténart if (IS_ERR(first_cdesc)) { 4091b44c5a6SAntoine Ténart ret = PTR_ERR(first_cdesc); 4101b44c5a6SAntoine Ténart goto unmap_cache; 4111b44c5a6SAntoine Ténart } 4121b44c5a6SAntoine Ténart n_cdesc++; 4131b44c5a6SAntoine Ténart 4141b44c5a6SAntoine Ténart queued -= cache_len; 4151b44c5a6SAntoine Ténart if (!queued) 4161b44c5a6SAntoine Ténart goto send_command; 4171b44c5a6SAntoine Ténart } 4181b44c5a6SAntoine Ténart 4191b44c5a6SAntoine Ténart /* Now handle the current ahash request buffer(s) */ 42041abed7dSPascal van Leeuwen req->nents = dma_map_sg(priv->dev, areq->src, 42141abed7dSPascal van Leeuwen sg_nents_for_len(areq->src, 42241abed7dSPascal van Leeuwen areq->nbytes), 4231b44c5a6SAntoine Ténart DMA_TO_DEVICE); 424c957f8b3SAntoine Ténart if (!req->nents) { 4251b44c5a6SAntoine Ténart ret = -ENOMEM; 4261b44c5a6SAntoine Ténart goto cdesc_rollback; 4271b44c5a6SAntoine Ténart } 4281b44c5a6SAntoine Ténart 429c957f8b3SAntoine Ténart for_each_sg(areq->src, sg, req->nents, i) { 4301b44c5a6SAntoine Ténart int sglen = sg_dma_len(sg); 4311b44c5a6SAntoine Ténart 432b98687bbSPascal van Leeuwen if (unlikely(sglen <= skip)) { 433b98687bbSPascal van Leeuwen skip -= sglen; 434b98687bbSPascal van Leeuwen continue; 435b98687bbSPascal van Leeuwen } 436b98687bbSPascal van Leeuwen 4371b44c5a6SAntoine Ténart /* Do not overflow the request */ 438b98687bbSPascal van Leeuwen if ((queued + skip) <= sglen) 4391b44c5a6SAntoine Ténart sglen = queued; 440b98687bbSPascal van Leeuwen else 441b98687bbSPascal van Leeuwen sglen -= skip; 4421b44c5a6SAntoine Ténart 4431b44c5a6SAntoine Ténart cdesc = safexcel_add_cdesc(priv, ring, !n_cdesc, 44441abed7dSPascal van Leeuwen !(queued - sglen), 445b98687bbSPascal van Leeuwen sg_dma_address(sg) + skip, sglen, 446098e51e5SPascal van Leeuwen len, ctx->base.ctxr_dma, &dmmy); 4471b44c5a6SAntoine Ténart if (IS_ERR(cdesc)) { 4481b44c5a6SAntoine Ténart ret = PTR_ERR(cdesc); 44957433b58SAntoine Tenart goto unmap_sg; 4501b44c5a6SAntoine Ténart } 4511b44c5a6SAntoine Ténart 452b98687bbSPascal van Leeuwen if (!n_cdesc) 4531b44c5a6SAntoine Ténart first_cdesc = cdesc; 454b98687bbSPascal van Leeuwen n_cdesc++; 4551b44c5a6SAntoine Ténart 4561b44c5a6SAntoine Ténart queued -= sglen; 4571b44c5a6SAntoine Ténart if (!queued) 4581b44c5a6SAntoine Ténart break; 459b98687bbSPascal van Leeuwen skip = 0; 4601b44c5a6SAntoine Ténart } 4611b44c5a6SAntoine Ténart 4621b44c5a6SAntoine Ténart send_command: 4631b44c5a6SAntoine Ténart /* Setup the context options */ 46441abed7dSPascal van Leeuwen safexcel_context_control(ctx, req, first_cdesc); 4651b44c5a6SAntoine Ténart 4666c1c09b3SPascal van Leeuwen /* Add the token */ 4676c1c09b3SPascal van Leeuwen safexcel_hash_token(first_cdesc, len, req->digest_sz, ctx->cbcmac); 4681b44c5a6SAntoine Ténart 4696c1c09b3SPascal van Leeuwen req->result_dma = dma_map_single(priv->dev, req->state, req->digest_sz, 470b8592027SOfer Heifetz DMA_FROM_DEVICE); 471b8592027SOfer Heifetz if (dma_mapping_error(priv->dev, req->result_dma)) { 4721b44c5a6SAntoine Ténart ret = -EINVAL; 47357433b58SAntoine Tenart goto unmap_sg; 4741b44c5a6SAntoine Ténart } 4751b44c5a6SAntoine Ténart 4761b44c5a6SAntoine Ténart /* Add a result descriptor */ 477b8592027SOfer Heifetz rdesc = safexcel_add_rdesc(priv, ring, 1, 1, req->result_dma, 4786c1c09b3SPascal van Leeuwen req->digest_sz); 4791b44c5a6SAntoine Ténart if (IS_ERR(rdesc)) { 4801b44c5a6SAntoine Ténart ret = PTR_ERR(rdesc); 48157240a78SAntoine Tenart goto unmap_result; 4821b44c5a6SAntoine Ténart } 4831b44c5a6SAntoine Ténart 4849744fec9SOfer Heifetz safexcel_rdr_req_set(priv, ring, rdesc, &areq->base); 4851b44c5a6SAntoine Ténart 486b98687bbSPascal van Leeuwen req->processed += len - extra; 487b460edb6SAntoine Tenart 4881b44c5a6SAntoine Ténart *commands = n_cdesc; 4891b44c5a6SAntoine Ténart *results = 1; 4901b44c5a6SAntoine Ténart return 0; 4911b44c5a6SAntoine Ténart 49257240a78SAntoine Tenart unmap_result: 4936c1c09b3SPascal van Leeuwen dma_unmap_single(priv->dev, req->result_dma, req->digest_sz, 49457433b58SAntoine Tenart DMA_FROM_DEVICE); 49557433b58SAntoine Tenart unmap_sg: 496b98687bbSPascal van Leeuwen if (req->nents) { 49757240a78SAntoine Tenart dma_unmap_sg(priv->dev, areq->src, req->nents, DMA_TO_DEVICE); 498b98687bbSPascal van Leeuwen req->nents = 0; 499b98687bbSPascal van Leeuwen } 5001b44c5a6SAntoine Ténart cdesc_rollback: 5011b44c5a6SAntoine Ténart for (i = 0; i < n_cdesc; i++) 5021b44c5a6SAntoine Ténart safexcel_ring_rollback_wptr(priv, &priv->ring[ring].cdr); 5031b44c5a6SAntoine Ténart unmap_cache: 504cff9a175SAntoine Tenart if (req->cache_dma) { 505cff9a175SAntoine Tenart dma_unmap_single(priv->dev, req->cache_dma, req->cache_sz, 506cff9a175SAntoine Tenart DMA_TO_DEVICE); 507aa524286SAntoine Tenart req->cache_dma = 0; 508cff9a175SAntoine Tenart req->cache_sz = 0; 5091b44c5a6SAntoine Ténart } 5101b44c5a6SAntoine Ténart 5111b44c5a6SAntoine Ténart return ret; 5121b44c5a6SAntoine Ténart } 5131b44c5a6SAntoine Ténart 5141b44c5a6SAntoine Ténart static int safexcel_handle_inv_result(struct safexcel_crypto_priv *priv, 5151b44c5a6SAntoine Ténart int ring, 5161b44c5a6SAntoine Ténart struct crypto_async_request *async, 5171b44c5a6SAntoine Ténart bool *should_complete, int *ret) 5181b44c5a6SAntoine Ténart { 5191b44c5a6SAntoine Ténart struct safexcel_result_desc *rdesc; 5201b44c5a6SAntoine Ténart struct ahash_request *areq = ahash_request_cast(async); 5211b44c5a6SAntoine Ténart struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); 5221b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(ahash); 5231b44c5a6SAntoine Ténart int enq_ret; 5241b44c5a6SAntoine Ténart 5251b44c5a6SAntoine Ténart *ret = 0; 5261b44c5a6SAntoine Ténart 5271b44c5a6SAntoine Ténart rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr); 5281b44c5a6SAntoine Ténart if (IS_ERR(rdesc)) { 5291b44c5a6SAntoine Ténart dev_err(priv->dev, 5301b44c5a6SAntoine Ténart "hash: invalidate: could not retrieve the result descriptor\n"); 5311b44c5a6SAntoine Ténart *ret = PTR_ERR(rdesc); 532cda3e73aSAntoine Tenart } else { 533cda3e73aSAntoine Tenart *ret = safexcel_rdesc_check_errors(priv, rdesc); 5341b44c5a6SAntoine Ténart } 5351b44c5a6SAntoine Ténart 5361b44c5a6SAntoine Ténart safexcel_complete(priv, ring); 5371b44c5a6SAntoine Ténart 5381b44c5a6SAntoine Ténart if (ctx->base.exit_inv) { 5391b44c5a6SAntoine Ténart dma_pool_free(priv->context_pool, ctx->base.ctxr, 5401b44c5a6SAntoine Ténart ctx->base.ctxr_dma); 5411b44c5a6SAntoine Ténart 5421b44c5a6SAntoine Ténart *should_complete = true; 5431b44c5a6SAntoine Ténart return 1; 5441b44c5a6SAntoine Ténart } 5451b44c5a6SAntoine Ténart 54686671abbSAntoine Ténart ring = safexcel_select_ring(priv); 54786671abbSAntoine Ténart ctx->base.ring = ring; 5481b44c5a6SAntoine Ténart 54986671abbSAntoine Ténart spin_lock_bh(&priv->ring[ring].queue_lock); 55086671abbSAntoine Ténart enq_ret = crypto_enqueue_request(&priv->ring[ring].queue, async); 55186671abbSAntoine Ténart spin_unlock_bh(&priv->ring[ring].queue_lock); 5521b44c5a6SAntoine Ténart 5531b44c5a6SAntoine Ténart if (enq_ret != -EINPROGRESS) 5541b44c5a6SAntoine Ténart *ret = enq_ret; 5551b44c5a6SAntoine Ténart 5568472e778SAntoine Ténart queue_work(priv->ring[ring].workqueue, 5578472e778SAntoine Ténart &priv->ring[ring].work_data.work); 55886671abbSAntoine Ténart 5591b44c5a6SAntoine Ténart *should_complete = false; 5601b44c5a6SAntoine Ténart 5611b44c5a6SAntoine Ténart return 1; 5621b44c5a6SAntoine Ténart } 5631b44c5a6SAntoine Ténart 5641eb7b403SOfer Heifetz static int safexcel_handle_result(struct safexcel_crypto_priv *priv, int ring, 5651eb7b403SOfer Heifetz struct crypto_async_request *async, 5661eb7b403SOfer Heifetz bool *should_complete, int *ret) 5671eb7b403SOfer Heifetz { 5681eb7b403SOfer Heifetz struct ahash_request *areq = ahash_request_cast(async); 5691eb7b403SOfer Heifetz struct safexcel_ahash_req *req = ahash_request_ctx(areq); 5701eb7b403SOfer Heifetz int err; 5711eb7b403SOfer Heifetz 57253c83e91SAntoine Tenart BUG_ON(!(priv->flags & EIP197_TRC_CACHE) && req->needs_inv); 573871df319SAntoine Ténart 5741eb7b403SOfer Heifetz if (req->needs_inv) { 5751eb7b403SOfer Heifetz req->needs_inv = false; 5761eb7b403SOfer Heifetz err = safexcel_handle_inv_result(priv, ring, async, 5771eb7b403SOfer Heifetz should_complete, ret); 5781eb7b403SOfer Heifetz } else { 5791eb7b403SOfer Heifetz err = safexcel_handle_req_result(priv, ring, async, 5801eb7b403SOfer Heifetz should_complete, ret); 5811eb7b403SOfer Heifetz } 5821eb7b403SOfer Heifetz 5831eb7b403SOfer Heifetz return err; 5841eb7b403SOfer Heifetz } 5851eb7b403SOfer Heifetz 5861b44c5a6SAntoine Ténart static int safexcel_ahash_send_inv(struct crypto_async_request *async, 5879744fec9SOfer Heifetz int ring, int *commands, int *results) 5881b44c5a6SAntoine Ténart { 5891b44c5a6SAntoine Ténart struct ahash_request *areq = ahash_request_cast(async); 5901b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 5911b44c5a6SAntoine Ténart int ret; 5921b44c5a6SAntoine Ténart 59318e51895SHerbert Xu ret = safexcel_invalidate_cache(async, ctx->base.priv, 5949744fec9SOfer Heifetz ctx->base.ctxr_dma, ring); 5951b44c5a6SAntoine Ténart if (unlikely(ret)) 5961b44c5a6SAntoine Ténart return ret; 5971b44c5a6SAntoine Ténart 5981b44c5a6SAntoine Ténart *commands = 1; 5991b44c5a6SAntoine Ténart *results = 1; 6001b44c5a6SAntoine Ténart 6011b44c5a6SAntoine Ténart return 0; 6021b44c5a6SAntoine Ténart } 6031b44c5a6SAntoine Ténart 6041eb7b403SOfer Heifetz static int safexcel_ahash_send(struct crypto_async_request *async, 6059744fec9SOfer Heifetz int ring, int *commands, int *results) 6061eb7b403SOfer Heifetz { 6071eb7b403SOfer Heifetz struct ahash_request *areq = ahash_request_cast(async); 6081eb7b403SOfer Heifetz struct safexcel_ahash_req *req = ahash_request_ctx(areq); 6091eb7b403SOfer Heifetz int ret; 6101eb7b403SOfer Heifetz 6111eb7b403SOfer Heifetz if (req->needs_inv) 6129744fec9SOfer Heifetz ret = safexcel_ahash_send_inv(async, ring, commands, results); 6131eb7b403SOfer Heifetz else 6149744fec9SOfer Heifetz ret = safexcel_ahash_send_req(async, ring, commands, results); 6159744fec9SOfer Heifetz 6161eb7b403SOfer Heifetz return ret; 6171eb7b403SOfer Heifetz } 6181eb7b403SOfer Heifetz 6191b44c5a6SAntoine Ténart static int safexcel_ahash_exit_inv(struct crypto_tfm *tfm) 6201b44c5a6SAntoine Ténart { 6211b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 62218e51895SHerbert Xu struct safexcel_crypto_priv *priv = ctx->base.priv; 62361824806SAntoine Tenart EIP197_REQUEST_ON_STACK(req, ahash, EIP197_AHASH_REQ_SIZE); 6247cad2fabSAntoine Ténart struct safexcel_ahash_req *rctx = ahash_request_ctx(req); 6253e1166b9SArnd Bergmann struct safexcel_inv_result result = {}; 62686671abbSAntoine Ténart int ring = ctx->base.ring; 6271b44c5a6SAntoine Ténart 628b926213dSAntoine Tenart memset(req, 0, EIP197_AHASH_REQ_SIZE); 6291b44c5a6SAntoine Ténart 6301b44c5a6SAntoine Ténart /* create invalidation request */ 6311b44c5a6SAntoine Ténart init_completion(&result.completion); 6327cad2fabSAntoine Ténart ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, 6331b44c5a6SAntoine Ténart safexcel_inv_complete, &result); 6341b44c5a6SAntoine Ténart 6357cad2fabSAntoine Ténart ahash_request_set_tfm(req, __crypto_ahash_cast(tfm)); 6367cad2fabSAntoine Ténart ctx = crypto_tfm_ctx(req->base.tfm); 6371b44c5a6SAntoine Ténart ctx->base.exit_inv = true; 6381eb7b403SOfer Heifetz rctx->needs_inv = true; 6391b44c5a6SAntoine Ténart 64086671abbSAntoine Ténart spin_lock_bh(&priv->ring[ring].queue_lock); 6417cad2fabSAntoine Ténart crypto_enqueue_request(&priv->ring[ring].queue, &req->base); 64286671abbSAntoine Ténart spin_unlock_bh(&priv->ring[ring].queue_lock); 6431b44c5a6SAntoine Ténart 6448472e778SAntoine Ténart queue_work(priv->ring[ring].workqueue, 6458472e778SAntoine Ténart &priv->ring[ring].work_data.work); 6461b44c5a6SAntoine Ténart 647b7007dbcSAntoine Tenart wait_for_completion(&result.completion); 6481b44c5a6SAntoine Ténart 6491b44c5a6SAntoine Ténart if (result.error) { 6501b44c5a6SAntoine Ténart dev_warn(priv->dev, "hash: completion error (%d)\n", 6511b44c5a6SAntoine Ténart result.error); 6521b44c5a6SAntoine Ténart return result.error; 6531b44c5a6SAntoine Ténart } 6541b44c5a6SAntoine Ténart 6551b44c5a6SAntoine Ténart return 0; 6561b44c5a6SAntoine Ténart } 6571b44c5a6SAntoine Ténart 658cc75f5ceSAntoine Ténart /* safexcel_ahash_cache: cache data until at least one request can be sent to 659cc75f5ceSAntoine Ténart * the engine, aka. when there is at least 1 block size in the pipe. 660cc75f5ceSAntoine Ténart */ 66141abed7dSPascal van Leeuwen static int safexcel_ahash_cache(struct ahash_request *areq) 6621b44c5a6SAntoine Ténart { 6631b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 66441abed7dSPascal van Leeuwen u64 cache_len; 6651b44c5a6SAntoine Ténart 666b460edb6SAntoine Tenart /* cache_len: everything accepted by the driver but not sent yet, 667b460edb6SAntoine Tenart * tot sz handled by update() - last req sz - tot sz handled by send() 668b460edb6SAntoine Tenart */ 66941abed7dSPascal van Leeuwen cache_len = safexcel_queued_len(req); 6701b44c5a6SAntoine Ténart 6711b44c5a6SAntoine Ténart /* 6721b44c5a6SAntoine Ténart * In case there isn't enough bytes to proceed (less than a 6731b44c5a6SAntoine Ténart * block size), cache the data until we have enough. 6741b44c5a6SAntoine Ténart */ 67541abed7dSPascal van Leeuwen if (cache_len + areq->nbytes <= HASH_CACHE_SIZE) { 6761b44c5a6SAntoine Ténart sg_pcopy_to_buffer(areq->src, sg_nents(areq->src), 6771b44c5a6SAntoine Ténart req->cache + cache_len, 6781b44c5a6SAntoine Ténart areq->nbytes, 0); 67941abed7dSPascal van Leeuwen return 0; 6801b44c5a6SAntoine Ténart } 6811b44c5a6SAntoine Ténart 682dfbcc08fSAntoine Ténart /* We couldn't cache all the data */ 6831b44c5a6SAntoine Ténart return -E2BIG; 6841b44c5a6SAntoine Ténart } 6851b44c5a6SAntoine Ténart 6861b44c5a6SAntoine Ténart static int safexcel_ahash_enqueue(struct ahash_request *areq) 6871b44c5a6SAntoine Ténart { 6881b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 6891b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 69018e51895SHerbert Xu struct safexcel_crypto_priv *priv = ctx->base.priv; 69186671abbSAntoine Ténart int ret, ring; 6921b44c5a6SAntoine Ténart 6931eb7b403SOfer Heifetz req->needs_inv = false; 6941b44c5a6SAntoine Ténart 695c4daf4ccSOfer Heifetz if (ctx->base.ctxr) { 69653c83e91SAntoine Tenart if (priv->flags & EIP197_TRC_CACHE && !ctx->base.needs_inv && 697b98687bbSPascal van Leeuwen /* invalidate for *any* non-XCBC continuation */ 698b98687bbSPascal van Leeuwen ((req->not_first && !req->xcbcmac) || 69941abed7dSPascal van Leeuwen /* invalidate if (i)digest changed */ 70041abed7dSPascal van Leeuwen memcmp(ctx->base.ctxr->data, req->state, req->state_sz) || 70141abed7dSPascal van Leeuwen /* invalidate for HMAC finish with odigest changed */ 702a7cf8658SPascal van Leeuwen (req->finish && req->hmac && 70341abed7dSPascal van Leeuwen memcmp(ctx->base.ctxr->data + (req->state_sz>>2), 70441abed7dSPascal van Leeuwen ctx->opad, req->state_sz)))) 70541abed7dSPascal van Leeuwen /* 70641abed7dSPascal van Leeuwen * We're still setting needs_inv here, even though it is 707c4daf4ccSOfer Heifetz * cleared right away, because the needs_inv flag can be 708c4daf4ccSOfer Heifetz * set in other functions and we want to keep the same 709c4daf4ccSOfer Heifetz * logic. 710c4daf4ccSOfer Heifetz */ 71141abed7dSPascal van Leeuwen ctx->base.needs_inv = true; 7121b44c5a6SAntoine Ténart 7131eb7b403SOfer Heifetz if (ctx->base.needs_inv) { 7141eb7b403SOfer Heifetz ctx->base.needs_inv = false; 7151eb7b403SOfer Heifetz req->needs_inv = true; 7161eb7b403SOfer Heifetz } 7171b44c5a6SAntoine Ténart } else { 7181b44c5a6SAntoine Ténart ctx->base.ring = safexcel_select_ring(priv); 7191b44c5a6SAntoine Ténart ctx->base.ctxr = dma_pool_zalloc(priv->context_pool, 7201b44c5a6SAntoine Ténart EIP197_GFP_FLAGS(areq->base), 7211b44c5a6SAntoine Ténart &ctx->base.ctxr_dma); 7221b44c5a6SAntoine Ténart if (!ctx->base.ctxr) 7231b44c5a6SAntoine Ténart return -ENOMEM; 7241b44c5a6SAntoine Ténart } 725b98687bbSPascal van Leeuwen req->not_first = true; 7261b44c5a6SAntoine Ténart 72786671abbSAntoine Ténart ring = ctx->base.ring; 7281b44c5a6SAntoine Ténart 72986671abbSAntoine Ténart spin_lock_bh(&priv->ring[ring].queue_lock); 73086671abbSAntoine Ténart ret = crypto_enqueue_request(&priv->ring[ring].queue, &areq->base); 73186671abbSAntoine Ténart spin_unlock_bh(&priv->ring[ring].queue_lock); 73286671abbSAntoine Ténart 7338472e778SAntoine Ténart queue_work(priv->ring[ring].workqueue, 7348472e778SAntoine Ténart &priv->ring[ring].work_data.work); 7351b44c5a6SAntoine Ténart 7361b44c5a6SAntoine Ténart return ret; 7371b44c5a6SAntoine Ténart } 7381b44c5a6SAntoine Ténart 7391b44c5a6SAntoine Ténart static int safexcel_ahash_update(struct ahash_request *areq) 7401b44c5a6SAntoine Ténart { 7411b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 74241abed7dSPascal van Leeuwen int ret; 7431b44c5a6SAntoine Ténart 7441b44c5a6SAntoine Ténart /* If the request is 0 length, do nothing */ 7451b44c5a6SAntoine Ténart if (!areq->nbytes) 7461b44c5a6SAntoine Ténart return 0; 7471b44c5a6SAntoine Ténart 74841abed7dSPascal van Leeuwen /* Add request to the cache if it fits */ 74941abed7dSPascal van Leeuwen ret = safexcel_ahash_cache(areq); 75041abed7dSPascal van Leeuwen 75141abed7dSPascal van Leeuwen /* Update total request length */ 75231fb084cSPascal van Leeuwen req->len += areq->nbytes; 7531b44c5a6SAntoine Ténart 75441abed7dSPascal van Leeuwen /* If not all data could fit into the cache, go process the excess. 75541abed7dSPascal van Leeuwen * Also go process immediately for an HMAC IV precompute, which 75641abed7dSPascal van Leeuwen * will never be finished at all, but needs to be processed anyway. 7571b44c5a6SAntoine Ténart */ 75841abed7dSPascal van Leeuwen if ((ret && !req->finish) || req->last_req) 7591b44c5a6SAntoine Ténart return safexcel_ahash_enqueue(areq); 7601b44c5a6SAntoine Ténart 7611b44c5a6SAntoine Ténart return 0; 7621b44c5a6SAntoine Ténart } 7631b44c5a6SAntoine Ténart 7641b44c5a6SAntoine Ténart static int safexcel_ahash_final(struct ahash_request *areq) 7651b44c5a6SAntoine Ténart { 7661b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 7671b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 7681b44c5a6SAntoine Ténart 7691b44c5a6SAntoine Ténart req->finish = true; 7701b44c5a6SAntoine Ténart 77131fb084cSPascal van Leeuwen if (unlikely(!req->len && !areq->nbytes)) { 77285695b09SPascal van Leeuwen /* 77385695b09SPascal van Leeuwen * If we have an overall 0 length *hash* request: 77485695b09SPascal van Leeuwen * The HW cannot do 0 length hash, so we provide the correct 77585695b09SPascal van Leeuwen * result directly here. 77685695b09SPascal van Leeuwen */ 777293f89cfSOfer Heifetz if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_MD5) 778293f89cfSOfer Heifetz memcpy(areq->result, md5_zero_message_hash, 779293f89cfSOfer Heifetz MD5_DIGEST_SIZE); 780293f89cfSOfer Heifetz else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA1) 7811b44c5a6SAntoine Ténart memcpy(areq->result, sha1_zero_message_hash, 7821b44c5a6SAntoine Ténart SHA1_DIGEST_SIZE); 7831b44c5a6SAntoine Ténart else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA224) 7841b44c5a6SAntoine Ténart memcpy(areq->result, sha224_zero_message_hash, 7851b44c5a6SAntoine Ténart SHA224_DIGEST_SIZE); 7861b44c5a6SAntoine Ténart else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA256) 7871b44c5a6SAntoine Ténart memcpy(areq->result, sha256_zero_message_hash, 7881b44c5a6SAntoine Ténart SHA256_DIGEST_SIZE); 7899e46eafdSAntoine Tenart else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA384) 7909e46eafdSAntoine Tenart memcpy(areq->result, sha384_zero_message_hash, 7919e46eafdSAntoine Tenart SHA384_DIGEST_SIZE); 792b460edb6SAntoine Tenart else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA512) 793b460edb6SAntoine Tenart memcpy(areq->result, sha512_zero_message_hash, 794b460edb6SAntoine Tenart SHA512_DIGEST_SIZE); 7950f2bc131SPascal van Leeuwen else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SM3) { 7960f2bc131SPascal van Leeuwen memcpy(areq->result, 7970f2bc131SPascal van Leeuwen EIP197_SM3_ZEROM_HASH, SM3_DIGEST_SIZE); 7980f2bc131SPascal van Leeuwen } 7991b44c5a6SAntoine Ténart 8001b44c5a6SAntoine Ténart return 0; 801a7cf8658SPascal van Leeuwen } else if (unlikely(req->digest == CONTEXT_CONTROL_DIGEST_XCM && 802a7cf8658SPascal van Leeuwen ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_MD5 && 803a7cf8658SPascal van Leeuwen req->len == sizeof(u32) && !areq->nbytes)) { 804a7cf8658SPascal van Leeuwen /* Zero length CRC32 */ 805a7cf8658SPascal van Leeuwen memcpy(areq->result, ctx->ipad, sizeof(u32)); 806a7cf8658SPascal van Leeuwen return 0; 80738f21b4bSPascal van Leeuwen } else if (unlikely(ctx->cbcmac && req->len == AES_BLOCK_SIZE && 808b98687bbSPascal van Leeuwen !areq->nbytes)) { 809b98687bbSPascal van Leeuwen /* Zero length CBC MAC */ 810b98687bbSPascal van Leeuwen memset(areq->result, 0, AES_BLOCK_SIZE); 811b98687bbSPascal van Leeuwen return 0; 81238f21b4bSPascal van Leeuwen } else if (unlikely(req->xcbcmac && req->len == AES_BLOCK_SIZE && 81338f21b4bSPascal van Leeuwen !areq->nbytes)) { 81438f21b4bSPascal van Leeuwen /* Zero length (X)CBC/CMAC */ 81538f21b4bSPascal van Leeuwen int i; 81638f21b4bSPascal van Leeuwen 81738f21b4bSPascal van Leeuwen for (i = 0; i < AES_BLOCK_SIZE / sizeof(u32); i++) 81813a1bb93SPascal van Leeuwen ((__be32 *)areq->result)[i] = 81913a1bb93SPascal van Leeuwen cpu_to_be32(le32_to_cpu(ctx->ipad[i + 4]));//K3 82038f21b4bSPascal van Leeuwen areq->result[0] ^= 0x80; // 10- padding 82138f21b4bSPascal van Leeuwen crypto_cipher_encrypt_one(ctx->kaes, areq->result, areq->result); 82238f21b4bSPascal van Leeuwen return 0; 82331fb084cSPascal van Leeuwen } else if (unlikely(req->hmac && 82431fb084cSPascal van Leeuwen (req->len == req->block_sz) && 82541abed7dSPascal van Leeuwen !areq->nbytes)) { 82685b36ee8SPascal van Leeuwen /* 82785b36ee8SPascal van Leeuwen * If we have an overall 0 length *HMAC* request: 82885b36ee8SPascal van Leeuwen * For HMAC, we need to finalize the inner digest 82985b36ee8SPascal van Leeuwen * and then perform the outer hash. 83085b36ee8SPascal van Leeuwen */ 83185b36ee8SPascal van Leeuwen 83285b36ee8SPascal van Leeuwen /* generate pad block in the cache */ 83385b36ee8SPascal van Leeuwen /* start with a hash block of all zeroes */ 83485b36ee8SPascal van Leeuwen memset(req->cache, 0, req->block_sz); 83585b36ee8SPascal van Leeuwen /* set the first byte to 0x80 to 'append a 1 bit' */ 83685b36ee8SPascal van Leeuwen req->cache[0] = 0x80; 83785b36ee8SPascal van Leeuwen /* add the length in bits in the last 2 bytes */ 83885b36ee8SPascal van Leeuwen if (req->len_is_le) { 83985b36ee8SPascal van Leeuwen /* Little endian length word (e.g. MD5) */ 84085b36ee8SPascal van Leeuwen req->cache[req->block_sz-8] = (req->block_sz << 3) & 84185b36ee8SPascal van Leeuwen 255; 84285b36ee8SPascal van Leeuwen req->cache[req->block_sz-7] = (req->block_sz >> 5); 84385b36ee8SPascal van Leeuwen } else { 84485b36ee8SPascal van Leeuwen /* Big endian length word (e.g. any SHA) */ 84585b36ee8SPascal van Leeuwen req->cache[req->block_sz-2] = (req->block_sz >> 5); 84685b36ee8SPascal van Leeuwen req->cache[req->block_sz-1] = (req->block_sz << 3) & 84785b36ee8SPascal van Leeuwen 255; 84885b36ee8SPascal van Leeuwen } 84985b36ee8SPascal van Leeuwen 85031fb084cSPascal van Leeuwen req->len += req->block_sz; /* plus 1 hash block */ 85185b36ee8SPascal van Leeuwen 85285b36ee8SPascal van Leeuwen /* Set special zero-length HMAC flag */ 85385b36ee8SPascal van Leeuwen req->hmac_zlen = true; 85485b36ee8SPascal van Leeuwen 85585b36ee8SPascal van Leeuwen /* Finalize HMAC */ 85685b36ee8SPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_HMAC; 85741abed7dSPascal van Leeuwen } else if (req->hmac) { 85841abed7dSPascal van Leeuwen /* Finalize HMAC */ 85941abed7dSPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_HMAC; 8601b44c5a6SAntoine Ténart } 8611b44c5a6SAntoine Ténart 8621b44c5a6SAntoine Ténart return safexcel_ahash_enqueue(areq); 8631b44c5a6SAntoine Ténart } 8641b44c5a6SAntoine Ténart 8651b44c5a6SAntoine Ténart static int safexcel_ahash_finup(struct ahash_request *areq) 8661b44c5a6SAntoine Ténart { 8671b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 8681b44c5a6SAntoine Ténart 8691b44c5a6SAntoine Ténart req->finish = true; 8701b44c5a6SAntoine Ténart 8711b44c5a6SAntoine Ténart safexcel_ahash_update(areq); 8721b44c5a6SAntoine Ténart return safexcel_ahash_final(areq); 8731b44c5a6SAntoine Ténart } 8741b44c5a6SAntoine Ténart 8751b44c5a6SAntoine Ténart static int safexcel_ahash_export(struct ahash_request *areq, void *out) 8761b44c5a6SAntoine Ténart { 8771b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 8781b44c5a6SAntoine Ténart struct safexcel_ahash_export_state *export = out; 8791b44c5a6SAntoine Ténart 88031fb084cSPascal van Leeuwen export->len = req->len; 88131fb084cSPascal van Leeuwen export->processed = req->processed; 8821b44c5a6SAntoine Ténart 883b869648cSAntoine Tenart export->digest = req->digest; 884b869648cSAntoine Tenart 8851b44c5a6SAntoine Ténart memcpy(export->state, req->state, req->state_sz); 88641abed7dSPascal van Leeuwen memcpy(export->cache, req->cache, HASH_CACHE_SIZE); 8871b44c5a6SAntoine Ténart 8881b44c5a6SAntoine Ténart return 0; 8891b44c5a6SAntoine Ténart } 8901b44c5a6SAntoine Ténart 8911b44c5a6SAntoine Ténart static int safexcel_ahash_import(struct ahash_request *areq, const void *in) 8921b44c5a6SAntoine Ténart { 8931b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 8941b44c5a6SAntoine Ténart const struct safexcel_ahash_export_state *export = in; 8951b44c5a6SAntoine Ténart int ret; 8961b44c5a6SAntoine Ténart 8971b44c5a6SAntoine Ténart ret = crypto_ahash_init(areq); 8981b44c5a6SAntoine Ténart if (ret) 8991b44c5a6SAntoine Ténart return ret; 9001b44c5a6SAntoine Ténart 90131fb084cSPascal van Leeuwen req->len = export->len; 90231fb084cSPascal van Leeuwen req->processed = export->processed; 9031b44c5a6SAntoine Ténart 904b869648cSAntoine Tenart req->digest = export->digest; 905b869648cSAntoine Tenart 90641abed7dSPascal van Leeuwen memcpy(req->cache, export->cache, HASH_CACHE_SIZE); 9071b44c5a6SAntoine Ténart memcpy(req->state, export->state, req->state_sz); 9081b44c5a6SAntoine Ténart 9091b44c5a6SAntoine Ténart return 0; 9101b44c5a6SAntoine Ténart } 9111b44c5a6SAntoine Ténart 9121b44c5a6SAntoine Ténart static int safexcel_ahash_cra_init(struct crypto_tfm *tfm) 9131b44c5a6SAntoine Ténart { 9141b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 9151b44c5a6SAntoine Ténart struct safexcel_alg_template *tmpl = 9161b44c5a6SAntoine Ténart container_of(__crypto_ahash_alg(tfm->__crt_alg), 9171b44c5a6SAntoine Ténart struct safexcel_alg_template, alg.ahash); 9181b44c5a6SAntoine Ténart 91918e51895SHerbert Xu ctx->base.priv = tmpl->priv; 9201eb7b403SOfer Heifetz ctx->base.send = safexcel_ahash_send; 9211eb7b403SOfer Heifetz ctx->base.handle_result = safexcel_handle_result; 9226c1c09b3SPascal van Leeuwen ctx->fb_do_setkey = false; 9231b44c5a6SAntoine Ténart 9241b44c5a6SAntoine Ténart crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), 9251b44c5a6SAntoine Ténart sizeof(struct safexcel_ahash_req)); 9261b44c5a6SAntoine Ténart return 0; 9271b44c5a6SAntoine Ténart } 9281b44c5a6SAntoine Ténart 9291b44c5a6SAntoine Ténart static int safexcel_sha1_init(struct ahash_request *areq) 9301b44c5a6SAntoine Ténart { 9311b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 9321b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 9331b44c5a6SAntoine Ténart 9341b44c5a6SAntoine Ténart memset(req, 0, sizeof(*req)); 9351b44c5a6SAntoine Ténart 9361b44c5a6SAntoine Ténart ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1; 937b869648cSAntoine Tenart req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 9381b44c5a6SAntoine Ténart req->state_sz = SHA1_DIGEST_SIZE; 9396c1c09b3SPascal van Leeuwen req->digest_sz = SHA1_DIGEST_SIZE; 94041abed7dSPascal van Leeuwen req->block_sz = SHA1_BLOCK_SIZE; 9411b44c5a6SAntoine Ténart 9421b44c5a6SAntoine Ténart return 0; 9431b44c5a6SAntoine Ténart } 9441b44c5a6SAntoine Ténart 9451b44c5a6SAntoine Ténart static int safexcel_sha1_digest(struct ahash_request *areq) 9461b44c5a6SAntoine Ténart { 9471b44c5a6SAntoine Ténart int ret = safexcel_sha1_init(areq); 9481b44c5a6SAntoine Ténart 9491b44c5a6SAntoine Ténart if (ret) 9501b44c5a6SAntoine Ténart return ret; 9511b44c5a6SAntoine Ténart 9521b44c5a6SAntoine Ténart return safexcel_ahash_finup(areq); 9531b44c5a6SAntoine Ténart } 9541b44c5a6SAntoine Ténart 9551b44c5a6SAntoine Ténart static void safexcel_ahash_cra_exit(struct crypto_tfm *tfm) 9561b44c5a6SAntoine Ténart { 9571b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 95818e51895SHerbert Xu struct safexcel_crypto_priv *priv = ctx->base.priv; 9591b44c5a6SAntoine Ténart int ret; 9601b44c5a6SAntoine Ténart 9611b44c5a6SAntoine Ténart /* context not allocated, skip invalidation */ 9621b44c5a6SAntoine Ténart if (!ctx->base.ctxr) 9631b44c5a6SAntoine Ténart return; 9641b44c5a6SAntoine Ténart 96553c83e91SAntoine Tenart if (priv->flags & EIP197_TRC_CACHE) { 9661b44c5a6SAntoine Ténart ret = safexcel_ahash_exit_inv(tfm); 9671b44c5a6SAntoine Ténart if (ret) 9681b44c5a6SAntoine Ténart dev_warn(priv->dev, "hash: invalidation error %d\n", ret); 969871df319SAntoine Ténart } else { 970871df319SAntoine Ténart dma_pool_free(priv->context_pool, ctx->base.ctxr, 971871df319SAntoine Ténart ctx->base.ctxr_dma); 972871df319SAntoine Ténart } 9731b44c5a6SAntoine Ténart } 9741b44c5a6SAntoine Ténart 9751b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha1 = { 9761b44c5a6SAntoine Ténart .type = SAFEXCEL_ALG_TYPE_AHASH, 977062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA1, 9781b44c5a6SAntoine Ténart .alg.ahash = { 9791b44c5a6SAntoine Ténart .init = safexcel_sha1_init, 9801b44c5a6SAntoine Ténart .update = safexcel_ahash_update, 9811b44c5a6SAntoine Ténart .final = safexcel_ahash_final, 9821b44c5a6SAntoine Ténart .finup = safexcel_ahash_finup, 9831b44c5a6SAntoine Ténart .digest = safexcel_sha1_digest, 9841b44c5a6SAntoine Ténart .export = safexcel_ahash_export, 9851b44c5a6SAntoine Ténart .import = safexcel_ahash_import, 9861b44c5a6SAntoine Ténart .halg = { 9871b44c5a6SAntoine Ténart .digestsize = SHA1_DIGEST_SIZE, 9881b44c5a6SAntoine Ténart .statesize = sizeof(struct safexcel_ahash_export_state), 9891b44c5a6SAntoine Ténart .base = { 9901b44c5a6SAntoine Ténart .cra_name = "sha1", 9911b44c5a6SAntoine Ténart .cra_driver_name = "safexcel-sha1", 992aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 9931b44c5a6SAntoine Ténart .cra_flags = CRYPTO_ALG_ASYNC | 994b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 9951b44c5a6SAntoine Ténart CRYPTO_ALG_KERN_DRIVER_ONLY, 9961b44c5a6SAntoine Ténart .cra_blocksize = SHA1_BLOCK_SIZE, 9971b44c5a6SAntoine Ténart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 9981b44c5a6SAntoine Ténart .cra_init = safexcel_ahash_cra_init, 9991b44c5a6SAntoine Ténart .cra_exit = safexcel_ahash_cra_exit, 10001b44c5a6SAntoine Ténart .cra_module = THIS_MODULE, 10011b44c5a6SAntoine Ténart }, 10021b44c5a6SAntoine Ténart }, 10031b44c5a6SAntoine Ténart }, 10041b44c5a6SAntoine Ténart }; 10051b44c5a6SAntoine Ténart 10061b44c5a6SAntoine Ténart static int safexcel_hmac_sha1_init(struct ahash_request *areq) 10071b44c5a6SAntoine Ténart { 100841abed7dSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 1009b869648cSAntoine Tenart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 10101b44c5a6SAntoine Ténart 101141abed7dSPascal van Leeuwen memset(req, 0, sizeof(*req)); 101241abed7dSPascal van Leeuwen 101341abed7dSPascal van Leeuwen /* Start from ipad precompute */ 101441abed7dSPascal van Leeuwen memcpy(req->state, ctx->ipad, SHA1_DIGEST_SIZE); 101541abed7dSPascal van Leeuwen /* Already processed the key^ipad part now! */ 101631fb084cSPascal van Leeuwen req->len = SHA1_BLOCK_SIZE; 101731fb084cSPascal van Leeuwen req->processed = SHA1_BLOCK_SIZE; 101841abed7dSPascal van Leeuwen 101941abed7dSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1; 102041abed7dSPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 102141abed7dSPascal van Leeuwen req->state_sz = SHA1_DIGEST_SIZE; 10226c1c09b3SPascal van Leeuwen req->digest_sz = SHA1_DIGEST_SIZE; 102341abed7dSPascal van Leeuwen req->block_sz = SHA1_BLOCK_SIZE; 102441abed7dSPascal van Leeuwen req->hmac = true; 102541abed7dSPascal van Leeuwen 10261b44c5a6SAntoine Ténart return 0; 10271b44c5a6SAntoine Ténart } 10281b44c5a6SAntoine Ténart 10291b44c5a6SAntoine Ténart static int safexcel_hmac_sha1_digest(struct ahash_request *areq) 10301b44c5a6SAntoine Ténart { 10311b44c5a6SAntoine Ténart int ret = safexcel_hmac_sha1_init(areq); 10321b44c5a6SAntoine Ténart 10331b44c5a6SAntoine Ténart if (ret) 10341b44c5a6SAntoine Ténart return ret; 10351b44c5a6SAntoine Ténart 10361b44c5a6SAntoine Ténart return safexcel_ahash_finup(areq); 10371b44c5a6SAntoine Ténart } 10381b44c5a6SAntoine Ténart 10391b44c5a6SAntoine Ténart struct safexcel_ahash_result { 10401b44c5a6SAntoine Ténart struct completion completion; 10411b44c5a6SAntoine Ténart int error; 10421b44c5a6SAntoine Ténart }; 10431b44c5a6SAntoine Ténart 10441b44c5a6SAntoine Ténart static void safexcel_ahash_complete(struct crypto_async_request *req, int error) 10451b44c5a6SAntoine Ténart { 10461b44c5a6SAntoine Ténart struct safexcel_ahash_result *result = req->data; 10471b44c5a6SAntoine Ténart 10481b44c5a6SAntoine Ténart if (error == -EINPROGRESS) 10491b44c5a6SAntoine Ténart return; 10501b44c5a6SAntoine Ténart 10511b44c5a6SAntoine Ténart result->error = error; 10521b44c5a6SAntoine Ténart complete(&result->completion); 10531b44c5a6SAntoine Ténart } 10541b44c5a6SAntoine Ténart 10551b44c5a6SAntoine Ténart static int safexcel_hmac_init_pad(struct ahash_request *areq, 10561b44c5a6SAntoine Ténart unsigned int blocksize, const u8 *key, 10571b44c5a6SAntoine Ténart unsigned int keylen, u8 *ipad, u8 *opad) 10581b44c5a6SAntoine Ténart { 10591b44c5a6SAntoine Ténart struct safexcel_ahash_result result; 10601b44c5a6SAntoine Ténart struct scatterlist sg; 10611b44c5a6SAntoine Ténart int ret, i; 10621b44c5a6SAntoine Ténart u8 *keydup; 10631b44c5a6SAntoine Ténart 10641b44c5a6SAntoine Ténart if (keylen <= blocksize) { 10651b44c5a6SAntoine Ténart memcpy(ipad, key, keylen); 10661b44c5a6SAntoine Ténart } else { 10671b44c5a6SAntoine Ténart keydup = kmemdup(key, keylen, GFP_KERNEL); 10681b44c5a6SAntoine Ténart if (!keydup) 10691b44c5a6SAntoine Ténart return -ENOMEM; 10701b44c5a6SAntoine Ténart 10711b44c5a6SAntoine Ténart ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_BACKLOG, 10721b44c5a6SAntoine Ténart safexcel_ahash_complete, &result); 10731b44c5a6SAntoine Ténart sg_init_one(&sg, keydup, keylen); 10741b44c5a6SAntoine Ténart ahash_request_set_crypt(areq, &sg, ipad, keylen); 10751b44c5a6SAntoine Ténart init_completion(&result.completion); 10761b44c5a6SAntoine Ténart 10771b44c5a6SAntoine Ténart ret = crypto_ahash_digest(areq); 10784dc5475aSAntoine Tenart if (ret == -EINPROGRESS || ret == -EBUSY) { 10791b44c5a6SAntoine Ténart wait_for_completion_interruptible(&result.completion); 10801b44c5a6SAntoine Ténart ret = result.error; 10811b44c5a6SAntoine Ténart } 10821b44c5a6SAntoine Ténart 10831b44c5a6SAntoine Ténart /* Avoid leaking */ 108457059185SDenis Efremov kfree_sensitive(keydup); 10851b44c5a6SAntoine Ténart 10861b44c5a6SAntoine Ténart if (ret) 10871b44c5a6SAntoine Ténart return ret; 10881b44c5a6SAntoine Ténart 10891b44c5a6SAntoine Ténart keylen = crypto_ahash_digestsize(crypto_ahash_reqtfm(areq)); 10901b44c5a6SAntoine Ténart } 10911b44c5a6SAntoine Ténart 10921b44c5a6SAntoine Ténart memset(ipad + keylen, 0, blocksize - keylen); 10931b44c5a6SAntoine Ténart memcpy(opad, ipad, blocksize); 10941b44c5a6SAntoine Ténart 10951b44c5a6SAntoine Ténart for (i = 0; i < blocksize; i++) { 1096aed3731eSAntoine Ténart ipad[i] ^= HMAC_IPAD_VALUE; 1097aed3731eSAntoine Ténart opad[i] ^= HMAC_OPAD_VALUE; 10981b44c5a6SAntoine Ténart } 10991b44c5a6SAntoine Ténart 11001b44c5a6SAntoine Ténart return 0; 11011b44c5a6SAntoine Ténart } 11021b44c5a6SAntoine Ténart 11031b44c5a6SAntoine Ténart static int safexcel_hmac_init_iv(struct ahash_request *areq, 11041b44c5a6SAntoine Ténart unsigned int blocksize, u8 *pad, void *state) 11051b44c5a6SAntoine Ténart { 11061b44c5a6SAntoine Ténart struct safexcel_ahash_result result; 11071b44c5a6SAntoine Ténart struct safexcel_ahash_req *req; 11081b44c5a6SAntoine Ténart struct scatterlist sg; 11091b44c5a6SAntoine Ténart int ret; 11101b44c5a6SAntoine Ténart 11111b44c5a6SAntoine Ténart ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_BACKLOG, 11121b44c5a6SAntoine Ténart safexcel_ahash_complete, &result); 11131b44c5a6SAntoine Ténart sg_init_one(&sg, pad, blocksize); 11141b44c5a6SAntoine Ténart ahash_request_set_crypt(areq, &sg, pad, blocksize); 11151b44c5a6SAntoine Ténart init_completion(&result.completion); 11161b44c5a6SAntoine Ténart 11171b44c5a6SAntoine Ténart ret = crypto_ahash_init(areq); 11181b44c5a6SAntoine Ténart if (ret) 11191b44c5a6SAntoine Ténart return ret; 11201b44c5a6SAntoine Ténart 11211b44c5a6SAntoine Ténart req = ahash_request_ctx(areq); 11221b44c5a6SAntoine Ténart req->hmac = true; 11231b44c5a6SAntoine Ténart req->last_req = true; 11241b44c5a6SAntoine Ténart 11251b44c5a6SAntoine Ténart ret = crypto_ahash_update(areq); 112612bf4142SOfer Heifetz if (ret && ret != -EINPROGRESS && ret != -EBUSY) 11271b44c5a6SAntoine Ténart return ret; 11281b44c5a6SAntoine Ténart 11291b44c5a6SAntoine Ténart wait_for_completion_interruptible(&result.completion); 11301b44c5a6SAntoine Ténart if (result.error) 11311b44c5a6SAntoine Ténart return result.error; 11321b44c5a6SAntoine Ténart 11331b44c5a6SAntoine Ténart return crypto_ahash_export(areq, state); 11341b44c5a6SAntoine Ténart } 11351b44c5a6SAntoine Ténart 1136f6beaea3SAntoine Tenart int safexcel_hmac_setkey(const char *alg, const u8 *key, unsigned int keylen, 1137f6beaea3SAntoine Tenart void *istate, void *ostate) 11381b44c5a6SAntoine Ténart { 11391b44c5a6SAntoine Ténart struct ahash_request *areq; 11401b44c5a6SAntoine Ténart struct crypto_ahash *tfm; 11411b44c5a6SAntoine Ténart unsigned int blocksize; 11421b44c5a6SAntoine Ténart u8 *ipad, *opad; 11431b44c5a6SAntoine Ténart int ret; 11441b44c5a6SAntoine Ténart 114585d7311fSEric Biggers tfm = crypto_alloc_ahash(alg, 0, 0); 11461b44c5a6SAntoine Ténart if (IS_ERR(tfm)) 11471b44c5a6SAntoine Ténart return PTR_ERR(tfm); 11481b44c5a6SAntoine Ténart 11491b44c5a6SAntoine Ténart areq = ahash_request_alloc(tfm, GFP_KERNEL); 11501b44c5a6SAntoine Ténart if (!areq) { 11511b44c5a6SAntoine Ténart ret = -ENOMEM; 11521b44c5a6SAntoine Ténart goto free_ahash; 11531b44c5a6SAntoine Ténart } 11541b44c5a6SAntoine Ténart 11551b44c5a6SAntoine Ténart crypto_ahash_clear_flags(tfm, ~0); 11561b44c5a6SAntoine Ténart blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); 11571b44c5a6SAntoine Ténart 11586396bb22SKees Cook ipad = kcalloc(2, blocksize, GFP_KERNEL); 11591b44c5a6SAntoine Ténart if (!ipad) { 11601b44c5a6SAntoine Ténart ret = -ENOMEM; 11611b44c5a6SAntoine Ténart goto free_request; 11621b44c5a6SAntoine Ténart } 11631b44c5a6SAntoine Ténart 11641b44c5a6SAntoine Ténart opad = ipad + blocksize; 11651b44c5a6SAntoine Ténart 11661b44c5a6SAntoine Ténart ret = safexcel_hmac_init_pad(areq, blocksize, key, keylen, ipad, opad); 11671b44c5a6SAntoine Ténart if (ret) 11681b44c5a6SAntoine Ténart goto free_ipad; 11691b44c5a6SAntoine Ténart 11701b44c5a6SAntoine Ténart ret = safexcel_hmac_init_iv(areq, blocksize, ipad, istate); 11711b44c5a6SAntoine Ténart if (ret) 11721b44c5a6SAntoine Ténart goto free_ipad; 11731b44c5a6SAntoine Ténart 11741b44c5a6SAntoine Ténart ret = safexcel_hmac_init_iv(areq, blocksize, opad, ostate); 11751b44c5a6SAntoine Ténart 11761b44c5a6SAntoine Ténart free_ipad: 11771b44c5a6SAntoine Ténart kfree(ipad); 11781b44c5a6SAntoine Ténart free_request: 11791b44c5a6SAntoine Ténart ahash_request_free(areq); 11801b44c5a6SAntoine Ténart free_ahash: 11811b44c5a6SAntoine Ténart crypto_free_ahash(tfm); 11821b44c5a6SAntoine Ténart 11831b44c5a6SAntoine Ténart return ret; 11841b44c5a6SAntoine Ténart } 11851b44c5a6SAntoine Ténart 118673f36ea7SAntoine Tenart static int safexcel_hmac_alg_setkey(struct crypto_ahash *tfm, const u8 *key, 118773f36ea7SAntoine Tenart unsigned int keylen, const char *alg, 118873f36ea7SAntoine Tenart unsigned int state_sz) 11891b44c5a6SAntoine Ténart { 11901b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 119118e51895SHerbert Xu struct safexcel_crypto_priv *priv = ctx->base.priv; 11921b44c5a6SAntoine Ténart struct safexcel_ahash_export_state istate, ostate; 119341abed7dSPascal van Leeuwen int ret; 11941b44c5a6SAntoine Ténart 119573f36ea7SAntoine Tenart ret = safexcel_hmac_setkey(alg, key, keylen, &istate, &ostate); 11961b44c5a6SAntoine Ténart if (ret) 11971b44c5a6SAntoine Ténart return ret; 11981b44c5a6SAntoine Ténart 119941abed7dSPascal van Leeuwen if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr && 120041abed7dSPascal van Leeuwen (memcmp(ctx->ipad, istate.state, state_sz) || 120141abed7dSPascal van Leeuwen memcmp(ctx->opad, ostate.state, state_sz))) 12021b44c5a6SAntoine Ténart ctx->base.needs_inv = true; 12031b44c5a6SAntoine Ténart 120473f36ea7SAntoine Tenart memcpy(ctx->ipad, &istate.state, state_sz); 120573f36ea7SAntoine Tenart memcpy(ctx->opad, &ostate.state, state_sz); 120642ef3bedSAntoine Ténart 12071b44c5a6SAntoine Ténart return 0; 12081b44c5a6SAntoine Ténart } 12091b44c5a6SAntoine Ténart 121073f36ea7SAntoine Tenart static int safexcel_hmac_sha1_setkey(struct crypto_ahash *tfm, const u8 *key, 121173f36ea7SAntoine Tenart unsigned int keylen) 121273f36ea7SAntoine Tenart { 121373f36ea7SAntoine Tenart return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha1", 121473f36ea7SAntoine Tenart SHA1_DIGEST_SIZE); 121573f36ea7SAntoine Tenart } 121673f36ea7SAntoine Tenart 12171b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_hmac_sha1 = { 12181b44c5a6SAntoine Ténart .type = SAFEXCEL_ALG_TYPE_AHASH, 1219062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA1, 12201b44c5a6SAntoine Ténart .alg.ahash = { 12211b44c5a6SAntoine Ténart .init = safexcel_hmac_sha1_init, 12221b44c5a6SAntoine Ténart .update = safexcel_ahash_update, 12231b44c5a6SAntoine Ténart .final = safexcel_ahash_final, 12241b44c5a6SAntoine Ténart .finup = safexcel_ahash_finup, 12251b44c5a6SAntoine Ténart .digest = safexcel_hmac_sha1_digest, 12261b44c5a6SAntoine Ténart .setkey = safexcel_hmac_sha1_setkey, 12271b44c5a6SAntoine Ténart .export = safexcel_ahash_export, 12281b44c5a6SAntoine Ténart .import = safexcel_ahash_import, 12291b44c5a6SAntoine Ténart .halg = { 12301b44c5a6SAntoine Ténart .digestsize = SHA1_DIGEST_SIZE, 12311b44c5a6SAntoine Ténart .statesize = sizeof(struct safexcel_ahash_export_state), 12321b44c5a6SAntoine Ténart .base = { 12331b44c5a6SAntoine Ténart .cra_name = "hmac(sha1)", 12341b44c5a6SAntoine Ténart .cra_driver_name = "safexcel-hmac-sha1", 1235aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 12361b44c5a6SAntoine Ténart .cra_flags = CRYPTO_ALG_ASYNC | 1237b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 12381b44c5a6SAntoine Ténart CRYPTO_ALG_KERN_DRIVER_ONLY, 12391b44c5a6SAntoine Ténart .cra_blocksize = SHA1_BLOCK_SIZE, 12401b44c5a6SAntoine Ténart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 12411b44c5a6SAntoine Ténart .cra_init = safexcel_ahash_cra_init, 12421b44c5a6SAntoine Ténart .cra_exit = safexcel_ahash_cra_exit, 12431b44c5a6SAntoine Ténart .cra_module = THIS_MODULE, 12441b44c5a6SAntoine Ténart }, 12451b44c5a6SAntoine Ténart }, 12461b44c5a6SAntoine Ténart }, 12471b44c5a6SAntoine Ténart }; 12481b44c5a6SAntoine Ténart 12491b44c5a6SAntoine Ténart static int safexcel_sha256_init(struct ahash_request *areq) 12501b44c5a6SAntoine Ténart { 12511b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 12521b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 12531b44c5a6SAntoine Ténart 12541b44c5a6SAntoine Ténart memset(req, 0, sizeof(*req)); 12551b44c5a6SAntoine Ténart 12561b44c5a6SAntoine Ténart ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256; 1257b869648cSAntoine Tenart req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 12581b44c5a6SAntoine Ténart req->state_sz = SHA256_DIGEST_SIZE; 12596c1c09b3SPascal van Leeuwen req->digest_sz = SHA256_DIGEST_SIZE; 126041abed7dSPascal van Leeuwen req->block_sz = SHA256_BLOCK_SIZE; 12611b44c5a6SAntoine Ténart 12621b44c5a6SAntoine Ténart return 0; 12631b44c5a6SAntoine Ténart } 12641b44c5a6SAntoine Ténart 12651b44c5a6SAntoine Ténart static int safexcel_sha256_digest(struct ahash_request *areq) 12661b44c5a6SAntoine Ténart { 12671b44c5a6SAntoine Ténart int ret = safexcel_sha256_init(areq); 12681b44c5a6SAntoine Ténart 12691b44c5a6SAntoine Ténart if (ret) 12701b44c5a6SAntoine Ténart return ret; 12711b44c5a6SAntoine Ténart 12721b44c5a6SAntoine Ténart return safexcel_ahash_finup(areq); 12731b44c5a6SAntoine Ténart } 12741b44c5a6SAntoine Ténart 12751b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha256 = { 12761b44c5a6SAntoine Ténart .type = SAFEXCEL_ALG_TYPE_AHASH, 1277062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA2_256, 12781b44c5a6SAntoine Ténart .alg.ahash = { 12791b44c5a6SAntoine Ténart .init = safexcel_sha256_init, 12801b44c5a6SAntoine Ténart .update = safexcel_ahash_update, 12811b44c5a6SAntoine Ténart .final = safexcel_ahash_final, 12821b44c5a6SAntoine Ténart .finup = safexcel_ahash_finup, 12831b44c5a6SAntoine Ténart .digest = safexcel_sha256_digest, 12841b44c5a6SAntoine Ténart .export = safexcel_ahash_export, 12851b44c5a6SAntoine Ténart .import = safexcel_ahash_import, 12861b44c5a6SAntoine Ténart .halg = { 12871b44c5a6SAntoine Ténart .digestsize = SHA256_DIGEST_SIZE, 12881b44c5a6SAntoine Ténart .statesize = sizeof(struct safexcel_ahash_export_state), 12891b44c5a6SAntoine Ténart .base = { 12901b44c5a6SAntoine Ténart .cra_name = "sha256", 12911b44c5a6SAntoine Ténart .cra_driver_name = "safexcel-sha256", 1292aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 12931b44c5a6SAntoine Ténart .cra_flags = CRYPTO_ALG_ASYNC | 1294b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 12951b44c5a6SAntoine Ténart CRYPTO_ALG_KERN_DRIVER_ONLY, 12961b44c5a6SAntoine Ténart .cra_blocksize = SHA256_BLOCK_SIZE, 12971b44c5a6SAntoine Ténart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 12981b44c5a6SAntoine Ténart .cra_init = safexcel_ahash_cra_init, 12991b44c5a6SAntoine Ténart .cra_exit = safexcel_ahash_cra_exit, 13001b44c5a6SAntoine Ténart .cra_module = THIS_MODULE, 13011b44c5a6SAntoine Ténart }, 13021b44c5a6SAntoine Ténart }, 13031b44c5a6SAntoine Ténart }, 13041b44c5a6SAntoine Ténart }; 13051b44c5a6SAntoine Ténart 13061b44c5a6SAntoine Ténart static int safexcel_sha224_init(struct ahash_request *areq) 13071b44c5a6SAntoine Ténart { 13081b44c5a6SAntoine Ténart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 13091b44c5a6SAntoine Ténart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 13101b44c5a6SAntoine Ténart 13111b44c5a6SAntoine Ténart memset(req, 0, sizeof(*req)); 13121b44c5a6SAntoine Ténart 13131b44c5a6SAntoine Ténart ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224; 1314b869648cSAntoine Tenart req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 13151b44c5a6SAntoine Ténart req->state_sz = SHA256_DIGEST_SIZE; 13166c1c09b3SPascal van Leeuwen req->digest_sz = SHA256_DIGEST_SIZE; 131741abed7dSPascal van Leeuwen req->block_sz = SHA256_BLOCK_SIZE; 13181b44c5a6SAntoine Ténart 13191b44c5a6SAntoine Ténart return 0; 13201b44c5a6SAntoine Ténart } 13211b44c5a6SAntoine Ténart 13221b44c5a6SAntoine Ténart static int safexcel_sha224_digest(struct ahash_request *areq) 13231b44c5a6SAntoine Ténart { 13241b44c5a6SAntoine Ténart int ret = safexcel_sha224_init(areq); 13251b44c5a6SAntoine Ténart 13261b44c5a6SAntoine Ténart if (ret) 13271b44c5a6SAntoine Ténart return ret; 13281b44c5a6SAntoine Ténart 13291b44c5a6SAntoine Ténart return safexcel_ahash_finup(areq); 13301b44c5a6SAntoine Ténart } 13311b44c5a6SAntoine Ténart 13321b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_sha224 = { 13331b44c5a6SAntoine Ténart .type = SAFEXCEL_ALG_TYPE_AHASH, 1334062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA2_256, 13351b44c5a6SAntoine Ténart .alg.ahash = { 13361b44c5a6SAntoine Ténart .init = safexcel_sha224_init, 13371b44c5a6SAntoine Ténart .update = safexcel_ahash_update, 13381b44c5a6SAntoine Ténart .final = safexcel_ahash_final, 13391b44c5a6SAntoine Ténart .finup = safexcel_ahash_finup, 13401b44c5a6SAntoine Ténart .digest = safexcel_sha224_digest, 13411b44c5a6SAntoine Ténart .export = safexcel_ahash_export, 13421b44c5a6SAntoine Ténart .import = safexcel_ahash_import, 13431b44c5a6SAntoine Ténart .halg = { 13441b44c5a6SAntoine Ténart .digestsize = SHA224_DIGEST_SIZE, 13451b44c5a6SAntoine Ténart .statesize = sizeof(struct safexcel_ahash_export_state), 13461b44c5a6SAntoine Ténart .base = { 13471b44c5a6SAntoine Ténart .cra_name = "sha224", 13481b44c5a6SAntoine Ténart .cra_driver_name = "safexcel-sha224", 1349aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 13501b44c5a6SAntoine Ténart .cra_flags = CRYPTO_ALG_ASYNC | 1351b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 13521b44c5a6SAntoine Ténart CRYPTO_ALG_KERN_DRIVER_ONLY, 13531b44c5a6SAntoine Ténart .cra_blocksize = SHA224_BLOCK_SIZE, 13541b44c5a6SAntoine Ténart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 13551b44c5a6SAntoine Ténart .cra_init = safexcel_ahash_cra_init, 13561b44c5a6SAntoine Ténart .cra_exit = safexcel_ahash_cra_exit, 13571b44c5a6SAntoine Ténart .cra_module = THIS_MODULE, 13581b44c5a6SAntoine Ténart }, 13591b44c5a6SAntoine Ténart }, 13601b44c5a6SAntoine Ténart }, 13611b44c5a6SAntoine Ténart }; 136273f36ea7SAntoine Tenart 13633ad618d8SAntoine Tenart static int safexcel_hmac_sha224_setkey(struct crypto_ahash *tfm, const u8 *key, 13643ad618d8SAntoine Tenart unsigned int keylen) 13653ad618d8SAntoine Tenart { 13663ad618d8SAntoine Tenart return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha224", 13673ad618d8SAntoine Tenart SHA256_DIGEST_SIZE); 13683ad618d8SAntoine Tenart } 13693ad618d8SAntoine Tenart 13703ad618d8SAntoine Tenart static int safexcel_hmac_sha224_init(struct ahash_request *areq) 13713ad618d8SAntoine Tenart { 137241abed7dSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 13733ad618d8SAntoine Tenart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 13743ad618d8SAntoine Tenart 137541abed7dSPascal van Leeuwen memset(req, 0, sizeof(*req)); 137641abed7dSPascal van Leeuwen 137741abed7dSPascal van Leeuwen /* Start from ipad precompute */ 137841abed7dSPascal van Leeuwen memcpy(req->state, ctx->ipad, SHA256_DIGEST_SIZE); 137941abed7dSPascal van Leeuwen /* Already processed the key^ipad part now! */ 138031fb084cSPascal van Leeuwen req->len = SHA256_BLOCK_SIZE; 138131fb084cSPascal van Leeuwen req->processed = SHA256_BLOCK_SIZE; 138241abed7dSPascal van Leeuwen 138341abed7dSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224; 138441abed7dSPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 138541abed7dSPascal van Leeuwen req->state_sz = SHA256_DIGEST_SIZE; 13866c1c09b3SPascal van Leeuwen req->digest_sz = SHA256_DIGEST_SIZE; 138741abed7dSPascal van Leeuwen req->block_sz = SHA256_BLOCK_SIZE; 138841abed7dSPascal van Leeuwen req->hmac = true; 138941abed7dSPascal van Leeuwen 13903ad618d8SAntoine Tenart return 0; 13913ad618d8SAntoine Tenart } 13923ad618d8SAntoine Tenart 13933ad618d8SAntoine Tenart static int safexcel_hmac_sha224_digest(struct ahash_request *areq) 13943ad618d8SAntoine Tenart { 13953ad618d8SAntoine Tenart int ret = safexcel_hmac_sha224_init(areq); 13963ad618d8SAntoine Tenart 13973ad618d8SAntoine Tenart if (ret) 13983ad618d8SAntoine Tenart return ret; 13993ad618d8SAntoine Tenart 14003ad618d8SAntoine Tenart return safexcel_ahash_finup(areq); 14013ad618d8SAntoine Tenart } 14023ad618d8SAntoine Tenart 14033ad618d8SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha224 = { 14043ad618d8SAntoine Tenart .type = SAFEXCEL_ALG_TYPE_AHASH, 1405062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA2_256, 14063ad618d8SAntoine Tenart .alg.ahash = { 14073ad618d8SAntoine Tenart .init = safexcel_hmac_sha224_init, 14083ad618d8SAntoine Tenart .update = safexcel_ahash_update, 14093ad618d8SAntoine Tenart .final = safexcel_ahash_final, 14103ad618d8SAntoine Tenart .finup = safexcel_ahash_finup, 14113ad618d8SAntoine Tenart .digest = safexcel_hmac_sha224_digest, 14123ad618d8SAntoine Tenart .setkey = safexcel_hmac_sha224_setkey, 14133ad618d8SAntoine Tenart .export = safexcel_ahash_export, 14143ad618d8SAntoine Tenart .import = safexcel_ahash_import, 14153ad618d8SAntoine Tenart .halg = { 14163ad618d8SAntoine Tenart .digestsize = SHA224_DIGEST_SIZE, 14173ad618d8SAntoine Tenart .statesize = sizeof(struct safexcel_ahash_export_state), 14183ad618d8SAntoine Tenart .base = { 14193ad618d8SAntoine Tenart .cra_name = "hmac(sha224)", 14203ad618d8SAntoine Tenart .cra_driver_name = "safexcel-hmac-sha224", 1421aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 14223ad618d8SAntoine Tenart .cra_flags = CRYPTO_ALG_ASYNC | 1423b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 14243ad618d8SAntoine Tenart CRYPTO_ALG_KERN_DRIVER_ONLY, 14253ad618d8SAntoine Tenart .cra_blocksize = SHA224_BLOCK_SIZE, 14263ad618d8SAntoine Tenart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 14273ad618d8SAntoine Tenart .cra_init = safexcel_ahash_cra_init, 14283ad618d8SAntoine Tenart .cra_exit = safexcel_ahash_cra_exit, 14293ad618d8SAntoine Tenart .cra_module = THIS_MODULE, 14303ad618d8SAntoine Tenart }, 14313ad618d8SAntoine Tenart }, 14323ad618d8SAntoine Tenart }, 14333ad618d8SAntoine Tenart }; 14343ad618d8SAntoine Tenart 143573f36ea7SAntoine Tenart static int safexcel_hmac_sha256_setkey(struct crypto_ahash *tfm, const u8 *key, 143673f36ea7SAntoine Tenart unsigned int keylen) 143773f36ea7SAntoine Tenart { 143873f36ea7SAntoine Tenart return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha256", 143973f36ea7SAntoine Tenart SHA256_DIGEST_SIZE); 144073f36ea7SAntoine Tenart } 144173f36ea7SAntoine Tenart 144273f36ea7SAntoine Tenart static int safexcel_hmac_sha256_init(struct ahash_request *areq) 144373f36ea7SAntoine Tenart { 144441abed7dSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 144573f36ea7SAntoine Tenart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 144673f36ea7SAntoine Tenart 144741abed7dSPascal van Leeuwen memset(req, 0, sizeof(*req)); 144841abed7dSPascal van Leeuwen 144941abed7dSPascal van Leeuwen /* Start from ipad precompute */ 145041abed7dSPascal van Leeuwen memcpy(req->state, ctx->ipad, SHA256_DIGEST_SIZE); 145141abed7dSPascal van Leeuwen /* Already processed the key^ipad part now! */ 145231fb084cSPascal van Leeuwen req->len = SHA256_BLOCK_SIZE; 145331fb084cSPascal van Leeuwen req->processed = SHA256_BLOCK_SIZE; 145441abed7dSPascal van Leeuwen 145541abed7dSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256; 145641abed7dSPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 145741abed7dSPascal van Leeuwen req->state_sz = SHA256_DIGEST_SIZE; 14586c1c09b3SPascal van Leeuwen req->digest_sz = SHA256_DIGEST_SIZE; 145941abed7dSPascal van Leeuwen req->block_sz = SHA256_BLOCK_SIZE; 146041abed7dSPascal van Leeuwen req->hmac = true; 146141abed7dSPascal van Leeuwen 146273f36ea7SAntoine Tenart return 0; 146373f36ea7SAntoine Tenart } 146473f36ea7SAntoine Tenart 146573f36ea7SAntoine Tenart static int safexcel_hmac_sha256_digest(struct ahash_request *areq) 146673f36ea7SAntoine Tenart { 146773f36ea7SAntoine Tenart int ret = safexcel_hmac_sha256_init(areq); 146873f36ea7SAntoine Tenart 146973f36ea7SAntoine Tenart if (ret) 147073f36ea7SAntoine Tenart return ret; 147173f36ea7SAntoine Tenart 147273f36ea7SAntoine Tenart return safexcel_ahash_finup(areq); 147373f36ea7SAntoine Tenart } 147473f36ea7SAntoine Tenart 147573f36ea7SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha256 = { 147673f36ea7SAntoine Tenart .type = SAFEXCEL_ALG_TYPE_AHASH, 1477062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA2_256, 147873f36ea7SAntoine Tenart .alg.ahash = { 147973f36ea7SAntoine Tenart .init = safexcel_hmac_sha256_init, 148073f36ea7SAntoine Tenart .update = safexcel_ahash_update, 148173f36ea7SAntoine Tenart .final = safexcel_ahash_final, 148273f36ea7SAntoine Tenart .finup = safexcel_ahash_finup, 148373f36ea7SAntoine Tenart .digest = safexcel_hmac_sha256_digest, 148473f36ea7SAntoine Tenart .setkey = safexcel_hmac_sha256_setkey, 148573f36ea7SAntoine Tenart .export = safexcel_ahash_export, 148673f36ea7SAntoine Tenart .import = safexcel_ahash_import, 148773f36ea7SAntoine Tenart .halg = { 148873f36ea7SAntoine Tenart .digestsize = SHA256_DIGEST_SIZE, 148973f36ea7SAntoine Tenart .statesize = sizeof(struct safexcel_ahash_export_state), 149073f36ea7SAntoine Tenart .base = { 149173f36ea7SAntoine Tenart .cra_name = "hmac(sha256)", 149273f36ea7SAntoine Tenart .cra_driver_name = "safexcel-hmac-sha256", 1493aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 149473f36ea7SAntoine Tenart .cra_flags = CRYPTO_ALG_ASYNC | 1495b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 149673f36ea7SAntoine Tenart CRYPTO_ALG_KERN_DRIVER_ONLY, 149773f36ea7SAntoine Tenart .cra_blocksize = SHA256_BLOCK_SIZE, 149873f36ea7SAntoine Tenart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 149973f36ea7SAntoine Tenart .cra_init = safexcel_ahash_cra_init, 150073f36ea7SAntoine Tenart .cra_exit = safexcel_ahash_cra_exit, 150173f36ea7SAntoine Tenart .cra_module = THIS_MODULE, 150273f36ea7SAntoine Tenart }, 150373f36ea7SAntoine Tenart }, 150473f36ea7SAntoine Tenart }, 150573f36ea7SAntoine Tenart }; 1506b460edb6SAntoine Tenart 1507b460edb6SAntoine Tenart static int safexcel_sha512_init(struct ahash_request *areq) 1508b460edb6SAntoine Tenart { 1509b460edb6SAntoine Tenart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 1510b460edb6SAntoine Tenart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 1511b460edb6SAntoine Tenart 1512b460edb6SAntoine Tenart memset(req, 0, sizeof(*req)); 1513b460edb6SAntoine Tenart 1514b460edb6SAntoine Tenart ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512; 1515b460edb6SAntoine Tenart req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 1516b460edb6SAntoine Tenart req->state_sz = SHA512_DIGEST_SIZE; 15176c1c09b3SPascal van Leeuwen req->digest_sz = SHA512_DIGEST_SIZE; 151841abed7dSPascal van Leeuwen req->block_sz = SHA512_BLOCK_SIZE; 1519b460edb6SAntoine Tenart 1520b460edb6SAntoine Tenart return 0; 1521b460edb6SAntoine Tenart } 1522b460edb6SAntoine Tenart 1523b460edb6SAntoine Tenart static int safexcel_sha512_digest(struct ahash_request *areq) 1524b460edb6SAntoine Tenart { 1525b460edb6SAntoine Tenart int ret = safexcel_sha512_init(areq); 1526b460edb6SAntoine Tenart 1527b460edb6SAntoine Tenart if (ret) 1528b460edb6SAntoine Tenart return ret; 1529b460edb6SAntoine Tenart 1530b460edb6SAntoine Tenart return safexcel_ahash_finup(areq); 1531b460edb6SAntoine Tenart } 1532b460edb6SAntoine Tenart 1533b460edb6SAntoine Tenart struct safexcel_alg_template safexcel_alg_sha512 = { 1534b460edb6SAntoine Tenart .type = SAFEXCEL_ALG_TYPE_AHASH, 1535062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA2_512, 1536b460edb6SAntoine Tenart .alg.ahash = { 1537b460edb6SAntoine Tenart .init = safexcel_sha512_init, 1538b460edb6SAntoine Tenart .update = safexcel_ahash_update, 1539b460edb6SAntoine Tenart .final = safexcel_ahash_final, 1540b460edb6SAntoine Tenart .finup = safexcel_ahash_finup, 1541b460edb6SAntoine Tenart .digest = safexcel_sha512_digest, 1542b460edb6SAntoine Tenart .export = safexcel_ahash_export, 1543b460edb6SAntoine Tenart .import = safexcel_ahash_import, 1544b460edb6SAntoine Tenart .halg = { 1545b460edb6SAntoine Tenart .digestsize = SHA512_DIGEST_SIZE, 1546b460edb6SAntoine Tenart .statesize = sizeof(struct safexcel_ahash_export_state), 1547b460edb6SAntoine Tenart .base = { 1548b460edb6SAntoine Tenart .cra_name = "sha512", 1549b460edb6SAntoine Tenart .cra_driver_name = "safexcel-sha512", 1550aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 1551b460edb6SAntoine Tenart .cra_flags = CRYPTO_ALG_ASYNC | 1552b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 1553b460edb6SAntoine Tenart CRYPTO_ALG_KERN_DRIVER_ONLY, 1554b460edb6SAntoine Tenart .cra_blocksize = SHA512_BLOCK_SIZE, 1555b460edb6SAntoine Tenart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 1556b460edb6SAntoine Tenart .cra_init = safexcel_ahash_cra_init, 1557b460edb6SAntoine Tenart .cra_exit = safexcel_ahash_cra_exit, 1558b460edb6SAntoine Tenart .cra_module = THIS_MODULE, 1559b460edb6SAntoine Tenart }, 1560b460edb6SAntoine Tenart }, 1561b460edb6SAntoine Tenart }, 1562b460edb6SAntoine Tenart }; 15630de54fb1SAntoine Tenart 15649e46eafdSAntoine Tenart static int safexcel_sha384_init(struct ahash_request *areq) 15659e46eafdSAntoine Tenart { 15669e46eafdSAntoine Tenart struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 15679e46eafdSAntoine Tenart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 15689e46eafdSAntoine Tenart 15699e46eafdSAntoine Tenart memset(req, 0, sizeof(*req)); 15709e46eafdSAntoine Tenart 15719e46eafdSAntoine Tenart ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384; 15729e46eafdSAntoine Tenart req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 15739e46eafdSAntoine Tenart req->state_sz = SHA512_DIGEST_SIZE; 15746c1c09b3SPascal van Leeuwen req->digest_sz = SHA512_DIGEST_SIZE; 157541abed7dSPascal van Leeuwen req->block_sz = SHA512_BLOCK_SIZE; 15769e46eafdSAntoine Tenart 15779e46eafdSAntoine Tenart return 0; 15789e46eafdSAntoine Tenart } 15799e46eafdSAntoine Tenart 15809e46eafdSAntoine Tenart static int safexcel_sha384_digest(struct ahash_request *areq) 15819e46eafdSAntoine Tenart { 15829e46eafdSAntoine Tenart int ret = safexcel_sha384_init(areq); 15839e46eafdSAntoine Tenart 15849e46eafdSAntoine Tenart if (ret) 15859e46eafdSAntoine Tenart return ret; 15869e46eafdSAntoine Tenart 15879e46eafdSAntoine Tenart return safexcel_ahash_finup(areq); 15889e46eafdSAntoine Tenart } 15899e46eafdSAntoine Tenart 15909e46eafdSAntoine Tenart struct safexcel_alg_template safexcel_alg_sha384 = { 15919e46eafdSAntoine Tenart .type = SAFEXCEL_ALG_TYPE_AHASH, 1592062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA2_512, 15939e46eafdSAntoine Tenart .alg.ahash = { 15949e46eafdSAntoine Tenart .init = safexcel_sha384_init, 15959e46eafdSAntoine Tenart .update = safexcel_ahash_update, 15969e46eafdSAntoine Tenart .final = safexcel_ahash_final, 15979e46eafdSAntoine Tenart .finup = safexcel_ahash_finup, 15989e46eafdSAntoine Tenart .digest = safexcel_sha384_digest, 15999e46eafdSAntoine Tenart .export = safexcel_ahash_export, 16009e46eafdSAntoine Tenart .import = safexcel_ahash_import, 16019e46eafdSAntoine Tenart .halg = { 16029e46eafdSAntoine Tenart .digestsize = SHA384_DIGEST_SIZE, 16039e46eafdSAntoine Tenart .statesize = sizeof(struct safexcel_ahash_export_state), 16049e46eafdSAntoine Tenart .base = { 16059e46eafdSAntoine Tenart .cra_name = "sha384", 16069e46eafdSAntoine Tenart .cra_driver_name = "safexcel-sha384", 1607aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 16089e46eafdSAntoine Tenart .cra_flags = CRYPTO_ALG_ASYNC | 1609b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 16109e46eafdSAntoine Tenart CRYPTO_ALG_KERN_DRIVER_ONLY, 16119e46eafdSAntoine Tenart .cra_blocksize = SHA384_BLOCK_SIZE, 16129e46eafdSAntoine Tenart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 16139e46eafdSAntoine Tenart .cra_init = safexcel_ahash_cra_init, 16149e46eafdSAntoine Tenart .cra_exit = safexcel_ahash_cra_exit, 16159e46eafdSAntoine Tenart .cra_module = THIS_MODULE, 16169e46eafdSAntoine Tenart }, 16179e46eafdSAntoine Tenart }, 16189e46eafdSAntoine Tenart }, 16199e46eafdSAntoine Tenart }; 16209e46eafdSAntoine Tenart 16210de54fb1SAntoine Tenart static int safexcel_hmac_sha512_setkey(struct crypto_ahash *tfm, const u8 *key, 16220de54fb1SAntoine Tenart unsigned int keylen) 16230de54fb1SAntoine Tenart { 16240de54fb1SAntoine Tenart return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha512", 16250de54fb1SAntoine Tenart SHA512_DIGEST_SIZE); 16260de54fb1SAntoine Tenart } 16270de54fb1SAntoine Tenart 16280de54fb1SAntoine Tenart static int safexcel_hmac_sha512_init(struct ahash_request *areq) 16290de54fb1SAntoine Tenart { 163041abed7dSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 16310de54fb1SAntoine Tenart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 16320de54fb1SAntoine Tenart 163341abed7dSPascal van Leeuwen memset(req, 0, sizeof(*req)); 163441abed7dSPascal van Leeuwen 163541abed7dSPascal van Leeuwen /* Start from ipad precompute */ 163641abed7dSPascal van Leeuwen memcpy(req->state, ctx->ipad, SHA512_DIGEST_SIZE); 163741abed7dSPascal van Leeuwen /* Already processed the key^ipad part now! */ 163831fb084cSPascal van Leeuwen req->len = SHA512_BLOCK_SIZE; 163931fb084cSPascal van Leeuwen req->processed = SHA512_BLOCK_SIZE; 164041abed7dSPascal van Leeuwen 164141abed7dSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512; 164241abed7dSPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 164341abed7dSPascal van Leeuwen req->state_sz = SHA512_DIGEST_SIZE; 16446c1c09b3SPascal van Leeuwen req->digest_sz = SHA512_DIGEST_SIZE; 164541abed7dSPascal van Leeuwen req->block_sz = SHA512_BLOCK_SIZE; 164641abed7dSPascal van Leeuwen req->hmac = true; 164741abed7dSPascal van Leeuwen 16480de54fb1SAntoine Tenart return 0; 16490de54fb1SAntoine Tenart } 16500de54fb1SAntoine Tenart 16510de54fb1SAntoine Tenart static int safexcel_hmac_sha512_digest(struct ahash_request *areq) 16520de54fb1SAntoine Tenart { 16530de54fb1SAntoine Tenart int ret = safexcel_hmac_sha512_init(areq); 16540de54fb1SAntoine Tenart 16550de54fb1SAntoine Tenart if (ret) 16560de54fb1SAntoine Tenart return ret; 16570de54fb1SAntoine Tenart 16580de54fb1SAntoine Tenart return safexcel_ahash_finup(areq); 16590de54fb1SAntoine Tenart } 16600de54fb1SAntoine Tenart 16610de54fb1SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha512 = { 16620de54fb1SAntoine Tenart .type = SAFEXCEL_ALG_TYPE_AHASH, 1663062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA2_512, 16640de54fb1SAntoine Tenart .alg.ahash = { 16650de54fb1SAntoine Tenart .init = safexcel_hmac_sha512_init, 16660de54fb1SAntoine Tenart .update = safexcel_ahash_update, 16670de54fb1SAntoine Tenart .final = safexcel_ahash_final, 16680de54fb1SAntoine Tenart .finup = safexcel_ahash_finup, 16690de54fb1SAntoine Tenart .digest = safexcel_hmac_sha512_digest, 16700de54fb1SAntoine Tenart .setkey = safexcel_hmac_sha512_setkey, 16710de54fb1SAntoine Tenart .export = safexcel_ahash_export, 16720de54fb1SAntoine Tenart .import = safexcel_ahash_import, 16730de54fb1SAntoine Tenart .halg = { 16740de54fb1SAntoine Tenart .digestsize = SHA512_DIGEST_SIZE, 16750de54fb1SAntoine Tenart .statesize = sizeof(struct safexcel_ahash_export_state), 16760de54fb1SAntoine Tenart .base = { 16770de54fb1SAntoine Tenart .cra_name = "hmac(sha512)", 16780de54fb1SAntoine Tenart .cra_driver_name = "safexcel-hmac-sha512", 1679aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 16800de54fb1SAntoine Tenart .cra_flags = CRYPTO_ALG_ASYNC | 1681b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 16820de54fb1SAntoine Tenart CRYPTO_ALG_KERN_DRIVER_ONLY, 16830de54fb1SAntoine Tenart .cra_blocksize = SHA512_BLOCK_SIZE, 16840de54fb1SAntoine Tenart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 16850de54fb1SAntoine Tenart .cra_init = safexcel_ahash_cra_init, 16860de54fb1SAntoine Tenart .cra_exit = safexcel_ahash_cra_exit, 16870de54fb1SAntoine Tenart .cra_module = THIS_MODULE, 16880de54fb1SAntoine Tenart }, 16890de54fb1SAntoine Tenart }, 16900de54fb1SAntoine Tenart }, 16910de54fb1SAntoine Tenart }; 16921f5d5d98SAntoine Tenart 16931f5d5d98SAntoine Tenart static int safexcel_hmac_sha384_setkey(struct crypto_ahash *tfm, const u8 *key, 16941f5d5d98SAntoine Tenart unsigned int keylen) 16951f5d5d98SAntoine Tenart { 16961f5d5d98SAntoine Tenart return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sha384", 16971f5d5d98SAntoine Tenart SHA512_DIGEST_SIZE); 16981f5d5d98SAntoine Tenart } 16991f5d5d98SAntoine Tenart 17001f5d5d98SAntoine Tenart static int safexcel_hmac_sha384_init(struct ahash_request *areq) 17011f5d5d98SAntoine Tenart { 170241abed7dSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 17031f5d5d98SAntoine Tenart struct safexcel_ahash_req *req = ahash_request_ctx(areq); 17041f5d5d98SAntoine Tenart 170541abed7dSPascal van Leeuwen memset(req, 0, sizeof(*req)); 170641abed7dSPascal van Leeuwen 170741abed7dSPascal van Leeuwen /* Start from ipad precompute */ 170841abed7dSPascal van Leeuwen memcpy(req->state, ctx->ipad, SHA512_DIGEST_SIZE); 170941abed7dSPascal van Leeuwen /* Already processed the key^ipad part now! */ 171031fb084cSPascal van Leeuwen req->len = SHA512_BLOCK_SIZE; 171131fb084cSPascal van Leeuwen req->processed = SHA512_BLOCK_SIZE; 171241abed7dSPascal van Leeuwen 171341abed7dSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384; 171441abed7dSPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 171541abed7dSPascal van Leeuwen req->state_sz = SHA512_DIGEST_SIZE; 17166c1c09b3SPascal van Leeuwen req->digest_sz = SHA512_DIGEST_SIZE; 171741abed7dSPascal van Leeuwen req->block_sz = SHA512_BLOCK_SIZE; 171841abed7dSPascal van Leeuwen req->hmac = true; 171941abed7dSPascal van Leeuwen 17201f5d5d98SAntoine Tenart return 0; 17211f5d5d98SAntoine Tenart } 17221f5d5d98SAntoine Tenart 17231f5d5d98SAntoine Tenart static int safexcel_hmac_sha384_digest(struct ahash_request *areq) 17241f5d5d98SAntoine Tenart { 17251f5d5d98SAntoine Tenart int ret = safexcel_hmac_sha384_init(areq); 17261f5d5d98SAntoine Tenart 17271f5d5d98SAntoine Tenart if (ret) 17281f5d5d98SAntoine Tenart return ret; 17291f5d5d98SAntoine Tenart 17301f5d5d98SAntoine Tenart return safexcel_ahash_finup(areq); 17311f5d5d98SAntoine Tenart } 17321f5d5d98SAntoine Tenart 17331f5d5d98SAntoine Tenart struct safexcel_alg_template safexcel_alg_hmac_sha384 = { 17341f5d5d98SAntoine Tenart .type = SAFEXCEL_ALG_TYPE_AHASH, 1735062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA2_512, 17361f5d5d98SAntoine Tenart .alg.ahash = { 17371f5d5d98SAntoine Tenart .init = safexcel_hmac_sha384_init, 17381f5d5d98SAntoine Tenart .update = safexcel_ahash_update, 17391f5d5d98SAntoine Tenart .final = safexcel_ahash_final, 17401f5d5d98SAntoine Tenart .finup = safexcel_ahash_finup, 17411f5d5d98SAntoine Tenart .digest = safexcel_hmac_sha384_digest, 17421f5d5d98SAntoine Tenart .setkey = safexcel_hmac_sha384_setkey, 17431f5d5d98SAntoine Tenart .export = safexcel_ahash_export, 17441f5d5d98SAntoine Tenart .import = safexcel_ahash_import, 17451f5d5d98SAntoine Tenart .halg = { 17461f5d5d98SAntoine Tenart .digestsize = SHA384_DIGEST_SIZE, 17471f5d5d98SAntoine Tenart .statesize = sizeof(struct safexcel_ahash_export_state), 17481f5d5d98SAntoine Tenart .base = { 17491f5d5d98SAntoine Tenart .cra_name = "hmac(sha384)", 17501f5d5d98SAntoine Tenart .cra_driver_name = "safexcel-hmac-sha384", 1751aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 17521f5d5d98SAntoine Tenart .cra_flags = CRYPTO_ALG_ASYNC | 1753b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 17541f5d5d98SAntoine Tenart CRYPTO_ALG_KERN_DRIVER_ONLY, 17551f5d5d98SAntoine Tenart .cra_blocksize = SHA384_BLOCK_SIZE, 17561f5d5d98SAntoine Tenart .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 17571f5d5d98SAntoine Tenart .cra_init = safexcel_ahash_cra_init, 17581f5d5d98SAntoine Tenart .cra_exit = safexcel_ahash_cra_exit, 17591f5d5d98SAntoine Tenart .cra_module = THIS_MODULE, 17601f5d5d98SAntoine Tenart }, 17611f5d5d98SAntoine Tenart }, 17621f5d5d98SAntoine Tenart }, 17631f5d5d98SAntoine Tenart }; 1764293f89cfSOfer Heifetz 1765293f89cfSOfer Heifetz static int safexcel_md5_init(struct ahash_request *areq) 1766293f89cfSOfer Heifetz { 1767293f89cfSOfer Heifetz struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 1768293f89cfSOfer Heifetz struct safexcel_ahash_req *req = ahash_request_ctx(areq); 1769293f89cfSOfer Heifetz 1770293f89cfSOfer Heifetz memset(req, 0, sizeof(*req)); 1771293f89cfSOfer Heifetz 1772293f89cfSOfer Heifetz ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_MD5; 1773293f89cfSOfer Heifetz req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 1774293f89cfSOfer Heifetz req->state_sz = MD5_DIGEST_SIZE; 17756c1c09b3SPascal van Leeuwen req->digest_sz = MD5_DIGEST_SIZE; 177641abed7dSPascal van Leeuwen req->block_sz = MD5_HMAC_BLOCK_SIZE; 1777293f89cfSOfer Heifetz 1778293f89cfSOfer Heifetz return 0; 1779293f89cfSOfer Heifetz } 1780293f89cfSOfer Heifetz 1781293f89cfSOfer Heifetz static int safexcel_md5_digest(struct ahash_request *areq) 1782293f89cfSOfer Heifetz { 1783293f89cfSOfer Heifetz int ret = safexcel_md5_init(areq); 1784293f89cfSOfer Heifetz 1785293f89cfSOfer Heifetz if (ret) 1786293f89cfSOfer Heifetz return ret; 1787293f89cfSOfer Heifetz 1788293f89cfSOfer Heifetz return safexcel_ahash_finup(areq); 1789293f89cfSOfer Heifetz } 1790293f89cfSOfer Heifetz 1791293f89cfSOfer Heifetz struct safexcel_alg_template safexcel_alg_md5 = { 1792293f89cfSOfer Heifetz .type = SAFEXCEL_ALG_TYPE_AHASH, 1793062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_MD5, 1794293f89cfSOfer Heifetz .alg.ahash = { 1795293f89cfSOfer Heifetz .init = safexcel_md5_init, 1796293f89cfSOfer Heifetz .update = safexcel_ahash_update, 1797293f89cfSOfer Heifetz .final = safexcel_ahash_final, 1798293f89cfSOfer Heifetz .finup = safexcel_ahash_finup, 1799293f89cfSOfer Heifetz .digest = safexcel_md5_digest, 1800293f89cfSOfer Heifetz .export = safexcel_ahash_export, 1801293f89cfSOfer Heifetz .import = safexcel_ahash_import, 1802293f89cfSOfer Heifetz .halg = { 1803293f89cfSOfer Heifetz .digestsize = MD5_DIGEST_SIZE, 1804293f89cfSOfer Heifetz .statesize = sizeof(struct safexcel_ahash_export_state), 1805293f89cfSOfer Heifetz .base = { 1806293f89cfSOfer Heifetz .cra_name = "md5", 1807293f89cfSOfer Heifetz .cra_driver_name = "safexcel-md5", 1808aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 1809293f89cfSOfer Heifetz .cra_flags = CRYPTO_ALG_ASYNC | 1810b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 1811293f89cfSOfer Heifetz CRYPTO_ALG_KERN_DRIVER_ONLY, 1812293f89cfSOfer Heifetz .cra_blocksize = MD5_HMAC_BLOCK_SIZE, 1813293f89cfSOfer Heifetz .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 1814293f89cfSOfer Heifetz .cra_init = safexcel_ahash_cra_init, 1815293f89cfSOfer Heifetz .cra_exit = safexcel_ahash_cra_exit, 1816293f89cfSOfer Heifetz .cra_module = THIS_MODULE, 1817293f89cfSOfer Heifetz }, 1818293f89cfSOfer Heifetz }, 1819293f89cfSOfer Heifetz }, 1820293f89cfSOfer Heifetz }; 1821b471e4b9SOfer Heifetz 1822b471e4b9SOfer Heifetz static int safexcel_hmac_md5_init(struct ahash_request *areq) 1823b471e4b9SOfer Heifetz { 182441abed7dSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 1825b471e4b9SOfer Heifetz struct safexcel_ahash_req *req = ahash_request_ctx(areq); 1826b471e4b9SOfer Heifetz 182741abed7dSPascal van Leeuwen memset(req, 0, sizeof(*req)); 182841abed7dSPascal van Leeuwen 182941abed7dSPascal van Leeuwen /* Start from ipad precompute */ 183041abed7dSPascal van Leeuwen memcpy(req->state, ctx->ipad, MD5_DIGEST_SIZE); 183141abed7dSPascal van Leeuwen /* Already processed the key^ipad part now! */ 183231fb084cSPascal van Leeuwen req->len = MD5_HMAC_BLOCK_SIZE; 183331fb084cSPascal van Leeuwen req->processed = MD5_HMAC_BLOCK_SIZE; 183441abed7dSPascal van Leeuwen 183541abed7dSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_MD5; 183641abed7dSPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 183741abed7dSPascal van Leeuwen req->state_sz = MD5_DIGEST_SIZE; 18386c1c09b3SPascal van Leeuwen req->digest_sz = MD5_DIGEST_SIZE; 183941abed7dSPascal van Leeuwen req->block_sz = MD5_HMAC_BLOCK_SIZE; 184085b36ee8SPascal van Leeuwen req->len_is_le = true; /* MD5 is little endian! ... */ 184141abed7dSPascal van Leeuwen req->hmac = true; 184241abed7dSPascal van Leeuwen 1843b471e4b9SOfer Heifetz return 0; 1844b471e4b9SOfer Heifetz } 1845b471e4b9SOfer Heifetz 1846b471e4b9SOfer Heifetz static int safexcel_hmac_md5_setkey(struct crypto_ahash *tfm, const u8 *key, 1847b471e4b9SOfer Heifetz unsigned int keylen) 1848b471e4b9SOfer Heifetz { 1849b471e4b9SOfer Heifetz return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-md5", 1850b471e4b9SOfer Heifetz MD5_DIGEST_SIZE); 1851b471e4b9SOfer Heifetz } 1852b471e4b9SOfer Heifetz 1853b471e4b9SOfer Heifetz static int safexcel_hmac_md5_digest(struct ahash_request *areq) 1854b471e4b9SOfer Heifetz { 1855b471e4b9SOfer Heifetz int ret = safexcel_hmac_md5_init(areq); 1856b471e4b9SOfer Heifetz 1857b471e4b9SOfer Heifetz if (ret) 1858b471e4b9SOfer Heifetz return ret; 1859b471e4b9SOfer Heifetz 1860b471e4b9SOfer Heifetz return safexcel_ahash_finup(areq); 1861b471e4b9SOfer Heifetz } 1862b471e4b9SOfer Heifetz 1863b471e4b9SOfer Heifetz struct safexcel_alg_template safexcel_alg_hmac_md5 = { 1864b471e4b9SOfer Heifetz .type = SAFEXCEL_ALG_TYPE_AHASH, 1865062b64caSPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_MD5, 1866b471e4b9SOfer Heifetz .alg.ahash = { 1867b471e4b9SOfer Heifetz .init = safexcel_hmac_md5_init, 1868b471e4b9SOfer Heifetz .update = safexcel_ahash_update, 1869b471e4b9SOfer Heifetz .final = safexcel_ahash_final, 1870b471e4b9SOfer Heifetz .finup = safexcel_ahash_finup, 1871b471e4b9SOfer Heifetz .digest = safexcel_hmac_md5_digest, 1872b471e4b9SOfer Heifetz .setkey = safexcel_hmac_md5_setkey, 1873b471e4b9SOfer Heifetz .export = safexcel_ahash_export, 1874b471e4b9SOfer Heifetz .import = safexcel_ahash_import, 1875b471e4b9SOfer Heifetz .halg = { 1876b471e4b9SOfer Heifetz .digestsize = MD5_DIGEST_SIZE, 1877b471e4b9SOfer Heifetz .statesize = sizeof(struct safexcel_ahash_export_state), 1878b471e4b9SOfer Heifetz .base = { 1879b471e4b9SOfer Heifetz .cra_name = "hmac(md5)", 1880b471e4b9SOfer Heifetz .cra_driver_name = "safexcel-hmac-md5", 1881aa88f331SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 1882b471e4b9SOfer Heifetz .cra_flags = CRYPTO_ALG_ASYNC | 1883b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 1884b471e4b9SOfer Heifetz CRYPTO_ALG_KERN_DRIVER_ONLY, 1885b471e4b9SOfer Heifetz .cra_blocksize = MD5_HMAC_BLOCK_SIZE, 1886b471e4b9SOfer Heifetz .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 1887b471e4b9SOfer Heifetz .cra_init = safexcel_ahash_cra_init, 1888b471e4b9SOfer Heifetz .cra_exit = safexcel_ahash_cra_exit, 1889b471e4b9SOfer Heifetz .cra_module = THIS_MODULE, 1890b471e4b9SOfer Heifetz }, 1891b471e4b9SOfer Heifetz }, 1892b471e4b9SOfer Heifetz }, 1893b471e4b9SOfer Heifetz }; 1894a7cf8658SPascal van Leeuwen 1895a7cf8658SPascal van Leeuwen static int safexcel_crc32_cra_init(struct crypto_tfm *tfm) 1896a7cf8658SPascal van Leeuwen { 1897a7cf8658SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 1898a7cf8658SPascal van Leeuwen int ret = safexcel_ahash_cra_init(tfm); 1899a7cf8658SPascal van Leeuwen 1900a7cf8658SPascal van Leeuwen /* Default 'key' is all zeroes */ 1901a7cf8658SPascal van Leeuwen memset(ctx->ipad, 0, sizeof(u32)); 1902a7cf8658SPascal van Leeuwen return ret; 1903a7cf8658SPascal van Leeuwen } 1904a7cf8658SPascal van Leeuwen 1905a7cf8658SPascal van Leeuwen static int safexcel_crc32_init(struct ahash_request *areq) 1906a7cf8658SPascal van Leeuwen { 1907a7cf8658SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 1908a7cf8658SPascal van Leeuwen struct safexcel_ahash_req *req = ahash_request_ctx(areq); 1909a7cf8658SPascal van Leeuwen 1910a7cf8658SPascal van Leeuwen memset(req, 0, sizeof(*req)); 1911a7cf8658SPascal van Leeuwen 1912a7cf8658SPascal van Leeuwen /* Start from loaded key */ 191313a1bb93SPascal van Leeuwen req->state[0] = (__force __le32)le32_to_cpu(~ctx->ipad[0]); 1914a7cf8658SPascal van Leeuwen /* Set processed to non-zero to enable invalidation detection */ 1915a7cf8658SPascal van Leeuwen req->len = sizeof(u32); 1916a7cf8658SPascal van Leeuwen req->processed = sizeof(u32); 1917a7cf8658SPascal van Leeuwen 1918a7cf8658SPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_CRC32; 1919a7cf8658SPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_XCM; 1920a7cf8658SPascal van Leeuwen req->state_sz = sizeof(u32); 19216c1c09b3SPascal van Leeuwen req->digest_sz = sizeof(u32); 1922a7cf8658SPascal van Leeuwen req->block_sz = sizeof(u32); 1923a7cf8658SPascal van Leeuwen 1924a7cf8658SPascal van Leeuwen return 0; 1925a7cf8658SPascal van Leeuwen } 1926a7cf8658SPascal van Leeuwen 1927a7cf8658SPascal van Leeuwen static int safexcel_crc32_setkey(struct crypto_ahash *tfm, const u8 *key, 1928a7cf8658SPascal van Leeuwen unsigned int keylen) 1929a7cf8658SPascal van Leeuwen { 1930a7cf8658SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 1931a7cf8658SPascal van Leeuwen 1932674f368aSEric Biggers if (keylen != sizeof(u32)) 1933a7cf8658SPascal van Leeuwen return -EINVAL; 1934a7cf8658SPascal van Leeuwen 1935a7cf8658SPascal van Leeuwen memcpy(ctx->ipad, key, sizeof(u32)); 1936a7cf8658SPascal van Leeuwen return 0; 1937a7cf8658SPascal van Leeuwen } 1938a7cf8658SPascal van Leeuwen 1939a7cf8658SPascal van Leeuwen static int safexcel_crc32_digest(struct ahash_request *areq) 1940a7cf8658SPascal van Leeuwen { 1941a7cf8658SPascal van Leeuwen return safexcel_crc32_init(areq) ?: safexcel_ahash_finup(areq); 1942a7cf8658SPascal van Leeuwen } 1943a7cf8658SPascal van Leeuwen 1944a7cf8658SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_crc32 = { 1945a7cf8658SPascal van Leeuwen .type = SAFEXCEL_ALG_TYPE_AHASH, 1946a7cf8658SPascal van Leeuwen .algo_mask = 0, 1947a7cf8658SPascal van Leeuwen .alg.ahash = { 1948a7cf8658SPascal van Leeuwen .init = safexcel_crc32_init, 1949a7cf8658SPascal van Leeuwen .update = safexcel_ahash_update, 1950a7cf8658SPascal van Leeuwen .final = safexcel_ahash_final, 1951a7cf8658SPascal van Leeuwen .finup = safexcel_ahash_finup, 1952a7cf8658SPascal van Leeuwen .digest = safexcel_crc32_digest, 1953a7cf8658SPascal van Leeuwen .setkey = safexcel_crc32_setkey, 1954a7cf8658SPascal van Leeuwen .export = safexcel_ahash_export, 1955a7cf8658SPascal van Leeuwen .import = safexcel_ahash_import, 1956a7cf8658SPascal van Leeuwen .halg = { 1957a7cf8658SPascal van Leeuwen .digestsize = sizeof(u32), 1958a7cf8658SPascal van Leeuwen .statesize = sizeof(struct safexcel_ahash_export_state), 1959a7cf8658SPascal van Leeuwen .base = { 1960a7cf8658SPascal van Leeuwen .cra_name = "crc32", 1961a7cf8658SPascal van Leeuwen .cra_driver_name = "safexcel-crc32", 1962a7cf8658SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 1963a7cf8658SPascal van Leeuwen .cra_flags = CRYPTO_ALG_OPTIONAL_KEY | 1964a7cf8658SPascal van Leeuwen CRYPTO_ALG_ASYNC | 1965b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 1966a7cf8658SPascal van Leeuwen CRYPTO_ALG_KERN_DRIVER_ONLY, 1967a7cf8658SPascal van Leeuwen .cra_blocksize = 1, 1968a7cf8658SPascal van Leeuwen .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 1969a7cf8658SPascal van Leeuwen .cra_init = safexcel_crc32_cra_init, 1970a7cf8658SPascal van Leeuwen .cra_exit = safexcel_ahash_cra_exit, 1971a7cf8658SPascal van Leeuwen .cra_module = THIS_MODULE, 1972a7cf8658SPascal van Leeuwen }, 1973a7cf8658SPascal van Leeuwen }, 1974a7cf8658SPascal van Leeuwen }, 1975a7cf8658SPascal van Leeuwen }; 1976b98687bbSPascal van Leeuwen 1977b98687bbSPascal van Leeuwen static int safexcel_cbcmac_init(struct ahash_request *areq) 1978b98687bbSPascal van Leeuwen { 1979b98687bbSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 1980b98687bbSPascal van Leeuwen struct safexcel_ahash_req *req = ahash_request_ctx(areq); 1981b98687bbSPascal van Leeuwen 1982b98687bbSPascal van Leeuwen memset(req, 0, sizeof(*req)); 1983b98687bbSPascal van Leeuwen 1984b98687bbSPascal van Leeuwen /* Start from loaded keys */ 1985b98687bbSPascal van Leeuwen memcpy(req->state, ctx->ipad, ctx->key_sz); 1986b98687bbSPascal van Leeuwen /* Set processed to non-zero to enable invalidation detection */ 1987b98687bbSPascal van Leeuwen req->len = AES_BLOCK_SIZE; 1988b98687bbSPascal van Leeuwen req->processed = AES_BLOCK_SIZE; 1989b98687bbSPascal van Leeuwen 1990b98687bbSPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_XCM; 1991b98687bbSPascal van Leeuwen req->state_sz = ctx->key_sz; 19926c1c09b3SPascal van Leeuwen req->digest_sz = AES_BLOCK_SIZE; 1993b98687bbSPascal van Leeuwen req->block_sz = AES_BLOCK_SIZE; 1994b98687bbSPascal van Leeuwen req->xcbcmac = true; 1995b98687bbSPascal van Leeuwen 1996b98687bbSPascal van Leeuwen return 0; 1997b98687bbSPascal van Leeuwen } 1998b98687bbSPascal van Leeuwen 1999b98687bbSPascal van Leeuwen static int safexcel_cbcmac_setkey(struct crypto_ahash *tfm, const u8 *key, 2000b98687bbSPascal van Leeuwen unsigned int len) 2001b98687bbSPascal van Leeuwen { 2002b98687bbSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 2003b98687bbSPascal van Leeuwen struct crypto_aes_ctx aes; 2004b98687bbSPascal van Leeuwen int ret, i; 2005b98687bbSPascal van Leeuwen 2006b98687bbSPascal van Leeuwen ret = aes_expandkey(&aes, key, len); 2007674f368aSEric Biggers if (ret) 2008b98687bbSPascal van Leeuwen return ret; 2009b98687bbSPascal van Leeuwen 2010b98687bbSPascal van Leeuwen memset(ctx->ipad, 0, 2 * AES_BLOCK_SIZE); 2011b98687bbSPascal van Leeuwen for (i = 0; i < len / sizeof(u32); i++) 201213a1bb93SPascal van Leeuwen ctx->ipad[i + 8] = (__force __le32)cpu_to_be32(aes.key_enc[i]); 2013b98687bbSPascal van Leeuwen 2014b98687bbSPascal van Leeuwen if (len == AES_KEYSIZE_192) { 2015b98687bbSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC192; 2016b98687bbSPascal van Leeuwen ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE; 2017b98687bbSPascal van Leeuwen } else if (len == AES_KEYSIZE_256) { 2018b98687bbSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC256; 2019b98687bbSPascal van Leeuwen ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE; 2020b98687bbSPascal van Leeuwen } else { 2021b98687bbSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128; 2022b98687bbSPascal van Leeuwen ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE; 2023b98687bbSPascal van Leeuwen } 202438f21b4bSPascal van Leeuwen ctx->cbcmac = true; 2025b98687bbSPascal van Leeuwen 2026b98687bbSPascal van Leeuwen memzero_explicit(&aes, sizeof(aes)); 2027b98687bbSPascal van Leeuwen return 0; 2028b98687bbSPascal van Leeuwen } 2029b98687bbSPascal van Leeuwen 2030b98687bbSPascal van Leeuwen static int safexcel_cbcmac_digest(struct ahash_request *areq) 2031b98687bbSPascal van Leeuwen { 2032b98687bbSPascal van Leeuwen return safexcel_cbcmac_init(areq) ?: safexcel_ahash_finup(areq); 2033b98687bbSPascal van Leeuwen } 2034b98687bbSPascal van Leeuwen 2035b98687bbSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_cbcmac = { 2036b98687bbSPascal van Leeuwen .type = SAFEXCEL_ALG_TYPE_AHASH, 2037b98687bbSPascal van Leeuwen .algo_mask = 0, 2038b98687bbSPascal van Leeuwen .alg.ahash = { 2039b98687bbSPascal van Leeuwen .init = safexcel_cbcmac_init, 2040b98687bbSPascal van Leeuwen .update = safexcel_ahash_update, 2041b98687bbSPascal van Leeuwen .final = safexcel_ahash_final, 2042b98687bbSPascal van Leeuwen .finup = safexcel_ahash_finup, 2043b98687bbSPascal van Leeuwen .digest = safexcel_cbcmac_digest, 2044b98687bbSPascal van Leeuwen .setkey = safexcel_cbcmac_setkey, 2045b98687bbSPascal van Leeuwen .export = safexcel_ahash_export, 2046b98687bbSPascal van Leeuwen .import = safexcel_ahash_import, 2047b98687bbSPascal van Leeuwen .halg = { 2048b98687bbSPascal van Leeuwen .digestsize = AES_BLOCK_SIZE, 2049b98687bbSPascal van Leeuwen .statesize = sizeof(struct safexcel_ahash_export_state), 2050b98687bbSPascal van Leeuwen .base = { 2051b98687bbSPascal van Leeuwen .cra_name = "cbcmac(aes)", 2052b98687bbSPascal van Leeuwen .cra_driver_name = "safexcel-cbcmac-aes", 2053b98687bbSPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 2054b98687bbSPascal van Leeuwen .cra_flags = CRYPTO_ALG_ASYNC | 2055b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 2056b98687bbSPascal van Leeuwen CRYPTO_ALG_KERN_DRIVER_ONLY, 2057b98687bbSPascal van Leeuwen .cra_blocksize = 1, 2058b98687bbSPascal van Leeuwen .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 2059b98687bbSPascal van Leeuwen .cra_init = safexcel_ahash_cra_init, 2060b98687bbSPascal van Leeuwen .cra_exit = safexcel_ahash_cra_exit, 2061b98687bbSPascal van Leeuwen .cra_module = THIS_MODULE, 2062b98687bbSPascal van Leeuwen }, 2063b98687bbSPascal van Leeuwen }, 2064b98687bbSPascal van Leeuwen }, 2065b98687bbSPascal van Leeuwen }; 206638f21b4bSPascal van Leeuwen 206738f21b4bSPascal van Leeuwen static int safexcel_xcbcmac_setkey(struct crypto_ahash *tfm, const u8 *key, 206838f21b4bSPascal van Leeuwen unsigned int len) 206938f21b4bSPascal van Leeuwen { 207038f21b4bSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 207138f21b4bSPascal van Leeuwen struct crypto_aes_ctx aes; 207238f21b4bSPascal van Leeuwen u32 key_tmp[3 * AES_BLOCK_SIZE / sizeof(u32)]; 207338f21b4bSPascal van Leeuwen int ret, i; 207438f21b4bSPascal van Leeuwen 207538f21b4bSPascal van Leeuwen ret = aes_expandkey(&aes, key, len); 2076674f368aSEric Biggers if (ret) 207738f21b4bSPascal van Leeuwen return ret; 207838f21b4bSPascal van Leeuwen 207938f21b4bSPascal van Leeuwen /* precompute the XCBC key material */ 208038f21b4bSPascal van Leeuwen crypto_cipher_clear_flags(ctx->kaes, CRYPTO_TFM_REQ_MASK); 208138f21b4bSPascal van Leeuwen crypto_cipher_set_flags(ctx->kaes, crypto_ahash_get_flags(tfm) & 208238f21b4bSPascal van Leeuwen CRYPTO_TFM_REQ_MASK); 208338f21b4bSPascal van Leeuwen ret = crypto_cipher_setkey(ctx->kaes, key, len); 208438f21b4bSPascal van Leeuwen if (ret) 208538f21b4bSPascal van Leeuwen return ret; 208638f21b4bSPascal van Leeuwen 208738f21b4bSPascal van Leeuwen crypto_cipher_encrypt_one(ctx->kaes, (u8 *)key_tmp + 2 * AES_BLOCK_SIZE, 208838f21b4bSPascal van Leeuwen "\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1"); 208938f21b4bSPascal van Leeuwen crypto_cipher_encrypt_one(ctx->kaes, (u8 *)key_tmp, 209038f21b4bSPascal van Leeuwen "\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2"); 209138f21b4bSPascal van Leeuwen crypto_cipher_encrypt_one(ctx->kaes, (u8 *)key_tmp + AES_BLOCK_SIZE, 209238f21b4bSPascal van Leeuwen "\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3"); 209338f21b4bSPascal van Leeuwen for (i = 0; i < 3 * AES_BLOCK_SIZE / sizeof(u32); i++) 209413a1bb93SPascal van Leeuwen ctx->ipad[i] = 209513a1bb93SPascal van Leeuwen cpu_to_le32((__force u32)cpu_to_be32(key_tmp[i])); 209638f21b4bSPascal van Leeuwen 209738f21b4bSPascal van Leeuwen crypto_cipher_clear_flags(ctx->kaes, CRYPTO_TFM_REQ_MASK); 209838f21b4bSPascal van Leeuwen crypto_cipher_set_flags(ctx->kaes, crypto_ahash_get_flags(tfm) & 209938f21b4bSPascal van Leeuwen CRYPTO_TFM_REQ_MASK); 210038f21b4bSPascal van Leeuwen ret = crypto_cipher_setkey(ctx->kaes, 210138f21b4bSPascal van Leeuwen (u8 *)key_tmp + 2 * AES_BLOCK_SIZE, 210238f21b4bSPascal van Leeuwen AES_MIN_KEY_SIZE); 210338f21b4bSPascal van Leeuwen if (ret) 210438f21b4bSPascal van Leeuwen return ret; 210538f21b4bSPascal van Leeuwen 210638f21b4bSPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128; 210738f21b4bSPascal van Leeuwen ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE; 210838f21b4bSPascal van Leeuwen ctx->cbcmac = false; 210938f21b4bSPascal van Leeuwen 211038f21b4bSPascal van Leeuwen memzero_explicit(&aes, sizeof(aes)); 211138f21b4bSPascal van Leeuwen return 0; 211238f21b4bSPascal van Leeuwen } 211338f21b4bSPascal van Leeuwen 211438f21b4bSPascal van Leeuwen static int safexcel_xcbcmac_cra_init(struct crypto_tfm *tfm) 211538f21b4bSPascal van Leeuwen { 211638f21b4bSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 211738f21b4bSPascal van Leeuwen 211838f21b4bSPascal van Leeuwen safexcel_ahash_cra_init(tfm); 211938f21b4bSPascal van Leeuwen ctx->kaes = crypto_alloc_cipher("aes", 0, 0); 212027018ab1SYueHaibing return PTR_ERR_OR_ZERO(ctx->kaes); 212138f21b4bSPascal van Leeuwen } 212238f21b4bSPascal van Leeuwen 212338f21b4bSPascal van Leeuwen static void safexcel_xcbcmac_cra_exit(struct crypto_tfm *tfm) 212438f21b4bSPascal van Leeuwen { 212538f21b4bSPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 212638f21b4bSPascal van Leeuwen 212738f21b4bSPascal van Leeuwen crypto_free_cipher(ctx->kaes); 212838f21b4bSPascal van Leeuwen safexcel_ahash_cra_exit(tfm); 212938f21b4bSPascal van Leeuwen } 213038f21b4bSPascal van Leeuwen 213138f21b4bSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_xcbcmac = { 213238f21b4bSPascal van Leeuwen .type = SAFEXCEL_ALG_TYPE_AHASH, 213338f21b4bSPascal van Leeuwen .algo_mask = 0, 213438f21b4bSPascal van Leeuwen .alg.ahash = { 213538f21b4bSPascal van Leeuwen .init = safexcel_cbcmac_init, 213638f21b4bSPascal van Leeuwen .update = safexcel_ahash_update, 213738f21b4bSPascal van Leeuwen .final = safexcel_ahash_final, 213838f21b4bSPascal van Leeuwen .finup = safexcel_ahash_finup, 213938f21b4bSPascal van Leeuwen .digest = safexcel_cbcmac_digest, 214038f21b4bSPascal van Leeuwen .setkey = safexcel_xcbcmac_setkey, 214138f21b4bSPascal van Leeuwen .export = safexcel_ahash_export, 214238f21b4bSPascal van Leeuwen .import = safexcel_ahash_import, 214338f21b4bSPascal van Leeuwen .halg = { 214438f21b4bSPascal van Leeuwen .digestsize = AES_BLOCK_SIZE, 214538f21b4bSPascal van Leeuwen .statesize = sizeof(struct safexcel_ahash_export_state), 214638f21b4bSPascal van Leeuwen .base = { 214738f21b4bSPascal van Leeuwen .cra_name = "xcbc(aes)", 214838f21b4bSPascal van Leeuwen .cra_driver_name = "safexcel-xcbc-aes", 214938f21b4bSPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 215038f21b4bSPascal van Leeuwen .cra_flags = CRYPTO_ALG_ASYNC | 2151b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 215238f21b4bSPascal van Leeuwen CRYPTO_ALG_KERN_DRIVER_ONLY, 215338f21b4bSPascal van Leeuwen .cra_blocksize = AES_BLOCK_SIZE, 215438f21b4bSPascal van Leeuwen .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 215538f21b4bSPascal van Leeuwen .cra_init = safexcel_xcbcmac_cra_init, 215638f21b4bSPascal van Leeuwen .cra_exit = safexcel_xcbcmac_cra_exit, 215738f21b4bSPascal van Leeuwen .cra_module = THIS_MODULE, 215838f21b4bSPascal van Leeuwen }, 215938f21b4bSPascal van Leeuwen }, 216038f21b4bSPascal van Leeuwen }, 216138f21b4bSPascal van Leeuwen }; 21627a627db9SPascal van Leeuwen 21637a627db9SPascal van Leeuwen static int safexcel_cmac_setkey(struct crypto_ahash *tfm, const u8 *key, 21647a627db9SPascal van Leeuwen unsigned int len) 21657a627db9SPascal van Leeuwen { 21667a627db9SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 21677a627db9SPascal van Leeuwen struct crypto_aes_ctx aes; 21687a627db9SPascal van Leeuwen __be64 consts[4]; 21697a627db9SPascal van Leeuwen u64 _const[2]; 21707a627db9SPascal van Leeuwen u8 msb_mask, gfmask; 21717a627db9SPascal van Leeuwen int ret, i; 21727a627db9SPascal van Leeuwen 21737a627db9SPascal van Leeuwen ret = aes_expandkey(&aes, key, len); 2174674f368aSEric Biggers if (ret) 21757a627db9SPascal van Leeuwen return ret; 21767a627db9SPascal van Leeuwen 21777a627db9SPascal van Leeuwen for (i = 0; i < len / sizeof(u32); i++) 217813a1bb93SPascal van Leeuwen ctx->ipad[i + 8] = 217913a1bb93SPascal van Leeuwen cpu_to_le32((__force u32)cpu_to_be32(aes.key_enc[i])); 21807a627db9SPascal van Leeuwen 21817a627db9SPascal van Leeuwen /* precompute the CMAC key material */ 21827a627db9SPascal van Leeuwen crypto_cipher_clear_flags(ctx->kaes, CRYPTO_TFM_REQ_MASK); 21837a627db9SPascal van Leeuwen crypto_cipher_set_flags(ctx->kaes, crypto_ahash_get_flags(tfm) & 21847a627db9SPascal van Leeuwen CRYPTO_TFM_REQ_MASK); 21857a627db9SPascal van Leeuwen ret = crypto_cipher_setkey(ctx->kaes, key, len); 21867a627db9SPascal van Leeuwen if (ret) 21877a627db9SPascal van Leeuwen return ret; 21887a627db9SPascal van Leeuwen 21897a627db9SPascal van Leeuwen /* code below borrowed from crypto/cmac.c */ 21907a627db9SPascal van Leeuwen /* encrypt the zero block */ 21917a627db9SPascal van Leeuwen memset(consts, 0, AES_BLOCK_SIZE); 21927a627db9SPascal van Leeuwen crypto_cipher_encrypt_one(ctx->kaes, (u8 *)consts, (u8 *)consts); 21937a627db9SPascal van Leeuwen 21947a627db9SPascal van Leeuwen gfmask = 0x87; 21957a627db9SPascal van Leeuwen _const[0] = be64_to_cpu(consts[1]); 21967a627db9SPascal van Leeuwen _const[1] = be64_to_cpu(consts[0]); 21977a627db9SPascal van Leeuwen 21987a627db9SPascal van Leeuwen /* gf(2^128) multiply zero-ciphertext with u and u^2 */ 21997a627db9SPascal van Leeuwen for (i = 0; i < 4; i += 2) { 22007a627db9SPascal van Leeuwen msb_mask = ((s64)_const[1] >> 63) & gfmask; 22017a627db9SPascal van Leeuwen _const[1] = (_const[1] << 1) | (_const[0] >> 63); 22027a627db9SPascal van Leeuwen _const[0] = (_const[0] << 1) ^ msb_mask; 22037a627db9SPascal van Leeuwen 22047a627db9SPascal van Leeuwen consts[i + 0] = cpu_to_be64(_const[1]); 22057a627db9SPascal van Leeuwen consts[i + 1] = cpu_to_be64(_const[0]); 22067a627db9SPascal van Leeuwen } 22077a627db9SPascal van Leeuwen /* end of code borrowed from crypto/cmac.c */ 22087a627db9SPascal van Leeuwen 22097a627db9SPascal van Leeuwen for (i = 0; i < 2 * AES_BLOCK_SIZE / sizeof(u32); i++) 221013a1bb93SPascal van Leeuwen ctx->ipad[i] = (__force __le32)cpu_to_be32(((u32 *)consts)[i]); 22117a627db9SPascal van Leeuwen 22127a627db9SPascal van Leeuwen if (len == AES_KEYSIZE_192) { 22137a627db9SPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC192; 22147a627db9SPascal van Leeuwen ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE; 22157a627db9SPascal van Leeuwen } else if (len == AES_KEYSIZE_256) { 22167a627db9SPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC256; 22177a627db9SPascal van Leeuwen ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE; 22187a627db9SPascal van Leeuwen } else { 22197a627db9SPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128; 22207a627db9SPascal van Leeuwen ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE; 22217a627db9SPascal van Leeuwen } 22227a627db9SPascal van Leeuwen ctx->cbcmac = false; 22237a627db9SPascal van Leeuwen 22247a627db9SPascal van Leeuwen memzero_explicit(&aes, sizeof(aes)); 22257a627db9SPascal van Leeuwen return 0; 22267a627db9SPascal van Leeuwen } 22277a627db9SPascal van Leeuwen 22287a627db9SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_cmac = { 22297a627db9SPascal van Leeuwen .type = SAFEXCEL_ALG_TYPE_AHASH, 22307a627db9SPascal van Leeuwen .algo_mask = 0, 22317a627db9SPascal van Leeuwen .alg.ahash = { 22327a627db9SPascal van Leeuwen .init = safexcel_cbcmac_init, 22337a627db9SPascal van Leeuwen .update = safexcel_ahash_update, 22347a627db9SPascal van Leeuwen .final = safexcel_ahash_final, 22357a627db9SPascal van Leeuwen .finup = safexcel_ahash_finup, 22367a627db9SPascal van Leeuwen .digest = safexcel_cbcmac_digest, 22377a627db9SPascal van Leeuwen .setkey = safexcel_cmac_setkey, 22387a627db9SPascal van Leeuwen .export = safexcel_ahash_export, 22397a627db9SPascal van Leeuwen .import = safexcel_ahash_import, 22407a627db9SPascal van Leeuwen .halg = { 22417a627db9SPascal van Leeuwen .digestsize = AES_BLOCK_SIZE, 22427a627db9SPascal van Leeuwen .statesize = sizeof(struct safexcel_ahash_export_state), 22437a627db9SPascal van Leeuwen .base = { 22447a627db9SPascal van Leeuwen .cra_name = "cmac(aes)", 22457a627db9SPascal van Leeuwen .cra_driver_name = "safexcel-cmac-aes", 22467a627db9SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 22477a627db9SPascal van Leeuwen .cra_flags = CRYPTO_ALG_ASYNC | 2248b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 22497a627db9SPascal van Leeuwen CRYPTO_ALG_KERN_DRIVER_ONLY, 22507a627db9SPascal van Leeuwen .cra_blocksize = AES_BLOCK_SIZE, 22517a627db9SPascal van Leeuwen .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 22527a627db9SPascal van Leeuwen .cra_init = safexcel_xcbcmac_cra_init, 22537a627db9SPascal van Leeuwen .cra_exit = safexcel_xcbcmac_cra_exit, 22547a627db9SPascal van Leeuwen .cra_module = THIS_MODULE, 22557a627db9SPascal van Leeuwen }, 22567a627db9SPascal van Leeuwen }, 22577a627db9SPascal van Leeuwen }, 22587a627db9SPascal van Leeuwen }; 22590f2bc131SPascal van Leeuwen 22600f2bc131SPascal van Leeuwen static int safexcel_sm3_init(struct ahash_request *areq) 22610f2bc131SPascal van Leeuwen { 22620f2bc131SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 22630f2bc131SPascal van Leeuwen struct safexcel_ahash_req *req = ahash_request_ctx(areq); 22640f2bc131SPascal van Leeuwen 22650f2bc131SPascal van Leeuwen memset(req, 0, sizeof(*req)); 22660f2bc131SPascal van Leeuwen 22670f2bc131SPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SM3; 22680f2bc131SPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 22690f2bc131SPascal van Leeuwen req->state_sz = SM3_DIGEST_SIZE; 22706c1c09b3SPascal van Leeuwen req->digest_sz = SM3_DIGEST_SIZE; 22710f2bc131SPascal van Leeuwen req->block_sz = SM3_BLOCK_SIZE; 22720f2bc131SPascal van Leeuwen 22730f2bc131SPascal van Leeuwen return 0; 22740f2bc131SPascal van Leeuwen } 22750f2bc131SPascal van Leeuwen 22760f2bc131SPascal van Leeuwen static int safexcel_sm3_digest(struct ahash_request *areq) 22770f2bc131SPascal van Leeuwen { 22780f2bc131SPascal van Leeuwen int ret = safexcel_sm3_init(areq); 22790f2bc131SPascal van Leeuwen 22800f2bc131SPascal van Leeuwen if (ret) 22810f2bc131SPascal van Leeuwen return ret; 22820f2bc131SPascal van Leeuwen 22830f2bc131SPascal van Leeuwen return safexcel_ahash_finup(areq); 22840f2bc131SPascal van Leeuwen } 22850f2bc131SPascal van Leeuwen 22860f2bc131SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_sm3 = { 22870f2bc131SPascal van Leeuwen .type = SAFEXCEL_ALG_TYPE_AHASH, 22880f2bc131SPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SM3, 22890f2bc131SPascal van Leeuwen .alg.ahash = { 22900f2bc131SPascal van Leeuwen .init = safexcel_sm3_init, 22910f2bc131SPascal van Leeuwen .update = safexcel_ahash_update, 22920f2bc131SPascal van Leeuwen .final = safexcel_ahash_final, 22930f2bc131SPascal van Leeuwen .finup = safexcel_ahash_finup, 22940f2bc131SPascal van Leeuwen .digest = safexcel_sm3_digest, 22950f2bc131SPascal van Leeuwen .export = safexcel_ahash_export, 22960f2bc131SPascal van Leeuwen .import = safexcel_ahash_import, 22970f2bc131SPascal van Leeuwen .halg = { 22980f2bc131SPascal van Leeuwen .digestsize = SM3_DIGEST_SIZE, 22990f2bc131SPascal van Leeuwen .statesize = sizeof(struct safexcel_ahash_export_state), 23000f2bc131SPascal van Leeuwen .base = { 23010f2bc131SPascal van Leeuwen .cra_name = "sm3", 23020f2bc131SPascal van Leeuwen .cra_driver_name = "safexcel-sm3", 23030f2bc131SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 23040f2bc131SPascal van Leeuwen .cra_flags = CRYPTO_ALG_ASYNC | 2305b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 23060f2bc131SPascal van Leeuwen CRYPTO_ALG_KERN_DRIVER_ONLY, 23070f2bc131SPascal van Leeuwen .cra_blocksize = SM3_BLOCK_SIZE, 23080f2bc131SPascal van Leeuwen .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 23090f2bc131SPascal van Leeuwen .cra_init = safexcel_ahash_cra_init, 23100f2bc131SPascal van Leeuwen .cra_exit = safexcel_ahash_cra_exit, 23110f2bc131SPascal van Leeuwen .cra_module = THIS_MODULE, 23120f2bc131SPascal van Leeuwen }, 23130f2bc131SPascal van Leeuwen }, 23140f2bc131SPascal van Leeuwen }, 23150f2bc131SPascal van Leeuwen }; 2316aa3a43e6SPascal van Leeuwen 2317aa3a43e6SPascal van Leeuwen static int safexcel_hmac_sm3_setkey(struct crypto_ahash *tfm, const u8 *key, 2318aa3a43e6SPascal van Leeuwen unsigned int keylen) 2319aa3a43e6SPascal van Leeuwen { 2320aa3a43e6SPascal van Leeuwen return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sm3", 2321aa3a43e6SPascal van Leeuwen SM3_DIGEST_SIZE); 2322aa3a43e6SPascal van Leeuwen } 2323aa3a43e6SPascal van Leeuwen 2324aa3a43e6SPascal van Leeuwen static int safexcel_hmac_sm3_init(struct ahash_request *areq) 2325aa3a43e6SPascal van Leeuwen { 2326aa3a43e6SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); 2327aa3a43e6SPascal van Leeuwen struct safexcel_ahash_req *req = ahash_request_ctx(areq); 2328aa3a43e6SPascal van Leeuwen 2329aa3a43e6SPascal van Leeuwen memset(req, 0, sizeof(*req)); 2330aa3a43e6SPascal van Leeuwen 2331aa3a43e6SPascal van Leeuwen /* Start from ipad precompute */ 2332aa3a43e6SPascal van Leeuwen memcpy(req->state, ctx->ipad, SM3_DIGEST_SIZE); 2333aa3a43e6SPascal van Leeuwen /* Already processed the key^ipad part now! */ 2334aa3a43e6SPascal van Leeuwen req->len = SM3_BLOCK_SIZE; 2335aa3a43e6SPascal van Leeuwen req->processed = SM3_BLOCK_SIZE; 2336aa3a43e6SPascal van Leeuwen 2337aa3a43e6SPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SM3; 2338aa3a43e6SPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; 2339aa3a43e6SPascal van Leeuwen req->state_sz = SM3_DIGEST_SIZE; 23406c1c09b3SPascal van Leeuwen req->digest_sz = SM3_DIGEST_SIZE; 2341aa3a43e6SPascal van Leeuwen req->block_sz = SM3_BLOCK_SIZE; 2342aa3a43e6SPascal van Leeuwen req->hmac = true; 2343aa3a43e6SPascal van Leeuwen 2344aa3a43e6SPascal van Leeuwen return 0; 2345aa3a43e6SPascal van Leeuwen } 2346aa3a43e6SPascal van Leeuwen 2347aa3a43e6SPascal van Leeuwen static int safexcel_hmac_sm3_digest(struct ahash_request *areq) 2348aa3a43e6SPascal van Leeuwen { 2349aa3a43e6SPascal van Leeuwen int ret = safexcel_hmac_sm3_init(areq); 2350aa3a43e6SPascal van Leeuwen 2351aa3a43e6SPascal van Leeuwen if (ret) 2352aa3a43e6SPascal van Leeuwen return ret; 2353aa3a43e6SPascal van Leeuwen 2354aa3a43e6SPascal van Leeuwen return safexcel_ahash_finup(areq); 2355aa3a43e6SPascal van Leeuwen } 2356aa3a43e6SPascal van Leeuwen 2357aa3a43e6SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_hmac_sm3 = { 2358aa3a43e6SPascal van Leeuwen .type = SAFEXCEL_ALG_TYPE_AHASH, 2359aa3a43e6SPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SM3, 2360aa3a43e6SPascal van Leeuwen .alg.ahash = { 2361aa3a43e6SPascal van Leeuwen .init = safexcel_hmac_sm3_init, 2362aa3a43e6SPascal van Leeuwen .update = safexcel_ahash_update, 2363aa3a43e6SPascal van Leeuwen .final = safexcel_ahash_final, 2364aa3a43e6SPascal van Leeuwen .finup = safexcel_ahash_finup, 2365aa3a43e6SPascal van Leeuwen .digest = safexcel_hmac_sm3_digest, 2366aa3a43e6SPascal van Leeuwen .setkey = safexcel_hmac_sm3_setkey, 2367aa3a43e6SPascal van Leeuwen .export = safexcel_ahash_export, 2368aa3a43e6SPascal van Leeuwen .import = safexcel_ahash_import, 2369aa3a43e6SPascal van Leeuwen .halg = { 2370aa3a43e6SPascal van Leeuwen .digestsize = SM3_DIGEST_SIZE, 2371aa3a43e6SPascal van Leeuwen .statesize = sizeof(struct safexcel_ahash_export_state), 2372aa3a43e6SPascal van Leeuwen .base = { 2373aa3a43e6SPascal van Leeuwen .cra_name = "hmac(sm3)", 2374aa3a43e6SPascal van Leeuwen .cra_driver_name = "safexcel-hmac-sm3", 2375aa3a43e6SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 2376aa3a43e6SPascal van Leeuwen .cra_flags = CRYPTO_ALG_ASYNC | 2377b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 2378aa3a43e6SPascal van Leeuwen CRYPTO_ALG_KERN_DRIVER_ONLY, 2379aa3a43e6SPascal van Leeuwen .cra_blocksize = SM3_BLOCK_SIZE, 2380aa3a43e6SPascal van Leeuwen .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 2381aa3a43e6SPascal van Leeuwen .cra_init = safexcel_ahash_cra_init, 2382aa3a43e6SPascal van Leeuwen .cra_exit = safexcel_ahash_cra_exit, 2383aa3a43e6SPascal van Leeuwen .cra_module = THIS_MODULE, 2384aa3a43e6SPascal van Leeuwen }, 2385aa3a43e6SPascal van Leeuwen }, 2386aa3a43e6SPascal van Leeuwen }, 2387aa3a43e6SPascal van Leeuwen }; 2388aaf5a383SPascal van Leeuwen 2389aaf5a383SPascal van Leeuwen static int safexcel_sha3_224_init(struct ahash_request *areq) 2390aaf5a383SPascal van Leeuwen { 2391aaf5a383SPascal van Leeuwen struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 2392aaf5a383SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 2393aaf5a383SPascal van Leeuwen struct safexcel_ahash_req *req = ahash_request_ctx(areq); 2394aaf5a383SPascal van Leeuwen 2395aaf5a383SPascal van Leeuwen memset(req, 0, sizeof(*req)); 2396aaf5a383SPascal van Leeuwen 2397aaf5a383SPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_224; 2398aaf5a383SPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_INITIAL; 2399aaf5a383SPascal van Leeuwen req->state_sz = SHA3_224_DIGEST_SIZE; 24006c1c09b3SPascal van Leeuwen req->digest_sz = SHA3_224_DIGEST_SIZE; 2401aaf5a383SPascal van Leeuwen req->block_sz = SHA3_224_BLOCK_SIZE; 2402aaf5a383SPascal van Leeuwen ctx->do_fallback = false; 2403aaf5a383SPascal van Leeuwen ctx->fb_init_done = false; 2404aaf5a383SPascal van Leeuwen return 0; 2405aaf5a383SPascal van Leeuwen } 2406aaf5a383SPascal van Leeuwen 2407aaf5a383SPascal van Leeuwen static int safexcel_sha3_fbcheck(struct ahash_request *req) 2408aaf5a383SPascal van Leeuwen { 2409aaf5a383SPascal van Leeuwen struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 2410aaf5a383SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 2411aaf5a383SPascal van Leeuwen struct ahash_request *subreq = ahash_request_ctx(req); 2412aaf5a383SPascal van Leeuwen int ret = 0; 2413aaf5a383SPascal van Leeuwen 2414aaf5a383SPascal van Leeuwen if (ctx->do_fallback) { 2415aaf5a383SPascal van Leeuwen ahash_request_set_tfm(subreq, ctx->fback); 2416aaf5a383SPascal van Leeuwen ahash_request_set_callback(subreq, req->base.flags, 2417aaf5a383SPascal van Leeuwen req->base.complete, req->base.data); 2418aaf5a383SPascal van Leeuwen ahash_request_set_crypt(subreq, req->src, req->result, 2419aaf5a383SPascal van Leeuwen req->nbytes); 2420aaf5a383SPascal van Leeuwen if (!ctx->fb_init_done) { 24216c1c09b3SPascal van Leeuwen if (ctx->fb_do_setkey) { 24226c1c09b3SPascal van Leeuwen /* Set fallback cipher HMAC key */ 24236c1c09b3SPascal van Leeuwen u8 key[SHA3_224_BLOCK_SIZE]; 24246c1c09b3SPascal van Leeuwen 24256c1c09b3SPascal van Leeuwen memcpy(key, ctx->ipad, 24266c1c09b3SPascal van Leeuwen crypto_ahash_blocksize(ctx->fback) / 2); 24276c1c09b3SPascal van Leeuwen memcpy(key + 24286c1c09b3SPascal van Leeuwen crypto_ahash_blocksize(ctx->fback) / 2, 24296c1c09b3SPascal van Leeuwen ctx->opad, 24306c1c09b3SPascal van Leeuwen crypto_ahash_blocksize(ctx->fback) / 2); 24316c1c09b3SPascal van Leeuwen ret = crypto_ahash_setkey(ctx->fback, key, 24326c1c09b3SPascal van Leeuwen crypto_ahash_blocksize(ctx->fback)); 24336c1c09b3SPascal van Leeuwen memzero_explicit(key, 24346c1c09b3SPascal van Leeuwen crypto_ahash_blocksize(ctx->fback)); 24356c1c09b3SPascal van Leeuwen ctx->fb_do_setkey = false; 24366c1c09b3SPascal van Leeuwen } 24376c1c09b3SPascal van Leeuwen ret = ret ?: crypto_ahash_init(subreq); 2438aaf5a383SPascal van Leeuwen ctx->fb_init_done = true; 2439aaf5a383SPascal van Leeuwen } 2440aaf5a383SPascal van Leeuwen } 2441aaf5a383SPascal van Leeuwen return ret; 2442aaf5a383SPascal van Leeuwen } 2443aaf5a383SPascal van Leeuwen 2444aaf5a383SPascal van Leeuwen static int safexcel_sha3_update(struct ahash_request *req) 2445aaf5a383SPascal van Leeuwen { 2446aaf5a383SPascal van Leeuwen struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 2447aaf5a383SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 2448aaf5a383SPascal van Leeuwen struct ahash_request *subreq = ahash_request_ctx(req); 2449aaf5a383SPascal van Leeuwen 2450aaf5a383SPascal van Leeuwen ctx->do_fallback = true; 2451aaf5a383SPascal van Leeuwen return safexcel_sha3_fbcheck(req) ?: crypto_ahash_update(subreq); 2452aaf5a383SPascal van Leeuwen } 2453aaf5a383SPascal van Leeuwen 2454aaf5a383SPascal van Leeuwen static int safexcel_sha3_final(struct ahash_request *req) 2455aaf5a383SPascal van Leeuwen { 2456aaf5a383SPascal van Leeuwen struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 2457aaf5a383SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 2458aaf5a383SPascal van Leeuwen struct ahash_request *subreq = ahash_request_ctx(req); 2459aaf5a383SPascal van Leeuwen 2460aaf5a383SPascal van Leeuwen ctx->do_fallback = true; 2461aaf5a383SPascal van Leeuwen return safexcel_sha3_fbcheck(req) ?: crypto_ahash_final(subreq); 2462aaf5a383SPascal van Leeuwen } 2463aaf5a383SPascal van Leeuwen 2464aaf5a383SPascal van Leeuwen static int safexcel_sha3_finup(struct ahash_request *req) 2465aaf5a383SPascal van Leeuwen { 2466aaf5a383SPascal van Leeuwen struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 2467aaf5a383SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 2468aaf5a383SPascal van Leeuwen struct ahash_request *subreq = ahash_request_ctx(req); 2469aaf5a383SPascal van Leeuwen 2470aaf5a383SPascal van Leeuwen ctx->do_fallback |= !req->nbytes; 2471aaf5a383SPascal van Leeuwen if (ctx->do_fallback) 2472aaf5a383SPascal van Leeuwen /* Update or ex/import happened or len 0, cannot use the HW */ 2473aaf5a383SPascal van Leeuwen return safexcel_sha3_fbcheck(req) ?: 2474aaf5a383SPascal van Leeuwen crypto_ahash_finup(subreq); 2475aaf5a383SPascal van Leeuwen else 2476aaf5a383SPascal van Leeuwen return safexcel_ahash_finup(req); 2477aaf5a383SPascal van Leeuwen } 2478aaf5a383SPascal van Leeuwen 2479aaf5a383SPascal van Leeuwen static int safexcel_sha3_digest_fallback(struct ahash_request *req) 2480aaf5a383SPascal van Leeuwen { 2481aaf5a383SPascal van Leeuwen struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 2482aaf5a383SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 2483aaf5a383SPascal van Leeuwen struct ahash_request *subreq = ahash_request_ctx(req); 2484aaf5a383SPascal van Leeuwen 2485aaf5a383SPascal van Leeuwen ctx->do_fallback = true; 2486aaf5a383SPascal van Leeuwen ctx->fb_init_done = false; 2487aaf5a383SPascal van Leeuwen return safexcel_sha3_fbcheck(req) ?: crypto_ahash_finup(subreq); 2488aaf5a383SPascal van Leeuwen } 2489aaf5a383SPascal van Leeuwen 2490aaf5a383SPascal van Leeuwen static int safexcel_sha3_224_digest(struct ahash_request *req) 2491aaf5a383SPascal van Leeuwen { 2492aaf5a383SPascal van Leeuwen if (req->nbytes) 2493aaf5a383SPascal van Leeuwen return safexcel_sha3_224_init(req) ?: safexcel_ahash_finup(req); 2494aaf5a383SPascal van Leeuwen 2495aaf5a383SPascal van Leeuwen /* HW cannot do zero length hash, use fallback instead */ 2496aaf5a383SPascal van Leeuwen return safexcel_sha3_digest_fallback(req); 2497aaf5a383SPascal van Leeuwen } 2498aaf5a383SPascal van Leeuwen 2499aaf5a383SPascal van Leeuwen static int safexcel_sha3_export(struct ahash_request *req, void *out) 2500aaf5a383SPascal van Leeuwen { 2501aaf5a383SPascal van Leeuwen struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 2502aaf5a383SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 2503aaf5a383SPascal van Leeuwen struct ahash_request *subreq = ahash_request_ctx(req); 2504aaf5a383SPascal van Leeuwen 2505aaf5a383SPascal van Leeuwen ctx->do_fallback = true; 2506aaf5a383SPascal van Leeuwen return safexcel_sha3_fbcheck(req) ?: crypto_ahash_export(subreq, out); 2507aaf5a383SPascal van Leeuwen } 2508aaf5a383SPascal van Leeuwen 2509aaf5a383SPascal van Leeuwen static int safexcel_sha3_import(struct ahash_request *req, const void *in) 2510aaf5a383SPascal van Leeuwen { 2511aaf5a383SPascal van Leeuwen struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 2512aaf5a383SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 2513aaf5a383SPascal van Leeuwen struct ahash_request *subreq = ahash_request_ctx(req); 2514aaf5a383SPascal van Leeuwen 2515aaf5a383SPascal van Leeuwen ctx->do_fallback = true; 2516aaf5a383SPascal van Leeuwen return safexcel_sha3_fbcheck(req) ?: crypto_ahash_import(subreq, in); 2517aaf5a383SPascal van Leeuwen // return safexcel_ahash_import(req, in); 2518aaf5a383SPascal van Leeuwen } 2519aaf5a383SPascal van Leeuwen 2520aaf5a383SPascal van Leeuwen static int safexcel_sha3_cra_init(struct crypto_tfm *tfm) 2521aaf5a383SPascal van Leeuwen { 2522aaf5a383SPascal van Leeuwen struct crypto_ahash *ahash = __crypto_ahash_cast(tfm); 2523aaf5a383SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 2524aaf5a383SPascal van Leeuwen 2525aaf5a383SPascal van Leeuwen safexcel_ahash_cra_init(tfm); 2526aaf5a383SPascal van Leeuwen 2527aaf5a383SPascal van Leeuwen /* Allocate fallback implementation */ 2528aaf5a383SPascal van Leeuwen ctx->fback = crypto_alloc_ahash(crypto_tfm_alg_name(tfm), 0, 2529aaf5a383SPascal van Leeuwen CRYPTO_ALG_ASYNC | 2530aaf5a383SPascal van Leeuwen CRYPTO_ALG_NEED_FALLBACK); 2531aaf5a383SPascal van Leeuwen if (IS_ERR(ctx->fback)) 2532aaf5a383SPascal van Leeuwen return PTR_ERR(ctx->fback); 2533aaf5a383SPascal van Leeuwen 2534aaf5a383SPascal van Leeuwen /* Update statesize from fallback algorithm! */ 2535aaf5a383SPascal van Leeuwen crypto_hash_alg_common(ahash)->statesize = 2536aaf5a383SPascal van Leeuwen crypto_ahash_statesize(ctx->fback); 2537aaf5a383SPascal van Leeuwen crypto_ahash_set_reqsize(ahash, max(sizeof(struct safexcel_ahash_req), 2538aaf5a383SPascal van Leeuwen sizeof(struct ahash_request) + 2539aaf5a383SPascal van Leeuwen crypto_ahash_reqsize(ctx->fback))); 2540aaf5a383SPascal van Leeuwen return 0; 2541aaf5a383SPascal van Leeuwen } 2542aaf5a383SPascal van Leeuwen 2543aaf5a383SPascal van Leeuwen static void safexcel_sha3_cra_exit(struct crypto_tfm *tfm) 2544aaf5a383SPascal van Leeuwen { 2545aaf5a383SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 2546aaf5a383SPascal van Leeuwen 2547aaf5a383SPascal van Leeuwen crypto_free_ahash(ctx->fback); 2548aaf5a383SPascal van Leeuwen safexcel_ahash_cra_exit(tfm); 2549aaf5a383SPascal van Leeuwen } 2550aaf5a383SPascal van Leeuwen 2551aaf5a383SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_sha3_224 = { 2552aaf5a383SPascal van Leeuwen .type = SAFEXCEL_ALG_TYPE_AHASH, 2553aaf5a383SPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA3, 2554aaf5a383SPascal van Leeuwen .alg.ahash = { 2555aaf5a383SPascal van Leeuwen .init = safexcel_sha3_224_init, 2556aaf5a383SPascal van Leeuwen .update = safexcel_sha3_update, 2557aaf5a383SPascal van Leeuwen .final = safexcel_sha3_final, 2558aaf5a383SPascal van Leeuwen .finup = safexcel_sha3_finup, 2559aaf5a383SPascal van Leeuwen .digest = safexcel_sha3_224_digest, 2560aaf5a383SPascal van Leeuwen .export = safexcel_sha3_export, 2561aaf5a383SPascal van Leeuwen .import = safexcel_sha3_import, 2562aaf5a383SPascal van Leeuwen .halg = { 2563aaf5a383SPascal van Leeuwen .digestsize = SHA3_224_DIGEST_SIZE, 2564aaf5a383SPascal van Leeuwen .statesize = sizeof(struct safexcel_ahash_export_state), 2565aaf5a383SPascal van Leeuwen .base = { 2566aaf5a383SPascal van Leeuwen .cra_name = "sha3-224", 2567aaf5a383SPascal van Leeuwen .cra_driver_name = "safexcel-sha3-224", 2568aaf5a383SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 2569aaf5a383SPascal van Leeuwen .cra_flags = CRYPTO_ALG_ASYNC | 2570aaf5a383SPascal van Leeuwen CRYPTO_ALG_KERN_DRIVER_ONLY | 2571aaf5a383SPascal van Leeuwen CRYPTO_ALG_NEED_FALLBACK, 2572aaf5a383SPascal van Leeuwen .cra_blocksize = SHA3_224_BLOCK_SIZE, 2573aaf5a383SPascal van Leeuwen .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 2574aaf5a383SPascal van Leeuwen .cra_init = safexcel_sha3_cra_init, 2575aaf5a383SPascal van Leeuwen .cra_exit = safexcel_sha3_cra_exit, 2576aaf5a383SPascal van Leeuwen .cra_module = THIS_MODULE, 2577aaf5a383SPascal van Leeuwen }, 2578aaf5a383SPascal van Leeuwen }, 2579aaf5a383SPascal van Leeuwen }, 2580aaf5a383SPascal van Leeuwen }; 2581aaf5a383SPascal van Leeuwen 2582aaf5a383SPascal van Leeuwen static int safexcel_sha3_256_init(struct ahash_request *areq) 2583aaf5a383SPascal van Leeuwen { 2584aaf5a383SPascal van Leeuwen struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 2585aaf5a383SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 2586aaf5a383SPascal van Leeuwen struct safexcel_ahash_req *req = ahash_request_ctx(areq); 2587aaf5a383SPascal van Leeuwen 2588aaf5a383SPascal van Leeuwen memset(req, 0, sizeof(*req)); 2589aaf5a383SPascal van Leeuwen 2590aaf5a383SPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_256; 2591aaf5a383SPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_INITIAL; 2592aaf5a383SPascal van Leeuwen req->state_sz = SHA3_256_DIGEST_SIZE; 25936c1c09b3SPascal van Leeuwen req->digest_sz = SHA3_256_DIGEST_SIZE; 2594aaf5a383SPascal van Leeuwen req->block_sz = SHA3_256_BLOCK_SIZE; 2595aaf5a383SPascal van Leeuwen ctx->do_fallback = false; 2596aaf5a383SPascal van Leeuwen ctx->fb_init_done = false; 2597aaf5a383SPascal van Leeuwen return 0; 2598aaf5a383SPascal van Leeuwen } 2599aaf5a383SPascal van Leeuwen 2600aaf5a383SPascal van Leeuwen static int safexcel_sha3_256_digest(struct ahash_request *req) 2601aaf5a383SPascal van Leeuwen { 2602aaf5a383SPascal van Leeuwen if (req->nbytes) 2603aaf5a383SPascal van Leeuwen return safexcel_sha3_256_init(req) ?: safexcel_ahash_finup(req); 2604aaf5a383SPascal van Leeuwen 2605aaf5a383SPascal van Leeuwen /* HW cannot do zero length hash, use fallback instead */ 2606aaf5a383SPascal van Leeuwen return safexcel_sha3_digest_fallback(req); 2607aaf5a383SPascal van Leeuwen } 2608aaf5a383SPascal van Leeuwen 2609aaf5a383SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_sha3_256 = { 2610aaf5a383SPascal van Leeuwen .type = SAFEXCEL_ALG_TYPE_AHASH, 2611aaf5a383SPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA3, 2612aaf5a383SPascal van Leeuwen .alg.ahash = { 2613aaf5a383SPascal van Leeuwen .init = safexcel_sha3_256_init, 2614aaf5a383SPascal van Leeuwen .update = safexcel_sha3_update, 2615aaf5a383SPascal van Leeuwen .final = safexcel_sha3_final, 2616aaf5a383SPascal van Leeuwen .finup = safexcel_sha3_finup, 2617aaf5a383SPascal van Leeuwen .digest = safexcel_sha3_256_digest, 2618aaf5a383SPascal van Leeuwen .export = safexcel_sha3_export, 2619aaf5a383SPascal van Leeuwen .import = safexcel_sha3_import, 2620aaf5a383SPascal van Leeuwen .halg = { 2621aaf5a383SPascal van Leeuwen .digestsize = SHA3_256_DIGEST_SIZE, 2622aaf5a383SPascal van Leeuwen .statesize = sizeof(struct safexcel_ahash_export_state), 2623aaf5a383SPascal van Leeuwen .base = { 2624aaf5a383SPascal van Leeuwen .cra_name = "sha3-256", 2625aaf5a383SPascal van Leeuwen .cra_driver_name = "safexcel-sha3-256", 2626aaf5a383SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 2627aaf5a383SPascal van Leeuwen .cra_flags = CRYPTO_ALG_ASYNC | 2628aaf5a383SPascal van Leeuwen CRYPTO_ALG_KERN_DRIVER_ONLY | 2629aaf5a383SPascal van Leeuwen CRYPTO_ALG_NEED_FALLBACK, 2630aaf5a383SPascal van Leeuwen .cra_blocksize = SHA3_256_BLOCK_SIZE, 2631aaf5a383SPascal van Leeuwen .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 2632aaf5a383SPascal van Leeuwen .cra_init = safexcel_sha3_cra_init, 2633aaf5a383SPascal van Leeuwen .cra_exit = safexcel_sha3_cra_exit, 2634aaf5a383SPascal van Leeuwen .cra_module = THIS_MODULE, 2635aaf5a383SPascal van Leeuwen }, 2636aaf5a383SPascal van Leeuwen }, 2637aaf5a383SPascal van Leeuwen }, 2638aaf5a383SPascal van Leeuwen }; 2639aaf5a383SPascal van Leeuwen 2640aaf5a383SPascal van Leeuwen static int safexcel_sha3_384_init(struct ahash_request *areq) 2641aaf5a383SPascal van Leeuwen { 2642aaf5a383SPascal van Leeuwen struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 2643aaf5a383SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 2644aaf5a383SPascal van Leeuwen struct safexcel_ahash_req *req = ahash_request_ctx(areq); 2645aaf5a383SPascal van Leeuwen 2646aaf5a383SPascal van Leeuwen memset(req, 0, sizeof(*req)); 2647aaf5a383SPascal van Leeuwen 2648aaf5a383SPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_384; 2649aaf5a383SPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_INITIAL; 2650aaf5a383SPascal van Leeuwen req->state_sz = SHA3_384_DIGEST_SIZE; 26516c1c09b3SPascal van Leeuwen req->digest_sz = SHA3_384_DIGEST_SIZE; 2652aaf5a383SPascal van Leeuwen req->block_sz = SHA3_384_BLOCK_SIZE; 2653aaf5a383SPascal van Leeuwen ctx->do_fallback = false; 2654aaf5a383SPascal van Leeuwen ctx->fb_init_done = false; 2655aaf5a383SPascal van Leeuwen return 0; 2656aaf5a383SPascal van Leeuwen } 2657aaf5a383SPascal van Leeuwen 2658aaf5a383SPascal van Leeuwen static int safexcel_sha3_384_digest(struct ahash_request *req) 2659aaf5a383SPascal van Leeuwen { 2660aaf5a383SPascal van Leeuwen if (req->nbytes) 2661aaf5a383SPascal van Leeuwen return safexcel_sha3_384_init(req) ?: safexcel_ahash_finup(req); 2662aaf5a383SPascal van Leeuwen 2663aaf5a383SPascal van Leeuwen /* HW cannot do zero length hash, use fallback instead */ 2664aaf5a383SPascal van Leeuwen return safexcel_sha3_digest_fallback(req); 2665aaf5a383SPascal van Leeuwen } 2666aaf5a383SPascal van Leeuwen 2667aaf5a383SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_sha3_384 = { 2668aaf5a383SPascal van Leeuwen .type = SAFEXCEL_ALG_TYPE_AHASH, 2669aaf5a383SPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA3, 2670aaf5a383SPascal van Leeuwen .alg.ahash = { 2671aaf5a383SPascal van Leeuwen .init = safexcel_sha3_384_init, 2672aaf5a383SPascal van Leeuwen .update = safexcel_sha3_update, 2673aaf5a383SPascal van Leeuwen .final = safexcel_sha3_final, 2674aaf5a383SPascal van Leeuwen .finup = safexcel_sha3_finup, 2675aaf5a383SPascal van Leeuwen .digest = safexcel_sha3_384_digest, 2676aaf5a383SPascal van Leeuwen .export = safexcel_sha3_export, 2677aaf5a383SPascal van Leeuwen .import = safexcel_sha3_import, 2678aaf5a383SPascal van Leeuwen .halg = { 2679aaf5a383SPascal van Leeuwen .digestsize = SHA3_384_DIGEST_SIZE, 2680aaf5a383SPascal van Leeuwen .statesize = sizeof(struct safexcel_ahash_export_state), 2681aaf5a383SPascal van Leeuwen .base = { 2682aaf5a383SPascal van Leeuwen .cra_name = "sha3-384", 2683aaf5a383SPascal van Leeuwen .cra_driver_name = "safexcel-sha3-384", 2684aaf5a383SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 2685aaf5a383SPascal van Leeuwen .cra_flags = CRYPTO_ALG_ASYNC | 2686aaf5a383SPascal van Leeuwen CRYPTO_ALG_KERN_DRIVER_ONLY | 2687aaf5a383SPascal van Leeuwen CRYPTO_ALG_NEED_FALLBACK, 2688aaf5a383SPascal van Leeuwen .cra_blocksize = SHA3_384_BLOCK_SIZE, 2689aaf5a383SPascal van Leeuwen .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 2690aaf5a383SPascal van Leeuwen .cra_init = safexcel_sha3_cra_init, 2691aaf5a383SPascal van Leeuwen .cra_exit = safexcel_sha3_cra_exit, 2692aaf5a383SPascal van Leeuwen .cra_module = THIS_MODULE, 2693aaf5a383SPascal van Leeuwen }, 2694aaf5a383SPascal van Leeuwen }, 2695aaf5a383SPascal van Leeuwen }, 2696aaf5a383SPascal van Leeuwen }; 2697aaf5a383SPascal van Leeuwen 2698aaf5a383SPascal van Leeuwen static int safexcel_sha3_512_init(struct ahash_request *areq) 2699aaf5a383SPascal van Leeuwen { 2700aaf5a383SPascal van Leeuwen struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 2701aaf5a383SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 2702aaf5a383SPascal van Leeuwen struct safexcel_ahash_req *req = ahash_request_ctx(areq); 2703aaf5a383SPascal van Leeuwen 2704aaf5a383SPascal van Leeuwen memset(req, 0, sizeof(*req)); 2705aaf5a383SPascal van Leeuwen 2706aaf5a383SPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_512; 2707aaf5a383SPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_INITIAL; 2708aaf5a383SPascal van Leeuwen req->state_sz = SHA3_512_DIGEST_SIZE; 27096c1c09b3SPascal van Leeuwen req->digest_sz = SHA3_512_DIGEST_SIZE; 2710aaf5a383SPascal van Leeuwen req->block_sz = SHA3_512_BLOCK_SIZE; 2711aaf5a383SPascal van Leeuwen ctx->do_fallback = false; 2712aaf5a383SPascal van Leeuwen ctx->fb_init_done = false; 2713aaf5a383SPascal van Leeuwen return 0; 2714aaf5a383SPascal van Leeuwen } 2715aaf5a383SPascal van Leeuwen 2716aaf5a383SPascal van Leeuwen static int safexcel_sha3_512_digest(struct ahash_request *req) 2717aaf5a383SPascal van Leeuwen { 2718aaf5a383SPascal van Leeuwen if (req->nbytes) 2719aaf5a383SPascal van Leeuwen return safexcel_sha3_512_init(req) ?: safexcel_ahash_finup(req); 2720aaf5a383SPascal van Leeuwen 2721aaf5a383SPascal van Leeuwen /* HW cannot do zero length hash, use fallback instead */ 2722aaf5a383SPascal van Leeuwen return safexcel_sha3_digest_fallback(req); 2723aaf5a383SPascal van Leeuwen } 2724aaf5a383SPascal van Leeuwen 2725aaf5a383SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_sha3_512 = { 2726aaf5a383SPascal van Leeuwen .type = SAFEXCEL_ALG_TYPE_AHASH, 2727aaf5a383SPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA3, 2728aaf5a383SPascal van Leeuwen .alg.ahash = { 2729aaf5a383SPascal van Leeuwen .init = safexcel_sha3_512_init, 2730aaf5a383SPascal van Leeuwen .update = safexcel_sha3_update, 2731aaf5a383SPascal van Leeuwen .final = safexcel_sha3_final, 2732aaf5a383SPascal van Leeuwen .finup = safexcel_sha3_finup, 2733aaf5a383SPascal van Leeuwen .digest = safexcel_sha3_512_digest, 2734aaf5a383SPascal van Leeuwen .export = safexcel_sha3_export, 2735aaf5a383SPascal van Leeuwen .import = safexcel_sha3_import, 2736aaf5a383SPascal van Leeuwen .halg = { 2737aaf5a383SPascal van Leeuwen .digestsize = SHA3_512_DIGEST_SIZE, 2738aaf5a383SPascal van Leeuwen .statesize = sizeof(struct safexcel_ahash_export_state), 2739aaf5a383SPascal van Leeuwen .base = { 2740aaf5a383SPascal van Leeuwen .cra_name = "sha3-512", 2741aaf5a383SPascal van Leeuwen .cra_driver_name = "safexcel-sha3-512", 2742aaf5a383SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 2743aaf5a383SPascal van Leeuwen .cra_flags = CRYPTO_ALG_ASYNC | 2744aaf5a383SPascal van Leeuwen CRYPTO_ALG_KERN_DRIVER_ONLY | 2745aaf5a383SPascal van Leeuwen CRYPTO_ALG_NEED_FALLBACK, 2746aaf5a383SPascal van Leeuwen .cra_blocksize = SHA3_512_BLOCK_SIZE, 2747aaf5a383SPascal van Leeuwen .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 2748aaf5a383SPascal van Leeuwen .cra_init = safexcel_sha3_cra_init, 2749aaf5a383SPascal van Leeuwen .cra_exit = safexcel_sha3_cra_exit, 2750aaf5a383SPascal van Leeuwen .cra_module = THIS_MODULE, 2751aaf5a383SPascal van Leeuwen }, 2752aaf5a383SPascal van Leeuwen }, 2753aaf5a383SPascal van Leeuwen }, 2754aaf5a383SPascal van Leeuwen }; 27556c1c09b3SPascal van Leeuwen 27566c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_cra_init(struct crypto_tfm *tfm, const char *alg) 27576c1c09b3SPascal van Leeuwen { 27586c1c09b3SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 27596c1c09b3SPascal van Leeuwen int ret; 27606c1c09b3SPascal van Leeuwen 27616c1c09b3SPascal van Leeuwen ret = safexcel_sha3_cra_init(tfm); 27626c1c09b3SPascal van Leeuwen if (ret) 27636c1c09b3SPascal van Leeuwen return ret; 27646c1c09b3SPascal van Leeuwen 27656c1c09b3SPascal van Leeuwen /* Allocate precalc basic digest implementation */ 27666c1c09b3SPascal van Leeuwen ctx->shpre = crypto_alloc_shash(alg, 0, CRYPTO_ALG_NEED_FALLBACK); 27676c1c09b3SPascal van Leeuwen if (IS_ERR(ctx->shpre)) 27686c1c09b3SPascal van Leeuwen return PTR_ERR(ctx->shpre); 27696c1c09b3SPascal van Leeuwen 27706c1c09b3SPascal van Leeuwen ctx->shdesc = kmalloc(sizeof(*ctx->shdesc) + 27716c1c09b3SPascal van Leeuwen crypto_shash_descsize(ctx->shpre), GFP_KERNEL); 27726c1c09b3SPascal van Leeuwen if (!ctx->shdesc) { 27736c1c09b3SPascal van Leeuwen crypto_free_shash(ctx->shpre); 27746c1c09b3SPascal van Leeuwen return -ENOMEM; 27756c1c09b3SPascal van Leeuwen } 27766c1c09b3SPascal van Leeuwen ctx->shdesc->tfm = ctx->shpre; 27776c1c09b3SPascal van Leeuwen return 0; 27786c1c09b3SPascal van Leeuwen } 27796c1c09b3SPascal van Leeuwen 27806c1c09b3SPascal van Leeuwen static void safexcel_hmac_sha3_cra_exit(struct crypto_tfm *tfm) 27816c1c09b3SPascal van Leeuwen { 27826c1c09b3SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); 27836c1c09b3SPascal van Leeuwen 27846c1c09b3SPascal van Leeuwen crypto_free_ahash(ctx->fback); 27856c1c09b3SPascal van Leeuwen crypto_free_shash(ctx->shpre); 27866c1c09b3SPascal van Leeuwen kfree(ctx->shdesc); 27876c1c09b3SPascal van Leeuwen safexcel_ahash_cra_exit(tfm); 27886c1c09b3SPascal van Leeuwen } 27896c1c09b3SPascal van Leeuwen 27906c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_setkey(struct crypto_ahash *tfm, const u8 *key, 27916c1c09b3SPascal van Leeuwen unsigned int keylen) 27926c1c09b3SPascal van Leeuwen { 27936c1c09b3SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 27946c1c09b3SPascal van Leeuwen int ret = 0; 27956c1c09b3SPascal van Leeuwen 27966c1c09b3SPascal van Leeuwen if (keylen > crypto_ahash_blocksize(tfm)) { 27976c1c09b3SPascal van Leeuwen /* 27986c1c09b3SPascal van Leeuwen * If the key is larger than the blocksize, then hash it 27996c1c09b3SPascal van Leeuwen * first using our fallback cipher 28006c1c09b3SPascal van Leeuwen */ 28016c1c09b3SPascal van Leeuwen ret = crypto_shash_digest(ctx->shdesc, key, keylen, 28026c1c09b3SPascal van Leeuwen (u8 *)ctx->ipad); 28036c1c09b3SPascal van Leeuwen keylen = crypto_shash_digestsize(ctx->shpre); 28046c1c09b3SPascal van Leeuwen 28056c1c09b3SPascal van Leeuwen /* 28066c1c09b3SPascal van Leeuwen * If the digest is larger than half the blocksize, we need to 28076c1c09b3SPascal van Leeuwen * move the rest to opad due to the way our HMAC infra works. 28086c1c09b3SPascal van Leeuwen */ 28096c1c09b3SPascal van Leeuwen if (keylen > crypto_ahash_blocksize(tfm) / 2) 28106c1c09b3SPascal van Leeuwen /* Buffers overlap, need to use memmove iso memcpy! */ 28116c1c09b3SPascal van Leeuwen memmove(ctx->opad, 28126c1c09b3SPascal van Leeuwen (u8 *)ctx->ipad + 28136c1c09b3SPascal van Leeuwen crypto_ahash_blocksize(tfm) / 2, 28146c1c09b3SPascal van Leeuwen keylen - crypto_ahash_blocksize(tfm) / 2); 28156c1c09b3SPascal van Leeuwen } else { 28166c1c09b3SPascal van Leeuwen /* 28176c1c09b3SPascal van Leeuwen * Copy the key to our ipad & opad buffers 28186c1c09b3SPascal van Leeuwen * Note that ipad and opad each contain one half of the key, 28196c1c09b3SPascal van Leeuwen * to match the existing HMAC driver infrastructure. 28206c1c09b3SPascal van Leeuwen */ 28216c1c09b3SPascal van Leeuwen if (keylen <= crypto_ahash_blocksize(tfm) / 2) { 28226c1c09b3SPascal van Leeuwen memcpy(ctx->ipad, key, keylen); 28236c1c09b3SPascal van Leeuwen } else { 28246c1c09b3SPascal van Leeuwen memcpy(ctx->ipad, key, 28256c1c09b3SPascal van Leeuwen crypto_ahash_blocksize(tfm) / 2); 28266c1c09b3SPascal van Leeuwen memcpy(ctx->opad, 28276c1c09b3SPascal van Leeuwen key + crypto_ahash_blocksize(tfm) / 2, 28286c1c09b3SPascal van Leeuwen keylen - crypto_ahash_blocksize(tfm) / 2); 28296c1c09b3SPascal van Leeuwen } 28306c1c09b3SPascal van Leeuwen } 28316c1c09b3SPascal van Leeuwen 28326c1c09b3SPascal van Leeuwen /* Pad key with zeroes */ 28336c1c09b3SPascal van Leeuwen if (keylen <= crypto_ahash_blocksize(tfm) / 2) { 28346c1c09b3SPascal van Leeuwen memset((u8 *)ctx->ipad + keylen, 0, 28356c1c09b3SPascal van Leeuwen crypto_ahash_blocksize(tfm) / 2 - keylen); 28366c1c09b3SPascal van Leeuwen memset(ctx->opad, 0, crypto_ahash_blocksize(tfm) / 2); 28376c1c09b3SPascal van Leeuwen } else { 28386c1c09b3SPascal van Leeuwen memset((u8 *)ctx->opad + keylen - 28396c1c09b3SPascal van Leeuwen crypto_ahash_blocksize(tfm) / 2, 0, 28406c1c09b3SPascal van Leeuwen crypto_ahash_blocksize(tfm) - keylen); 28416c1c09b3SPascal van Leeuwen } 28426c1c09b3SPascal van Leeuwen 28436c1c09b3SPascal van Leeuwen /* If doing fallback, still need to set the new key! */ 28446c1c09b3SPascal van Leeuwen ctx->fb_do_setkey = true; 28456c1c09b3SPascal van Leeuwen return ret; 28466c1c09b3SPascal van Leeuwen } 28476c1c09b3SPascal van Leeuwen 28486c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_224_init(struct ahash_request *areq) 28496c1c09b3SPascal van Leeuwen { 28506c1c09b3SPascal van Leeuwen struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 28516c1c09b3SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 28526c1c09b3SPascal van Leeuwen struct safexcel_ahash_req *req = ahash_request_ctx(areq); 28536c1c09b3SPascal van Leeuwen 28546c1c09b3SPascal van Leeuwen memset(req, 0, sizeof(*req)); 28556c1c09b3SPascal van Leeuwen 28566c1c09b3SPascal van Leeuwen /* Copy (half of) the key */ 28576c1c09b3SPascal van Leeuwen memcpy(req->state, ctx->ipad, SHA3_224_BLOCK_SIZE / 2); 28586c1c09b3SPascal van Leeuwen /* Start of HMAC should have len == processed == blocksize */ 28596c1c09b3SPascal van Leeuwen req->len = SHA3_224_BLOCK_SIZE; 28606c1c09b3SPascal van Leeuwen req->processed = SHA3_224_BLOCK_SIZE; 28616c1c09b3SPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_224; 28626c1c09b3SPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_HMAC; 28636c1c09b3SPascal van Leeuwen req->state_sz = SHA3_224_BLOCK_SIZE / 2; 28646c1c09b3SPascal van Leeuwen req->digest_sz = SHA3_224_DIGEST_SIZE; 28656c1c09b3SPascal van Leeuwen req->block_sz = SHA3_224_BLOCK_SIZE; 28666c1c09b3SPascal van Leeuwen req->hmac = true; 28676c1c09b3SPascal van Leeuwen ctx->do_fallback = false; 28686c1c09b3SPascal van Leeuwen ctx->fb_init_done = false; 28696c1c09b3SPascal van Leeuwen return 0; 28706c1c09b3SPascal van Leeuwen } 28716c1c09b3SPascal van Leeuwen 28726c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_224_digest(struct ahash_request *req) 28736c1c09b3SPascal van Leeuwen { 28746c1c09b3SPascal van Leeuwen if (req->nbytes) 28756c1c09b3SPascal van Leeuwen return safexcel_hmac_sha3_224_init(req) ?: 28766c1c09b3SPascal van Leeuwen safexcel_ahash_finup(req); 28776c1c09b3SPascal van Leeuwen 28786c1c09b3SPascal van Leeuwen /* HW cannot do zero length HMAC, use fallback instead */ 28796c1c09b3SPascal van Leeuwen return safexcel_sha3_digest_fallback(req); 28806c1c09b3SPascal van Leeuwen } 28816c1c09b3SPascal van Leeuwen 28826c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_224_cra_init(struct crypto_tfm *tfm) 28836c1c09b3SPascal van Leeuwen { 28846c1c09b3SPascal van Leeuwen return safexcel_hmac_sha3_cra_init(tfm, "sha3-224"); 28856c1c09b3SPascal van Leeuwen } 28866c1c09b3SPascal van Leeuwen 28876c1c09b3SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_hmac_sha3_224 = { 28886c1c09b3SPascal van Leeuwen .type = SAFEXCEL_ALG_TYPE_AHASH, 28896c1c09b3SPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA3, 28906c1c09b3SPascal van Leeuwen .alg.ahash = { 28916c1c09b3SPascal van Leeuwen .init = safexcel_hmac_sha3_224_init, 28926c1c09b3SPascal van Leeuwen .update = safexcel_sha3_update, 28936c1c09b3SPascal van Leeuwen .final = safexcel_sha3_final, 28946c1c09b3SPascal van Leeuwen .finup = safexcel_sha3_finup, 28956c1c09b3SPascal van Leeuwen .digest = safexcel_hmac_sha3_224_digest, 28966c1c09b3SPascal van Leeuwen .setkey = safexcel_hmac_sha3_setkey, 28976c1c09b3SPascal van Leeuwen .export = safexcel_sha3_export, 28986c1c09b3SPascal van Leeuwen .import = safexcel_sha3_import, 28996c1c09b3SPascal van Leeuwen .halg = { 29006c1c09b3SPascal van Leeuwen .digestsize = SHA3_224_DIGEST_SIZE, 29016c1c09b3SPascal van Leeuwen .statesize = sizeof(struct safexcel_ahash_export_state), 29026c1c09b3SPascal van Leeuwen .base = { 29036c1c09b3SPascal van Leeuwen .cra_name = "hmac(sha3-224)", 29046c1c09b3SPascal van Leeuwen .cra_driver_name = "safexcel-hmac-sha3-224", 29056c1c09b3SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 29066c1c09b3SPascal van Leeuwen .cra_flags = CRYPTO_ALG_ASYNC | 29076c1c09b3SPascal van Leeuwen CRYPTO_ALG_KERN_DRIVER_ONLY | 29086c1c09b3SPascal van Leeuwen CRYPTO_ALG_NEED_FALLBACK, 29096c1c09b3SPascal van Leeuwen .cra_blocksize = SHA3_224_BLOCK_SIZE, 29106c1c09b3SPascal van Leeuwen .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 29116c1c09b3SPascal van Leeuwen .cra_init = safexcel_hmac_sha3_224_cra_init, 29126c1c09b3SPascal van Leeuwen .cra_exit = safexcel_hmac_sha3_cra_exit, 29136c1c09b3SPascal van Leeuwen .cra_module = THIS_MODULE, 29146c1c09b3SPascal van Leeuwen }, 29156c1c09b3SPascal van Leeuwen }, 29166c1c09b3SPascal van Leeuwen }, 29176c1c09b3SPascal van Leeuwen }; 29186c1c09b3SPascal van Leeuwen 29196c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_256_init(struct ahash_request *areq) 29206c1c09b3SPascal van Leeuwen { 29216c1c09b3SPascal van Leeuwen struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 29226c1c09b3SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 29236c1c09b3SPascal van Leeuwen struct safexcel_ahash_req *req = ahash_request_ctx(areq); 29246c1c09b3SPascal van Leeuwen 29256c1c09b3SPascal van Leeuwen memset(req, 0, sizeof(*req)); 29266c1c09b3SPascal van Leeuwen 29276c1c09b3SPascal van Leeuwen /* Copy (half of) the key */ 29286c1c09b3SPascal van Leeuwen memcpy(req->state, ctx->ipad, SHA3_256_BLOCK_SIZE / 2); 29296c1c09b3SPascal van Leeuwen /* Start of HMAC should have len == processed == blocksize */ 29306c1c09b3SPascal van Leeuwen req->len = SHA3_256_BLOCK_SIZE; 29316c1c09b3SPascal van Leeuwen req->processed = SHA3_256_BLOCK_SIZE; 29326c1c09b3SPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_256; 29336c1c09b3SPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_HMAC; 29346c1c09b3SPascal van Leeuwen req->state_sz = SHA3_256_BLOCK_SIZE / 2; 29356c1c09b3SPascal van Leeuwen req->digest_sz = SHA3_256_DIGEST_SIZE; 29366c1c09b3SPascal van Leeuwen req->block_sz = SHA3_256_BLOCK_SIZE; 29376c1c09b3SPascal van Leeuwen req->hmac = true; 29386c1c09b3SPascal van Leeuwen ctx->do_fallback = false; 29396c1c09b3SPascal van Leeuwen ctx->fb_init_done = false; 29406c1c09b3SPascal van Leeuwen return 0; 29416c1c09b3SPascal van Leeuwen } 29426c1c09b3SPascal van Leeuwen 29436c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_256_digest(struct ahash_request *req) 29446c1c09b3SPascal van Leeuwen { 29456c1c09b3SPascal van Leeuwen if (req->nbytes) 29466c1c09b3SPascal van Leeuwen return safexcel_hmac_sha3_256_init(req) ?: 29476c1c09b3SPascal van Leeuwen safexcel_ahash_finup(req); 29486c1c09b3SPascal van Leeuwen 29496c1c09b3SPascal van Leeuwen /* HW cannot do zero length HMAC, use fallback instead */ 29506c1c09b3SPascal van Leeuwen return safexcel_sha3_digest_fallback(req); 29516c1c09b3SPascal van Leeuwen } 29526c1c09b3SPascal van Leeuwen 29536c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_256_cra_init(struct crypto_tfm *tfm) 29546c1c09b3SPascal van Leeuwen { 29556c1c09b3SPascal van Leeuwen return safexcel_hmac_sha3_cra_init(tfm, "sha3-256"); 29566c1c09b3SPascal van Leeuwen } 29576c1c09b3SPascal van Leeuwen 29586c1c09b3SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_hmac_sha3_256 = { 29596c1c09b3SPascal van Leeuwen .type = SAFEXCEL_ALG_TYPE_AHASH, 29606c1c09b3SPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA3, 29616c1c09b3SPascal van Leeuwen .alg.ahash = { 29626c1c09b3SPascal van Leeuwen .init = safexcel_hmac_sha3_256_init, 29636c1c09b3SPascal van Leeuwen .update = safexcel_sha3_update, 29646c1c09b3SPascal van Leeuwen .final = safexcel_sha3_final, 29656c1c09b3SPascal van Leeuwen .finup = safexcel_sha3_finup, 29666c1c09b3SPascal van Leeuwen .digest = safexcel_hmac_sha3_256_digest, 29676c1c09b3SPascal van Leeuwen .setkey = safexcel_hmac_sha3_setkey, 29686c1c09b3SPascal van Leeuwen .export = safexcel_sha3_export, 29696c1c09b3SPascal van Leeuwen .import = safexcel_sha3_import, 29706c1c09b3SPascal van Leeuwen .halg = { 29716c1c09b3SPascal van Leeuwen .digestsize = SHA3_256_DIGEST_SIZE, 29726c1c09b3SPascal van Leeuwen .statesize = sizeof(struct safexcel_ahash_export_state), 29736c1c09b3SPascal van Leeuwen .base = { 29746c1c09b3SPascal van Leeuwen .cra_name = "hmac(sha3-256)", 29756c1c09b3SPascal van Leeuwen .cra_driver_name = "safexcel-hmac-sha3-256", 29766c1c09b3SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 29776c1c09b3SPascal van Leeuwen .cra_flags = CRYPTO_ALG_ASYNC | 29786c1c09b3SPascal van Leeuwen CRYPTO_ALG_KERN_DRIVER_ONLY | 29796c1c09b3SPascal van Leeuwen CRYPTO_ALG_NEED_FALLBACK, 29806c1c09b3SPascal van Leeuwen .cra_blocksize = SHA3_256_BLOCK_SIZE, 29816c1c09b3SPascal van Leeuwen .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 29826c1c09b3SPascal van Leeuwen .cra_init = safexcel_hmac_sha3_256_cra_init, 29836c1c09b3SPascal van Leeuwen .cra_exit = safexcel_hmac_sha3_cra_exit, 29846c1c09b3SPascal van Leeuwen .cra_module = THIS_MODULE, 29856c1c09b3SPascal van Leeuwen }, 29866c1c09b3SPascal van Leeuwen }, 29876c1c09b3SPascal van Leeuwen }, 29886c1c09b3SPascal van Leeuwen }; 29896c1c09b3SPascal van Leeuwen 29906c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_384_init(struct ahash_request *areq) 29916c1c09b3SPascal van Leeuwen { 29926c1c09b3SPascal van Leeuwen struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 29936c1c09b3SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 29946c1c09b3SPascal van Leeuwen struct safexcel_ahash_req *req = ahash_request_ctx(areq); 29956c1c09b3SPascal van Leeuwen 29966c1c09b3SPascal van Leeuwen memset(req, 0, sizeof(*req)); 29976c1c09b3SPascal van Leeuwen 29986c1c09b3SPascal van Leeuwen /* Copy (half of) the key */ 29996c1c09b3SPascal van Leeuwen memcpy(req->state, ctx->ipad, SHA3_384_BLOCK_SIZE / 2); 30006c1c09b3SPascal van Leeuwen /* Start of HMAC should have len == processed == blocksize */ 30016c1c09b3SPascal van Leeuwen req->len = SHA3_384_BLOCK_SIZE; 30026c1c09b3SPascal van Leeuwen req->processed = SHA3_384_BLOCK_SIZE; 30036c1c09b3SPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_384; 30046c1c09b3SPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_HMAC; 30056c1c09b3SPascal van Leeuwen req->state_sz = SHA3_384_BLOCK_SIZE / 2; 30066c1c09b3SPascal van Leeuwen req->digest_sz = SHA3_384_DIGEST_SIZE; 30076c1c09b3SPascal van Leeuwen req->block_sz = SHA3_384_BLOCK_SIZE; 30086c1c09b3SPascal van Leeuwen req->hmac = true; 30096c1c09b3SPascal van Leeuwen ctx->do_fallback = false; 30106c1c09b3SPascal van Leeuwen ctx->fb_init_done = false; 30116c1c09b3SPascal van Leeuwen return 0; 30126c1c09b3SPascal van Leeuwen } 30136c1c09b3SPascal van Leeuwen 30146c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_384_digest(struct ahash_request *req) 30156c1c09b3SPascal van Leeuwen { 30166c1c09b3SPascal van Leeuwen if (req->nbytes) 30176c1c09b3SPascal van Leeuwen return safexcel_hmac_sha3_384_init(req) ?: 30186c1c09b3SPascal van Leeuwen safexcel_ahash_finup(req); 30196c1c09b3SPascal van Leeuwen 30206c1c09b3SPascal van Leeuwen /* HW cannot do zero length HMAC, use fallback instead */ 30216c1c09b3SPascal van Leeuwen return safexcel_sha3_digest_fallback(req); 30226c1c09b3SPascal van Leeuwen } 30236c1c09b3SPascal van Leeuwen 30246c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_384_cra_init(struct crypto_tfm *tfm) 30256c1c09b3SPascal van Leeuwen { 30266c1c09b3SPascal van Leeuwen return safexcel_hmac_sha3_cra_init(tfm, "sha3-384"); 30276c1c09b3SPascal van Leeuwen } 30286c1c09b3SPascal van Leeuwen 30296c1c09b3SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_hmac_sha3_384 = { 30306c1c09b3SPascal van Leeuwen .type = SAFEXCEL_ALG_TYPE_AHASH, 30316c1c09b3SPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA3, 30326c1c09b3SPascal van Leeuwen .alg.ahash = { 30336c1c09b3SPascal van Leeuwen .init = safexcel_hmac_sha3_384_init, 30346c1c09b3SPascal van Leeuwen .update = safexcel_sha3_update, 30356c1c09b3SPascal van Leeuwen .final = safexcel_sha3_final, 30366c1c09b3SPascal van Leeuwen .finup = safexcel_sha3_finup, 30376c1c09b3SPascal van Leeuwen .digest = safexcel_hmac_sha3_384_digest, 30386c1c09b3SPascal van Leeuwen .setkey = safexcel_hmac_sha3_setkey, 30396c1c09b3SPascal van Leeuwen .export = safexcel_sha3_export, 30406c1c09b3SPascal van Leeuwen .import = safexcel_sha3_import, 30416c1c09b3SPascal van Leeuwen .halg = { 30426c1c09b3SPascal van Leeuwen .digestsize = SHA3_384_DIGEST_SIZE, 30436c1c09b3SPascal van Leeuwen .statesize = sizeof(struct safexcel_ahash_export_state), 30446c1c09b3SPascal van Leeuwen .base = { 30456c1c09b3SPascal van Leeuwen .cra_name = "hmac(sha3-384)", 30466c1c09b3SPascal van Leeuwen .cra_driver_name = "safexcel-hmac-sha3-384", 30476c1c09b3SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 30486c1c09b3SPascal van Leeuwen .cra_flags = CRYPTO_ALG_ASYNC | 30496c1c09b3SPascal van Leeuwen CRYPTO_ALG_KERN_DRIVER_ONLY | 30506c1c09b3SPascal van Leeuwen CRYPTO_ALG_NEED_FALLBACK, 30516c1c09b3SPascal van Leeuwen .cra_blocksize = SHA3_384_BLOCK_SIZE, 30526c1c09b3SPascal van Leeuwen .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 30536c1c09b3SPascal van Leeuwen .cra_init = safexcel_hmac_sha3_384_cra_init, 30546c1c09b3SPascal van Leeuwen .cra_exit = safexcel_hmac_sha3_cra_exit, 30556c1c09b3SPascal van Leeuwen .cra_module = THIS_MODULE, 30566c1c09b3SPascal van Leeuwen }, 30576c1c09b3SPascal van Leeuwen }, 30586c1c09b3SPascal van Leeuwen }, 30596c1c09b3SPascal van Leeuwen }; 30606c1c09b3SPascal van Leeuwen 30616c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_512_init(struct ahash_request *areq) 30626c1c09b3SPascal van Leeuwen { 30636c1c09b3SPascal van Leeuwen struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 30646c1c09b3SPascal van Leeuwen struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 30656c1c09b3SPascal van Leeuwen struct safexcel_ahash_req *req = ahash_request_ctx(areq); 30666c1c09b3SPascal van Leeuwen 30676c1c09b3SPascal van Leeuwen memset(req, 0, sizeof(*req)); 30686c1c09b3SPascal van Leeuwen 30696c1c09b3SPascal van Leeuwen /* Copy (half of) the key */ 30706c1c09b3SPascal van Leeuwen memcpy(req->state, ctx->ipad, SHA3_512_BLOCK_SIZE / 2); 30716c1c09b3SPascal van Leeuwen /* Start of HMAC should have len == processed == blocksize */ 30726c1c09b3SPascal van Leeuwen req->len = SHA3_512_BLOCK_SIZE; 30736c1c09b3SPascal van Leeuwen req->processed = SHA3_512_BLOCK_SIZE; 30746c1c09b3SPascal van Leeuwen ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_512; 30756c1c09b3SPascal van Leeuwen req->digest = CONTEXT_CONTROL_DIGEST_HMAC; 30766c1c09b3SPascal van Leeuwen req->state_sz = SHA3_512_BLOCK_SIZE / 2; 30776c1c09b3SPascal van Leeuwen req->digest_sz = SHA3_512_DIGEST_SIZE; 30786c1c09b3SPascal van Leeuwen req->block_sz = SHA3_512_BLOCK_SIZE; 30796c1c09b3SPascal van Leeuwen req->hmac = true; 30806c1c09b3SPascal van Leeuwen ctx->do_fallback = false; 30816c1c09b3SPascal van Leeuwen ctx->fb_init_done = false; 30826c1c09b3SPascal van Leeuwen return 0; 30836c1c09b3SPascal van Leeuwen } 30846c1c09b3SPascal van Leeuwen 30856c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_512_digest(struct ahash_request *req) 30866c1c09b3SPascal van Leeuwen { 30876c1c09b3SPascal van Leeuwen if (req->nbytes) 30886c1c09b3SPascal van Leeuwen return safexcel_hmac_sha3_512_init(req) ?: 30896c1c09b3SPascal van Leeuwen safexcel_ahash_finup(req); 30906c1c09b3SPascal van Leeuwen 30916c1c09b3SPascal van Leeuwen /* HW cannot do zero length HMAC, use fallback instead */ 30926c1c09b3SPascal van Leeuwen return safexcel_sha3_digest_fallback(req); 30936c1c09b3SPascal van Leeuwen } 30946c1c09b3SPascal van Leeuwen 30956c1c09b3SPascal van Leeuwen static int safexcel_hmac_sha3_512_cra_init(struct crypto_tfm *tfm) 30966c1c09b3SPascal van Leeuwen { 30976c1c09b3SPascal van Leeuwen return safexcel_hmac_sha3_cra_init(tfm, "sha3-512"); 30986c1c09b3SPascal van Leeuwen } 30996c1c09b3SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_hmac_sha3_512 = { 31006c1c09b3SPascal van Leeuwen .type = SAFEXCEL_ALG_TYPE_AHASH, 31016c1c09b3SPascal van Leeuwen .algo_mask = SAFEXCEL_ALG_SHA3, 31026c1c09b3SPascal van Leeuwen .alg.ahash = { 31036c1c09b3SPascal van Leeuwen .init = safexcel_hmac_sha3_512_init, 31046c1c09b3SPascal van Leeuwen .update = safexcel_sha3_update, 31056c1c09b3SPascal van Leeuwen .final = safexcel_sha3_final, 31066c1c09b3SPascal van Leeuwen .finup = safexcel_sha3_finup, 31076c1c09b3SPascal van Leeuwen .digest = safexcel_hmac_sha3_512_digest, 31086c1c09b3SPascal van Leeuwen .setkey = safexcel_hmac_sha3_setkey, 31096c1c09b3SPascal van Leeuwen .export = safexcel_sha3_export, 31106c1c09b3SPascal van Leeuwen .import = safexcel_sha3_import, 31116c1c09b3SPascal van Leeuwen .halg = { 31126c1c09b3SPascal van Leeuwen .digestsize = SHA3_512_DIGEST_SIZE, 31136c1c09b3SPascal van Leeuwen .statesize = sizeof(struct safexcel_ahash_export_state), 31146c1c09b3SPascal van Leeuwen .base = { 31156c1c09b3SPascal van Leeuwen .cra_name = "hmac(sha3-512)", 31166c1c09b3SPascal van Leeuwen .cra_driver_name = "safexcel-hmac-sha3-512", 31176c1c09b3SPascal van Leeuwen .cra_priority = SAFEXCEL_CRA_PRIORITY, 31186c1c09b3SPascal van Leeuwen .cra_flags = CRYPTO_ALG_ASYNC | 31196c1c09b3SPascal van Leeuwen CRYPTO_ALG_KERN_DRIVER_ONLY | 31206c1c09b3SPascal van Leeuwen CRYPTO_ALG_NEED_FALLBACK, 31216c1c09b3SPascal van Leeuwen .cra_blocksize = SHA3_512_BLOCK_SIZE, 31226c1c09b3SPascal van Leeuwen .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), 31236c1c09b3SPascal van Leeuwen .cra_init = safexcel_hmac_sha3_512_cra_init, 31246c1c09b3SPascal van Leeuwen .cra_exit = safexcel_hmac_sha3_cra_exit, 31256c1c09b3SPascal van Leeuwen .cra_module = THIS_MODULE, 31266c1c09b3SPascal van Leeuwen }, 31276c1c09b3SPascal van Leeuwen }, 31286c1c09b3SPascal van Leeuwen }, 31296c1c09b3SPascal van Leeuwen }; 3130