11b44c5a6SAntoine Ténart /* 21b44c5a6SAntoine Ténart * Copyright (C) 2017 Marvell 31b44c5a6SAntoine Ténart * 41b44c5a6SAntoine Ténart * Antoine Tenart <antoine.tenart@free-electrons.com> 51b44c5a6SAntoine Ténart * 61b44c5a6SAntoine Ténart * This file is licensed under the terms of the GNU General Public 71b44c5a6SAntoine Ténart * License version 2. This program is licensed "as is" without any 81b44c5a6SAntoine Ténart * warranty of any kind, whether express or implied. 91b44c5a6SAntoine Ténart */ 101b44c5a6SAntoine Ténart 111b44c5a6SAntoine Ténart #include <linux/device.h> 121b44c5a6SAntoine Ténart #include <linux/dma-mapping.h> 131b44c5a6SAntoine Ténart #include <linux/dmapool.h> 141b44c5a6SAntoine Ténart 15f6beaea3SAntoine Tenart #include <crypto/aead.h> 161b44c5a6SAntoine Ténart #include <crypto/aes.h> 17f6beaea3SAntoine Tenart #include <crypto/authenc.h> 18f6beaea3SAntoine Tenart #include <crypto/sha.h> 191b44c5a6SAntoine Ténart #include <crypto/skcipher.h> 20f6beaea3SAntoine Tenart #include <crypto/internal/aead.h> 211eb7b403SOfer Heifetz #include <crypto/internal/skcipher.h> 221b44c5a6SAntoine Ténart 231b44c5a6SAntoine Ténart #include "safexcel.h" 241b44c5a6SAntoine Ténart 251b44c5a6SAntoine Ténart enum safexcel_cipher_direction { 261b44c5a6SAntoine Ténart SAFEXCEL_ENCRYPT, 271b44c5a6SAntoine Ténart SAFEXCEL_DECRYPT, 281b44c5a6SAntoine Ténart }; 291b44c5a6SAntoine Ténart 301b44c5a6SAntoine Ténart struct safexcel_cipher_ctx { 311b44c5a6SAntoine Ténart struct safexcel_context base; 321b44c5a6SAntoine Ténart struct safexcel_crypto_priv *priv; 331b44c5a6SAntoine Ténart 341b44c5a6SAntoine Ténart u32 mode; 35f6beaea3SAntoine Tenart bool aead; 361b44c5a6SAntoine Ténart 371b44c5a6SAntoine Ténart __le32 key[8]; 381b44c5a6SAntoine Ténart unsigned int key_len; 39f6beaea3SAntoine Tenart 40f6beaea3SAntoine Tenart /* All the below is AEAD specific */ 41f6beaea3SAntoine Tenart u32 alg; 42f6beaea3SAntoine Tenart u32 state_sz; 43f6beaea3SAntoine Tenart u32 ipad[SHA256_DIGEST_SIZE / sizeof(u32)]; 44f6beaea3SAntoine Tenart u32 opad[SHA256_DIGEST_SIZE / sizeof(u32)]; 451b44c5a6SAntoine Ténart }; 461b44c5a6SAntoine Ténart 471eb7b403SOfer Heifetz struct safexcel_cipher_req { 48847ccfc5SOfer Heifetz enum safexcel_cipher_direction direction; 491eb7b403SOfer Heifetz bool needs_inv; 501eb7b403SOfer Heifetz }; 511eb7b403SOfer Heifetz 528ac1283eSAntoine Tenart static void safexcel_skcipher_token(struct safexcel_cipher_ctx *ctx, u8 *iv, 531b44c5a6SAntoine Ténart struct safexcel_command_desc *cdesc, 541b44c5a6SAntoine Ténart u32 length) 551b44c5a6SAntoine Ténart { 561b44c5a6SAntoine Ténart struct safexcel_token *token; 571b44c5a6SAntoine Ténart unsigned offset = 0; 581b44c5a6SAntoine Ténart 591b44c5a6SAntoine Ténart if (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CBC) { 601b44c5a6SAntoine Ténart offset = AES_BLOCK_SIZE / sizeof(u32); 618ac1283eSAntoine Tenart memcpy(cdesc->control_data.token, iv, AES_BLOCK_SIZE); 621b44c5a6SAntoine Ténart 631b44c5a6SAntoine Ténart cdesc->control_data.options |= EIP197_OPTION_4_TOKEN_IV_CMD; 641b44c5a6SAntoine Ténart } 651b44c5a6SAntoine Ténart 661b44c5a6SAntoine Ténart token = (struct safexcel_token *)(cdesc->control_data.token + offset); 671b44c5a6SAntoine Ténart 681b44c5a6SAntoine Ténart token[0].opcode = EIP197_TOKEN_OPCODE_DIRECTION; 691b44c5a6SAntoine Ténart token[0].packet_length = length; 7015f64ee0SAntoine Tenart token[0].stat = EIP197_TOKEN_STAT_LAST_PACKET | 7115f64ee0SAntoine Tenart EIP197_TOKEN_STAT_LAST_HASH; 721b44c5a6SAntoine Ténart token[0].instructions = EIP197_TOKEN_INS_LAST | 731b44c5a6SAntoine Ténart EIP197_TOKEN_INS_TYPE_CRYTO | 741b44c5a6SAntoine Ténart EIP197_TOKEN_INS_TYPE_OUTPUT; 751b44c5a6SAntoine Ténart } 761b44c5a6SAntoine Ténart 77f6beaea3SAntoine Tenart static void safexcel_aead_token(struct safexcel_cipher_ctx *ctx, u8 *iv, 78f6beaea3SAntoine Tenart struct safexcel_command_desc *cdesc, 79f6beaea3SAntoine Tenart enum safexcel_cipher_direction direction, 80f6beaea3SAntoine Tenart u32 cryptlen, u32 assoclen, u32 digestsize) 81f6beaea3SAntoine Tenart { 82f6beaea3SAntoine Tenart struct safexcel_token *token; 83f6beaea3SAntoine Tenart unsigned offset = 0; 84f6beaea3SAntoine Tenart 85f6beaea3SAntoine Tenart if (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CBC) { 86f6beaea3SAntoine Tenart offset = AES_BLOCK_SIZE / sizeof(u32); 87f6beaea3SAntoine Tenart memcpy(cdesc->control_data.token, iv, AES_BLOCK_SIZE); 88f6beaea3SAntoine Tenart 89f6beaea3SAntoine Tenart cdesc->control_data.options |= EIP197_OPTION_4_TOKEN_IV_CMD; 90f6beaea3SAntoine Tenart } 91f6beaea3SAntoine Tenart 92f6beaea3SAntoine Tenart token = (struct safexcel_token *)(cdesc->control_data.token + offset); 93f6beaea3SAntoine Tenart 94f6beaea3SAntoine Tenart if (direction == SAFEXCEL_DECRYPT) 95f6beaea3SAntoine Tenart cryptlen -= digestsize; 96f6beaea3SAntoine Tenart 97f6beaea3SAntoine Tenart token[0].opcode = EIP197_TOKEN_OPCODE_DIRECTION; 98f6beaea3SAntoine Tenart token[0].packet_length = assoclen; 99f6beaea3SAntoine Tenart token[0].instructions = EIP197_TOKEN_INS_TYPE_HASH | 100f6beaea3SAntoine Tenart EIP197_TOKEN_INS_TYPE_OUTPUT; 101f6beaea3SAntoine Tenart 102f6beaea3SAntoine Tenart token[1].opcode = EIP197_TOKEN_OPCODE_DIRECTION; 103f6beaea3SAntoine Tenart token[1].packet_length = cryptlen; 104f6beaea3SAntoine Tenart token[1].stat = EIP197_TOKEN_STAT_LAST_HASH; 105f6beaea3SAntoine Tenart token[1].instructions = EIP197_TOKEN_INS_LAST | 106f6beaea3SAntoine Tenart EIP197_TOKEN_INS_TYPE_CRYTO | 107f6beaea3SAntoine Tenart EIP197_TOKEN_INS_TYPE_HASH | 108f6beaea3SAntoine Tenart EIP197_TOKEN_INS_TYPE_OUTPUT; 109f6beaea3SAntoine Tenart 110f6beaea3SAntoine Tenart if (direction == SAFEXCEL_ENCRYPT) { 111f6beaea3SAntoine Tenart token[2].opcode = EIP197_TOKEN_OPCODE_INSERT; 112f6beaea3SAntoine Tenart token[2].packet_length = digestsize; 113f6beaea3SAntoine Tenart token[2].stat = EIP197_TOKEN_STAT_LAST_HASH | 114f6beaea3SAntoine Tenart EIP197_TOKEN_STAT_LAST_PACKET; 115f6beaea3SAntoine Tenart token[2].instructions = EIP197_TOKEN_INS_TYPE_OUTPUT | 116f6beaea3SAntoine Tenart EIP197_TOKEN_INS_INSERT_HASH_DIGEST; 117f6beaea3SAntoine Tenart } else { 118f6beaea3SAntoine Tenart token[2].opcode = EIP197_TOKEN_OPCODE_RETRIEVE; 119f6beaea3SAntoine Tenart token[2].packet_length = digestsize; 120f6beaea3SAntoine Tenart token[2].stat = EIP197_TOKEN_STAT_LAST_HASH | 121f6beaea3SAntoine Tenart EIP197_TOKEN_STAT_LAST_PACKET; 122f6beaea3SAntoine Tenart token[2].instructions = EIP197_TOKEN_INS_INSERT_HASH_DIGEST; 123f6beaea3SAntoine Tenart 124f6beaea3SAntoine Tenart token[3].opcode = EIP197_TOKEN_OPCODE_VERIFY; 125f6beaea3SAntoine Tenart token[3].packet_length = digestsize | 126f6beaea3SAntoine Tenart EIP197_TOKEN_HASH_RESULT_VERIFY; 127f6beaea3SAntoine Tenart token[3].stat = EIP197_TOKEN_STAT_LAST_HASH | 128f6beaea3SAntoine Tenart EIP197_TOKEN_STAT_LAST_PACKET; 129f6beaea3SAntoine Tenart token[3].instructions = EIP197_TOKEN_INS_TYPE_OUTPUT; 130f6beaea3SAntoine Tenart } 131f6beaea3SAntoine Tenart } 132f6beaea3SAntoine Tenart 1338ac1283eSAntoine Tenart static int safexcel_skcipher_aes_setkey(struct crypto_skcipher *ctfm, 1348ac1283eSAntoine Tenart const u8 *key, unsigned int len) 1351b44c5a6SAntoine Ténart { 1361b44c5a6SAntoine Ténart struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm); 1371b44c5a6SAntoine Ténart struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); 138871df319SAntoine Ténart struct safexcel_crypto_priv *priv = ctx->priv; 1391b44c5a6SAntoine Ténart struct crypto_aes_ctx aes; 1401b44c5a6SAntoine Ténart int ret, i; 1411b44c5a6SAntoine Ténart 1421b44c5a6SAntoine Ténart ret = crypto_aes_expand_key(&aes, key, len); 1431b44c5a6SAntoine Ténart if (ret) { 1441b44c5a6SAntoine Ténart crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN); 1451b44c5a6SAntoine Ténart return ret; 1461b44c5a6SAntoine Ténart } 1471b44c5a6SAntoine Ténart 148871df319SAntoine Ténart if (priv->version == EIP197 && ctx->base.ctxr_dma) { 1491b44c5a6SAntoine Ténart for (i = 0; i < len / sizeof(u32); i++) { 1501b44c5a6SAntoine Ténart if (ctx->key[i] != cpu_to_le32(aes.key_enc[i])) { 1511b44c5a6SAntoine Ténart ctx->base.needs_inv = true; 1521b44c5a6SAntoine Ténart break; 1531b44c5a6SAntoine Ténart } 1541b44c5a6SAntoine Ténart } 155c4daf4ccSOfer Heifetz } 1561b44c5a6SAntoine Ténart 1571b44c5a6SAntoine Ténart for (i = 0; i < len / sizeof(u32); i++) 1581b44c5a6SAntoine Ténart ctx->key[i] = cpu_to_le32(aes.key_enc[i]); 1591b44c5a6SAntoine Ténart 1601b44c5a6SAntoine Ténart ctx->key_len = len; 1611b44c5a6SAntoine Ténart 1621b44c5a6SAntoine Ténart memzero_explicit(&aes, sizeof(aes)); 1631b44c5a6SAntoine Ténart return 0; 1641b44c5a6SAntoine Ténart } 1651b44c5a6SAntoine Ténart 166f6beaea3SAntoine Tenart static int safexcel_aead_aes_setkey(struct crypto_aead *ctfm, const u8 *key, 167f6beaea3SAntoine Tenart unsigned int len) 168f6beaea3SAntoine Tenart { 169f6beaea3SAntoine Tenart struct crypto_tfm *tfm = crypto_aead_tfm(ctfm); 170f6beaea3SAntoine Tenart struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); 171f6beaea3SAntoine Tenart struct safexcel_ahash_export_state istate, ostate; 172f6beaea3SAntoine Tenart struct safexcel_crypto_priv *priv = ctx->priv; 173f6beaea3SAntoine Tenart struct crypto_authenc_keys keys; 174f6beaea3SAntoine Tenart 175f6beaea3SAntoine Tenart if (crypto_authenc_extractkeys(&keys, key, len) != 0) 176f6beaea3SAntoine Tenart goto badkey; 177f6beaea3SAntoine Tenart 178f6beaea3SAntoine Tenart if (keys.enckeylen > sizeof(ctx->key)) 179f6beaea3SAntoine Tenart goto badkey; 180f6beaea3SAntoine Tenart 181f6beaea3SAntoine Tenart /* Encryption key */ 182f6beaea3SAntoine Tenart if (priv->version == EIP197 && ctx->base.ctxr_dma && 183f6beaea3SAntoine Tenart memcmp(ctx->key, keys.enckey, keys.enckeylen)) 184f6beaea3SAntoine Tenart ctx->base.needs_inv = true; 185f6beaea3SAntoine Tenart 186f6beaea3SAntoine Tenart /* Auth key */ 187f6beaea3SAntoine Tenart if (safexcel_hmac_setkey("safexcel-sha256", keys.authkey, 188f6beaea3SAntoine Tenart keys.authkeylen, &istate, &ostate)) 189f6beaea3SAntoine Tenart goto badkey; 190f6beaea3SAntoine Tenart 191f6beaea3SAntoine Tenart crypto_aead_set_flags(ctfm, crypto_aead_get_flags(ctfm) & 192f6beaea3SAntoine Tenart CRYPTO_TFM_RES_MASK); 193f6beaea3SAntoine Tenart 194f6beaea3SAntoine Tenart if (priv->version == EIP197 && ctx->base.ctxr_dma && 195f6beaea3SAntoine Tenart (memcmp(ctx->ipad, istate.state, ctx->state_sz) || 196f6beaea3SAntoine Tenart memcmp(ctx->opad, ostate.state, ctx->state_sz))) 197f6beaea3SAntoine Tenart ctx->base.needs_inv = true; 198f6beaea3SAntoine Tenart 199f6beaea3SAntoine Tenart /* Now copy the keys into the context */ 200f6beaea3SAntoine Tenart memcpy(ctx->key, keys.enckey, keys.enckeylen); 201f6beaea3SAntoine Tenart ctx->key_len = keys.enckeylen; 202f6beaea3SAntoine Tenart 203f6beaea3SAntoine Tenart memcpy(ctx->ipad, &istate.state, ctx->state_sz); 204f6beaea3SAntoine Tenart memcpy(ctx->opad, &ostate.state, ctx->state_sz); 205f6beaea3SAntoine Tenart 206f6beaea3SAntoine Tenart memzero_explicit(&keys, sizeof(keys)); 207f6beaea3SAntoine Tenart return 0; 208f6beaea3SAntoine Tenart 209f6beaea3SAntoine Tenart badkey: 210f6beaea3SAntoine Tenart crypto_aead_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN); 211f6beaea3SAntoine Tenart memzero_explicit(&keys, sizeof(keys)); 212f6beaea3SAntoine Tenart return -EINVAL; 213f6beaea3SAntoine Tenart } 214f6beaea3SAntoine Tenart 2151b44c5a6SAntoine Ténart static int safexcel_context_control(struct safexcel_cipher_ctx *ctx, 216847ccfc5SOfer Heifetz struct crypto_async_request *async, 2178ac1283eSAntoine Tenart struct safexcel_cipher_req *sreq, 2181b44c5a6SAntoine Ténart struct safexcel_command_desc *cdesc) 2191b44c5a6SAntoine Ténart { 2201b44c5a6SAntoine Ténart struct safexcel_crypto_priv *priv = ctx->priv; 2211b44c5a6SAntoine Ténart int ctrl_size; 2221b44c5a6SAntoine Ténart 223f6beaea3SAntoine Tenart if (ctx->aead) { 224f6beaea3SAntoine Tenart if (sreq->direction == SAFEXCEL_ENCRYPT) 225f6beaea3SAntoine Tenart cdesc->control_data.control0 |= CONTEXT_CONTROL_TYPE_ENCRYPT_HASH_OUT; 226f6beaea3SAntoine Tenart else 227f6beaea3SAntoine Tenart cdesc->control_data.control0 |= CONTEXT_CONTROL_TYPE_HASH_DECRYPT_IN; 228f6beaea3SAntoine Tenart } else { 2291b44c5a6SAntoine Ténart cdesc->control_data.control0 |= CONTEXT_CONTROL_TYPE_CRYPTO_OUT; 2303a5ca230SAntoine Tenart 231f6beaea3SAntoine Tenart /* The decryption control type is a combination of the 232f6beaea3SAntoine Tenart * encryption type and CONTEXT_CONTROL_TYPE_NULL_IN, for all 233f6beaea3SAntoine Tenart * types. 2343a5ca230SAntoine Tenart */ 2353a5ca230SAntoine Tenart if (sreq->direction == SAFEXCEL_DECRYPT) 2363a5ca230SAntoine Tenart cdesc->control_data.control0 |= CONTEXT_CONTROL_TYPE_NULL_IN; 237f6beaea3SAntoine Tenart } 2381b44c5a6SAntoine Ténart 2391b44c5a6SAntoine Ténart cdesc->control_data.control0 |= CONTEXT_CONTROL_KEY_EN; 2401b44c5a6SAntoine Ténart cdesc->control_data.control1 |= ctx->mode; 2411b44c5a6SAntoine Ténart 242f6beaea3SAntoine Tenart if (ctx->aead) 243f6beaea3SAntoine Tenart cdesc->control_data.control0 |= CONTEXT_CONTROL_DIGEST_HMAC | 244f6beaea3SAntoine Tenart ctx->alg; 245f6beaea3SAntoine Tenart 2461b44c5a6SAntoine Ténart switch (ctx->key_len) { 2471b44c5a6SAntoine Ténart case AES_KEYSIZE_128: 2481b44c5a6SAntoine Ténart cdesc->control_data.control0 |= CONTEXT_CONTROL_CRYPTO_ALG_AES128; 2491b44c5a6SAntoine Ténart break; 2501b44c5a6SAntoine Ténart case AES_KEYSIZE_192: 2511b44c5a6SAntoine Ténart cdesc->control_data.control0 |= CONTEXT_CONTROL_CRYPTO_ALG_AES192; 2521b44c5a6SAntoine Ténart break; 2531b44c5a6SAntoine Ténart case AES_KEYSIZE_256: 2541b44c5a6SAntoine Ténart cdesc->control_data.control0 |= CONTEXT_CONTROL_CRYPTO_ALG_AES256; 2551b44c5a6SAntoine Ténart break; 2561b44c5a6SAntoine Ténart default: 2571b44c5a6SAntoine Ténart dev_err(priv->dev, "aes keysize not supported: %u\n", 2581b44c5a6SAntoine Ténart ctx->key_len); 2591b44c5a6SAntoine Ténart return -EINVAL; 2601b44c5a6SAntoine Ténart } 261fef0cfe5SAntoine Tenart 262fef0cfe5SAntoine Tenart ctrl_size = ctx->key_len / sizeof(u32); 263f6beaea3SAntoine Tenart if (ctx->aead) 264f6beaea3SAntoine Tenart /* Take in account the ipad+opad digests */ 265f6beaea3SAntoine Tenart ctrl_size += ctx->state_sz / sizeof(u32) * 2; 2661b44c5a6SAntoine Ténart cdesc->control_data.control0 |= CONTEXT_CONTROL_SIZE(ctrl_size); 2671b44c5a6SAntoine Ténart 2681b44c5a6SAntoine Ténart return 0; 2691b44c5a6SAntoine Ténart } 2701b44c5a6SAntoine Ténart 2711eb7b403SOfer Heifetz static int safexcel_handle_req_result(struct safexcel_crypto_priv *priv, int ring, 2721b44c5a6SAntoine Ténart struct crypto_async_request *async, 2738ac1283eSAntoine Tenart struct scatterlist *src, 2748ac1283eSAntoine Tenart struct scatterlist *dst, 2758ac1283eSAntoine Tenart unsigned int cryptlen, 2768ac1283eSAntoine Tenart struct safexcel_cipher_req *sreq, 2771b44c5a6SAntoine Ténart bool *should_complete, int *ret) 2781b44c5a6SAntoine Ténart { 2791b44c5a6SAntoine Ténart struct safexcel_result_desc *rdesc; 2801b44c5a6SAntoine Ténart int ndesc = 0; 2811b44c5a6SAntoine Ténart 2821b44c5a6SAntoine Ténart *ret = 0; 2831b44c5a6SAntoine Ténart 2841b44c5a6SAntoine Ténart spin_lock_bh(&priv->ring[ring].egress_lock); 2851b44c5a6SAntoine Ténart do { 2861b44c5a6SAntoine Ténart rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr); 2871b44c5a6SAntoine Ténart if (IS_ERR(rdesc)) { 2881b44c5a6SAntoine Ténart dev_err(priv->dev, 2891b44c5a6SAntoine Ténart "cipher: result: could not retrieve the result descriptor\n"); 2901b44c5a6SAntoine Ténart *ret = PTR_ERR(rdesc); 2911b44c5a6SAntoine Ténart break; 2921b44c5a6SAntoine Ténart } 2931b44c5a6SAntoine Ténart 294bdfd1909SAntoine Tenart if (likely(!*ret)) 295bdfd1909SAntoine Tenart *ret = safexcel_rdesc_check_errors(priv, rdesc); 2961b44c5a6SAntoine Ténart 2971b44c5a6SAntoine Ténart ndesc++; 2981b44c5a6SAntoine Ténart } while (!rdesc->last_seg); 2991b44c5a6SAntoine Ténart 3001b44c5a6SAntoine Ténart safexcel_complete(priv, ring); 3011b44c5a6SAntoine Ténart spin_unlock_bh(&priv->ring[ring].egress_lock); 3021b44c5a6SAntoine Ténart 3038ac1283eSAntoine Tenart if (src == dst) { 3048ac1283eSAntoine Tenart dma_unmap_sg(priv->dev, src, 3058ac1283eSAntoine Tenart sg_nents_for_len(src, cryptlen), 3061b44c5a6SAntoine Ténart DMA_BIDIRECTIONAL); 3071b44c5a6SAntoine Ténart } else { 3088ac1283eSAntoine Tenart dma_unmap_sg(priv->dev, src, 3098ac1283eSAntoine Tenart sg_nents_for_len(src, cryptlen), 3101b44c5a6SAntoine Ténart DMA_TO_DEVICE); 3118ac1283eSAntoine Tenart dma_unmap_sg(priv->dev, dst, 3128ac1283eSAntoine Tenart sg_nents_for_len(dst, cryptlen), 3131b44c5a6SAntoine Ténart DMA_FROM_DEVICE); 3141b44c5a6SAntoine Ténart } 3151b44c5a6SAntoine Ténart 3161b44c5a6SAntoine Ténart *should_complete = true; 3171b44c5a6SAntoine Ténart 3181b44c5a6SAntoine Ténart return ndesc; 3191b44c5a6SAntoine Ténart } 3201b44c5a6SAntoine Ténart 3218ac1283eSAntoine Tenart static int safexcel_aes_send(struct crypto_async_request *base, int ring, 3228ac1283eSAntoine Tenart struct safexcel_request *request, 3238ac1283eSAntoine Tenart struct safexcel_cipher_req *sreq, 3248ac1283eSAntoine Tenart struct scatterlist *src, struct scatterlist *dst, 325f6beaea3SAntoine Tenart unsigned int cryptlen, unsigned int assoclen, 326f6beaea3SAntoine Tenart unsigned int digestsize, u8 *iv, int *commands, 3278ac1283eSAntoine Tenart int *results) 3281b44c5a6SAntoine Ténart { 3298ac1283eSAntoine Tenart struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(base->tfm); 3301b44c5a6SAntoine Ténart struct safexcel_crypto_priv *priv = ctx->priv; 3311b44c5a6SAntoine Ténart struct safexcel_command_desc *cdesc; 3321b44c5a6SAntoine Ténart struct safexcel_result_desc *rdesc; 3331b44c5a6SAntoine Ténart struct scatterlist *sg; 334f6beaea3SAntoine Tenart unsigned int totlen = cryptlen + assoclen; 335f6beaea3SAntoine Tenart int nr_src, nr_dst, n_cdesc = 0, n_rdesc = 0, queued = totlen; 3361b44c5a6SAntoine Ténart int i, ret = 0; 3371b44c5a6SAntoine Ténart 3388ac1283eSAntoine Tenart if (src == dst) { 3398ac1283eSAntoine Tenart nr_src = dma_map_sg(priv->dev, src, 340f6beaea3SAntoine Tenart sg_nents_for_len(src, totlen), 3411b44c5a6SAntoine Ténart DMA_BIDIRECTIONAL); 3421b44c5a6SAntoine Ténart nr_dst = nr_src; 3431b44c5a6SAntoine Ténart if (!nr_src) 3441b44c5a6SAntoine Ténart return -EINVAL; 3451b44c5a6SAntoine Ténart } else { 3468ac1283eSAntoine Tenart nr_src = dma_map_sg(priv->dev, src, 347f6beaea3SAntoine Tenart sg_nents_for_len(src, totlen), 3481b44c5a6SAntoine Ténart DMA_TO_DEVICE); 3491b44c5a6SAntoine Ténart if (!nr_src) 3501b44c5a6SAntoine Ténart return -EINVAL; 3511b44c5a6SAntoine Ténart 3528ac1283eSAntoine Tenart nr_dst = dma_map_sg(priv->dev, dst, 353f6beaea3SAntoine Tenart sg_nents_for_len(dst, totlen), 3541b44c5a6SAntoine Ténart DMA_FROM_DEVICE); 3551b44c5a6SAntoine Ténart if (!nr_dst) { 3568ac1283eSAntoine Tenart dma_unmap_sg(priv->dev, src, 357f6beaea3SAntoine Tenart sg_nents_for_len(src, totlen), 3581b44c5a6SAntoine Ténart DMA_TO_DEVICE); 3591b44c5a6SAntoine Ténart return -EINVAL; 3601b44c5a6SAntoine Ténart } 3611b44c5a6SAntoine Ténart } 3621b44c5a6SAntoine Ténart 3631b44c5a6SAntoine Ténart memcpy(ctx->base.ctxr->data, ctx->key, ctx->key_len); 3641b44c5a6SAntoine Ténart 365f6beaea3SAntoine Tenart if (ctx->aead) { 366f6beaea3SAntoine Tenart memcpy(ctx->base.ctxr->data + ctx->key_len / sizeof(u32), 367f6beaea3SAntoine Tenart ctx->ipad, ctx->state_sz); 368f6beaea3SAntoine Tenart memcpy(ctx->base.ctxr->data + (ctx->key_len + ctx->state_sz) / sizeof(u32), 369f6beaea3SAntoine Tenart ctx->opad, ctx->state_sz); 370f6beaea3SAntoine Tenart } 371f6beaea3SAntoine Tenart 3721b44c5a6SAntoine Ténart spin_lock_bh(&priv->ring[ring].egress_lock); 3731b44c5a6SAntoine Ténart 3741b44c5a6SAntoine Ténart /* command descriptors */ 3758ac1283eSAntoine Tenart for_each_sg(src, sg, nr_src, i) { 3761b44c5a6SAntoine Ténart int len = sg_dma_len(sg); 3771b44c5a6SAntoine Ténart 3781b44c5a6SAntoine Ténart /* Do not overflow the request */ 3791b44c5a6SAntoine Ténart if (queued - len < 0) 3801b44c5a6SAntoine Ténart len = queued; 3811b44c5a6SAntoine Ténart 3821b44c5a6SAntoine Ténart cdesc = safexcel_add_cdesc(priv, ring, !n_cdesc, !(queued - len), 383f6beaea3SAntoine Tenart sg_dma_address(sg), len, totlen, 3841b44c5a6SAntoine Ténart ctx->base.ctxr_dma); 3851b44c5a6SAntoine Ténart if (IS_ERR(cdesc)) { 3861b44c5a6SAntoine Ténart /* No space left in the command descriptor ring */ 3871b44c5a6SAntoine Ténart ret = PTR_ERR(cdesc); 3881b44c5a6SAntoine Ténart goto cdesc_rollback; 3891b44c5a6SAntoine Ténart } 3901b44c5a6SAntoine Ténart n_cdesc++; 3911b44c5a6SAntoine Ténart 3921b44c5a6SAntoine Ténart if (n_cdesc == 1) { 3938ac1283eSAntoine Tenart safexcel_context_control(ctx, base, sreq, cdesc); 394f6beaea3SAntoine Tenart if (ctx->aead) 395f6beaea3SAntoine Tenart safexcel_aead_token(ctx, iv, cdesc, 396f6beaea3SAntoine Tenart sreq->direction, cryptlen, 397f6beaea3SAntoine Tenart assoclen, digestsize); 398f6beaea3SAntoine Tenart else 399f6beaea3SAntoine Tenart safexcel_skcipher_token(ctx, iv, cdesc, 400f6beaea3SAntoine Tenart cryptlen); 4011b44c5a6SAntoine Ténart } 4021b44c5a6SAntoine Ténart 4031b44c5a6SAntoine Ténart queued -= len; 4041b44c5a6SAntoine Ténart if (!queued) 4051b44c5a6SAntoine Ténart break; 4061b44c5a6SAntoine Ténart } 4071b44c5a6SAntoine Ténart 4081b44c5a6SAntoine Ténart /* result descriptors */ 4098ac1283eSAntoine Tenart for_each_sg(dst, sg, nr_dst, i) { 4101b44c5a6SAntoine Ténart bool first = !i, last = (i == nr_dst - 1); 4111b44c5a6SAntoine Ténart u32 len = sg_dma_len(sg); 4121b44c5a6SAntoine Ténart 4131b44c5a6SAntoine Ténart rdesc = safexcel_add_rdesc(priv, ring, first, last, 4141b44c5a6SAntoine Ténart sg_dma_address(sg), len); 4151b44c5a6SAntoine Ténart if (IS_ERR(rdesc)) { 4161b44c5a6SAntoine Ténart /* No space left in the result descriptor ring */ 4171b44c5a6SAntoine Ténart ret = PTR_ERR(rdesc); 4181b44c5a6SAntoine Ténart goto rdesc_rollback; 4191b44c5a6SAntoine Ténart } 4201b44c5a6SAntoine Ténart n_rdesc++; 4211b44c5a6SAntoine Ténart } 4221b44c5a6SAntoine Ténart 4231b44c5a6SAntoine Ténart spin_unlock_bh(&priv->ring[ring].egress_lock); 4241b44c5a6SAntoine Ténart 4258ac1283eSAntoine Tenart request->req = base; 42697858434SAntoine Ténart 4271b44c5a6SAntoine Ténart *commands = n_cdesc; 428152bdf4cSOfer Heifetz *results = n_rdesc; 4291b44c5a6SAntoine Ténart return 0; 4301b44c5a6SAntoine Ténart 4311b44c5a6SAntoine Ténart rdesc_rollback: 4321b44c5a6SAntoine Ténart for (i = 0; i < n_rdesc; i++) 4331b44c5a6SAntoine Ténart safexcel_ring_rollback_wptr(priv, &priv->ring[ring].rdr); 4341b44c5a6SAntoine Ténart cdesc_rollback: 4351b44c5a6SAntoine Ténart for (i = 0; i < n_cdesc; i++) 4361b44c5a6SAntoine Ténart safexcel_ring_rollback_wptr(priv, &priv->ring[ring].cdr); 4371b44c5a6SAntoine Ténart 4381b44c5a6SAntoine Ténart spin_unlock_bh(&priv->ring[ring].egress_lock); 4391b44c5a6SAntoine Ténart 4408ac1283eSAntoine Tenart if (src == dst) { 4418ac1283eSAntoine Tenart dma_unmap_sg(priv->dev, src, 442f6beaea3SAntoine Tenart sg_nents_for_len(src, totlen), 4431b44c5a6SAntoine Ténart DMA_BIDIRECTIONAL); 4441b44c5a6SAntoine Ténart } else { 4458ac1283eSAntoine Tenart dma_unmap_sg(priv->dev, src, 446f6beaea3SAntoine Tenart sg_nents_for_len(src, totlen), 4471b44c5a6SAntoine Ténart DMA_TO_DEVICE); 4488ac1283eSAntoine Tenart dma_unmap_sg(priv->dev, dst, 449f6beaea3SAntoine Tenart sg_nents_for_len(dst, totlen), 4501b44c5a6SAntoine Ténart DMA_FROM_DEVICE); 4511b44c5a6SAntoine Ténart } 4521b44c5a6SAntoine Ténart 4531b44c5a6SAntoine Ténart return ret; 4541b44c5a6SAntoine Ténart } 4551b44c5a6SAntoine Ténart 4561b44c5a6SAntoine Ténart static int safexcel_handle_inv_result(struct safexcel_crypto_priv *priv, 4571b44c5a6SAntoine Ténart int ring, 4588ac1283eSAntoine Tenart struct crypto_async_request *base, 4591b44c5a6SAntoine Ténart bool *should_complete, int *ret) 4601b44c5a6SAntoine Ténart { 4618ac1283eSAntoine Tenart struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(base->tfm); 4621b44c5a6SAntoine Ténart struct safexcel_result_desc *rdesc; 4631b44c5a6SAntoine Ténart int ndesc = 0, enq_ret; 4641b44c5a6SAntoine Ténart 4651b44c5a6SAntoine Ténart *ret = 0; 4661b44c5a6SAntoine Ténart 4671b44c5a6SAntoine Ténart spin_lock_bh(&priv->ring[ring].egress_lock); 4681b44c5a6SAntoine Ténart do { 4691b44c5a6SAntoine Ténart rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr); 4701b44c5a6SAntoine Ténart if (IS_ERR(rdesc)) { 4711b44c5a6SAntoine Ténart dev_err(priv->dev, 4721b44c5a6SAntoine Ténart "cipher: invalidate: could not retrieve the result descriptor\n"); 4731b44c5a6SAntoine Ténart *ret = PTR_ERR(rdesc); 4741b44c5a6SAntoine Ténart break; 4751b44c5a6SAntoine Ténart } 4761b44c5a6SAntoine Ténart 4771b44c5a6SAntoine Ténart if (rdesc->result_data.error_code) { 4781b44c5a6SAntoine Ténart dev_err(priv->dev, "cipher: invalidate: result descriptor error (%d)\n", 4791b44c5a6SAntoine Ténart rdesc->result_data.error_code); 4801b44c5a6SAntoine Ténart *ret = -EIO; 4811b44c5a6SAntoine Ténart } 4821b44c5a6SAntoine Ténart 4831b44c5a6SAntoine Ténart ndesc++; 4841b44c5a6SAntoine Ténart } while (!rdesc->last_seg); 4851b44c5a6SAntoine Ténart 4861b44c5a6SAntoine Ténart safexcel_complete(priv, ring); 4871b44c5a6SAntoine Ténart spin_unlock_bh(&priv->ring[ring].egress_lock); 4881b44c5a6SAntoine Ténart 4891b44c5a6SAntoine Ténart if (ctx->base.exit_inv) { 4901b44c5a6SAntoine Ténart dma_pool_free(priv->context_pool, ctx->base.ctxr, 4911b44c5a6SAntoine Ténart ctx->base.ctxr_dma); 4921b44c5a6SAntoine Ténart 4931b44c5a6SAntoine Ténart *should_complete = true; 4941b44c5a6SAntoine Ténart 4951b44c5a6SAntoine Ténart return ndesc; 4961b44c5a6SAntoine Ténart } 4971b44c5a6SAntoine Ténart 49886671abbSAntoine Ténart ring = safexcel_select_ring(priv); 49986671abbSAntoine Ténart ctx->base.ring = ring; 5001b44c5a6SAntoine Ténart 50186671abbSAntoine Ténart spin_lock_bh(&priv->ring[ring].queue_lock); 5028ac1283eSAntoine Tenart enq_ret = crypto_enqueue_request(&priv->ring[ring].queue, base); 50386671abbSAntoine Ténart spin_unlock_bh(&priv->ring[ring].queue_lock); 5041b44c5a6SAntoine Ténart 5051b44c5a6SAntoine Ténart if (enq_ret != -EINPROGRESS) 5061b44c5a6SAntoine Ténart *ret = enq_ret; 5071b44c5a6SAntoine Ténart 5088472e778SAntoine Ténart queue_work(priv->ring[ring].workqueue, 5098472e778SAntoine Ténart &priv->ring[ring].work_data.work); 51086671abbSAntoine Ténart 5111b44c5a6SAntoine Ténart *should_complete = false; 5121b44c5a6SAntoine Ténart 5131b44c5a6SAntoine Ténart return ndesc; 5141b44c5a6SAntoine Ténart } 5151b44c5a6SAntoine Ténart 5168ac1283eSAntoine Tenart static int safexcel_skcipher_handle_result(struct safexcel_crypto_priv *priv, 5178ac1283eSAntoine Tenart int ring, 5181eb7b403SOfer Heifetz struct crypto_async_request *async, 5191eb7b403SOfer Heifetz bool *should_complete, int *ret) 5201eb7b403SOfer Heifetz { 5211eb7b403SOfer Heifetz struct skcipher_request *req = skcipher_request_cast(async); 5221eb7b403SOfer Heifetz struct safexcel_cipher_req *sreq = skcipher_request_ctx(req); 5231eb7b403SOfer Heifetz int err; 5241eb7b403SOfer Heifetz 5251eb7b403SOfer Heifetz if (sreq->needs_inv) { 5261eb7b403SOfer Heifetz sreq->needs_inv = false; 5271eb7b403SOfer Heifetz err = safexcel_handle_inv_result(priv, ring, async, 5281eb7b403SOfer Heifetz should_complete, ret); 5291eb7b403SOfer Heifetz } else { 5308ac1283eSAntoine Tenart err = safexcel_handle_req_result(priv, ring, async, req->src, 5318ac1283eSAntoine Tenart req->dst, req->cryptlen, sreq, 5321eb7b403SOfer Heifetz should_complete, ret); 5331eb7b403SOfer Heifetz } 5341eb7b403SOfer Heifetz 5351eb7b403SOfer Heifetz return err; 5361eb7b403SOfer Heifetz } 5371eb7b403SOfer Heifetz 538f6beaea3SAntoine Tenart static int safexcel_aead_handle_result(struct safexcel_crypto_priv *priv, 539f6beaea3SAntoine Tenart int ring, 540f6beaea3SAntoine Tenart struct crypto_async_request *async, 541f6beaea3SAntoine Tenart bool *should_complete, int *ret) 542f6beaea3SAntoine Tenart { 543f6beaea3SAntoine Tenart struct aead_request *req = aead_request_cast(async); 544f6beaea3SAntoine Tenart struct crypto_aead *tfm = crypto_aead_reqtfm(req); 545f6beaea3SAntoine Tenart struct safexcel_cipher_req *sreq = aead_request_ctx(req); 546f6beaea3SAntoine Tenart int err; 547f6beaea3SAntoine Tenart 548f6beaea3SAntoine Tenart if (sreq->needs_inv) { 549f6beaea3SAntoine Tenart sreq->needs_inv = false; 550f6beaea3SAntoine Tenart err = safexcel_handle_inv_result(priv, ring, async, 551f6beaea3SAntoine Tenart should_complete, ret); 552f6beaea3SAntoine Tenart } else { 553f6beaea3SAntoine Tenart err = safexcel_handle_req_result(priv, ring, async, req->src, 554f6beaea3SAntoine Tenart req->dst, 555f6beaea3SAntoine Tenart req->cryptlen + crypto_aead_authsize(tfm), 556f6beaea3SAntoine Tenart sreq, should_complete, ret); 557f6beaea3SAntoine Tenart } 558f6beaea3SAntoine Tenart 559f6beaea3SAntoine Tenart return err; 560f6beaea3SAntoine Tenart } 561f6beaea3SAntoine Tenart 5628ac1283eSAntoine Tenart static int safexcel_cipher_send_inv(struct crypto_async_request *base, 5631b44c5a6SAntoine Ténart int ring, struct safexcel_request *request, 5641b44c5a6SAntoine Ténart int *commands, int *results) 5651b44c5a6SAntoine Ténart { 5668ac1283eSAntoine Tenart struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(base->tfm); 5671b44c5a6SAntoine Ténart struct safexcel_crypto_priv *priv = ctx->priv; 5681b44c5a6SAntoine Ténart int ret; 5691b44c5a6SAntoine Ténart 5708ac1283eSAntoine Tenart ret = safexcel_invalidate_cache(base, priv, ctx->base.ctxr_dma, ring, 5718ac1283eSAntoine Tenart request); 5721b44c5a6SAntoine Ténart if (unlikely(ret)) 5731b44c5a6SAntoine Ténart return ret; 5741b44c5a6SAntoine Ténart 5751b44c5a6SAntoine Ténart *commands = 1; 5761b44c5a6SAntoine Ténart *results = 1; 5771b44c5a6SAntoine Ténart 5781b44c5a6SAntoine Ténart return 0; 5791b44c5a6SAntoine Ténart } 5801b44c5a6SAntoine Ténart 5818ac1283eSAntoine Tenart static int safexcel_skcipher_send(struct crypto_async_request *async, int ring, 5828ac1283eSAntoine Tenart struct safexcel_request *request, 5831eb7b403SOfer Heifetz int *commands, int *results) 5841eb7b403SOfer Heifetz { 5851eb7b403SOfer Heifetz struct skcipher_request *req = skcipher_request_cast(async); 586871df319SAntoine Ténart struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(req->base.tfm); 5871eb7b403SOfer Heifetz struct safexcel_cipher_req *sreq = skcipher_request_ctx(req); 588871df319SAntoine Ténart struct safexcel_crypto_priv *priv = ctx->priv; 5891eb7b403SOfer Heifetz int ret; 5901eb7b403SOfer Heifetz 591871df319SAntoine Ténart BUG_ON(priv->version == EIP97 && sreq->needs_inv); 592871df319SAntoine Ténart 5931eb7b403SOfer Heifetz if (sreq->needs_inv) 5948ac1283eSAntoine Tenart ret = safexcel_cipher_send_inv(async, ring, request, commands, 5958ac1283eSAntoine Tenart results); 5961eb7b403SOfer Heifetz else 5978ac1283eSAntoine Tenart ret = safexcel_aes_send(async, ring, request, sreq, req->src, 598f6beaea3SAntoine Tenart req->dst, req->cryptlen, 0, 0, req->iv, 599f6beaea3SAntoine Tenart commands, results); 600f6beaea3SAntoine Tenart return ret; 601f6beaea3SAntoine Tenart } 602f6beaea3SAntoine Tenart 603f6beaea3SAntoine Tenart static int safexcel_aead_send(struct crypto_async_request *async, int ring, 604f6beaea3SAntoine Tenart struct safexcel_request *request, int *commands, 605f6beaea3SAntoine Tenart int *results) 606f6beaea3SAntoine Tenart { 607f6beaea3SAntoine Tenart struct aead_request *req = aead_request_cast(async); 608f6beaea3SAntoine Tenart struct crypto_aead *tfm = crypto_aead_reqtfm(req); 609f6beaea3SAntoine Tenart struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(req->base.tfm); 610f6beaea3SAntoine Tenart struct safexcel_cipher_req *sreq = aead_request_ctx(req); 611f6beaea3SAntoine Tenart struct safexcel_crypto_priv *priv = ctx->priv; 612f6beaea3SAntoine Tenart int ret; 613f6beaea3SAntoine Tenart 614f6beaea3SAntoine Tenart BUG_ON(priv->version == EIP97 && sreq->needs_inv); 615f6beaea3SAntoine Tenart 616f6beaea3SAntoine Tenart if (sreq->needs_inv) 617f6beaea3SAntoine Tenart ret = safexcel_cipher_send_inv(async, ring, request, commands, 618f6beaea3SAntoine Tenart results); 619f6beaea3SAntoine Tenart else 620f6beaea3SAntoine Tenart ret = safexcel_aes_send(async, ring, request, sreq, req->src, 621f6beaea3SAntoine Tenart req->dst, req->cryptlen, req->assoclen, 622f6beaea3SAntoine Tenart crypto_aead_authsize(tfm), req->iv, 6231eb7b403SOfer Heifetz commands, results); 6241eb7b403SOfer Heifetz return ret; 6251eb7b403SOfer Heifetz } 6261eb7b403SOfer Heifetz 6278ac1283eSAntoine Tenart static int safexcel_cipher_exit_inv(struct crypto_tfm *tfm, 6288ac1283eSAntoine Tenart struct crypto_async_request *base, 6298ac1283eSAntoine Tenart struct safexcel_cipher_req *sreq, 6308ac1283eSAntoine Tenart struct safexcel_inv_result *result) 6311b44c5a6SAntoine Ténart { 6321b44c5a6SAntoine Ténart struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); 6331b44c5a6SAntoine Ténart struct safexcel_crypto_priv *priv = ctx->priv; 63486671abbSAntoine Ténart int ring = ctx->base.ring; 6351b44c5a6SAntoine Ténart 6368ac1283eSAntoine Tenart init_completion(&result->completion); 6371b44c5a6SAntoine Ténart 6388ac1283eSAntoine Tenart ctx = crypto_tfm_ctx(base->tfm); 6391b44c5a6SAntoine Ténart ctx->base.exit_inv = true; 6401eb7b403SOfer Heifetz sreq->needs_inv = true; 6411b44c5a6SAntoine Ténart 64286671abbSAntoine Ténart spin_lock_bh(&priv->ring[ring].queue_lock); 6438ac1283eSAntoine Tenart crypto_enqueue_request(&priv->ring[ring].queue, base); 64486671abbSAntoine Ténart spin_unlock_bh(&priv->ring[ring].queue_lock); 6451b44c5a6SAntoine Ténart 6468472e778SAntoine Ténart queue_work(priv->ring[ring].workqueue, 6478472e778SAntoine Ténart &priv->ring[ring].work_data.work); 6481b44c5a6SAntoine Ténart 6498ac1283eSAntoine Tenart wait_for_completion(&result->completion); 6501b44c5a6SAntoine Ténart 6518ac1283eSAntoine Tenart if (result->error) { 6521b44c5a6SAntoine Ténart dev_warn(priv->dev, 6531b44c5a6SAntoine Ténart "cipher: sync: invalidate: completion error %d\n", 6548ac1283eSAntoine Tenart result->error); 6558ac1283eSAntoine Tenart return result->error; 6561b44c5a6SAntoine Ténart } 6571b44c5a6SAntoine Ténart 6581b44c5a6SAntoine Ténart return 0; 6591b44c5a6SAntoine Ténart } 6601b44c5a6SAntoine Ténart 6618ac1283eSAntoine Tenart static int safexcel_skcipher_exit_inv(struct crypto_tfm *tfm) 6628ac1283eSAntoine Tenart { 6638ac1283eSAntoine Tenart EIP197_REQUEST_ON_STACK(req, skcipher, EIP197_SKCIPHER_REQ_SIZE); 6648ac1283eSAntoine Tenart struct safexcel_cipher_req *sreq = skcipher_request_ctx(req); 6658ac1283eSAntoine Tenart struct safexcel_inv_result result = {}; 6668ac1283eSAntoine Tenart 6678ac1283eSAntoine Tenart memset(req, 0, sizeof(struct skcipher_request)); 6688ac1283eSAntoine Tenart 6698ac1283eSAntoine Tenart skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, 6708ac1283eSAntoine Tenart safexcel_inv_complete, &result); 6718ac1283eSAntoine Tenart skcipher_request_set_tfm(req, __crypto_skcipher_cast(tfm)); 6728ac1283eSAntoine Tenart 6738ac1283eSAntoine Tenart return safexcel_cipher_exit_inv(tfm, &req->base, sreq, &result); 6748ac1283eSAntoine Tenart } 6758ac1283eSAntoine Tenart 676f6beaea3SAntoine Tenart static int safexcel_aead_exit_inv(struct crypto_tfm *tfm) 677f6beaea3SAntoine Tenart { 678f6beaea3SAntoine Tenart EIP197_REQUEST_ON_STACK(req, aead, EIP197_AEAD_REQ_SIZE); 679f6beaea3SAntoine Tenart struct safexcel_cipher_req *sreq = aead_request_ctx(req); 680f6beaea3SAntoine Tenart struct safexcel_inv_result result = {}; 681f6beaea3SAntoine Tenart 682f6beaea3SAntoine Tenart memset(req, 0, sizeof(struct aead_request)); 683f6beaea3SAntoine Tenart 684f6beaea3SAntoine Tenart aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, 685f6beaea3SAntoine Tenart safexcel_inv_complete, &result); 686f6beaea3SAntoine Tenart aead_request_set_tfm(req, __crypto_aead_cast(tfm)); 687f6beaea3SAntoine Tenart 688f6beaea3SAntoine Tenart return safexcel_cipher_exit_inv(tfm, &req->base, sreq, &result); 689f6beaea3SAntoine Tenart } 690f6beaea3SAntoine Tenart 6918ac1283eSAntoine Tenart static int safexcel_aes(struct crypto_async_request *base, 6928ac1283eSAntoine Tenart struct safexcel_cipher_req *sreq, 6931b44c5a6SAntoine Ténart enum safexcel_cipher_direction dir, u32 mode) 6941b44c5a6SAntoine Ténart { 6958ac1283eSAntoine Tenart struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(base->tfm); 6961b44c5a6SAntoine Ténart struct safexcel_crypto_priv *priv = ctx->priv; 69786671abbSAntoine Ténart int ret, ring; 6981b44c5a6SAntoine Ténart 6991eb7b403SOfer Heifetz sreq->needs_inv = false; 700847ccfc5SOfer Heifetz sreq->direction = dir; 7011b44c5a6SAntoine Ténart ctx->mode = mode; 7021b44c5a6SAntoine Ténart 7031b44c5a6SAntoine Ténart if (ctx->base.ctxr) { 704871df319SAntoine Ténart if (priv->version == EIP197 && ctx->base.needs_inv) { 7051eb7b403SOfer Heifetz sreq->needs_inv = true; 7061eb7b403SOfer Heifetz ctx->base.needs_inv = false; 7071eb7b403SOfer Heifetz } 7081b44c5a6SAntoine Ténart } else { 7091b44c5a6SAntoine Ténart ctx->base.ring = safexcel_select_ring(priv); 7101b44c5a6SAntoine Ténart ctx->base.ctxr = dma_pool_zalloc(priv->context_pool, 7118ac1283eSAntoine Tenart EIP197_GFP_FLAGS(*base), 7121b44c5a6SAntoine Ténart &ctx->base.ctxr_dma); 7131b44c5a6SAntoine Ténart if (!ctx->base.ctxr) 7141b44c5a6SAntoine Ténart return -ENOMEM; 7151b44c5a6SAntoine Ténart } 7161b44c5a6SAntoine Ténart 71786671abbSAntoine Ténart ring = ctx->base.ring; 7181b44c5a6SAntoine Ténart 71986671abbSAntoine Ténart spin_lock_bh(&priv->ring[ring].queue_lock); 7208ac1283eSAntoine Tenart ret = crypto_enqueue_request(&priv->ring[ring].queue, base); 72186671abbSAntoine Ténart spin_unlock_bh(&priv->ring[ring].queue_lock); 72286671abbSAntoine Ténart 7238472e778SAntoine Ténart queue_work(priv->ring[ring].workqueue, 7248472e778SAntoine Ténart &priv->ring[ring].work_data.work); 7251b44c5a6SAntoine Ténart 7261b44c5a6SAntoine Ténart return ret; 7271b44c5a6SAntoine Ténart } 7281b44c5a6SAntoine Ténart 7291b44c5a6SAntoine Ténart static int safexcel_ecb_aes_encrypt(struct skcipher_request *req) 7301b44c5a6SAntoine Ténart { 7318ac1283eSAntoine Tenart return safexcel_aes(&req->base, skcipher_request_ctx(req), 7328ac1283eSAntoine Tenart SAFEXCEL_ENCRYPT, CONTEXT_CONTROL_CRYPTO_MODE_ECB); 7331b44c5a6SAntoine Ténart } 7341b44c5a6SAntoine Ténart 7351b44c5a6SAntoine Ténart static int safexcel_ecb_aes_decrypt(struct skcipher_request *req) 7361b44c5a6SAntoine Ténart { 7378ac1283eSAntoine Tenart return safexcel_aes(&req->base, skcipher_request_ctx(req), 7388ac1283eSAntoine Tenart SAFEXCEL_DECRYPT, CONTEXT_CONTROL_CRYPTO_MODE_ECB); 7391b44c5a6SAntoine Ténart } 7401b44c5a6SAntoine Ténart 7411b44c5a6SAntoine Ténart static int safexcel_skcipher_cra_init(struct crypto_tfm *tfm) 7421b44c5a6SAntoine Ténart { 7431b44c5a6SAntoine Ténart struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); 7441b44c5a6SAntoine Ténart struct safexcel_alg_template *tmpl = 7451b44c5a6SAntoine Ténart container_of(tfm->__crt_alg, struct safexcel_alg_template, 7461b44c5a6SAntoine Ténart alg.skcipher.base); 7471b44c5a6SAntoine Ténart 7481eb7b403SOfer Heifetz crypto_skcipher_set_reqsize(__crypto_skcipher_cast(tfm), 7491eb7b403SOfer Heifetz sizeof(struct safexcel_cipher_req)); 7501b44c5a6SAntoine Ténart 7518ac1283eSAntoine Tenart ctx->priv = tmpl->priv; 7528ac1283eSAntoine Tenart 7538ac1283eSAntoine Tenart ctx->base.send = safexcel_skcipher_send; 7548ac1283eSAntoine Tenart ctx->base.handle_result = safexcel_skcipher_handle_result; 7558ac1283eSAntoine Tenart return 0; 7568ac1283eSAntoine Tenart } 7578ac1283eSAntoine Tenart 7588ac1283eSAntoine Tenart static int safexcel_cipher_cra_exit(struct crypto_tfm *tfm) 7598ac1283eSAntoine Tenart { 7608ac1283eSAntoine Tenart struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); 7618ac1283eSAntoine Tenart 762ce679559SAntoine Tenart memzero_explicit(ctx->key, sizeof(ctx->key)); 7638ac1283eSAntoine Tenart 7648ac1283eSAntoine Tenart /* context not allocated, skip invalidation */ 7658ac1283eSAntoine Tenart if (!ctx->base.ctxr) 7668ac1283eSAntoine Tenart return -ENOMEM; 7678ac1283eSAntoine Tenart 768ce679559SAntoine Tenart memzero_explicit(ctx->base.ctxr->data, sizeof(ctx->base.ctxr->data)); 7691b44c5a6SAntoine Ténart return 0; 7701b44c5a6SAntoine Ténart } 7711b44c5a6SAntoine Ténart 7721b44c5a6SAntoine Ténart static void safexcel_skcipher_cra_exit(struct crypto_tfm *tfm) 7731b44c5a6SAntoine Ténart { 7741b44c5a6SAntoine Ténart struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); 7751b44c5a6SAntoine Ténart struct safexcel_crypto_priv *priv = ctx->priv; 7761b44c5a6SAntoine Ténart int ret; 7771b44c5a6SAntoine Ténart 7788ac1283eSAntoine Tenart if (safexcel_cipher_cra_exit(tfm)) 7791b44c5a6SAntoine Ténart return; 7801b44c5a6SAntoine Ténart 781871df319SAntoine Ténart if (priv->version == EIP197) { 7828ac1283eSAntoine Tenart ret = safexcel_skcipher_exit_inv(tfm); 7831b44c5a6SAntoine Ténart if (ret) 7848ac1283eSAntoine Tenart dev_warn(priv->dev, "skcipher: invalidation error %d\n", 7858ac1283eSAntoine Tenart ret); 786871df319SAntoine Ténart } else { 787871df319SAntoine Ténart dma_pool_free(priv->context_pool, ctx->base.ctxr, 788871df319SAntoine Ténart ctx->base.ctxr_dma); 789871df319SAntoine Ténart } 7901b44c5a6SAntoine Ténart } 7911b44c5a6SAntoine Ténart 792f6beaea3SAntoine Tenart static void safexcel_aead_cra_exit(struct crypto_tfm *tfm) 793f6beaea3SAntoine Tenart { 794f6beaea3SAntoine Tenart struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); 795f6beaea3SAntoine Tenart struct safexcel_crypto_priv *priv = ctx->priv; 796f6beaea3SAntoine Tenart int ret; 797f6beaea3SAntoine Tenart 798f6beaea3SAntoine Tenart if (safexcel_cipher_cra_exit(tfm)) 799f6beaea3SAntoine Tenart return; 800f6beaea3SAntoine Tenart 801f6beaea3SAntoine Tenart if (priv->version == EIP197) { 802f6beaea3SAntoine Tenart ret = safexcel_aead_exit_inv(tfm); 803f6beaea3SAntoine Tenart if (ret) 804f6beaea3SAntoine Tenart dev_warn(priv->dev, "aead: invalidation error %d\n", 805f6beaea3SAntoine Tenart ret); 806f6beaea3SAntoine Tenart } else { 807f6beaea3SAntoine Tenart dma_pool_free(priv->context_pool, ctx->base.ctxr, 808f6beaea3SAntoine Tenart ctx->base.ctxr_dma); 809f6beaea3SAntoine Tenart } 810f6beaea3SAntoine Tenart } 811f6beaea3SAntoine Tenart 8121b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_ecb_aes = { 8131b44c5a6SAntoine Ténart .type = SAFEXCEL_ALG_TYPE_SKCIPHER, 8141b44c5a6SAntoine Ténart .alg.skcipher = { 8158ac1283eSAntoine Tenart .setkey = safexcel_skcipher_aes_setkey, 8161b44c5a6SAntoine Ténart .encrypt = safexcel_ecb_aes_encrypt, 8171b44c5a6SAntoine Ténart .decrypt = safexcel_ecb_aes_decrypt, 8181b44c5a6SAntoine Ténart .min_keysize = AES_MIN_KEY_SIZE, 8191b44c5a6SAntoine Ténart .max_keysize = AES_MAX_KEY_SIZE, 8201b44c5a6SAntoine Ténart .base = { 8211b44c5a6SAntoine Ténart .cra_name = "ecb(aes)", 8221b44c5a6SAntoine Ténart .cra_driver_name = "safexcel-ecb-aes", 8231b44c5a6SAntoine Ténart .cra_priority = 300, 8241b44c5a6SAntoine Ténart .cra_flags = CRYPTO_ALG_TYPE_SKCIPHER | CRYPTO_ALG_ASYNC | 8251b44c5a6SAntoine Ténart CRYPTO_ALG_KERN_DRIVER_ONLY, 8261b44c5a6SAntoine Ténart .cra_blocksize = AES_BLOCK_SIZE, 8271b44c5a6SAntoine Ténart .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), 8281b44c5a6SAntoine Ténart .cra_alignmask = 0, 8291b44c5a6SAntoine Ténart .cra_init = safexcel_skcipher_cra_init, 8301b44c5a6SAntoine Ténart .cra_exit = safexcel_skcipher_cra_exit, 8311b44c5a6SAntoine Ténart .cra_module = THIS_MODULE, 8321b44c5a6SAntoine Ténart }, 8331b44c5a6SAntoine Ténart }, 8341b44c5a6SAntoine Ténart }; 8351b44c5a6SAntoine Ténart 8361b44c5a6SAntoine Ténart static int safexcel_cbc_aes_encrypt(struct skcipher_request *req) 8371b44c5a6SAntoine Ténart { 8388ac1283eSAntoine Tenart return safexcel_aes(&req->base, skcipher_request_ctx(req), 8398ac1283eSAntoine Tenart SAFEXCEL_ENCRYPT, CONTEXT_CONTROL_CRYPTO_MODE_CBC); 8401b44c5a6SAntoine Ténart } 8411b44c5a6SAntoine Ténart 8421b44c5a6SAntoine Ténart static int safexcel_cbc_aes_decrypt(struct skcipher_request *req) 8431b44c5a6SAntoine Ténart { 8448ac1283eSAntoine Tenart return safexcel_aes(&req->base, skcipher_request_ctx(req), 8458ac1283eSAntoine Tenart SAFEXCEL_DECRYPT, CONTEXT_CONTROL_CRYPTO_MODE_CBC); 8461b44c5a6SAntoine Ténart } 8471b44c5a6SAntoine Ténart 8481b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_cbc_aes = { 8491b44c5a6SAntoine Ténart .type = SAFEXCEL_ALG_TYPE_SKCIPHER, 8501b44c5a6SAntoine Ténart .alg.skcipher = { 8518ac1283eSAntoine Tenart .setkey = safexcel_skcipher_aes_setkey, 8521b44c5a6SAntoine Ténart .encrypt = safexcel_cbc_aes_encrypt, 8531b44c5a6SAntoine Ténart .decrypt = safexcel_cbc_aes_decrypt, 8541b44c5a6SAntoine Ténart .min_keysize = AES_MIN_KEY_SIZE, 8551b44c5a6SAntoine Ténart .max_keysize = AES_MAX_KEY_SIZE, 8561b44c5a6SAntoine Ténart .ivsize = AES_BLOCK_SIZE, 8571b44c5a6SAntoine Ténart .base = { 8581b44c5a6SAntoine Ténart .cra_name = "cbc(aes)", 8591b44c5a6SAntoine Ténart .cra_driver_name = "safexcel-cbc-aes", 8601b44c5a6SAntoine Ténart .cra_priority = 300, 8611b44c5a6SAntoine Ténart .cra_flags = CRYPTO_ALG_TYPE_SKCIPHER | CRYPTO_ALG_ASYNC | 8621b44c5a6SAntoine Ténart CRYPTO_ALG_KERN_DRIVER_ONLY, 8631b44c5a6SAntoine Ténart .cra_blocksize = AES_BLOCK_SIZE, 8641b44c5a6SAntoine Ténart .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), 8651b44c5a6SAntoine Ténart .cra_alignmask = 0, 8661b44c5a6SAntoine Ténart .cra_init = safexcel_skcipher_cra_init, 8671b44c5a6SAntoine Ténart .cra_exit = safexcel_skcipher_cra_exit, 8681b44c5a6SAntoine Ténart .cra_module = THIS_MODULE, 8691b44c5a6SAntoine Ténart }, 8701b44c5a6SAntoine Ténart }, 8711b44c5a6SAntoine Ténart }; 872f6beaea3SAntoine Tenart 873f6beaea3SAntoine Tenart static int safexcel_aead_encrypt(struct aead_request *req) 874f6beaea3SAntoine Tenart { 875f6beaea3SAntoine Tenart struct safexcel_cipher_req *creq = aead_request_ctx(req); 876f6beaea3SAntoine Tenart 877f6beaea3SAntoine Tenart return safexcel_aes(&req->base, creq, SAFEXCEL_ENCRYPT, 878f6beaea3SAntoine Tenart CONTEXT_CONTROL_CRYPTO_MODE_CBC); 879f6beaea3SAntoine Tenart } 880f6beaea3SAntoine Tenart 881f6beaea3SAntoine Tenart static int safexcel_aead_decrypt(struct aead_request *req) 882f6beaea3SAntoine Tenart { 883f6beaea3SAntoine Tenart struct safexcel_cipher_req *creq = aead_request_ctx(req); 884f6beaea3SAntoine Tenart 885f6beaea3SAntoine Tenart return safexcel_aes(&req->base, creq, SAFEXCEL_DECRYPT, 886f6beaea3SAntoine Tenart CONTEXT_CONTROL_CRYPTO_MODE_CBC); 887f6beaea3SAntoine Tenart } 888f6beaea3SAntoine Tenart 889f6beaea3SAntoine Tenart static int safexcel_aead_cra_init(struct crypto_tfm *tfm) 890f6beaea3SAntoine Tenart { 891f6beaea3SAntoine Tenart struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); 892f6beaea3SAntoine Tenart struct safexcel_alg_template *tmpl = 893f6beaea3SAntoine Tenart container_of(tfm->__crt_alg, struct safexcel_alg_template, 894f6beaea3SAntoine Tenart alg.aead.base); 895f6beaea3SAntoine Tenart 896f6beaea3SAntoine Tenart crypto_aead_set_reqsize(__crypto_aead_cast(tfm), 897f6beaea3SAntoine Tenart sizeof(struct safexcel_cipher_req)); 898f6beaea3SAntoine Tenart 899f6beaea3SAntoine Tenart ctx->priv = tmpl->priv; 900f6beaea3SAntoine Tenart 901f6beaea3SAntoine Tenart ctx->aead = true; 902f6beaea3SAntoine Tenart ctx->base.send = safexcel_aead_send; 903f6beaea3SAntoine Tenart ctx->base.handle_result = safexcel_aead_handle_result; 904f6beaea3SAntoine Tenart return 0; 905f6beaea3SAntoine Tenart } 906f6beaea3SAntoine Tenart 907f6beaea3SAntoine Tenart static int safexcel_aead_sha256_cra_init(struct crypto_tfm *tfm) 908f6beaea3SAntoine Tenart { 909f6beaea3SAntoine Tenart struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); 910f6beaea3SAntoine Tenart 911f6beaea3SAntoine Tenart safexcel_aead_cra_init(tfm); 912f6beaea3SAntoine Tenart ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256; 913f6beaea3SAntoine Tenart ctx->state_sz = SHA256_DIGEST_SIZE; 914f6beaea3SAntoine Tenart return 0; 915f6beaea3SAntoine Tenart } 916f6beaea3SAntoine Tenart 917f6beaea3SAntoine Tenart struct safexcel_alg_template safexcel_alg_authenc_hmac_sha256_cbc_aes = { 918f6beaea3SAntoine Tenart .type = SAFEXCEL_ALG_TYPE_AEAD, 919f6beaea3SAntoine Tenart .alg.aead = { 920f6beaea3SAntoine Tenart .setkey = safexcel_aead_aes_setkey, 921f6beaea3SAntoine Tenart .encrypt = safexcel_aead_encrypt, 922f6beaea3SAntoine Tenart .decrypt = safexcel_aead_decrypt, 923f6beaea3SAntoine Tenart .ivsize = AES_BLOCK_SIZE, 924f6beaea3SAntoine Tenart .maxauthsize = SHA256_DIGEST_SIZE, 925f6beaea3SAntoine Tenart .base = { 926f6beaea3SAntoine Tenart .cra_name = "authenc(hmac(sha256),cbc(aes))", 927f6beaea3SAntoine Tenart .cra_driver_name = "safexcel-authenc-hmac-sha256-cbc-aes", 928f6beaea3SAntoine Tenart .cra_priority = 300, 929f6beaea3SAntoine Tenart .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC | 930f6beaea3SAntoine Tenart CRYPTO_ALG_KERN_DRIVER_ONLY, 931f6beaea3SAntoine Tenart .cra_blocksize = AES_BLOCK_SIZE, 932f6beaea3SAntoine Tenart .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), 933f6beaea3SAntoine Tenart .cra_alignmask = 0, 934f6beaea3SAntoine Tenart .cra_init = safexcel_aead_sha256_cra_init, 935f6beaea3SAntoine Tenart .cra_exit = safexcel_aead_cra_exit, 936f6beaea3SAntoine Tenart .cra_module = THIS_MODULE, 937f6beaea3SAntoine Tenart }, 938f6beaea3SAntoine Tenart }, 939f6beaea3SAntoine Tenart }; 940