1af873fceSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 29e054ec2SFabien DESSENNE /* 39e054ec2SFabien DESSENNE * Copyright (C) STMicroelectronics SA 2017 49e054ec2SFabien DESSENNE * Author: Fabien Dessenne <fabien.dessenne@st.com> 59e054ec2SFabien DESSENNE */ 69e054ec2SFabien DESSENNE 79e054ec2SFabien DESSENNE #include <linux/clk.h> 89e054ec2SFabien DESSENNE #include <linux/delay.h> 99e054ec2SFabien DESSENNE #include <linux/interrupt.h> 109e054ec2SFabien DESSENNE #include <linux/iopoll.h> 119e054ec2SFabien DESSENNE #include <linux/module.h> 129e054ec2SFabien DESSENNE #include <linux/of_device.h> 139e054ec2SFabien DESSENNE #include <linux/platform_device.h> 1465f9aa36Slionel.debieve@st.com #include <linux/pm_runtime.h> 159e054ec2SFabien DESSENNE #include <linux/reset.h> 169e054ec2SFabien DESSENNE 179e054ec2SFabien DESSENNE #include <crypto/aes.h> 18b5d0ba83SArd Biesheuvel #include <crypto/internal/des.h> 199e054ec2SFabien DESSENNE #include <crypto/engine.h> 209e054ec2SFabien DESSENNE #include <crypto/scatterwalk.h> 219d3b5030SFabien DESSENNE #include <crypto/internal/aead.h> 2247ece481SArd Biesheuvel #include <crypto/internal/skcipher.h> 239e054ec2SFabien DESSENNE 249e054ec2SFabien DESSENNE #define DRIVER_NAME "stm32-cryp" 259e054ec2SFabien DESSENNE 269e054ec2SFabien DESSENNE /* Bit [0] encrypt / decrypt */ 279e054ec2SFabien DESSENNE #define FLG_ENCRYPT BIT(0) 289e054ec2SFabien DESSENNE /* Bit [8..1] algo & operation mode */ 299e054ec2SFabien DESSENNE #define FLG_AES BIT(1) 309e054ec2SFabien DESSENNE #define FLG_DES BIT(2) 319e054ec2SFabien DESSENNE #define FLG_TDES BIT(3) 329e054ec2SFabien DESSENNE #define FLG_ECB BIT(4) 339e054ec2SFabien DESSENNE #define FLG_CBC BIT(5) 349e054ec2SFabien DESSENNE #define FLG_CTR BIT(6) 359d3b5030SFabien DESSENNE #define FLG_GCM BIT(7) 369d3b5030SFabien DESSENNE #define FLG_CCM BIT(8) 379e054ec2SFabien DESSENNE /* Mode mask = bits [15..0] */ 389e054ec2SFabien DESSENNE #define FLG_MODE_MASK GENMASK(15, 0) 399d3b5030SFabien DESSENNE /* Bit [31..16] status */ 409d3b5030SFabien DESSENNE #define FLG_CCM_PADDED_WA BIT(16) 419e054ec2SFabien DESSENNE 429e054ec2SFabien DESSENNE /* Registers */ 439e054ec2SFabien DESSENNE #define CRYP_CR 0x00000000 449e054ec2SFabien DESSENNE #define CRYP_SR 0x00000004 459e054ec2SFabien DESSENNE #define CRYP_DIN 0x00000008 469e054ec2SFabien DESSENNE #define CRYP_DOUT 0x0000000C 479e054ec2SFabien DESSENNE #define CRYP_DMACR 0x00000010 489e054ec2SFabien DESSENNE #define CRYP_IMSCR 0x00000014 499e054ec2SFabien DESSENNE #define CRYP_RISR 0x00000018 509e054ec2SFabien DESSENNE #define CRYP_MISR 0x0000001C 519e054ec2SFabien DESSENNE #define CRYP_K0LR 0x00000020 529e054ec2SFabien DESSENNE #define CRYP_K0RR 0x00000024 539e054ec2SFabien DESSENNE #define CRYP_K1LR 0x00000028 549e054ec2SFabien DESSENNE #define CRYP_K1RR 0x0000002C 559e054ec2SFabien DESSENNE #define CRYP_K2LR 0x00000030 569e054ec2SFabien DESSENNE #define CRYP_K2RR 0x00000034 579e054ec2SFabien DESSENNE #define CRYP_K3LR 0x00000038 589e054ec2SFabien DESSENNE #define CRYP_K3RR 0x0000003C 599e054ec2SFabien DESSENNE #define CRYP_IV0LR 0x00000040 609e054ec2SFabien DESSENNE #define CRYP_IV0RR 0x00000044 619e054ec2SFabien DESSENNE #define CRYP_IV1LR 0x00000048 629e054ec2SFabien DESSENNE #define CRYP_IV1RR 0x0000004C 639d3b5030SFabien DESSENNE #define CRYP_CSGCMCCM0R 0x00000050 649d3b5030SFabien DESSENNE #define CRYP_CSGCM0R 0x00000070 659e054ec2SFabien DESSENNE 669e054ec2SFabien DESSENNE /* Registers values */ 679e054ec2SFabien DESSENNE #define CR_DEC_NOT_ENC 0x00000004 689e054ec2SFabien DESSENNE #define CR_TDES_ECB 0x00000000 699e054ec2SFabien DESSENNE #define CR_TDES_CBC 0x00000008 709e054ec2SFabien DESSENNE #define CR_DES_ECB 0x00000010 719e054ec2SFabien DESSENNE #define CR_DES_CBC 0x00000018 729e054ec2SFabien DESSENNE #define CR_AES_ECB 0x00000020 739e054ec2SFabien DESSENNE #define CR_AES_CBC 0x00000028 749e054ec2SFabien DESSENNE #define CR_AES_CTR 0x00000030 759e054ec2SFabien DESSENNE #define CR_AES_KP 0x00000038 769d3b5030SFabien DESSENNE #define CR_AES_GCM 0x00080000 779d3b5030SFabien DESSENNE #define CR_AES_CCM 0x00080008 789e054ec2SFabien DESSENNE #define CR_AES_UNKNOWN 0xFFFFFFFF 799e054ec2SFabien DESSENNE #define CR_ALGO_MASK 0x00080038 809e054ec2SFabien DESSENNE #define CR_DATA32 0x00000000 819e054ec2SFabien DESSENNE #define CR_DATA16 0x00000040 829e054ec2SFabien DESSENNE #define CR_DATA8 0x00000080 839e054ec2SFabien DESSENNE #define CR_DATA1 0x000000C0 849e054ec2SFabien DESSENNE #define CR_KEY128 0x00000000 859e054ec2SFabien DESSENNE #define CR_KEY192 0x00000100 869e054ec2SFabien DESSENNE #define CR_KEY256 0x00000200 879e054ec2SFabien DESSENNE #define CR_FFLUSH 0x00004000 889e054ec2SFabien DESSENNE #define CR_CRYPEN 0x00008000 899d3b5030SFabien DESSENNE #define CR_PH_INIT 0x00000000 909d3b5030SFabien DESSENNE #define CR_PH_HEADER 0x00010000 919d3b5030SFabien DESSENNE #define CR_PH_PAYLOAD 0x00020000 929d3b5030SFabien DESSENNE #define CR_PH_FINAL 0x00030000 939d3b5030SFabien DESSENNE #define CR_PH_MASK 0x00030000 949d3b5030SFabien DESSENNE #define CR_NBPBL_SHIFT 20 959e054ec2SFabien DESSENNE 969e054ec2SFabien DESSENNE #define SR_BUSY 0x00000010 979e054ec2SFabien DESSENNE #define SR_OFNE 0x00000004 989e054ec2SFabien DESSENNE 999e054ec2SFabien DESSENNE #define IMSCR_IN BIT(0) 1009e054ec2SFabien DESSENNE #define IMSCR_OUT BIT(1) 1019e054ec2SFabien DESSENNE 1029e054ec2SFabien DESSENNE #define MISR_IN BIT(0) 1039e054ec2SFabien DESSENNE #define MISR_OUT BIT(1) 1049e054ec2SFabien DESSENNE 1059e054ec2SFabien DESSENNE /* Misc */ 1069e054ec2SFabien DESSENNE #define AES_BLOCK_32 (AES_BLOCK_SIZE / sizeof(u32)) 1079d3b5030SFabien DESSENNE #define GCM_CTR_INIT 2 1089e054ec2SFabien DESSENNE #define _walked_in (cryp->in_walk.offset - cryp->in_sg->offset) 1099e054ec2SFabien DESSENNE #define _walked_out (cryp->out_walk.offset - cryp->out_sg->offset) 11065f9aa36Slionel.debieve@st.com #define CRYP_AUTOSUSPEND_DELAY 50 1119e054ec2SFabien DESSENNE 1129d3b5030SFabien DESSENNE struct stm32_cryp_caps { 1139d3b5030SFabien DESSENNE bool swap_final; 1149d3b5030SFabien DESSENNE bool padding_wa; 1159d3b5030SFabien DESSENNE }; 1169d3b5030SFabien DESSENNE 1179e054ec2SFabien DESSENNE struct stm32_cryp_ctx { 118dc7bcef5SCorentin LABBE struct crypto_engine_ctx enginectx; 1199e054ec2SFabien DESSENNE struct stm32_cryp *cryp; 1209e054ec2SFabien DESSENNE int keylen; 121*bbb28326SHerbert Xu __be32 key[AES_KEYSIZE_256 / sizeof(u32)]; 1229e054ec2SFabien DESSENNE unsigned long flags; 1239e054ec2SFabien DESSENNE }; 1249e054ec2SFabien DESSENNE 1259e054ec2SFabien DESSENNE struct stm32_cryp_reqctx { 1269e054ec2SFabien DESSENNE unsigned long mode; 1279e054ec2SFabien DESSENNE }; 1289e054ec2SFabien DESSENNE 1299e054ec2SFabien DESSENNE struct stm32_cryp { 1309e054ec2SFabien DESSENNE struct list_head list; 1319e054ec2SFabien DESSENNE struct device *dev; 1329e054ec2SFabien DESSENNE void __iomem *regs; 1339e054ec2SFabien DESSENNE struct clk *clk; 1349e054ec2SFabien DESSENNE unsigned long flags; 1359e054ec2SFabien DESSENNE u32 irq_status; 1369d3b5030SFabien DESSENNE const struct stm32_cryp_caps *caps; 1379e054ec2SFabien DESSENNE struct stm32_cryp_ctx *ctx; 1389e054ec2SFabien DESSENNE 1399e054ec2SFabien DESSENNE struct crypto_engine *engine; 1409e054ec2SFabien DESSENNE 14147ece481SArd Biesheuvel struct skcipher_request *req; 1429d3b5030SFabien DESSENNE struct aead_request *areq; 1439e054ec2SFabien DESSENNE 1449d3b5030SFabien DESSENNE size_t authsize; 1459e054ec2SFabien DESSENNE size_t hw_blocksize; 1469e054ec2SFabien DESSENNE 1479e054ec2SFabien DESSENNE size_t total_in; 1489e054ec2SFabien DESSENNE size_t total_in_save; 1499e054ec2SFabien DESSENNE size_t total_out; 1509e054ec2SFabien DESSENNE size_t total_out_save; 1519e054ec2SFabien DESSENNE 1529e054ec2SFabien DESSENNE struct scatterlist *in_sg; 1539e054ec2SFabien DESSENNE struct scatterlist *out_sg; 1549e054ec2SFabien DESSENNE struct scatterlist *out_sg_save; 1559e054ec2SFabien DESSENNE 1569e054ec2SFabien DESSENNE struct scatterlist in_sgl; 1579e054ec2SFabien DESSENNE struct scatterlist out_sgl; 1589e054ec2SFabien DESSENNE bool sgs_copied; 1599e054ec2SFabien DESSENNE 1609e054ec2SFabien DESSENNE int in_sg_len; 1619e054ec2SFabien DESSENNE int out_sg_len; 1629e054ec2SFabien DESSENNE 1639e054ec2SFabien DESSENNE struct scatter_walk in_walk; 1649e054ec2SFabien DESSENNE struct scatter_walk out_walk; 1659e054ec2SFabien DESSENNE 1669e054ec2SFabien DESSENNE u32 last_ctr[4]; 1679d3b5030SFabien DESSENNE u32 gcm_ctr; 1689e054ec2SFabien DESSENNE }; 1699e054ec2SFabien DESSENNE 1709e054ec2SFabien DESSENNE struct stm32_cryp_list { 1719e054ec2SFabien DESSENNE struct list_head dev_list; 1729e054ec2SFabien DESSENNE spinlock_t lock; /* protect dev_list */ 1739e054ec2SFabien DESSENNE }; 1749e054ec2SFabien DESSENNE 1759e054ec2SFabien DESSENNE static struct stm32_cryp_list cryp_list = { 1769e054ec2SFabien DESSENNE .dev_list = LIST_HEAD_INIT(cryp_list.dev_list), 1779e054ec2SFabien DESSENNE .lock = __SPIN_LOCK_UNLOCKED(cryp_list.lock), 1789e054ec2SFabien DESSENNE }; 1799e054ec2SFabien DESSENNE 1809e054ec2SFabien DESSENNE static inline bool is_aes(struct stm32_cryp *cryp) 1819e054ec2SFabien DESSENNE { 1829e054ec2SFabien DESSENNE return cryp->flags & FLG_AES; 1839e054ec2SFabien DESSENNE } 1849e054ec2SFabien DESSENNE 1859e054ec2SFabien DESSENNE static inline bool is_des(struct stm32_cryp *cryp) 1869e054ec2SFabien DESSENNE { 1879e054ec2SFabien DESSENNE return cryp->flags & FLG_DES; 1889e054ec2SFabien DESSENNE } 1899e054ec2SFabien DESSENNE 1909e054ec2SFabien DESSENNE static inline bool is_tdes(struct stm32_cryp *cryp) 1919e054ec2SFabien DESSENNE { 1929e054ec2SFabien DESSENNE return cryp->flags & FLG_TDES; 1939e054ec2SFabien DESSENNE } 1949e054ec2SFabien DESSENNE 1959e054ec2SFabien DESSENNE static inline bool is_ecb(struct stm32_cryp *cryp) 1969e054ec2SFabien DESSENNE { 1979e054ec2SFabien DESSENNE return cryp->flags & FLG_ECB; 1989e054ec2SFabien DESSENNE } 1999e054ec2SFabien DESSENNE 2009e054ec2SFabien DESSENNE static inline bool is_cbc(struct stm32_cryp *cryp) 2019e054ec2SFabien DESSENNE { 2029e054ec2SFabien DESSENNE return cryp->flags & FLG_CBC; 2039e054ec2SFabien DESSENNE } 2049e054ec2SFabien DESSENNE 2059e054ec2SFabien DESSENNE static inline bool is_ctr(struct stm32_cryp *cryp) 2069e054ec2SFabien DESSENNE { 2079e054ec2SFabien DESSENNE return cryp->flags & FLG_CTR; 2089e054ec2SFabien DESSENNE } 2099e054ec2SFabien DESSENNE 2109d3b5030SFabien DESSENNE static inline bool is_gcm(struct stm32_cryp *cryp) 2119d3b5030SFabien DESSENNE { 2129d3b5030SFabien DESSENNE return cryp->flags & FLG_GCM; 2139d3b5030SFabien DESSENNE } 2149d3b5030SFabien DESSENNE 2159d3b5030SFabien DESSENNE static inline bool is_ccm(struct stm32_cryp *cryp) 2169d3b5030SFabien DESSENNE { 2179d3b5030SFabien DESSENNE return cryp->flags & FLG_CCM; 2189d3b5030SFabien DESSENNE } 2199d3b5030SFabien DESSENNE 2209e054ec2SFabien DESSENNE static inline bool is_encrypt(struct stm32_cryp *cryp) 2219e054ec2SFabien DESSENNE { 2229e054ec2SFabien DESSENNE return cryp->flags & FLG_ENCRYPT; 2239e054ec2SFabien DESSENNE } 2249e054ec2SFabien DESSENNE 2259e054ec2SFabien DESSENNE static inline bool is_decrypt(struct stm32_cryp *cryp) 2269e054ec2SFabien DESSENNE { 2279e054ec2SFabien DESSENNE return !is_encrypt(cryp); 2289e054ec2SFabien DESSENNE } 2299e054ec2SFabien DESSENNE 2309e054ec2SFabien DESSENNE static inline u32 stm32_cryp_read(struct stm32_cryp *cryp, u32 ofst) 2319e054ec2SFabien DESSENNE { 2329e054ec2SFabien DESSENNE return readl_relaxed(cryp->regs + ofst); 2339e054ec2SFabien DESSENNE } 2349e054ec2SFabien DESSENNE 2359e054ec2SFabien DESSENNE static inline void stm32_cryp_write(struct stm32_cryp *cryp, u32 ofst, u32 val) 2369e054ec2SFabien DESSENNE { 2379e054ec2SFabien DESSENNE writel_relaxed(val, cryp->regs + ofst); 2389e054ec2SFabien DESSENNE } 2399e054ec2SFabien DESSENNE 2409e054ec2SFabien DESSENNE static inline int stm32_cryp_wait_busy(struct stm32_cryp *cryp) 2419e054ec2SFabien DESSENNE { 2429e054ec2SFabien DESSENNE u32 status; 2439e054ec2SFabien DESSENNE 2449e054ec2SFabien DESSENNE return readl_relaxed_poll_timeout(cryp->regs + CRYP_SR, status, 2459e054ec2SFabien DESSENNE !(status & SR_BUSY), 10, 100000); 2469e054ec2SFabien DESSENNE } 2479e054ec2SFabien DESSENNE 2489d3b5030SFabien DESSENNE static inline int stm32_cryp_wait_enable(struct stm32_cryp *cryp) 2499d3b5030SFabien DESSENNE { 2509d3b5030SFabien DESSENNE u32 status; 2519d3b5030SFabien DESSENNE 2529d3b5030SFabien DESSENNE return readl_relaxed_poll_timeout(cryp->regs + CRYP_CR, status, 2539d3b5030SFabien DESSENNE !(status & CR_CRYPEN), 10, 100000); 2549d3b5030SFabien DESSENNE } 2559d3b5030SFabien DESSENNE 2569d3b5030SFabien DESSENNE static inline int stm32_cryp_wait_output(struct stm32_cryp *cryp) 2579d3b5030SFabien DESSENNE { 2589d3b5030SFabien DESSENNE u32 status; 2599d3b5030SFabien DESSENNE 2609d3b5030SFabien DESSENNE return readl_relaxed_poll_timeout(cryp->regs + CRYP_SR, status, 2619d3b5030SFabien DESSENNE status & SR_OFNE, 10, 100000); 2629d3b5030SFabien DESSENNE } 2639d3b5030SFabien DESSENNE 2649d3b5030SFabien DESSENNE static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp); 2659d3b5030SFabien DESSENNE 2669e054ec2SFabien DESSENNE static struct stm32_cryp *stm32_cryp_find_dev(struct stm32_cryp_ctx *ctx) 2679e054ec2SFabien DESSENNE { 2689e054ec2SFabien DESSENNE struct stm32_cryp *tmp, *cryp = NULL; 2699e054ec2SFabien DESSENNE 2709e054ec2SFabien DESSENNE spin_lock_bh(&cryp_list.lock); 2719e054ec2SFabien DESSENNE if (!ctx->cryp) { 2729e054ec2SFabien DESSENNE list_for_each_entry(tmp, &cryp_list.dev_list, list) { 2739e054ec2SFabien DESSENNE cryp = tmp; 2749e054ec2SFabien DESSENNE break; 2759e054ec2SFabien DESSENNE } 2769e054ec2SFabien DESSENNE ctx->cryp = cryp; 2779e054ec2SFabien DESSENNE } else { 2789e054ec2SFabien DESSENNE cryp = ctx->cryp; 2799e054ec2SFabien DESSENNE } 2809e054ec2SFabien DESSENNE 2819e054ec2SFabien DESSENNE spin_unlock_bh(&cryp_list.lock); 2829e054ec2SFabien DESSENNE 2839e054ec2SFabien DESSENNE return cryp; 2849e054ec2SFabien DESSENNE } 2859e054ec2SFabien DESSENNE 2869e054ec2SFabien DESSENNE static int stm32_cryp_check_aligned(struct scatterlist *sg, size_t total, 2879e054ec2SFabien DESSENNE size_t align) 2889e054ec2SFabien DESSENNE { 2899e054ec2SFabien DESSENNE int len = 0; 2909e054ec2SFabien DESSENNE 2919e054ec2SFabien DESSENNE if (!total) 2929e054ec2SFabien DESSENNE return 0; 2939e054ec2SFabien DESSENNE 2949e054ec2SFabien DESSENNE if (!IS_ALIGNED(total, align)) 2959e054ec2SFabien DESSENNE return -EINVAL; 2969e054ec2SFabien DESSENNE 2979e054ec2SFabien DESSENNE while (sg) { 2989e054ec2SFabien DESSENNE if (!IS_ALIGNED(sg->offset, sizeof(u32))) 2999e054ec2SFabien DESSENNE return -EINVAL; 3009e054ec2SFabien DESSENNE 3019e054ec2SFabien DESSENNE if (!IS_ALIGNED(sg->length, align)) 3029e054ec2SFabien DESSENNE return -EINVAL; 3039e054ec2SFabien DESSENNE 3049e054ec2SFabien DESSENNE len += sg->length; 3059e054ec2SFabien DESSENNE sg = sg_next(sg); 3069e054ec2SFabien DESSENNE } 3079e054ec2SFabien DESSENNE 3089e054ec2SFabien DESSENNE if (len != total) 3099e054ec2SFabien DESSENNE return -EINVAL; 3109e054ec2SFabien DESSENNE 3119e054ec2SFabien DESSENNE return 0; 3129e054ec2SFabien DESSENNE } 3139e054ec2SFabien DESSENNE 3149e054ec2SFabien DESSENNE static int stm32_cryp_check_io_aligned(struct stm32_cryp *cryp) 3159e054ec2SFabien DESSENNE { 3169e054ec2SFabien DESSENNE int ret; 3179e054ec2SFabien DESSENNE 3189e054ec2SFabien DESSENNE ret = stm32_cryp_check_aligned(cryp->in_sg, cryp->total_in, 3199e054ec2SFabien DESSENNE cryp->hw_blocksize); 3209e054ec2SFabien DESSENNE if (ret) 3219e054ec2SFabien DESSENNE return ret; 3229e054ec2SFabien DESSENNE 3239e054ec2SFabien DESSENNE ret = stm32_cryp_check_aligned(cryp->out_sg, cryp->total_out, 3249e054ec2SFabien DESSENNE cryp->hw_blocksize); 3259e054ec2SFabien DESSENNE 3269e054ec2SFabien DESSENNE return ret; 3279e054ec2SFabien DESSENNE } 3289e054ec2SFabien DESSENNE 3299e054ec2SFabien DESSENNE static void sg_copy_buf(void *buf, struct scatterlist *sg, 3309e054ec2SFabien DESSENNE unsigned int start, unsigned int nbytes, int out) 3319e054ec2SFabien DESSENNE { 3329e054ec2SFabien DESSENNE struct scatter_walk walk; 3339e054ec2SFabien DESSENNE 3349e054ec2SFabien DESSENNE if (!nbytes) 3359e054ec2SFabien DESSENNE return; 3369e054ec2SFabien DESSENNE 3379e054ec2SFabien DESSENNE scatterwalk_start(&walk, sg); 3389e054ec2SFabien DESSENNE scatterwalk_advance(&walk, start); 3399e054ec2SFabien DESSENNE scatterwalk_copychunks(buf, &walk, nbytes, out); 3409e054ec2SFabien DESSENNE scatterwalk_done(&walk, out, 0); 3419e054ec2SFabien DESSENNE } 3429e054ec2SFabien DESSENNE 3439e054ec2SFabien DESSENNE static int stm32_cryp_copy_sgs(struct stm32_cryp *cryp) 3449e054ec2SFabien DESSENNE { 3459e054ec2SFabien DESSENNE void *buf_in, *buf_out; 3469e054ec2SFabien DESSENNE int pages, total_in, total_out; 3479e054ec2SFabien DESSENNE 3489e054ec2SFabien DESSENNE if (!stm32_cryp_check_io_aligned(cryp)) { 3499e054ec2SFabien DESSENNE cryp->sgs_copied = 0; 3509e054ec2SFabien DESSENNE return 0; 3519e054ec2SFabien DESSENNE } 3529e054ec2SFabien DESSENNE 3539e054ec2SFabien DESSENNE total_in = ALIGN(cryp->total_in, cryp->hw_blocksize); 3549e054ec2SFabien DESSENNE pages = total_in ? get_order(total_in) : 1; 3559e054ec2SFabien DESSENNE buf_in = (void *)__get_free_pages(GFP_ATOMIC, pages); 3569e054ec2SFabien DESSENNE 3579e054ec2SFabien DESSENNE total_out = ALIGN(cryp->total_out, cryp->hw_blocksize); 3589e054ec2SFabien DESSENNE pages = total_out ? get_order(total_out) : 1; 3599e054ec2SFabien DESSENNE buf_out = (void *)__get_free_pages(GFP_ATOMIC, pages); 3609e054ec2SFabien DESSENNE 3619e054ec2SFabien DESSENNE if (!buf_in || !buf_out) { 3629e054ec2SFabien DESSENNE dev_err(cryp->dev, "Can't allocate pages when unaligned\n"); 3639e054ec2SFabien DESSENNE cryp->sgs_copied = 0; 3649e054ec2SFabien DESSENNE return -EFAULT; 3659e054ec2SFabien DESSENNE } 3669e054ec2SFabien DESSENNE 3679e054ec2SFabien DESSENNE sg_copy_buf(buf_in, cryp->in_sg, 0, cryp->total_in, 0); 3689e054ec2SFabien DESSENNE 3699e054ec2SFabien DESSENNE sg_init_one(&cryp->in_sgl, buf_in, total_in); 3709e054ec2SFabien DESSENNE cryp->in_sg = &cryp->in_sgl; 3719e054ec2SFabien DESSENNE cryp->in_sg_len = 1; 3729e054ec2SFabien DESSENNE 3739e054ec2SFabien DESSENNE sg_init_one(&cryp->out_sgl, buf_out, total_out); 3749e054ec2SFabien DESSENNE cryp->out_sg_save = cryp->out_sg; 3759e054ec2SFabien DESSENNE cryp->out_sg = &cryp->out_sgl; 3769e054ec2SFabien DESSENNE cryp->out_sg_len = 1; 3779e054ec2SFabien DESSENNE 3789e054ec2SFabien DESSENNE cryp->sgs_copied = 1; 3799e054ec2SFabien DESSENNE 3809e054ec2SFabien DESSENNE return 0; 3819e054ec2SFabien DESSENNE } 3829e054ec2SFabien DESSENNE 383*bbb28326SHerbert Xu static void stm32_cryp_hw_write_iv(struct stm32_cryp *cryp, __be32 *iv) 3849e054ec2SFabien DESSENNE { 3859e054ec2SFabien DESSENNE if (!iv) 3869e054ec2SFabien DESSENNE return; 3879e054ec2SFabien DESSENNE 388*bbb28326SHerbert Xu stm32_cryp_write(cryp, CRYP_IV0LR, be32_to_cpu(*iv++)); 389*bbb28326SHerbert Xu stm32_cryp_write(cryp, CRYP_IV0RR, be32_to_cpu(*iv++)); 3909e054ec2SFabien DESSENNE 3919e054ec2SFabien DESSENNE if (is_aes(cryp)) { 392*bbb28326SHerbert Xu stm32_cryp_write(cryp, CRYP_IV1LR, be32_to_cpu(*iv++)); 393*bbb28326SHerbert Xu stm32_cryp_write(cryp, CRYP_IV1RR, be32_to_cpu(*iv++)); 3949e054ec2SFabien DESSENNE } 3959e054ec2SFabien DESSENNE } 3969e054ec2SFabien DESSENNE 3975f49f18dSLionel Debieve static void stm32_cryp_get_iv(struct stm32_cryp *cryp) 3985f49f18dSLionel Debieve { 39947ece481SArd Biesheuvel struct skcipher_request *req = cryp->req; 400*bbb28326SHerbert Xu __be32 *tmp = (void *)req->iv; 4015f49f18dSLionel Debieve 4025f49f18dSLionel Debieve if (!tmp) 4035f49f18dSLionel Debieve return; 4045f49f18dSLionel Debieve 4055f49f18dSLionel Debieve *tmp++ = cpu_to_be32(stm32_cryp_read(cryp, CRYP_IV0LR)); 4065f49f18dSLionel Debieve *tmp++ = cpu_to_be32(stm32_cryp_read(cryp, CRYP_IV0RR)); 4075f49f18dSLionel Debieve 4085f49f18dSLionel Debieve if (is_aes(cryp)) { 4095f49f18dSLionel Debieve *tmp++ = cpu_to_be32(stm32_cryp_read(cryp, CRYP_IV1LR)); 4105f49f18dSLionel Debieve *tmp++ = cpu_to_be32(stm32_cryp_read(cryp, CRYP_IV1RR)); 4115f49f18dSLionel Debieve } 4125f49f18dSLionel Debieve } 4135f49f18dSLionel Debieve 4149e054ec2SFabien DESSENNE static void stm32_cryp_hw_write_key(struct stm32_cryp *c) 4159e054ec2SFabien DESSENNE { 4169e054ec2SFabien DESSENNE unsigned int i; 4179e054ec2SFabien DESSENNE int r_id; 4189e054ec2SFabien DESSENNE 4199e054ec2SFabien DESSENNE if (is_des(c)) { 420*bbb28326SHerbert Xu stm32_cryp_write(c, CRYP_K1LR, be32_to_cpu(c->ctx->key[0])); 421*bbb28326SHerbert Xu stm32_cryp_write(c, CRYP_K1RR, be32_to_cpu(c->ctx->key[1])); 4229e054ec2SFabien DESSENNE } else { 4239e054ec2SFabien DESSENNE r_id = CRYP_K3RR; 4249e054ec2SFabien DESSENNE for (i = c->ctx->keylen / sizeof(u32); i > 0; i--, r_id -= 4) 4259e054ec2SFabien DESSENNE stm32_cryp_write(c, r_id, 426*bbb28326SHerbert Xu be32_to_cpu(c->ctx->key[i - 1])); 4279e054ec2SFabien DESSENNE } 4289e054ec2SFabien DESSENNE } 4299e054ec2SFabien DESSENNE 4309e054ec2SFabien DESSENNE static u32 stm32_cryp_get_hw_mode(struct stm32_cryp *cryp) 4319e054ec2SFabien DESSENNE { 4329e054ec2SFabien DESSENNE if (is_aes(cryp) && is_ecb(cryp)) 4339e054ec2SFabien DESSENNE return CR_AES_ECB; 4349e054ec2SFabien DESSENNE 4359e054ec2SFabien DESSENNE if (is_aes(cryp) && is_cbc(cryp)) 4369e054ec2SFabien DESSENNE return CR_AES_CBC; 4379e054ec2SFabien DESSENNE 4389e054ec2SFabien DESSENNE if (is_aes(cryp) && is_ctr(cryp)) 4399e054ec2SFabien DESSENNE return CR_AES_CTR; 4409e054ec2SFabien DESSENNE 4419d3b5030SFabien DESSENNE if (is_aes(cryp) && is_gcm(cryp)) 4429d3b5030SFabien DESSENNE return CR_AES_GCM; 4439d3b5030SFabien DESSENNE 4449d3b5030SFabien DESSENNE if (is_aes(cryp) && is_ccm(cryp)) 4459d3b5030SFabien DESSENNE return CR_AES_CCM; 4469d3b5030SFabien DESSENNE 4479e054ec2SFabien DESSENNE if (is_des(cryp) && is_ecb(cryp)) 4489e054ec2SFabien DESSENNE return CR_DES_ECB; 4499e054ec2SFabien DESSENNE 4509e054ec2SFabien DESSENNE if (is_des(cryp) && is_cbc(cryp)) 4519e054ec2SFabien DESSENNE return CR_DES_CBC; 4529e054ec2SFabien DESSENNE 4539e054ec2SFabien DESSENNE if (is_tdes(cryp) && is_ecb(cryp)) 4549e054ec2SFabien DESSENNE return CR_TDES_ECB; 4559e054ec2SFabien DESSENNE 4569e054ec2SFabien DESSENNE if (is_tdes(cryp) && is_cbc(cryp)) 4579e054ec2SFabien DESSENNE return CR_TDES_CBC; 4589e054ec2SFabien DESSENNE 4599e054ec2SFabien DESSENNE dev_err(cryp->dev, "Unknown mode\n"); 4609e054ec2SFabien DESSENNE return CR_AES_UNKNOWN; 4619e054ec2SFabien DESSENNE } 4629e054ec2SFabien DESSENNE 4639d3b5030SFabien DESSENNE static unsigned int stm32_cryp_get_input_text_len(struct stm32_cryp *cryp) 4649d3b5030SFabien DESSENNE { 4659d3b5030SFabien DESSENNE return is_encrypt(cryp) ? cryp->areq->cryptlen : 4669d3b5030SFabien DESSENNE cryp->areq->cryptlen - cryp->authsize; 4679d3b5030SFabien DESSENNE } 4689d3b5030SFabien DESSENNE 4699d3b5030SFabien DESSENNE static int stm32_cryp_gcm_init(struct stm32_cryp *cryp, u32 cfg) 4709d3b5030SFabien DESSENNE { 4719d3b5030SFabien DESSENNE int ret; 472*bbb28326SHerbert Xu __be32 iv[4]; 4739d3b5030SFabien DESSENNE 4749d3b5030SFabien DESSENNE /* Phase 1 : init */ 4759d3b5030SFabien DESSENNE memcpy(iv, cryp->areq->iv, 12); 4769d3b5030SFabien DESSENNE iv[3] = cpu_to_be32(GCM_CTR_INIT); 4779d3b5030SFabien DESSENNE cryp->gcm_ctr = GCM_CTR_INIT; 4789d3b5030SFabien DESSENNE stm32_cryp_hw_write_iv(cryp, iv); 4799d3b5030SFabien DESSENNE 4809d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_CR, cfg | CR_PH_INIT | CR_CRYPEN); 4819d3b5030SFabien DESSENNE 4829d3b5030SFabien DESSENNE /* Wait for end of processing */ 4839d3b5030SFabien DESSENNE ret = stm32_cryp_wait_enable(cryp); 4849d3b5030SFabien DESSENNE if (ret) 4859d3b5030SFabien DESSENNE dev_err(cryp->dev, "Timeout (gcm init)\n"); 4869d3b5030SFabien DESSENNE 4879d3b5030SFabien DESSENNE return ret; 4889d3b5030SFabien DESSENNE } 4899d3b5030SFabien DESSENNE 4909d3b5030SFabien DESSENNE static int stm32_cryp_ccm_init(struct stm32_cryp *cryp, u32 cfg) 4919d3b5030SFabien DESSENNE { 4929d3b5030SFabien DESSENNE int ret; 4939d3b5030SFabien DESSENNE u8 iv[AES_BLOCK_SIZE], b0[AES_BLOCK_SIZE]; 494*bbb28326SHerbert Xu __be32 *bd; 4959d3b5030SFabien DESSENNE u32 *d; 4969d3b5030SFabien DESSENNE unsigned int i, textlen; 4979d3b5030SFabien DESSENNE 4989d3b5030SFabien DESSENNE /* Phase 1 : init. Firstly set the CTR value to 1 (not 0) */ 4999d3b5030SFabien DESSENNE memcpy(iv, cryp->areq->iv, AES_BLOCK_SIZE); 5009d3b5030SFabien DESSENNE memset(iv + AES_BLOCK_SIZE - 1 - iv[0], 0, iv[0] + 1); 5019d3b5030SFabien DESSENNE iv[AES_BLOCK_SIZE - 1] = 1; 502*bbb28326SHerbert Xu stm32_cryp_hw_write_iv(cryp, (__be32 *)iv); 5039d3b5030SFabien DESSENNE 5049d3b5030SFabien DESSENNE /* Build B0 */ 5059d3b5030SFabien DESSENNE memcpy(b0, iv, AES_BLOCK_SIZE); 5069d3b5030SFabien DESSENNE 5079d3b5030SFabien DESSENNE b0[0] |= (8 * ((cryp->authsize - 2) / 2)); 5089d3b5030SFabien DESSENNE 5099d3b5030SFabien DESSENNE if (cryp->areq->assoclen) 5109d3b5030SFabien DESSENNE b0[0] |= 0x40; 5119d3b5030SFabien DESSENNE 5129d3b5030SFabien DESSENNE textlen = stm32_cryp_get_input_text_len(cryp); 5139d3b5030SFabien DESSENNE 5149d3b5030SFabien DESSENNE b0[AES_BLOCK_SIZE - 2] = textlen >> 8; 5159d3b5030SFabien DESSENNE b0[AES_BLOCK_SIZE - 1] = textlen & 0xFF; 5169d3b5030SFabien DESSENNE 5179d3b5030SFabien DESSENNE /* Enable HW */ 5189d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_CR, cfg | CR_PH_INIT | CR_CRYPEN); 5199d3b5030SFabien DESSENNE 5209d3b5030SFabien DESSENNE /* Write B0 */ 5219d3b5030SFabien DESSENNE d = (u32 *)b0; 522*bbb28326SHerbert Xu bd = (__be32 *)b0; 5239d3b5030SFabien DESSENNE 5249d3b5030SFabien DESSENNE for (i = 0; i < AES_BLOCK_32; i++) { 525*bbb28326SHerbert Xu u32 xd = d[i]; 526*bbb28326SHerbert Xu 5279d3b5030SFabien DESSENNE if (!cryp->caps->padding_wa) 528*bbb28326SHerbert Xu xd = be32_to_cpu(bd[i]); 529*bbb28326SHerbert Xu stm32_cryp_write(cryp, CRYP_DIN, xd); 5309d3b5030SFabien DESSENNE } 5319d3b5030SFabien DESSENNE 5329d3b5030SFabien DESSENNE /* Wait for end of processing */ 5339d3b5030SFabien DESSENNE ret = stm32_cryp_wait_enable(cryp); 5349d3b5030SFabien DESSENNE if (ret) 5359d3b5030SFabien DESSENNE dev_err(cryp->dev, "Timeout (ccm init)\n"); 5369d3b5030SFabien DESSENNE 5379d3b5030SFabien DESSENNE return ret; 5389d3b5030SFabien DESSENNE } 5399d3b5030SFabien DESSENNE 5409e054ec2SFabien DESSENNE static int stm32_cryp_hw_init(struct stm32_cryp *cryp) 5419e054ec2SFabien DESSENNE { 5429e054ec2SFabien DESSENNE int ret; 5439e054ec2SFabien DESSENNE u32 cfg, hw_mode; 5449e054ec2SFabien DESSENNE 54565f9aa36Slionel.debieve@st.com pm_runtime_get_sync(cryp->dev); 54665f9aa36Slionel.debieve@st.com 5479e054ec2SFabien DESSENNE /* Disable interrupt */ 5489e054ec2SFabien DESSENNE stm32_cryp_write(cryp, CRYP_IMSCR, 0); 5499e054ec2SFabien DESSENNE 5509e054ec2SFabien DESSENNE /* Set key */ 5519e054ec2SFabien DESSENNE stm32_cryp_hw_write_key(cryp); 5529e054ec2SFabien DESSENNE 5539e054ec2SFabien DESSENNE /* Set configuration */ 5549e054ec2SFabien DESSENNE cfg = CR_DATA8 | CR_FFLUSH; 5559e054ec2SFabien DESSENNE 5569e054ec2SFabien DESSENNE switch (cryp->ctx->keylen) { 5579e054ec2SFabien DESSENNE case AES_KEYSIZE_128: 5589e054ec2SFabien DESSENNE cfg |= CR_KEY128; 5599e054ec2SFabien DESSENNE break; 5609e054ec2SFabien DESSENNE 5619e054ec2SFabien DESSENNE case AES_KEYSIZE_192: 5629e054ec2SFabien DESSENNE cfg |= CR_KEY192; 5639e054ec2SFabien DESSENNE break; 5649e054ec2SFabien DESSENNE 5659e054ec2SFabien DESSENNE default: 5669e054ec2SFabien DESSENNE case AES_KEYSIZE_256: 5679e054ec2SFabien DESSENNE cfg |= CR_KEY256; 5689e054ec2SFabien DESSENNE break; 5699e054ec2SFabien DESSENNE } 5709e054ec2SFabien DESSENNE 5719e054ec2SFabien DESSENNE hw_mode = stm32_cryp_get_hw_mode(cryp); 5729e054ec2SFabien DESSENNE if (hw_mode == CR_AES_UNKNOWN) 5739e054ec2SFabien DESSENNE return -EINVAL; 5749e054ec2SFabien DESSENNE 5759e054ec2SFabien DESSENNE /* AES ECB/CBC decrypt: run key preparation first */ 5769e054ec2SFabien DESSENNE if (is_decrypt(cryp) && 5779e054ec2SFabien DESSENNE ((hw_mode == CR_AES_ECB) || (hw_mode == CR_AES_CBC))) { 5789e054ec2SFabien DESSENNE stm32_cryp_write(cryp, CRYP_CR, cfg | CR_AES_KP | CR_CRYPEN); 5799e054ec2SFabien DESSENNE 5809e054ec2SFabien DESSENNE /* Wait for end of processing */ 5819e054ec2SFabien DESSENNE ret = stm32_cryp_wait_busy(cryp); 5829e054ec2SFabien DESSENNE if (ret) { 5839e054ec2SFabien DESSENNE dev_err(cryp->dev, "Timeout (key preparation)\n"); 5849e054ec2SFabien DESSENNE return ret; 5859e054ec2SFabien DESSENNE } 5869e054ec2SFabien DESSENNE } 5879e054ec2SFabien DESSENNE 5889e054ec2SFabien DESSENNE cfg |= hw_mode; 5899e054ec2SFabien DESSENNE 5909e054ec2SFabien DESSENNE if (is_decrypt(cryp)) 5919e054ec2SFabien DESSENNE cfg |= CR_DEC_NOT_ENC; 5929e054ec2SFabien DESSENNE 5939e054ec2SFabien DESSENNE /* Apply config and flush (valid when CRYPEN = 0) */ 5949e054ec2SFabien DESSENNE stm32_cryp_write(cryp, CRYP_CR, cfg); 5959e054ec2SFabien DESSENNE 5969e054ec2SFabien DESSENNE switch (hw_mode) { 5979d3b5030SFabien DESSENNE case CR_AES_GCM: 5989d3b5030SFabien DESSENNE case CR_AES_CCM: 5999d3b5030SFabien DESSENNE /* Phase 1 : init */ 6009d3b5030SFabien DESSENNE if (hw_mode == CR_AES_CCM) 6019d3b5030SFabien DESSENNE ret = stm32_cryp_ccm_init(cryp, cfg); 6029d3b5030SFabien DESSENNE else 6039d3b5030SFabien DESSENNE ret = stm32_cryp_gcm_init(cryp, cfg); 6049d3b5030SFabien DESSENNE 6059d3b5030SFabien DESSENNE if (ret) 6069d3b5030SFabien DESSENNE return ret; 6079d3b5030SFabien DESSENNE 6089d3b5030SFabien DESSENNE /* Phase 2 : header (authenticated data) */ 6099d3b5030SFabien DESSENNE if (cryp->areq->assoclen) { 6109d3b5030SFabien DESSENNE cfg |= CR_PH_HEADER; 6119d3b5030SFabien DESSENNE } else if (stm32_cryp_get_input_text_len(cryp)) { 6129d3b5030SFabien DESSENNE cfg |= CR_PH_PAYLOAD; 6139d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_CR, cfg); 6149d3b5030SFabien DESSENNE } else { 6159d3b5030SFabien DESSENNE cfg |= CR_PH_INIT; 6169d3b5030SFabien DESSENNE } 6179d3b5030SFabien DESSENNE 6189d3b5030SFabien DESSENNE break; 6199d3b5030SFabien DESSENNE 6209e054ec2SFabien DESSENNE case CR_DES_CBC: 6219e054ec2SFabien DESSENNE case CR_TDES_CBC: 6229e054ec2SFabien DESSENNE case CR_AES_CBC: 6239e054ec2SFabien DESSENNE case CR_AES_CTR: 624*bbb28326SHerbert Xu stm32_cryp_hw_write_iv(cryp, (__be32 *)cryp->req->iv); 6259e054ec2SFabien DESSENNE break; 6269e054ec2SFabien DESSENNE 6279e054ec2SFabien DESSENNE default: 6289e054ec2SFabien DESSENNE break; 6299e054ec2SFabien DESSENNE } 6309e054ec2SFabien DESSENNE 6319e054ec2SFabien DESSENNE /* Enable now */ 6329e054ec2SFabien DESSENNE cfg |= CR_CRYPEN; 6339e054ec2SFabien DESSENNE 6349e054ec2SFabien DESSENNE stm32_cryp_write(cryp, CRYP_CR, cfg); 6359e054ec2SFabien DESSENNE 6369d3b5030SFabien DESSENNE cryp->flags &= ~FLG_CCM_PADDED_WA; 6379d3b5030SFabien DESSENNE 6389e054ec2SFabien DESSENNE return 0; 6399e054ec2SFabien DESSENNE } 6409e054ec2SFabien DESSENNE 6419d3b5030SFabien DESSENNE static void stm32_cryp_finish_req(struct stm32_cryp *cryp, int err) 6429e054ec2SFabien DESSENNE { 6439d3b5030SFabien DESSENNE if (!err && (is_gcm(cryp) || is_ccm(cryp))) 6449d3b5030SFabien DESSENNE /* Phase 4 : output tag */ 6459d3b5030SFabien DESSENNE err = stm32_cryp_read_auth_tag(cryp); 6469e054ec2SFabien DESSENNE 6475f49f18dSLionel Debieve if (!err && (!(is_gcm(cryp) || is_ccm(cryp)))) 6485f49f18dSLionel Debieve stm32_cryp_get_iv(cryp); 6495f49f18dSLionel Debieve 6509e054ec2SFabien DESSENNE if (cryp->sgs_copied) { 6519e054ec2SFabien DESSENNE void *buf_in, *buf_out; 6529e054ec2SFabien DESSENNE int pages, len; 6539e054ec2SFabien DESSENNE 6549e054ec2SFabien DESSENNE buf_in = sg_virt(&cryp->in_sgl); 6559e054ec2SFabien DESSENNE buf_out = sg_virt(&cryp->out_sgl); 6569e054ec2SFabien DESSENNE 6579e054ec2SFabien DESSENNE sg_copy_buf(buf_out, cryp->out_sg_save, 0, 6589e054ec2SFabien DESSENNE cryp->total_out_save, 1); 6599e054ec2SFabien DESSENNE 6609e054ec2SFabien DESSENNE len = ALIGN(cryp->total_in_save, cryp->hw_blocksize); 6619e054ec2SFabien DESSENNE pages = len ? get_order(len) : 1; 6629e054ec2SFabien DESSENNE free_pages((unsigned long)buf_in, pages); 6639e054ec2SFabien DESSENNE 6649e054ec2SFabien DESSENNE len = ALIGN(cryp->total_out_save, cryp->hw_blocksize); 6659e054ec2SFabien DESSENNE pages = len ? get_order(len) : 1; 6669e054ec2SFabien DESSENNE free_pages((unsigned long)buf_out, pages); 6679e054ec2SFabien DESSENNE } 6689e054ec2SFabien DESSENNE 66965f9aa36Slionel.debieve@st.com pm_runtime_mark_last_busy(cryp->dev); 67065f9aa36Slionel.debieve@st.com pm_runtime_put_autosuspend(cryp->dev); 67165f9aa36Slionel.debieve@st.com 67229aed438SLionel Debieve if (is_gcm(cryp) || is_ccm(cryp)) 6739d3b5030SFabien DESSENNE crypto_finalize_aead_request(cryp->engine, cryp->areq, err); 67429aed438SLionel Debieve else 67547ece481SArd Biesheuvel crypto_finalize_skcipher_request(cryp->engine, cryp->req, 6769d3b5030SFabien DESSENNE err); 6779e054ec2SFabien DESSENNE 6789e054ec2SFabien DESSENNE memset(cryp->ctx->key, 0, cryp->ctx->keylen); 6799e054ec2SFabien DESSENNE } 6809e054ec2SFabien DESSENNE 6819e054ec2SFabien DESSENNE static int stm32_cryp_cpu_start(struct stm32_cryp *cryp) 6829e054ec2SFabien DESSENNE { 6839e054ec2SFabien DESSENNE /* Enable interrupt and let the IRQ handler do everything */ 6849e054ec2SFabien DESSENNE stm32_cryp_write(cryp, CRYP_IMSCR, IMSCR_IN | IMSCR_OUT); 6859e054ec2SFabien DESSENNE 6869e054ec2SFabien DESSENNE return 0; 6879e054ec2SFabien DESSENNE } 6889e054ec2SFabien DESSENNE 689dc7bcef5SCorentin LABBE static int stm32_cryp_cipher_one_req(struct crypto_engine *engine, void *areq); 690dc7bcef5SCorentin LABBE static int stm32_cryp_prepare_cipher_req(struct crypto_engine *engine, 691dc7bcef5SCorentin LABBE void *areq); 692dc7bcef5SCorentin LABBE 69347ece481SArd Biesheuvel static int stm32_cryp_init_tfm(struct crypto_skcipher *tfm) 6949e054ec2SFabien DESSENNE { 69547ece481SArd Biesheuvel struct stm32_cryp_ctx *ctx = crypto_skcipher_ctx(tfm); 696dc7bcef5SCorentin LABBE 69747ece481SArd Biesheuvel crypto_skcipher_set_reqsize(tfm, sizeof(struct stm32_cryp_reqctx)); 6989e054ec2SFabien DESSENNE 699dc7bcef5SCorentin LABBE ctx->enginectx.op.do_one_request = stm32_cryp_cipher_one_req; 700dc7bcef5SCorentin LABBE ctx->enginectx.op.prepare_request = stm32_cryp_prepare_cipher_req; 701dc7bcef5SCorentin LABBE ctx->enginectx.op.unprepare_request = NULL; 7029e054ec2SFabien DESSENNE return 0; 7039e054ec2SFabien DESSENNE } 7049e054ec2SFabien DESSENNE 7059d3b5030SFabien DESSENNE static int stm32_cryp_aead_one_req(struct crypto_engine *engine, void *areq); 7069d3b5030SFabien DESSENNE static int stm32_cryp_prepare_aead_req(struct crypto_engine *engine, 7079d3b5030SFabien DESSENNE void *areq); 7089d3b5030SFabien DESSENNE 7099d3b5030SFabien DESSENNE static int stm32_cryp_aes_aead_init(struct crypto_aead *tfm) 7109d3b5030SFabien DESSENNE { 7119d3b5030SFabien DESSENNE struct stm32_cryp_ctx *ctx = crypto_aead_ctx(tfm); 7129d3b5030SFabien DESSENNE 7139d3b5030SFabien DESSENNE tfm->reqsize = sizeof(struct stm32_cryp_reqctx); 7149d3b5030SFabien DESSENNE 7159d3b5030SFabien DESSENNE ctx->enginectx.op.do_one_request = stm32_cryp_aead_one_req; 7169d3b5030SFabien DESSENNE ctx->enginectx.op.prepare_request = stm32_cryp_prepare_aead_req; 7179d3b5030SFabien DESSENNE ctx->enginectx.op.unprepare_request = NULL; 7189d3b5030SFabien DESSENNE 7199d3b5030SFabien DESSENNE return 0; 7209d3b5030SFabien DESSENNE } 7219d3b5030SFabien DESSENNE 72247ece481SArd Biesheuvel static int stm32_cryp_crypt(struct skcipher_request *req, unsigned long mode) 7239e054ec2SFabien DESSENNE { 72447ece481SArd Biesheuvel struct stm32_cryp_ctx *ctx = crypto_skcipher_ctx( 72547ece481SArd Biesheuvel crypto_skcipher_reqtfm(req)); 72647ece481SArd Biesheuvel struct stm32_cryp_reqctx *rctx = skcipher_request_ctx(req); 7279e054ec2SFabien DESSENNE struct stm32_cryp *cryp = stm32_cryp_find_dev(ctx); 7289e054ec2SFabien DESSENNE 7299e054ec2SFabien DESSENNE if (!cryp) 7309e054ec2SFabien DESSENNE return -ENODEV; 7319e054ec2SFabien DESSENNE 7329e054ec2SFabien DESSENNE rctx->mode = mode; 7339e054ec2SFabien DESSENNE 73447ece481SArd Biesheuvel return crypto_transfer_skcipher_request_to_engine(cryp->engine, req); 7359e054ec2SFabien DESSENNE } 7369e054ec2SFabien DESSENNE 7379d3b5030SFabien DESSENNE static int stm32_cryp_aead_crypt(struct aead_request *req, unsigned long mode) 7389d3b5030SFabien DESSENNE { 7399d3b5030SFabien DESSENNE struct stm32_cryp_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); 7409d3b5030SFabien DESSENNE struct stm32_cryp_reqctx *rctx = aead_request_ctx(req); 7419d3b5030SFabien DESSENNE struct stm32_cryp *cryp = stm32_cryp_find_dev(ctx); 7429d3b5030SFabien DESSENNE 7439d3b5030SFabien DESSENNE if (!cryp) 7449d3b5030SFabien DESSENNE return -ENODEV; 7459d3b5030SFabien DESSENNE 7469d3b5030SFabien DESSENNE rctx->mode = mode; 7479d3b5030SFabien DESSENNE 7489d3b5030SFabien DESSENNE return crypto_transfer_aead_request_to_engine(cryp->engine, req); 7499d3b5030SFabien DESSENNE } 7509d3b5030SFabien DESSENNE 75147ece481SArd Biesheuvel static int stm32_cryp_setkey(struct crypto_skcipher *tfm, const u8 *key, 7529e054ec2SFabien DESSENNE unsigned int keylen) 7539e054ec2SFabien DESSENNE { 75447ece481SArd Biesheuvel struct stm32_cryp_ctx *ctx = crypto_skcipher_ctx(tfm); 7559e054ec2SFabien DESSENNE 7569e054ec2SFabien DESSENNE memcpy(ctx->key, key, keylen); 7579e054ec2SFabien DESSENNE ctx->keylen = keylen; 7589e054ec2SFabien DESSENNE 7599e054ec2SFabien DESSENNE return 0; 7609e054ec2SFabien DESSENNE } 7619e054ec2SFabien DESSENNE 76247ece481SArd Biesheuvel static int stm32_cryp_aes_setkey(struct crypto_skcipher *tfm, const u8 *key, 7639e054ec2SFabien DESSENNE unsigned int keylen) 7649e054ec2SFabien DESSENNE { 7659e054ec2SFabien DESSENNE if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_192 && 7669e054ec2SFabien DESSENNE keylen != AES_KEYSIZE_256) 7679e054ec2SFabien DESSENNE return -EINVAL; 7689e054ec2SFabien DESSENNE else 7699e054ec2SFabien DESSENNE return stm32_cryp_setkey(tfm, key, keylen); 7709e054ec2SFabien DESSENNE } 7719e054ec2SFabien DESSENNE 77247ece481SArd Biesheuvel static int stm32_cryp_des_setkey(struct crypto_skcipher *tfm, const u8 *key, 7739e054ec2SFabien DESSENNE unsigned int keylen) 7749e054ec2SFabien DESSENNE { 77547ece481SArd Biesheuvel return verify_skcipher_des_key(tfm, key) ?: 776b5d0ba83SArd Biesheuvel stm32_cryp_setkey(tfm, key, keylen); 7779e054ec2SFabien DESSENNE } 7789e054ec2SFabien DESSENNE 77947ece481SArd Biesheuvel static int stm32_cryp_tdes_setkey(struct crypto_skcipher *tfm, const u8 *key, 7809e054ec2SFabien DESSENNE unsigned int keylen) 7819e054ec2SFabien DESSENNE { 78247ece481SArd Biesheuvel return verify_skcipher_des3_key(tfm, key) ?: 783b5d0ba83SArd Biesheuvel stm32_cryp_setkey(tfm, key, keylen); 7849e054ec2SFabien DESSENNE } 7859e054ec2SFabien DESSENNE 7869d3b5030SFabien DESSENNE static int stm32_cryp_aes_aead_setkey(struct crypto_aead *tfm, const u8 *key, 7879d3b5030SFabien DESSENNE unsigned int keylen) 7889d3b5030SFabien DESSENNE { 7899d3b5030SFabien DESSENNE struct stm32_cryp_ctx *ctx = crypto_aead_ctx(tfm); 7909d3b5030SFabien DESSENNE 7919d3b5030SFabien DESSENNE if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_192 && 7929d3b5030SFabien DESSENNE keylen != AES_KEYSIZE_256) 7939d3b5030SFabien DESSENNE return -EINVAL; 7949d3b5030SFabien DESSENNE 7959d3b5030SFabien DESSENNE memcpy(ctx->key, key, keylen); 7969d3b5030SFabien DESSENNE ctx->keylen = keylen; 7979d3b5030SFabien DESSENNE 7989d3b5030SFabien DESSENNE return 0; 7999d3b5030SFabien DESSENNE } 8009d3b5030SFabien DESSENNE 8019d3b5030SFabien DESSENNE static int stm32_cryp_aes_gcm_setauthsize(struct crypto_aead *tfm, 8029d3b5030SFabien DESSENNE unsigned int authsize) 8039d3b5030SFabien DESSENNE { 8049d3b5030SFabien DESSENNE return authsize == AES_BLOCK_SIZE ? 0 : -EINVAL; 8059d3b5030SFabien DESSENNE } 8069d3b5030SFabien DESSENNE 8079d3b5030SFabien DESSENNE static int stm32_cryp_aes_ccm_setauthsize(struct crypto_aead *tfm, 8089d3b5030SFabien DESSENNE unsigned int authsize) 8099d3b5030SFabien DESSENNE { 8109d3b5030SFabien DESSENNE switch (authsize) { 8119d3b5030SFabien DESSENNE case 4: 8129d3b5030SFabien DESSENNE case 6: 8139d3b5030SFabien DESSENNE case 8: 8149d3b5030SFabien DESSENNE case 10: 8159d3b5030SFabien DESSENNE case 12: 8169d3b5030SFabien DESSENNE case 14: 8179d3b5030SFabien DESSENNE case 16: 8189d3b5030SFabien DESSENNE break; 8199d3b5030SFabien DESSENNE default: 8209d3b5030SFabien DESSENNE return -EINVAL; 8219d3b5030SFabien DESSENNE } 8229d3b5030SFabien DESSENNE 8239d3b5030SFabien DESSENNE return 0; 8249d3b5030SFabien DESSENNE } 8259d3b5030SFabien DESSENNE 82647ece481SArd Biesheuvel static int stm32_cryp_aes_ecb_encrypt(struct skcipher_request *req) 8279e054ec2SFabien DESSENNE { 8289e054ec2SFabien DESSENNE return stm32_cryp_crypt(req, FLG_AES | FLG_ECB | FLG_ENCRYPT); 8299e054ec2SFabien DESSENNE } 8309e054ec2SFabien DESSENNE 83147ece481SArd Biesheuvel static int stm32_cryp_aes_ecb_decrypt(struct skcipher_request *req) 8329e054ec2SFabien DESSENNE { 8339e054ec2SFabien DESSENNE return stm32_cryp_crypt(req, FLG_AES | FLG_ECB); 8349e054ec2SFabien DESSENNE } 8359e054ec2SFabien DESSENNE 83647ece481SArd Biesheuvel static int stm32_cryp_aes_cbc_encrypt(struct skcipher_request *req) 8379e054ec2SFabien DESSENNE { 8389e054ec2SFabien DESSENNE return stm32_cryp_crypt(req, FLG_AES | FLG_CBC | FLG_ENCRYPT); 8399e054ec2SFabien DESSENNE } 8409e054ec2SFabien DESSENNE 84147ece481SArd Biesheuvel static int stm32_cryp_aes_cbc_decrypt(struct skcipher_request *req) 8429e054ec2SFabien DESSENNE { 8439e054ec2SFabien DESSENNE return stm32_cryp_crypt(req, FLG_AES | FLG_CBC); 8449e054ec2SFabien DESSENNE } 8459e054ec2SFabien DESSENNE 84647ece481SArd Biesheuvel static int stm32_cryp_aes_ctr_encrypt(struct skcipher_request *req) 8479e054ec2SFabien DESSENNE { 8489e054ec2SFabien DESSENNE return stm32_cryp_crypt(req, FLG_AES | FLG_CTR | FLG_ENCRYPT); 8499e054ec2SFabien DESSENNE } 8509e054ec2SFabien DESSENNE 85147ece481SArd Biesheuvel static int stm32_cryp_aes_ctr_decrypt(struct skcipher_request *req) 8529e054ec2SFabien DESSENNE { 8539e054ec2SFabien DESSENNE return stm32_cryp_crypt(req, FLG_AES | FLG_CTR); 8549e054ec2SFabien DESSENNE } 8559e054ec2SFabien DESSENNE 8569d3b5030SFabien DESSENNE static int stm32_cryp_aes_gcm_encrypt(struct aead_request *req) 8579d3b5030SFabien DESSENNE { 8589d3b5030SFabien DESSENNE return stm32_cryp_aead_crypt(req, FLG_AES | FLG_GCM | FLG_ENCRYPT); 8599d3b5030SFabien DESSENNE } 8609d3b5030SFabien DESSENNE 8619d3b5030SFabien DESSENNE static int stm32_cryp_aes_gcm_decrypt(struct aead_request *req) 8629d3b5030SFabien DESSENNE { 8639d3b5030SFabien DESSENNE return stm32_cryp_aead_crypt(req, FLG_AES | FLG_GCM); 8649d3b5030SFabien DESSENNE } 8659d3b5030SFabien DESSENNE 8669d3b5030SFabien DESSENNE static int stm32_cryp_aes_ccm_encrypt(struct aead_request *req) 8679d3b5030SFabien DESSENNE { 8689d3b5030SFabien DESSENNE return stm32_cryp_aead_crypt(req, FLG_AES | FLG_CCM | FLG_ENCRYPT); 8699d3b5030SFabien DESSENNE } 8709d3b5030SFabien DESSENNE 8719d3b5030SFabien DESSENNE static int stm32_cryp_aes_ccm_decrypt(struct aead_request *req) 8729d3b5030SFabien DESSENNE { 8739d3b5030SFabien DESSENNE return stm32_cryp_aead_crypt(req, FLG_AES | FLG_CCM); 8749d3b5030SFabien DESSENNE } 8759d3b5030SFabien DESSENNE 87647ece481SArd Biesheuvel static int stm32_cryp_des_ecb_encrypt(struct skcipher_request *req) 8779e054ec2SFabien DESSENNE { 8789e054ec2SFabien DESSENNE return stm32_cryp_crypt(req, FLG_DES | FLG_ECB | FLG_ENCRYPT); 8799e054ec2SFabien DESSENNE } 8809e054ec2SFabien DESSENNE 88147ece481SArd Biesheuvel static int stm32_cryp_des_ecb_decrypt(struct skcipher_request *req) 8829e054ec2SFabien DESSENNE { 8839e054ec2SFabien DESSENNE return stm32_cryp_crypt(req, FLG_DES | FLG_ECB); 8849e054ec2SFabien DESSENNE } 8859e054ec2SFabien DESSENNE 88647ece481SArd Biesheuvel static int stm32_cryp_des_cbc_encrypt(struct skcipher_request *req) 8879e054ec2SFabien DESSENNE { 8889e054ec2SFabien DESSENNE return stm32_cryp_crypt(req, FLG_DES | FLG_CBC | FLG_ENCRYPT); 8899e054ec2SFabien DESSENNE } 8909e054ec2SFabien DESSENNE 89147ece481SArd Biesheuvel static int stm32_cryp_des_cbc_decrypt(struct skcipher_request *req) 8929e054ec2SFabien DESSENNE { 8939e054ec2SFabien DESSENNE return stm32_cryp_crypt(req, FLG_DES | FLG_CBC); 8949e054ec2SFabien DESSENNE } 8959e054ec2SFabien DESSENNE 89647ece481SArd Biesheuvel static int stm32_cryp_tdes_ecb_encrypt(struct skcipher_request *req) 8979e054ec2SFabien DESSENNE { 8989e054ec2SFabien DESSENNE return stm32_cryp_crypt(req, FLG_TDES | FLG_ECB | FLG_ENCRYPT); 8999e054ec2SFabien DESSENNE } 9009e054ec2SFabien DESSENNE 90147ece481SArd Biesheuvel static int stm32_cryp_tdes_ecb_decrypt(struct skcipher_request *req) 9029e054ec2SFabien DESSENNE { 9039e054ec2SFabien DESSENNE return stm32_cryp_crypt(req, FLG_TDES | FLG_ECB); 9049e054ec2SFabien DESSENNE } 9059e054ec2SFabien DESSENNE 90647ece481SArd Biesheuvel static int stm32_cryp_tdes_cbc_encrypt(struct skcipher_request *req) 9079e054ec2SFabien DESSENNE { 9089e054ec2SFabien DESSENNE return stm32_cryp_crypt(req, FLG_TDES | FLG_CBC | FLG_ENCRYPT); 9099e054ec2SFabien DESSENNE } 9109e054ec2SFabien DESSENNE 91147ece481SArd Biesheuvel static int stm32_cryp_tdes_cbc_decrypt(struct skcipher_request *req) 9129e054ec2SFabien DESSENNE { 9139e054ec2SFabien DESSENNE return stm32_cryp_crypt(req, FLG_TDES | FLG_CBC); 9149e054ec2SFabien DESSENNE } 9159e054ec2SFabien DESSENNE 91647ece481SArd Biesheuvel static int stm32_cryp_prepare_req(struct skcipher_request *req, 9179d3b5030SFabien DESSENNE struct aead_request *areq) 9189e054ec2SFabien DESSENNE { 9199e054ec2SFabien DESSENNE struct stm32_cryp_ctx *ctx; 9209e054ec2SFabien DESSENNE struct stm32_cryp *cryp; 9219e054ec2SFabien DESSENNE struct stm32_cryp_reqctx *rctx; 9229e054ec2SFabien DESSENNE int ret; 9239e054ec2SFabien DESSENNE 9249d3b5030SFabien DESSENNE if (!req && !areq) 9259e054ec2SFabien DESSENNE return -EINVAL; 9269e054ec2SFabien DESSENNE 92747ece481SArd Biesheuvel ctx = req ? crypto_skcipher_ctx(crypto_skcipher_reqtfm(req)) : 9289d3b5030SFabien DESSENNE crypto_aead_ctx(crypto_aead_reqtfm(areq)); 9299e054ec2SFabien DESSENNE 9309e054ec2SFabien DESSENNE cryp = ctx->cryp; 9319e054ec2SFabien DESSENNE 9329e054ec2SFabien DESSENNE if (!cryp) 9339e054ec2SFabien DESSENNE return -ENODEV; 9349e054ec2SFabien DESSENNE 93547ece481SArd Biesheuvel rctx = req ? skcipher_request_ctx(req) : aead_request_ctx(areq); 9369e054ec2SFabien DESSENNE rctx->mode &= FLG_MODE_MASK; 9379e054ec2SFabien DESSENNE 9389e054ec2SFabien DESSENNE ctx->cryp = cryp; 9399e054ec2SFabien DESSENNE 9409e054ec2SFabien DESSENNE cryp->flags = (cryp->flags & ~FLG_MODE_MASK) | rctx->mode; 9419e054ec2SFabien DESSENNE cryp->hw_blocksize = is_aes(cryp) ? AES_BLOCK_SIZE : DES_BLOCK_SIZE; 9429e054ec2SFabien DESSENNE cryp->ctx = ctx; 9439e054ec2SFabien DESSENNE 9449d3b5030SFabien DESSENNE if (req) { 9459e054ec2SFabien DESSENNE cryp->req = req; 94629aed438SLionel Debieve cryp->areq = NULL; 94747ece481SArd Biesheuvel cryp->total_in = req->cryptlen; 9489e054ec2SFabien DESSENNE cryp->total_out = cryp->total_in; 9499d3b5030SFabien DESSENNE } else { 9509d3b5030SFabien DESSENNE /* 9519d3b5030SFabien DESSENNE * Length of input and output data: 9529d3b5030SFabien DESSENNE * Encryption case: 9539d3b5030SFabien DESSENNE * INPUT = AssocData || PlainText 9549d3b5030SFabien DESSENNE * <- assoclen -> <- cryptlen -> 9559d3b5030SFabien DESSENNE * <------- total_in -----------> 9569d3b5030SFabien DESSENNE * 9579d3b5030SFabien DESSENNE * OUTPUT = AssocData || CipherText || AuthTag 9589d3b5030SFabien DESSENNE * <- assoclen -> <- cryptlen -> <- authsize -> 9599d3b5030SFabien DESSENNE * <---------------- total_out -----------------> 9609d3b5030SFabien DESSENNE * 9619d3b5030SFabien DESSENNE * Decryption case: 9629d3b5030SFabien DESSENNE * INPUT = AssocData || CipherText || AuthTag 9639d3b5030SFabien DESSENNE * <- assoclen -> <--------- cryptlen ---------> 9649d3b5030SFabien DESSENNE * <- authsize -> 9659d3b5030SFabien DESSENNE * <---------------- total_in ------------------> 9669d3b5030SFabien DESSENNE * 9679d3b5030SFabien DESSENNE * OUTPUT = AssocData || PlainText 9689d3b5030SFabien DESSENNE * <- assoclen -> <- crypten - authsize -> 9699d3b5030SFabien DESSENNE * <---------- total_out -----------------> 9709d3b5030SFabien DESSENNE */ 9719d3b5030SFabien DESSENNE cryp->areq = areq; 97229aed438SLionel Debieve cryp->req = NULL; 9739d3b5030SFabien DESSENNE cryp->authsize = crypto_aead_authsize(crypto_aead_reqtfm(areq)); 9749d3b5030SFabien DESSENNE cryp->total_in = areq->assoclen + areq->cryptlen; 9759d3b5030SFabien DESSENNE if (is_encrypt(cryp)) 9769d3b5030SFabien DESSENNE /* Append auth tag to output */ 9779d3b5030SFabien DESSENNE cryp->total_out = cryp->total_in + cryp->authsize; 9789d3b5030SFabien DESSENNE else 9799d3b5030SFabien DESSENNE /* No auth tag in output */ 9809d3b5030SFabien DESSENNE cryp->total_out = cryp->total_in - cryp->authsize; 9819d3b5030SFabien DESSENNE } 9829e054ec2SFabien DESSENNE 9839e054ec2SFabien DESSENNE cryp->total_in_save = cryp->total_in; 9849e054ec2SFabien DESSENNE cryp->total_out_save = cryp->total_out; 9859e054ec2SFabien DESSENNE 9869d3b5030SFabien DESSENNE cryp->in_sg = req ? req->src : areq->src; 9879d3b5030SFabien DESSENNE cryp->out_sg = req ? req->dst : areq->dst; 9889e054ec2SFabien DESSENNE cryp->out_sg_save = cryp->out_sg; 9899e054ec2SFabien DESSENNE 9909e054ec2SFabien DESSENNE cryp->in_sg_len = sg_nents_for_len(cryp->in_sg, cryp->total_in); 9919e054ec2SFabien DESSENNE if (cryp->in_sg_len < 0) { 9929e054ec2SFabien DESSENNE dev_err(cryp->dev, "Cannot get in_sg_len\n"); 9939e054ec2SFabien DESSENNE ret = cryp->in_sg_len; 99429aed438SLionel Debieve return ret; 9959e054ec2SFabien DESSENNE } 9969e054ec2SFabien DESSENNE 9979e054ec2SFabien DESSENNE cryp->out_sg_len = sg_nents_for_len(cryp->out_sg, cryp->total_out); 9989e054ec2SFabien DESSENNE if (cryp->out_sg_len < 0) { 9999e054ec2SFabien DESSENNE dev_err(cryp->dev, "Cannot get out_sg_len\n"); 10009e054ec2SFabien DESSENNE ret = cryp->out_sg_len; 100129aed438SLionel Debieve return ret; 10029e054ec2SFabien DESSENNE } 10039e054ec2SFabien DESSENNE 10049e054ec2SFabien DESSENNE ret = stm32_cryp_copy_sgs(cryp); 10059e054ec2SFabien DESSENNE if (ret) 100629aed438SLionel Debieve return ret; 10079e054ec2SFabien DESSENNE 10089e054ec2SFabien DESSENNE scatterwalk_start(&cryp->in_walk, cryp->in_sg); 10099e054ec2SFabien DESSENNE scatterwalk_start(&cryp->out_walk, cryp->out_sg); 10109e054ec2SFabien DESSENNE 10119d3b5030SFabien DESSENNE if (is_gcm(cryp) || is_ccm(cryp)) { 10129d3b5030SFabien DESSENNE /* In output, jump after assoc data */ 10139d3b5030SFabien DESSENNE scatterwalk_advance(&cryp->out_walk, cryp->areq->assoclen); 10149d3b5030SFabien DESSENNE cryp->total_out -= cryp->areq->assoclen; 10159d3b5030SFabien DESSENNE } 10169d3b5030SFabien DESSENNE 10179e054ec2SFabien DESSENNE ret = stm32_cryp_hw_init(cryp); 10189e054ec2SFabien DESSENNE return ret; 10199e054ec2SFabien DESSENNE } 10209e054ec2SFabien DESSENNE 10219e054ec2SFabien DESSENNE static int stm32_cryp_prepare_cipher_req(struct crypto_engine *engine, 1022dc7bcef5SCorentin LABBE void *areq) 10239e054ec2SFabien DESSENNE { 102447ece481SArd Biesheuvel struct skcipher_request *req = container_of(areq, 102547ece481SArd Biesheuvel struct skcipher_request, 1026dc7bcef5SCorentin LABBE base); 1027dc7bcef5SCorentin LABBE 10289d3b5030SFabien DESSENNE return stm32_cryp_prepare_req(req, NULL); 10299e054ec2SFabien DESSENNE } 10309e054ec2SFabien DESSENNE 1031dc7bcef5SCorentin LABBE static int stm32_cryp_cipher_one_req(struct crypto_engine *engine, void *areq) 10329e054ec2SFabien DESSENNE { 103347ece481SArd Biesheuvel struct skcipher_request *req = container_of(areq, 103447ece481SArd Biesheuvel struct skcipher_request, 1035dc7bcef5SCorentin LABBE base); 103647ece481SArd Biesheuvel struct stm32_cryp_ctx *ctx = crypto_skcipher_ctx( 103747ece481SArd Biesheuvel crypto_skcipher_reqtfm(req)); 10389e054ec2SFabien DESSENNE struct stm32_cryp *cryp = ctx->cryp; 10399e054ec2SFabien DESSENNE 10409e054ec2SFabien DESSENNE if (!cryp) 10419e054ec2SFabien DESSENNE return -ENODEV; 10429e054ec2SFabien DESSENNE 10439e054ec2SFabien DESSENNE return stm32_cryp_cpu_start(cryp); 10449e054ec2SFabien DESSENNE } 10459e054ec2SFabien DESSENNE 10469d3b5030SFabien DESSENNE static int stm32_cryp_prepare_aead_req(struct crypto_engine *engine, void *areq) 10479d3b5030SFabien DESSENNE { 10489d3b5030SFabien DESSENNE struct aead_request *req = container_of(areq, struct aead_request, 10499d3b5030SFabien DESSENNE base); 10509d3b5030SFabien DESSENNE 10519d3b5030SFabien DESSENNE return stm32_cryp_prepare_req(NULL, req); 10529d3b5030SFabien DESSENNE } 10539d3b5030SFabien DESSENNE 10549d3b5030SFabien DESSENNE static int stm32_cryp_aead_one_req(struct crypto_engine *engine, void *areq) 10559d3b5030SFabien DESSENNE { 10569d3b5030SFabien DESSENNE struct aead_request *req = container_of(areq, struct aead_request, 10579d3b5030SFabien DESSENNE base); 10589d3b5030SFabien DESSENNE struct stm32_cryp_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); 10599d3b5030SFabien DESSENNE struct stm32_cryp *cryp = ctx->cryp; 10609d3b5030SFabien DESSENNE 10619d3b5030SFabien DESSENNE if (!cryp) 10629d3b5030SFabien DESSENNE return -ENODEV; 10639d3b5030SFabien DESSENNE 10649d3b5030SFabien DESSENNE if (unlikely(!cryp->areq->assoclen && 10659d3b5030SFabien DESSENNE !stm32_cryp_get_input_text_len(cryp))) { 10669d3b5030SFabien DESSENNE /* No input data to process: get tag and finish */ 10679d3b5030SFabien DESSENNE stm32_cryp_finish_req(cryp, 0); 10689d3b5030SFabien DESSENNE return 0; 10699d3b5030SFabien DESSENNE } 10709d3b5030SFabien DESSENNE 10719d3b5030SFabien DESSENNE return stm32_cryp_cpu_start(cryp); 10729d3b5030SFabien DESSENNE } 10739d3b5030SFabien DESSENNE 10749e054ec2SFabien DESSENNE static u32 *stm32_cryp_next_out(struct stm32_cryp *cryp, u32 *dst, 10759e054ec2SFabien DESSENNE unsigned int n) 10769e054ec2SFabien DESSENNE { 10779e054ec2SFabien DESSENNE scatterwalk_advance(&cryp->out_walk, n); 10789e054ec2SFabien DESSENNE 10799e054ec2SFabien DESSENNE if (unlikely(cryp->out_sg->length == _walked_out)) { 10809e054ec2SFabien DESSENNE cryp->out_sg = sg_next(cryp->out_sg); 10819e054ec2SFabien DESSENNE if (cryp->out_sg) { 10829e054ec2SFabien DESSENNE scatterwalk_start(&cryp->out_walk, cryp->out_sg); 10839e054ec2SFabien DESSENNE return (sg_virt(cryp->out_sg) + _walked_out); 10849e054ec2SFabien DESSENNE } 10859e054ec2SFabien DESSENNE } 10869e054ec2SFabien DESSENNE 10879e054ec2SFabien DESSENNE return (u32 *)((u8 *)dst + n); 10889e054ec2SFabien DESSENNE } 10899e054ec2SFabien DESSENNE 10909e054ec2SFabien DESSENNE static u32 *stm32_cryp_next_in(struct stm32_cryp *cryp, u32 *src, 10919e054ec2SFabien DESSENNE unsigned int n) 10929e054ec2SFabien DESSENNE { 10939e054ec2SFabien DESSENNE scatterwalk_advance(&cryp->in_walk, n); 10949e054ec2SFabien DESSENNE 10959e054ec2SFabien DESSENNE if (unlikely(cryp->in_sg->length == _walked_in)) { 10969e054ec2SFabien DESSENNE cryp->in_sg = sg_next(cryp->in_sg); 10979e054ec2SFabien DESSENNE if (cryp->in_sg) { 10989e054ec2SFabien DESSENNE scatterwalk_start(&cryp->in_walk, cryp->in_sg); 10999e054ec2SFabien DESSENNE return (sg_virt(cryp->in_sg) + _walked_in); 11009e054ec2SFabien DESSENNE } 11019e054ec2SFabien DESSENNE } 11029e054ec2SFabien DESSENNE 11039e054ec2SFabien DESSENNE return (u32 *)((u8 *)src + n); 11049e054ec2SFabien DESSENNE } 11059e054ec2SFabien DESSENNE 11069d3b5030SFabien DESSENNE static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp) 11079d3b5030SFabien DESSENNE { 11089d3b5030SFabien DESSENNE u32 cfg, size_bit, *dst, d32; 11099d3b5030SFabien DESSENNE u8 *d8; 11109d3b5030SFabien DESSENNE unsigned int i, j; 11119d3b5030SFabien DESSENNE int ret = 0; 11129d3b5030SFabien DESSENNE 11139d3b5030SFabien DESSENNE /* Update Config */ 11149d3b5030SFabien DESSENNE cfg = stm32_cryp_read(cryp, CRYP_CR); 11159d3b5030SFabien DESSENNE 11169d3b5030SFabien DESSENNE cfg &= ~CR_PH_MASK; 11179d3b5030SFabien DESSENNE cfg |= CR_PH_FINAL; 11189d3b5030SFabien DESSENNE cfg &= ~CR_DEC_NOT_ENC; 11199d3b5030SFabien DESSENNE cfg |= CR_CRYPEN; 11209d3b5030SFabien DESSENNE 11219d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_CR, cfg); 11229d3b5030SFabien DESSENNE 11239d3b5030SFabien DESSENNE if (is_gcm(cryp)) { 11249d3b5030SFabien DESSENNE /* GCM: write aad and payload size (in bits) */ 11259d3b5030SFabien DESSENNE size_bit = cryp->areq->assoclen * 8; 11269d3b5030SFabien DESSENNE if (cryp->caps->swap_final) 1127*bbb28326SHerbert Xu size_bit = (__force u32)cpu_to_be32(size_bit); 11289d3b5030SFabien DESSENNE 11299d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_DIN, 0); 11309d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_DIN, size_bit); 11319d3b5030SFabien DESSENNE 11329d3b5030SFabien DESSENNE size_bit = is_encrypt(cryp) ? cryp->areq->cryptlen : 11339d3b5030SFabien DESSENNE cryp->areq->cryptlen - AES_BLOCK_SIZE; 11349d3b5030SFabien DESSENNE size_bit *= 8; 11359d3b5030SFabien DESSENNE if (cryp->caps->swap_final) 1136*bbb28326SHerbert Xu size_bit = (__force u32)cpu_to_be32(size_bit); 11379d3b5030SFabien DESSENNE 11389d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_DIN, 0); 11399d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_DIN, size_bit); 11409d3b5030SFabien DESSENNE } else { 11419d3b5030SFabien DESSENNE /* CCM: write CTR0 */ 11429d3b5030SFabien DESSENNE u8 iv[AES_BLOCK_SIZE]; 11439d3b5030SFabien DESSENNE u32 *iv32 = (u32 *)iv; 1144*bbb28326SHerbert Xu __be32 *biv; 1145*bbb28326SHerbert Xu 1146*bbb28326SHerbert Xu biv = (void *)iv; 11479d3b5030SFabien DESSENNE 11489d3b5030SFabien DESSENNE memcpy(iv, cryp->areq->iv, AES_BLOCK_SIZE); 11499d3b5030SFabien DESSENNE memset(iv + AES_BLOCK_SIZE - 1 - iv[0], 0, iv[0] + 1); 11509d3b5030SFabien DESSENNE 11519d3b5030SFabien DESSENNE for (i = 0; i < AES_BLOCK_32; i++) { 1152*bbb28326SHerbert Xu u32 xiv = iv32[i]; 1153*bbb28326SHerbert Xu 11549d3b5030SFabien DESSENNE if (!cryp->caps->padding_wa) 1155*bbb28326SHerbert Xu xiv = be32_to_cpu(biv[i]); 1156*bbb28326SHerbert Xu stm32_cryp_write(cryp, CRYP_DIN, xiv); 11579d3b5030SFabien DESSENNE } 11589d3b5030SFabien DESSENNE } 11599d3b5030SFabien DESSENNE 11609d3b5030SFabien DESSENNE /* Wait for output data */ 11619d3b5030SFabien DESSENNE ret = stm32_cryp_wait_output(cryp); 11629d3b5030SFabien DESSENNE if (ret) { 11639d3b5030SFabien DESSENNE dev_err(cryp->dev, "Timeout (read tag)\n"); 11649d3b5030SFabien DESSENNE return ret; 11659d3b5030SFabien DESSENNE } 11669d3b5030SFabien DESSENNE 11679d3b5030SFabien DESSENNE if (is_encrypt(cryp)) { 11689d3b5030SFabien DESSENNE /* Get and write tag */ 11699d3b5030SFabien DESSENNE dst = sg_virt(cryp->out_sg) + _walked_out; 11709d3b5030SFabien DESSENNE 11719d3b5030SFabien DESSENNE for (i = 0; i < AES_BLOCK_32; i++) { 11729d3b5030SFabien DESSENNE if (cryp->total_out >= sizeof(u32)) { 11739d3b5030SFabien DESSENNE /* Read a full u32 */ 11749d3b5030SFabien DESSENNE *dst = stm32_cryp_read(cryp, CRYP_DOUT); 11759d3b5030SFabien DESSENNE 11769d3b5030SFabien DESSENNE dst = stm32_cryp_next_out(cryp, dst, 11779d3b5030SFabien DESSENNE sizeof(u32)); 11789d3b5030SFabien DESSENNE cryp->total_out -= sizeof(u32); 11799d3b5030SFabien DESSENNE } else if (!cryp->total_out) { 11809d3b5030SFabien DESSENNE /* Empty fifo out (data from input padding) */ 11819d3b5030SFabien DESSENNE stm32_cryp_read(cryp, CRYP_DOUT); 11829d3b5030SFabien DESSENNE } else { 11839d3b5030SFabien DESSENNE /* Read less than an u32 */ 11849d3b5030SFabien DESSENNE d32 = stm32_cryp_read(cryp, CRYP_DOUT); 11859d3b5030SFabien DESSENNE d8 = (u8 *)&d32; 11869d3b5030SFabien DESSENNE 11879d3b5030SFabien DESSENNE for (j = 0; j < cryp->total_out; j++) { 11889d3b5030SFabien DESSENNE *((u8 *)dst) = *(d8++); 11899d3b5030SFabien DESSENNE dst = stm32_cryp_next_out(cryp, dst, 1); 11909d3b5030SFabien DESSENNE } 11919d3b5030SFabien DESSENNE cryp->total_out = 0; 11929d3b5030SFabien DESSENNE } 11939d3b5030SFabien DESSENNE } 11949d3b5030SFabien DESSENNE } else { 11959d3b5030SFabien DESSENNE /* Get and check tag */ 11969d3b5030SFabien DESSENNE u32 in_tag[AES_BLOCK_32], out_tag[AES_BLOCK_32]; 11979d3b5030SFabien DESSENNE 11989d3b5030SFabien DESSENNE scatterwalk_map_and_copy(in_tag, cryp->in_sg, 11999d3b5030SFabien DESSENNE cryp->total_in_save - cryp->authsize, 12009d3b5030SFabien DESSENNE cryp->authsize, 0); 12019d3b5030SFabien DESSENNE 12029d3b5030SFabien DESSENNE for (i = 0; i < AES_BLOCK_32; i++) 12039d3b5030SFabien DESSENNE out_tag[i] = stm32_cryp_read(cryp, CRYP_DOUT); 12049d3b5030SFabien DESSENNE 12059d3b5030SFabien DESSENNE if (crypto_memneq(in_tag, out_tag, cryp->authsize)) 12069d3b5030SFabien DESSENNE ret = -EBADMSG; 12079d3b5030SFabien DESSENNE } 12089d3b5030SFabien DESSENNE 12099d3b5030SFabien DESSENNE /* Disable cryp */ 12109d3b5030SFabien DESSENNE cfg &= ~CR_CRYPEN; 12119d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_CR, cfg); 12129d3b5030SFabien DESSENNE 12139d3b5030SFabien DESSENNE return ret; 12149d3b5030SFabien DESSENNE } 12159d3b5030SFabien DESSENNE 12169e054ec2SFabien DESSENNE static void stm32_cryp_check_ctr_counter(struct stm32_cryp *cryp) 12179e054ec2SFabien DESSENNE { 12189e054ec2SFabien DESSENNE u32 cr; 12199e054ec2SFabien DESSENNE 12209e054ec2SFabien DESSENNE if (unlikely(cryp->last_ctr[3] == 0xFFFFFFFF)) { 12219e054ec2SFabien DESSENNE cryp->last_ctr[3] = 0; 12229e054ec2SFabien DESSENNE cryp->last_ctr[2]++; 12239e054ec2SFabien DESSENNE if (!cryp->last_ctr[2]) { 12249e054ec2SFabien DESSENNE cryp->last_ctr[1]++; 12259e054ec2SFabien DESSENNE if (!cryp->last_ctr[1]) 12269e054ec2SFabien DESSENNE cryp->last_ctr[0]++; 12279e054ec2SFabien DESSENNE } 12289e054ec2SFabien DESSENNE 12299e054ec2SFabien DESSENNE cr = stm32_cryp_read(cryp, CRYP_CR); 12309e054ec2SFabien DESSENNE stm32_cryp_write(cryp, CRYP_CR, cr & ~CR_CRYPEN); 12319e054ec2SFabien DESSENNE 12329e054ec2SFabien DESSENNE stm32_cryp_hw_write_iv(cryp, (u32 *)cryp->last_ctr); 12339e054ec2SFabien DESSENNE 12349e054ec2SFabien DESSENNE stm32_cryp_write(cryp, CRYP_CR, cr); 12359e054ec2SFabien DESSENNE } 12369e054ec2SFabien DESSENNE 12379e054ec2SFabien DESSENNE cryp->last_ctr[0] = stm32_cryp_read(cryp, CRYP_IV0LR); 12389e054ec2SFabien DESSENNE cryp->last_ctr[1] = stm32_cryp_read(cryp, CRYP_IV0RR); 12399e054ec2SFabien DESSENNE cryp->last_ctr[2] = stm32_cryp_read(cryp, CRYP_IV1LR); 12409e054ec2SFabien DESSENNE cryp->last_ctr[3] = stm32_cryp_read(cryp, CRYP_IV1RR); 12419e054ec2SFabien DESSENNE } 12429e054ec2SFabien DESSENNE 12439e054ec2SFabien DESSENNE static bool stm32_cryp_irq_read_data(struct stm32_cryp *cryp) 12449e054ec2SFabien DESSENNE { 12459e054ec2SFabien DESSENNE unsigned int i, j; 12469e054ec2SFabien DESSENNE u32 d32, *dst; 12479e054ec2SFabien DESSENNE u8 *d8; 12489d3b5030SFabien DESSENNE size_t tag_size; 12499d3b5030SFabien DESSENNE 12509d3b5030SFabien DESSENNE /* Do no read tag now (if any) */ 12519d3b5030SFabien DESSENNE if (is_encrypt(cryp) && (is_gcm(cryp) || is_ccm(cryp))) 12529d3b5030SFabien DESSENNE tag_size = cryp->authsize; 12539d3b5030SFabien DESSENNE else 12549d3b5030SFabien DESSENNE tag_size = 0; 12559e054ec2SFabien DESSENNE 12569e054ec2SFabien DESSENNE dst = sg_virt(cryp->out_sg) + _walked_out; 12579e054ec2SFabien DESSENNE 12589e054ec2SFabien DESSENNE for (i = 0; i < cryp->hw_blocksize / sizeof(u32); i++) { 12599d3b5030SFabien DESSENNE if (likely(cryp->total_out - tag_size >= sizeof(u32))) { 12609e054ec2SFabien DESSENNE /* Read a full u32 */ 12619e054ec2SFabien DESSENNE *dst = stm32_cryp_read(cryp, CRYP_DOUT); 12629e054ec2SFabien DESSENNE 12639e054ec2SFabien DESSENNE dst = stm32_cryp_next_out(cryp, dst, sizeof(u32)); 12649e054ec2SFabien DESSENNE cryp->total_out -= sizeof(u32); 12659d3b5030SFabien DESSENNE } else if (cryp->total_out == tag_size) { 12669e054ec2SFabien DESSENNE /* Empty fifo out (data from input padding) */ 12679e054ec2SFabien DESSENNE d32 = stm32_cryp_read(cryp, CRYP_DOUT); 12689e054ec2SFabien DESSENNE } else { 12699e054ec2SFabien DESSENNE /* Read less than an u32 */ 12709e054ec2SFabien DESSENNE d32 = stm32_cryp_read(cryp, CRYP_DOUT); 12719e054ec2SFabien DESSENNE d8 = (u8 *)&d32; 12729e054ec2SFabien DESSENNE 12739d3b5030SFabien DESSENNE for (j = 0; j < cryp->total_out - tag_size; j++) { 12749e054ec2SFabien DESSENNE *((u8 *)dst) = *(d8++); 12759e054ec2SFabien DESSENNE dst = stm32_cryp_next_out(cryp, dst, 1); 12769e054ec2SFabien DESSENNE } 12779d3b5030SFabien DESSENNE cryp->total_out = tag_size; 12789e054ec2SFabien DESSENNE } 12799e054ec2SFabien DESSENNE } 12809e054ec2SFabien DESSENNE 12819d3b5030SFabien DESSENNE return !(cryp->total_out - tag_size) || !cryp->total_in; 12829e054ec2SFabien DESSENNE } 12839e054ec2SFabien DESSENNE 12849e054ec2SFabien DESSENNE static void stm32_cryp_irq_write_block(struct stm32_cryp *cryp) 12859e054ec2SFabien DESSENNE { 12869e054ec2SFabien DESSENNE unsigned int i, j; 12879e054ec2SFabien DESSENNE u32 *src; 12889e054ec2SFabien DESSENNE u8 d8[4]; 12899d3b5030SFabien DESSENNE size_t tag_size; 12909d3b5030SFabien DESSENNE 12919d3b5030SFabien DESSENNE /* Do no write tag (if any) */ 12929d3b5030SFabien DESSENNE if (is_decrypt(cryp) && (is_gcm(cryp) || is_ccm(cryp))) 12939d3b5030SFabien DESSENNE tag_size = cryp->authsize; 12949d3b5030SFabien DESSENNE else 12959d3b5030SFabien DESSENNE tag_size = 0; 12969e054ec2SFabien DESSENNE 12979e054ec2SFabien DESSENNE src = sg_virt(cryp->in_sg) + _walked_in; 12989e054ec2SFabien DESSENNE 12999e054ec2SFabien DESSENNE for (i = 0; i < cryp->hw_blocksize / sizeof(u32); i++) { 13009d3b5030SFabien DESSENNE if (likely(cryp->total_in - tag_size >= sizeof(u32))) { 13019e054ec2SFabien DESSENNE /* Write a full u32 */ 13029e054ec2SFabien DESSENNE stm32_cryp_write(cryp, CRYP_DIN, *src); 13039e054ec2SFabien DESSENNE 13049e054ec2SFabien DESSENNE src = stm32_cryp_next_in(cryp, src, sizeof(u32)); 13059e054ec2SFabien DESSENNE cryp->total_in -= sizeof(u32); 13069d3b5030SFabien DESSENNE } else if (cryp->total_in == tag_size) { 13079e054ec2SFabien DESSENNE /* Write padding data */ 13089e054ec2SFabien DESSENNE stm32_cryp_write(cryp, CRYP_DIN, 0); 13099e054ec2SFabien DESSENNE } else { 13109e054ec2SFabien DESSENNE /* Write less than an u32 */ 13119e054ec2SFabien DESSENNE memset(d8, 0, sizeof(u32)); 13129d3b5030SFabien DESSENNE for (j = 0; j < cryp->total_in - tag_size; j++) { 13139e054ec2SFabien DESSENNE d8[j] = *((u8 *)src); 13149e054ec2SFabien DESSENNE src = stm32_cryp_next_in(cryp, src, 1); 13159e054ec2SFabien DESSENNE } 13169e054ec2SFabien DESSENNE 13179e054ec2SFabien DESSENNE stm32_cryp_write(cryp, CRYP_DIN, *(u32 *)d8); 13189d3b5030SFabien DESSENNE cryp->total_in = tag_size; 13199e054ec2SFabien DESSENNE } 13209e054ec2SFabien DESSENNE } 13219e054ec2SFabien DESSENNE } 13229e054ec2SFabien DESSENNE 13239d3b5030SFabien DESSENNE static void stm32_cryp_irq_write_gcm_padded_data(struct stm32_cryp *cryp) 13249d3b5030SFabien DESSENNE { 13259d3b5030SFabien DESSENNE int err; 13269d3b5030SFabien DESSENNE u32 cfg, tmp[AES_BLOCK_32]; 13279d3b5030SFabien DESSENNE size_t total_in_ori = cryp->total_in; 13289d3b5030SFabien DESSENNE struct scatterlist *out_sg_ori = cryp->out_sg; 13299d3b5030SFabien DESSENNE unsigned int i; 13309d3b5030SFabien DESSENNE 13319d3b5030SFabien DESSENNE /* 'Special workaround' procedure described in the datasheet */ 13329d3b5030SFabien DESSENNE 13339d3b5030SFabien DESSENNE /* a) disable ip */ 13349d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_IMSCR, 0); 13359d3b5030SFabien DESSENNE cfg = stm32_cryp_read(cryp, CRYP_CR); 13369d3b5030SFabien DESSENNE cfg &= ~CR_CRYPEN; 13379d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_CR, cfg); 13389d3b5030SFabien DESSENNE 13399d3b5030SFabien DESSENNE /* b) Update IV1R */ 13409d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_IV1RR, cryp->gcm_ctr - 2); 13419d3b5030SFabien DESSENNE 13429d3b5030SFabien DESSENNE /* c) change mode to CTR */ 13439d3b5030SFabien DESSENNE cfg &= ~CR_ALGO_MASK; 13449d3b5030SFabien DESSENNE cfg |= CR_AES_CTR; 13459d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_CR, cfg); 13469d3b5030SFabien DESSENNE 13479d3b5030SFabien DESSENNE /* a) enable IP */ 13489d3b5030SFabien DESSENNE cfg |= CR_CRYPEN; 13499d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_CR, cfg); 13509d3b5030SFabien DESSENNE 13519d3b5030SFabien DESSENNE /* b) pad and write the last block */ 13529d3b5030SFabien DESSENNE stm32_cryp_irq_write_block(cryp); 13539d3b5030SFabien DESSENNE cryp->total_in = total_in_ori; 13549d3b5030SFabien DESSENNE err = stm32_cryp_wait_output(cryp); 13559d3b5030SFabien DESSENNE if (err) { 13569d3b5030SFabien DESSENNE dev_err(cryp->dev, "Timeout (write gcm header)\n"); 13579d3b5030SFabien DESSENNE return stm32_cryp_finish_req(cryp, err); 13589d3b5030SFabien DESSENNE } 13599d3b5030SFabien DESSENNE 13609d3b5030SFabien DESSENNE /* c) get and store encrypted data */ 13619d3b5030SFabien DESSENNE stm32_cryp_irq_read_data(cryp); 13629d3b5030SFabien DESSENNE scatterwalk_map_and_copy(tmp, out_sg_ori, 13639d3b5030SFabien DESSENNE cryp->total_in_save - total_in_ori, 13649d3b5030SFabien DESSENNE total_in_ori, 0); 13659d3b5030SFabien DESSENNE 13669d3b5030SFabien DESSENNE /* d) change mode back to AES GCM */ 13679d3b5030SFabien DESSENNE cfg &= ~CR_ALGO_MASK; 13689d3b5030SFabien DESSENNE cfg |= CR_AES_GCM; 13699d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_CR, cfg); 13709d3b5030SFabien DESSENNE 13719d3b5030SFabien DESSENNE /* e) change phase to Final */ 13729d3b5030SFabien DESSENNE cfg &= ~CR_PH_MASK; 13739d3b5030SFabien DESSENNE cfg |= CR_PH_FINAL; 13749d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_CR, cfg); 13759d3b5030SFabien DESSENNE 13769d3b5030SFabien DESSENNE /* f) write padded data */ 13779d3b5030SFabien DESSENNE for (i = 0; i < AES_BLOCK_32; i++) { 13789d3b5030SFabien DESSENNE if (cryp->total_in) 13799d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_DIN, tmp[i]); 13809d3b5030SFabien DESSENNE else 13819d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_DIN, 0); 13829d3b5030SFabien DESSENNE 13839d3b5030SFabien DESSENNE cryp->total_in -= min_t(size_t, sizeof(u32), cryp->total_in); 13849d3b5030SFabien DESSENNE } 13859d3b5030SFabien DESSENNE 13869d3b5030SFabien DESSENNE /* g) Empty fifo out */ 13879d3b5030SFabien DESSENNE err = stm32_cryp_wait_output(cryp); 13889d3b5030SFabien DESSENNE if (err) { 13899d3b5030SFabien DESSENNE dev_err(cryp->dev, "Timeout (write gcm header)\n"); 13909d3b5030SFabien DESSENNE return stm32_cryp_finish_req(cryp, err); 13919d3b5030SFabien DESSENNE } 13929d3b5030SFabien DESSENNE 13939d3b5030SFabien DESSENNE for (i = 0; i < AES_BLOCK_32; i++) 13949d3b5030SFabien DESSENNE stm32_cryp_read(cryp, CRYP_DOUT); 13959d3b5030SFabien DESSENNE 13969d3b5030SFabien DESSENNE /* h) run the he normal Final phase */ 13979d3b5030SFabien DESSENNE stm32_cryp_finish_req(cryp, 0); 13989d3b5030SFabien DESSENNE } 13999d3b5030SFabien DESSENNE 14009d3b5030SFabien DESSENNE static void stm32_cryp_irq_set_npblb(struct stm32_cryp *cryp) 14019d3b5030SFabien DESSENNE { 14029d3b5030SFabien DESSENNE u32 cfg, payload_bytes; 14039d3b5030SFabien DESSENNE 14049d3b5030SFabien DESSENNE /* disable ip, set NPBLB and reneable ip */ 14059d3b5030SFabien DESSENNE cfg = stm32_cryp_read(cryp, CRYP_CR); 14069d3b5030SFabien DESSENNE cfg &= ~CR_CRYPEN; 14079d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_CR, cfg); 14089d3b5030SFabien DESSENNE 14099d3b5030SFabien DESSENNE payload_bytes = is_decrypt(cryp) ? cryp->total_in - cryp->authsize : 14109d3b5030SFabien DESSENNE cryp->total_in; 14119d3b5030SFabien DESSENNE cfg |= (cryp->hw_blocksize - payload_bytes) << CR_NBPBL_SHIFT; 14129d3b5030SFabien DESSENNE cfg |= CR_CRYPEN; 14139d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_CR, cfg); 14149d3b5030SFabien DESSENNE } 14159d3b5030SFabien DESSENNE 14169d3b5030SFabien DESSENNE static void stm32_cryp_irq_write_ccm_padded_data(struct stm32_cryp *cryp) 14179d3b5030SFabien DESSENNE { 14189d3b5030SFabien DESSENNE int err = 0; 14199d3b5030SFabien DESSENNE u32 cfg, iv1tmp; 14209d3b5030SFabien DESSENNE u32 cstmp1[AES_BLOCK_32], cstmp2[AES_BLOCK_32], tmp[AES_BLOCK_32]; 14219d3b5030SFabien DESSENNE size_t last_total_out, total_in_ori = cryp->total_in; 14229d3b5030SFabien DESSENNE struct scatterlist *out_sg_ori = cryp->out_sg; 14239d3b5030SFabien DESSENNE unsigned int i; 14249d3b5030SFabien DESSENNE 14259d3b5030SFabien DESSENNE /* 'Special workaround' procedure described in the datasheet */ 14269d3b5030SFabien DESSENNE cryp->flags |= FLG_CCM_PADDED_WA; 14279d3b5030SFabien DESSENNE 14289d3b5030SFabien DESSENNE /* a) disable ip */ 14299d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_IMSCR, 0); 14309d3b5030SFabien DESSENNE 14319d3b5030SFabien DESSENNE cfg = stm32_cryp_read(cryp, CRYP_CR); 14329d3b5030SFabien DESSENNE cfg &= ~CR_CRYPEN; 14339d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_CR, cfg); 14349d3b5030SFabien DESSENNE 14359d3b5030SFabien DESSENNE /* b) get IV1 from CRYP_CSGCMCCM7 */ 14369d3b5030SFabien DESSENNE iv1tmp = stm32_cryp_read(cryp, CRYP_CSGCMCCM0R + 7 * 4); 14379d3b5030SFabien DESSENNE 14389d3b5030SFabien DESSENNE /* c) Load CRYP_CSGCMCCMxR */ 14399d3b5030SFabien DESSENNE for (i = 0; i < ARRAY_SIZE(cstmp1); i++) 14409d3b5030SFabien DESSENNE cstmp1[i] = stm32_cryp_read(cryp, CRYP_CSGCMCCM0R + i * 4); 14419d3b5030SFabien DESSENNE 14429d3b5030SFabien DESSENNE /* d) Write IV1R */ 14439d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_IV1RR, iv1tmp); 14449d3b5030SFabien DESSENNE 14459d3b5030SFabien DESSENNE /* e) change mode to CTR */ 14469d3b5030SFabien DESSENNE cfg &= ~CR_ALGO_MASK; 14479d3b5030SFabien DESSENNE cfg |= CR_AES_CTR; 14489d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_CR, cfg); 14499d3b5030SFabien DESSENNE 14509d3b5030SFabien DESSENNE /* a) enable IP */ 14519d3b5030SFabien DESSENNE cfg |= CR_CRYPEN; 14529d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_CR, cfg); 14539d3b5030SFabien DESSENNE 14549d3b5030SFabien DESSENNE /* b) pad and write the last block */ 14559d3b5030SFabien DESSENNE stm32_cryp_irq_write_block(cryp); 14569d3b5030SFabien DESSENNE cryp->total_in = total_in_ori; 14579d3b5030SFabien DESSENNE err = stm32_cryp_wait_output(cryp); 14589d3b5030SFabien DESSENNE if (err) { 14599d3b5030SFabien DESSENNE dev_err(cryp->dev, "Timeout (wite ccm padded data)\n"); 14609d3b5030SFabien DESSENNE return stm32_cryp_finish_req(cryp, err); 14619d3b5030SFabien DESSENNE } 14629d3b5030SFabien DESSENNE 14639d3b5030SFabien DESSENNE /* c) get and store decrypted data */ 14649d3b5030SFabien DESSENNE last_total_out = cryp->total_out; 14659d3b5030SFabien DESSENNE stm32_cryp_irq_read_data(cryp); 14669d3b5030SFabien DESSENNE 14679d3b5030SFabien DESSENNE memset(tmp, 0, sizeof(tmp)); 14689d3b5030SFabien DESSENNE scatterwalk_map_and_copy(tmp, out_sg_ori, 14699d3b5030SFabien DESSENNE cryp->total_out_save - last_total_out, 14709d3b5030SFabien DESSENNE last_total_out, 0); 14719d3b5030SFabien DESSENNE 14729d3b5030SFabien DESSENNE /* d) Load again CRYP_CSGCMCCMxR */ 14739d3b5030SFabien DESSENNE for (i = 0; i < ARRAY_SIZE(cstmp2); i++) 14749d3b5030SFabien DESSENNE cstmp2[i] = stm32_cryp_read(cryp, CRYP_CSGCMCCM0R + i * 4); 14759d3b5030SFabien DESSENNE 14769d3b5030SFabien DESSENNE /* e) change mode back to AES CCM */ 14779d3b5030SFabien DESSENNE cfg &= ~CR_ALGO_MASK; 14789d3b5030SFabien DESSENNE cfg |= CR_AES_CCM; 14799d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_CR, cfg); 14809d3b5030SFabien DESSENNE 14819d3b5030SFabien DESSENNE /* f) change phase to header */ 14829d3b5030SFabien DESSENNE cfg &= ~CR_PH_MASK; 14839d3b5030SFabien DESSENNE cfg |= CR_PH_HEADER; 14849d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_CR, cfg); 14859d3b5030SFabien DESSENNE 14869d3b5030SFabien DESSENNE /* g) XOR and write padded data */ 14879d3b5030SFabien DESSENNE for (i = 0; i < ARRAY_SIZE(tmp); i++) { 14889d3b5030SFabien DESSENNE tmp[i] ^= cstmp1[i]; 14899d3b5030SFabien DESSENNE tmp[i] ^= cstmp2[i]; 14909d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_DIN, tmp[i]); 14919d3b5030SFabien DESSENNE } 14929d3b5030SFabien DESSENNE 14939d3b5030SFabien DESSENNE /* h) wait for completion */ 14949d3b5030SFabien DESSENNE err = stm32_cryp_wait_busy(cryp); 14959d3b5030SFabien DESSENNE if (err) 14969d3b5030SFabien DESSENNE dev_err(cryp->dev, "Timeout (wite ccm padded data)\n"); 14979d3b5030SFabien DESSENNE 14989d3b5030SFabien DESSENNE /* i) run the he normal Final phase */ 14999d3b5030SFabien DESSENNE stm32_cryp_finish_req(cryp, err); 15009d3b5030SFabien DESSENNE } 15019d3b5030SFabien DESSENNE 15029e054ec2SFabien DESSENNE static void stm32_cryp_irq_write_data(struct stm32_cryp *cryp) 15039e054ec2SFabien DESSENNE { 15049e054ec2SFabien DESSENNE if (unlikely(!cryp->total_in)) { 15059e054ec2SFabien DESSENNE dev_warn(cryp->dev, "No more data to process\n"); 15069e054ec2SFabien DESSENNE return; 15079e054ec2SFabien DESSENNE } 15089e054ec2SFabien DESSENNE 15099d3b5030SFabien DESSENNE if (unlikely(cryp->total_in < AES_BLOCK_SIZE && 15109d3b5030SFabien DESSENNE (stm32_cryp_get_hw_mode(cryp) == CR_AES_GCM) && 15119d3b5030SFabien DESSENNE is_encrypt(cryp))) { 15129d3b5030SFabien DESSENNE /* Padding for AES GCM encryption */ 15139d3b5030SFabien DESSENNE if (cryp->caps->padding_wa) 15149d3b5030SFabien DESSENNE /* Special case 1 */ 15159d3b5030SFabien DESSENNE return stm32_cryp_irq_write_gcm_padded_data(cryp); 15169d3b5030SFabien DESSENNE 15179d3b5030SFabien DESSENNE /* Setting padding bytes (NBBLB) */ 15189d3b5030SFabien DESSENNE stm32_cryp_irq_set_npblb(cryp); 15199d3b5030SFabien DESSENNE } 15209d3b5030SFabien DESSENNE 15219d3b5030SFabien DESSENNE if (unlikely((cryp->total_in - cryp->authsize < AES_BLOCK_SIZE) && 15229d3b5030SFabien DESSENNE (stm32_cryp_get_hw_mode(cryp) == CR_AES_CCM) && 15239d3b5030SFabien DESSENNE is_decrypt(cryp))) { 15249d3b5030SFabien DESSENNE /* Padding for AES CCM decryption */ 15259d3b5030SFabien DESSENNE if (cryp->caps->padding_wa) 15269d3b5030SFabien DESSENNE /* Special case 2 */ 15279d3b5030SFabien DESSENNE return stm32_cryp_irq_write_ccm_padded_data(cryp); 15289d3b5030SFabien DESSENNE 15299d3b5030SFabien DESSENNE /* Setting padding bytes (NBBLB) */ 15309d3b5030SFabien DESSENNE stm32_cryp_irq_set_npblb(cryp); 15319d3b5030SFabien DESSENNE } 15329d3b5030SFabien DESSENNE 15339e054ec2SFabien DESSENNE if (is_aes(cryp) && is_ctr(cryp)) 15349e054ec2SFabien DESSENNE stm32_cryp_check_ctr_counter(cryp); 15359e054ec2SFabien DESSENNE 15369e054ec2SFabien DESSENNE stm32_cryp_irq_write_block(cryp); 15379e054ec2SFabien DESSENNE } 15389e054ec2SFabien DESSENNE 15399d3b5030SFabien DESSENNE static void stm32_cryp_irq_write_gcm_header(struct stm32_cryp *cryp) 15409d3b5030SFabien DESSENNE { 15419d3b5030SFabien DESSENNE int err; 15429d3b5030SFabien DESSENNE unsigned int i, j; 15439d3b5030SFabien DESSENNE u32 cfg, *src; 15449d3b5030SFabien DESSENNE 15459d3b5030SFabien DESSENNE src = sg_virt(cryp->in_sg) + _walked_in; 15469d3b5030SFabien DESSENNE 15479d3b5030SFabien DESSENNE for (i = 0; i < AES_BLOCK_32; i++) { 15489d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_DIN, *src); 15499d3b5030SFabien DESSENNE 15509d3b5030SFabien DESSENNE src = stm32_cryp_next_in(cryp, src, sizeof(u32)); 15519d3b5030SFabien DESSENNE cryp->total_in -= min_t(size_t, sizeof(u32), cryp->total_in); 15529d3b5030SFabien DESSENNE 15539d3b5030SFabien DESSENNE /* Check if whole header written */ 15549d3b5030SFabien DESSENNE if ((cryp->total_in_save - cryp->total_in) == 15559d3b5030SFabien DESSENNE cryp->areq->assoclen) { 15569d3b5030SFabien DESSENNE /* Write padding if needed */ 15579d3b5030SFabien DESSENNE for (j = i + 1; j < AES_BLOCK_32; j++) 15589d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_DIN, 0); 15599d3b5030SFabien DESSENNE 15609d3b5030SFabien DESSENNE /* Wait for completion */ 15619d3b5030SFabien DESSENNE err = stm32_cryp_wait_busy(cryp); 15629d3b5030SFabien DESSENNE if (err) { 15639d3b5030SFabien DESSENNE dev_err(cryp->dev, "Timeout (gcm header)\n"); 15649d3b5030SFabien DESSENNE return stm32_cryp_finish_req(cryp, err); 15659d3b5030SFabien DESSENNE } 15669d3b5030SFabien DESSENNE 15679d3b5030SFabien DESSENNE if (stm32_cryp_get_input_text_len(cryp)) { 15689d3b5030SFabien DESSENNE /* Phase 3 : payload */ 15699d3b5030SFabien DESSENNE cfg = stm32_cryp_read(cryp, CRYP_CR); 15709d3b5030SFabien DESSENNE cfg &= ~CR_CRYPEN; 15719d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_CR, cfg); 15729d3b5030SFabien DESSENNE 15739d3b5030SFabien DESSENNE cfg &= ~CR_PH_MASK; 15749d3b5030SFabien DESSENNE cfg |= CR_PH_PAYLOAD; 15759d3b5030SFabien DESSENNE cfg |= CR_CRYPEN; 15769d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_CR, cfg); 15779d3b5030SFabien DESSENNE } else { 15789d3b5030SFabien DESSENNE /* Phase 4 : tag */ 15799d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_IMSCR, 0); 15809d3b5030SFabien DESSENNE stm32_cryp_finish_req(cryp, 0); 15819d3b5030SFabien DESSENNE } 15829d3b5030SFabien DESSENNE 15839d3b5030SFabien DESSENNE break; 15849d3b5030SFabien DESSENNE } 15859d3b5030SFabien DESSENNE 15869d3b5030SFabien DESSENNE if (!cryp->total_in) 15879d3b5030SFabien DESSENNE break; 15889d3b5030SFabien DESSENNE } 15899d3b5030SFabien DESSENNE } 15909d3b5030SFabien DESSENNE 15919d3b5030SFabien DESSENNE static void stm32_cryp_irq_write_ccm_header(struct stm32_cryp *cryp) 15929d3b5030SFabien DESSENNE { 15939d3b5030SFabien DESSENNE int err; 15949d3b5030SFabien DESSENNE unsigned int i = 0, j, k; 15959d3b5030SFabien DESSENNE u32 alen, cfg, *src; 15969d3b5030SFabien DESSENNE u8 d8[4]; 15979d3b5030SFabien DESSENNE 15989d3b5030SFabien DESSENNE src = sg_virt(cryp->in_sg) + _walked_in; 15999d3b5030SFabien DESSENNE alen = cryp->areq->assoclen; 16009d3b5030SFabien DESSENNE 16019d3b5030SFabien DESSENNE if (!_walked_in) { 16029d3b5030SFabien DESSENNE if (cryp->areq->assoclen <= 65280) { 16039d3b5030SFabien DESSENNE /* Write first u32 of B1 */ 16049d3b5030SFabien DESSENNE d8[0] = (alen >> 8) & 0xFF; 16059d3b5030SFabien DESSENNE d8[1] = alen & 0xFF; 16069d3b5030SFabien DESSENNE d8[2] = *((u8 *)src); 16079d3b5030SFabien DESSENNE src = stm32_cryp_next_in(cryp, src, 1); 16089d3b5030SFabien DESSENNE d8[3] = *((u8 *)src); 16099d3b5030SFabien DESSENNE src = stm32_cryp_next_in(cryp, src, 1); 16109d3b5030SFabien DESSENNE 16119d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_DIN, *(u32 *)d8); 16129d3b5030SFabien DESSENNE i++; 16139d3b5030SFabien DESSENNE 16149d3b5030SFabien DESSENNE cryp->total_in -= min_t(size_t, 2, cryp->total_in); 16159d3b5030SFabien DESSENNE } else { 16169d3b5030SFabien DESSENNE /* Build the two first u32 of B1 */ 16179d3b5030SFabien DESSENNE d8[0] = 0xFF; 16189d3b5030SFabien DESSENNE d8[1] = 0xFE; 16199d3b5030SFabien DESSENNE d8[2] = alen & 0xFF000000; 16209d3b5030SFabien DESSENNE d8[3] = alen & 0x00FF0000; 16219d3b5030SFabien DESSENNE 16229d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_DIN, *(u32 *)d8); 16239d3b5030SFabien DESSENNE i++; 16249d3b5030SFabien DESSENNE 16259d3b5030SFabien DESSENNE d8[0] = alen & 0x0000FF00; 16269d3b5030SFabien DESSENNE d8[1] = alen & 0x000000FF; 16279d3b5030SFabien DESSENNE d8[2] = *((u8 *)src); 16289d3b5030SFabien DESSENNE src = stm32_cryp_next_in(cryp, src, 1); 16299d3b5030SFabien DESSENNE d8[3] = *((u8 *)src); 16309d3b5030SFabien DESSENNE src = stm32_cryp_next_in(cryp, src, 1); 16319d3b5030SFabien DESSENNE 16329d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_DIN, *(u32 *)d8); 16339d3b5030SFabien DESSENNE i++; 16349d3b5030SFabien DESSENNE 16359d3b5030SFabien DESSENNE cryp->total_in -= min_t(size_t, 2, cryp->total_in); 16369d3b5030SFabien DESSENNE } 16379d3b5030SFabien DESSENNE } 16389d3b5030SFabien DESSENNE 16399d3b5030SFabien DESSENNE /* Write next u32 */ 16409d3b5030SFabien DESSENNE for (; i < AES_BLOCK_32; i++) { 16419d3b5030SFabien DESSENNE /* Build an u32 */ 16429d3b5030SFabien DESSENNE memset(d8, 0, sizeof(u32)); 16439d3b5030SFabien DESSENNE for (k = 0; k < sizeof(u32); k++) { 16449d3b5030SFabien DESSENNE d8[k] = *((u8 *)src); 16459d3b5030SFabien DESSENNE src = stm32_cryp_next_in(cryp, src, 1); 16469d3b5030SFabien DESSENNE 16479d3b5030SFabien DESSENNE cryp->total_in -= min_t(size_t, 1, cryp->total_in); 16489d3b5030SFabien DESSENNE if ((cryp->total_in_save - cryp->total_in) == alen) 16499d3b5030SFabien DESSENNE break; 16509d3b5030SFabien DESSENNE } 16519d3b5030SFabien DESSENNE 16529d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_DIN, *(u32 *)d8); 16539d3b5030SFabien DESSENNE 16549d3b5030SFabien DESSENNE if ((cryp->total_in_save - cryp->total_in) == alen) { 16559d3b5030SFabien DESSENNE /* Write padding if needed */ 16569d3b5030SFabien DESSENNE for (j = i + 1; j < AES_BLOCK_32; j++) 16579d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_DIN, 0); 16589d3b5030SFabien DESSENNE 16599d3b5030SFabien DESSENNE /* Wait for completion */ 16609d3b5030SFabien DESSENNE err = stm32_cryp_wait_busy(cryp); 16619d3b5030SFabien DESSENNE if (err) { 16629d3b5030SFabien DESSENNE dev_err(cryp->dev, "Timeout (ccm header)\n"); 16639d3b5030SFabien DESSENNE return stm32_cryp_finish_req(cryp, err); 16649d3b5030SFabien DESSENNE } 16659d3b5030SFabien DESSENNE 16669d3b5030SFabien DESSENNE if (stm32_cryp_get_input_text_len(cryp)) { 16679d3b5030SFabien DESSENNE /* Phase 3 : payload */ 16689d3b5030SFabien DESSENNE cfg = stm32_cryp_read(cryp, CRYP_CR); 16699d3b5030SFabien DESSENNE cfg &= ~CR_CRYPEN; 16709d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_CR, cfg); 16719d3b5030SFabien DESSENNE 16729d3b5030SFabien DESSENNE cfg &= ~CR_PH_MASK; 16739d3b5030SFabien DESSENNE cfg |= CR_PH_PAYLOAD; 16749d3b5030SFabien DESSENNE cfg |= CR_CRYPEN; 16759d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_CR, cfg); 16769d3b5030SFabien DESSENNE } else { 16779d3b5030SFabien DESSENNE /* Phase 4 : tag */ 16789d3b5030SFabien DESSENNE stm32_cryp_write(cryp, CRYP_IMSCR, 0); 16799d3b5030SFabien DESSENNE stm32_cryp_finish_req(cryp, 0); 16809d3b5030SFabien DESSENNE } 16819d3b5030SFabien DESSENNE 16829d3b5030SFabien DESSENNE break; 16839d3b5030SFabien DESSENNE } 16849d3b5030SFabien DESSENNE } 16859d3b5030SFabien DESSENNE } 16869d3b5030SFabien DESSENNE 16879e054ec2SFabien DESSENNE static irqreturn_t stm32_cryp_irq_thread(int irq, void *arg) 16889e054ec2SFabien DESSENNE { 16899e054ec2SFabien DESSENNE struct stm32_cryp *cryp = arg; 16909d3b5030SFabien DESSENNE u32 ph; 16919e054ec2SFabien DESSENNE 16929e054ec2SFabien DESSENNE if (cryp->irq_status & MISR_OUT) 16939e054ec2SFabien DESSENNE /* Output FIFO IRQ: read data */ 16949e054ec2SFabien DESSENNE if (unlikely(stm32_cryp_irq_read_data(cryp))) { 16959e054ec2SFabien DESSENNE /* All bytes processed, finish */ 16969e054ec2SFabien DESSENNE stm32_cryp_write(cryp, CRYP_IMSCR, 0); 16979d3b5030SFabien DESSENNE stm32_cryp_finish_req(cryp, 0); 16989e054ec2SFabien DESSENNE return IRQ_HANDLED; 16999e054ec2SFabien DESSENNE } 17009e054ec2SFabien DESSENNE 17019e054ec2SFabien DESSENNE if (cryp->irq_status & MISR_IN) { 17029d3b5030SFabien DESSENNE if (is_gcm(cryp)) { 17039d3b5030SFabien DESSENNE ph = stm32_cryp_read(cryp, CRYP_CR) & CR_PH_MASK; 17049d3b5030SFabien DESSENNE if (unlikely(ph == CR_PH_HEADER)) 17059d3b5030SFabien DESSENNE /* Write Header */ 17069d3b5030SFabien DESSENNE stm32_cryp_irq_write_gcm_header(cryp); 17079d3b5030SFabien DESSENNE else 17089e054ec2SFabien DESSENNE /* Input FIFO IRQ: write data */ 17099e054ec2SFabien DESSENNE stm32_cryp_irq_write_data(cryp); 17109d3b5030SFabien DESSENNE cryp->gcm_ctr++; 17119d3b5030SFabien DESSENNE } else if (is_ccm(cryp)) { 17129d3b5030SFabien DESSENNE ph = stm32_cryp_read(cryp, CRYP_CR) & CR_PH_MASK; 17139d3b5030SFabien DESSENNE if (unlikely(ph == CR_PH_HEADER)) 17149d3b5030SFabien DESSENNE /* Write Header */ 17159d3b5030SFabien DESSENNE stm32_cryp_irq_write_ccm_header(cryp); 17169d3b5030SFabien DESSENNE else 17179d3b5030SFabien DESSENNE /* Input FIFO IRQ: write data */ 17189d3b5030SFabien DESSENNE stm32_cryp_irq_write_data(cryp); 17199d3b5030SFabien DESSENNE } else { 17209d3b5030SFabien DESSENNE /* Input FIFO IRQ: write data */ 17219d3b5030SFabien DESSENNE stm32_cryp_irq_write_data(cryp); 17229d3b5030SFabien DESSENNE } 17239e054ec2SFabien DESSENNE } 17249e054ec2SFabien DESSENNE 17259e054ec2SFabien DESSENNE return IRQ_HANDLED; 17269e054ec2SFabien DESSENNE } 17279e054ec2SFabien DESSENNE 17289e054ec2SFabien DESSENNE static irqreturn_t stm32_cryp_irq(int irq, void *arg) 17299e054ec2SFabien DESSENNE { 17309e054ec2SFabien DESSENNE struct stm32_cryp *cryp = arg; 17319e054ec2SFabien DESSENNE 17329e054ec2SFabien DESSENNE cryp->irq_status = stm32_cryp_read(cryp, CRYP_MISR); 17339e054ec2SFabien DESSENNE 17349e054ec2SFabien DESSENNE return IRQ_WAKE_THREAD; 17359e054ec2SFabien DESSENNE } 17369e054ec2SFabien DESSENNE 173747ece481SArd Biesheuvel static struct skcipher_alg crypto_algs[] = { 17389e054ec2SFabien DESSENNE { 173947ece481SArd Biesheuvel .base.cra_name = "ecb(aes)", 174047ece481SArd Biesheuvel .base.cra_driver_name = "stm32-ecb-aes", 174147ece481SArd Biesheuvel .base.cra_priority = 200, 174247ece481SArd Biesheuvel .base.cra_flags = CRYPTO_ALG_ASYNC, 174347ece481SArd Biesheuvel .base.cra_blocksize = AES_BLOCK_SIZE, 174447ece481SArd Biesheuvel .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx), 174547ece481SArd Biesheuvel .base.cra_alignmask = 0xf, 174647ece481SArd Biesheuvel .base.cra_module = THIS_MODULE, 174747ece481SArd Biesheuvel 174847ece481SArd Biesheuvel .init = stm32_cryp_init_tfm, 17499e054ec2SFabien DESSENNE .min_keysize = AES_MIN_KEY_SIZE, 17509e054ec2SFabien DESSENNE .max_keysize = AES_MAX_KEY_SIZE, 17519e054ec2SFabien DESSENNE .setkey = stm32_cryp_aes_setkey, 17529e054ec2SFabien DESSENNE .encrypt = stm32_cryp_aes_ecb_encrypt, 17539e054ec2SFabien DESSENNE .decrypt = stm32_cryp_aes_ecb_decrypt, 17549e054ec2SFabien DESSENNE }, 17559e054ec2SFabien DESSENNE { 175647ece481SArd Biesheuvel .base.cra_name = "cbc(aes)", 175747ece481SArd Biesheuvel .base.cra_driver_name = "stm32-cbc-aes", 175847ece481SArd Biesheuvel .base.cra_priority = 200, 175947ece481SArd Biesheuvel .base.cra_flags = CRYPTO_ALG_ASYNC, 176047ece481SArd Biesheuvel .base.cra_blocksize = AES_BLOCK_SIZE, 176147ece481SArd Biesheuvel .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx), 176247ece481SArd Biesheuvel .base.cra_alignmask = 0xf, 176347ece481SArd Biesheuvel .base.cra_module = THIS_MODULE, 176447ece481SArd Biesheuvel 176547ece481SArd Biesheuvel .init = stm32_cryp_init_tfm, 17669e054ec2SFabien DESSENNE .min_keysize = AES_MIN_KEY_SIZE, 17679e054ec2SFabien DESSENNE .max_keysize = AES_MAX_KEY_SIZE, 17689e054ec2SFabien DESSENNE .ivsize = AES_BLOCK_SIZE, 17699e054ec2SFabien DESSENNE .setkey = stm32_cryp_aes_setkey, 17709e054ec2SFabien DESSENNE .encrypt = stm32_cryp_aes_cbc_encrypt, 17719e054ec2SFabien DESSENNE .decrypt = stm32_cryp_aes_cbc_decrypt, 17729e054ec2SFabien DESSENNE }, 17739e054ec2SFabien DESSENNE { 177447ece481SArd Biesheuvel .base.cra_name = "ctr(aes)", 177547ece481SArd Biesheuvel .base.cra_driver_name = "stm32-ctr-aes", 177647ece481SArd Biesheuvel .base.cra_priority = 200, 177747ece481SArd Biesheuvel .base.cra_flags = CRYPTO_ALG_ASYNC, 177847ece481SArd Biesheuvel .base.cra_blocksize = 1, 177947ece481SArd Biesheuvel .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx), 178047ece481SArd Biesheuvel .base.cra_alignmask = 0xf, 178147ece481SArd Biesheuvel .base.cra_module = THIS_MODULE, 178247ece481SArd Biesheuvel 178347ece481SArd Biesheuvel .init = stm32_cryp_init_tfm, 17849e054ec2SFabien DESSENNE .min_keysize = AES_MIN_KEY_SIZE, 17859e054ec2SFabien DESSENNE .max_keysize = AES_MAX_KEY_SIZE, 17869e054ec2SFabien DESSENNE .ivsize = AES_BLOCK_SIZE, 17879e054ec2SFabien DESSENNE .setkey = stm32_cryp_aes_setkey, 17889e054ec2SFabien DESSENNE .encrypt = stm32_cryp_aes_ctr_encrypt, 17899e054ec2SFabien DESSENNE .decrypt = stm32_cryp_aes_ctr_decrypt, 17909e054ec2SFabien DESSENNE }, 17919e054ec2SFabien DESSENNE { 179247ece481SArd Biesheuvel .base.cra_name = "ecb(des)", 179347ece481SArd Biesheuvel .base.cra_driver_name = "stm32-ecb-des", 179447ece481SArd Biesheuvel .base.cra_priority = 200, 179547ece481SArd Biesheuvel .base.cra_flags = CRYPTO_ALG_ASYNC, 179647ece481SArd Biesheuvel .base.cra_blocksize = DES_BLOCK_SIZE, 179747ece481SArd Biesheuvel .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx), 179847ece481SArd Biesheuvel .base.cra_alignmask = 0xf, 179947ece481SArd Biesheuvel .base.cra_module = THIS_MODULE, 180047ece481SArd Biesheuvel 180147ece481SArd Biesheuvel .init = stm32_cryp_init_tfm, 18029e054ec2SFabien DESSENNE .min_keysize = DES_BLOCK_SIZE, 18039e054ec2SFabien DESSENNE .max_keysize = DES_BLOCK_SIZE, 18049e054ec2SFabien DESSENNE .setkey = stm32_cryp_des_setkey, 18059e054ec2SFabien DESSENNE .encrypt = stm32_cryp_des_ecb_encrypt, 18069e054ec2SFabien DESSENNE .decrypt = stm32_cryp_des_ecb_decrypt, 18079e054ec2SFabien DESSENNE }, 18089e054ec2SFabien DESSENNE { 180947ece481SArd Biesheuvel .base.cra_name = "cbc(des)", 181047ece481SArd Biesheuvel .base.cra_driver_name = "stm32-cbc-des", 181147ece481SArd Biesheuvel .base.cra_priority = 200, 181247ece481SArd Biesheuvel .base.cra_flags = CRYPTO_ALG_ASYNC, 181347ece481SArd Biesheuvel .base.cra_blocksize = DES_BLOCK_SIZE, 181447ece481SArd Biesheuvel .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx), 181547ece481SArd Biesheuvel .base.cra_alignmask = 0xf, 181647ece481SArd Biesheuvel .base.cra_module = THIS_MODULE, 181747ece481SArd Biesheuvel 181847ece481SArd Biesheuvel .init = stm32_cryp_init_tfm, 18199e054ec2SFabien DESSENNE .min_keysize = DES_BLOCK_SIZE, 18209e054ec2SFabien DESSENNE .max_keysize = DES_BLOCK_SIZE, 18219e054ec2SFabien DESSENNE .ivsize = DES_BLOCK_SIZE, 18229e054ec2SFabien DESSENNE .setkey = stm32_cryp_des_setkey, 18239e054ec2SFabien DESSENNE .encrypt = stm32_cryp_des_cbc_encrypt, 18249e054ec2SFabien DESSENNE .decrypt = stm32_cryp_des_cbc_decrypt, 18259e054ec2SFabien DESSENNE }, 18269e054ec2SFabien DESSENNE { 182747ece481SArd Biesheuvel .base.cra_name = "ecb(des3_ede)", 182847ece481SArd Biesheuvel .base.cra_driver_name = "stm32-ecb-des3", 182947ece481SArd Biesheuvel .base.cra_priority = 200, 183047ece481SArd Biesheuvel .base.cra_flags = CRYPTO_ALG_ASYNC, 183147ece481SArd Biesheuvel .base.cra_blocksize = DES_BLOCK_SIZE, 183247ece481SArd Biesheuvel .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx), 183347ece481SArd Biesheuvel .base.cra_alignmask = 0xf, 183447ece481SArd Biesheuvel .base.cra_module = THIS_MODULE, 183547ece481SArd Biesheuvel 183647ece481SArd Biesheuvel .init = stm32_cryp_init_tfm, 18379e054ec2SFabien DESSENNE .min_keysize = 3 * DES_BLOCK_SIZE, 18389e054ec2SFabien DESSENNE .max_keysize = 3 * DES_BLOCK_SIZE, 18399e054ec2SFabien DESSENNE .setkey = stm32_cryp_tdes_setkey, 18409e054ec2SFabien DESSENNE .encrypt = stm32_cryp_tdes_ecb_encrypt, 18419e054ec2SFabien DESSENNE .decrypt = stm32_cryp_tdes_ecb_decrypt, 18429e054ec2SFabien DESSENNE }, 18439e054ec2SFabien DESSENNE { 184447ece481SArd Biesheuvel .base.cra_name = "cbc(des3_ede)", 184547ece481SArd Biesheuvel .base.cra_driver_name = "stm32-cbc-des3", 184647ece481SArd Biesheuvel .base.cra_priority = 200, 184747ece481SArd Biesheuvel .base.cra_flags = CRYPTO_ALG_ASYNC, 184847ece481SArd Biesheuvel .base.cra_blocksize = DES_BLOCK_SIZE, 184947ece481SArd Biesheuvel .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx), 185047ece481SArd Biesheuvel .base.cra_alignmask = 0xf, 185147ece481SArd Biesheuvel .base.cra_module = THIS_MODULE, 185247ece481SArd Biesheuvel 185347ece481SArd Biesheuvel .init = stm32_cryp_init_tfm, 18549e054ec2SFabien DESSENNE .min_keysize = 3 * DES_BLOCK_SIZE, 18559e054ec2SFabien DESSENNE .max_keysize = 3 * DES_BLOCK_SIZE, 18569e054ec2SFabien DESSENNE .ivsize = DES_BLOCK_SIZE, 18579e054ec2SFabien DESSENNE .setkey = stm32_cryp_tdes_setkey, 18589e054ec2SFabien DESSENNE .encrypt = stm32_cryp_tdes_cbc_encrypt, 18599e054ec2SFabien DESSENNE .decrypt = stm32_cryp_tdes_cbc_decrypt, 18609e054ec2SFabien DESSENNE }, 18619e054ec2SFabien DESSENNE }; 18629e054ec2SFabien DESSENNE 18639d3b5030SFabien DESSENNE static struct aead_alg aead_algs[] = { 18649d3b5030SFabien DESSENNE { 18659d3b5030SFabien DESSENNE .setkey = stm32_cryp_aes_aead_setkey, 18669d3b5030SFabien DESSENNE .setauthsize = stm32_cryp_aes_gcm_setauthsize, 18679d3b5030SFabien DESSENNE .encrypt = stm32_cryp_aes_gcm_encrypt, 18689d3b5030SFabien DESSENNE .decrypt = stm32_cryp_aes_gcm_decrypt, 18699d3b5030SFabien DESSENNE .init = stm32_cryp_aes_aead_init, 18709d3b5030SFabien DESSENNE .ivsize = 12, 18719d3b5030SFabien DESSENNE .maxauthsize = AES_BLOCK_SIZE, 18729d3b5030SFabien DESSENNE 18739d3b5030SFabien DESSENNE .base = { 18749d3b5030SFabien DESSENNE .cra_name = "gcm(aes)", 18759d3b5030SFabien DESSENNE .cra_driver_name = "stm32-gcm-aes", 18769d3b5030SFabien DESSENNE .cra_priority = 200, 18779d3b5030SFabien DESSENNE .cra_flags = CRYPTO_ALG_ASYNC, 18789d3b5030SFabien DESSENNE .cra_blocksize = 1, 18799d3b5030SFabien DESSENNE .cra_ctxsize = sizeof(struct stm32_cryp_ctx), 18809d3b5030SFabien DESSENNE .cra_alignmask = 0xf, 18819d3b5030SFabien DESSENNE .cra_module = THIS_MODULE, 18829d3b5030SFabien DESSENNE }, 18839d3b5030SFabien DESSENNE }, 18849d3b5030SFabien DESSENNE { 18859d3b5030SFabien DESSENNE .setkey = stm32_cryp_aes_aead_setkey, 18869d3b5030SFabien DESSENNE .setauthsize = stm32_cryp_aes_ccm_setauthsize, 18879d3b5030SFabien DESSENNE .encrypt = stm32_cryp_aes_ccm_encrypt, 18889d3b5030SFabien DESSENNE .decrypt = stm32_cryp_aes_ccm_decrypt, 18899d3b5030SFabien DESSENNE .init = stm32_cryp_aes_aead_init, 18909d3b5030SFabien DESSENNE .ivsize = AES_BLOCK_SIZE, 18919d3b5030SFabien DESSENNE .maxauthsize = AES_BLOCK_SIZE, 18929d3b5030SFabien DESSENNE 18939d3b5030SFabien DESSENNE .base = { 18949d3b5030SFabien DESSENNE .cra_name = "ccm(aes)", 18959d3b5030SFabien DESSENNE .cra_driver_name = "stm32-ccm-aes", 18969d3b5030SFabien DESSENNE .cra_priority = 200, 18979d3b5030SFabien DESSENNE .cra_flags = CRYPTO_ALG_ASYNC, 18989d3b5030SFabien DESSENNE .cra_blocksize = 1, 18999d3b5030SFabien DESSENNE .cra_ctxsize = sizeof(struct stm32_cryp_ctx), 19009d3b5030SFabien DESSENNE .cra_alignmask = 0xf, 19019d3b5030SFabien DESSENNE .cra_module = THIS_MODULE, 19029d3b5030SFabien DESSENNE }, 19039d3b5030SFabien DESSENNE }, 19049d3b5030SFabien DESSENNE }; 19059d3b5030SFabien DESSENNE 19069d3b5030SFabien DESSENNE static const struct stm32_cryp_caps f7_data = { 19079d3b5030SFabien DESSENNE .swap_final = true, 19089d3b5030SFabien DESSENNE .padding_wa = true, 19099d3b5030SFabien DESSENNE }; 19109d3b5030SFabien DESSENNE 1911a43a3484SFabien DESSENNE static const struct stm32_cryp_caps mp1_data = { 1912a43a3484SFabien DESSENNE .swap_final = false, 1913a43a3484SFabien DESSENNE .padding_wa = false, 1914a43a3484SFabien DESSENNE }; 1915a43a3484SFabien DESSENNE 19169e054ec2SFabien DESSENNE static const struct of_device_id stm32_dt_ids[] = { 19179d3b5030SFabien DESSENNE { .compatible = "st,stm32f756-cryp", .data = &f7_data}, 1918a43a3484SFabien DESSENNE { .compatible = "st,stm32mp1-cryp", .data = &mp1_data}, 19199e054ec2SFabien DESSENNE {}, 19209e054ec2SFabien DESSENNE }; 1921761a6982SCorentin LABBE MODULE_DEVICE_TABLE(of, stm32_dt_ids); 19229e054ec2SFabien DESSENNE 19239e054ec2SFabien DESSENNE static int stm32_cryp_probe(struct platform_device *pdev) 19249e054ec2SFabien DESSENNE { 19259e054ec2SFabien DESSENNE struct device *dev = &pdev->dev; 19269e054ec2SFabien DESSENNE struct stm32_cryp *cryp; 19279e054ec2SFabien DESSENNE struct reset_control *rst; 19289e054ec2SFabien DESSENNE int irq, ret; 19299e054ec2SFabien DESSENNE 19309e054ec2SFabien DESSENNE cryp = devm_kzalloc(dev, sizeof(*cryp), GFP_KERNEL); 19319e054ec2SFabien DESSENNE if (!cryp) 19329e054ec2SFabien DESSENNE return -ENOMEM; 19339e054ec2SFabien DESSENNE 19349d3b5030SFabien DESSENNE cryp->caps = of_device_get_match_data(dev); 19359d3b5030SFabien DESSENNE if (!cryp->caps) 19369d3b5030SFabien DESSENNE return -ENODEV; 19379d3b5030SFabien DESSENNE 19389e054ec2SFabien DESSENNE cryp->dev = dev; 19399e054ec2SFabien DESSENNE 1940473b4d99SYueHaibing cryp->regs = devm_platform_ioremap_resource(pdev, 0); 194160bcf265Sweiyongjun \(A\) if (IS_ERR(cryp->regs)) 19429e054ec2SFabien DESSENNE return PTR_ERR(cryp->regs); 19439e054ec2SFabien DESSENNE 19449e054ec2SFabien DESSENNE irq = platform_get_irq(pdev, 0); 1945514838e9SStephen Boyd if (irq < 0) 19469e054ec2SFabien DESSENNE return irq; 19479e054ec2SFabien DESSENNE 19489e054ec2SFabien DESSENNE ret = devm_request_threaded_irq(dev, irq, stm32_cryp_irq, 19499e054ec2SFabien DESSENNE stm32_cryp_irq_thread, IRQF_ONESHOT, 19509e054ec2SFabien DESSENNE dev_name(dev), cryp); 19519e054ec2SFabien DESSENNE if (ret) { 19529e054ec2SFabien DESSENNE dev_err(dev, "Cannot grab IRQ\n"); 19539e054ec2SFabien DESSENNE return ret; 19549e054ec2SFabien DESSENNE } 19559e054ec2SFabien DESSENNE 19569e054ec2SFabien DESSENNE cryp->clk = devm_clk_get(dev, NULL); 19579e054ec2SFabien DESSENNE if (IS_ERR(cryp->clk)) { 19589e054ec2SFabien DESSENNE dev_err(dev, "Could not get clock\n"); 19599e054ec2SFabien DESSENNE return PTR_ERR(cryp->clk); 19609e054ec2SFabien DESSENNE } 19619e054ec2SFabien DESSENNE 19629e054ec2SFabien DESSENNE ret = clk_prepare_enable(cryp->clk); 19639e054ec2SFabien DESSENNE if (ret) { 19649e054ec2SFabien DESSENNE dev_err(cryp->dev, "Failed to enable clock\n"); 19659e054ec2SFabien DESSENNE return ret; 19669e054ec2SFabien DESSENNE } 19679e054ec2SFabien DESSENNE 196865f9aa36Slionel.debieve@st.com pm_runtime_set_autosuspend_delay(dev, CRYP_AUTOSUSPEND_DELAY); 196965f9aa36Slionel.debieve@st.com pm_runtime_use_autosuspend(dev); 197065f9aa36Slionel.debieve@st.com 197165f9aa36Slionel.debieve@st.com pm_runtime_get_noresume(dev); 197265f9aa36Slionel.debieve@st.com pm_runtime_set_active(dev); 197365f9aa36Slionel.debieve@st.com pm_runtime_enable(dev); 197465f9aa36Slionel.debieve@st.com 19759e054ec2SFabien DESSENNE rst = devm_reset_control_get(dev, NULL); 19769e054ec2SFabien DESSENNE if (!IS_ERR(rst)) { 19779e054ec2SFabien DESSENNE reset_control_assert(rst); 19789e054ec2SFabien DESSENNE udelay(2); 19799e054ec2SFabien DESSENNE reset_control_deassert(rst); 19809e054ec2SFabien DESSENNE } 19819e054ec2SFabien DESSENNE 19829e054ec2SFabien DESSENNE platform_set_drvdata(pdev, cryp); 19839e054ec2SFabien DESSENNE 19849e054ec2SFabien DESSENNE spin_lock(&cryp_list.lock); 19859e054ec2SFabien DESSENNE list_add(&cryp->list, &cryp_list.dev_list); 19869e054ec2SFabien DESSENNE spin_unlock(&cryp_list.lock); 19879e054ec2SFabien DESSENNE 19889e054ec2SFabien DESSENNE /* Initialize crypto engine */ 19899e054ec2SFabien DESSENNE cryp->engine = crypto_engine_alloc_init(dev, 1); 19909e054ec2SFabien DESSENNE if (!cryp->engine) { 19919e054ec2SFabien DESSENNE dev_err(dev, "Could not init crypto engine\n"); 19929e054ec2SFabien DESSENNE ret = -ENOMEM; 19939e054ec2SFabien DESSENNE goto err_engine1; 19949e054ec2SFabien DESSENNE } 19959e054ec2SFabien DESSENNE 19969e054ec2SFabien DESSENNE ret = crypto_engine_start(cryp->engine); 19979e054ec2SFabien DESSENNE if (ret) { 19989e054ec2SFabien DESSENNE dev_err(dev, "Could not start crypto engine\n"); 19999e054ec2SFabien DESSENNE goto err_engine2; 20009e054ec2SFabien DESSENNE } 20019e054ec2SFabien DESSENNE 200247ece481SArd Biesheuvel ret = crypto_register_skciphers(crypto_algs, ARRAY_SIZE(crypto_algs)); 20039e054ec2SFabien DESSENNE if (ret) { 20049e054ec2SFabien DESSENNE dev_err(dev, "Could not register algs\n"); 20059e054ec2SFabien DESSENNE goto err_algs; 20069e054ec2SFabien DESSENNE } 20079e054ec2SFabien DESSENNE 20089d3b5030SFabien DESSENNE ret = crypto_register_aeads(aead_algs, ARRAY_SIZE(aead_algs)); 20099d3b5030SFabien DESSENNE if (ret) 20109d3b5030SFabien DESSENNE goto err_aead_algs; 20119d3b5030SFabien DESSENNE 20129e054ec2SFabien DESSENNE dev_info(dev, "Initialized\n"); 20139e054ec2SFabien DESSENNE 201465f9aa36Slionel.debieve@st.com pm_runtime_put_sync(dev); 201565f9aa36Slionel.debieve@st.com 20169e054ec2SFabien DESSENNE return 0; 20179e054ec2SFabien DESSENNE 20189d3b5030SFabien DESSENNE err_aead_algs: 201947ece481SArd Biesheuvel crypto_unregister_skciphers(crypto_algs, ARRAY_SIZE(crypto_algs)); 20209e054ec2SFabien DESSENNE err_algs: 20219e054ec2SFabien DESSENNE err_engine2: 20229e054ec2SFabien DESSENNE crypto_engine_exit(cryp->engine); 20239e054ec2SFabien DESSENNE err_engine1: 20249e054ec2SFabien DESSENNE spin_lock(&cryp_list.lock); 20259e054ec2SFabien DESSENNE list_del(&cryp->list); 20269e054ec2SFabien DESSENNE spin_unlock(&cryp_list.lock); 20279e054ec2SFabien DESSENNE 202865f9aa36Slionel.debieve@st.com pm_runtime_disable(dev); 202965f9aa36Slionel.debieve@st.com pm_runtime_put_noidle(dev); 203065f9aa36Slionel.debieve@st.com pm_runtime_disable(dev); 203165f9aa36Slionel.debieve@st.com pm_runtime_put_noidle(dev); 203265f9aa36Slionel.debieve@st.com 20339e054ec2SFabien DESSENNE clk_disable_unprepare(cryp->clk); 20349e054ec2SFabien DESSENNE 20359e054ec2SFabien DESSENNE return ret; 20369e054ec2SFabien DESSENNE } 20379e054ec2SFabien DESSENNE 20389e054ec2SFabien DESSENNE static int stm32_cryp_remove(struct platform_device *pdev) 20399e054ec2SFabien DESSENNE { 20409e054ec2SFabien DESSENNE struct stm32_cryp *cryp = platform_get_drvdata(pdev); 204165f9aa36Slionel.debieve@st.com int ret; 20429e054ec2SFabien DESSENNE 20439e054ec2SFabien DESSENNE if (!cryp) 20449e054ec2SFabien DESSENNE return -ENODEV; 20459e054ec2SFabien DESSENNE 204665f9aa36Slionel.debieve@st.com ret = pm_runtime_get_sync(cryp->dev); 204765f9aa36Slionel.debieve@st.com if (ret < 0) 204865f9aa36Slionel.debieve@st.com return ret; 204965f9aa36Slionel.debieve@st.com 20509d3b5030SFabien DESSENNE crypto_unregister_aeads(aead_algs, ARRAY_SIZE(aead_algs)); 205147ece481SArd Biesheuvel crypto_unregister_skciphers(crypto_algs, ARRAY_SIZE(crypto_algs)); 20529e054ec2SFabien DESSENNE 20539e054ec2SFabien DESSENNE crypto_engine_exit(cryp->engine); 20549e054ec2SFabien DESSENNE 20559e054ec2SFabien DESSENNE spin_lock(&cryp_list.lock); 20569e054ec2SFabien DESSENNE list_del(&cryp->list); 20579e054ec2SFabien DESSENNE spin_unlock(&cryp_list.lock); 20589e054ec2SFabien DESSENNE 205965f9aa36Slionel.debieve@st.com pm_runtime_disable(cryp->dev); 206065f9aa36Slionel.debieve@st.com pm_runtime_put_noidle(cryp->dev); 206165f9aa36Slionel.debieve@st.com 20629e054ec2SFabien DESSENNE clk_disable_unprepare(cryp->clk); 20639e054ec2SFabien DESSENNE 20649e054ec2SFabien DESSENNE return 0; 20659e054ec2SFabien DESSENNE } 20669e054ec2SFabien DESSENNE 206765f9aa36Slionel.debieve@st.com #ifdef CONFIG_PM 206865f9aa36Slionel.debieve@st.com static int stm32_cryp_runtime_suspend(struct device *dev) 206965f9aa36Slionel.debieve@st.com { 207065f9aa36Slionel.debieve@st.com struct stm32_cryp *cryp = dev_get_drvdata(dev); 207165f9aa36Slionel.debieve@st.com 207265f9aa36Slionel.debieve@st.com clk_disable_unprepare(cryp->clk); 207365f9aa36Slionel.debieve@st.com 207465f9aa36Slionel.debieve@st.com return 0; 207565f9aa36Slionel.debieve@st.com } 207665f9aa36Slionel.debieve@st.com 207765f9aa36Slionel.debieve@st.com static int stm32_cryp_runtime_resume(struct device *dev) 207865f9aa36Slionel.debieve@st.com { 207965f9aa36Slionel.debieve@st.com struct stm32_cryp *cryp = dev_get_drvdata(dev); 208065f9aa36Slionel.debieve@st.com int ret; 208165f9aa36Slionel.debieve@st.com 208265f9aa36Slionel.debieve@st.com ret = clk_prepare_enable(cryp->clk); 208365f9aa36Slionel.debieve@st.com if (ret) { 208465f9aa36Slionel.debieve@st.com dev_err(cryp->dev, "Failed to prepare_enable clock\n"); 208565f9aa36Slionel.debieve@st.com return ret; 208665f9aa36Slionel.debieve@st.com } 208765f9aa36Slionel.debieve@st.com 208865f9aa36Slionel.debieve@st.com return 0; 208965f9aa36Slionel.debieve@st.com } 209065f9aa36Slionel.debieve@st.com #endif 209165f9aa36Slionel.debieve@st.com 209265f9aa36Slionel.debieve@st.com static const struct dev_pm_ops stm32_cryp_pm_ops = { 209365f9aa36Slionel.debieve@st.com SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 209465f9aa36Slionel.debieve@st.com pm_runtime_force_resume) 209565f9aa36Slionel.debieve@st.com SET_RUNTIME_PM_OPS(stm32_cryp_runtime_suspend, 209665f9aa36Slionel.debieve@st.com stm32_cryp_runtime_resume, NULL) 209765f9aa36Slionel.debieve@st.com }; 209865f9aa36Slionel.debieve@st.com 20999e054ec2SFabien DESSENNE static struct platform_driver stm32_cryp_driver = { 21009e054ec2SFabien DESSENNE .probe = stm32_cryp_probe, 21019e054ec2SFabien DESSENNE .remove = stm32_cryp_remove, 21029e054ec2SFabien DESSENNE .driver = { 21039e054ec2SFabien DESSENNE .name = DRIVER_NAME, 210465f9aa36Slionel.debieve@st.com .pm = &stm32_cryp_pm_ops, 21059e054ec2SFabien DESSENNE .of_match_table = stm32_dt_ids, 21069e054ec2SFabien DESSENNE }, 21079e054ec2SFabien DESSENNE }; 21089e054ec2SFabien DESSENNE 21099e054ec2SFabien DESSENNE module_platform_driver(stm32_cryp_driver); 21109e054ec2SFabien DESSENNE 21119e054ec2SFabien DESSENNE MODULE_AUTHOR("Fabien Dessenne <fabien.dessenne@st.com>"); 21129e054ec2SFabien DESSENNE MODULE_DESCRIPTION("STMicrolectronics STM32 CRYP hardware driver"); 21139e054ec2SFabien DESSENNE MODULE_LICENSE("GPL"); 2114