18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * sun4i-ss-cipher.c - hardware cryptographic accelerator for Allwinner A20 SoC 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2013-2015 Corentin LABBE <clabbe.montjoie@gmail.com> 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * This file add support for AES cipher with 128,192,256 bits 88c2ecf20Sopenharmony_ci * keysize in CBC and ECB mode. 98c2ecf20Sopenharmony_ci * Add support also for DES and 3DES in CBC and ECB mode. 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * You could find the datasheet in Documentation/arm/sunxi.rst 128c2ecf20Sopenharmony_ci */ 138c2ecf20Sopenharmony_ci#include "sun4i-ss.h" 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_cistatic int noinline_for_stack sun4i_ss_opti_poll(struct skcipher_request *areq) 168c2ecf20Sopenharmony_ci{ 178c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq); 188c2ecf20Sopenharmony_ci struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm); 198c2ecf20Sopenharmony_ci struct sun4i_ss_ctx *ss = op->ss; 208c2ecf20Sopenharmony_ci unsigned int ivsize = crypto_skcipher_ivsize(tfm); 218c2ecf20Sopenharmony_ci struct sun4i_cipher_req_ctx *ctx = skcipher_request_ctx(areq); 228c2ecf20Sopenharmony_ci u32 mode = ctx->mode; 238c2ecf20Sopenharmony_ci void *backup_iv = NULL; 248c2ecf20Sopenharmony_ci /* when activating SS, the default FIFO space is SS_RX_DEFAULT(32) */ 258c2ecf20Sopenharmony_ci u32 rx_cnt = SS_RX_DEFAULT; 268c2ecf20Sopenharmony_ci u32 tx_cnt = 0; 278c2ecf20Sopenharmony_ci u32 spaces; 288c2ecf20Sopenharmony_ci u32 v; 298c2ecf20Sopenharmony_ci int err = 0; 308c2ecf20Sopenharmony_ci unsigned int i; 318c2ecf20Sopenharmony_ci unsigned int ileft = areq->cryptlen; 328c2ecf20Sopenharmony_ci unsigned int oleft = areq->cryptlen; 338c2ecf20Sopenharmony_ci unsigned int todo; 348c2ecf20Sopenharmony_ci unsigned long pi = 0, po = 0; /* progress for in and out */ 358c2ecf20Sopenharmony_ci bool miter_err; 368c2ecf20Sopenharmony_ci struct sg_mapping_iter mi, mo; 378c2ecf20Sopenharmony_ci unsigned int oi, oo; /* offset for in and out */ 388c2ecf20Sopenharmony_ci unsigned long flags; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci if (!areq->cryptlen) 418c2ecf20Sopenharmony_ci return 0; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci if (!areq->src || !areq->dst) { 448c2ecf20Sopenharmony_ci dev_err_ratelimited(ss->dev, "ERROR: Some SGs are NULL\n"); 458c2ecf20Sopenharmony_ci return -EINVAL; 468c2ecf20Sopenharmony_ci } 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci if (areq->iv && ivsize > 0 && mode & SS_DECRYPTION) { 498c2ecf20Sopenharmony_ci backup_iv = kzalloc(ivsize, GFP_KERNEL); 508c2ecf20Sopenharmony_ci if (!backup_iv) 518c2ecf20Sopenharmony_ci return -ENOMEM; 528c2ecf20Sopenharmony_ci scatterwalk_map_and_copy(backup_iv, areq->src, areq->cryptlen - ivsize, ivsize, 0); 538c2ecf20Sopenharmony_ci } 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci spin_lock_irqsave(&ss->slock, flags); 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci for (i = 0; i < op->keylen / 4; i++) 588c2ecf20Sopenharmony_ci writesl(ss->base + SS_KEY0 + i * 4, &op->key[i], 1); 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci if (areq->iv) { 618c2ecf20Sopenharmony_ci for (i = 0; i < 4 && i < ivsize / 4; i++) { 628c2ecf20Sopenharmony_ci v = *(u32 *)(areq->iv + i * 4); 638c2ecf20Sopenharmony_ci writesl(ss->base + SS_IV0 + i * 4, &v, 1); 648c2ecf20Sopenharmony_ci } 658c2ecf20Sopenharmony_ci } 668c2ecf20Sopenharmony_ci writel(mode, ss->base + SS_CTL); 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci ileft = areq->cryptlen / 4; 708c2ecf20Sopenharmony_ci oleft = areq->cryptlen / 4; 718c2ecf20Sopenharmony_ci oi = 0; 728c2ecf20Sopenharmony_ci oo = 0; 738c2ecf20Sopenharmony_ci do { 748c2ecf20Sopenharmony_ci if (ileft) { 758c2ecf20Sopenharmony_ci sg_miter_start(&mi, areq->src, sg_nents(areq->src), 768c2ecf20Sopenharmony_ci SG_MITER_FROM_SG | SG_MITER_ATOMIC); 778c2ecf20Sopenharmony_ci if (pi) 788c2ecf20Sopenharmony_ci sg_miter_skip(&mi, pi); 798c2ecf20Sopenharmony_ci miter_err = sg_miter_next(&mi); 808c2ecf20Sopenharmony_ci if (!miter_err || !mi.addr) { 818c2ecf20Sopenharmony_ci dev_err_ratelimited(ss->dev, "ERROR: sg_miter return null\n"); 828c2ecf20Sopenharmony_ci err = -EINVAL; 838c2ecf20Sopenharmony_ci goto release_ss; 848c2ecf20Sopenharmony_ci } 858c2ecf20Sopenharmony_ci todo = min(rx_cnt, ileft); 868c2ecf20Sopenharmony_ci todo = min_t(size_t, todo, (mi.length - oi) / 4); 878c2ecf20Sopenharmony_ci if (todo) { 888c2ecf20Sopenharmony_ci ileft -= todo; 898c2ecf20Sopenharmony_ci writesl(ss->base + SS_RXFIFO, mi.addr + oi, todo); 908c2ecf20Sopenharmony_ci oi += todo * 4; 918c2ecf20Sopenharmony_ci } 928c2ecf20Sopenharmony_ci if (oi == mi.length) { 938c2ecf20Sopenharmony_ci pi += mi.length; 948c2ecf20Sopenharmony_ci oi = 0; 958c2ecf20Sopenharmony_ci } 968c2ecf20Sopenharmony_ci sg_miter_stop(&mi); 978c2ecf20Sopenharmony_ci } 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci spaces = readl(ss->base + SS_FCSR); 1008c2ecf20Sopenharmony_ci rx_cnt = SS_RXFIFO_SPACES(spaces); 1018c2ecf20Sopenharmony_ci tx_cnt = SS_TXFIFO_SPACES(spaces); 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci sg_miter_start(&mo, areq->dst, sg_nents(areq->dst), 1048c2ecf20Sopenharmony_ci SG_MITER_TO_SG | SG_MITER_ATOMIC); 1058c2ecf20Sopenharmony_ci if (po) 1068c2ecf20Sopenharmony_ci sg_miter_skip(&mo, po); 1078c2ecf20Sopenharmony_ci miter_err = sg_miter_next(&mo); 1088c2ecf20Sopenharmony_ci if (!miter_err || !mo.addr) { 1098c2ecf20Sopenharmony_ci dev_err_ratelimited(ss->dev, "ERROR: sg_miter return null\n"); 1108c2ecf20Sopenharmony_ci err = -EINVAL; 1118c2ecf20Sopenharmony_ci goto release_ss; 1128c2ecf20Sopenharmony_ci } 1138c2ecf20Sopenharmony_ci todo = min(tx_cnt, oleft); 1148c2ecf20Sopenharmony_ci todo = min_t(size_t, todo, (mo.length - oo) / 4); 1158c2ecf20Sopenharmony_ci if (todo) { 1168c2ecf20Sopenharmony_ci oleft -= todo; 1178c2ecf20Sopenharmony_ci readsl(ss->base + SS_TXFIFO, mo.addr + oo, todo); 1188c2ecf20Sopenharmony_ci oo += todo * 4; 1198c2ecf20Sopenharmony_ci } 1208c2ecf20Sopenharmony_ci if (oo == mo.length) { 1218c2ecf20Sopenharmony_ci oo = 0; 1228c2ecf20Sopenharmony_ci po += mo.length; 1238c2ecf20Sopenharmony_ci } 1248c2ecf20Sopenharmony_ci sg_miter_stop(&mo); 1258c2ecf20Sopenharmony_ci } while (oleft); 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci if (areq->iv) { 1288c2ecf20Sopenharmony_ci if (mode & SS_DECRYPTION) { 1298c2ecf20Sopenharmony_ci memcpy(areq->iv, backup_iv, ivsize); 1308c2ecf20Sopenharmony_ci kfree_sensitive(backup_iv); 1318c2ecf20Sopenharmony_ci } else { 1328c2ecf20Sopenharmony_ci scatterwalk_map_and_copy(areq->iv, areq->dst, areq->cryptlen - ivsize, 1338c2ecf20Sopenharmony_ci ivsize, 0); 1348c2ecf20Sopenharmony_ci } 1358c2ecf20Sopenharmony_ci } 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_cirelease_ss: 1388c2ecf20Sopenharmony_ci writel(0, ss->base + SS_CTL); 1398c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ss->slock, flags); 1408c2ecf20Sopenharmony_ci return err; 1418c2ecf20Sopenharmony_ci} 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_cistatic int noinline_for_stack sun4i_ss_cipher_poll_fallback(struct skcipher_request *areq) 1458c2ecf20Sopenharmony_ci{ 1468c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq); 1478c2ecf20Sopenharmony_ci struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm); 1488c2ecf20Sopenharmony_ci struct sun4i_cipher_req_ctx *ctx = skcipher_request_ctx(areq); 1498c2ecf20Sopenharmony_ci int err; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci skcipher_request_set_tfm(&ctx->fallback_req, op->fallback_tfm); 1528c2ecf20Sopenharmony_ci skcipher_request_set_callback(&ctx->fallback_req, areq->base.flags, 1538c2ecf20Sopenharmony_ci areq->base.complete, areq->base.data); 1548c2ecf20Sopenharmony_ci skcipher_request_set_crypt(&ctx->fallback_req, areq->src, areq->dst, 1558c2ecf20Sopenharmony_ci areq->cryptlen, areq->iv); 1568c2ecf20Sopenharmony_ci if (ctx->mode & SS_DECRYPTION) 1578c2ecf20Sopenharmony_ci err = crypto_skcipher_decrypt(&ctx->fallback_req); 1588c2ecf20Sopenharmony_ci else 1598c2ecf20Sopenharmony_ci err = crypto_skcipher_encrypt(&ctx->fallback_req); 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci return err; 1628c2ecf20Sopenharmony_ci} 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci/* Generic function that support SG with size not multiple of 4 */ 1658c2ecf20Sopenharmony_cistatic int sun4i_ss_cipher_poll(struct skcipher_request *areq) 1668c2ecf20Sopenharmony_ci{ 1678c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq); 1688c2ecf20Sopenharmony_ci struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm); 1698c2ecf20Sopenharmony_ci struct sun4i_ss_ctx *ss = op->ss; 1708c2ecf20Sopenharmony_ci int no_chunk = 1; 1718c2ecf20Sopenharmony_ci struct scatterlist *in_sg = areq->src; 1728c2ecf20Sopenharmony_ci struct scatterlist *out_sg = areq->dst; 1738c2ecf20Sopenharmony_ci unsigned int ivsize = crypto_skcipher_ivsize(tfm); 1748c2ecf20Sopenharmony_ci struct sun4i_cipher_req_ctx *ctx = skcipher_request_ctx(areq); 1758c2ecf20Sopenharmony_ci struct skcipher_alg *alg = crypto_skcipher_alg(tfm); 1768c2ecf20Sopenharmony_ci struct sun4i_ss_alg_template *algt; 1778c2ecf20Sopenharmony_ci u32 mode = ctx->mode; 1788c2ecf20Sopenharmony_ci /* when activating SS, the default FIFO space is SS_RX_DEFAULT(32) */ 1798c2ecf20Sopenharmony_ci u32 rx_cnt = SS_RX_DEFAULT; 1808c2ecf20Sopenharmony_ci u32 tx_cnt = 0; 1818c2ecf20Sopenharmony_ci u32 v; 1828c2ecf20Sopenharmony_ci u32 spaces; 1838c2ecf20Sopenharmony_ci int err = 0; 1848c2ecf20Sopenharmony_ci unsigned int i; 1858c2ecf20Sopenharmony_ci unsigned int ileft = areq->cryptlen; 1868c2ecf20Sopenharmony_ci unsigned int oleft = areq->cryptlen; 1878c2ecf20Sopenharmony_ci unsigned int todo; 1888c2ecf20Sopenharmony_ci void *backup_iv = NULL; 1898c2ecf20Sopenharmony_ci struct sg_mapping_iter mi, mo; 1908c2ecf20Sopenharmony_ci unsigned long pi = 0, po = 0; /* progress for in and out */ 1918c2ecf20Sopenharmony_ci bool miter_err; 1928c2ecf20Sopenharmony_ci unsigned int oi, oo; /* offset for in and out */ 1938c2ecf20Sopenharmony_ci unsigned int ob = 0; /* offset in buf */ 1948c2ecf20Sopenharmony_ci unsigned int obo = 0; /* offset in bufo*/ 1958c2ecf20Sopenharmony_ci unsigned int obl = 0; /* length of data in bufo */ 1968c2ecf20Sopenharmony_ci unsigned long flags; 1978c2ecf20Sopenharmony_ci bool need_fallback = false; 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci if (!areq->cryptlen) 2008c2ecf20Sopenharmony_ci return 0; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci if (!areq->src || !areq->dst) { 2038c2ecf20Sopenharmony_ci dev_err_ratelimited(ss->dev, "ERROR: Some SGs are NULL\n"); 2048c2ecf20Sopenharmony_ci return -EINVAL; 2058c2ecf20Sopenharmony_ci } 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci algt = container_of(alg, struct sun4i_ss_alg_template, alg.crypto); 2088c2ecf20Sopenharmony_ci if (areq->cryptlen % algt->alg.crypto.base.cra_blocksize) 2098c2ecf20Sopenharmony_ci need_fallback = true; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci /* 2128c2ecf20Sopenharmony_ci * if we have only SGs with size multiple of 4, 2138c2ecf20Sopenharmony_ci * we can use the SS optimized function 2148c2ecf20Sopenharmony_ci */ 2158c2ecf20Sopenharmony_ci while (in_sg && no_chunk == 1) { 2168c2ecf20Sopenharmony_ci if ((in_sg->length | in_sg->offset) & 3u) 2178c2ecf20Sopenharmony_ci no_chunk = 0; 2188c2ecf20Sopenharmony_ci in_sg = sg_next(in_sg); 2198c2ecf20Sopenharmony_ci } 2208c2ecf20Sopenharmony_ci while (out_sg && no_chunk == 1) { 2218c2ecf20Sopenharmony_ci if ((out_sg->length | out_sg->offset) & 3u) 2228c2ecf20Sopenharmony_ci no_chunk = 0; 2238c2ecf20Sopenharmony_ci out_sg = sg_next(out_sg); 2248c2ecf20Sopenharmony_ci } 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci if (no_chunk == 1 && !need_fallback) 2278c2ecf20Sopenharmony_ci return sun4i_ss_opti_poll(areq); 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci if (need_fallback) 2308c2ecf20Sopenharmony_ci return sun4i_ss_cipher_poll_fallback(areq); 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci if (areq->iv && ivsize > 0 && mode & SS_DECRYPTION) { 2338c2ecf20Sopenharmony_ci backup_iv = kzalloc(ivsize, GFP_KERNEL); 2348c2ecf20Sopenharmony_ci if (!backup_iv) 2358c2ecf20Sopenharmony_ci return -ENOMEM; 2368c2ecf20Sopenharmony_ci scatterwalk_map_and_copy(backup_iv, areq->src, areq->cryptlen - ivsize, ivsize, 0); 2378c2ecf20Sopenharmony_ci } 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci spin_lock_irqsave(&ss->slock, flags); 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci for (i = 0; i < op->keylen / 4; i++) 2428c2ecf20Sopenharmony_ci writesl(ss->base + SS_KEY0 + i * 4, &op->key[i], 1); 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci if (areq->iv) { 2458c2ecf20Sopenharmony_ci for (i = 0; i < 4 && i < ivsize / 4; i++) { 2468c2ecf20Sopenharmony_ci v = *(u32 *)(areq->iv + i * 4); 2478c2ecf20Sopenharmony_ci writesl(ss->base + SS_IV0 + i * 4, &v, 1); 2488c2ecf20Sopenharmony_ci } 2498c2ecf20Sopenharmony_ci } 2508c2ecf20Sopenharmony_ci writel(mode, ss->base + SS_CTL); 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci ileft = areq->cryptlen; 2538c2ecf20Sopenharmony_ci oleft = areq->cryptlen; 2548c2ecf20Sopenharmony_ci oi = 0; 2558c2ecf20Sopenharmony_ci oo = 0; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci while (oleft) { 2588c2ecf20Sopenharmony_ci if (ileft) { 2598c2ecf20Sopenharmony_ci sg_miter_start(&mi, areq->src, sg_nents(areq->src), 2608c2ecf20Sopenharmony_ci SG_MITER_FROM_SG | SG_MITER_ATOMIC); 2618c2ecf20Sopenharmony_ci if (pi) 2628c2ecf20Sopenharmony_ci sg_miter_skip(&mi, pi); 2638c2ecf20Sopenharmony_ci miter_err = sg_miter_next(&mi); 2648c2ecf20Sopenharmony_ci if (!miter_err || !mi.addr) { 2658c2ecf20Sopenharmony_ci dev_err_ratelimited(ss->dev, "ERROR: sg_miter return null\n"); 2668c2ecf20Sopenharmony_ci err = -EINVAL; 2678c2ecf20Sopenharmony_ci goto release_ss; 2688c2ecf20Sopenharmony_ci } 2698c2ecf20Sopenharmony_ci /* 2708c2ecf20Sopenharmony_ci * todo is the number of consecutive 4byte word that we 2718c2ecf20Sopenharmony_ci * can read from current SG 2728c2ecf20Sopenharmony_ci */ 2738c2ecf20Sopenharmony_ci todo = min(rx_cnt, ileft / 4); 2748c2ecf20Sopenharmony_ci todo = min_t(size_t, todo, (mi.length - oi) / 4); 2758c2ecf20Sopenharmony_ci if (todo && !ob) { 2768c2ecf20Sopenharmony_ci writesl(ss->base + SS_RXFIFO, mi.addr + oi, 2778c2ecf20Sopenharmony_ci todo); 2788c2ecf20Sopenharmony_ci ileft -= todo * 4; 2798c2ecf20Sopenharmony_ci oi += todo * 4; 2808c2ecf20Sopenharmony_ci } else { 2818c2ecf20Sopenharmony_ci /* 2828c2ecf20Sopenharmony_ci * not enough consecutive bytes, so we need to 2838c2ecf20Sopenharmony_ci * linearize in buf. todo is in bytes 2848c2ecf20Sopenharmony_ci * After that copy, if we have a multiple of 4 2858c2ecf20Sopenharmony_ci * we need to be able to write all buf in one 2868c2ecf20Sopenharmony_ci * pass, so it is why we min() with rx_cnt 2878c2ecf20Sopenharmony_ci */ 2888c2ecf20Sopenharmony_ci todo = min(rx_cnt * 4 - ob, ileft); 2898c2ecf20Sopenharmony_ci todo = min_t(size_t, todo, mi.length - oi); 2908c2ecf20Sopenharmony_ci memcpy(ss->buf + ob, mi.addr + oi, todo); 2918c2ecf20Sopenharmony_ci ileft -= todo; 2928c2ecf20Sopenharmony_ci oi += todo; 2938c2ecf20Sopenharmony_ci ob += todo; 2948c2ecf20Sopenharmony_ci if (!(ob % 4)) { 2958c2ecf20Sopenharmony_ci writesl(ss->base + SS_RXFIFO, ss->buf, 2968c2ecf20Sopenharmony_ci ob / 4); 2978c2ecf20Sopenharmony_ci ob = 0; 2988c2ecf20Sopenharmony_ci } 2998c2ecf20Sopenharmony_ci } 3008c2ecf20Sopenharmony_ci if (oi == mi.length) { 3018c2ecf20Sopenharmony_ci pi += mi.length; 3028c2ecf20Sopenharmony_ci oi = 0; 3038c2ecf20Sopenharmony_ci } 3048c2ecf20Sopenharmony_ci sg_miter_stop(&mi); 3058c2ecf20Sopenharmony_ci } 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci spaces = readl(ss->base + SS_FCSR); 3088c2ecf20Sopenharmony_ci rx_cnt = SS_RXFIFO_SPACES(spaces); 3098c2ecf20Sopenharmony_ci tx_cnt = SS_TXFIFO_SPACES(spaces); 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci if (!tx_cnt) 3128c2ecf20Sopenharmony_ci continue; 3138c2ecf20Sopenharmony_ci sg_miter_start(&mo, areq->dst, sg_nents(areq->dst), 3148c2ecf20Sopenharmony_ci SG_MITER_TO_SG | SG_MITER_ATOMIC); 3158c2ecf20Sopenharmony_ci if (po) 3168c2ecf20Sopenharmony_ci sg_miter_skip(&mo, po); 3178c2ecf20Sopenharmony_ci miter_err = sg_miter_next(&mo); 3188c2ecf20Sopenharmony_ci if (!miter_err || !mo.addr) { 3198c2ecf20Sopenharmony_ci dev_err_ratelimited(ss->dev, "ERROR: sg_miter return null\n"); 3208c2ecf20Sopenharmony_ci err = -EINVAL; 3218c2ecf20Sopenharmony_ci goto release_ss; 3228c2ecf20Sopenharmony_ci } 3238c2ecf20Sopenharmony_ci /* todo in 4bytes word */ 3248c2ecf20Sopenharmony_ci todo = min(tx_cnt, oleft / 4); 3258c2ecf20Sopenharmony_ci todo = min_t(size_t, todo, (mo.length - oo) / 4); 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci if (todo) { 3288c2ecf20Sopenharmony_ci readsl(ss->base + SS_TXFIFO, mo.addr + oo, todo); 3298c2ecf20Sopenharmony_ci oleft -= todo * 4; 3308c2ecf20Sopenharmony_ci oo += todo * 4; 3318c2ecf20Sopenharmony_ci if (oo == mo.length) { 3328c2ecf20Sopenharmony_ci po += mo.length; 3338c2ecf20Sopenharmony_ci oo = 0; 3348c2ecf20Sopenharmony_ci } 3358c2ecf20Sopenharmony_ci } else { 3368c2ecf20Sopenharmony_ci /* 3378c2ecf20Sopenharmony_ci * read obl bytes in bufo, we read at maximum for 3388c2ecf20Sopenharmony_ci * emptying the device 3398c2ecf20Sopenharmony_ci */ 3408c2ecf20Sopenharmony_ci readsl(ss->base + SS_TXFIFO, ss->bufo, tx_cnt); 3418c2ecf20Sopenharmony_ci obl = tx_cnt * 4; 3428c2ecf20Sopenharmony_ci obo = 0; 3438c2ecf20Sopenharmony_ci do { 3448c2ecf20Sopenharmony_ci /* 3458c2ecf20Sopenharmony_ci * how many bytes we can copy ? 3468c2ecf20Sopenharmony_ci * no more than remaining SG size 3478c2ecf20Sopenharmony_ci * no more than remaining buffer 3488c2ecf20Sopenharmony_ci * no need to test against oleft 3498c2ecf20Sopenharmony_ci */ 3508c2ecf20Sopenharmony_ci todo = min_t(size_t, 3518c2ecf20Sopenharmony_ci mo.length - oo, obl - obo); 3528c2ecf20Sopenharmony_ci memcpy(mo.addr + oo, ss->bufo + obo, todo); 3538c2ecf20Sopenharmony_ci oleft -= todo; 3548c2ecf20Sopenharmony_ci obo += todo; 3558c2ecf20Sopenharmony_ci oo += todo; 3568c2ecf20Sopenharmony_ci if (oo == mo.length) { 3578c2ecf20Sopenharmony_ci po += mo.length; 3588c2ecf20Sopenharmony_ci sg_miter_next(&mo); 3598c2ecf20Sopenharmony_ci oo = 0; 3608c2ecf20Sopenharmony_ci } 3618c2ecf20Sopenharmony_ci } while (obo < obl); 3628c2ecf20Sopenharmony_ci /* bufo must be fully used here */ 3638c2ecf20Sopenharmony_ci } 3648c2ecf20Sopenharmony_ci sg_miter_stop(&mo); 3658c2ecf20Sopenharmony_ci } 3668c2ecf20Sopenharmony_ci if (areq->iv) { 3678c2ecf20Sopenharmony_ci if (mode & SS_DECRYPTION) { 3688c2ecf20Sopenharmony_ci memcpy(areq->iv, backup_iv, ivsize); 3698c2ecf20Sopenharmony_ci kfree_sensitive(backup_iv); 3708c2ecf20Sopenharmony_ci } else { 3718c2ecf20Sopenharmony_ci scatterwalk_map_and_copy(areq->iv, areq->dst, areq->cryptlen - ivsize, 3728c2ecf20Sopenharmony_ci ivsize, 0); 3738c2ecf20Sopenharmony_ci } 3748c2ecf20Sopenharmony_ci } 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_cirelease_ss: 3778c2ecf20Sopenharmony_ci writel(0, ss->base + SS_CTL); 3788c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ss->slock, flags); 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci return err; 3818c2ecf20Sopenharmony_ci} 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci/* CBC AES */ 3848c2ecf20Sopenharmony_ciint sun4i_ss_cbc_aes_encrypt(struct skcipher_request *areq) 3858c2ecf20Sopenharmony_ci{ 3868c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq); 3878c2ecf20Sopenharmony_ci struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm); 3888c2ecf20Sopenharmony_ci struct sun4i_cipher_req_ctx *rctx = skcipher_request_ctx(areq); 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci rctx->mode = SS_OP_AES | SS_CBC | SS_ENABLED | SS_ENCRYPTION | 3918c2ecf20Sopenharmony_ci op->keymode; 3928c2ecf20Sopenharmony_ci return sun4i_ss_cipher_poll(areq); 3938c2ecf20Sopenharmony_ci} 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ciint sun4i_ss_cbc_aes_decrypt(struct skcipher_request *areq) 3968c2ecf20Sopenharmony_ci{ 3978c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq); 3988c2ecf20Sopenharmony_ci struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm); 3998c2ecf20Sopenharmony_ci struct sun4i_cipher_req_ctx *rctx = skcipher_request_ctx(areq); 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci rctx->mode = SS_OP_AES | SS_CBC | SS_ENABLED | SS_DECRYPTION | 4028c2ecf20Sopenharmony_ci op->keymode; 4038c2ecf20Sopenharmony_ci return sun4i_ss_cipher_poll(areq); 4048c2ecf20Sopenharmony_ci} 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci/* ECB AES */ 4078c2ecf20Sopenharmony_ciint sun4i_ss_ecb_aes_encrypt(struct skcipher_request *areq) 4088c2ecf20Sopenharmony_ci{ 4098c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq); 4108c2ecf20Sopenharmony_ci struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm); 4118c2ecf20Sopenharmony_ci struct sun4i_cipher_req_ctx *rctx = skcipher_request_ctx(areq); 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci rctx->mode = SS_OP_AES | SS_ECB | SS_ENABLED | SS_ENCRYPTION | 4148c2ecf20Sopenharmony_ci op->keymode; 4158c2ecf20Sopenharmony_ci return sun4i_ss_cipher_poll(areq); 4168c2ecf20Sopenharmony_ci} 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ciint sun4i_ss_ecb_aes_decrypt(struct skcipher_request *areq) 4198c2ecf20Sopenharmony_ci{ 4208c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq); 4218c2ecf20Sopenharmony_ci struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm); 4228c2ecf20Sopenharmony_ci struct sun4i_cipher_req_ctx *rctx = skcipher_request_ctx(areq); 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci rctx->mode = SS_OP_AES | SS_ECB | SS_ENABLED | SS_DECRYPTION | 4258c2ecf20Sopenharmony_ci op->keymode; 4268c2ecf20Sopenharmony_ci return sun4i_ss_cipher_poll(areq); 4278c2ecf20Sopenharmony_ci} 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci/* CBC DES */ 4308c2ecf20Sopenharmony_ciint sun4i_ss_cbc_des_encrypt(struct skcipher_request *areq) 4318c2ecf20Sopenharmony_ci{ 4328c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq); 4338c2ecf20Sopenharmony_ci struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm); 4348c2ecf20Sopenharmony_ci struct sun4i_cipher_req_ctx *rctx = skcipher_request_ctx(areq); 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci rctx->mode = SS_OP_DES | SS_CBC | SS_ENABLED | SS_ENCRYPTION | 4378c2ecf20Sopenharmony_ci op->keymode; 4388c2ecf20Sopenharmony_ci return sun4i_ss_cipher_poll(areq); 4398c2ecf20Sopenharmony_ci} 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ciint sun4i_ss_cbc_des_decrypt(struct skcipher_request *areq) 4428c2ecf20Sopenharmony_ci{ 4438c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq); 4448c2ecf20Sopenharmony_ci struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm); 4458c2ecf20Sopenharmony_ci struct sun4i_cipher_req_ctx *rctx = skcipher_request_ctx(areq); 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci rctx->mode = SS_OP_DES | SS_CBC | SS_ENABLED | SS_DECRYPTION | 4488c2ecf20Sopenharmony_ci op->keymode; 4498c2ecf20Sopenharmony_ci return sun4i_ss_cipher_poll(areq); 4508c2ecf20Sopenharmony_ci} 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci/* ECB DES */ 4538c2ecf20Sopenharmony_ciint sun4i_ss_ecb_des_encrypt(struct skcipher_request *areq) 4548c2ecf20Sopenharmony_ci{ 4558c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq); 4568c2ecf20Sopenharmony_ci struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm); 4578c2ecf20Sopenharmony_ci struct sun4i_cipher_req_ctx *rctx = skcipher_request_ctx(areq); 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci rctx->mode = SS_OP_DES | SS_ECB | SS_ENABLED | SS_ENCRYPTION | 4608c2ecf20Sopenharmony_ci op->keymode; 4618c2ecf20Sopenharmony_ci return sun4i_ss_cipher_poll(areq); 4628c2ecf20Sopenharmony_ci} 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ciint sun4i_ss_ecb_des_decrypt(struct skcipher_request *areq) 4658c2ecf20Sopenharmony_ci{ 4668c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq); 4678c2ecf20Sopenharmony_ci struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm); 4688c2ecf20Sopenharmony_ci struct sun4i_cipher_req_ctx *rctx = skcipher_request_ctx(areq); 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci rctx->mode = SS_OP_DES | SS_ECB | SS_ENABLED | SS_DECRYPTION | 4718c2ecf20Sopenharmony_ci op->keymode; 4728c2ecf20Sopenharmony_ci return sun4i_ss_cipher_poll(areq); 4738c2ecf20Sopenharmony_ci} 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci/* CBC 3DES */ 4768c2ecf20Sopenharmony_ciint sun4i_ss_cbc_des3_encrypt(struct skcipher_request *areq) 4778c2ecf20Sopenharmony_ci{ 4788c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq); 4798c2ecf20Sopenharmony_ci struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm); 4808c2ecf20Sopenharmony_ci struct sun4i_cipher_req_ctx *rctx = skcipher_request_ctx(areq); 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci rctx->mode = SS_OP_3DES | SS_CBC | SS_ENABLED | SS_ENCRYPTION | 4838c2ecf20Sopenharmony_ci op->keymode; 4848c2ecf20Sopenharmony_ci return sun4i_ss_cipher_poll(areq); 4858c2ecf20Sopenharmony_ci} 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ciint sun4i_ss_cbc_des3_decrypt(struct skcipher_request *areq) 4888c2ecf20Sopenharmony_ci{ 4898c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq); 4908c2ecf20Sopenharmony_ci struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm); 4918c2ecf20Sopenharmony_ci struct sun4i_cipher_req_ctx *rctx = skcipher_request_ctx(areq); 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci rctx->mode = SS_OP_3DES | SS_CBC | SS_ENABLED | SS_DECRYPTION | 4948c2ecf20Sopenharmony_ci op->keymode; 4958c2ecf20Sopenharmony_ci return sun4i_ss_cipher_poll(areq); 4968c2ecf20Sopenharmony_ci} 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci/* ECB 3DES */ 4998c2ecf20Sopenharmony_ciint sun4i_ss_ecb_des3_encrypt(struct skcipher_request *areq) 5008c2ecf20Sopenharmony_ci{ 5018c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq); 5028c2ecf20Sopenharmony_ci struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm); 5038c2ecf20Sopenharmony_ci struct sun4i_cipher_req_ctx *rctx = skcipher_request_ctx(areq); 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci rctx->mode = SS_OP_3DES | SS_ECB | SS_ENABLED | SS_ENCRYPTION | 5068c2ecf20Sopenharmony_ci op->keymode; 5078c2ecf20Sopenharmony_ci return sun4i_ss_cipher_poll(areq); 5088c2ecf20Sopenharmony_ci} 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ciint sun4i_ss_ecb_des3_decrypt(struct skcipher_request *areq) 5118c2ecf20Sopenharmony_ci{ 5128c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq); 5138c2ecf20Sopenharmony_ci struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm); 5148c2ecf20Sopenharmony_ci struct sun4i_cipher_req_ctx *rctx = skcipher_request_ctx(areq); 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ci rctx->mode = SS_OP_3DES | SS_ECB | SS_ENABLED | SS_DECRYPTION | 5178c2ecf20Sopenharmony_ci op->keymode; 5188c2ecf20Sopenharmony_ci return sun4i_ss_cipher_poll(areq); 5198c2ecf20Sopenharmony_ci} 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ciint sun4i_ss_cipher_init(struct crypto_tfm *tfm) 5228c2ecf20Sopenharmony_ci{ 5238c2ecf20Sopenharmony_ci struct sun4i_tfm_ctx *op = crypto_tfm_ctx(tfm); 5248c2ecf20Sopenharmony_ci struct sun4i_ss_alg_template *algt; 5258c2ecf20Sopenharmony_ci const char *name = crypto_tfm_alg_name(tfm); 5268c2ecf20Sopenharmony_ci int err; 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci memset(op, 0, sizeof(struct sun4i_tfm_ctx)); 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci algt = container_of(tfm->__crt_alg, struct sun4i_ss_alg_template, 5318c2ecf20Sopenharmony_ci alg.crypto.base); 5328c2ecf20Sopenharmony_ci op->ss = algt->ss; 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci op->fallback_tfm = crypto_alloc_skcipher(name, 0, CRYPTO_ALG_NEED_FALLBACK); 5358c2ecf20Sopenharmony_ci if (IS_ERR(op->fallback_tfm)) { 5368c2ecf20Sopenharmony_ci dev_err(op->ss->dev, "ERROR: Cannot allocate fallback for %s %ld\n", 5378c2ecf20Sopenharmony_ci name, PTR_ERR(op->fallback_tfm)); 5388c2ecf20Sopenharmony_ci return PTR_ERR(op->fallback_tfm); 5398c2ecf20Sopenharmony_ci } 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci crypto_skcipher_set_reqsize(__crypto_skcipher_cast(tfm), 5428c2ecf20Sopenharmony_ci sizeof(struct sun4i_cipher_req_ctx) + 5438c2ecf20Sopenharmony_ci crypto_skcipher_reqsize(op->fallback_tfm)); 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ci err = pm_runtime_get_sync(op->ss->dev); 5478c2ecf20Sopenharmony_ci if (err < 0) 5488c2ecf20Sopenharmony_ci goto error_pm; 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci return 0; 5518c2ecf20Sopenharmony_cierror_pm: 5528c2ecf20Sopenharmony_ci crypto_free_skcipher(op->fallback_tfm); 5538c2ecf20Sopenharmony_ci return err; 5548c2ecf20Sopenharmony_ci} 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_civoid sun4i_ss_cipher_exit(struct crypto_tfm *tfm) 5578c2ecf20Sopenharmony_ci{ 5588c2ecf20Sopenharmony_ci struct sun4i_tfm_ctx *op = crypto_tfm_ctx(tfm); 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ci crypto_free_skcipher(op->fallback_tfm); 5618c2ecf20Sopenharmony_ci pm_runtime_put(op->ss->dev); 5628c2ecf20Sopenharmony_ci} 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ci/* check and set the AES key, prepare the mode to be used */ 5658c2ecf20Sopenharmony_ciint sun4i_ss_aes_setkey(struct crypto_skcipher *tfm, const u8 *key, 5668c2ecf20Sopenharmony_ci unsigned int keylen) 5678c2ecf20Sopenharmony_ci{ 5688c2ecf20Sopenharmony_ci struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm); 5698c2ecf20Sopenharmony_ci struct sun4i_ss_ctx *ss = op->ss; 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_ci switch (keylen) { 5728c2ecf20Sopenharmony_ci case 128 / 8: 5738c2ecf20Sopenharmony_ci op->keymode = SS_AES_128BITS; 5748c2ecf20Sopenharmony_ci break; 5758c2ecf20Sopenharmony_ci case 192 / 8: 5768c2ecf20Sopenharmony_ci op->keymode = SS_AES_192BITS; 5778c2ecf20Sopenharmony_ci break; 5788c2ecf20Sopenharmony_ci case 256 / 8: 5798c2ecf20Sopenharmony_ci op->keymode = SS_AES_256BITS; 5808c2ecf20Sopenharmony_ci break; 5818c2ecf20Sopenharmony_ci default: 5828c2ecf20Sopenharmony_ci dev_dbg(ss->dev, "ERROR: Invalid keylen %u\n", keylen); 5838c2ecf20Sopenharmony_ci return -EINVAL; 5848c2ecf20Sopenharmony_ci } 5858c2ecf20Sopenharmony_ci op->keylen = keylen; 5868c2ecf20Sopenharmony_ci memcpy(op->key, key, keylen); 5878c2ecf20Sopenharmony_ci 5888c2ecf20Sopenharmony_ci crypto_skcipher_clear_flags(op->fallback_tfm, CRYPTO_TFM_REQ_MASK); 5898c2ecf20Sopenharmony_ci crypto_skcipher_set_flags(op->fallback_tfm, tfm->base.crt_flags & CRYPTO_TFM_REQ_MASK); 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci return crypto_skcipher_setkey(op->fallback_tfm, key, keylen); 5928c2ecf20Sopenharmony_ci} 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_ci/* check and set the DES key, prepare the mode to be used */ 5958c2ecf20Sopenharmony_ciint sun4i_ss_des_setkey(struct crypto_skcipher *tfm, const u8 *key, 5968c2ecf20Sopenharmony_ci unsigned int keylen) 5978c2ecf20Sopenharmony_ci{ 5988c2ecf20Sopenharmony_ci struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm); 5998c2ecf20Sopenharmony_ci int err; 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci err = verify_skcipher_des_key(tfm, key); 6028c2ecf20Sopenharmony_ci if (err) 6038c2ecf20Sopenharmony_ci return err; 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ci op->keylen = keylen; 6068c2ecf20Sopenharmony_ci memcpy(op->key, key, keylen); 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci crypto_skcipher_clear_flags(op->fallback_tfm, CRYPTO_TFM_REQ_MASK); 6098c2ecf20Sopenharmony_ci crypto_skcipher_set_flags(op->fallback_tfm, tfm->base.crt_flags & CRYPTO_TFM_REQ_MASK); 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci return crypto_skcipher_setkey(op->fallback_tfm, key, keylen); 6128c2ecf20Sopenharmony_ci} 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ci/* check and set the 3DES key, prepare the mode to be used */ 6158c2ecf20Sopenharmony_ciint sun4i_ss_des3_setkey(struct crypto_skcipher *tfm, const u8 *key, 6168c2ecf20Sopenharmony_ci unsigned int keylen) 6178c2ecf20Sopenharmony_ci{ 6188c2ecf20Sopenharmony_ci struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm); 6198c2ecf20Sopenharmony_ci int err; 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_ci err = verify_skcipher_des3_key(tfm, key); 6228c2ecf20Sopenharmony_ci if (err) 6238c2ecf20Sopenharmony_ci return err; 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_ci op->keylen = keylen; 6268c2ecf20Sopenharmony_ci memcpy(op->key, key, keylen); 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci crypto_skcipher_clear_flags(op->fallback_tfm, CRYPTO_TFM_REQ_MASK); 6298c2ecf20Sopenharmony_ci crypto_skcipher_set_flags(op->fallback_tfm, tfm->base.crt_flags & CRYPTO_TFM_REQ_MASK); 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci return crypto_skcipher_setkey(op->fallback_tfm, key, keylen); 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci} 634