18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright 2016 Broadcom 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <linux/err.h> 78c2ecf20Sopenharmony_ci#include <linux/module.h> 88c2ecf20Sopenharmony_ci#include <linux/init.h> 98c2ecf20Sopenharmony_ci#include <linux/errno.h> 108c2ecf20Sopenharmony_ci#include <linux/kernel.h> 118c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 128c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 138c2ecf20Sopenharmony_ci#include <linux/scatterlist.h> 148c2ecf20Sopenharmony_ci#include <linux/crypto.h> 158c2ecf20Sopenharmony_ci#include <linux/kthread.h> 168c2ecf20Sopenharmony_ci#include <linux/rtnetlink.h> 178c2ecf20Sopenharmony_ci#include <linux/sched.h> 188c2ecf20Sopenharmony_ci#include <linux/of_address.h> 198c2ecf20Sopenharmony_ci#include <linux/of_device.h> 208c2ecf20Sopenharmony_ci#include <linux/io.h> 218c2ecf20Sopenharmony_ci#include <linux/bitops.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#include <crypto/algapi.h> 248c2ecf20Sopenharmony_ci#include <crypto/aead.h> 258c2ecf20Sopenharmony_ci#include <crypto/internal/aead.h> 268c2ecf20Sopenharmony_ci#include <crypto/aes.h> 278c2ecf20Sopenharmony_ci#include <crypto/internal/des.h> 288c2ecf20Sopenharmony_ci#include <crypto/hmac.h> 298c2ecf20Sopenharmony_ci#include <crypto/sha.h> 308c2ecf20Sopenharmony_ci#include <crypto/md5.h> 318c2ecf20Sopenharmony_ci#include <crypto/authenc.h> 328c2ecf20Sopenharmony_ci#include <crypto/skcipher.h> 338c2ecf20Sopenharmony_ci#include <crypto/hash.h> 348c2ecf20Sopenharmony_ci#include <crypto/sha3.h> 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#include "util.h" 378c2ecf20Sopenharmony_ci#include "cipher.h" 388c2ecf20Sopenharmony_ci#include "spu.h" 398c2ecf20Sopenharmony_ci#include "spum.h" 408c2ecf20Sopenharmony_ci#include "spu2.h" 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci/* ================= Device Structure ================== */ 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_cistruct bcm_device_private iproc_priv; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci/* ==================== Parameters ===================== */ 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ciint flow_debug_logging; 498c2ecf20Sopenharmony_cimodule_param(flow_debug_logging, int, 0644); 508c2ecf20Sopenharmony_ciMODULE_PARM_DESC(flow_debug_logging, "Enable Flow Debug Logging"); 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ciint packet_debug_logging; 538c2ecf20Sopenharmony_cimodule_param(packet_debug_logging, int, 0644); 548c2ecf20Sopenharmony_ciMODULE_PARM_DESC(packet_debug_logging, "Enable Packet Debug Logging"); 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ciint debug_logging_sleep; 578c2ecf20Sopenharmony_cimodule_param(debug_logging_sleep, int, 0644); 588c2ecf20Sopenharmony_ciMODULE_PARM_DESC(debug_logging_sleep, "Packet Debug Logging Sleep"); 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci/* 618c2ecf20Sopenharmony_ci * The value of these module parameters is used to set the priority for each 628c2ecf20Sopenharmony_ci * algo type when this driver registers algos with the kernel crypto API. 638c2ecf20Sopenharmony_ci * To use a priority other than the default, set the priority in the insmod or 648c2ecf20Sopenharmony_ci * modprobe. Changing the module priority after init time has no effect. 658c2ecf20Sopenharmony_ci * 668c2ecf20Sopenharmony_ci * The default priorities are chosen to be lower (less preferred) than ARMv8 CE 678c2ecf20Sopenharmony_ci * algos, but more preferred than generic software algos. 688c2ecf20Sopenharmony_ci */ 698c2ecf20Sopenharmony_cistatic int cipher_pri = 150; 708c2ecf20Sopenharmony_cimodule_param(cipher_pri, int, 0644); 718c2ecf20Sopenharmony_ciMODULE_PARM_DESC(cipher_pri, "Priority for cipher algos"); 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_cistatic int hash_pri = 100; 748c2ecf20Sopenharmony_cimodule_param(hash_pri, int, 0644); 758c2ecf20Sopenharmony_ciMODULE_PARM_DESC(hash_pri, "Priority for hash algos"); 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_cistatic int aead_pri = 150; 788c2ecf20Sopenharmony_cimodule_param(aead_pri, int, 0644); 798c2ecf20Sopenharmony_ciMODULE_PARM_DESC(aead_pri, "Priority for AEAD algos"); 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci/* A type 3 BCM header, expected to precede the SPU header for SPU-M. 828c2ecf20Sopenharmony_ci * Bits 3 and 4 in the first byte encode the channel number (the dma ringset). 838c2ecf20Sopenharmony_ci * 0x60 - ring 0 848c2ecf20Sopenharmony_ci * 0x68 - ring 1 858c2ecf20Sopenharmony_ci * 0x70 - ring 2 868c2ecf20Sopenharmony_ci * 0x78 - ring 3 878c2ecf20Sopenharmony_ci */ 888c2ecf20Sopenharmony_cistatic char BCMHEADER[] = { 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28 }; 898c2ecf20Sopenharmony_ci/* 908c2ecf20Sopenharmony_ci * Some SPU hw does not use BCM header on SPU messages. So BCM_HDR_LEN 918c2ecf20Sopenharmony_ci * is set dynamically after reading SPU type from device tree. 928c2ecf20Sopenharmony_ci */ 938c2ecf20Sopenharmony_ci#define BCM_HDR_LEN iproc_priv.bcm_hdr_len 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci/* min and max time to sleep before retrying when mbox queue is full. usec */ 968c2ecf20Sopenharmony_ci#define MBOX_SLEEP_MIN 800 978c2ecf20Sopenharmony_ci#define MBOX_SLEEP_MAX 1000 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci/** 1008c2ecf20Sopenharmony_ci * select_channel() - Select a SPU channel to handle a crypto request. Selects 1018c2ecf20Sopenharmony_ci * channel in round robin order. 1028c2ecf20Sopenharmony_ci * 1038c2ecf20Sopenharmony_ci * Return: channel index 1048c2ecf20Sopenharmony_ci */ 1058c2ecf20Sopenharmony_cistatic u8 select_channel(void) 1068c2ecf20Sopenharmony_ci{ 1078c2ecf20Sopenharmony_ci u8 chan_idx = atomic_inc_return(&iproc_priv.next_chan); 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci return chan_idx % iproc_priv.spu.num_chan; 1108c2ecf20Sopenharmony_ci} 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci/** 1138c2ecf20Sopenharmony_ci * spu_skcipher_rx_sg_create() - Build up the scatterlist of buffers used to 1148c2ecf20Sopenharmony_ci * receive a SPU response message for an skcipher request. Includes buffers to 1158c2ecf20Sopenharmony_ci * catch SPU message headers and the response data. 1168c2ecf20Sopenharmony_ci * @mssg: mailbox message containing the receive sg 1178c2ecf20Sopenharmony_ci * @rctx: crypto request context 1188c2ecf20Sopenharmony_ci * @rx_frag_num: number of scatterlist elements required to hold the 1198c2ecf20Sopenharmony_ci * SPU response message 1208c2ecf20Sopenharmony_ci * @chunksize: Number of bytes of response data expected 1218c2ecf20Sopenharmony_ci * @stat_pad_len: Number of bytes required to pad the STAT field to 1228c2ecf20Sopenharmony_ci * a 4-byte boundary 1238c2ecf20Sopenharmony_ci * 1248c2ecf20Sopenharmony_ci * The scatterlist that gets allocated here is freed in spu_chunk_cleanup() 1258c2ecf20Sopenharmony_ci * when the request completes, whether the request is handled successfully or 1268c2ecf20Sopenharmony_ci * there is an error. 1278c2ecf20Sopenharmony_ci * 1288c2ecf20Sopenharmony_ci * Returns: 1298c2ecf20Sopenharmony_ci * 0 if successful 1308c2ecf20Sopenharmony_ci * < 0 if an error 1318c2ecf20Sopenharmony_ci */ 1328c2ecf20Sopenharmony_cistatic int 1338c2ecf20Sopenharmony_cispu_skcipher_rx_sg_create(struct brcm_message *mssg, 1348c2ecf20Sopenharmony_ci struct iproc_reqctx_s *rctx, 1358c2ecf20Sopenharmony_ci u8 rx_frag_num, 1368c2ecf20Sopenharmony_ci unsigned int chunksize, u32 stat_pad_len) 1378c2ecf20Sopenharmony_ci{ 1388c2ecf20Sopenharmony_ci struct spu_hw *spu = &iproc_priv.spu; 1398c2ecf20Sopenharmony_ci struct scatterlist *sg; /* used to build sgs in mbox message */ 1408c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = rctx->ctx; 1418c2ecf20Sopenharmony_ci u32 datalen; /* Number of bytes of response data expected */ 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci mssg->spu.dst = kcalloc(rx_frag_num, sizeof(struct scatterlist), 1448c2ecf20Sopenharmony_ci rctx->gfp); 1458c2ecf20Sopenharmony_ci if (!mssg->spu.dst) 1468c2ecf20Sopenharmony_ci return -ENOMEM; 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci sg = mssg->spu.dst; 1498c2ecf20Sopenharmony_ci sg_init_table(sg, rx_frag_num); 1508c2ecf20Sopenharmony_ci /* Space for SPU message header */ 1518c2ecf20Sopenharmony_ci sg_set_buf(sg++, rctx->msg_buf.spu_resp_hdr, ctx->spu_resp_hdr_len); 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci /* If XTS tweak in payload, add buffer to receive encrypted tweak */ 1548c2ecf20Sopenharmony_ci if ((ctx->cipher.mode == CIPHER_MODE_XTS) && 1558c2ecf20Sopenharmony_ci spu->spu_xts_tweak_in_payload()) 1568c2ecf20Sopenharmony_ci sg_set_buf(sg++, rctx->msg_buf.c.supdt_tweak, 1578c2ecf20Sopenharmony_ci SPU_XTS_TWEAK_SIZE); 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci /* Copy in each dst sg entry from request, up to chunksize */ 1608c2ecf20Sopenharmony_ci datalen = spu_msg_sg_add(&sg, &rctx->dst_sg, &rctx->dst_skip, 1618c2ecf20Sopenharmony_ci rctx->dst_nents, chunksize); 1628c2ecf20Sopenharmony_ci if (datalen < chunksize) { 1638c2ecf20Sopenharmony_ci pr_err("%s(): failed to copy dst sg to mbox msg. chunksize %u, datalen %u", 1648c2ecf20Sopenharmony_ci __func__, chunksize, datalen); 1658c2ecf20Sopenharmony_ci return -EFAULT; 1668c2ecf20Sopenharmony_ci } 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci if (stat_pad_len) 1698c2ecf20Sopenharmony_ci sg_set_buf(sg++, rctx->msg_buf.rx_stat_pad, stat_pad_len); 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci memset(rctx->msg_buf.rx_stat, 0, SPU_RX_STATUS_LEN); 1728c2ecf20Sopenharmony_ci sg_set_buf(sg, rctx->msg_buf.rx_stat, spu->spu_rx_status_len()); 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci return 0; 1758c2ecf20Sopenharmony_ci} 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci/** 1788c2ecf20Sopenharmony_ci * spu_skcipher_tx_sg_create() - Build up the scatterlist of buffers used to 1798c2ecf20Sopenharmony_ci * send a SPU request message for an skcipher request. Includes SPU message 1808c2ecf20Sopenharmony_ci * headers and the request data. 1818c2ecf20Sopenharmony_ci * @mssg: mailbox message containing the transmit sg 1828c2ecf20Sopenharmony_ci * @rctx: crypto request context 1838c2ecf20Sopenharmony_ci * @tx_frag_num: number of scatterlist elements required to construct the 1848c2ecf20Sopenharmony_ci * SPU request message 1858c2ecf20Sopenharmony_ci * @chunksize: Number of bytes of request data 1868c2ecf20Sopenharmony_ci * @pad_len: Number of pad bytes 1878c2ecf20Sopenharmony_ci * 1888c2ecf20Sopenharmony_ci * The scatterlist that gets allocated here is freed in spu_chunk_cleanup() 1898c2ecf20Sopenharmony_ci * when the request completes, whether the request is handled successfully or 1908c2ecf20Sopenharmony_ci * there is an error. 1918c2ecf20Sopenharmony_ci * 1928c2ecf20Sopenharmony_ci * Returns: 1938c2ecf20Sopenharmony_ci * 0 if successful 1948c2ecf20Sopenharmony_ci * < 0 if an error 1958c2ecf20Sopenharmony_ci */ 1968c2ecf20Sopenharmony_cistatic int 1978c2ecf20Sopenharmony_cispu_skcipher_tx_sg_create(struct brcm_message *mssg, 1988c2ecf20Sopenharmony_ci struct iproc_reqctx_s *rctx, 1998c2ecf20Sopenharmony_ci u8 tx_frag_num, unsigned int chunksize, u32 pad_len) 2008c2ecf20Sopenharmony_ci{ 2018c2ecf20Sopenharmony_ci struct spu_hw *spu = &iproc_priv.spu; 2028c2ecf20Sopenharmony_ci struct scatterlist *sg; /* used to build sgs in mbox message */ 2038c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = rctx->ctx; 2048c2ecf20Sopenharmony_ci u32 datalen; /* Number of bytes of response data expected */ 2058c2ecf20Sopenharmony_ci u32 stat_len; 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci mssg->spu.src = kcalloc(tx_frag_num, sizeof(struct scatterlist), 2088c2ecf20Sopenharmony_ci rctx->gfp); 2098c2ecf20Sopenharmony_ci if (unlikely(!mssg->spu.src)) 2108c2ecf20Sopenharmony_ci return -ENOMEM; 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci sg = mssg->spu.src; 2138c2ecf20Sopenharmony_ci sg_init_table(sg, tx_frag_num); 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci sg_set_buf(sg++, rctx->msg_buf.bcm_spu_req_hdr, 2168c2ecf20Sopenharmony_ci BCM_HDR_LEN + ctx->spu_req_hdr_len); 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci /* if XTS tweak in payload, copy from IV (where crypto API puts it) */ 2198c2ecf20Sopenharmony_ci if ((ctx->cipher.mode == CIPHER_MODE_XTS) && 2208c2ecf20Sopenharmony_ci spu->spu_xts_tweak_in_payload()) 2218c2ecf20Sopenharmony_ci sg_set_buf(sg++, rctx->msg_buf.iv_ctr, SPU_XTS_TWEAK_SIZE); 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci /* Copy in each src sg entry from request, up to chunksize */ 2248c2ecf20Sopenharmony_ci datalen = spu_msg_sg_add(&sg, &rctx->src_sg, &rctx->src_skip, 2258c2ecf20Sopenharmony_ci rctx->src_nents, chunksize); 2268c2ecf20Sopenharmony_ci if (unlikely(datalen < chunksize)) { 2278c2ecf20Sopenharmony_ci pr_err("%s(): failed to copy src sg to mbox msg", 2288c2ecf20Sopenharmony_ci __func__); 2298c2ecf20Sopenharmony_ci return -EFAULT; 2308c2ecf20Sopenharmony_ci } 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci if (pad_len) 2338c2ecf20Sopenharmony_ci sg_set_buf(sg++, rctx->msg_buf.spu_req_pad, pad_len); 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci stat_len = spu->spu_tx_status_len(); 2368c2ecf20Sopenharmony_ci if (stat_len) { 2378c2ecf20Sopenharmony_ci memset(rctx->msg_buf.tx_stat, 0, stat_len); 2388c2ecf20Sopenharmony_ci sg_set_buf(sg, rctx->msg_buf.tx_stat, stat_len); 2398c2ecf20Sopenharmony_ci } 2408c2ecf20Sopenharmony_ci return 0; 2418c2ecf20Sopenharmony_ci} 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_cistatic int mailbox_send_message(struct brcm_message *mssg, u32 flags, 2448c2ecf20Sopenharmony_ci u8 chan_idx) 2458c2ecf20Sopenharmony_ci{ 2468c2ecf20Sopenharmony_ci int err; 2478c2ecf20Sopenharmony_ci int retry_cnt = 0; 2488c2ecf20Sopenharmony_ci struct device *dev = &(iproc_priv.pdev->dev); 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci err = mbox_send_message(iproc_priv.mbox[chan_idx], mssg); 2518c2ecf20Sopenharmony_ci if (flags & CRYPTO_TFM_REQ_MAY_SLEEP) { 2528c2ecf20Sopenharmony_ci while ((err == -ENOBUFS) && (retry_cnt < SPU_MB_RETRY_MAX)) { 2538c2ecf20Sopenharmony_ci /* 2548c2ecf20Sopenharmony_ci * Mailbox queue is full. Since MAY_SLEEP is set, assume 2558c2ecf20Sopenharmony_ci * not in atomic context and we can wait and try again. 2568c2ecf20Sopenharmony_ci */ 2578c2ecf20Sopenharmony_ci retry_cnt++; 2588c2ecf20Sopenharmony_ci usleep_range(MBOX_SLEEP_MIN, MBOX_SLEEP_MAX); 2598c2ecf20Sopenharmony_ci err = mbox_send_message(iproc_priv.mbox[chan_idx], 2608c2ecf20Sopenharmony_ci mssg); 2618c2ecf20Sopenharmony_ci atomic_inc(&iproc_priv.mb_no_spc); 2628c2ecf20Sopenharmony_ci } 2638c2ecf20Sopenharmony_ci } 2648c2ecf20Sopenharmony_ci if (err < 0) { 2658c2ecf20Sopenharmony_ci atomic_inc(&iproc_priv.mb_send_fail); 2668c2ecf20Sopenharmony_ci return err; 2678c2ecf20Sopenharmony_ci } 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci /* Check error returned by mailbox controller */ 2708c2ecf20Sopenharmony_ci err = mssg->error; 2718c2ecf20Sopenharmony_ci if (unlikely(err < 0)) { 2728c2ecf20Sopenharmony_ci dev_err(dev, "message error %d", err); 2738c2ecf20Sopenharmony_ci /* Signal txdone for mailbox channel */ 2748c2ecf20Sopenharmony_ci } 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci /* Signal txdone for mailbox channel */ 2778c2ecf20Sopenharmony_ci mbox_client_txdone(iproc_priv.mbox[chan_idx], err); 2788c2ecf20Sopenharmony_ci return err; 2798c2ecf20Sopenharmony_ci} 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci/** 2828c2ecf20Sopenharmony_ci * handle_skcipher_req() - Submit as much of a block cipher request as fits in 2838c2ecf20Sopenharmony_ci * a single SPU request message, starting at the current position in the request 2848c2ecf20Sopenharmony_ci * data. 2858c2ecf20Sopenharmony_ci * @rctx: Crypto request context 2868c2ecf20Sopenharmony_ci * 2878c2ecf20Sopenharmony_ci * This may be called on the crypto API thread, or, when a request is so large 2888c2ecf20Sopenharmony_ci * it must be broken into multiple SPU messages, on the thread used to invoke 2898c2ecf20Sopenharmony_ci * the response callback. When requests are broken into multiple SPU 2908c2ecf20Sopenharmony_ci * messages, we assume subsequent messages depend on previous results, and 2918c2ecf20Sopenharmony_ci * thus always wait for previous results before submitting the next message. 2928c2ecf20Sopenharmony_ci * Because requests are submitted in lock step like this, there is no need 2938c2ecf20Sopenharmony_ci * to synchronize access to request data structures. 2948c2ecf20Sopenharmony_ci * 2958c2ecf20Sopenharmony_ci * Return: -EINPROGRESS: request has been accepted and result will be returned 2968c2ecf20Sopenharmony_ci * asynchronously 2978c2ecf20Sopenharmony_ci * Any other value indicates an error 2988c2ecf20Sopenharmony_ci */ 2998c2ecf20Sopenharmony_cistatic int handle_skcipher_req(struct iproc_reqctx_s *rctx) 3008c2ecf20Sopenharmony_ci{ 3018c2ecf20Sopenharmony_ci struct spu_hw *spu = &iproc_priv.spu; 3028c2ecf20Sopenharmony_ci struct crypto_async_request *areq = rctx->parent; 3038c2ecf20Sopenharmony_ci struct skcipher_request *req = 3048c2ecf20Sopenharmony_ci container_of(areq, struct skcipher_request, base); 3058c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = rctx->ctx; 3068c2ecf20Sopenharmony_ci struct spu_cipher_parms cipher_parms; 3078c2ecf20Sopenharmony_ci int err; 3088c2ecf20Sopenharmony_ci unsigned int chunksize; /* Num bytes of request to submit */ 3098c2ecf20Sopenharmony_ci int remaining; /* Bytes of request still to process */ 3108c2ecf20Sopenharmony_ci int chunk_start; /* Beginning of data for current SPU msg */ 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci /* IV or ctr value to use in this SPU msg */ 3138c2ecf20Sopenharmony_ci u8 local_iv_ctr[MAX_IV_SIZE]; 3148c2ecf20Sopenharmony_ci u32 stat_pad_len; /* num bytes to align status field */ 3158c2ecf20Sopenharmony_ci u32 pad_len; /* total length of all padding */ 3168c2ecf20Sopenharmony_ci struct brcm_message *mssg; /* mailbox message */ 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci /* number of entries in src and dst sg in mailbox message. */ 3198c2ecf20Sopenharmony_ci u8 rx_frag_num = 2; /* response header and STATUS */ 3208c2ecf20Sopenharmony_ci u8 tx_frag_num = 1; /* request header */ 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci flow_log("%s\n", __func__); 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci cipher_parms.alg = ctx->cipher.alg; 3258c2ecf20Sopenharmony_ci cipher_parms.mode = ctx->cipher.mode; 3268c2ecf20Sopenharmony_ci cipher_parms.type = ctx->cipher_type; 3278c2ecf20Sopenharmony_ci cipher_parms.key_len = ctx->enckeylen; 3288c2ecf20Sopenharmony_ci cipher_parms.key_buf = ctx->enckey; 3298c2ecf20Sopenharmony_ci cipher_parms.iv_buf = local_iv_ctr; 3308c2ecf20Sopenharmony_ci cipher_parms.iv_len = rctx->iv_ctr_len; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci mssg = &rctx->mb_mssg; 3338c2ecf20Sopenharmony_ci chunk_start = rctx->src_sent; 3348c2ecf20Sopenharmony_ci remaining = rctx->total_todo - chunk_start; 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci /* determine the chunk we are breaking off and update the indexes */ 3378c2ecf20Sopenharmony_ci if ((ctx->max_payload != SPU_MAX_PAYLOAD_INF) && 3388c2ecf20Sopenharmony_ci (remaining > ctx->max_payload)) 3398c2ecf20Sopenharmony_ci chunksize = ctx->max_payload; 3408c2ecf20Sopenharmony_ci else 3418c2ecf20Sopenharmony_ci chunksize = remaining; 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci rctx->src_sent += chunksize; 3448c2ecf20Sopenharmony_ci rctx->total_sent = rctx->src_sent; 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci /* Count number of sg entries to be included in this request */ 3478c2ecf20Sopenharmony_ci rctx->src_nents = spu_sg_count(rctx->src_sg, rctx->src_skip, chunksize); 3488c2ecf20Sopenharmony_ci rctx->dst_nents = spu_sg_count(rctx->dst_sg, rctx->dst_skip, chunksize); 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci if ((ctx->cipher.mode == CIPHER_MODE_CBC) && 3518c2ecf20Sopenharmony_ci rctx->is_encrypt && chunk_start) 3528c2ecf20Sopenharmony_ci /* 3538c2ecf20Sopenharmony_ci * Encrypting non-first first chunk. Copy last block of 3548c2ecf20Sopenharmony_ci * previous result to IV for this chunk. 3558c2ecf20Sopenharmony_ci */ 3568c2ecf20Sopenharmony_ci sg_copy_part_to_buf(req->dst, rctx->msg_buf.iv_ctr, 3578c2ecf20Sopenharmony_ci rctx->iv_ctr_len, 3588c2ecf20Sopenharmony_ci chunk_start - rctx->iv_ctr_len); 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci if (rctx->iv_ctr_len) { 3618c2ecf20Sopenharmony_ci /* get our local copy of the iv */ 3628c2ecf20Sopenharmony_ci __builtin_memcpy(local_iv_ctr, rctx->msg_buf.iv_ctr, 3638c2ecf20Sopenharmony_ci rctx->iv_ctr_len); 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci /* generate the next IV if possible */ 3668c2ecf20Sopenharmony_ci if ((ctx->cipher.mode == CIPHER_MODE_CBC) && 3678c2ecf20Sopenharmony_ci !rctx->is_encrypt) { 3688c2ecf20Sopenharmony_ci /* 3698c2ecf20Sopenharmony_ci * CBC Decrypt: next IV is the last ciphertext block in 3708c2ecf20Sopenharmony_ci * this chunk 3718c2ecf20Sopenharmony_ci */ 3728c2ecf20Sopenharmony_ci sg_copy_part_to_buf(req->src, rctx->msg_buf.iv_ctr, 3738c2ecf20Sopenharmony_ci rctx->iv_ctr_len, 3748c2ecf20Sopenharmony_ci rctx->src_sent - rctx->iv_ctr_len); 3758c2ecf20Sopenharmony_ci } else if (ctx->cipher.mode == CIPHER_MODE_CTR) { 3768c2ecf20Sopenharmony_ci /* 3778c2ecf20Sopenharmony_ci * The SPU hardware increments the counter once for 3788c2ecf20Sopenharmony_ci * each AES block of 16 bytes. So update the counter 3798c2ecf20Sopenharmony_ci * for the next chunk, if there is one. Note that for 3808c2ecf20Sopenharmony_ci * this chunk, the counter has already been copied to 3818c2ecf20Sopenharmony_ci * local_iv_ctr. We can assume a block size of 16, 3828c2ecf20Sopenharmony_ci * because we only support CTR mode for AES, not for 3838c2ecf20Sopenharmony_ci * any other cipher alg. 3848c2ecf20Sopenharmony_ci */ 3858c2ecf20Sopenharmony_ci add_to_ctr(rctx->msg_buf.iv_ctr, chunksize >> 4); 3868c2ecf20Sopenharmony_ci } 3878c2ecf20Sopenharmony_ci } 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci if (ctx->max_payload == SPU_MAX_PAYLOAD_INF) 3908c2ecf20Sopenharmony_ci flow_log("max_payload infinite\n"); 3918c2ecf20Sopenharmony_ci else 3928c2ecf20Sopenharmony_ci flow_log("max_payload %u\n", ctx->max_payload); 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci flow_log("sent:%u start:%u remains:%u size:%u\n", 3958c2ecf20Sopenharmony_ci rctx->src_sent, chunk_start, remaining, chunksize); 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci /* Copy SPU header template created at setkey time */ 3988c2ecf20Sopenharmony_ci memcpy(rctx->msg_buf.bcm_spu_req_hdr, ctx->bcm_spu_req_hdr, 3998c2ecf20Sopenharmony_ci sizeof(rctx->msg_buf.bcm_spu_req_hdr)); 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci spu->spu_cipher_req_finish(rctx->msg_buf.bcm_spu_req_hdr + BCM_HDR_LEN, 4028c2ecf20Sopenharmony_ci ctx->spu_req_hdr_len, !(rctx->is_encrypt), 4038c2ecf20Sopenharmony_ci &cipher_parms, chunksize); 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci atomic64_add(chunksize, &iproc_priv.bytes_out); 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci stat_pad_len = spu->spu_wordalign_padlen(chunksize); 4088c2ecf20Sopenharmony_ci if (stat_pad_len) 4098c2ecf20Sopenharmony_ci rx_frag_num++; 4108c2ecf20Sopenharmony_ci pad_len = stat_pad_len; 4118c2ecf20Sopenharmony_ci if (pad_len) { 4128c2ecf20Sopenharmony_ci tx_frag_num++; 4138c2ecf20Sopenharmony_ci spu->spu_request_pad(rctx->msg_buf.spu_req_pad, 0, 4148c2ecf20Sopenharmony_ci 0, ctx->auth.alg, ctx->auth.mode, 4158c2ecf20Sopenharmony_ci rctx->total_sent, stat_pad_len); 4168c2ecf20Sopenharmony_ci } 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci spu->spu_dump_msg_hdr(rctx->msg_buf.bcm_spu_req_hdr + BCM_HDR_LEN, 4198c2ecf20Sopenharmony_ci ctx->spu_req_hdr_len); 4208c2ecf20Sopenharmony_ci packet_log("payload:\n"); 4218c2ecf20Sopenharmony_ci dump_sg(rctx->src_sg, rctx->src_skip, chunksize); 4228c2ecf20Sopenharmony_ci packet_dump(" pad: ", rctx->msg_buf.spu_req_pad, pad_len); 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci /* 4258c2ecf20Sopenharmony_ci * Build mailbox message containing SPU request msg and rx buffers 4268c2ecf20Sopenharmony_ci * to catch response message 4278c2ecf20Sopenharmony_ci */ 4288c2ecf20Sopenharmony_ci memset(mssg, 0, sizeof(*mssg)); 4298c2ecf20Sopenharmony_ci mssg->type = BRCM_MESSAGE_SPU; 4308c2ecf20Sopenharmony_ci mssg->ctx = rctx; /* Will be returned in response */ 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci /* Create rx scatterlist to catch result */ 4338c2ecf20Sopenharmony_ci rx_frag_num += rctx->dst_nents; 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci if ((ctx->cipher.mode == CIPHER_MODE_XTS) && 4368c2ecf20Sopenharmony_ci spu->spu_xts_tweak_in_payload()) 4378c2ecf20Sopenharmony_ci rx_frag_num++; /* extra sg to insert tweak */ 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci err = spu_skcipher_rx_sg_create(mssg, rctx, rx_frag_num, chunksize, 4408c2ecf20Sopenharmony_ci stat_pad_len); 4418c2ecf20Sopenharmony_ci if (err) 4428c2ecf20Sopenharmony_ci return err; 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci /* Create tx scatterlist containing SPU request message */ 4458c2ecf20Sopenharmony_ci tx_frag_num += rctx->src_nents; 4468c2ecf20Sopenharmony_ci if (spu->spu_tx_status_len()) 4478c2ecf20Sopenharmony_ci tx_frag_num++; 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_ci if ((ctx->cipher.mode == CIPHER_MODE_XTS) && 4508c2ecf20Sopenharmony_ci spu->spu_xts_tweak_in_payload()) 4518c2ecf20Sopenharmony_ci tx_frag_num++; /* extra sg to insert tweak */ 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci err = spu_skcipher_tx_sg_create(mssg, rctx, tx_frag_num, chunksize, 4548c2ecf20Sopenharmony_ci pad_len); 4558c2ecf20Sopenharmony_ci if (err) 4568c2ecf20Sopenharmony_ci return err; 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ci err = mailbox_send_message(mssg, req->base.flags, rctx->chan_idx); 4598c2ecf20Sopenharmony_ci if (unlikely(err < 0)) 4608c2ecf20Sopenharmony_ci return err; 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci return -EINPROGRESS; 4638c2ecf20Sopenharmony_ci} 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci/** 4668c2ecf20Sopenharmony_ci * handle_skcipher_resp() - Process a block cipher SPU response. Updates the 4678c2ecf20Sopenharmony_ci * total received count for the request and updates global stats. 4688c2ecf20Sopenharmony_ci * @rctx: Crypto request context 4698c2ecf20Sopenharmony_ci */ 4708c2ecf20Sopenharmony_cistatic void handle_skcipher_resp(struct iproc_reqctx_s *rctx) 4718c2ecf20Sopenharmony_ci{ 4728c2ecf20Sopenharmony_ci struct spu_hw *spu = &iproc_priv.spu; 4738c2ecf20Sopenharmony_ci#ifdef DEBUG 4748c2ecf20Sopenharmony_ci struct crypto_async_request *areq = rctx->parent; 4758c2ecf20Sopenharmony_ci struct skcipher_request *req = skcipher_request_cast(areq); 4768c2ecf20Sopenharmony_ci#endif 4778c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = rctx->ctx; 4788c2ecf20Sopenharmony_ci u32 payload_len; 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci /* See how much data was returned */ 4818c2ecf20Sopenharmony_ci payload_len = spu->spu_payload_length(rctx->msg_buf.spu_resp_hdr); 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci /* 4848c2ecf20Sopenharmony_ci * In XTS mode, the first SPU_XTS_TWEAK_SIZE bytes may be the 4858c2ecf20Sopenharmony_ci * encrypted tweak ("i") value; we don't count those. 4868c2ecf20Sopenharmony_ci */ 4878c2ecf20Sopenharmony_ci if ((ctx->cipher.mode == CIPHER_MODE_XTS) && 4888c2ecf20Sopenharmony_ci spu->spu_xts_tweak_in_payload() && 4898c2ecf20Sopenharmony_ci (payload_len >= SPU_XTS_TWEAK_SIZE)) 4908c2ecf20Sopenharmony_ci payload_len -= SPU_XTS_TWEAK_SIZE; 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci atomic64_add(payload_len, &iproc_priv.bytes_in); 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci flow_log("%s() offset: %u, bd_len: %u BD:\n", 4958c2ecf20Sopenharmony_ci __func__, rctx->total_received, payload_len); 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci dump_sg(req->dst, rctx->total_received, payload_len); 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci rctx->total_received += payload_len; 5008c2ecf20Sopenharmony_ci if (rctx->total_received == rctx->total_todo) { 5018c2ecf20Sopenharmony_ci atomic_inc(&iproc_priv.op_counts[SPU_OP_CIPHER]); 5028c2ecf20Sopenharmony_ci atomic_inc( 5038c2ecf20Sopenharmony_ci &iproc_priv.cipher_cnt[ctx->cipher.alg][ctx->cipher.mode]); 5048c2ecf20Sopenharmony_ci } 5058c2ecf20Sopenharmony_ci} 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci/** 5088c2ecf20Sopenharmony_ci * spu_ahash_rx_sg_create() - Build up the scatterlist of buffers used to 5098c2ecf20Sopenharmony_ci * receive a SPU response message for an ahash request. 5108c2ecf20Sopenharmony_ci * @mssg: mailbox message containing the receive sg 5118c2ecf20Sopenharmony_ci * @rctx: crypto request context 5128c2ecf20Sopenharmony_ci * @rx_frag_num: number of scatterlist elements required to hold the 5138c2ecf20Sopenharmony_ci * SPU response message 5148c2ecf20Sopenharmony_ci * @digestsize: length of hash digest, in bytes 5158c2ecf20Sopenharmony_ci * @stat_pad_len: Number of bytes required to pad the STAT field to 5168c2ecf20Sopenharmony_ci * a 4-byte boundary 5178c2ecf20Sopenharmony_ci * 5188c2ecf20Sopenharmony_ci * The scatterlist that gets allocated here is freed in spu_chunk_cleanup() 5198c2ecf20Sopenharmony_ci * when the request completes, whether the request is handled successfully or 5208c2ecf20Sopenharmony_ci * there is an error. 5218c2ecf20Sopenharmony_ci * 5228c2ecf20Sopenharmony_ci * Return: 5238c2ecf20Sopenharmony_ci * 0 if successful 5248c2ecf20Sopenharmony_ci * < 0 if an error 5258c2ecf20Sopenharmony_ci */ 5268c2ecf20Sopenharmony_cistatic int 5278c2ecf20Sopenharmony_cispu_ahash_rx_sg_create(struct brcm_message *mssg, 5288c2ecf20Sopenharmony_ci struct iproc_reqctx_s *rctx, 5298c2ecf20Sopenharmony_ci u8 rx_frag_num, unsigned int digestsize, 5308c2ecf20Sopenharmony_ci u32 stat_pad_len) 5318c2ecf20Sopenharmony_ci{ 5328c2ecf20Sopenharmony_ci struct spu_hw *spu = &iproc_priv.spu; 5338c2ecf20Sopenharmony_ci struct scatterlist *sg; /* used to build sgs in mbox message */ 5348c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = rctx->ctx; 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci mssg->spu.dst = kcalloc(rx_frag_num, sizeof(struct scatterlist), 5378c2ecf20Sopenharmony_ci rctx->gfp); 5388c2ecf20Sopenharmony_ci if (!mssg->spu.dst) 5398c2ecf20Sopenharmony_ci return -ENOMEM; 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci sg = mssg->spu.dst; 5428c2ecf20Sopenharmony_ci sg_init_table(sg, rx_frag_num); 5438c2ecf20Sopenharmony_ci /* Space for SPU message header */ 5448c2ecf20Sopenharmony_ci sg_set_buf(sg++, rctx->msg_buf.spu_resp_hdr, ctx->spu_resp_hdr_len); 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ci /* Space for digest */ 5478c2ecf20Sopenharmony_ci sg_set_buf(sg++, rctx->msg_buf.digest, digestsize); 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ci if (stat_pad_len) 5508c2ecf20Sopenharmony_ci sg_set_buf(sg++, rctx->msg_buf.rx_stat_pad, stat_pad_len); 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci memset(rctx->msg_buf.rx_stat, 0, SPU_RX_STATUS_LEN); 5538c2ecf20Sopenharmony_ci sg_set_buf(sg, rctx->msg_buf.rx_stat, spu->spu_rx_status_len()); 5548c2ecf20Sopenharmony_ci return 0; 5558c2ecf20Sopenharmony_ci} 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci/** 5588c2ecf20Sopenharmony_ci * spu_ahash_tx_sg_create() - Build up the scatterlist of buffers used to send 5598c2ecf20Sopenharmony_ci * a SPU request message for an ahash request. Includes SPU message headers and 5608c2ecf20Sopenharmony_ci * the request data. 5618c2ecf20Sopenharmony_ci * @mssg: mailbox message containing the transmit sg 5628c2ecf20Sopenharmony_ci * @rctx: crypto request context 5638c2ecf20Sopenharmony_ci * @tx_frag_num: number of scatterlist elements required to construct the 5648c2ecf20Sopenharmony_ci * SPU request message 5658c2ecf20Sopenharmony_ci * @spu_hdr_len: length in bytes of SPU message header 5668c2ecf20Sopenharmony_ci * @hash_carry_len: Number of bytes of data carried over from previous req 5678c2ecf20Sopenharmony_ci * @new_data_len: Number of bytes of new request data 5688c2ecf20Sopenharmony_ci * @pad_len: Number of pad bytes 5698c2ecf20Sopenharmony_ci * 5708c2ecf20Sopenharmony_ci * The scatterlist that gets allocated here is freed in spu_chunk_cleanup() 5718c2ecf20Sopenharmony_ci * when the request completes, whether the request is handled successfully or 5728c2ecf20Sopenharmony_ci * there is an error. 5738c2ecf20Sopenharmony_ci * 5748c2ecf20Sopenharmony_ci * Return: 5758c2ecf20Sopenharmony_ci * 0 if successful 5768c2ecf20Sopenharmony_ci * < 0 if an error 5778c2ecf20Sopenharmony_ci */ 5788c2ecf20Sopenharmony_cistatic int 5798c2ecf20Sopenharmony_cispu_ahash_tx_sg_create(struct brcm_message *mssg, 5808c2ecf20Sopenharmony_ci struct iproc_reqctx_s *rctx, 5818c2ecf20Sopenharmony_ci u8 tx_frag_num, 5828c2ecf20Sopenharmony_ci u32 spu_hdr_len, 5838c2ecf20Sopenharmony_ci unsigned int hash_carry_len, 5848c2ecf20Sopenharmony_ci unsigned int new_data_len, u32 pad_len) 5858c2ecf20Sopenharmony_ci{ 5868c2ecf20Sopenharmony_ci struct spu_hw *spu = &iproc_priv.spu; 5878c2ecf20Sopenharmony_ci struct scatterlist *sg; /* used to build sgs in mbox message */ 5888c2ecf20Sopenharmony_ci u32 datalen; /* Number of bytes of response data expected */ 5898c2ecf20Sopenharmony_ci u32 stat_len; 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci mssg->spu.src = kcalloc(tx_frag_num, sizeof(struct scatterlist), 5928c2ecf20Sopenharmony_ci rctx->gfp); 5938c2ecf20Sopenharmony_ci if (!mssg->spu.src) 5948c2ecf20Sopenharmony_ci return -ENOMEM; 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci sg = mssg->spu.src; 5978c2ecf20Sopenharmony_ci sg_init_table(sg, tx_frag_num); 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci sg_set_buf(sg++, rctx->msg_buf.bcm_spu_req_hdr, 6008c2ecf20Sopenharmony_ci BCM_HDR_LEN + spu_hdr_len); 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_ci if (hash_carry_len) 6038c2ecf20Sopenharmony_ci sg_set_buf(sg++, rctx->hash_carry, hash_carry_len); 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ci if (new_data_len) { 6068c2ecf20Sopenharmony_ci /* Copy in each src sg entry from request, up to chunksize */ 6078c2ecf20Sopenharmony_ci datalen = spu_msg_sg_add(&sg, &rctx->src_sg, &rctx->src_skip, 6088c2ecf20Sopenharmony_ci rctx->src_nents, new_data_len); 6098c2ecf20Sopenharmony_ci if (datalen < new_data_len) { 6108c2ecf20Sopenharmony_ci pr_err("%s(): failed to copy src sg to mbox msg", 6118c2ecf20Sopenharmony_ci __func__); 6128c2ecf20Sopenharmony_ci return -EFAULT; 6138c2ecf20Sopenharmony_ci } 6148c2ecf20Sopenharmony_ci } 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci if (pad_len) 6178c2ecf20Sopenharmony_ci sg_set_buf(sg++, rctx->msg_buf.spu_req_pad, pad_len); 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci stat_len = spu->spu_tx_status_len(); 6208c2ecf20Sopenharmony_ci if (stat_len) { 6218c2ecf20Sopenharmony_ci memset(rctx->msg_buf.tx_stat, 0, stat_len); 6228c2ecf20Sopenharmony_ci sg_set_buf(sg, rctx->msg_buf.tx_stat, stat_len); 6238c2ecf20Sopenharmony_ci } 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_ci return 0; 6268c2ecf20Sopenharmony_ci} 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci/** 6298c2ecf20Sopenharmony_ci * handle_ahash_req() - Process an asynchronous hash request from the crypto 6308c2ecf20Sopenharmony_ci * API. 6318c2ecf20Sopenharmony_ci * @rctx: Crypto request context 6328c2ecf20Sopenharmony_ci * 6338c2ecf20Sopenharmony_ci * Builds a SPU request message embedded in a mailbox message and submits the 6348c2ecf20Sopenharmony_ci * mailbox message on a selected mailbox channel. The SPU request message is 6358c2ecf20Sopenharmony_ci * constructed as a scatterlist, including entries from the crypto API's 6368c2ecf20Sopenharmony_ci * src scatterlist to avoid copying the data to be hashed. This function is 6378c2ecf20Sopenharmony_ci * called either on the thread from the crypto API, or, in the case that the 6388c2ecf20Sopenharmony_ci * crypto API request is too large to fit in a single SPU request message, 6398c2ecf20Sopenharmony_ci * on the thread that invokes the receive callback with a response message. 6408c2ecf20Sopenharmony_ci * Because some operations require the response from one chunk before the next 6418c2ecf20Sopenharmony_ci * chunk can be submitted, we always wait for the response for the previous 6428c2ecf20Sopenharmony_ci * chunk before submitting the next chunk. Because requests are submitted in 6438c2ecf20Sopenharmony_ci * lock step like this, there is no need to synchronize access to request data 6448c2ecf20Sopenharmony_ci * structures. 6458c2ecf20Sopenharmony_ci * 6468c2ecf20Sopenharmony_ci * Return: 6478c2ecf20Sopenharmony_ci * -EINPROGRESS: request has been submitted to SPU and response will be 6488c2ecf20Sopenharmony_ci * returned asynchronously 6498c2ecf20Sopenharmony_ci * -EAGAIN: non-final request included a small amount of data, which for 6508c2ecf20Sopenharmony_ci * efficiency we did not submit to the SPU, but instead stored 6518c2ecf20Sopenharmony_ci * to be submitted to the SPU with the next part of the request 6528c2ecf20Sopenharmony_ci * other: an error code 6538c2ecf20Sopenharmony_ci */ 6548c2ecf20Sopenharmony_cistatic int handle_ahash_req(struct iproc_reqctx_s *rctx) 6558c2ecf20Sopenharmony_ci{ 6568c2ecf20Sopenharmony_ci struct spu_hw *spu = &iproc_priv.spu; 6578c2ecf20Sopenharmony_ci struct crypto_async_request *areq = rctx->parent; 6588c2ecf20Sopenharmony_ci struct ahash_request *req = ahash_request_cast(areq); 6598c2ecf20Sopenharmony_ci struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); 6608c2ecf20Sopenharmony_ci struct crypto_tfm *tfm = crypto_ahash_tfm(ahash); 6618c2ecf20Sopenharmony_ci unsigned int blocksize = crypto_tfm_alg_blocksize(tfm); 6628c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = rctx->ctx; 6638c2ecf20Sopenharmony_ci 6648c2ecf20Sopenharmony_ci /* number of bytes still to be hashed in this req */ 6658c2ecf20Sopenharmony_ci unsigned int nbytes_to_hash = 0; 6668c2ecf20Sopenharmony_ci int err; 6678c2ecf20Sopenharmony_ci unsigned int chunksize = 0; /* length of hash carry + new data */ 6688c2ecf20Sopenharmony_ci /* 6698c2ecf20Sopenharmony_ci * length of new data, not from hash carry, to be submitted in 6708c2ecf20Sopenharmony_ci * this hw request 6718c2ecf20Sopenharmony_ci */ 6728c2ecf20Sopenharmony_ci unsigned int new_data_len; 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci unsigned int __maybe_unused chunk_start = 0; 6758c2ecf20Sopenharmony_ci u32 db_size; /* Length of data field, incl gcm and hash padding */ 6768c2ecf20Sopenharmony_ci int pad_len = 0; /* total pad len, including gcm, hash, stat padding */ 6778c2ecf20Sopenharmony_ci u32 data_pad_len = 0; /* length of GCM/CCM padding */ 6788c2ecf20Sopenharmony_ci u32 stat_pad_len = 0; /* length of padding to align STATUS word */ 6798c2ecf20Sopenharmony_ci struct brcm_message *mssg; /* mailbox message */ 6808c2ecf20Sopenharmony_ci struct spu_request_opts req_opts; 6818c2ecf20Sopenharmony_ci struct spu_cipher_parms cipher_parms; 6828c2ecf20Sopenharmony_ci struct spu_hash_parms hash_parms; 6838c2ecf20Sopenharmony_ci struct spu_aead_parms aead_parms; 6848c2ecf20Sopenharmony_ci unsigned int local_nbuf; 6858c2ecf20Sopenharmony_ci u32 spu_hdr_len; 6868c2ecf20Sopenharmony_ci unsigned int digestsize; 6878c2ecf20Sopenharmony_ci u16 rem = 0; 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_ci /* 6908c2ecf20Sopenharmony_ci * number of entries in src and dst sg. Always includes SPU msg header. 6918c2ecf20Sopenharmony_ci * rx always includes a buffer to catch digest and STATUS. 6928c2ecf20Sopenharmony_ci */ 6938c2ecf20Sopenharmony_ci u8 rx_frag_num = 3; 6948c2ecf20Sopenharmony_ci u8 tx_frag_num = 1; 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_ci flow_log("total_todo %u, total_sent %u\n", 6978c2ecf20Sopenharmony_ci rctx->total_todo, rctx->total_sent); 6988c2ecf20Sopenharmony_ci 6998c2ecf20Sopenharmony_ci memset(&req_opts, 0, sizeof(req_opts)); 7008c2ecf20Sopenharmony_ci memset(&cipher_parms, 0, sizeof(cipher_parms)); 7018c2ecf20Sopenharmony_ci memset(&hash_parms, 0, sizeof(hash_parms)); 7028c2ecf20Sopenharmony_ci memset(&aead_parms, 0, sizeof(aead_parms)); 7038c2ecf20Sopenharmony_ci 7048c2ecf20Sopenharmony_ci req_opts.bd_suppress = true; 7058c2ecf20Sopenharmony_ci hash_parms.alg = ctx->auth.alg; 7068c2ecf20Sopenharmony_ci hash_parms.mode = ctx->auth.mode; 7078c2ecf20Sopenharmony_ci hash_parms.type = HASH_TYPE_NONE; 7088c2ecf20Sopenharmony_ci hash_parms.key_buf = (u8 *)ctx->authkey; 7098c2ecf20Sopenharmony_ci hash_parms.key_len = ctx->authkeylen; 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci /* 7128c2ecf20Sopenharmony_ci * For hash algorithms below assignment looks bit odd but 7138c2ecf20Sopenharmony_ci * it's needed for AES-XCBC and AES-CMAC hash algorithms 7148c2ecf20Sopenharmony_ci * to differentiate between 128, 192, 256 bit key values. 7158c2ecf20Sopenharmony_ci * Based on the key values, hash algorithm is selected. 7168c2ecf20Sopenharmony_ci * For example for 128 bit key, hash algorithm is AES-128. 7178c2ecf20Sopenharmony_ci */ 7188c2ecf20Sopenharmony_ci cipher_parms.type = ctx->cipher_type; 7198c2ecf20Sopenharmony_ci 7208c2ecf20Sopenharmony_ci mssg = &rctx->mb_mssg; 7218c2ecf20Sopenharmony_ci chunk_start = rctx->src_sent; 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci /* 7248c2ecf20Sopenharmony_ci * Compute the amount remaining to hash. This may include data 7258c2ecf20Sopenharmony_ci * carried over from previous requests. 7268c2ecf20Sopenharmony_ci */ 7278c2ecf20Sopenharmony_ci nbytes_to_hash = rctx->total_todo - rctx->total_sent; 7288c2ecf20Sopenharmony_ci chunksize = nbytes_to_hash; 7298c2ecf20Sopenharmony_ci if ((ctx->max_payload != SPU_MAX_PAYLOAD_INF) && 7308c2ecf20Sopenharmony_ci (chunksize > ctx->max_payload)) 7318c2ecf20Sopenharmony_ci chunksize = ctx->max_payload; 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_ci /* 7348c2ecf20Sopenharmony_ci * If this is not a final request and the request data is not a multiple 7358c2ecf20Sopenharmony_ci * of a full block, then simply park the extra data and prefix it to the 7368c2ecf20Sopenharmony_ci * data for the next request. 7378c2ecf20Sopenharmony_ci */ 7388c2ecf20Sopenharmony_ci if (!rctx->is_final) { 7398c2ecf20Sopenharmony_ci u8 *dest = rctx->hash_carry + rctx->hash_carry_len; 7408c2ecf20Sopenharmony_ci u16 new_len; /* len of data to add to hash carry */ 7418c2ecf20Sopenharmony_ci 7428c2ecf20Sopenharmony_ci rem = chunksize % blocksize; /* remainder */ 7438c2ecf20Sopenharmony_ci if (rem) { 7448c2ecf20Sopenharmony_ci /* chunksize not a multiple of blocksize */ 7458c2ecf20Sopenharmony_ci chunksize -= rem; 7468c2ecf20Sopenharmony_ci if (chunksize == 0) { 7478c2ecf20Sopenharmony_ci /* Don't have a full block to submit to hw */ 7488c2ecf20Sopenharmony_ci new_len = rem - rctx->hash_carry_len; 7498c2ecf20Sopenharmony_ci sg_copy_part_to_buf(req->src, dest, new_len, 7508c2ecf20Sopenharmony_ci rctx->src_sent); 7518c2ecf20Sopenharmony_ci rctx->hash_carry_len = rem; 7528c2ecf20Sopenharmony_ci flow_log("Exiting with hash carry len: %u\n", 7538c2ecf20Sopenharmony_ci rctx->hash_carry_len); 7548c2ecf20Sopenharmony_ci packet_dump(" buf: ", 7558c2ecf20Sopenharmony_ci rctx->hash_carry, 7568c2ecf20Sopenharmony_ci rctx->hash_carry_len); 7578c2ecf20Sopenharmony_ci return -EAGAIN; 7588c2ecf20Sopenharmony_ci } 7598c2ecf20Sopenharmony_ci } 7608c2ecf20Sopenharmony_ci } 7618c2ecf20Sopenharmony_ci 7628c2ecf20Sopenharmony_ci /* if we have hash carry, then prefix it to the data in this request */ 7638c2ecf20Sopenharmony_ci local_nbuf = rctx->hash_carry_len; 7648c2ecf20Sopenharmony_ci rctx->hash_carry_len = 0; 7658c2ecf20Sopenharmony_ci if (local_nbuf) 7668c2ecf20Sopenharmony_ci tx_frag_num++; 7678c2ecf20Sopenharmony_ci new_data_len = chunksize - local_nbuf; 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_ci /* Count number of sg entries to be used in this request */ 7708c2ecf20Sopenharmony_ci rctx->src_nents = spu_sg_count(rctx->src_sg, rctx->src_skip, 7718c2ecf20Sopenharmony_ci new_data_len); 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci /* AES hashing keeps key size in type field, so need to copy it here */ 7748c2ecf20Sopenharmony_ci if (hash_parms.alg == HASH_ALG_AES) 7758c2ecf20Sopenharmony_ci hash_parms.type = (enum hash_type)cipher_parms.type; 7768c2ecf20Sopenharmony_ci else 7778c2ecf20Sopenharmony_ci hash_parms.type = spu->spu_hash_type(rctx->total_sent); 7788c2ecf20Sopenharmony_ci 7798c2ecf20Sopenharmony_ci digestsize = spu->spu_digest_size(ctx->digestsize, ctx->auth.alg, 7808c2ecf20Sopenharmony_ci hash_parms.type); 7818c2ecf20Sopenharmony_ci hash_parms.digestsize = digestsize; 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_ci /* update the indexes */ 7848c2ecf20Sopenharmony_ci rctx->total_sent += chunksize; 7858c2ecf20Sopenharmony_ci /* if you sent a prebuf then that wasn't from this req->src */ 7868c2ecf20Sopenharmony_ci rctx->src_sent += new_data_len; 7878c2ecf20Sopenharmony_ci 7888c2ecf20Sopenharmony_ci if ((rctx->total_sent == rctx->total_todo) && rctx->is_final) 7898c2ecf20Sopenharmony_ci hash_parms.pad_len = spu->spu_hash_pad_len(hash_parms.alg, 7908c2ecf20Sopenharmony_ci hash_parms.mode, 7918c2ecf20Sopenharmony_ci chunksize, 7928c2ecf20Sopenharmony_ci blocksize); 7938c2ecf20Sopenharmony_ci 7948c2ecf20Sopenharmony_ci /* 7958c2ecf20Sopenharmony_ci * If a non-first chunk, then include the digest returned from the 7968c2ecf20Sopenharmony_ci * previous chunk so that hw can add to it (except for AES types). 7978c2ecf20Sopenharmony_ci */ 7988c2ecf20Sopenharmony_ci if ((hash_parms.type == HASH_TYPE_UPDT) && 7998c2ecf20Sopenharmony_ci (hash_parms.alg != HASH_ALG_AES)) { 8008c2ecf20Sopenharmony_ci hash_parms.key_buf = rctx->incr_hash; 8018c2ecf20Sopenharmony_ci hash_parms.key_len = digestsize; 8028c2ecf20Sopenharmony_ci } 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_ci atomic64_add(chunksize, &iproc_priv.bytes_out); 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_ci flow_log("%s() final: %u nbuf: %u ", 8078c2ecf20Sopenharmony_ci __func__, rctx->is_final, local_nbuf); 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci if (ctx->max_payload == SPU_MAX_PAYLOAD_INF) 8108c2ecf20Sopenharmony_ci flow_log("max_payload infinite\n"); 8118c2ecf20Sopenharmony_ci else 8128c2ecf20Sopenharmony_ci flow_log("max_payload %u\n", ctx->max_payload); 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_ci flow_log("chunk_start: %u chunk_size: %u\n", chunk_start, chunksize); 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_ci /* Prepend SPU header with type 3 BCM header */ 8178c2ecf20Sopenharmony_ci memcpy(rctx->msg_buf.bcm_spu_req_hdr, BCMHEADER, BCM_HDR_LEN); 8188c2ecf20Sopenharmony_ci 8198c2ecf20Sopenharmony_ci hash_parms.prebuf_len = local_nbuf; 8208c2ecf20Sopenharmony_ci spu_hdr_len = spu->spu_create_request(rctx->msg_buf.bcm_spu_req_hdr + 8218c2ecf20Sopenharmony_ci BCM_HDR_LEN, 8228c2ecf20Sopenharmony_ci &req_opts, &cipher_parms, 8238c2ecf20Sopenharmony_ci &hash_parms, &aead_parms, 8248c2ecf20Sopenharmony_ci new_data_len); 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_ci if (spu_hdr_len == 0) { 8278c2ecf20Sopenharmony_ci pr_err("Failed to create SPU request header\n"); 8288c2ecf20Sopenharmony_ci return -EFAULT; 8298c2ecf20Sopenharmony_ci } 8308c2ecf20Sopenharmony_ci 8318c2ecf20Sopenharmony_ci /* 8328c2ecf20Sopenharmony_ci * Determine total length of padding required. Put all padding in one 8338c2ecf20Sopenharmony_ci * buffer. 8348c2ecf20Sopenharmony_ci */ 8358c2ecf20Sopenharmony_ci data_pad_len = spu->spu_gcm_ccm_pad_len(ctx->cipher.mode, chunksize); 8368c2ecf20Sopenharmony_ci db_size = spu_real_db_size(0, 0, local_nbuf, new_data_len, 8378c2ecf20Sopenharmony_ci 0, 0, hash_parms.pad_len); 8388c2ecf20Sopenharmony_ci if (spu->spu_tx_status_len()) 8398c2ecf20Sopenharmony_ci stat_pad_len = spu->spu_wordalign_padlen(db_size); 8408c2ecf20Sopenharmony_ci if (stat_pad_len) 8418c2ecf20Sopenharmony_ci rx_frag_num++; 8428c2ecf20Sopenharmony_ci pad_len = hash_parms.pad_len + data_pad_len + stat_pad_len; 8438c2ecf20Sopenharmony_ci if (pad_len) { 8448c2ecf20Sopenharmony_ci tx_frag_num++; 8458c2ecf20Sopenharmony_ci spu->spu_request_pad(rctx->msg_buf.spu_req_pad, data_pad_len, 8468c2ecf20Sopenharmony_ci hash_parms.pad_len, ctx->auth.alg, 8478c2ecf20Sopenharmony_ci ctx->auth.mode, rctx->total_sent, 8488c2ecf20Sopenharmony_ci stat_pad_len); 8498c2ecf20Sopenharmony_ci } 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_ci spu->spu_dump_msg_hdr(rctx->msg_buf.bcm_spu_req_hdr + BCM_HDR_LEN, 8528c2ecf20Sopenharmony_ci spu_hdr_len); 8538c2ecf20Sopenharmony_ci packet_dump(" prebuf: ", rctx->hash_carry, local_nbuf); 8548c2ecf20Sopenharmony_ci flow_log("Data:\n"); 8558c2ecf20Sopenharmony_ci dump_sg(rctx->src_sg, rctx->src_skip, new_data_len); 8568c2ecf20Sopenharmony_ci packet_dump(" pad: ", rctx->msg_buf.spu_req_pad, pad_len); 8578c2ecf20Sopenharmony_ci 8588c2ecf20Sopenharmony_ci /* 8598c2ecf20Sopenharmony_ci * Build mailbox message containing SPU request msg and rx buffers 8608c2ecf20Sopenharmony_ci * to catch response message 8618c2ecf20Sopenharmony_ci */ 8628c2ecf20Sopenharmony_ci memset(mssg, 0, sizeof(*mssg)); 8638c2ecf20Sopenharmony_ci mssg->type = BRCM_MESSAGE_SPU; 8648c2ecf20Sopenharmony_ci mssg->ctx = rctx; /* Will be returned in response */ 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_ci /* Create rx scatterlist to catch result */ 8678c2ecf20Sopenharmony_ci err = spu_ahash_rx_sg_create(mssg, rctx, rx_frag_num, digestsize, 8688c2ecf20Sopenharmony_ci stat_pad_len); 8698c2ecf20Sopenharmony_ci if (err) 8708c2ecf20Sopenharmony_ci return err; 8718c2ecf20Sopenharmony_ci 8728c2ecf20Sopenharmony_ci /* Create tx scatterlist containing SPU request message */ 8738c2ecf20Sopenharmony_ci tx_frag_num += rctx->src_nents; 8748c2ecf20Sopenharmony_ci if (spu->spu_tx_status_len()) 8758c2ecf20Sopenharmony_ci tx_frag_num++; 8768c2ecf20Sopenharmony_ci err = spu_ahash_tx_sg_create(mssg, rctx, tx_frag_num, spu_hdr_len, 8778c2ecf20Sopenharmony_ci local_nbuf, new_data_len, pad_len); 8788c2ecf20Sopenharmony_ci if (err) 8798c2ecf20Sopenharmony_ci return err; 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_ci err = mailbox_send_message(mssg, req->base.flags, rctx->chan_idx); 8828c2ecf20Sopenharmony_ci if (unlikely(err < 0)) 8838c2ecf20Sopenharmony_ci return err; 8848c2ecf20Sopenharmony_ci 8858c2ecf20Sopenharmony_ci return -EINPROGRESS; 8868c2ecf20Sopenharmony_ci} 8878c2ecf20Sopenharmony_ci 8888c2ecf20Sopenharmony_ci/** 8898c2ecf20Sopenharmony_ci * spu_hmac_outer_hash() - Request synchonous software compute of the outer hash 8908c2ecf20Sopenharmony_ci * for an HMAC request. 8918c2ecf20Sopenharmony_ci * @req: The HMAC request from the crypto API 8928c2ecf20Sopenharmony_ci * @ctx: The session context 8938c2ecf20Sopenharmony_ci * 8948c2ecf20Sopenharmony_ci * Return: 0 if synchronous hash operation successful 8958c2ecf20Sopenharmony_ci * -EINVAL if the hash algo is unrecognized 8968c2ecf20Sopenharmony_ci * any other value indicates an error 8978c2ecf20Sopenharmony_ci */ 8988c2ecf20Sopenharmony_cistatic int spu_hmac_outer_hash(struct ahash_request *req, 8998c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx) 9008c2ecf20Sopenharmony_ci{ 9018c2ecf20Sopenharmony_ci struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); 9028c2ecf20Sopenharmony_ci unsigned int blocksize = 9038c2ecf20Sopenharmony_ci crypto_tfm_alg_blocksize(crypto_ahash_tfm(ahash)); 9048c2ecf20Sopenharmony_ci int rc; 9058c2ecf20Sopenharmony_ci 9068c2ecf20Sopenharmony_ci switch (ctx->auth.alg) { 9078c2ecf20Sopenharmony_ci case HASH_ALG_MD5: 9088c2ecf20Sopenharmony_ci rc = do_shash("md5", req->result, ctx->opad, blocksize, 9098c2ecf20Sopenharmony_ci req->result, ctx->digestsize, NULL, 0); 9108c2ecf20Sopenharmony_ci break; 9118c2ecf20Sopenharmony_ci case HASH_ALG_SHA1: 9128c2ecf20Sopenharmony_ci rc = do_shash("sha1", req->result, ctx->opad, blocksize, 9138c2ecf20Sopenharmony_ci req->result, ctx->digestsize, NULL, 0); 9148c2ecf20Sopenharmony_ci break; 9158c2ecf20Sopenharmony_ci case HASH_ALG_SHA224: 9168c2ecf20Sopenharmony_ci rc = do_shash("sha224", req->result, ctx->opad, blocksize, 9178c2ecf20Sopenharmony_ci req->result, ctx->digestsize, NULL, 0); 9188c2ecf20Sopenharmony_ci break; 9198c2ecf20Sopenharmony_ci case HASH_ALG_SHA256: 9208c2ecf20Sopenharmony_ci rc = do_shash("sha256", req->result, ctx->opad, blocksize, 9218c2ecf20Sopenharmony_ci req->result, ctx->digestsize, NULL, 0); 9228c2ecf20Sopenharmony_ci break; 9238c2ecf20Sopenharmony_ci case HASH_ALG_SHA384: 9248c2ecf20Sopenharmony_ci rc = do_shash("sha384", req->result, ctx->opad, blocksize, 9258c2ecf20Sopenharmony_ci req->result, ctx->digestsize, NULL, 0); 9268c2ecf20Sopenharmony_ci break; 9278c2ecf20Sopenharmony_ci case HASH_ALG_SHA512: 9288c2ecf20Sopenharmony_ci rc = do_shash("sha512", req->result, ctx->opad, blocksize, 9298c2ecf20Sopenharmony_ci req->result, ctx->digestsize, NULL, 0); 9308c2ecf20Sopenharmony_ci break; 9318c2ecf20Sopenharmony_ci default: 9328c2ecf20Sopenharmony_ci pr_err("%s() Error : unknown hmac type\n", __func__); 9338c2ecf20Sopenharmony_ci rc = -EINVAL; 9348c2ecf20Sopenharmony_ci } 9358c2ecf20Sopenharmony_ci return rc; 9368c2ecf20Sopenharmony_ci} 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_ci/** 9398c2ecf20Sopenharmony_ci * ahash_req_done() - Process a hash result from the SPU hardware. 9408c2ecf20Sopenharmony_ci * @rctx: Crypto request context 9418c2ecf20Sopenharmony_ci * 9428c2ecf20Sopenharmony_ci * Return: 0 if successful 9438c2ecf20Sopenharmony_ci * < 0 if an error 9448c2ecf20Sopenharmony_ci */ 9458c2ecf20Sopenharmony_cistatic int ahash_req_done(struct iproc_reqctx_s *rctx) 9468c2ecf20Sopenharmony_ci{ 9478c2ecf20Sopenharmony_ci struct spu_hw *spu = &iproc_priv.spu; 9488c2ecf20Sopenharmony_ci struct crypto_async_request *areq = rctx->parent; 9498c2ecf20Sopenharmony_ci struct ahash_request *req = ahash_request_cast(areq); 9508c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = rctx->ctx; 9518c2ecf20Sopenharmony_ci int err; 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ci memcpy(req->result, rctx->msg_buf.digest, ctx->digestsize); 9548c2ecf20Sopenharmony_ci 9558c2ecf20Sopenharmony_ci if (spu->spu_type == SPU_TYPE_SPUM) { 9568c2ecf20Sopenharmony_ci /* byte swap the output from the UPDT function to network byte 9578c2ecf20Sopenharmony_ci * order 9588c2ecf20Sopenharmony_ci */ 9598c2ecf20Sopenharmony_ci if (ctx->auth.alg == HASH_ALG_MD5) { 9608c2ecf20Sopenharmony_ci __swab32s((u32 *)req->result); 9618c2ecf20Sopenharmony_ci __swab32s(((u32 *)req->result) + 1); 9628c2ecf20Sopenharmony_ci __swab32s(((u32 *)req->result) + 2); 9638c2ecf20Sopenharmony_ci __swab32s(((u32 *)req->result) + 3); 9648c2ecf20Sopenharmony_ci __swab32s(((u32 *)req->result) + 4); 9658c2ecf20Sopenharmony_ci } 9668c2ecf20Sopenharmony_ci } 9678c2ecf20Sopenharmony_ci 9688c2ecf20Sopenharmony_ci flow_dump(" digest ", req->result, ctx->digestsize); 9698c2ecf20Sopenharmony_ci 9708c2ecf20Sopenharmony_ci /* if this an HMAC then do the outer hash */ 9718c2ecf20Sopenharmony_ci if (rctx->is_sw_hmac) { 9728c2ecf20Sopenharmony_ci err = spu_hmac_outer_hash(req, ctx); 9738c2ecf20Sopenharmony_ci if (err < 0) 9748c2ecf20Sopenharmony_ci return err; 9758c2ecf20Sopenharmony_ci flow_dump(" hmac: ", req->result, ctx->digestsize); 9768c2ecf20Sopenharmony_ci } 9778c2ecf20Sopenharmony_ci 9788c2ecf20Sopenharmony_ci if (rctx->is_sw_hmac || ctx->auth.mode == HASH_MODE_HMAC) { 9798c2ecf20Sopenharmony_ci atomic_inc(&iproc_priv.op_counts[SPU_OP_HMAC]); 9808c2ecf20Sopenharmony_ci atomic_inc(&iproc_priv.hmac_cnt[ctx->auth.alg]); 9818c2ecf20Sopenharmony_ci } else { 9828c2ecf20Sopenharmony_ci atomic_inc(&iproc_priv.op_counts[SPU_OP_HASH]); 9838c2ecf20Sopenharmony_ci atomic_inc(&iproc_priv.hash_cnt[ctx->auth.alg]); 9848c2ecf20Sopenharmony_ci } 9858c2ecf20Sopenharmony_ci 9868c2ecf20Sopenharmony_ci return 0; 9878c2ecf20Sopenharmony_ci} 9888c2ecf20Sopenharmony_ci 9898c2ecf20Sopenharmony_ci/** 9908c2ecf20Sopenharmony_ci * handle_ahash_resp() - Process a SPU response message for a hash request. 9918c2ecf20Sopenharmony_ci * Checks if the entire crypto API request has been processed, and if so, 9928c2ecf20Sopenharmony_ci * invokes post processing on the result. 9938c2ecf20Sopenharmony_ci * @rctx: Crypto request context 9948c2ecf20Sopenharmony_ci */ 9958c2ecf20Sopenharmony_cistatic void handle_ahash_resp(struct iproc_reqctx_s *rctx) 9968c2ecf20Sopenharmony_ci{ 9978c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = rctx->ctx; 9988c2ecf20Sopenharmony_ci#ifdef DEBUG 9998c2ecf20Sopenharmony_ci struct crypto_async_request *areq = rctx->parent; 10008c2ecf20Sopenharmony_ci struct ahash_request *req = ahash_request_cast(areq); 10018c2ecf20Sopenharmony_ci struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); 10028c2ecf20Sopenharmony_ci unsigned int blocksize = 10038c2ecf20Sopenharmony_ci crypto_tfm_alg_blocksize(crypto_ahash_tfm(ahash)); 10048c2ecf20Sopenharmony_ci#endif 10058c2ecf20Sopenharmony_ci /* 10068c2ecf20Sopenharmony_ci * Save hash to use as input to next op if incremental. Might be copying 10078c2ecf20Sopenharmony_ci * too much, but that's easier than figuring out actual digest size here 10088c2ecf20Sopenharmony_ci */ 10098c2ecf20Sopenharmony_ci memcpy(rctx->incr_hash, rctx->msg_buf.digest, MAX_DIGEST_SIZE); 10108c2ecf20Sopenharmony_ci 10118c2ecf20Sopenharmony_ci flow_log("%s() blocksize:%u digestsize:%u\n", 10128c2ecf20Sopenharmony_ci __func__, blocksize, ctx->digestsize); 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_ci atomic64_add(ctx->digestsize, &iproc_priv.bytes_in); 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_ci if (rctx->is_final && (rctx->total_sent == rctx->total_todo)) 10178c2ecf20Sopenharmony_ci ahash_req_done(rctx); 10188c2ecf20Sopenharmony_ci} 10198c2ecf20Sopenharmony_ci 10208c2ecf20Sopenharmony_ci/** 10218c2ecf20Sopenharmony_ci * spu_aead_rx_sg_create() - Build up the scatterlist of buffers used to receive 10228c2ecf20Sopenharmony_ci * a SPU response message for an AEAD request. Includes buffers to catch SPU 10238c2ecf20Sopenharmony_ci * message headers and the response data. 10248c2ecf20Sopenharmony_ci * @mssg: mailbox message containing the receive sg 10258c2ecf20Sopenharmony_ci * @rctx: crypto request context 10268c2ecf20Sopenharmony_ci * @rx_frag_num: number of scatterlist elements required to hold the 10278c2ecf20Sopenharmony_ci * SPU response message 10288c2ecf20Sopenharmony_ci * @assoc_len: Length of associated data included in the crypto request 10298c2ecf20Sopenharmony_ci * @ret_iv_len: Length of IV returned in response 10308c2ecf20Sopenharmony_ci * @resp_len: Number of bytes of response data expected to be written to 10318c2ecf20Sopenharmony_ci * dst buffer from crypto API 10328c2ecf20Sopenharmony_ci * @digestsize: Length of hash digest, in bytes 10338c2ecf20Sopenharmony_ci * @stat_pad_len: Number of bytes required to pad the STAT field to 10348c2ecf20Sopenharmony_ci * a 4-byte boundary 10358c2ecf20Sopenharmony_ci * 10368c2ecf20Sopenharmony_ci * The scatterlist that gets allocated here is freed in spu_chunk_cleanup() 10378c2ecf20Sopenharmony_ci * when the request completes, whether the request is handled successfully or 10388c2ecf20Sopenharmony_ci * there is an error. 10398c2ecf20Sopenharmony_ci * 10408c2ecf20Sopenharmony_ci * Returns: 10418c2ecf20Sopenharmony_ci * 0 if successful 10428c2ecf20Sopenharmony_ci * < 0 if an error 10438c2ecf20Sopenharmony_ci */ 10448c2ecf20Sopenharmony_cistatic int spu_aead_rx_sg_create(struct brcm_message *mssg, 10458c2ecf20Sopenharmony_ci struct aead_request *req, 10468c2ecf20Sopenharmony_ci struct iproc_reqctx_s *rctx, 10478c2ecf20Sopenharmony_ci u8 rx_frag_num, 10488c2ecf20Sopenharmony_ci unsigned int assoc_len, 10498c2ecf20Sopenharmony_ci u32 ret_iv_len, unsigned int resp_len, 10508c2ecf20Sopenharmony_ci unsigned int digestsize, u32 stat_pad_len) 10518c2ecf20Sopenharmony_ci{ 10528c2ecf20Sopenharmony_ci struct spu_hw *spu = &iproc_priv.spu; 10538c2ecf20Sopenharmony_ci struct scatterlist *sg; /* used to build sgs in mbox message */ 10548c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = rctx->ctx; 10558c2ecf20Sopenharmony_ci u32 datalen; /* Number of bytes of response data expected */ 10568c2ecf20Sopenharmony_ci u32 assoc_buf_len; 10578c2ecf20Sopenharmony_ci u8 data_padlen = 0; 10588c2ecf20Sopenharmony_ci 10598c2ecf20Sopenharmony_ci if (ctx->is_rfc4543) { 10608c2ecf20Sopenharmony_ci /* RFC4543: only pad after data, not after AAD */ 10618c2ecf20Sopenharmony_ci data_padlen = spu->spu_gcm_ccm_pad_len(ctx->cipher.mode, 10628c2ecf20Sopenharmony_ci assoc_len + resp_len); 10638c2ecf20Sopenharmony_ci assoc_buf_len = assoc_len; 10648c2ecf20Sopenharmony_ci } else { 10658c2ecf20Sopenharmony_ci data_padlen = spu->spu_gcm_ccm_pad_len(ctx->cipher.mode, 10668c2ecf20Sopenharmony_ci resp_len); 10678c2ecf20Sopenharmony_ci assoc_buf_len = spu->spu_assoc_resp_len(ctx->cipher.mode, 10688c2ecf20Sopenharmony_ci assoc_len, ret_iv_len, 10698c2ecf20Sopenharmony_ci rctx->is_encrypt); 10708c2ecf20Sopenharmony_ci } 10718c2ecf20Sopenharmony_ci 10728c2ecf20Sopenharmony_ci if (ctx->cipher.mode == CIPHER_MODE_CCM) 10738c2ecf20Sopenharmony_ci /* ICV (after data) must be in the next 32-bit word for CCM */ 10748c2ecf20Sopenharmony_ci data_padlen += spu->spu_wordalign_padlen(assoc_buf_len + 10758c2ecf20Sopenharmony_ci resp_len + 10768c2ecf20Sopenharmony_ci data_padlen); 10778c2ecf20Sopenharmony_ci 10788c2ecf20Sopenharmony_ci if (data_padlen) 10798c2ecf20Sopenharmony_ci /* have to catch gcm pad in separate buffer */ 10808c2ecf20Sopenharmony_ci rx_frag_num++; 10818c2ecf20Sopenharmony_ci 10828c2ecf20Sopenharmony_ci mssg->spu.dst = kcalloc(rx_frag_num, sizeof(struct scatterlist), 10838c2ecf20Sopenharmony_ci rctx->gfp); 10848c2ecf20Sopenharmony_ci if (!mssg->spu.dst) 10858c2ecf20Sopenharmony_ci return -ENOMEM; 10868c2ecf20Sopenharmony_ci 10878c2ecf20Sopenharmony_ci sg = mssg->spu.dst; 10888c2ecf20Sopenharmony_ci sg_init_table(sg, rx_frag_num); 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_ci /* Space for SPU message header */ 10918c2ecf20Sopenharmony_ci sg_set_buf(sg++, rctx->msg_buf.spu_resp_hdr, ctx->spu_resp_hdr_len); 10928c2ecf20Sopenharmony_ci 10938c2ecf20Sopenharmony_ci if (assoc_buf_len) { 10948c2ecf20Sopenharmony_ci /* 10958c2ecf20Sopenharmony_ci * Don't write directly to req->dst, because SPU may pad the 10968c2ecf20Sopenharmony_ci * assoc data in the response 10978c2ecf20Sopenharmony_ci */ 10988c2ecf20Sopenharmony_ci memset(rctx->msg_buf.a.resp_aad, 0, assoc_buf_len); 10998c2ecf20Sopenharmony_ci sg_set_buf(sg++, rctx->msg_buf.a.resp_aad, assoc_buf_len); 11008c2ecf20Sopenharmony_ci } 11018c2ecf20Sopenharmony_ci 11028c2ecf20Sopenharmony_ci if (resp_len) { 11038c2ecf20Sopenharmony_ci /* 11048c2ecf20Sopenharmony_ci * Copy in each dst sg entry from request, up to chunksize. 11058c2ecf20Sopenharmony_ci * dst sg catches just the data. digest caught in separate buf. 11068c2ecf20Sopenharmony_ci */ 11078c2ecf20Sopenharmony_ci datalen = spu_msg_sg_add(&sg, &rctx->dst_sg, &rctx->dst_skip, 11088c2ecf20Sopenharmony_ci rctx->dst_nents, resp_len); 11098c2ecf20Sopenharmony_ci if (datalen < (resp_len)) { 11108c2ecf20Sopenharmony_ci pr_err("%s(): failed to copy dst sg to mbox msg. expected len %u, datalen %u", 11118c2ecf20Sopenharmony_ci __func__, resp_len, datalen); 11128c2ecf20Sopenharmony_ci return -EFAULT; 11138c2ecf20Sopenharmony_ci } 11148c2ecf20Sopenharmony_ci } 11158c2ecf20Sopenharmony_ci 11168c2ecf20Sopenharmony_ci /* If GCM/CCM data is padded, catch padding in separate buffer */ 11178c2ecf20Sopenharmony_ci if (data_padlen) { 11188c2ecf20Sopenharmony_ci memset(rctx->msg_buf.a.gcmpad, 0, data_padlen); 11198c2ecf20Sopenharmony_ci sg_set_buf(sg++, rctx->msg_buf.a.gcmpad, data_padlen); 11208c2ecf20Sopenharmony_ci } 11218c2ecf20Sopenharmony_ci 11228c2ecf20Sopenharmony_ci /* Always catch ICV in separate buffer */ 11238c2ecf20Sopenharmony_ci sg_set_buf(sg++, rctx->msg_buf.digest, digestsize); 11248c2ecf20Sopenharmony_ci 11258c2ecf20Sopenharmony_ci flow_log("stat_pad_len %u\n", stat_pad_len); 11268c2ecf20Sopenharmony_ci if (stat_pad_len) { 11278c2ecf20Sopenharmony_ci memset(rctx->msg_buf.rx_stat_pad, 0, stat_pad_len); 11288c2ecf20Sopenharmony_ci sg_set_buf(sg++, rctx->msg_buf.rx_stat_pad, stat_pad_len); 11298c2ecf20Sopenharmony_ci } 11308c2ecf20Sopenharmony_ci 11318c2ecf20Sopenharmony_ci memset(rctx->msg_buf.rx_stat, 0, SPU_RX_STATUS_LEN); 11328c2ecf20Sopenharmony_ci sg_set_buf(sg, rctx->msg_buf.rx_stat, spu->spu_rx_status_len()); 11338c2ecf20Sopenharmony_ci 11348c2ecf20Sopenharmony_ci return 0; 11358c2ecf20Sopenharmony_ci} 11368c2ecf20Sopenharmony_ci 11378c2ecf20Sopenharmony_ci/** 11388c2ecf20Sopenharmony_ci * spu_aead_tx_sg_create() - Build up the scatterlist of buffers used to send a 11398c2ecf20Sopenharmony_ci * SPU request message for an AEAD request. Includes SPU message headers and the 11408c2ecf20Sopenharmony_ci * request data. 11418c2ecf20Sopenharmony_ci * @mssg: mailbox message containing the transmit sg 11428c2ecf20Sopenharmony_ci * @rctx: crypto request context 11438c2ecf20Sopenharmony_ci * @tx_frag_num: number of scatterlist elements required to construct the 11448c2ecf20Sopenharmony_ci * SPU request message 11458c2ecf20Sopenharmony_ci * @spu_hdr_len: length of SPU message header in bytes 11468c2ecf20Sopenharmony_ci * @assoc: crypto API associated data scatterlist 11478c2ecf20Sopenharmony_ci * @assoc_len: length of associated data 11488c2ecf20Sopenharmony_ci * @assoc_nents: number of scatterlist entries containing assoc data 11498c2ecf20Sopenharmony_ci * @aead_iv_len: length of AEAD IV, if included 11508c2ecf20Sopenharmony_ci * @chunksize: Number of bytes of request data 11518c2ecf20Sopenharmony_ci * @aad_pad_len: Number of bytes of padding at end of AAD. For GCM/CCM. 11528c2ecf20Sopenharmony_ci * @pad_len: Number of pad bytes 11538c2ecf20Sopenharmony_ci * @incl_icv: If true, write separate ICV buffer after data and 11548c2ecf20Sopenharmony_ci * any padding 11558c2ecf20Sopenharmony_ci * 11568c2ecf20Sopenharmony_ci * The scatterlist that gets allocated here is freed in spu_chunk_cleanup() 11578c2ecf20Sopenharmony_ci * when the request completes, whether the request is handled successfully or 11588c2ecf20Sopenharmony_ci * there is an error. 11598c2ecf20Sopenharmony_ci * 11608c2ecf20Sopenharmony_ci * Return: 11618c2ecf20Sopenharmony_ci * 0 if successful 11628c2ecf20Sopenharmony_ci * < 0 if an error 11638c2ecf20Sopenharmony_ci */ 11648c2ecf20Sopenharmony_cistatic int spu_aead_tx_sg_create(struct brcm_message *mssg, 11658c2ecf20Sopenharmony_ci struct iproc_reqctx_s *rctx, 11668c2ecf20Sopenharmony_ci u8 tx_frag_num, 11678c2ecf20Sopenharmony_ci u32 spu_hdr_len, 11688c2ecf20Sopenharmony_ci struct scatterlist *assoc, 11698c2ecf20Sopenharmony_ci unsigned int assoc_len, 11708c2ecf20Sopenharmony_ci int assoc_nents, 11718c2ecf20Sopenharmony_ci unsigned int aead_iv_len, 11728c2ecf20Sopenharmony_ci unsigned int chunksize, 11738c2ecf20Sopenharmony_ci u32 aad_pad_len, u32 pad_len, bool incl_icv) 11748c2ecf20Sopenharmony_ci{ 11758c2ecf20Sopenharmony_ci struct spu_hw *spu = &iproc_priv.spu; 11768c2ecf20Sopenharmony_ci struct scatterlist *sg; /* used to build sgs in mbox message */ 11778c2ecf20Sopenharmony_ci struct scatterlist *assoc_sg = assoc; 11788c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = rctx->ctx; 11798c2ecf20Sopenharmony_ci u32 datalen; /* Number of bytes of data to write */ 11808c2ecf20Sopenharmony_ci u32 written; /* Number of bytes of data written */ 11818c2ecf20Sopenharmony_ci u32 assoc_offset = 0; 11828c2ecf20Sopenharmony_ci u32 stat_len; 11838c2ecf20Sopenharmony_ci 11848c2ecf20Sopenharmony_ci mssg->spu.src = kcalloc(tx_frag_num, sizeof(struct scatterlist), 11858c2ecf20Sopenharmony_ci rctx->gfp); 11868c2ecf20Sopenharmony_ci if (!mssg->spu.src) 11878c2ecf20Sopenharmony_ci return -ENOMEM; 11888c2ecf20Sopenharmony_ci 11898c2ecf20Sopenharmony_ci sg = mssg->spu.src; 11908c2ecf20Sopenharmony_ci sg_init_table(sg, tx_frag_num); 11918c2ecf20Sopenharmony_ci 11928c2ecf20Sopenharmony_ci sg_set_buf(sg++, rctx->msg_buf.bcm_spu_req_hdr, 11938c2ecf20Sopenharmony_ci BCM_HDR_LEN + spu_hdr_len); 11948c2ecf20Sopenharmony_ci 11958c2ecf20Sopenharmony_ci if (assoc_len) { 11968c2ecf20Sopenharmony_ci /* Copy in each associated data sg entry from request */ 11978c2ecf20Sopenharmony_ci written = spu_msg_sg_add(&sg, &assoc_sg, &assoc_offset, 11988c2ecf20Sopenharmony_ci assoc_nents, assoc_len); 11998c2ecf20Sopenharmony_ci if (written < assoc_len) { 12008c2ecf20Sopenharmony_ci pr_err("%s(): failed to copy assoc sg to mbox msg", 12018c2ecf20Sopenharmony_ci __func__); 12028c2ecf20Sopenharmony_ci return -EFAULT; 12038c2ecf20Sopenharmony_ci } 12048c2ecf20Sopenharmony_ci } 12058c2ecf20Sopenharmony_ci 12068c2ecf20Sopenharmony_ci if (aead_iv_len) 12078c2ecf20Sopenharmony_ci sg_set_buf(sg++, rctx->msg_buf.iv_ctr, aead_iv_len); 12088c2ecf20Sopenharmony_ci 12098c2ecf20Sopenharmony_ci if (aad_pad_len) { 12108c2ecf20Sopenharmony_ci memset(rctx->msg_buf.a.req_aad_pad, 0, aad_pad_len); 12118c2ecf20Sopenharmony_ci sg_set_buf(sg++, rctx->msg_buf.a.req_aad_pad, aad_pad_len); 12128c2ecf20Sopenharmony_ci } 12138c2ecf20Sopenharmony_ci 12148c2ecf20Sopenharmony_ci datalen = chunksize; 12158c2ecf20Sopenharmony_ci if ((chunksize > ctx->digestsize) && incl_icv) 12168c2ecf20Sopenharmony_ci datalen -= ctx->digestsize; 12178c2ecf20Sopenharmony_ci if (datalen) { 12188c2ecf20Sopenharmony_ci /* For aead, a single msg should consume the entire src sg */ 12198c2ecf20Sopenharmony_ci written = spu_msg_sg_add(&sg, &rctx->src_sg, &rctx->src_skip, 12208c2ecf20Sopenharmony_ci rctx->src_nents, datalen); 12218c2ecf20Sopenharmony_ci if (written < datalen) { 12228c2ecf20Sopenharmony_ci pr_err("%s(): failed to copy src sg to mbox msg", 12238c2ecf20Sopenharmony_ci __func__); 12248c2ecf20Sopenharmony_ci return -EFAULT; 12258c2ecf20Sopenharmony_ci } 12268c2ecf20Sopenharmony_ci } 12278c2ecf20Sopenharmony_ci 12288c2ecf20Sopenharmony_ci if (pad_len) { 12298c2ecf20Sopenharmony_ci memset(rctx->msg_buf.spu_req_pad, 0, pad_len); 12308c2ecf20Sopenharmony_ci sg_set_buf(sg++, rctx->msg_buf.spu_req_pad, pad_len); 12318c2ecf20Sopenharmony_ci } 12328c2ecf20Sopenharmony_ci 12338c2ecf20Sopenharmony_ci if (incl_icv) 12348c2ecf20Sopenharmony_ci sg_set_buf(sg++, rctx->msg_buf.digest, ctx->digestsize); 12358c2ecf20Sopenharmony_ci 12368c2ecf20Sopenharmony_ci stat_len = spu->spu_tx_status_len(); 12378c2ecf20Sopenharmony_ci if (stat_len) { 12388c2ecf20Sopenharmony_ci memset(rctx->msg_buf.tx_stat, 0, stat_len); 12398c2ecf20Sopenharmony_ci sg_set_buf(sg, rctx->msg_buf.tx_stat, stat_len); 12408c2ecf20Sopenharmony_ci } 12418c2ecf20Sopenharmony_ci return 0; 12428c2ecf20Sopenharmony_ci} 12438c2ecf20Sopenharmony_ci 12448c2ecf20Sopenharmony_ci/** 12458c2ecf20Sopenharmony_ci * handle_aead_req() - Submit a SPU request message for the next chunk of the 12468c2ecf20Sopenharmony_ci * current AEAD request. 12478c2ecf20Sopenharmony_ci * @rctx: Crypto request context 12488c2ecf20Sopenharmony_ci * 12498c2ecf20Sopenharmony_ci * Unlike other operation types, we assume the length of the request fits in 12508c2ecf20Sopenharmony_ci * a single SPU request message. aead_enqueue() makes sure this is true. 12518c2ecf20Sopenharmony_ci * Comments for other op types regarding threads applies here as well. 12528c2ecf20Sopenharmony_ci * 12538c2ecf20Sopenharmony_ci * Unlike incremental hash ops, where the spu returns the entire hash for 12548c2ecf20Sopenharmony_ci * truncated algs like sha-224, the SPU returns just the truncated hash in 12558c2ecf20Sopenharmony_ci * response to aead requests. So digestsize is always ctx->digestsize here. 12568c2ecf20Sopenharmony_ci * 12578c2ecf20Sopenharmony_ci * Return: -EINPROGRESS: crypto request has been accepted and result will be 12588c2ecf20Sopenharmony_ci * returned asynchronously 12598c2ecf20Sopenharmony_ci * Any other value indicates an error 12608c2ecf20Sopenharmony_ci */ 12618c2ecf20Sopenharmony_cistatic int handle_aead_req(struct iproc_reqctx_s *rctx) 12628c2ecf20Sopenharmony_ci{ 12638c2ecf20Sopenharmony_ci struct spu_hw *spu = &iproc_priv.spu; 12648c2ecf20Sopenharmony_ci struct crypto_async_request *areq = rctx->parent; 12658c2ecf20Sopenharmony_ci struct aead_request *req = container_of(areq, 12668c2ecf20Sopenharmony_ci struct aead_request, base); 12678c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = rctx->ctx; 12688c2ecf20Sopenharmony_ci int err; 12698c2ecf20Sopenharmony_ci unsigned int chunksize; 12708c2ecf20Sopenharmony_ci unsigned int resp_len; 12718c2ecf20Sopenharmony_ci u32 spu_hdr_len; 12728c2ecf20Sopenharmony_ci u32 db_size; 12738c2ecf20Sopenharmony_ci u32 stat_pad_len; 12748c2ecf20Sopenharmony_ci u32 pad_len; 12758c2ecf20Sopenharmony_ci struct brcm_message *mssg; /* mailbox message */ 12768c2ecf20Sopenharmony_ci struct spu_request_opts req_opts; 12778c2ecf20Sopenharmony_ci struct spu_cipher_parms cipher_parms; 12788c2ecf20Sopenharmony_ci struct spu_hash_parms hash_parms; 12798c2ecf20Sopenharmony_ci struct spu_aead_parms aead_parms; 12808c2ecf20Sopenharmony_ci int assoc_nents = 0; 12818c2ecf20Sopenharmony_ci bool incl_icv = false; 12828c2ecf20Sopenharmony_ci unsigned int digestsize = ctx->digestsize; 12838c2ecf20Sopenharmony_ci 12848c2ecf20Sopenharmony_ci /* number of entries in src and dst sg. Always includes SPU msg header. 12858c2ecf20Sopenharmony_ci */ 12868c2ecf20Sopenharmony_ci u8 rx_frag_num = 2; /* and STATUS */ 12878c2ecf20Sopenharmony_ci u8 tx_frag_num = 1; 12888c2ecf20Sopenharmony_ci 12898c2ecf20Sopenharmony_ci /* doing the whole thing at once */ 12908c2ecf20Sopenharmony_ci chunksize = rctx->total_todo; 12918c2ecf20Sopenharmony_ci 12928c2ecf20Sopenharmony_ci flow_log("%s: chunksize %u\n", __func__, chunksize); 12938c2ecf20Sopenharmony_ci 12948c2ecf20Sopenharmony_ci memset(&req_opts, 0, sizeof(req_opts)); 12958c2ecf20Sopenharmony_ci memset(&hash_parms, 0, sizeof(hash_parms)); 12968c2ecf20Sopenharmony_ci memset(&aead_parms, 0, sizeof(aead_parms)); 12978c2ecf20Sopenharmony_ci 12988c2ecf20Sopenharmony_ci req_opts.is_inbound = !(rctx->is_encrypt); 12998c2ecf20Sopenharmony_ci req_opts.auth_first = ctx->auth_first; 13008c2ecf20Sopenharmony_ci req_opts.is_aead = true; 13018c2ecf20Sopenharmony_ci req_opts.is_esp = ctx->is_esp; 13028c2ecf20Sopenharmony_ci 13038c2ecf20Sopenharmony_ci cipher_parms.alg = ctx->cipher.alg; 13048c2ecf20Sopenharmony_ci cipher_parms.mode = ctx->cipher.mode; 13058c2ecf20Sopenharmony_ci cipher_parms.type = ctx->cipher_type; 13068c2ecf20Sopenharmony_ci cipher_parms.key_buf = ctx->enckey; 13078c2ecf20Sopenharmony_ci cipher_parms.key_len = ctx->enckeylen; 13088c2ecf20Sopenharmony_ci cipher_parms.iv_buf = rctx->msg_buf.iv_ctr; 13098c2ecf20Sopenharmony_ci cipher_parms.iv_len = rctx->iv_ctr_len; 13108c2ecf20Sopenharmony_ci 13118c2ecf20Sopenharmony_ci hash_parms.alg = ctx->auth.alg; 13128c2ecf20Sopenharmony_ci hash_parms.mode = ctx->auth.mode; 13138c2ecf20Sopenharmony_ci hash_parms.type = HASH_TYPE_NONE; 13148c2ecf20Sopenharmony_ci hash_parms.key_buf = (u8 *)ctx->authkey; 13158c2ecf20Sopenharmony_ci hash_parms.key_len = ctx->authkeylen; 13168c2ecf20Sopenharmony_ci hash_parms.digestsize = digestsize; 13178c2ecf20Sopenharmony_ci 13188c2ecf20Sopenharmony_ci if ((ctx->auth.alg == HASH_ALG_SHA224) && 13198c2ecf20Sopenharmony_ci (ctx->authkeylen < SHA224_DIGEST_SIZE)) 13208c2ecf20Sopenharmony_ci hash_parms.key_len = SHA224_DIGEST_SIZE; 13218c2ecf20Sopenharmony_ci 13228c2ecf20Sopenharmony_ci aead_parms.assoc_size = req->assoclen; 13238c2ecf20Sopenharmony_ci if (ctx->is_esp && !ctx->is_rfc4543) { 13248c2ecf20Sopenharmony_ci /* 13258c2ecf20Sopenharmony_ci * 8-byte IV is included assoc data in request. SPU2 13268c2ecf20Sopenharmony_ci * expects AAD to include just SPI and seqno. So 13278c2ecf20Sopenharmony_ci * subtract off the IV len. 13288c2ecf20Sopenharmony_ci */ 13298c2ecf20Sopenharmony_ci aead_parms.assoc_size -= GCM_RFC4106_IV_SIZE; 13308c2ecf20Sopenharmony_ci 13318c2ecf20Sopenharmony_ci if (rctx->is_encrypt) { 13328c2ecf20Sopenharmony_ci aead_parms.return_iv = true; 13338c2ecf20Sopenharmony_ci aead_parms.ret_iv_len = GCM_RFC4106_IV_SIZE; 13348c2ecf20Sopenharmony_ci aead_parms.ret_iv_off = GCM_ESP_SALT_SIZE; 13358c2ecf20Sopenharmony_ci } 13368c2ecf20Sopenharmony_ci } else { 13378c2ecf20Sopenharmony_ci aead_parms.ret_iv_len = 0; 13388c2ecf20Sopenharmony_ci } 13398c2ecf20Sopenharmony_ci 13408c2ecf20Sopenharmony_ci /* 13418c2ecf20Sopenharmony_ci * Count number of sg entries from the crypto API request that are to 13428c2ecf20Sopenharmony_ci * be included in this mailbox message. For dst sg, don't count space 13438c2ecf20Sopenharmony_ci * for digest. Digest gets caught in a separate buffer and copied back 13448c2ecf20Sopenharmony_ci * to dst sg when processing response. 13458c2ecf20Sopenharmony_ci */ 13468c2ecf20Sopenharmony_ci rctx->src_nents = spu_sg_count(rctx->src_sg, rctx->src_skip, chunksize); 13478c2ecf20Sopenharmony_ci rctx->dst_nents = spu_sg_count(rctx->dst_sg, rctx->dst_skip, chunksize); 13488c2ecf20Sopenharmony_ci if (aead_parms.assoc_size) 13498c2ecf20Sopenharmony_ci assoc_nents = spu_sg_count(rctx->assoc, 0, 13508c2ecf20Sopenharmony_ci aead_parms.assoc_size); 13518c2ecf20Sopenharmony_ci 13528c2ecf20Sopenharmony_ci mssg = &rctx->mb_mssg; 13538c2ecf20Sopenharmony_ci 13548c2ecf20Sopenharmony_ci rctx->total_sent = chunksize; 13558c2ecf20Sopenharmony_ci rctx->src_sent = chunksize; 13568c2ecf20Sopenharmony_ci if (spu->spu_assoc_resp_len(ctx->cipher.mode, 13578c2ecf20Sopenharmony_ci aead_parms.assoc_size, 13588c2ecf20Sopenharmony_ci aead_parms.ret_iv_len, 13598c2ecf20Sopenharmony_ci rctx->is_encrypt)) 13608c2ecf20Sopenharmony_ci rx_frag_num++; 13618c2ecf20Sopenharmony_ci 13628c2ecf20Sopenharmony_ci aead_parms.iv_len = spu->spu_aead_ivlen(ctx->cipher.mode, 13638c2ecf20Sopenharmony_ci rctx->iv_ctr_len); 13648c2ecf20Sopenharmony_ci 13658c2ecf20Sopenharmony_ci if (ctx->auth.alg == HASH_ALG_AES) 13668c2ecf20Sopenharmony_ci hash_parms.type = (enum hash_type)ctx->cipher_type; 13678c2ecf20Sopenharmony_ci 13688c2ecf20Sopenharmony_ci /* General case AAD padding (CCM and RFC4543 special cases below) */ 13698c2ecf20Sopenharmony_ci aead_parms.aad_pad_len = spu->spu_gcm_ccm_pad_len(ctx->cipher.mode, 13708c2ecf20Sopenharmony_ci aead_parms.assoc_size); 13718c2ecf20Sopenharmony_ci 13728c2ecf20Sopenharmony_ci /* General case data padding (CCM decrypt special case below) */ 13738c2ecf20Sopenharmony_ci aead_parms.data_pad_len = spu->spu_gcm_ccm_pad_len(ctx->cipher.mode, 13748c2ecf20Sopenharmony_ci chunksize); 13758c2ecf20Sopenharmony_ci 13768c2ecf20Sopenharmony_ci if (ctx->cipher.mode == CIPHER_MODE_CCM) { 13778c2ecf20Sopenharmony_ci /* 13788c2ecf20Sopenharmony_ci * for CCM, AAD len + 2 (rather than AAD len) needs to be 13798c2ecf20Sopenharmony_ci * 128-bit aligned 13808c2ecf20Sopenharmony_ci */ 13818c2ecf20Sopenharmony_ci aead_parms.aad_pad_len = spu->spu_gcm_ccm_pad_len( 13828c2ecf20Sopenharmony_ci ctx->cipher.mode, 13838c2ecf20Sopenharmony_ci aead_parms.assoc_size + 2); 13848c2ecf20Sopenharmony_ci 13858c2ecf20Sopenharmony_ci /* 13868c2ecf20Sopenharmony_ci * And when decrypting CCM, need to pad without including 13878c2ecf20Sopenharmony_ci * size of ICV which is tacked on to end of chunk 13888c2ecf20Sopenharmony_ci */ 13898c2ecf20Sopenharmony_ci if (!rctx->is_encrypt) 13908c2ecf20Sopenharmony_ci aead_parms.data_pad_len = 13918c2ecf20Sopenharmony_ci spu->spu_gcm_ccm_pad_len(ctx->cipher.mode, 13928c2ecf20Sopenharmony_ci chunksize - digestsize); 13938c2ecf20Sopenharmony_ci 13948c2ecf20Sopenharmony_ci /* CCM also requires software to rewrite portions of IV: */ 13958c2ecf20Sopenharmony_ci spu->spu_ccm_update_iv(digestsize, &cipher_parms, req->assoclen, 13968c2ecf20Sopenharmony_ci chunksize, rctx->is_encrypt, 13978c2ecf20Sopenharmony_ci ctx->is_esp); 13988c2ecf20Sopenharmony_ci } 13998c2ecf20Sopenharmony_ci 14008c2ecf20Sopenharmony_ci if (ctx->is_rfc4543) { 14018c2ecf20Sopenharmony_ci /* 14028c2ecf20Sopenharmony_ci * RFC4543: data is included in AAD, so don't pad after AAD 14038c2ecf20Sopenharmony_ci * and pad data based on both AAD + data size 14048c2ecf20Sopenharmony_ci */ 14058c2ecf20Sopenharmony_ci aead_parms.aad_pad_len = 0; 14068c2ecf20Sopenharmony_ci if (!rctx->is_encrypt) 14078c2ecf20Sopenharmony_ci aead_parms.data_pad_len = spu->spu_gcm_ccm_pad_len( 14088c2ecf20Sopenharmony_ci ctx->cipher.mode, 14098c2ecf20Sopenharmony_ci aead_parms.assoc_size + chunksize - 14108c2ecf20Sopenharmony_ci digestsize); 14118c2ecf20Sopenharmony_ci else 14128c2ecf20Sopenharmony_ci aead_parms.data_pad_len = spu->spu_gcm_ccm_pad_len( 14138c2ecf20Sopenharmony_ci ctx->cipher.mode, 14148c2ecf20Sopenharmony_ci aead_parms.assoc_size + chunksize); 14158c2ecf20Sopenharmony_ci 14168c2ecf20Sopenharmony_ci req_opts.is_rfc4543 = true; 14178c2ecf20Sopenharmony_ci } 14188c2ecf20Sopenharmony_ci 14198c2ecf20Sopenharmony_ci if (spu_req_incl_icv(ctx->cipher.mode, rctx->is_encrypt)) { 14208c2ecf20Sopenharmony_ci incl_icv = true; 14218c2ecf20Sopenharmony_ci tx_frag_num++; 14228c2ecf20Sopenharmony_ci /* Copy ICV from end of src scatterlist to digest buf */ 14238c2ecf20Sopenharmony_ci sg_copy_part_to_buf(req->src, rctx->msg_buf.digest, digestsize, 14248c2ecf20Sopenharmony_ci req->assoclen + rctx->total_sent - 14258c2ecf20Sopenharmony_ci digestsize); 14268c2ecf20Sopenharmony_ci } 14278c2ecf20Sopenharmony_ci 14288c2ecf20Sopenharmony_ci atomic64_add(chunksize, &iproc_priv.bytes_out); 14298c2ecf20Sopenharmony_ci 14308c2ecf20Sopenharmony_ci flow_log("%s()-sent chunksize:%u\n", __func__, chunksize); 14318c2ecf20Sopenharmony_ci 14328c2ecf20Sopenharmony_ci /* Prepend SPU header with type 3 BCM header */ 14338c2ecf20Sopenharmony_ci memcpy(rctx->msg_buf.bcm_spu_req_hdr, BCMHEADER, BCM_HDR_LEN); 14348c2ecf20Sopenharmony_ci 14358c2ecf20Sopenharmony_ci spu_hdr_len = spu->spu_create_request(rctx->msg_buf.bcm_spu_req_hdr + 14368c2ecf20Sopenharmony_ci BCM_HDR_LEN, &req_opts, 14378c2ecf20Sopenharmony_ci &cipher_parms, &hash_parms, 14388c2ecf20Sopenharmony_ci &aead_parms, chunksize); 14398c2ecf20Sopenharmony_ci 14408c2ecf20Sopenharmony_ci /* Determine total length of padding. Put all padding in one buffer. */ 14418c2ecf20Sopenharmony_ci db_size = spu_real_db_size(aead_parms.assoc_size, aead_parms.iv_len, 0, 14428c2ecf20Sopenharmony_ci chunksize, aead_parms.aad_pad_len, 14438c2ecf20Sopenharmony_ci aead_parms.data_pad_len, 0); 14448c2ecf20Sopenharmony_ci 14458c2ecf20Sopenharmony_ci stat_pad_len = spu->spu_wordalign_padlen(db_size); 14468c2ecf20Sopenharmony_ci 14478c2ecf20Sopenharmony_ci if (stat_pad_len) 14488c2ecf20Sopenharmony_ci rx_frag_num++; 14498c2ecf20Sopenharmony_ci pad_len = aead_parms.data_pad_len + stat_pad_len; 14508c2ecf20Sopenharmony_ci if (pad_len) { 14518c2ecf20Sopenharmony_ci tx_frag_num++; 14528c2ecf20Sopenharmony_ci spu->spu_request_pad(rctx->msg_buf.spu_req_pad, 14538c2ecf20Sopenharmony_ci aead_parms.data_pad_len, 0, 14548c2ecf20Sopenharmony_ci ctx->auth.alg, ctx->auth.mode, 14558c2ecf20Sopenharmony_ci rctx->total_sent, stat_pad_len); 14568c2ecf20Sopenharmony_ci } 14578c2ecf20Sopenharmony_ci 14588c2ecf20Sopenharmony_ci spu->spu_dump_msg_hdr(rctx->msg_buf.bcm_spu_req_hdr + BCM_HDR_LEN, 14598c2ecf20Sopenharmony_ci spu_hdr_len); 14608c2ecf20Sopenharmony_ci dump_sg(rctx->assoc, 0, aead_parms.assoc_size); 14618c2ecf20Sopenharmony_ci packet_dump(" aead iv: ", rctx->msg_buf.iv_ctr, aead_parms.iv_len); 14628c2ecf20Sopenharmony_ci packet_log("BD:\n"); 14638c2ecf20Sopenharmony_ci dump_sg(rctx->src_sg, rctx->src_skip, chunksize); 14648c2ecf20Sopenharmony_ci packet_dump(" pad: ", rctx->msg_buf.spu_req_pad, pad_len); 14658c2ecf20Sopenharmony_ci 14668c2ecf20Sopenharmony_ci /* 14678c2ecf20Sopenharmony_ci * Build mailbox message containing SPU request msg and rx buffers 14688c2ecf20Sopenharmony_ci * to catch response message 14698c2ecf20Sopenharmony_ci */ 14708c2ecf20Sopenharmony_ci memset(mssg, 0, sizeof(*mssg)); 14718c2ecf20Sopenharmony_ci mssg->type = BRCM_MESSAGE_SPU; 14728c2ecf20Sopenharmony_ci mssg->ctx = rctx; /* Will be returned in response */ 14738c2ecf20Sopenharmony_ci 14748c2ecf20Sopenharmony_ci /* Create rx scatterlist to catch result */ 14758c2ecf20Sopenharmony_ci rx_frag_num += rctx->dst_nents; 14768c2ecf20Sopenharmony_ci resp_len = chunksize; 14778c2ecf20Sopenharmony_ci 14788c2ecf20Sopenharmony_ci /* 14798c2ecf20Sopenharmony_ci * Always catch ICV in separate buffer. Have to for GCM/CCM because of 14808c2ecf20Sopenharmony_ci * padding. Have to for SHA-224 and other truncated SHAs because SPU 14818c2ecf20Sopenharmony_ci * sends entire digest back. 14828c2ecf20Sopenharmony_ci */ 14838c2ecf20Sopenharmony_ci rx_frag_num++; 14848c2ecf20Sopenharmony_ci 14858c2ecf20Sopenharmony_ci if (((ctx->cipher.mode == CIPHER_MODE_GCM) || 14868c2ecf20Sopenharmony_ci (ctx->cipher.mode == CIPHER_MODE_CCM)) && !rctx->is_encrypt) { 14878c2ecf20Sopenharmony_ci /* 14888c2ecf20Sopenharmony_ci * Input is ciphertxt plus ICV, but ICV not incl 14898c2ecf20Sopenharmony_ci * in output. 14908c2ecf20Sopenharmony_ci */ 14918c2ecf20Sopenharmony_ci resp_len -= ctx->digestsize; 14928c2ecf20Sopenharmony_ci if (resp_len == 0) 14938c2ecf20Sopenharmony_ci /* no rx frags to catch output data */ 14948c2ecf20Sopenharmony_ci rx_frag_num -= rctx->dst_nents; 14958c2ecf20Sopenharmony_ci } 14968c2ecf20Sopenharmony_ci 14978c2ecf20Sopenharmony_ci err = spu_aead_rx_sg_create(mssg, req, rctx, rx_frag_num, 14988c2ecf20Sopenharmony_ci aead_parms.assoc_size, 14998c2ecf20Sopenharmony_ci aead_parms.ret_iv_len, resp_len, digestsize, 15008c2ecf20Sopenharmony_ci stat_pad_len); 15018c2ecf20Sopenharmony_ci if (err) 15028c2ecf20Sopenharmony_ci return err; 15038c2ecf20Sopenharmony_ci 15048c2ecf20Sopenharmony_ci /* Create tx scatterlist containing SPU request message */ 15058c2ecf20Sopenharmony_ci tx_frag_num += rctx->src_nents; 15068c2ecf20Sopenharmony_ci tx_frag_num += assoc_nents; 15078c2ecf20Sopenharmony_ci if (aead_parms.aad_pad_len) 15088c2ecf20Sopenharmony_ci tx_frag_num++; 15098c2ecf20Sopenharmony_ci if (aead_parms.iv_len) 15108c2ecf20Sopenharmony_ci tx_frag_num++; 15118c2ecf20Sopenharmony_ci if (spu->spu_tx_status_len()) 15128c2ecf20Sopenharmony_ci tx_frag_num++; 15138c2ecf20Sopenharmony_ci err = spu_aead_tx_sg_create(mssg, rctx, tx_frag_num, spu_hdr_len, 15148c2ecf20Sopenharmony_ci rctx->assoc, aead_parms.assoc_size, 15158c2ecf20Sopenharmony_ci assoc_nents, aead_parms.iv_len, chunksize, 15168c2ecf20Sopenharmony_ci aead_parms.aad_pad_len, pad_len, incl_icv); 15178c2ecf20Sopenharmony_ci if (err) 15188c2ecf20Sopenharmony_ci return err; 15198c2ecf20Sopenharmony_ci 15208c2ecf20Sopenharmony_ci err = mailbox_send_message(mssg, req->base.flags, rctx->chan_idx); 15218c2ecf20Sopenharmony_ci if (unlikely(err < 0)) 15228c2ecf20Sopenharmony_ci return err; 15238c2ecf20Sopenharmony_ci 15248c2ecf20Sopenharmony_ci return -EINPROGRESS; 15258c2ecf20Sopenharmony_ci} 15268c2ecf20Sopenharmony_ci 15278c2ecf20Sopenharmony_ci/** 15288c2ecf20Sopenharmony_ci * handle_aead_resp() - Process a SPU response message for an AEAD request. 15298c2ecf20Sopenharmony_ci * @rctx: Crypto request context 15308c2ecf20Sopenharmony_ci */ 15318c2ecf20Sopenharmony_cistatic void handle_aead_resp(struct iproc_reqctx_s *rctx) 15328c2ecf20Sopenharmony_ci{ 15338c2ecf20Sopenharmony_ci struct spu_hw *spu = &iproc_priv.spu; 15348c2ecf20Sopenharmony_ci struct crypto_async_request *areq = rctx->parent; 15358c2ecf20Sopenharmony_ci struct aead_request *req = container_of(areq, 15368c2ecf20Sopenharmony_ci struct aead_request, base); 15378c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = rctx->ctx; 15388c2ecf20Sopenharmony_ci u32 payload_len; 15398c2ecf20Sopenharmony_ci unsigned int icv_offset; 15408c2ecf20Sopenharmony_ci u32 result_len; 15418c2ecf20Sopenharmony_ci 15428c2ecf20Sopenharmony_ci /* See how much data was returned */ 15438c2ecf20Sopenharmony_ci payload_len = spu->spu_payload_length(rctx->msg_buf.spu_resp_hdr); 15448c2ecf20Sopenharmony_ci flow_log("payload_len %u\n", payload_len); 15458c2ecf20Sopenharmony_ci 15468c2ecf20Sopenharmony_ci /* only count payload */ 15478c2ecf20Sopenharmony_ci atomic64_add(payload_len, &iproc_priv.bytes_in); 15488c2ecf20Sopenharmony_ci 15498c2ecf20Sopenharmony_ci if (req->assoclen) 15508c2ecf20Sopenharmony_ci packet_dump(" assoc_data ", rctx->msg_buf.a.resp_aad, 15518c2ecf20Sopenharmony_ci req->assoclen); 15528c2ecf20Sopenharmony_ci 15538c2ecf20Sopenharmony_ci /* 15548c2ecf20Sopenharmony_ci * Copy the ICV back to the destination 15558c2ecf20Sopenharmony_ci * buffer. In decrypt case, SPU gives us back the digest, but crypto 15568c2ecf20Sopenharmony_ci * API doesn't expect ICV in dst buffer. 15578c2ecf20Sopenharmony_ci */ 15588c2ecf20Sopenharmony_ci result_len = req->cryptlen; 15598c2ecf20Sopenharmony_ci if (rctx->is_encrypt) { 15608c2ecf20Sopenharmony_ci icv_offset = req->assoclen + rctx->total_sent; 15618c2ecf20Sopenharmony_ci packet_dump(" ICV: ", rctx->msg_buf.digest, ctx->digestsize); 15628c2ecf20Sopenharmony_ci flow_log("copying ICV to dst sg at offset %u\n", icv_offset); 15638c2ecf20Sopenharmony_ci sg_copy_part_from_buf(req->dst, rctx->msg_buf.digest, 15648c2ecf20Sopenharmony_ci ctx->digestsize, icv_offset); 15658c2ecf20Sopenharmony_ci result_len += ctx->digestsize; 15668c2ecf20Sopenharmony_ci } 15678c2ecf20Sopenharmony_ci 15688c2ecf20Sopenharmony_ci packet_log("response data: "); 15698c2ecf20Sopenharmony_ci dump_sg(req->dst, req->assoclen, result_len); 15708c2ecf20Sopenharmony_ci 15718c2ecf20Sopenharmony_ci atomic_inc(&iproc_priv.op_counts[SPU_OP_AEAD]); 15728c2ecf20Sopenharmony_ci if (ctx->cipher.alg == CIPHER_ALG_AES) { 15738c2ecf20Sopenharmony_ci if (ctx->cipher.mode == CIPHER_MODE_CCM) 15748c2ecf20Sopenharmony_ci atomic_inc(&iproc_priv.aead_cnt[AES_CCM]); 15758c2ecf20Sopenharmony_ci else if (ctx->cipher.mode == CIPHER_MODE_GCM) 15768c2ecf20Sopenharmony_ci atomic_inc(&iproc_priv.aead_cnt[AES_GCM]); 15778c2ecf20Sopenharmony_ci else 15788c2ecf20Sopenharmony_ci atomic_inc(&iproc_priv.aead_cnt[AUTHENC]); 15798c2ecf20Sopenharmony_ci } else { 15808c2ecf20Sopenharmony_ci atomic_inc(&iproc_priv.aead_cnt[AUTHENC]); 15818c2ecf20Sopenharmony_ci } 15828c2ecf20Sopenharmony_ci} 15838c2ecf20Sopenharmony_ci 15848c2ecf20Sopenharmony_ci/** 15858c2ecf20Sopenharmony_ci * spu_chunk_cleanup() - Do cleanup after processing one chunk of a request 15868c2ecf20Sopenharmony_ci * @rctx: request context 15878c2ecf20Sopenharmony_ci * 15888c2ecf20Sopenharmony_ci * Mailbox scatterlists are allocated for each chunk. So free them after 15898c2ecf20Sopenharmony_ci * processing each chunk. 15908c2ecf20Sopenharmony_ci */ 15918c2ecf20Sopenharmony_cistatic void spu_chunk_cleanup(struct iproc_reqctx_s *rctx) 15928c2ecf20Sopenharmony_ci{ 15938c2ecf20Sopenharmony_ci /* mailbox message used to tx request */ 15948c2ecf20Sopenharmony_ci struct brcm_message *mssg = &rctx->mb_mssg; 15958c2ecf20Sopenharmony_ci 15968c2ecf20Sopenharmony_ci kfree(mssg->spu.src); 15978c2ecf20Sopenharmony_ci kfree(mssg->spu.dst); 15988c2ecf20Sopenharmony_ci memset(mssg, 0, sizeof(struct brcm_message)); 15998c2ecf20Sopenharmony_ci} 16008c2ecf20Sopenharmony_ci 16018c2ecf20Sopenharmony_ci/** 16028c2ecf20Sopenharmony_ci * finish_req() - Used to invoke the complete callback from the requester when 16038c2ecf20Sopenharmony_ci * a request has been handled asynchronously. 16048c2ecf20Sopenharmony_ci * @rctx: Request context 16058c2ecf20Sopenharmony_ci * @err: Indicates whether the request was successful or not 16068c2ecf20Sopenharmony_ci * 16078c2ecf20Sopenharmony_ci * Ensures that cleanup has been done for request 16088c2ecf20Sopenharmony_ci */ 16098c2ecf20Sopenharmony_cistatic void finish_req(struct iproc_reqctx_s *rctx, int err) 16108c2ecf20Sopenharmony_ci{ 16118c2ecf20Sopenharmony_ci struct crypto_async_request *areq = rctx->parent; 16128c2ecf20Sopenharmony_ci 16138c2ecf20Sopenharmony_ci flow_log("%s() err:%d\n\n", __func__, err); 16148c2ecf20Sopenharmony_ci 16158c2ecf20Sopenharmony_ci /* No harm done if already called */ 16168c2ecf20Sopenharmony_ci spu_chunk_cleanup(rctx); 16178c2ecf20Sopenharmony_ci 16188c2ecf20Sopenharmony_ci if (areq) 16198c2ecf20Sopenharmony_ci areq->complete(areq, err); 16208c2ecf20Sopenharmony_ci} 16218c2ecf20Sopenharmony_ci 16228c2ecf20Sopenharmony_ci/** 16238c2ecf20Sopenharmony_ci * spu_rx_callback() - Callback from mailbox framework with a SPU response. 16248c2ecf20Sopenharmony_ci * @cl: mailbox client structure for SPU driver 16258c2ecf20Sopenharmony_ci * @msg: mailbox message containing SPU response 16268c2ecf20Sopenharmony_ci */ 16278c2ecf20Sopenharmony_cistatic void spu_rx_callback(struct mbox_client *cl, void *msg) 16288c2ecf20Sopenharmony_ci{ 16298c2ecf20Sopenharmony_ci struct spu_hw *spu = &iproc_priv.spu; 16308c2ecf20Sopenharmony_ci struct brcm_message *mssg = msg; 16318c2ecf20Sopenharmony_ci struct iproc_reqctx_s *rctx; 16328c2ecf20Sopenharmony_ci int err; 16338c2ecf20Sopenharmony_ci 16348c2ecf20Sopenharmony_ci rctx = mssg->ctx; 16358c2ecf20Sopenharmony_ci if (unlikely(!rctx)) { 16368c2ecf20Sopenharmony_ci /* This is fatal */ 16378c2ecf20Sopenharmony_ci pr_err("%s(): no request context", __func__); 16388c2ecf20Sopenharmony_ci err = -EFAULT; 16398c2ecf20Sopenharmony_ci goto cb_finish; 16408c2ecf20Sopenharmony_ci } 16418c2ecf20Sopenharmony_ci 16428c2ecf20Sopenharmony_ci /* process the SPU status */ 16438c2ecf20Sopenharmony_ci err = spu->spu_status_process(rctx->msg_buf.rx_stat); 16448c2ecf20Sopenharmony_ci if (err != 0) { 16458c2ecf20Sopenharmony_ci if (err == SPU_INVALID_ICV) 16468c2ecf20Sopenharmony_ci atomic_inc(&iproc_priv.bad_icv); 16478c2ecf20Sopenharmony_ci err = -EBADMSG; 16488c2ecf20Sopenharmony_ci goto cb_finish; 16498c2ecf20Sopenharmony_ci } 16508c2ecf20Sopenharmony_ci 16518c2ecf20Sopenharmony_ci /* Process the SPU response message */ 16528c2ecf20Sopenharmony_ci switch (rctx->ctx->alg->type) { 16538c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_SKCIPHER: 16548c2ecf20Sopenharmony_ci handle_skcipher_resp(rctx); 16558c2ecf20Sopenharmony_ci break; 16568c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_AHASH: 16578c2ecf20Sopenharmony_ci handle_ahash_resp(rctx); 16588c2ecf20Sopenharmony_ci break; 16598c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_AEAD: 16608c2ecf20Sopenharmony_ci handle_aead_resp(rctx); 16618c2ecf20Sopenharmony_ci break; 16628c2ecf20Sopenharmony_ci default: 16638c2ecf20Sopenharmony_ci err = -EINVAL; 16648c2ecf20Sopenharmony_ci goto cb_finish; 16658c2ecf20Sopenharmony_ci } 16668c2ecf20Sopenharmony_ci 16678c2ecf20Sopenharmony_ci /* 16688c2ecf20Sopenharmony_ci * If this response does not complete the request, then send the next 16698c2ecf20Sopenharmony_ci * request chunk. 16708c2ecf20Sopenharmony_ci */ 16718c2ecf20Sopenharmony_ci if (rctx->total_sent < rctx->total_todo) { 16728c2ecf20Sopenharmony_ci /* Deallocate anything specific to previous chunk */ 16738c2ecf20Sopenharmony_ci spu_chunk_cleanup(rctx); 16748c2ecf20Sopenharmony_ci 16758c2ecf20Sopenharmony_ci switch (rctx->ctx->alg->type) { 16768c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_SKCIPHER: 16778c2ecf20Sopenharmony_ci err = handle_skcipher_req(rctx); 16788c2ecf20Sopenharmony_ci break; 16798c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_AHASH: 16808c2ecf20Sopenharmony_ci err = handle_ahash_req(rctx); 16818c2ecf20Sopenharmony_ci if (err == -EAGAIN) 16828c2ecf20Sopenharmony_ci /* 16838c2ecf20Sopenharmony_ci * we saved data in hash carry, but tell crypto 16848c2ecf20Sopenharmony_ci * API we successfully completed request. 16858c2ecf20Sopenharmony_ci */ 16868c2ecf20Sopenharmony_ci err = 0; 16878c2ecf20Sopenharmony_ci break; 16888c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_AEAD: 16898c2ecf20Sopenharmony_ci err = handle_aead_req(rctx); 16908c2ecf20Sopenharmony_ci break; 16918c2ecf20Sopenharmony_ci default: 16928c2ecf20Sopenharmony_ci err = -EINVAL; 16938c2ecf20Sopenharmony_ci } 16948c2ecf20Sopenharmony_ci 16958c2ecf20Sopenharmony_ci if (err == -EINPROGRESS) 16968c2ecf20Sopenharmony_ci /* Successfully submitted request for next chunk */ 16978c2ecf20Sopenharmony_ci return; 16988c2ecf20Sopenharmony_ci } 16998c2ecf20Sopenharmony_ci 17008c2ecf20Sopenharmony_cicb_finish: 17018c2ecf20Sopenharmony_ci finish_req(rctx, err); 17028c2ecf20Sopenharmony_ci} 17038c2ecf20Sopenharmony_ci 17048c2ecf20Sopenharmony_ci/* ==================== Kernel Cryptographic API ==================== */ 17058c2ecf20Sopenharmony_ci 17068c2ecf20Sopenharmony_ci/** 17078c2ecf20Sopenharmony_ci * skcipher_enqueue() - Handle skcipher encrypt or decrypt request. 17088c2ecf20Sopenharmony_ci * @req: Crypto API request 17098c2ecf20Sopenharmony_ci * @encrypt: true if encrypting; false if decrypting 17108c2ecf20Sopenharmony_ci * 17118c2ecf20Sopenharmony_ci * Return: -EINPROGRESS if request accepted and result will be returned 17128c2ecf20Sopenharmony_ci * asynchronously 17138c2ecf20Sopenharmony_ci * < 0 if an error 17148c2ecf20Sopenharmony_ci */ 17158c2ecf20Sopenharmony_cistatic int skcipher_enqueue(struct skcipher_request *req, bool encrypt) 17168c2ecf20Sopenharmony_ci{ 17178c2ecf20Sopenharmony_ci struct iproc_reqctx_s *rctx = skcipher_request_ctx(req); 17188c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = 17198c2ecf20Sopenharmony_ci crypto_skcipher_ctx(crypto_skcipher_reqtfm(req)); 17208c2ecf20Sopenharmony_ci int err; 17218c2ecf20Sopenharmony_ci 17228c2ecf20Sopenharmony_ci flow_log("%s() enc:%u\n", __func__, encrypt); 17238c2ecf20Sopenharmony_ci 17248c2ecf20Sopenharmony_ci rctx->gfp = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG | 17258c2ecf20Sopenharmony_ci CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC; 17268c2ecf20Sopenharmony_ci rctx->parent = &req->base; 17278c2ecf20Sopenharmony_ci rctx->is_encrypt = encrypt; 17288c2ecf20Sopenharmony_ci rctx->bd_suppress = false; 17298c2ecf20Sopenharmony_ci rctx->total_todo = req->cryptlen; 17308c2ecf20Sopenharmony_ci rctx->src_sent = 0; 17318c2ecf20Sopenharmony_ci rctx->total_sent = 0; 17328c2ecf20Sopenharmony_ci rctx->total_received = 0; 17338c2ecf20Sopenharmony_ci rctx->ctx = ctx; 17348c2ecf20Sopenharmony_ci 17358c2ecf20Sopenharmony_ci /* Initialize current position in src and dst scatterlists */ 17368c2ecf20Sopenharmony_ci rctx->src_sg = req->src; 17378c2ecf20Sopenharmony_ci rctx->src_nents = 0; 17388c2ecf20Sopenharmony_ci rctx->src_skip = 0; 17398c2ecf20Sopenharmony_ci rctx->dst_sg = req->dst; 17408c2ecf20Sopenharmony_ci rctx->dst_nents = 0; 17418c2ecf20Sopenharmony_ci rctx->dst_skip = 0; 17428c2ecf20Sopenharmony_ci 17438c2ecf20Sopenharmony_ci if (ctx->cipher.mode == CIPHER_MODE_CBC || 17448c2ecf20Sopenharmony_ci ctx->cipher.mode == CIPHER_MODE_CTR || 17458c2ecf20Sopenharmony_ci ctx->cipher.mode == CIPHER_MODE_OFB || 17468c2ecf20Sopenharmony_ci ctx->cipher.mode == CIPHER_MODE_XTS || 17478c2ecf20Sopenharmony_ci ctx->cipher.mode == CIPHER_MODE_GCM || 17488c2ecf20Sopenharmony_ci ctx->cipher.mode == CIPHER_MODE_CCM) { 17498c2ecf20Sopenharmony_ci rctx->iv_ctr_len = 17508c2ecf20Sopenharmony_ci crypto_skcipher_ivsize(crypto_skcipher_reqtfm(req)); 17518c2ecf20Sopenharmony_ci memcpy(rctx->msg_buf.iv_ctr, req->iv, rctx->iv_ctr_len); 17528c2ecf20Sopenharmony_ci } else { 17538c2ecf20Sopenharmony_ci rctx->iv_ctr_len = 0; 17548c2ecf20Sopenharmony_ci } 17558c2ecf20Sopenharmony_ci 17568c2ecf20Sopenharmony_ci /* Choose a SPU to process this request */ 17578c2ecf20Sopenharmony_ci rctx->chan_idx = select_channel(); 17588c2ecf20Sopenharmony_ci err = handle_skcipher_req(rctx); 17598c2ecf20Sopenharmony_ci if (err != -EINPROGRESS) 17608c2ecf20Sopenharmony_ci /* synchronous result */ 17618c2ecf20Sopenharmony_ci spu_chunk_cleanup(rctx); 17628c2ecf20Sopenharmony_ci 17638c2ecf20Sopenharmony_ci return err; 17648c2ecf20Sopenharmony_ci} 17658c2ecf20Sopenharmony_ci 17668c2ecf20Sopenharmony_cistatic int des_setkey(struct crypto_skcipher *cipher, const u8 *key, 17678c2ecf20Sopenharmony_ci unsigned int keylen) 17688c2ecf20Sopenharmony_ci{ 17698c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = crypto_skcipher_ctx(cipher); 17708c2ecf20Sopenharmony_ci int err; 17718c2ecf20Sopenharmony_ci 17728c2ecf20Sopenharmony_ci err = verify_skcipher_des_key(cipher, key); 17738c2ecf20Sopenharmony_ci if (err) 17748c2ecf20Sopenharmony_ci return err; 17758c2ecf20Sopenharmony_ci 17768c2ecf20Sopenharmony_ci ctx->cipher_type = CIPHER_TYPE_DES; 17778c2ecf20Sopenharmony_ci return 0; 17788c2ecf20Sopenharmony_ci} 17798c2ecf20Sopenharmony_ci 17808c2ecf20Sopenharmony_cistatic int threedes_setkey(struct crypto_skcipher *cipher, const u8 *key, 17818c2ecf20Sopenharmony_ci unsigned int keylen) 17828c2ecf20Sopenharmony_ci{ 17838c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = crypto_skcipher_ctx(cipher); 17848c2ecf20Sopenharmony_ci int err; 17858c2ecf20Sopenharmony_ci 17868c2ecf20Sopenharmony_ci err = verify_skcipher_des3_key(cipher, key); 17878c2ecf20Sopenharmony_ci if (err) 17888c2ecf20Sopenharmony_ci return err; 17898c2ecf20Sopenharmony_ci 17908c2ecf20Sopenharmony_ci ctx->cipher_type = CIPHER_TYPE_3DES; 17918c2ecf20Sopenharmony_ci return 0; 17928c2ecf20Sopenharmony_ci} 17938c2ecf20Sopenharmony_ci 17948c2ecf20Sopenharmony_cistatic int aes_setkey(struct crypto_skcipher *cipher, const u8 *key, 17958c2ecf20Sopenharmony_ci unsigned int keylen) 17968c2ecf20Sopenharmony_ci{ 17978c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = crypto_skcipher_ctx(cipher); 17988c2ecf20Sopenharmony_ci 17998c2ecf20Sopenharmony_ci if (ctx->cipher.mode == CIPHER_MODE_XTS) 18008c2ecf20Sopenharmony_ci /* XTS includes two keys of equal length */ 18018c2ecf20Sopenharmony_ci keylen = keylen / 2; 18028c2ecf20Sopenharmony_ci 18038c2ecf20Sopenharmony_ci switch (keylen) { 18048c2ecf20Sopenharmony_ci case AES_KEYSIZE_128: 18058c2ecf20Sopenharmony_ci ctx->cipher_type = CIPHER_TYPE_AES128; 18068c2ecf20Sopenharmony_ci break; 18078c2ecf20Sopenharmony_ci case AES_KEYSIZE_192: 18088c2ecf20Sopenharmony_ci ctx->cipher_type = CIPHER_TYPE_AES192; 18098c2ecf20Sopenharmony_ci break; 18108c2ecf20Sopenharmony_ci case AES_KEYSIZE_256: 18118c2ecf20Sopenharmony_ci ctx->cipher_type = CIPHER_TYPE_AES256; 18128c2ecf20Sopenharmony_ci break; 18138c2ecf20Sopenharmony_ci default: 18148c2ecf20Sopenharmony_ci return -EINVAL; 18158c2ecf20Sopenharmony_ci } 18168c2ecf20Sopenharmony_ci WARN_ON((ctx->max_payload != SPU_MAX_PAYLOAD_INF) && 18178c2ecf20Sopenharmony_ci ((ctx->max_payload % AES_BLOCK_SIZE) != 0)); 18188c2ecf20Sopenharmony_ci return 0; 18198c2ecf20Sopenharmony_ci} 18208c2ecf20Sopenharmony_ci 18218c2ecf20Sopenharmony_cistatic int skcipher_setkey(struct crypto_skcipher *cipher, const u8 *key, 18228c2ecf20Sopenharmony_ci unsigned int keylen) 18238c2ecf20Sopenharmony_ci{ 18248c2ecf20Sopenharmony_ci struct spu_hw *spu = &iproc_priv.spu; 18258c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = crypto_skcipher_ctx(cipher); 18268c2ecf20Sopenharmony_ci struct spu_cipher_parms cipher_parms; 18278c2ecf20Sopenharmony_ci u32 alloc_len = 0; 18288c2ecf20Sopenharmony_ci int err; 18298c2ecf20Sopenharmony_ci 18308c2ecf20Sopenharmony_ci flow_log("skcipher_setkey() keylen: %d\n", keylen); 18318c2ecf20Sopenharmony_ci flow_dump(" key: ", key, keylen); 18328c2ecf20Sopenharmony_ci 18338c2ecf20Sopenharmony_ci switch (ctx->cipher.alg) { 18348c2ecf20Sopenharmony_ci case CIPHER_ALG_DES: 18358c2ecf20Sopenharmony_ci err = des_setkey(cipher, key, keylen); 18368c2ecf20Sopenharmony_ci break; 18378c2ecf20Sopenharmony_ci case CIPHER_ALG_3DES: 18388c2ecf20Sopenharmony_ci err = threedes_setkey(cipher, key, keylen); 18398c2ecf20Sopenharmony_ci break; 18408c2ecf20Sopenharmony_ci case CIPHER_ALG_AES: 18418c2ecf20Sopenharmony_ci err = aes_setkey(cipher, key, keylen); 18428c2ecf20Sopenharmony_ci break; 18438c2ecf20Sopenharmony_ci default: 18448c2ecf20Sopenharmony_ci pr_err("%s() Error: unknown cipher alg\n", __func__); 18458c2ecf20Sopenharmony_ci err = -EINVAL; 18468c2ecf20Sopenharmony_ci } 18478c2ecf20Sopenharmony_ci if (err) 18488c2ecf20Sopenharmony_ci return err; 18498c2ecf20Sopenharmony_ci 18508c2ecf20Sopenharmony_ci memcpy(ctx->enckey, key, keylen); 18518c2ecf20Sopenharmony_ci ctx->enckeylen = keylen; 18528c2ecf20Sopenharmony_ci 18538c2ecf20Sopenharmony_ci /* SPU needs XTS keys in the reverse order the crypto API presents */ 18548c2ecf20Sopenharmony_ci if ((ctx->cipher.alg == CIPHER_ALG_AES) && 18558c2ecf20Sopenharmony_ci (ctx->cipher.mode == CIPHER_MODE_XTS)) { 18568c2ecf20Sopenharmony_ci unsigned int xts_keylen = keylen / 2; 18578c2ecf20Sopenharmony_ci 18588c2ecf20Sopenharmony_ci memcpy(ctx->enckey, key + xts_keylen, xts_keylen); 18598c2ecf20Sopenharmony_ci memcpy(ctx->enckey + xts_keylen, key, xts_keylen); 18608c2ecf20Sopenharmony_ci } 18618c2ecf20Sopenharmony_ci 18628c2ecf20Sopenharmony_ci if (spu->spu_type == SPU_TYPE_SPUM) 18638c2ecf20Sopenharmony_ci alloc_len = BCM_HDR_LEN + SPU_HEADER_ALLOC_LEN; 18648c2ecf20Sopenharmony_ci else if (spu->spu_type == SPU_TYPE_SPU2) 18658c2ecf20Sopenharmony_ci alloc_len = BCM_HDR_LEN + SPU2_HEADER_ALLOC_LEN; 18668c2ecf20Sopenharmony_ci memset(ctx->bcm_spu_req_hdr, 0, alloc_len); 18678c2ecf20Sopenharmony_ci cipher_parms.iv_buf = NULL; 18688c2ecf20Sopenharmony_ci cipher_parms.iv_len = crypto_skcipher_ivsize(cipher); 18698c2ecf20Sopenharmony_ci flow_log("%s: iv_len %u\n", __func__, cipher_parms.iv_len); 18708c2ecf20Sopenharmony_ci 18718c2ecf20Sopenharmony_ci cipher_parms.alg = ctx->cipher.alg; 18728c2ecf20Sopenharmony_ci cipher_parms.mode = ctx->cipher.mode; 18738c2ecf20Sopenharmony_ci cipher_parms.type = ctx->cipher_type; 18748c2ecf20Sopenharmony_ci cipher_parms.key_buf = ctx->enckey; 18758c2ecf20Sopenharmony_ci cipher_parms.key_len = ctx->enckeylen; 18768c2ecf20Sopenharmony_ci 18778c2ecf20Sopenharmony_ci /* Prepend SPU request message with BCM header */ 18788c2ecf20Sopenharmony_ci memcpy(ctx->bcm_spu_req_hdr, BCMHEADER, BCM_HDR_LEN); 18798c2ecf20Sopenharmony_ci ctx->spu_req_hdr_len = 18808c2ecf20Sopenharmony_ci spu->spu_cipher_req_init(ctx->bcm_spu_req_hdr + BCM_HDR_LEN, 18818c2ecf20Sopenharmony_ci &cipher_parms); 18828c2ecf20Sopenharmony_ci 18838c2ecf20Sopenharmony_ci ctx->spu_resp_hdr_len = spu->spu_response_hdr_len(ctx->authkeylen, 18848c2ecf20Sopenharmony_ci ctx->enckeylen, 18858c2ecf20Sopenharmony_ci false); 18868c2ecf20Sopenharmony_ci 18878c2ecf20Sopenharmony_ci atomic_inc(&iproc_priv.setkey_cnt[SPU_OP_CIPHER]); 18888c2ecf20Sopenharmony_ci 18898c2ecf20Sopenharmony_ci return 0; 18908c2ecf20Sopenharmony_ci} 18918c2ecf20Sopenharmony_ci 18928c2ecf20Sopenharmony_cistatic int skcipher_encrypt(struct skcipher_request *req) 18938c2ecf20Sopenharmony_ci{ 18948c2ecf20Sopenharmony_ci flow_log("skcipher_encrypt() nbytes:%u\n", req->cryptlen); 18958c2ecf20Sopenharmony_ci 18968c2ecf20Sopenharmony_ci return skcipher_enqueue(req, true); 18978c2ecf20Sopenharmony_ci} 18988c2ecf20Sopenharmony_ci 18998c2ecf20Sopenharmony_cistatic int skcipher_decrypt(struct skcipher_request *req) 19008c2ecf20Sopenharmony_ci{ 19018c2ecf20Sopenharmony_ci flow_log("skcipher_decrypt() nbytes:%u\n", req->cryptlen); 19028c2ecf20Sopenharmony_ci return skcipher_enqueue(req, false); 19038c2ecf20Sopenharmony_ci} 19048c2ecf20Sopenharmony_ci 19058c2ecf20Sopenharmony_cistatic int ahash_enqueue(struct ahash_request *req) 19068c2ecf20Sopenharmony_ci{ 19078c2ecf20Sopenharmony_ci struct iproc_reqctx_s *rctx = ahash_request_ctx(req); 19088c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 19098c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = crypto_ahash_ctx(tfm); 19108c2ecf20Sopenharmony_ci int err; 19118c2ecf20Sopenharmony_ci const char *alg_name; 19128c2ecf20Sopenharmony_ci 19138c2ecf20Sopenharmony_ci flow_log("ahash_enqueue() nbytes:%u\n", req->nbytes); 19148c2ecf20Sopenharmony_ci 19158c2ecf20Sopenharmony_ci rctx->gfp = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG | 19168c2ecf20Sopenharmony_ci CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC; 19178c2ecf20Sopenharmony_ci rctx->parent = &req->base; 19188c2ecf20Sopenharmony_ci rctx->ctx = ctx; 19198c2ecf20Sopenharmony_ci rctx->bd_suppress = true; 19208c2ecf20Sopenharmony_ci memset(&rctx->mb_mssg, 0, sizeof(struct brcm_message)); 19218c2ecf20Sopenharmony_ci 19228c2ecf20Sopenharmony_ci /* Initialize position in src scatterlist */ 19238c2ecf20Sopenharmony_ci rctx->src_sg = req->src; 19248c2ecf20Sopenharmony_ci rctx->src_skip = 0; 19258c2ecf20Sopenharmony_ci rctx->src_nents = 0; 19268c2ecf20Sopenharmony_ci rctx->dst_sg = NULL; 19278c2ecf20Sopenharmony_ci rctx->dst_skip = 0; 19288c2ecf20Sopenharmony_ci rctx->dst_nents = 0; 19298c2ecf20Sopenharmony_ci 19308c2ecf20Sopenharmony_ci /* SPU2 hardware does not compute hash of zero length data */ 19318c2ecf20Sopenharmony_ci if ((rctx->is_final == 1) && (rctx->total_todo == 0) && 19328c2ecf20Sopenharmony_ci (iproc_priv.spu.spu_type == SPU_TYPE_SPU2)) { 19338c2ecf20Sopenharmony_ci alg_name = crypto_tfm_alg_name(crypto_ahash_tfm(tfm)); 19348c2ecf20Sopenharmony_ci flow_log("Doing %sfinal %s zero-len hash request in software\n", 19358c2ecf20Sopenharmony_ci rctx->is_final ? "" : "non-", alg_name); 19368c2ecf20Sopenharmony_ci err = do_shash((unsigned char *)alg_name, req->result, 19378c2ecf20Sopenharmony_ci NULL, 0, NULL, 0, ctx->authkey, 19388c2ecf20Sopenharmony_ci ctx->authkeylen); 19398c2ecf20Sopenharmony_ci if (err < 0) 19408c2ecf20Sopenharmony_ci flow_log("Hash request failed with error %d\n", err); 19418c2ecf20Sopenharmony_ci return err; 19428c2ecf20Sopenharmony_ci } 19438c2ecf20Sopenharmony_ci /* Choose a SPU to process this request */ 19448c2ecf20Sopenharmony_ci rctx->chan_idx = select_channel(); 19458c2ecf20Sopenharmony_ci 19468c2ecf20Sopenharmony_ci err = handle_ahash_req(rctx); 19478c2ecf20Sopenharmony_ci if (err != -EINPROGRESS) 19488c2ecf20Sopenharmony_ci /* synchronous result */ 19498c2ecf20Sopenharmony_ci spu_chunk_cleanup(rctx); 19508c2ecf20Sopenharmony_ci 19518c2ecf20Sopenharmony_ci if (err == -EAGAIN) 19528c2ecf20Sopenharmony_ci /* 19538c2ecf20Sopenharmony_ci * we saved data in hash carry, but tell crypto API 19548c2ecf20Sopenharmony_ci * we successfully completed request. 19558c2ecf20Sopenharmony_ci */ 19568c2ecf20Sopenharmony_ci err = 0; 19578c2ecf20Sopenharmony_ci 19588c2ecf20Sopenharmony_ci return err; 19598c2ecf20Sopenharmony_ci} 19608c2ecf20Sopenharmony_ci 19618c2ecf20Sopenharmony_cistatic int __ahash_init(struct ahash_request *req) 19628c2ecf20Sopenharmony_ci{ 19638c2ecf20Sopenharmony_ci struct spu_hw *spu = &iproc_priv.spu; 19648c2ecf20Sopenharmony_ci struct iproc_reqctx_s *rctx = ahash_request_ctx(req); 19658c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 19668c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = crypto_ahash_ctx(tfm); 19678c2ecf20Sopenharmony_ci 19688c2ecf20Sopenharmony_ci flow_log("%s()\n", __func__); 19698c2ecf20Sopenharmony_ci 19708c2ecf20Sopenharmony_ci /* Initialize the context */ 19718c2ecf20Sopenharmony_ci rctx->hash_carry_len = 0; 19728c2ecf20Sopenharmony_ci rctx->is_final = 0; 19738c2ecf20Sopenharmony_ci 19748c2ecf20Sopenharmony_ci rctx->total_todo = 0; 19758c2ecf20Sopenharmony_ci rctx->src_sent = 0; 19768c2ecf20Sopenharmony_ci rctx->total_sent = 0; 19778c2ecf20Sopenharmony_ci rctx->total_received = 0; 19788c2ecf20Sopenharmony_ci 19798c2ecf20Sopenharmony_ci ctx->digestsize = crypto_ahash_digestsize(tfm); 19808c2ecf20Sopenharmony_ci /* If we add a hash whose digest is larger, catch it here. */ 19818c2ecf20Sopenharmony_ci WARN_ON(ctx->digestsize > MAX_DIGEST_SIZE); 19828c2ecf20Sopenharmony_ci 19838c2ecf20Sopenharmony_ci rctx->is_sw_hmac = false; 19848c2ecf20Sopenharmony_ci 19858c2ecf20Sopenharmony_ci ctx->spu_resp_hdr_len = spu->spu_response_hdr_len(ctx->authkeylen, 0, 19868c2ecf20Sopenharmony_ci true); 19878c2ecf20Sopenharmony_ci 19888c2ecf20Sopenharmony_ci return 0; 19898c2ecf20Sopenharmony_ci} 19908c2ecf20Sopenharmony_ci 19918c2ecf20Sopenharmony_ci/** 19928c2ecf20Sopenharmony_ci * spu_no_incr_hash() - Determine whether incremental hashing is supported. 19938c2ecf20Sopenharmony_ci * @ctx: Crypto session context 19948c2ecf20Sopenharmony_ci * 19958c2ecf20Sopenharmony_ci * SPU-2 does not support incremental hashing (we'll have to revisit and 19968c2ecf20Sopenharmony_ci * condition based on chip revision or device tree entry if future versions do 19978c2ecf20Sopenharmony_ci * support incremental hash) 19988c2ecf20Sopenharmony_ci * 19998c2ecf20Sopenharmony_ci * SPU-M also doesn't support incremental hashing of AES-XCBC 20008c2ecf20Sopenharmony_ci * 20018c2ecf20Sopenharmony_ci * Return: true if incremental hashing is not supported 20028c2ecf20Sopenharmony_ci * false otherwise 20038c2ecf20Sopenharmony_ci */ 20048c2ecf20Sopenharmony_cistatic bool spu_no_incr_hash(struct iproc_ctx_s *ctx) 20058c2ecf20Sopenharmony_ci{ 20068c2ecf20Sopenharmony_ci struct spu_hw *spu = &iproc_priv.spu; 20078c2ecf20Sopenharmony_ci 20088c2ecf20Sopenharmony_ci if (spu->spu_type == SPU_TYPE_SPU2) 20098c2ecf20Sopenharmony_ci return true; 20108c2ecf20Sopenharmony_ci 20118c2ecf20Sopenharmony_ci if ((ctx->auth.alg == HASH_ALG_AES) && 20128c2ecf20Sopenharmony_ci (ctx->auth.mode == HASH_MODE_XCBC)) 20138c2ecf20Sopenharmony_ci return true; 20148c2ecf20Sopenharmony_ci 20158c2ecf20Sopenharmony_ci /* Otherwise, incremental hashing is supported */ 20168c2ecf20Sopenharmony_ci return false; 20178c2ecf20Sopenharmony_ci} 20188c2ecf20Sopenharmony_ci 20198c2ecf20Sopenharmony_cistatic int ahash_init(struct ahash_request *req) 20208c2ecf20Sopenharmony_ci{ 20218c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 20228c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = crypto_ahash_ctx(tfm); 20238c2ecf20Sopenharmony_ci const char *alg_name; 20248c2ecf20Sopenharmony_ci struct crypto_shash *hash; 20258c2ecf20Sopenharmony_ci int ret; 20268c2ecf20Sopenharmony_ci gfp_t gfp; 20278c2ecf20Sopenharmony_ci 20288c2ecf20Sopenharmony_ci if (spu_no_incr_hash(ctx)) { 20298c2ecf20Sopenharmony_ci /* 20308c2ecf20Sopenharmony_ci * If we get an incremental hashing request and it's not 20318c2ecf20Sopenharmony_ci * supported by the hardware, we need to handle it in software 20328c2ecf20Sopenharmony_ci * by calling synchronous hash functions. 20338c2ecf20Sopenharmony_ci */ 20348c2ecf20Sopenharmony_ci alg_name = crypto_tfm_alg_name(crypto_ahash_tfm(tfm)); 20358c2ecf20Sopenharmony_ci hash = crypto_alloc_shash(alg_name, 0, 0); 20368c2ecf20Sopenharmony_ci if (IS_ERR(hash)) { 20378c2ecf20Sopenharmony_ci ret = PTR_ERR(hash); 20388c2ecf20Sopenharmony_ci goto err; 20398c2ecf20Sopenharmony_ci } 20408c2ecf20Sopenharmony_ci 20418c2ecf20Sopenharmony_ci gfp = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG | 20428c2ecf20Sopenharmony_ci CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC; 20438c2ecf20Sopenharmony_ci ctx->shash = kmalloc(sizeof(*ctx->shash) + 20448c2ecf20Sopenharmony_ci crypto_shash_descsize(hash), gfp); 20458c2ecf20Sopenharmony_ci if (!ctx->shash) { 20468c2ecf20Sopenharmony_ci ret = -ENOMEM; 20478c2ecf20Sopenharmony_ci goto err_hash; 20488c2ecf20Sopenharmony_ci } 20498c2ecf20Sopenharmony_ci ctx->shash->tfm = hash; 20508c2ecf20Sopenharmony_ci 20518c2ecf20Sopenharmony_ci /* Set the key using data we already have from setkey */ 20528c2ecf20Sopenharmony_ci if (ctx->authkeylen > 0) { 20538c2ecf20Sopenharmony_ci ret = crypto_shash_setkey(hash, ctx->authkey, 20548c2ecf20Sopenharmony_ci ctx->authkeylen); 20558c2ecf20Sopenharmony_ci if (ret) 20568c2ecf20Sopenharmony_ci goto err_shash; 20578c2ecf20Sopenharmony_ci } 20588c2ecf20Sopenharmony_ci 20598c2ecf20Sopenharmony_ci /* Initialize hash w/ this key and other params */ 20608c2ecf20Sopenharmony_ci ret = crypto_shash_init(ctx->shash); 20618c2ecf20Sopenharmony_ci if (ret) 20628c2ecf20Sopenharmony_ci goto err_shash; 20638c2ecf20Sopenharmony_ci } else { 20648c2ecf20Sopenharmony_ci /* Otherwise call the internal function which uses SPU hw */ 20658c2ecf20Sopenharmony_ci ret = __ahash_init(req); 20668c2ecf20Sopenharmony_ci } 20678c2ecf20Sopenharmony_ci 20688c2ecf20Sopenharmony_ci return ret; 20698c2ecf20Sopenharmony_ci 20708c2ecf20Sopenharmony_cierr_shash: 20718c2ecf20Sopenharmony_ci kfree(ctx->shash); 20728c2ecf20Sopenharmony_cierr_hash: 20738c2ecf20Sopenharmony_ci crypto_free_shash(hash); 20748c2ecf20Sopenharmony_cierr: 20758c2ecf20Sopenharmony_ci return ret; 20768c2ecf20Sopenharmony_ci} 20778c2ecf20Sopenharmony_ci 20788c2ecf20Sopenharmony_cistatic int __ahash_update(struct ahash_request *req) 20798c2ecf20Sopenharmony_ci{ 20808c2ecf20Sopenharmony_ci struct iproc_reqctx_s *rctx = ahash_request_ctx(req); 20818c2ecf20Sopenharmony_ci 20828c2ecf20Sopenharmony_ci flow_log("ahash_update() nbytes:%u\n", req->nbytes); 20838c2ecf20Sopenharmony_ci 20848c2ecf20Sopenharmony_ci if (!req->nbytes) 20858c2ecf20Sopenharmony_ci return 0; 20868c2ecf20Sopenharmony_ci rctx->total_todo += req->nbytes; 20878c2ecf20Sopenharmony_ci rctx->src_sent = 0; 20888c2ecf20Sopenharmony_ci 20898c2ecf20Sopenharmony_ci return ahash_enqueue(req); 20908c2ecf20Sopenharmony_ci} 20918c2ecf20Sopenharmony_ci 20928c2ecf20Sopenharmony_cistatic int ahash_update(struct ahash_request *req) 20938c2ecf20Sopenharmony_ci{ 20948c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 20958c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = crypto_ahash_ctx(tfm); 20968c2ecf20Sopenharmony_ci u8 *tmpbuf; 20978c2ecf20Sopenharmony_ci int ret; 20988c2ecf20Sopenharmony_ci int nents; 20998c2ecf20Sopenharmony_ci gfp_t gfp; 21008c2ecf20Sopenharmony_ci 21018c2ecf20Sopenharmony_ci if (spu_no_incr_hash(ctx)) { 21028c2ecf20Sopenharmony_ci /* 21038c2ecf20Sopenharmony_ci * If we get an incremental hashing request and it's not 21048c2ecf20Sopenharmony_ci * supported by the hardware, we need to handle it in software 21058c2ecf20Sopenharmony_ci * by calling synchronous hash functions. 21068c2ecf20Sopenharmony_ci */ 21078c2ecf20Sopenharmony_ci if (req->src) 21088c2ecf20Sopenharmony_ci nents = sg_nents(req->src); 21098c2ecf20Sopenharmony_ci else 21108c2ecf20Sopenharmony_ci return -EINVAL; 21118c2ecf20Sopenharmony_ci 21128c2ecf20Sopenharmony_ci /* Copy data from req scatterlist to tmp buffer */ 21138c2ecf20Sopenharmony_ci gfp = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG | 21148c2ecf20Sopenharmony_ci CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC; 21158c2ecf20Sopenharmony_ci tmpbuf = kmalloc(req->nbytes, gfp); 21168c2ecf20Sopenharmony_ci if (!tmpbuf) 21178c2ecf20Sopenharmony_ci return -ENOMEM; 21188c2ecf20Sopenharmony_ci 21198c2ecf20Sopenharmony_ci if (sg_copy_to_buffer(req->src, nents, tmpbuf, req->nbytes) != 21208c2ecf20Sopenharmony_ci req->nbytes) { 21218c2ecf20Sopenharmony_ci kfree(tmpbuf); 21228c2ecf20Sopenharmony_ci return -EINVAL; 21238c2ecf20Sopenharmony_ci } 21248c2ecf20Sopenharmony_ci 21258c2ecf20Sopenharmony_ci /* Call synchronous update */ 21268c2ecf20Sopenharmony_ci ret = crypto_shash_update(ctx->shash, tmpbuf, req->nbytes); 21278c2ecf20Sopenharmony_ci kfree(tmpbuf); 21288c2ecf20Sopenharmony_ci } else { 21298c2ecf20Sopenharmony_ci /* Otherwise call the internal function which uses SPU hw */ 21308c2ecf20Sopenharmony_ci ret = __ahash_update(req); 21318c2ecf20Sopenharmony_ci } 21328c2ecf20Sopenharmony_ci 21338c2ecf20Sopenharmony_ci return ret; 21348c2ecf20Sopenharmony_ci} 21358c2ecf20Sopenharmony_ci 21368c2ecf20Sopenharmony_cistatic int __ahash_final(struct ahash_request *req) 21378c2ecf20Sopenharmony_ci{ 21388c2ecf20Sopenharmony_ci struct iproc_reqctx_s *rctx = ahash_request_ctx(req); 21398c2ecf20Sopenharmony_ci 21408c2ecf20Sopenharmony_ci flow_log("ahash_final() nbytes:%u\n", req->nbytes); 21418c2ecf20Sopenharmony_ci 21428c2ecf20Sopenharmony_ci rctx->is_final = 1; 21438c2ecf20Sopenharmony_ci 21448c2ecf20Sopenharmony_ci return ahash_enqueue(req); 21458c2ecf20Sopenharmony_ci} 21468c2ecf20Sopenharmony_ci 21478c2ecf20Sopenharmony_cistatic int ahash_final(struct ahash_request *req) 21488c2ecf20Sopenharmony_ci{ 21498c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 21508c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = crypto_ahash_ctx(tfm); 21518c2ecf20Sopenharmony_ci int ret; 21528c2ecf20Sopenharmony_ci 21538c2ecf20Sopenharmony_ci if (spu_no_incr_hash(ctx)) { 21548c2ecf20Sopenharmony_ci /* 21558c2ecf20Sopenharmony_ci * If we get an incremental hashing request and it's not 21568c2ecf20Sopenharmony_ci * supported by the hardware, we need to handle it in software 21578c2ecf20Sopenharmony_ci * by calling synchronous hash functions. 21588c2ecf20Sopenharmony_ci */ 21598c2ecf20Sopenharmony_ci ret = crypto_shash_final(ctx->shash, req->result); 21608c2ecf20Sopenharmony_ci 21618c2ecf20Sopenharmony_ci /* Done with hash, can deallocate it now */ 21628c2ecf20Sopenharmony_ci crypto_free_shash(ctx->shash->tfm); 21638c2ecf20Sopenharmony_ci kfree(ctx->shash); 21648c2ecf20Sopenharmony_ci 21658c2ecf20Sopenharmony_ci } else { 21668c2ecf20Sopenharmony_ci /* Otherwise call the internal function which uses SPU hw */ 21678c2ecf20Sopenharmony_ci ret = __ahash_final(req); 21688c2ecf20Sopenharmony_ci } 21698c2ecf20Sopenharmony_ci 21708c2ecf20Sopenharmony_ci return ret; 21718c2ecf20Sopenharmony_ci} 21728c2ecf20Sopenharmony_ci 21738c2ecf20Sopenharmony_cistatic int __ahash_finup(struct ahash_request *req) 21748c2ecf20Sopenharmony_ci{ 21758c2ecf20Sopenharmony_ci struct iproc_reqctx_s *rctx = ahash_request_ctx(req); 21768c2ecf20Sopenharmony_ci 21778c2ecf20Sopenharmony_ci flow_log("ahash_finup() nbytes:%u\n", req->nbytes); 21788c2ecf20Sopenharmony_ci 21798c2ecf20Sopenharmony_ci rctx->total_todo += req->nbytes; 21808c2ecf20Sopenharmony_ci rctx->src_sent = 0; 21818c2ecf20Sopenharmony_ci rctx->is_final = 1; 21828c2ecf20Sopenharmony_ci 21838c2ecf20Sopenharmony_ci return ahash_enqueue(req); 21848c2ecf20Sopenharmony_ci} 21858c2ecf20Sopenharmony_ci 21868c2ecf20Sopenharmony_cistatic int ahash_finup(struct ahash_request *req) 21878c2ecf20Sopenharmony_ci{ 21888c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 21898c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = crypto_ahash_ctx(tfm); 21908c2ecf20Sopenharmony_ci u8 *tmpbuf; 21918c2ecf20Sopenharmony_ci int ret; 21928c2ecf20Sopenharmony_ci int nents; 21938c2ecf20Sopenharmony_ci gfp_t gfp; 21948c2ecf20Sopenharmony_ci 21958c2ecf20Sopenharmony_ci if (spu_no_incr_hash(ctx)) { 21968c2ecf20Sopenharmony_ci /* 21978c2ecf20Sopenharmony_ci * If we get an incremental hashing request and it's not 21988c2ecf20Sopenharmony_ci * supported by the hardware, we need to handle it in software 21998c2ecf20Sopenharmony_ci * by calling synchronous hash functions. 22008c2ecf20Sopenharmony_ci */ 22018c2ecf20Sopenharmony_ci if (req->src) { 22028c2ecf20Sopenharmony_ci nents = sg_nents(req->src); 22038c2ecf20Sopenharmony_ci } else { 22048c2ecf20Sopenharmony_ci ret = -EINVAL; 22058c2ecf20Sopenharmony_ci goto ahash_finup_exit; 22068c2ecf20Sopenharmony_ci } 22078c2ecf20Sopenharmony_ci 22088c2ecf20Sopenharmony_ci /* Copy data from req scatterlist to tmp buffer */ 22098c2ecf20Sopenharmony_ci gfp = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG | 22108c2ecf20Sopenharmony_ci CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC; 22118c2ecf20Sopenharmony_ci tmpbuf = kmalloc(req->nbytes, gfp); 22128c2ecf20Sopenharmony_ci if (!tmpbuf) { 22138c2ecf20Sopenharmony_ci ret = -ENOMEM; 22148c2ecf20Sopenharmony_ci goto ahash_finup_exit; 22158c2ecf20Sopenharmony_ci } 22168c2ecf20Sopenharmony_ci 22178c2ecf20Sopenharmony_ci if (sg_copy_to_buffer(req->src, nents, tmpbuf, req->nbytes) != 22188c2ecf20Sopenharmony_ci req->nbytes) { 22198c2ecf20Sopenharmony_ci ret = -EINVAL; 22208c2ecf20Sopenharmony_ci goto ahash_finup_free; 22218c2ecf20Sopenharmony_ci } 22228c2ecf20Sopenharmony_ci 22238c2ecf20Sopenharmony_ci /* Call synchronous update */ 22248c2ecf20Sopenharmony_ci ret = crypto_shash_finup(ctx->shash, tmpbuf, req->nbytes, 22258c2ecf20Sopenharmony_ci req->result); 22268c2ecf20Sopenharmony_ci } else { 22278c2ecf20Sopenharmony_ci /* Otherwise call the internal function which uses SPU hw */ 22288c2ecf20Sopenharmony_ci return __ahash_finup(req); 22298c2ecf20Sopenharmony_ci } 22308c2ecf20Sopenharmony_ciahash_finup_free: 22318c2ecf20Sopenharmony_ci kfree(tmpbuf); 22328c2ecf20Sopenharmony_ci 22338c2ecf20Sopenharmony_ciahash_finup_exit: 22348c2ecf20Sopenharmony_ci /* Done with hash, can deallocate it now */ 22358c2ecf20Sopenharmony_ci crypto_free_shash(ctx->shash->tfm); 22368c2ecf20Sopenharmony_ci kfree(ctx->shash); 22378c2ecf20Sopenharmony_ci return ret; 22388c2ecf20Sopenharmony_ci} 22398c2ecf20Sopenharmony_ci 22408c2ecf20Sopenharmony_cistatic int ahash_digest(struct ahash_request *req) 22418c2ecf20Sopenharmony_ci{ 22428c2ecf20Sopenharmony_ci int err; 22438c2ecf20Sopenharmony_ci 22448c2ecf20Sopenharmony_ci flow_log("ahash_digest() nbytes:%u\n", req->nbytes); 22458c2ecf20Sopenharmony_ci 22468c2ecf20Sopenharmony_ci /* whole thing at once */ 22478c2ecf20Sopenharmony_ci err = __ahash_init(req); 22488c2ecf20Sopenharmony_ci if (!err) 22498c2ecf20Sopenharmony_ci err = __ahash_finup(req); 22508c2ecf20Sopenharmony_ci 22518c2ecf20Sopenharmony_ci return err; 22528c2ecf20Sopenharmony_ci} 22538c2ecf20Sopenharmony_ci 22548c2ecf20Sopenharmony_cistatic int ahash_setkey(struct crypto_ahash *ahash, const u8 *key, 22558c2ecf20Sopenharmony_ci unsigned int keylen) 22568c2ecf20Sopenharmony_ci{ 22578c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = crypto_ahash_ctx(ahash); 22588c2ecf20Sopenharmony_ci 22598c2ecf20Sopenharmony_ci flow_log("%s() ahash:%p key:%p keylen:%u\n", 22608c2ecf20Sopenharmony_ci __func__, ahash, key, keylen); 22618c2ecf20Sopenharmony_ci flow_dump(" key: ", key, keylen); 22628c2ecf20Sopenharmony_ci 22638c2ecf20Sopenharmony_ci if (ctx->auth.alg == HASH_ALG_AES) { 22648c2ecf20Sopenharmony_ci switch (keylen) { 22658c2ecf20Sopenharmony_ci case AES_KEYSIZE_128: 22668c2ecf20Sopenharmony_ci ctx->cipher_type = CIPHER_TYPE_AES128; 22678c2ecf20Sopenharmony_ci break; 22688c2ecf20Sopenharmony_ci case AES_KEYSIZE_192: 22698c2ecf20Sopenharmony_ci ctx->cipher_type = CIPHER_TYPE_AES192; 22708c2ecf20Sopenharmony_ci break; 22718c2ecf20Sopenharmony_ci case AES_KEYSIZE_256: 22728c2ecf20Sopenharmony_ci ctx->cipher_type = CIPHER_TYPE_AES256; 22738c2ecf20Sopenharmony_ci break; 22748c2ecf20Sopenharmony_ci default: 22758c2ecf20Sopenharmony_ci pr_err("%s() Error: Invalid key length\n", __func__); 22768c2ecf20Sopenharmony_ci return -EINVAL; 22778c2ecf20Sopenharmony_ci } 22788c2ecf20Sopenharmony_ci } else { 22798c2ecf20Sopenharmony_ci pr_err("%s() Error: unknown hash alg\n", __func__); 22808c2ecf20Sopenharmony_ci return -EINVAL; 22818c2ecf20Sopenharmony_ci } 22828c2ecf20Sopenharmony_ci memcpy(ctx->authkey, key, keylen); 22838c2ecf20Sopenharmony_ci ctx->authkeylen = keylen; 22848c2ecf20Sopenharmony_ci 22858c2ecf20Sopenharmony_ci return 0; 22868c2ecf20Sopenharmony_ci} 22878c2ecf20Sopenharmony_ci 22888c2ecf20Sopenharmony_cistatic int ahash_export(struct ahash_request *req, void *out) 22898c2ecf20Sopenharmony_ci{ 22908c2ecf20Sopenharmony_ci const struct iproc_reqctx_s *rctx = ahash_request_ctx(req); 22918c2ecf20Sopenharmony_ci struct spu_hash_export_s *spu_exp = (struct spu_hash_export_s *)out; 22928c2ecf20Sopenharmony_ci 22938c2ecf20Sopenharmony_ci spu_exp->total_todo = rctx->total_todo; 22948c2ecf20Sopenharmony_ci spu_exp->total_sent = rctx->total_sent; 22958c2ecf20Sopenharmony_ci spu_exp->is_sw_hmac = rctx->is_sw_hmac; 22968c2ecf20Sopenharmony_ci memcpy(spu_exp->hash_carry, rctx->hash_carry, sizeof(rctx->hash_carry)); 22978c2ecf20Sopenharmony_ci spu_exp->hash_carry_len = rctx->hash_carry_len; 22988c2ecf20Sopenharmony_ci memcpy(spu_exp->incr_hash, rctx->incr_hash, sizeof(rctx->incr_hash)); 22998c2ecf20Sopenharmony_ci 23008c2ecf20Sopenharmony_ci return 0; 23018c2ecf20Sopenharmony_ci} 23028c2ecf20Sopenharmony_ci 23038c2ecf20Sopenharmony_cistatic int ahash_import(struct ahash_request *req, const void *in) 23048c2ecf20Sopenharmony_ci{ 23058c2ecf20Sopenharmony_ci struct iproc_reqctx_s *rctx = ahash_request_ctx(req); 23068c2ecf20Sopenharmony_ci struct spu_hash_export_s *spu_exp = (struct spu_hash_export_s *)in; 23078c2ecf20Sopenharmony_ci 23088c2ecf20Sopenharmony_ci rctx->total_todo = spu_exp->total_todo; 23098c2ecf20Sopenharmony_ci rctx->total_sent = spu_exp->total_sent; 23108c2ecf20Sopenharmony_ci rctx->is_sw_hmac = spu_exp->is_sw_hmac; 23118c2ecf20Sopenharmony_ci memcpy(rctx->hash_carry, spu_exp->hash_carry, sizeof(rctx->hash_carry)); 23128c2ecf20Sopenharmony_ci rctx->hash_carry_len = spu_exp->hash_carry_len; 23138c2ecf20Sopenharmony_ci memcpy(rctx->incr_hash, spu_exp->incr_hash, sizeof(rctx->incr_hash)); 23148c2ecf20Sopenharmony_ci 23158c2ecf20Sopenharmony_ci return 0; 23168c2ecf20Sopenharmony_ci} 23178c2ecf20Sopenharmony_ci 23188c2ecf20Sopenharmony_cistatic int ahash_hmac_setkey(struct crypto_ahash *ahash, const u8 *key, 23198c2ecf20Sopenharmony_ci unsigned int keylen) 23208c2ecf20Sopenharmony_ci{ 23218c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = crypto_ahash_ctx(ahash); 23228c2ecf20Sopenharmony_ci unsigned int blocksize = 23238c2ecf20Sopenharmony_ci crypto_tfm_alg_blocksize(crypto_ahash_tfm(ahash)); 23248c2ecf20Sopenharmony_ci unsigned int digestsize = crypto_ahash_digestsize(ahash); 23258c2ecf20Sopenharmony_ci unsigned int index; 23268c2ecf20Sopenharmony_ci int rc; 23278c2ecf20Sopenharmony_ci 23288c2ecf20Sopenharmony_ci flow_log("%s() ahash:%p key:%p keylen:%u blksz:%u digestsz:%u\n", 23298c2ecf20Sopenharmony_ci __func__, ahash, key, keylen, blocksize, digestsize); 23308c2ecf20Sopenharmony_ci flow_dump(" key: ", key, keylen); 23318c2ecf20Sopenharmony_ci 23328c2ecf20Sopenharmony_ci if (keylen > blocksize) { 23338c2ecf20Sopenharmony_ci switch (ctx->auth.alg) { 23348c2ecf20Sopenharmony_ci case HASH_ALG_MD5: 23358c2ecf20Sopenharmony_ci rc = do_shash("md5", ctx->authkey, key, keylen, NULL, 23368c2ecf20Sopenharmony_ci 0, NULL, 0); 23378c2ecf20Sopenharmony_ci break; 23388c2ecf20Sopenharmony_ci case HASH_ALG_SHA1: 23398c2ecf20Sopenharmony_ci rc = do_shash("sha1", ctx->authkey, key, keylen, NULL, 23408c2ecf20Sopenharmony_ci 0, NULL, 0); 23418c2ecf20Sopenharmony_ci break; 23428c2ecf20Sopenharmony_ci case HASH_ALG_SHA224: 23438c2ecf20Sopenharmony_ci rc = do_shash("sha224", ctx->authkey, key, keylen, NULL, 23448c2ecf20Sopenharmony_ci 0, NULL, 0); 23458c2ecf20Sopenharmony_ci break; 23468c2ecf20Sopenharmony_ci case HASH_ALG_SHA256: 23478c2ecf20Sopenharmony_ci rc = do_shash("sha256", ctx->authkey, key, keylen, NULL, 23488c2ecf20Sopenharmony_ci 0, NULL, 0); 23498c2ecf20Sopenharmony_ci break; 23508c2ecf20Sopenharmony_ci case HASH_ALG_SHA384: 23518c2ecf20Sopenharmony_ci rc = do_shash("sha384", ctx->authkey, key, keylen, NULL, 23528c2ecf20Sopenharmony_ci 0, NULL, 0); 23538c2ecf20Sopenharmony_ci break; 23548c2ecf20Sopenharmony_ci case HASH_ALG_SHA512: 23558c2ecf20Sopenharmony_ci rc = do_shash("sha512", ctx->authkey, key, keylen, NULL, 23568c2ecf20Sopenharmony_ci 0, NULL, 0); 23578c2ecf20Sopenharmony_ci break; 23588c2ecf20Sopenharmony_ci case HASH_ALG_SHA3_224: 23598c2ecf20Sopenharmony_ci rc = do_shash("sha3-224", ctx->authkey, key, keylen, 23608c2ecf20Sopenharmony_ci NULL, 0, NULL, 0); 23618c2ecf20Sopenharmony_ci break; 23628c2ecf20Sopenharmony_ci case HASH_ALG_SHA3_256: 23638c2ecf20Sopenharmony_ci rc = do_shash("sha3-256", ctx->authkey, key, keylen, 23648c2ecf20Sopenharmony_ci NULL, 0, NULL, 0); 23658c2ecf20Sopenharmony_ci break; 23668c2ecf20Sopenharmony_ci case HASH_ALG_SHA3_384: 23678c2ecf20Sopenharmony_ci rc = do_shash("sha3-384", ctx->authkey, key, keylen, 23688c2ecf20Sopenharmony_ci NULL, 0, NULL, 0); 23698c2ecf20Sopenharmony_ci break; 23708c2ecf20Sopenharmony_ci case HASH_ALG_SHA3_512: 23718c2ecf20Sopenharmony_ci rc = do_shash("sha3-512", ctx->authkey, key, keylen, 23728c2ecf20Sopenharmony_ci NULL, 0, NULL, 0); 23738c2ecf20Sopenharmony_ci break; 23748c2ecf20Sopenharmony_ci default: 23758c2ecf20Sopenharmony_ci pr_err("%s() Error: unknown hash alg\n", __func__); 23768c2ecf20Sopenharmony_ci return -EINVAL; 23778c2ecf20Sopenharmony_ci } 23788c2ecf20Sopenharmony_ci if (rc < 0) { 23798c2ecf20Sopenharmony_ci pr_err("%s() Error %d computing shash for %s\n", 23808c2ecf20Sopenharmony_ci __func__, rc, hash_alg_name[ctx->auth.alg]); 23818c2ecf20Sopenharmony_ci return rc; 23828c2ecf20Sopenharmony_ci } 23838c2ecf20Sopenharmony_ci ctx->authkeylen = digestsize; 23848c2ecf20Sopenharmony_ci 23858c2ecf20Sopenharmony_ci flow_log(" keylen > digestsize... hashed\n"); 23868c2ecf20Sopenharmony_ci flow_dump(" newkey: ", ctx->authkey, ctx->authkeylen); 23878c2ecf20Sopenharmony_ci } else { 23888c2ecf20Sopenharmony_ci memcpy(ctx->authkey, key, keylen); 23898c2ecf20Sopenharmony_ci ctx->authkeylen = keylen; 23908c2ecf20Sopenharmony_ci } 23918c2ecf20Sopenharmony_ci 23928c2ecf20Sopenharmony_ci /* 23938c2ecf20Sopenharmony_ci * Full HMAC operation in SPUM is not verified, 23948c2ecf20Sopenharmony_ci * So keeping the generation of IPAD, OPAD and 23958c2ecf20Sopenharmony_ci * outer hashing in software. 23968c2ecf20Sopenharmony_ci */ 23978c2ecf20Sopenharmony_ci if (iproc_priv.spu.spu_type == SPU_TYPE_SPUM) { 23988c2ecf20Sopenharmony_ci memcpy(ctx->ipad, ctx->authkey, ctx->authkeylen); 23998c2ecf20Sopenharmony_ci memset(ctx->ipad + ctx->authkeylen, 0, 24008c2ecf20Sopenharmony_ci blocksize - ctx->authkeylen); 24018c2ecf20Sopenharmony_ci ctx->authkeylen = 0; 24028c2ecf20Sopenharmony_ci memcpy(ctx->opad, ctx->ipad, blocksize); 24038c2ecf20Sopenharmony_ci 24048c2ecf20Sopenharmony_ci for (index = 0; index < blocksize; index++) { 24058c2ecf20Sopenharmony_ci ctx->ipad[index] ^= HMAC_IPAD_VALUE; 24068c2ecf20Sopenharmony_ci ctx->opad[index] ^= HMAC_OPAD_VALUE; 24078c2ecf20Sopenharmony_ci } 24088c2ecf20Sopenharmony_ci 24098c2ecf20Sopenharmony_ci flow_dump(" ipad: ", ctx->ipad, blocksize); 24108c2ecf20Sopenharmony_ci flow_dump(" opad: ", ctx->opad, blocksize); 24118c2ecf20Sopenharmony_ci } 24128c2ecf20Sopenharmony_ci ctx->digestsize = digestsize; 24138c2ecf20Sopenharmony_ci atomic_inc(&iproc_priv.setkey_cnt[SPU_OP_HMAC]); 24148c2ecf20Sopenharmony_ci 24158c2ecf20Sopenharmony_ci return 0; 24168c2ecf20Sopenharmony_ci} 24178c2ecf20Sopenharmony_ci 24188c2ecf20Sopenharmony_cistatic int ahash_hmac_init(struct ahash_request *req) 24198c2ecf20Sopenharmony_ci{ 24208c2ecf20Sopenharmony_ci struct iproc_reqctx_s *rctx = ahash_request_ctx(req); 24218c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 24228c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = crypto_ahash_ctx(tfm); 24238c2ecf20Sopenharmony_ci unsigned int blocksize = 24248c2ecf20Sopenharmony_ci crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); 24258c2ecf20Sopenharmony_ci 24268c2ecf20Sopenharmony_ci flow_log("ahash_hmac_init()\n"); 24278c2ecf20Sopenharmony_ci 24288c2ecf20Sopenharmony_ci /* init the context as a hash */ 24298c2ecf20Sopenharmony_ci ahash_init(req); 24308c2ecf20Sopenharmony_ci 24318c2ecf20Sopenharmony_ci if (!spu_no_incr_hash(ctx)) { 24328c2ecf20Sopenharmony_ci /* SPU-M can do incr hashing but needs sw for outer HMAC */ 24338c2ecf20Sopenharmony_ci rctx->is_sw_hmac = true; 24348c2ecf20Sopenharmony_ci ctx->auth.mode = HASH_MODE_HASH; 24358c2ecf20Sopenharmony_ci /* start with a prepended ipad */ 24368c2ecf20Sopenharmony_ci memcpy(rctx->hash_carry, ctx->ipad, blocksize); 24378c2ecf20Sopenharmony_ci rctx->hash_carry_len = blocksize; 24388c2ecf20Sopenharmony_ci rctx->total_todo += blocksize; 24398c2ecf20Sopenharmony_ci } 24408c2ecf20Sopenharmony_ci 24418c2ecf20Sopenharmony_ci return 0; 24428c2ecf20Sopenharmony_ci} 24438c2ecf20Sopenharmony_ci 24448c2ecf20Sopenharmony_cistatic int ahash_hmac_update(struct ahash_request *req) 24458c2ecf20Sopenharmony_ci{ 24468c2ecf20Sopenharmony_ci flow_log("ahash_hmac_update() nbytes:%u\n", req->nbytes); 24478c2ecf20Sopenharmony_ci 24488c2ecf20Sopenharmony_ci if (!req->nbytes) 24498c2ecf20Sopenharmony_ci return 0; 24508c2ecf20Sopenharmony_ci 24518c2ecf20Sopenharmony_ci return ahash_update(req); 24528c2ecf20Sopenharmony_ci} 24538c2ecf20Sopenharmony_ci 24548c2ecf20Sopenharmony_cistatic int ahash_hmac_final(struct ahash_request *req) 24558c2ecf20Sopenharmony_ci{ 24568c2ecf20Sopenharmony_ci flow_log("ahash_hmac_final() nbytes:%u\n", req->nbytes); 24578c2ecf20Sopenharmony_ci 24588c2ecf20Sopenharmony_ci return ahash_final(req); 24598c2ecf20Sopenharmony_ci} 24608c2ecf20Sopenharmony_ci 24618c2ecf20Sopenharmony_cistatic int ahash_hmac_finup(struct ahash_request *req) 24628c2ecf20Sopenharmony_ci{ 24638c2ecf20Sopenharmony_ci flow_log("ahash_hmac_finupl() nbytes:%u\n", req->nbytes); 24648c2ecf20Sopenharmony_ci 24658c2ecf20Sopenharmony_ci return ahash_finup(req); 24668c2ecf20Sopenharmony_ci} 24678c2ecf20Sopenharmony_ci 24688c2ecf20Sopenharmony_cistatic int ahash_hmac_digest(struct ahash_request *req) 24698c2ecf20Sopenharmony_ci{ 24708c2ecf20Sopenharmony_ci struct iproc_reqctx_s *rctx = ahash_request_ctx(req); 24718c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 24728c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = crypto_ahash_ctx(tfm); 24738c2ecf20Sopenharmony_ci unsigned int blocksize = 24748c2ecf20Sopenharmony_ci crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); 24758c2ecf20Sopenharmony_ci 24768c2ecf20Sopenharmony_ci flow_log("ahash_hmac_digest() nbytes:%u\n", req->nbytes); 24778c2ecf20Sopenharmony_ci 24788c2ecf20Sopenharmony_ci /* Perform initialization and then call finup */ 24798c2ecf20Sopenharmony_ci __ahash_init(req); 24808c2ecf20Sopenharmony_ci 24818c2ecf20Sopenharmony_ci if (iproc_priv.spu.spu_type == SPU_TYPE_SPU2) { 24828c2ecf20Sopenharmony_ci /* 24838c2ecf20Sopenharmony_ci * SPU2 supports full HMAC implementation in the 24848c2ecf20Sopenharmony_ci * hardware, need not to generate IPAD, OPAD and 24858c2ecf20Sopenharmony_ci * outer hash in software. 24868c2ecf20Sopenharmony_ci * Only for hash key len > hash block size, SPU2 24878c2ecf20Sopenharmony_ci * expects to perform hashing on the key, shorten 24888c2ecf20Sopenharmony_ci * it to digest size and feed it as hash key. 24898c2ecf20Sopenharmony_ci */ 24908c2ecf20Sopenharmony_ci rctx->is_sw_hmac = false; 24918c2ecf20Sopenharmony_ci ctx->auth.mode = HASH_MODE_HMAC; 24928c2ecf20Sopenharmony_ci } else { 24938c2ecf20Sopenharmony_ci rctx->is_sw_hmac = true; 24948c2ecf20Sopenharmony_ci ctx->auth.mode = HASH_MODE_HASH; 24958c2ecf20Sopenharmony_ci /* start with a prepended ipad */ 24968c2ecf20Sopenharmony_ci memcpy(rctx->hash_carry, ctx->ipad, blocksize); 24978c2ecf20Sopenharmony_ci rctx->hash_carry_len = blocksize; 24988c2ecf20Sopenharmony_ci rctx->total_todo += blocksize; 24998c2ecf20Sopenharmony_ci } 25008c2ecf20Sopenharmony_ci 25018c2ecf20Sopenharmony_ci return __ahash_finup(req); 25028c2ecf20Sopenharmony_ci} 25038c2ecf20Sopenharmony_ci 25048c2ecf20Sopenharmony_ci/* aead helpers */ 25058c2ecf20Sopenharmony_ci 25068c2ecf20Sopenharmony_cistatic int aead_need_fallback(struct aead_request *req) 25078c2ecf20Sopenharmony_ci{ 25088c2ecf20Sopenharmony_ci struct iproc_reqctx_s *rctx = aead_request_ctx(req); 25098c2ecf20Sopenharmony_ci struct spu_hw *spu = &iproc_priv.spu; 25108c2ecf20Sopenharmony_ci struct crypto_aead *aead = crypto_aead_reqtfm(req); 25118c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = crypto_aead_ctx(aead); 25128c2ecf20Sopenharmony_ci u32 payload_len; 25138c2ecf20Sopenharmony_ci 25148c2ecf20Sopenharmony_ci /* 25158c2ecf20Sopenharmony_ci * SPU hardware cannot handle the AES-GCM/CCM case where plaintext 25168c2ecf20Sopenharmony_ci * and AAD are both 0 bytes long. So use fallback in this case. 25178c2ecf20Sopenharmony_ci */ 25188c2ecf20Sopenharmony_ci if (((ctx->cipher.mode == CIPHER_MODE_GCM) || 25198c2ecf20Sopenharmony_ci (ctx->cipher.mode == CIPHER_MODE_CCM)) && 25208c2ecf20Sopenharmony_ci (req->assoclen == 0)) { 25218c2ecf20Sopenharmony_ci if ((rctx->is_encrypt && (req->cryptlen == 0)) || 25228c2ecf20Sopenharmony_ci (!rctx->is_encrypt && (req->cryptlen == ctx->digestsize))) { 25238c2ecf20Sopenharmony_ci flow_log("AES GCM/CCM needs fallback for 0 len req\n"); 25248c2ecf20Sopenharmony_ci return 1; 25258c2ecf20Sopenharmony_ci } 25268c2ecf20Sopenharmony_ci } 25278c2ecf20Sopenharmony_ci 25288c2ecf20Sopenharmony_ci /* SPU-M hardware only supports CCM digest size of 8, 12, or 16 bytes */ 25298c2ecf20Sopenharmony_ci if ((ctx->cipher.mode == CIPHER_MODE_CCM) && 25308c2ecf20Sopenharmony_ci (spu->spu_type == SPU_TYPE_SPUM) && 25318c2ecf20Sopenharmony_ci (ctx->digestsize != 8) && (ctx->digestsize != 12) && 25328c2ecf20Sopenharmony_ci (ctx->digestsize != 16)) { 25338c2ecf20Sopenharmony_ci flow_log("%s() AES CCM needs fallback for digest size %d\n", 25348c2ecf20Sopenharmony_ci __func__, ctx->digestsize); 25358c2ecf20Sopenharmony_ci return 1; 25368c2ecf20Sopenharmony_ci } 25378c2ecf20Sopenharmony_ci 25388c2ecf20Sopenharmony_ci /* 25398c2ecf20Sopenharmony_ci * SPU-M on NSP has an issue where AES-CCM hash is not correct 25408c2ecf20Sopenharmony_ci * when AAD size is 0 25418c2ecf20Sopenharmony_ci */ 25428c2ecf20Sopenharmony_ci if ((ctx->cipher.mode == CIPHER_MODE_CCM) && 25438c2ecf20Sopenharmony_ci (spu->spu_subtype == SPU_SUBTYPE_SPUM_NSP) && 25448c2ecf20Sopenharmony_ci (req->assoclen == 0)) { 25458c2ecf20Sopenharmony_ci flow_log("%s() AES_CCM needs fallback for 0 len AAD on NSP\n", 25468c2ecf20Sopenharmony_ci __func__); 25478c2ecf20Sopenharmony_ci return 1; 25488c2ecf20Sopenharmony_ci } 25498c2ecf20Sopenharmony_ci 25508c2ecf20Sopenharmony_ci /* 25518c2ecf20Sopenharmony_ci * RFC4106 and RFC4543 cannot handle the case where AAD is other than 25528c2ecf20Sopenharmony_ci * 16 or 20 bytes long. So use fallback in this case. 25538c2ecf20Sopenharmony_ci */ 25548c2ecf20Sopenharmony_ci if (ctx->cipher.mode == CIPHER_MODE_GCM && 25558c2ecf20Sopenharmony_ci ctx->cipher.alg == CIPHER_ALG_AES && 25568c2ecf20Sopenharmony_ci rctx->iv_ctr_len == GCM_RFC4106_IV_SIZE && 25578c2ecf20Sopenharmony_ci req->assoclen != 16 && req->assoclen != 20) { 25588c2ecf20Sopenharmony_ci flow_log("RFC4106/RFC4543 needs fallback for assoclen" 25598c2ecf20Sopenharmony_ci " other than 16 or 20 bytes\n"); 25608c2ecf20Sopenharmony_ci return 1; 25618c2ecf20Sopenharmony_ci } 25628c2ecf20Sopenharmony_ci 25638c2ecf20Sopenharmony_ci payload_len = req->cryptlen; 25648c2ecf20Sopenharmony_ci if (spu->spu_type == SPU_TYPE_SPUM) 25658c2ecf20Sopenharmony_ci payload_len += req->assoclen; 25668c2ecf20Sopenharmony_ci 25678c2ecf20Sopenharmony_ci flow_log("%s() payload len: %u\n", __func__, payload_len); 25688c2ecf20Sopenharmony_ci 25698c2ecf20Sopenharmony_ci if (ctx->max_payload == SPU_MAX_PAYLOAD_INF) 25708c2ecf20Sopenharmony_ci return 0; 25718c2ecf20Sopenharmony_ci else 25728c2ecf20Sopenharmony_ci return payload_len > ctx->max_payload; 25738c2ecf20Sopenharmony_ci} 25748c2ecf20Sopenharmony_ci 25758c2ecf20Sopenharmony_cistatic void aead_complete(struct crypto_async_request *areq, int err) 25768c2ecf20Sopenharmony_ci{ 25778c2ecf20Sopenharmony_ci struct aead_request *req = 25788c2ecf20Sopenharmony_ci container_of(areq, struct aead_request, base); 25798c2ecf20Sopenharmony_ci struct iproc_reqctx_s *rctx = aead_request_ctx(req); 25808c2ecf20Sopenharmony_ci struct crypto_aead *aead = crypto_aead_reqtfm(req); 25818c2ecf20Sopenharmony_ci 25828c2ecf20Sopenharmony_ci flow_log("%s() err:%d\n", __func__, err); 25838c2ecf20Sopenharmony_ci 25848c2ecf20Sopenharmony_ci areq->tfm = crypto_aead_tfm(aead); 25858c2ecf20Sopenharmony_ci 25868c2ecf20Sopenharmony_ci areq->complete = rctx->old_complete; 25878c2ecf20Sopenharmony_ci areq->data = rctx->old_data; 25888c2ecf20Sopenharmony_ci 25898c2ecf20Sopenharmony_ci areq->complete(areq, err); 25908c2ecf20Sopenharmony_ci} 25918c2ecf20Sopenharmony_ci 25928c2ecf20Sopenharmony_cistatic int aead_do_fallback(struct aead_request *req, bool is_encrypt) 25938c2ecf20Sopenharmony_ci{ 25948c2ecf20Sopenharmony_ci struct crypto_aead *aead = crypto_aead_reqtfm(req); 25958c2ecf20Sopenharmony_ci struct crypto_tfm *tfm = crypto_aead_tfm(aead); 25968c2ecf20Sopenharmony_ci struct iproc_reqctx_s *rctx = aead_request_ctx(req); 25978c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = crypto_tfm_ctx(tfm); 25988c2ecf20Sopenharmony_ci int err; 25998c2ecf20Sopenharmony_ci u32 req_flags; 26008c2ecf20Sopenharmony_ci 26018c2ecf20Sopenharmony_ci flow_log("%s() enc:%u\n", __func__, is_encrypt); 26028c2ecf20Sopenharmony_ci 26038c2ecf20Sopenharmony_ci if (ctx->fallback_cipher) { 26048c2ecf20Sopenharmony_ci /* Store the cipher tfm and then use the fallback tfm */ 26058c2ecf20Sopenharmony_ci rctx->old_tfm = tfm; 26068c2ecf20Sopenharmony_ci aead_request_set_tfm(req, ctx->fallback_cipher); 26078c2ecf20Sopenharmony_ci /* 26088c2ecf20Sopenharmony_ci * Save the callback and chain ourselves in, so we can restore 26098c2ecf20Sopenharmony_ci * the tfm 26108c2ecf20Sopenharmony_ci */ 26118c2ecf20Sopenharmony_ci rctx->old_complete = req->base.complete; 26128c2ecf20Sopenharmony_ci rctx->old_data = req->base.data; 26138c2ecf20Sopenharmony_ci req_flags = aead_request_flags(req); 26148c2ecf20Sopenharmony_ci aead_request_set_callback(req, req_flags, aead_complete, req); 26158c2ecf20Sopenharmony_ci err = is_encrypt ? crypto_aead_encrypt(req) : 26168c2ecf20Sopenharmony_ci crypto_aead_decrypt(req); 26178c2ecf20Sopenharmony_ci 26188c2ecf20Sopenharmony_ci if (err == 0) { 26198c2ecf20Sopenharmony_ci /* 26208c2ecf20Sopenharmony_ci * fallback was synchronous (did not return 26218c2ecf20Sopenharmony_ci * -EINPROGRESS). So restore request state here. 26228c2ecf20Sopenharmony_ci */ 26238c2ecf20Sopenharmony_ci aead_request_set_callback(req, req_flags, 26248c2ecf20Sopenharmony_ci rctx->old_complete, req); 26258c2ecf20Sopenharmony_ci req->base.data = rctx->old_data; 26268c2ecf20Sopenharmony_ci aead_request_set_tfm(req, aead); 26278c2ecf20Sopenharmony_ci flow_log("%s() fallback completed successfully\n\n", 26288c2ecf20Sopenharmony_ci __func__); 26298c2ecf20Sopenharmony_ci } 26308c2ecf20Sopenharmony_ci } else { 26318c2ecf20Sopenharmony_ci err = -EINVAL; 26328c2ecf20Sopenharmony_ci } 26338c2ecf20Sopenharmony_ci 26348c2ecf20Sopenharmony_ci return err; 26358c2ecf20Sopenharmony_ci} 26368c2ecf20Sopenharmony_ci 26378c2ecf20Sopenharmony_cistatic int aead_enqueue(struct aead_request *req, bool is_encrypt) 26388c2ecf20Sopenharmony_ci{ 26398c2ecf20Sopenharmony_ci struct iproc_reqctx_s *rctx = aead_request_ctx(req); 26408c2ecf20Sopenharmony_ci struct crypto_aead *aead = crypto_aead_reqtfm(req); 26418c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = crypto_aead_ctx(aead); 26428c2ecf20Sopenharmony_ci int err; 26438c2ecf20Sopenharmony_ci 26448c2ecf20Sopenharmony_ci flow_log("%s() enc:%u\n", __func__, is_encrypt); 26458c2ecf20Sopenharmony_ci 26468c2ecf20Sopenharmony_ci if (req->assoclen > MAX_ASSOC_SIZE) { 26478c2ecf20Sopenharmony_ci pr_err 26488c2ecf20Sopenharmony_ci ("%s() Error: associated data too long. (%u > %u bytes)\n", 26498c2ecf20Sopenharmony_ci __func__, req->assoclen, MAX_ASSOC_SIZE); 26508c2ecf20Sopenharmony_ci return -EINVAL; 26518c2ecf20Sopenharmony_ci } 26528c2ecf20Sopenharmony_ci 26538c2ecf20Sopenharmony_ci rctx->gfp = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG | 26548c2ecf20Sopenharmony_ci CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC; 26558c2ecf20Sopenharmony_ci rctx->parent = &req->base; 26568c2ecf20Sopenharmony_ci rctx->is_encrypt = is_encrypt; 26578c2ecf20Sopenharmony_ci rctx->bd_suppress = false; 26588c2ecf20Sopenharmony_ci rctx->total_todo = req->cryptlen; 26598c2ecf20Sopenharmony_ci rctx->src_sent = 0; 26608c2ecf20Sopenharmony_ci rctx->total_sent = 0; 26618c2ecf20Sopenharmony_ci rctx->total_received = 0; 26628c2ecf20Sopenharmony_ci rctx->is_sw_hmac = false; 26638c2ecf20Sopenharmony_ci rctx->ctx = ctx; 26648c2ecf20Sopenharmony_ci memset(&rctx->mb_mssg, 0, sizeof(struct brcm_message)); 26658c2ecf20Sopenharmony_ci 26668c2ecf20Sopenharmony_ci /* assoc data is at start of src sg */ 26678c2ecf20Sopenharmony_ci rctx->assoc = req->src; 26688c2ecf20Sopenharmony_ci 26698c2ecf20Sopenharmony_ci /* 26708c2ecf20Sopenharmony_ci * Init current position in src scatterlist to be after assoc data. 26718c2ecf20Sopenharmony_ci * src_skip set to buffer offset where data begins. (Assoc data could 26728c2ecf20Sopenharmony_ci * end in the middle of a buffer.) 26738c2ecf20Sopenharmony_ci */ 26748c2ecf20Sopenharmony_ci if (spu_sg_at_offset(req->src, req->assoclen, &rctx->src_sg, 26758c2ecf20Sopenharmony_ci &rctx->src_skip) < 0) { 26768c2ecf20Sopenharmony_ci pr_err("%s() Error: Unable to find start of src data\n", 26778c2ecf20Sopenharmony_ci __func__); 26788c2ecf20Sopenharmony_ci return -EINVAL; 26798c2ecf20Sopenharmony_ci } 26808c2ecf20Sopenharmony_ci 26818c2ecf20Sopenharmony_ci rctx->src_nents = 0; 26828c2ecf20Sopenharmony_ci rctx->dst_nents = 0; 26838c2ecf20Sopenharmony_ci if (req->dst == req->src) { 26848c2ecf20Sopenharmony_ci rctx->dst_sg = rctx->src_sg; 26858c2ecf20Sopenharmony_ci rctx->dst_skip = rctx->src_skip; 26868c2ecf20Sopenharmony_ci } else { 26878c2ecf20Sopenharmony_ci /* 26888c2ecf20Sopenharmony_ci * Expect req->dst to have room for assoc data followed by 26898c2ecf20Sopenharmony_ci * output data and ICV, if encrypt. So initialize dst_sg 26908c2ecf20Sopenharmony_ci * to point beyond assoc len offset. 26918c2ecf20Sopenharmony_ci */ 26928c2ecf20Sopenharmony_ci if (spu_sg_at_offset(req->dst, req->assoclen, &rctx->dst_sg, 26938c2ecf20Sopenharmony_ci &rctx->dst_skip) < 0) { 26948c2ecf20Sopenharmony_ci pr_err("%s() Error: Unable to find start of dst data\n", 26958c2ecf20Sopenharmony_ci __func__); 26968c2ecf20Sopenharmony_ci return -EINVAL; 26978c2ecf20Sopenharmony_ci } 26988c2ecf20Sopenharmony_ci } 26998c2ecf20Sopenharmony_ci 27008c2ecf20Sopenharmony_ci if (ctx->cipher.mode == CIPHER_MODE_CBC || 27018c2ecf20Sopenharmony_ci ctx->cipher.mode == CIPHER_MODE_CTR || 27028c2ecf20Sopenharmony_ci ctx->cipher.mode == CIPHER_MODE_OFB || 27038c2ecf20Sopenharmony_ci ctx->cipher.mode == CIPHER_MODE_XTS || 27048c2ecf20Sopenharmony_ci ctx->cipher.mode == CIPHER_MODE_GCM) { 27058c2ecf20Sopenharmony_ci rctx->iv_ctr_len = 27068c2ecf20Sopenharmony_ci ctx->salt_len + 27078c2ecf20Sopenharmony_ci crypto_aead_ivsize(crypto_aead_reqtfm(req)); 27088c2ecf20Sopenharmony_ci } else if (ctx->cipher.mode == CIPHER_MODE_CCM) { 27098c2ecf20Sopenharmony_ci rctx->iv_ctr_len = CCM_AES_IV_SIZE; 27108c2ecf20Sopenharmony_ci } else { 27118c2ecf20Sopenharmony_ci rctx->iv_ctr_len = 0; 27128c2ecf20Sopenharmony_ci } 27138c2ecf20Sopenharmony_ci 27148c2ecf20Sopenharmony_ci rctx->hash_carry_len = 0; 27158c2ecf20Sopenharmony_ci 27168c2ecf20Sopenharmony_ci flow_log(" src sg: %p\n", req->src); 27178c2ecf20Sopenharmony_ci flow_log(" rctx->src_sg: %p, src_skip %u\n", 27188c2ecf20Sopenharmony_ci rctx->src_sg, rctx->src_skip); 27198c2ecf20Sopenharmony_ci flow_log(" assoc: %p, assoclen %u\n", rctx->assoc, req->assoclen); 27208c2ecf20Sopenharmony_ci flow_log(" dst sg: %p\n", req->dst); 27218c2ecf20Sopenharmony_ci flow_log(" rctx->dst_sg: %p, dst_skip %u\n", 27228c2ecf20Sopenharmony_ci rctx->dst_sg, rctx->dst_skip); 27238c2ecf20Sopenharmony_ci flow_log(" iv_ctr_len:%u\n", rctx->iv_ctr_len); 27248c2ecf20Sopenharmony_ci flow_dump(" iv: ", req->iv, rctx->iv_ctr_len); 27258c2ecf20Sopenharmony_ci flow_log(" authkeylen:%u\n", ctx->authkeylen); 27268c2ecf20Sopenharmony_ci flow_log(" is_esp: %s\n", ctx->is_esp ? "yes" : "no"); 27278c2ecf20Sopenharmony_ci 27288c2ecf20Sopenharmony_ci if (ctx->max_payload == SPU_MAX_PAYLOAD_INF) 27298c2ecf20Sopenharmony_ci flow_log(" max_payload infinite"); 27308c2ecf20Sopenharmony_ci else 27318c2ecf20Sopenharmony_ci flow_log(" max_payload: %u\n", ctx->max_payload); 27328c2ecf20Sopenharmony_ci 27338c2ecf20Sopenharmony_ci if (unlikely(aead_need_fallback(req))) 27348c2ecf20Sopenharmony_ci return aead_do_fallback(req, is_encrypt); 27358c2ecf20Sopenharmony_ci 27368c2ecf20Sopenharmony_ci /* 27378c2ecf20Sopenharmony_ci * Do memory allocations for request after fallback check, because if we 27388c2ecf20Sopenharmony_ci * do fallback, we won't call finish_req() to dealloc. 27398c2ecf20Sopenharmony_ci */ 27408c2ecf20Sopenharmony_ci if (rctx->iv_ctr_len) { 27418c2ecf20Sopenharmony_ci if (ctx->salt_len) 27428c2ecf20Sopenharmony_ci memcpy(rctx->msg_buf.iv_ctr + ctx->salt_offset, 27438c2ecf20Sopenharmony_ci ctx->salt, ctx->salt_len); 27448c2ecf20Sopenharmony_ci memcpy(rctx->msg_buf.iv_ctr + ctx->salt_offset + ctx->salt_len, 27458c2ecf20Sopenharmony_ci req->iv, 27468c2ecf20Sopenharmony_ci rctx->iv_ctr_len - ctx->salt_len - ctx->salt_offset); 27478c2ecf20Sopenharmony_ci } 27488c2ecf20Sopenharmony_ci 27498c2ecf20Sopenharmony_ci rctx->chan_idx = select_channel(); 27508c2ecf20Sopenharmony_ci err = handle_aead_req(rctx); 27518c2ecf20Sopenharmony_ci if (err != -EINPROGRESS) 27528c2ecf20Sopenharmony_ci /* synchronous result */ 27538c2ecf20Sopenharmony_ci spu_chunk_cleanup(rctx); 27548c2ecf20Sopenharmony_ci 27558c2ecf20Sopenharmony_ci return err; 27568c2ecf20Sopenharmony_ci} 27578c2ecf20Sopenharmony_ci 27588c2ecf20Sopenharmony_cistatic int aead_authenc_setkey(struct crypto_aead *cipher, 27598c2ecf20Sopenharmony_ci const u8 *key, unsigned int keylen) 27608c2ecf20Sopenharmony_ci{ 27618c2ecf20Sopenharmony_ci struct spu_hw *spu = &iproc_priv.spu; 27628c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher); 27638c2ecf20Sopenharmony_ci struct crypto_tfm *tfm = crypto_aead_tfm(cipher); 27648c2ecf20Sopenharmony_ci struct crypto_authenc_keys keys; 27658c2ecf20Sopenharmony_ci int ret; 27668c2ecf20Sopenharmony_ci 27678c2ecf20Sopenharmony_ci flow_log("%s() aead:%p key:%p keylen:%u\n", __func__, cipher, key, 27688c2ecf20Sopenharmony_ci keylen); 27698c2ecf20Sopenharmony_ci flow_dump(" key: ", key, keylen); 27708c2ecf20Sopenharmony_ci 27718c2ecf20Sopenharmony_ci ret = crypto_authenc_extractkeys(&keys, key, keylen); 27728c2ecf20Sopenharmony_ci if (ret) 27738c2ecf20Sopenharmony_ci goto badkey; 27748c2ecf20Sopenharmony_ci 27758c2ecf20Sopenharmony_ci if (keys.enckeylen > MAX_KEY_SIZE || 27768c2ecf20Sopenharmony_ci keys.authkeylen > MAX_KEY_SIZE) 27778c2ecf20Sopenharmony_ci goto badkey; 27788c2ecf20Sopenharmony_ci 27798c2ecf20Sopenharmony_ci ctx->enckeylen = keys.enckeylen; 27808c2ecf20Sopenharmony_ci ctx->authkeylen = keys.authkeylen; 27818c2ecf20Sopenharmony_ci 27828c2ecf20Sopenharmony_ci memcpy(ctx->enckey, keys.enckey, keys.enckeylen); 27838c2ecf20Sopenharmony_ci /* May end up padding auth key. So make sure it's zeroed. */ 27848c2ecf20Sopenharmony_ci memset(ctx->authkey, 0, sizeof(ctx->authkey)); 27858c2ecf20Sopenharmony_ci memcpy(ctx->authkey, keys.authkey, keys.authkeylen); 27868c2ecf20Sopenharmony_ci 27878c2ecf20Sopenharmony_ci switch (ctx->alg->cipher_info.alg) { 27888c2ecf20Sopenharmony_ci case CIPHER_ALG_DES: 27898c2ecf20Sopenharmony_ci if (verify_aead_des_key(cipher, keys.enckey, keys.enckeylen)) 27908c2ecf20Sopenharmony_ci return -EINVAL; 27918c2ecf20Sopenharmony_ci 27928c2ecf20Sopenharmony_ci ctx->cipher_type = CIPHER_TYPE_DES; 27938c2ecf20Sopenharmony_ci break; 27948c2ecf20Sopenharmony_ci case CIPHER_ALG_3DES: 27958c2ecf20Sopenharmony_ci if (verify_aead_des3_key(cipher, keys.enckey, keys.enckeylen)) 27968c2ecf20Sopenharmony_ci return -EINVAL; 27978c2ecf20Sopenharmony_ci 27988c2ecf20Sopenharmony_ci ctx->cipher_type = CIPHER_TYPE_3DES; 27998c2ecf20Sopenharmony_ci break; 28008c2ecf20Sopenharmony_ci case CIPHER_ALG_AES: 28018c2ecf20Sopenharmony_ci switch (ctx->enckeylen) { 28028c2ecf20Sopenharmony_ci case AES_KEYSIZE_128: 28038c2ecf20Sopenharmony_ci ctx->cipher_type = CIPHER_TYPE_AES128; 28048c2ecf20Sopenharmony_ci break; 28058c2ecf20Sopenharmony_ci case AES_KEYSIZE_192: 28068c2ecf20Sopenharmony_ci ctx->cipher_type = CIPHER_TYPE_AES192; 28078c2ecf20Sopenharmony_ci break; 28088c2ecf20Sopenharmony_ci case AES_KEYSIZE_256: 28098c2ecf20Sopenharmony_ci ctx->cipher_type = CIPHER_TYPE_AES256; 28108c2ecf20Sopenharmony_ci break; 28118c2ecf20Sopenharmony_ci default: 28128c2ecf20Sopenharmony_ci goto badkey; 28138c2ecf20Sopenharmony_ci } 28148c2ecf20Sopenharmony_ci break; 28158c2ecf20Sopenharmony_ci default: 28168c2ecf20Sopenharmony_ci pr_err("%s() Error: Unknown cipher alg\n", __func__); 28178c2ecf20Sopenharmony_ci return -EINVAL; 28188c2ecf20Sopenharmony_ci } 28198c2ecf20Sopenharmony_ci 28208c2ecf20Sopenharmony_ci flow_log(" enckeylen:%u authkeylen:%u\n", ctx->enckeylen, 28218c2ecf20Sopenharmony_ci ctx->authkeylen); 28228c2ecf20Sopenharmony_ci flow_dump(" enc: ", ctx->enckey, ctx->enckeylen); 28238c2ecf20Sopenharmony_ci flow_dump(" auth: ", ctx->authkey, ctx->authkeylen); 28248c2ecf20Sopenharmony_ci 28258c2ecf20Sopenharmony_ci /* setkey the fallback just in case we needto use it */ 28268c2ecf20Sopenharmony_ci if (ctx->fallback_cipher) { 28278c2ecf20Sopenharmony_ci flow_log(" running fallback setkey()\n"); 28288c2ecf20Sopenharmony_ci 28298c2ecf20Sopenharmony_ci ctx->fallback_cipher->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK; 28308c2ecf20Sopenharmony_ci ctx->fallback_cipher->base.crt_flags |= 28318c2ecf20Sopenharmony_ci tfm->crt_flags & CRYPTO_TFM_REQ_MASK; 28328c2ecf20Sopenharmony_ci ret = crypto_aead_setkey(ctx->fallback_cipher, key, keylen); 28338c2ecf20Sopenharmony_ci if (ret) 28348c2ecf20Sopenharmony_ci flow_log(" fallback setkey() returned:%d\n", ret); 28358c2ecf20Sopenharmony_ci } 28368c2ecf20Sopenharmony_ci 28378c2ecf20Sopenharmony_ci ctx->spu_resp_hdr_len = spu->spu_response_hdr_len(ctx->authkeylen, 28388c2ecf20Sopenharmony_ci ctx->enckeylen, 28398c2ecf20Sopenharmony_ci false); 28408c2ecf20Sopenharmony_ci 28418c2ecf20Sopenharmony_ci atomic_inc(&iproc_priv.setkey_cnt[SPU_OP_AEAD]); 28428c2ecf20Sopenharmony_ci 28438c2ecf20Sopenharmony_ci return ret; 28448c2ecf20Sopenharmony_ci 28458c2ecf20Sopenharmony_cibadkey: 28468c2ecf20Sopenharmony_ci ctx->enckeylen = 0; 28478c2ecf20Sopenharmony_ci ctx->authkeylen = 0; 28488c2ecf20Sopenharmony_ci ctx->digestsize = 0; 28498c2ecf20Sopenharmony_ci 28508c2ecf20Sopenharmony_ci return -EINVAL; 28518c2ecf20Sopenharmony_ci} 28528c2ecf20Sopenharmony_ci 28538c2ecf20Sopenharmony_cistatic int aead_gcm_ccm_setkey(struct crypto_aead *cipher, 28548c2ecf20Sopenharmony_ci const u8 *key, unsigned int keylen) 28558c2ecf20Sopenharmony_ci{ 28568c2ecf20Sopenharmony_ci struct spu_hw *spu = &iproc_priv.spu; 28578c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher); 28588c2ecf20Sopenharmony_ci struct crypto_tfm *tfm = crypto_aead_tfm(cipher); 28598c2ecf20Sopenharmony_ci 28608c2ecf20Sopenharmony_ci int ret = 0; 28618c2ecf20Sopenharmony_ci 28628c2ecf20Sopenharmony_ci flow_log("%s() keylen:%u\n", __func__, keylen); 28638c2ecf20Sopenharmony_ci flow_dump(" key: ", key, keylen); 28648c2ecf20Sopenharmony_ci 28658c2ecf20Sopenharmony_ci if (!ctx->is_esp) 28668c2ecf20Sopenharmony_ci ctx->digestsize = keylen; 28678c2ecf20Sopenharmony_ci 28688c2ecf20Sopenharmony_ci ctx->enckeylen = keylen; 28698c2ecf20Sopenharmony_ci ctx->authkeylen = 0; 28708c2ecf20Sopenharmony_ci 28718c2ecf20Sopenharmony_ci switch (ctx->enckeylen) { 28728c2ecf20Sopenharmony_ci case AES_KEYSIZE_128: 28738c2ecf20Sopenharmony_ci ctx->cipher_type = CIPHER_TYPE_AES128; 28748c2ecf20Sopenharmony_ci break; 28758c2ecf20Sopenharmony_ci case AES_KEYSIZE_192: 28768c2ecf20Sopenharmony_ci ctx->cipher_type = CIPHER_TYPE_AES192; 28778c2ecf20Sopenharmony_ci break; 28788c2ecf20Sopenharmony_ci case AES_KEYSIZE_256: 28798c2ecf20Sopenharmony_ci ctx->cipher_type = CIPHER_TYPE_AES256; 28808c2ecf20Sopenharmony_ci break; 28818c2ecf20Sopenharmony_ci default: 28828c2ecf20Sopenharmony_ci goto badkey; 28838c2ecf20Sopenharmony_ci } 28848c2ecf20Sopenharmony_ci 28858c2ecf20Sopenharmony_ci memcpy(ctx->enckey, key, ctx->enckeylen); 28868c2ecf20Sopenharmony_ci 28878c2ecf20Sopenharmony_ci flow_log(" enckeylen:%u authkeylen:%u\n", ctx->enckeylen, 28888c2ecf20Sopenharmony_ci ctx->authkeylen); 28898c2ecf20Sopenharmony_ci flow_dump(" enc: ", ctx->enckey, ctx->enckeylen); 28908c2ecf20Sopenharmony_ci flow_dump(" auth: ", ctx->authkey, ctx->authkeylen); 28918c2ecf20Sopenharmony_ci 28928c2ecf20Sopenharmony_ci /* setkey the fallback just in case we need to use it */ 28938c2ecf20Sopenharmony_ci if (ctx->fallback_cipher) { 28948c2ecf20Sopenharmony_ci flow_log(" running fallback setkey()\n"); 28958c2ecf20Sopenharmony_ci 28968c2ecf20Sopenharmony_ci ctx->fallback_cipher->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK; 28978c2ecf20Sopenharmony_ci ctx->fallback_cipher->base.crt_flags |= 28988c2ecf20Sopenharmony_ci tfm->crt_flags & CRYPTO_TFM_REQ_MASK; 28998c2ecf20Sopenharmony_ci ret = crypto_aead_setkey(ctx->fallback_cipher, key, 29008c2ecf20Sopenharmony_ci keylen + ctx->salt_len); 29018c2ecf20Sopenharmony_ci if (ret) 29028c2ecf20Sopenharmony_ci flow_log(" fallback setkey() returned:%d\n", ret); 29038c2ecf20Sopenharmony_ci } 29048c2ecf20Sopenharmony_ci 29058c2ecf20Sopenharmony_ci ctx->spu_resp_hdr_len = spu->spu_response_hdr_len(ctx->authkeylen, 29068c2ecf20Sopenharmony_ci ctx->enckeylen, 29078c2ecf20Sopenharmony_ci false); 29088c2ecf20Sopenharmony_ci 29098c2ecf20Sopenharmony_ci atomic_inc(&iproc_priv.setkey_cnt[SPU_OP_AEAD]); 29108c2ecf20Sopenharmony_ci 29118c2ecf20Sopenharmony_ci flow_log(" enckeylen:%u authkeylen:%u\n", ctx->enckeylen, 29128c2ecf20Sopenharmony_ci ctx->authkeylen); 29138c2ecf20Sopenharmony_ci 29148c2ecf20Sopenharmony_ci return ret; 29158c2ecf20Sopenharmony_ci 29168c2ecf20Sopenharmony_cibadkey: 29178c2ecf20Sopenharmony_ci ctx->enckeylen = 0; 29188c2ecf20Sopenharmony_ci ctx->authkeylen = 0; 29198c2ecf20Sopenharmony_ci ctx->digestsize = 0; 29208c2ecf20Sopenharmony_ci 29218c2ecf20Sopenharmony_ci return -EINVAL; 29228c2ecf20Sopenharmony_ci} 29238c2ecf20Sopenharmony_ci 29248c2ecf20Sopenharmony_ci/** 29258c2ecf20Sopenharmony_ci * aead_gcm_esp_setkey() - setkey() operation for ESP variant of GCM AES. 29268c2ecf20Sopenharmony_ci * @cipher: AEAD structure 29278c2ecf20Sopenharmony_ci * @key: Key followed by 4 bytes of salt 29288c2ecf20Sopenharmony_ci * @keylen: Length of key plus salt, in bytes 29298c2ecf20Sopenharmony_ci * 29308c2ecf20Sopenharmony_ci * Extracts salt from key and stores it to be prepended to IV on each request. 29318c2ecf20Sopenharmony_ci * Digest is always 16 bytes 29328c2ecf20Sopenharmony_ci * 29338c2ecf20Sopenharmony_ci * Return: Value from generic gcm setkey. 29348c2ecf20Sopenharmony_ci */ 29358c2ecf20Sopenharmony_cistatic int aead_gcm_esp_setkey(struct crypto_aead *cipher, 29368c2ecf20Sopenharmony_ci const u8 *key, unsigned int keylen) 29378c2ecf20Sopenharmony_ci{ 29388c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher); 29398c2ecf20Sopenharmony_ci 29408c2ecf20Sopenharmony_ci flow_log("%s\n", __func__); 29418c2ecf20Sopenharmony_ci 29428c2ecf20Sopenharmony_ci if (keylen < GCM_ESP_SALT_SIZE) 29438c2ecf20Sopenharmony_ci return -EINVAL; 29448c2ecf20Sopenharmony_ci 29458c2ecf20Sopenharmony_ci ctx->salt_len = GCM_ESP_SALT_SIZE; 29468c2ecf20Sopenharmony_ci ctx->salt_offset = GCM_ESP_SALT_OFFSET; 29478c2ecf20Sopenharmony_ci memcpy(ctx->salt, key + keylen - GCM_ESP_SALT_SIZE, GCM_ESP_SALT_SIZE); 29488c2ecf20Sopenharmony_ci keylen -= GCM_ESP_SALT_SIZE; 29498c2ecf20Sopenharmony_ci ctx->digestsize = GCM_ESP_DIGESTSIZE; 29508c2ecf20Sopenharmony_ci ctx->is_esp = true; 29518c2ecf20Sopenharmony_ci flow_dump("salt: ", ctx->salt, GCM_ESP_SALT_SIZE); 29528c2ecf20Sopenharmony_ci 29538c2ecf20Sopenharmony_ci return aead_gcm_ccm_setkey(cipher, key, keylen); 29548c2ecf20Sopenharmony_ci} 29558c2ecf20Sopenharmony_ci 29568c2ecf20Sopenharmony_ci/** 29578c2ecf20Sopenharmony_ci * rfc4543_gcm_esp_setkey() - setkey operation for RFC4543 variant of GCM/GMAC. 29588c2ecf20Sopenharmony_ci * cipher: AEAD structure 29598c2ecf20Sopenharmony_ci * key: Key followed by 4 bytes of salt 29608c2ecf20Sopenharmony_ci * keylen: Length of key plus salt, in bytes 29618c2ecf20Sopenharmony_ci * 29628c2ecf20Sopenharmony_ci * Extracts salt from key and stores it to be prepended to IV on each request. 29638c2ecf20Sopenharmony_ci * Digest is always 16 bytes 29648c2ecf20Sopenharmony_ci * 29658c2ecf20Sopenharmony_ci * Return: Value from generic gcm setkey. 29668c2ecf20Sopenharmony_ci */ 29678c2ecf20Sopenharmony_cistatic int rfc4543_gcm_esp_setkey(struct crypto_aead *cipher, 29688c2ecf20Sopenharmony_ci const u8 *key, unsigned int keylen) 29698c2ecf20Sopenharmony_ci{ 29708c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher); 29718c2ecf20Sopenharmony_ci 29728c2ecf20Sopenharmony_ci flow_log("%s\n", __func__); 29738c2ecf20Sopenharmony_ci 29748c2ecf20Sopenharmony_ci if (keylen < GCM_ESP_SALT_SIZE) 29758c2ecf20Sopenharmony_ci return -EINVAL; 29768c2ecf20Sopenharmony_ci 29778c2ecf20Sopenharmony_ci ctx->salt_len = GCM_ESP_SALT_SIZE; 29788c2ecf20Sopenharmony_ci ctx->salt_offset = GCM_ESP_SALT_OFFSET; 29798c2ecf20Sopenharmony_ci memcpy(ctx->salt, key + keylen - GCM_ESP_SALT_SIZE, GCM_ESP_SALT_SIZE); 29808c2ecf20Sopenharmony_ci keylen -= GCM_ESP_SALT_SIZE; 29818c2ecf20Sopenharmony_ci ctx->digestsize = GCM_ESP_DIGESTSIZE; 29828c2ecf20Sopenharmony_ci ctx->is_esp = true; 29838c2ecf20Sopenharmony_ci ctx->is_rfc4543 = true; 29848c2ecf20Sopenharmony_ci flow_dump("salt: ", ctx->salt, GCM_ESP_SALT_SIZE); 29858c2ecf20Sopenharmony_ci 29868c2ecf20Sopenharmony_ci return aead_gcm_ccm_setkey(cipher, key, keylen); 29878c2ecf20Sopenharmony_ci} 29888c2ecf20Sopenharmony_ci 29898c2ecf20Sopenharmony_ci/** 29908c2ecf20Sopenharmony_ci * aead_ccm_esp_setkey() - setkey() operation for ESP variant of CCM AES. 29918c2ecf20Sopenharmony_ci * @cipher: AEAD structure 29928c2ecf20Sopenharmony_ci * @key: Key followed by 4 bytes of salt 29938c2ecf20Sopenharmony_ci * @keylen: Length of key plus salt, in bytes 29948c2ecf20Sopenharmony_ci * 29958c2ecf20Sopenharmony_ci * Extracts salt from key and stores it to be prepended to IV on each request. 29968c2ecf20Sopenharmony_ci * Digest is always 16 bytes 29978c2ecf20Sopenharmony_ci * 29988c2ecf20Sopenharmony_ci * Return: Value from generic ccm setkey. 29998c2ecf20Sopenharmony_ci */ 30008c2ecf20Sopenharmony_cistatic int aead_ccm_esp_setkey(struct crypto_aead *cipher, 30018c2ecf20Sopenharmony_ci const u8 *key, unsigned int keylen) 30028c2ecf20Sopenharmony_ci{ 30038c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher); 30048c2ecf20Sopenharmony_ci 30058c2ecf20Sopenharmony_ci flow_log("%s\n", __func__); 30068c2ecf20Sopenharmony_ci 30078c2ecf20Sopenharmony_ci if (keylen < CCM_ESP_SALT_SIZE) 30088c2ecf20Sopenharmony_ci return -EINVAL; 30098c2ecf20Sopenharmony_ci 30108c2ecf20Sopenharmony_ci ctx->salt_len = CCM_ESP_SALT_SIZE; 30118c2ecf20Sopenharmony_ci ctx->salt_offset = CCM_ESP_SALT_OFFSET; 30128c2ecf20Sopenharmony_ci memcpy(ctx->salt, key + keylen - CCM_ESP_SALT_SIZE, CCM_ESP_SALT_SIZE); 30138c2ecf20Sopenharmony_ci keylen -= CCM_ESP_SALT_SIZE; 30148c2ecf20Sopenharmony_ci ctx->is_esp = true; 30158c2ecf20Sopenharmony_ci flow_dump("salt: ", ctx->salt, CCM_ESP_SALT_SIZE); 30168c2ecf20Sopenharmony_ci 30178c2ecf20Sopenharmony_ci return aead_gcm_ccm_setkey(cipher, key, keylen); 30188c2ecf20Sopenharmony_ci} 30198c2ecf20Sopenharmony_ci 30208c2ecf20Sopenharmony_cistatic int aead_setauthsize(struct crypto_aead *cipher, unsigned int authsize) 30218c2ecf20Sopenharmony_ci{ 30228c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher); 30238c2ecf20Sopenharmony_ci int ret = 0; 30248c2ecf20Sopenharmony_ci 30258c2ecf20Sopenharmony_ci flow_log("%s() authkeylen:%u authsize:%u\n", 30268c2ecf20Sopenharmony_ci __func__, ctx->authkeylen, authsize); 30278c2ecf20Sopenharmony_ci 30288c2ecf20Sopenharmony_ci ctx->digestsize = authsize; 30298c2ecf20Sopenharmony_ci 30308c2ecf20Sopenharmony_ci /* setkey the fallback just in case we needto use it */ 30318c2ecf20Sopenharmony_ci if (ctx->fallback_cipher) { 30328c2ecf20Sopenharmony_ci flow_log(" running fallback setauth()\n"); 30338c2ecf20Sopenharmony_ci 30348c2ecf20Sopenharmony_ci ret = crypto_aead_setauthsize(ctx->fallback_cipher, authsize); 30358c2ecf20Sopenharmony_ci if (ret) 30368c2ecf20Sopenharmony_ci flow_log(" fallback setauth() returned:%d\n", ret); 30378c2ecf20Sopenharmony_ci } 30388c2ecf20Sopenharmony_ci 30398c2ecf20Sopenharmony_ci return ret; 30408c2ecf20Sopenharmony_ci} 30418c2ecf20Sopenharmony_ci 30428c2ecf20Sopenharmony_cistatic int aead_encrypt(struct aead_request *req) 30438c2ecf20Sopenharmony_ci{ 30448c2ecf20Sopenharmony_ci flow_log("%s() cryptlen:%u %08x\n", __func__, req->cryptlen, 30458c2ecf20Sopenharmony_ci req->cryptlen); 30468c2ecf20Sopenharmony_ci dump_sg(req->src, 0, req->cryptlen + req->assoclen); 30478c2ecf20Sopenharmony_ci flow_log(" assoc_len:%u\n", req->assoclen); 30488c2ecf20Sopenharmony_ci 30498c2ecf20Sopenharmony_ci return aead_enqueue(req, true); 30508c2ecf20Sopenharmony_ci} 30518c2ecf20Sopenharmony_ci 30528c2ecf20Sopenharmony_cistatic int aead_decrypt(struct aead_request *req) 30538c2ecf20Sopenharmony_ci{ 30548c2ecf20Sopenharmony_ci flow_log("%s() cryptlen:%u\n", __func__, req->cryptlen); 30558c2ecf20Sopenharmony_ci dump_sg(req->src, 0, req->cryptlen + req->assoclen); 30568c2ecf20Sopenharmony_ci flow_log(" assoc_len:%u\n", req->assoclen); 30578c2ecf20Sopenharmony_ci 30588c2ecf20Sopenharmony_ci return aead_enqueue(req, false); 30598c2ecf20Sopenharmony_ci} 30608c2ecf20Sopenharmony_ci 30618c2ecf20Sopenharmony_ci/* ==================== Supported Cipher Algorithms ==================== */ 30628c2ecf20Sopenharmony_ci 30638c2ecf20Sopenharmony_cistatic struct iproc_alg_s driver_algs[] = { 30648c2ecf20Sopenharmony_ci { 30658c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD, 30668c2ecf20Sopenharmony_ci .alg.aead = { 30678c2ecf20Sopenharmony_ci .base = { 30688c2ecf20Sopenharmony_ci .cra_name = "gcm(aes)", 30698c2ecf20Sopenharmony_ci .cra_driver_name = "gcm-aes-iproc", 30708c2ecf20Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 30718c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_NEED_FALLBACK 30728c2ecf20Sopenharmony_ci }, 30738c2ecf20Sopenharmony_ci .setkey = aead_gcm_ccm_setkey, 30748c2ecf20Sopenharmony_ci .ivsize = GCM_AES_IV_SIZE, 30758c2ecf20Sopenharmony_ci .maxauthsize = AES_BLOCK_SIZE, 30768c2ecf20Sopenharmony_ci }, 30778c2ecf20Sopenharmony_ci .cipher_info = { 30788c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_AES, 30798c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_GCM, 30808c2ecf20Sopenharmony_ci }, 30818c2ecf20Sopenharmony_ci .auth_info = { 30828c2ecf20Sopenharmony_ci .alg = HASH_ALG_AES, 30838c2ecf20Sopenharmony_ci .mode = HASH_MODE_GCM, 30848c2ecf20Sopenharmony_ci }, 30858c2ecf20Sopenharmony_ci .auth_first = 0, 30868c2ecf20Sopenharmony_ci }, 30878c2ecf20Sopenharmony_ci { 30888c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD, 30898c2ecf20Sopenharmony_ci .alg.aead = { 30908c2ecf20Sopenharmony_ci .base = { 30918c2ecf20Sopenharmony_ci .cra_name = "ccm(aes)", 30928c2ecf20Sopenharmony_ci .cra_driver_name = "ccm-aes-iproc", 30938c2ecf20Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 30948c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_NEED_FALLBACK 30958c2ecf20Sopenharmony_ci }, 30968c2ecf20Sopenharmony_ci .setkey = aead_gcm_ccm_setkey, 30978c2ecf20Sopenharmony_ci .ivsize = CCM_AES_IV_SIZE, 30988c2ecf20Sopenharmony_ci .maxauthsize = AES_BLOCK_SIZE, 30998c2ecf20Sopenharmony_ci }, 31008c2ecf20Sopenharmony_ci .cipher_info = { 31018c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_AES, 31028c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_CCM, 31038c2ecf20Sopenharmony_ci }, 31048c2ecf20Sopenharmony_ci .auth_info = { 31058c2ecf20Sopenharmony_ci .alg = HASH_ALG_AES, 31068c2ecf20Sopenharmony_ci .mode = HASH_MODE_CCM, 31078c2ecf20Sopenharmony_ci }, 31088c2ecf20Sopenharmony_ci .auth_first = 0, 31098c2ecf20Sopenharmony_ci }, 31108c2ecf20Sopenharmony_ci { 31118c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD, 31128c2ecf20Sopenharmony_ci .alg.aead = { 31138c2ecf20Sopenharmony_ci .base = { 31148c2ecf20Sopenharmony_ci .cra_name = "rfc4106(gcm(aes))", 31158c2ecf20Sopenharmony_ci .cra_driver_name = "gcm-aes-esp-iproc", 31168c2ecf20Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 31178c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_NEED_FALLBACK 31188c2ecf20Sopenharmony_ci }, 31198c2ecf20Sopenharmony_ci .setkey = aead_gcm_esp_setkey, 31208c2ecf20Sopenharmony_ci .ivsize = GCM_RFC4106_IV_SIZE, 31218c2ecf20Sopenharmony_ci .maxauthsize = AES_BLOCK_SIZE, 31228c2ecf20Sopenharmony_ci }, 31238c2ecf20Sopenharmony_ci .cipher_info = { 31248c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_AES, 31258c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_GCM, 31268c2ecf20Sopenharmony_ci }, 31278c2ecf20Sopenharmony_ci .auth_info = { 31288c2ecf20Sopenharmony_ci .alg = HASH_ALG_AES, 31298c2ecf20Sopenharmony_ci .mode = HASH_MODE_GCM, 31308c2ecf20Sopenharmony_ci }, 31318c2ecf20Sopenharmony_ci .auth_first = 0, 31328c2ecf20Sopenharmony_ci }, 31338c2ecf20Sopenharmony_ci { 31348c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD, 31358c2ecf20Sopenharmony_ci .alg.aead = { 31368c2ecf20Sopenharmony_ci .base = { 31378c2ecf20Sopenharmony_ci .cra_name = "rfc4309(ccm(aes))", 31388c2ecf20Sopenharmony_ci .cra_driver_name = "ccm-aes-esp-iproc", 31398c2ecf20Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 31408c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_NEED_FALLBACK 31418c2ecf20Sopenharmony_ci }, 31428c2ecf20Sopenharmony_ci .setkey = aead_ccm_esp_setkey, 31438c2ecf20Sopenharmony_ci .ivsize = CCM_AES_IV_SIZE, 31448c2ecf20Sopenharmony_ci .maxauthsize = AES_BLOCK_SIZE, 31458c2ecf20Sopenharmony_ci }, 31468c2ecf20Sopenharmony_ci .cipher_info = { 31478c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_AES, 31488c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_CCM, 31498c2ecf20Sopenharmony_ci }, 31508c2ecf20Sopenharmony_ci .auth_info = { 31518c2ecf20Sopenharmony_ci .alg = HASH_ALG_AES, 31528c2ecf20Sopenharmony_ci .mode = HASH_MODE_CCM, 31538c2ecf20Sopenharmony_ci }, 31548c2ecf20Sopenharmony_ci .auth_first = 0, 31558c2ecf20Sopenharmony_ci }, 31568c2ecf20Sopenharmony_ci { 31578c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD, 31588c2ecf20Sopenharmony_ci .alg.aead = { 31598c2ecf20Sopenharmony_ci .base = { 31608c2ecf20Sopenharmony_ci .cra_name = "rfc4543(gcm(aes))", 31618c2ecf20Sopenharmony_ci .cra_driver_name = "gmac-aes-esp-iproc", 31628c2ecf20Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 31638c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_NEED_FALLBACK 31648c2ecf20Sopenharmony_ci }, 31658c2ecf20Sopenharmony_ci .setkey = rfc4543_gcm_esp_setkey, 31668c2ecf20Sopenharmony_ci .ivsize = GCM_RFC4106_IV_SIZE, 31678c2ecf20Sopenharmony_ci .maxauthsize = AES_BLOCK_SIZE, 31688c2ecf20Sopenharmony_ci }, 31698c2ecf20Sopenharmony_ci .cipher_info = { 31708c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_AES, 31718c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_GCM, 31728c2ecf20Sopenharmony_ci }, 31738c2ecf20Sopenharmony_ci .auth_info = { 31748c2ecf20Sopenharmony_ci .alg = HASH_ALG_AES, 31758c2ecf20Sopenharmony_ci .mode = HASH_MODE_GCM, 31768c2ecf20Sopenharmony_ci }, 31778c2ecf20Sopenharmony_ci .auth_first = 0, 31788c2ecf20Sopenharmony_ci }, 31798c2ecf20Sopenharmony_ci { 31808c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD, 31818c2ecf20Sopenharmony_ci .alg.aead = { 31828c2ecf20Sopenharmony_ci .base = { 31838c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(md5),cbc(aes))", 31848c2ecf20Sopenharmony_ci .cra_driver_name = "authenc-hmac-md5-cbc-aes-iproc", 31858c2ecf20Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 31868c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_NEED_FALLBACK | 31878c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 31888c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY 31898c2ecf20Sopenharmony_ci }, 31908c2ecf20Sopenharmony_ci .setkey = aead_authenc_setkey, 31918c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 31928c2ecf20Sopenharmony_ci .maxauthsize = MD5_DIGEST_SIZE, 31938c2ecf20Sopenharmony_ci }, 31948c2ecf20Sopenharmony_ci .cipher_info = { 31958c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_AES, 31968c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_CBC, 31978c2ecf20Sopenharmony_ci }, 31988c2ecf20Sopenharmony_ci .auth_info = { 31998c2ecf20Sopenharmony_ci .alg = HASH_ALG_MD5, 32008c2ecf20Sopenharmony_ci .mode = HASH_MODE_HMAC, 32018c2ecf20Sopenharmony_ci }, 32028c2ecf20Sopenharmony_ci .auth_first = 0, 32038c2ecf20Sopenharmony_ci }, 32048c2ecf20Sopenharmony_ci { 32058c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD, 32068c2ecf20Sopenharmony_ci .alg.aead = { 32078c2ecf20Sopenharmony_ci .base = { 32088c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha1),cbc(aes))", 32098c2ecf20Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha1-cbc-aes-iproc", 32108c2ecf20Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 32118c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_NEED_FALLBACK | 32128c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 32138c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY 32148c2ecf20Sopenharmony_ci }, 32158c2ecf20Sopenharmony_ci .setkey = aead_authenc_setkey, 32168c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 32178c2ecf20Sopenharmony_ci .maxauthsize = SHA1_DIGEST_SIZE, 32188c2ecf20Sopenharmony_ci }, 32198c2ecf20Sopenharmony_ci .cipher_info = { 32208c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_AES, 32218c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_CBC, 32228c2ecf20Sopenharmony_ci }, 32238c2ecf20Sopenharmony_ci .auth_info = { 32248c2ecf20Sopenharmony_ci .alg = HASH_ALG_SHA1, 32258c2ecf20Sopenharmony_ci .mode = HASH_MODE_HMAC, 32268c2ecf20Sopenharmony_ci }, 32278c2ecf20Sopenharmony_ci .auth_first = 0, 32288c2ecf20Sopenharmony_ci }, 32298c2ecf20Sopenharmony_ci { 32308c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD, 32318c2ecf20Sopenharmony_ci .alg.aead = { 32328c2ecf20Sopenharmony_ci .base = { 32338c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha256),cbc(aes))", 32348c2ecf20Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha256-cbc-aes-iproc", 32358c2ecf20Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 32368c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_NEED_FALLBACK | 32378c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 32388c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY 32398c2ecf20Sopenharmony_ci }, 32408c2ecf20Sopenharmony_ci .setkey = aead_authenc_setkey, 32418c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 32428c2ecf20Sopenharmony_ci .maxauthsize = SHA256_DIGEST_SIZE, 32438c2ecf20Sopenharmony_ci }, 32448c2ecf20Sopenharmony_ci .cipher_info = { 32458c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_AES, 32468c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_CBC, 32478c2ecf20Sopenharmony_ci }, 32488c2ecf20Sopenharmony_ci .auth_info = { 32498c2ecf20Sopenharmony_ci .alg = HASH_ALG_SHA256, 32508c2ecf20Sopenharmony_ci .mode = HASH_MODE_HMAC, 32518c2ecf20Sopenharmony_ci }, 32528c2ecf20Sopenharmony_ci .auth_first = 0, 32538c2ecf20Sopenharmony_ci }, 32548c2ecf20Sopenharmony_ci { 32558c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD, 32568c2ecf20Sopenharmony_ci .alg.aead = { 32578c2ecf20Sopenharmony_ci .base = { 32588c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(md5),cbc(des))", 32598c2ecf20Sopenharmony_ci .cra_driver_name = "authenc-hmac-md5-cbc-des-iproc", 32608c2ecf20Sopenharmony_ci .cra_blocksize = DES_BLOCK_SIZE, 32618c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_NEED_FALLBACK | 32628c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 32638c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY 32648c2ecf20Sopenharmony_ci }, 32658c2ecf20Sopenharmony_ci .setkey = aead_authenc_setkey, 32668c2ecf20Sopenharmony_ci .ivsize = DES_BLOCK_SIZE, 32678c2ecf20Sopenharmony_ci .maxauthsize = MD5_DIGEST_SIZE, 32688c2ecf20Sopenharmony_ci }, 32698c2ecf20Sopenharmony_ci .cipher_info = { 32708c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_DES, 32718c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_CBC, 32728c2ecf20Sopenharmony_ci }, 32738c2ecf20Sopenharmony_ci .auth_info = { 32748c2ecf20Sopenharmony_ci .alg = HASH_ALG_MD5, 32758c2ecf20Sopenharmony_ci .mode = HASH_MODE_HMAC, 32768c2ecf20Sopenharmony_ci }, 32778c2ecf20Sopenharmony_ci .auth_first = 0, 32788c2ecf20Sopenharmony_ci }, 32798c2ecf20Sopenharmony_ci { 32808c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD, 32818c2ecf20Sopenharmony_ci .alg.aead = { 32828c2ecf20Sopenharmony_ci .base = { 32838c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha1),cbc(des))", 32848c2ecf20Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha1-cbc-des-iproc", 32858c2ecf20Sopenharmony_ci .cra_blocksize = DES_BLOCK_SIZE, 32868c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_NEED_FALLBACK | 32878c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 32888c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY 32898c2ecf20Sopenharmony_ci }, 32908c2ecf20Sopenharmony_ci .setkey = aead_authenc_setkey, 32918c2ecf20Sopenharmony_ci .ivsize = DES_BLOCK_SIZE, 32928c2ecf20Sopenharmony_ci .maxauthsize = SHA1_DIGEST_SIZE, 32938c2ecf20Sopenharmony_ci }, 32948c2ecf20Sopenharmony_ci .cipher_info = { 32958c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_DES, 32968c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_CBC, 32978c2ecf20Sopenharmony_ci }, 32988c2ecf20Sopenharmony_ci .auth_info = { 32998c2ecf20Sopenharmony_ci .alg = HASH_ALG_SHA1, 33008c2ecf20Sopenharmony_ci .mode = HASH_MODE_HMAC, 33018c2ecf20Sopenharmony_ci }, 33028c2ecf20Sopenharmony_ci .auth_first = 0, 33038c2ecf20Sopenharmony_ci }, 33048c2ecf20Sopenharmony_ci { 33058c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD, 33068c2ecf20Sopenharmony_ci .alg.aead = { 33078c2ecf20Sopenharmony_ci .base = { 33088c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha224),cbc(des))", 33098c2ecf20Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha224-cbc-des-iproc", 33108c2ecf20Sopenharmony_ci .cra_blocksize = DES_BLOCK_SIZE, 33118c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_NEED_FALLBACK | 33128c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 33138c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY 33148c2ecf20Sopenharmony_ci }, 33158c2ecf20Sopenharmony_ci .setkey = aead_authenc_setkey, 33168c2ecf20Sopenharmony_ci .ivsize = DES_BLOCK_SIZE, 33178c2ecf20Sopenharmony_ci .maxauthsize = SHA224_DIGEST_SIZE, 33188c2ecf20Sopenharmony_ci }, 33198c2ecf20Sopenharmony_ci .cipher_info = { 33208c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_DES, 33218c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_CBC, 33228c2ecf20Sopenharmony_ci }, 33238c2ecf20Sopenharmony_ci .auth_info = { 33248c2ecf20Sopenharmony_ci .alg = HASH_ALG_SHA224, 33258c2ecf20Sopenharmony_ci .mode = HASH_MODE_HMAC, 33268c2ecf20Sopenharmony_ci }, 33278c2ecf20Sopenharmony_ci .auth_first = 0, 33288c2ecf20Sopenharmony_ci }, 33298c2ecf20Sopenharmony_ci { 33308c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD, 33318c2ecf20Sopenharmony_ci .alg.aead = { 33328c2ecf20Sopenharmony_ci .base = { 33338c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha256),cbc(des))", 33348c2ecf20Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha256-cbc-des-iproc", 33358c2ecf20Sopenharmony_ci .cra_blocksize = DES_BLOCK_SIZE, 33368c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_NEED_FALLBACK | 33378c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 33388c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY 33398c2ecf20Sopenharmony_ci }, 33408c2ecf20Sopenharmony_ci .setkey = aead_authenc_setkey, 33418c2ecf20Sopenharmony_ci .ivsize = DES_BLOCK_SIZE, 33428c2ecf20Sopenharmony_ci .maxauthsize = SHA256_DIGEST_SIZE, 33438c2ecf20Sopenharmony_ci }, 33448c2ecf20Sopenharmony_ci .cipher_info = { 33458c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_DES, 33468c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_CBC, 33478c2ecf20Sopenharmony_ci }, 33488c2ecf20Sopenharmony_ci .auth_info = { 33498c2ecf20Sopenharmony_ci .alg = HASH_ALG_SHA256, 33508c2ecf20Sopenharmony_ci .mode = HASH_MODE_HMAC, 33518c2ecf20Sopenharmony_ci }, 33528c2ecf20Sopenharmony_ci .auth_first = 0, 33538c2ecf20Sopenharmony_ci }, 33548c2ecf20Sopenharmony_ci { 33558c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD, 33568c2ecf20Sopenharmony_ci .alg.aead = { 33578c2ecf20Sopenharmony_ci .base = { 33588c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha384),cbc(des))", 33598c2ecf20Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha384-cbc-des-iproc", 33608c2ecf20Sopenharmony_ci .cra_blocksize = DES_BLOCK_SIZE, 33618c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_NEED_FALLBACK | 33628c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 33638c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY 33648c2ecf20Sopenharmony_ci }, 33658c2ecf20Sopenharmony_ci .setkey = aead_authenc_setkey, 33668c2ecf20Sopenharmony_ci .ivsize = DES_BLOCK_SIZE, 33678c2ecf20Sopenharmony_ci .maxauthsize = SHA384_DIGEST_SIZE, 33688c2ecf20Sopenharmony_ci }, 33698c2ecf20Sopenharmony_ci .cipher_info = { 33708c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_DES, 33718c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_CBC, 33728c2ecf20Sopenharmony_ci }, 33738c2ecf20Sopenharmony_ci .auth_info = { 33748c2ecf20Sopenharmony_ci .alg = HASH_ALG_SHA384, 33758c2ecf20Sopenharmony_ci .mode = HASH_MODE_HMAC, 33768c2ecf20Sopenharmony_ci }, 33778c2ecf20Sopenharmony_ci .auth_first = 0, 33788c2ecf20Sopenharmony_ci }, 33798c2ecf20Sopenharmony_ci { 33808c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD, 33818c2ecf20Sopenharmony_ci .alg.aead = { 33828c2ecf20Sopenharmony_ci .base = { 33838c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha512),cbc(des))", 33848c2ecf20Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha512-cbc-des-iproc", 33858c2ecf20Sopenharmony_ci .cra_blocksize = DES_BLOCK_SIZE, 33868c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_NEED_FALLBACK | 33878c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 33888c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY 33898c2ecf20Sopenharmony_ci }, 33908c2ecf20Sopenharmony_ci .setkey = aead_authenc_setkey, 33918c2ecf20Sopenharmony_ci .ivsize = DES_BLOCK_SIZE, 33928c2ecf20Sopenharmony_ci .maxauthsize = SHA512_DIGEST_SIZE, 33938c2ecf20Sopenharmony_ci }, 33948c2ecf20Sopenharmony_ci .cipher_info = { 33958c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_DES, 33968c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_CBC, 33978c2ecf20Sopenharmony_ci }, 33988c2ecf20Sopenharmony_ci .auth_info = { 33998c2ecf20Sopenharmony_ci .alg = HASH_ALG_SHA512, 34008c2ecf20Sopenharmony_ci .mode = HASH_MODE_HMAC, 34018c2ecf20Sopenharmony_ci }, 34028c2ecf20Sopenharmony_ci .auth_first = 0, 34038c2ecf20Sopenharmony_ci }, 34048c2ecf20Sopenharmony_ci { 34058c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD, 34068c2ecf20Sopenharmony_ci .alg.aead = { 34078c2ecf20Sopenharmony_ci .base = { 34088c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(md5),cbc(des3_ede))", 34098c2ecf20Sopenharmony_ci .cra_driver_name = "authenc-hmac-md5-cbc-des3-iproc", 34108c2ecf20Sopenharmony_ci .cra_blocksize = DES3_EDE_BLOCK_SIZE, 34118c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_NEED_FALLBACK | 34128c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 34138c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY 34148c2ecf20Sopenharmony_ci }, 34158c2ecf20Sopenharmony_ci .setkey = aead_authenc_setkey, 34168c2ecf20Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 34178c2ecf20Sopenharmony_ci .maxauthsize = MD5_DIGEST_SIZE, 34188c2ecf20Sopenharmony_ci }, 34198c2ecf20Sopenharmony_ci .cipher_info = { 34208c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_3DES, 34218c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_CBC, 34228c2ecf20Sopenharmony_ci }, 34238c2ecf20Sopenharmony_ci .auth_info = { 34248c2ecf20Sopenharmony_ci .alg = HASH_ALG_MD5, 34258c2ecf20Sopenharmony_ci .mode = HASH_MODE_HMAC, 34268c2ecf20Sopenharmony_ci }, 34278c2ecf20Sopenharmony_ci .auth_first = 0, 34288c2ecf20Sopenharmony_ci }, 34298c2ecf20Sopenharmony_ci { 34308c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD, 34318c2ecf20Sopenharmony_ci .alg.aead = { 34328c2ecf20Sopenharmony_ci .base = { 34338c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha1),cbc(des3_ede))", 34348c2ecf20Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha1-cbc-des3-iproc", 34358c2ecf20Sopenharmony_ci .cra_blocksize = DES3_EDE_BLOCK_SIZE, 34368c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_NEED_FALLBACK | 34378c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 34388c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY 34398c2ecf20Sopenharmony_ci }, 34408c2ecf20Sopenharmony_ci .setkey = aead_authenc_setkey, 34418c2ecf20Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 34428c2ecf20Sopenharmony_ci .maxauthsize = SHA1_DIGEST_SIZE, 34438c2ecf20Sopenharmony_ci }, 34448c2ecf20Sopenharmony_ci .cipher_info = { 34458c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_3DES, 34468c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_CBC, 34478c2ecf20Sopenharmony_ci }, 34488c2ecf20Sopenharmony_ci .auth_info = { 34498c2ecf20Sopenharmony_ci .alg = HASH_ALG_SHA1, 34508c2ecf20Sopenharmony_ci .mode = HASH_MODE_HMAC, 34518c2ecf20Sopenharmony_ci }, 34528c2ecf20Sopenharmony_ci .auth_first = 0, 34538c2ecf20Sopenharmony_ci }, 34548c2ecf20Sopenharmony_ci { 34558c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD, 34568c2ecf20Sopenharmony_ci .alg.aead = { 34578c2ecf20Sopenharmony_ci .base = { 34588c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha224),cbc(des3_ede))", 34598c2ecf20Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha224-cbc-des3-iproc", 34608c2ecf20Sopenharmony_ci .cra_blocksize = DES3_EDE_BLOCK_SIZE, 34618c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_NEED_FALLBACK | 34628c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 34638c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY 34648c2ecf20Sopenharmony_ci }, 34658c2ecf20Sopenharmony_ci .setkey = aead_authenc_setkey, 34668c2ecf20Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 34678c2ecf20Sopenharmony_ci .maxauthsize = SHA224_DIGEST_SIZE, 34688c2ecf20Sopenharmony_ci }, 34698c2ecf20Sopenharmony_ci .cipher_info = { 34708c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_3DES, 34718c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_CBC, 34728c2ecf20Sopenharmony_ci }, 34738c2ecf20Sopenharmony_ci .auth_info = { 34748c2ecf20Sopenharmony_ci .alg = HASH_ALG_SHA224, 34758c2ecf20Sopenharmony_ci .mode = HASH_MODE_HMAC, 34768c2ecf20Sopenharmony_ci }, 34778c2ecf20Sopenharmony_ci .auth_first = 0, 34788c2ecf20Sopenharmony_ci }, 34798c2ecf20Sopenharmony_ci { 34808c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD, 34818c2ecf20Sopenharmony_ci .alg.aead = { 34828c2ecf20Sopenharmony_ci .base = { 34838c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha256),cbc(des3_ede))", 34848c2ecf20Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha256-cbc-des3-iproc", 34858c2ecf20Sopenharmony_ci .cra_blocksize = DES3_EDE_BLOCK_SIZE, 34868c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_NEED_FALLBACK | 34878c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 34888c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY 34898c2ecf20Sopenharmony_ci }, 34908c2ecf20Sopenharmony_ci .setkey = aead_authenc_setkey, 34918c2ecf20Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 34928c2ecf20Sopenharmony_ci .maxauthsize = SHA256_DIGEST_SIZE, 34938c2ecf20Sopenharmony_ci }, 34948c2ecf20Sopenharmony_ci .cipher_info = { 34958c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_3DES, 34968c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_CBC, 34978c2ecf20Sopenharmony_ci }, 34988c2ecf20Sopenharmony_ci .auth_info = { 34998c2ecf20Sopenharmony_ci .alg = HASH_ALG_SHA256, 35008c2ecf20Sopenharmony_ci .mode = HASH_MODE_HMAC, 35018c2ecf20Sopenharmony_ci }, 35028c2ecf20Sopenharmony_ci .auth_first = 0, 35038c2ecf20Sopenharmony_ci }, 35048c2ecf20Sopenharmony_ci { 35058c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD, 35068c2ecf20Sopenharmony_ci .alg.aead = { 35078c2ecf20Sopenharmony_ci .base = { 35088c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha384),cbc(des3_ede))", 35098c2ecf20Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha384-cbc-des3-iproc", 35108c2ecf20Sopenharmony_ci .cra_blocksize = DES3_EDE_BLOCK_SIZE, 35118c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_NEED_FALLBACK | 35128c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 35138c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY 35148c2ecf20Sopenharmony_ci }, 35158c2ecf20Sopenharmony_ci .setkey = aead_authenc_setkey, 35168c2ecf20Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 35178c2ecf20Sopenharmony_ci .maxauthsize = SHA384_DIGEST_SIZE, 35188c2ecf20Sopenharmony_ci }, 35198c2ecf20Sopenharmony_ci .cipher_info = { 35208c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_3DES, 35218c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_CBC, 35228c2ecf20Sopenharmony_ci }, 35238c2ecf20Sopenharmony_ci .auth_info = { 35248c2ecf20Sopenharmony_ci .alg = HASH_ALG_SHA384, 35258c2ecf20Sopenharmony_ci .mode = HASH_MODE_HMAC, 35268c2ecf20Sopenharmony_ci }, 35278c2ecf20Sopenharmony_ci .auth_first = 0, 35288c2ecf20Sopenharmony_ci }, 35298c2ecf20Sopenharmony_ci { 35308c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD, 35318c2ecf20Sopenharmony_ci .alg.aead = { 35328c2ecf20Sopenharmony_ci .base = { 35338c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha512),cbc(des3_ede))", 35348c2ecf20Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha512-cbc-des3-iproc", 35358c2ecf20Sopenharmony_ci .cra_blocksize = DES3_EDE_BLOCK_SIZE, 35368c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_NEED_FALLBACK | 35378c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 35388c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY 35398c2ecf20Sopenharmony_ci }, 35408c2ecf20Sopenharmony_ci .setkey = aead_authenc_setkey, 35418c2ecf20Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 35428c2ecf20Sopenharmony_ci .maxauthsize = SHA512_DIGEST_SIZE, 35438c2ecf20Sopenharmony_ci }, 35448c2ecf20Sopenharmony_ci .cipher_info = { 35458c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_3DES, 35468c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_CBC, 35478c2ecf20Sopenharmony_ci }, 35488c2ecf20Sopenharmony_ci .auth_info = { 35498c2ecf20Sopenharmony_ci .alg = HASH_ALG_SHA512, 35508c2ecf20Sopenharmony_ci .mode = HASH_MODE_HMAC, 35518c2ecf20Sopenharmony_ci }, 35528c2ecf20Sopenharmony_ci .auth_first = 0, 35538c2ecf20Sopenharmony_ci }, 35548c2ecf20Sopenharmony_ci 35558c2ecf20Sopenharmony_ci/* SKCIPHER algorithms. */ 35568c2ecf20Sopenharmony_ci { 35578c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_SKCIPHER, 35588c2ecf20Sopenharmony_ci .alg.skcipher = { 35598c2ecf20Sopenharmony_ci .base.cra_name = "ofb(des)", 35608c2ecf20Sopenharmony_ci .base.cra_driver_name = "ofb-des-iproc", 35618c2ecf20Sopenharmony_ci .base.cra_blocksize = DES_BLOCK_SIZE, 35628c2ecf20Sopenharmony_ci .min_keysize = DES_KEY_SIZE, 35638c2ecf20Sopenharmony_ci .max_keysize = DES_KEY_SIZE, 35648c2ecf20Sopenharmony_ci .ivsize = DES_BLOCK_SIZE, 35658c2ecf20Sopenharmony_ci }, 35668c2ecf20Sopenharmony_ci .cipher_info = { 35678c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_DES, 35688c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_OFB, 35698c2ecf20Sopenharmony_ci }, 35708c2ecf20Sopenharmony_ci .auth_info = { 35718c2ecf20Sopenharmony_ci .alg = HASH_ALG_NONE, 35728c2ecf20Sopenharmony_ci .mode = HASH_MODE_NONE, 35738c2ecf20Sopenharmony_ci }, 35748c2ecf20Sopenharmony_ci }, 35758c2ecf20Sopenharmony_ci { 35768c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_SKCIPHER, 35778c2ecf20Sopenharmony_ci .alg.skcipher = { 35788c2ecf20Sopenharmony_ci .base.cra_name = "cbc(des)", 35798c2ecf20Sopenharmony_ci .base.cra_driver_name = "cbc-des-iproc", 35808c2ecf20Sopenharmony_ci .base.cra_blocksize = DES_BLOCK_SIZE, 35818c2ecf20Sopenharmony_ci .min_keysize = DES_KEY_SIZE, 35828c2ecf20Sopenharmony_ci .max_keysize = DES_KEY_SIZE, 35838c2ecf20Sopenharmony_ci .ivsize = DES_BLOCK_SIZE, 35848c2ecf20Sopenharmony_ci }, 35858c2ecf20Sopenharmony_ci .cipher_info = { 35868c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_DES, 35878c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_CBC, 35888c2ecf20Sopenharmony_ci }, 35898c2ecf20Sopenharmony_ci .auth_info = { 35908c2ecf20Sopenharmony_ci .alg = HASH_ALG_NONE, 35918c2ecf20Sopenharmony_ci .mode = HASH_MODE_NONE, 35928c2ecf20Sopenharmony_ci }, 35938c2ecf20Sopenharmony_ci }, 35948c2ecf20Sopenharmony_ci { 35958c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_SKCIPHER, 35968c2ecf20Sopenharmony_ci .alg.skcipher = { 35978c2ecf20Sopenharmony_ci .base.cra_name = "ecb(des)", 35988c2ecf20Sopenharmony_ci .base.cra_driver_name = "ecb-des-iproc", 35998c2ecf20Sopenharmony_ci .base.cra_blocksize = DES_BLOCK_SIZE, 36008c2ecf20Sopenharmony_ci .min_keysize = DES_KEY_SIZE, 36018c2ecf20Sopenharmony_ci .max_keysize = DES_KEY_SIZE, 36028c2ecf20Sopenharmony_ci .ivsize = 0, 36038c2ecf20Sopenharmony_ci }, 36048c2ecf20Sopenharmony_ci .cipher_info = { 36058c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_DES, 36068c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_ECB, 36078c2ecf20Sopenharmony_ci }, 36088c2ecf20Sopenharmony_ci .auth_info = { 36098c2ecf20Sopenharmony_ci .alg = HASH_ALG_NONE, 36108c2ecf20Sopenharmony_ci .mode = HASH_MODE_NONE, 36118c2ecf20Sopenharmony_ci }, 36128c2ecf20Sopenharmony_ci }, 36138c2ecf20Sopenharmony_ci { 36148c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_SKCIPHER, 36158c2ecf20Sopenharmony_ci .alg.skcipher = { 36168c2ecf20Sopenharmony_ci .base.cra_name = "ofb(des3_ede)", 36178c2ecf20Sopenharmony_ci .base.cra_driver_name = "ofb-des3-iproc", 36188c2ecf20Sopenharmony_ci .base.cra_blocksize = DES3_EDE_BLOCK_SIZE, 36198c2ecf20Sopenharmony_ci .min_keysize = DES3_EDE_KEY_SIZE, 36208c2ecf20Sopenharmony_ci .max_keysize = DES3_EDE_KEY_SIZE, 36218c2ecf20Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 36228c2ecf20Sopenharmony_ci }, 36238c2ecf20Sopenharmony_ci .cipher_info = { 36248c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_3DES, 36258c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_OFB, 36268c2ecf20Sopenharmony_ci }, 36278c2ecf20Sopenharmony_ci .auth_info = { 36288c2ecf20Sopenharmony_ci .alg = HASH_ALG_NONE, 36298c2ecf20Sopenharmony_ci .mode = HASH_MODE_NONE, 36308c2ecf20Sopenharmony_ci }, 36318c2ecf20Sopenharmony_ci }, 36328c2ecf20Sopenharmony_ci { 36338c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_SKCIPHER, 36348c2ecf20Sopenharmony_ci .alg.skcipher = { 36358c2ecf20Sopenharmony_ci .base.cra_name = "cbc(des3_ede)", 36368c2ecf20Sopenharmony_ci .base.cra_driver_name = "cbc-des3-iproc", 36378c2ecf20Sopenharmony_ci .base.cra_blocksize = DES3_EDE_BLOCK_SIZE, 36388c2ecf20Sopenharmony_ci .min_keysize = DES3_EDE_KEY_SIZE, 36398c2ecf20Sopenharmony_ci .max_keysize = DES3_EDE_KEY_SIZE, 36408c2ecf20Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 36418c2ecf20Sopenharmony_ci }, 36428c2ecf20Sopenharmony_ci .cipher_info = { 36438c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_3DES, 36448c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_CBC, 36458c2ecf20Sopenharmony_ci }, 36468c2ecf20Sopenharmony_ci .auth_info = { 36478c2ecf20Sopenharmony_ci .alg = HASH_ALG_NONE, 36488c2ecf20Sopenharmony_ci .mode = HASH_MODE_NONE, 36498c2ecf20Sopenharmony_ci }, 36508c2ecf20Sopenharmony_ci }, 36518c2ecf20Sopenharmony_ci { 36528c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_SKCIPHER, 36538c2ecf20Sopenharmony_ci .alg.skcipher = { 36548c2ecf20Sopenharmony_ci .base.cra_name = "ecb(des3_ede)", 36558c2ecf20Sopenharmony_ci .base.cra_driver_name = "ecb-des3-iproc", 36568c2ecf20Sopenharmony_ci .base.cra_blocksize = DES3_EDE_BLOCK_SIZE, 36578c2ecf20Sopenharmony_ci .min_keysize = DES3_EDE_KEY_SIZE, 36588c2ecf20Sopenharmony_ci .max_keysize = DES3_EDE_KEY_SIZE, 36598c2ecf20Sopenharmony_ci .ivsize = 0, 36608c2ecf20Sopenharmony_ci }, 36618c2ecf20Sopenharmony_ci .cipher_info = { 36628c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_3DES, 36638c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_ECB, 36648c2ecf20Sopenharmony_ci }, 36658c2ecf20Sopenharmony_ci .auth_info = { 36668c2ecf20Sopenharmony_ci .alg = HASH_ALG_NONE, 36678c2ecf20Sopenharmony_ci .mode = HASH_MODE_NONE, 36688c2ecf20Sopenharmony_ci }, 36698c2ecf20Sopenharmony_ci }, 36708c2ecf20Sopenharmony_ci { 36718c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_SKCIPHER, 36728c2ecf20Sopenharmony_ci .alg.skcipher = { 36738c2ecf20Sopenharmony_ci .base.cra_name = "ofb(aes)", 36748c2ecf20Sopenharmony_ci .base.cra_driver_name = "ofb-aes-iproc", 36758c2ecf20Sopenharmony_ci .base.cra_blocksize = AES_BLOCK_SIZE, 36768c2ecf20Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 36778c2ecf20Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 36788c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 36798c2ecf20Sopenharmony_ci }, 36808c2ecf20Sopenharmony_ci .cipher_info = { 36818c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_AES, 36828c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_OFB, 36838c2ecf20Sopenharmony_ci }, 36848c2ecf20Sopenharmony_ci .auth_info = { 36858c2ecf20Sopenharmony_ci .alg = HASH_ALG_NONE, 36868c2ecf20Sopenharmony_ci .mode = HASH_MODE_NONE, 36878c2ecf20Sopenharmony_ci }, 36888c2ecf20Sopenharmony_ci }, 36898c2ecf20Sopenharmony_ci { 36908c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_SKCIPHER, 36918c2ecf20Sopenharmony_ci .alg.skcipher = { 36928c2ecf20Sopenharmony_ci .base.cra_name = "cbc(aes)", 36938c2ecf20Sopenharmony_ci .base.cra_driver_name = "cbc-aes-iproc", 36948c2ecf20Sopenharmony_ci .base.cra_blocksize = AES_BLOCK_SIZE, 36958c2ecf20Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 36968c2ecf20Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 36978c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 36988c2ecf20Sopenharmony_ci }, 36998c2ecf20Sopenharmony_ci .cipher_info = { 37008c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_AES, 37018c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_CBC, 37028c2ecf20Sopenharmony_ci }, 37038c2ecf20Sopenharmony_ci .auth_info = { 37048c2ecf20Sopenharmony_ci .alg = HASH_ALG_NONE, 37058c2ecf20Sopenharmony_ci .mode = HASH_MODE_NONE, 37068c2ecf20Sopenharmony_ci }, 37078c2ecf20Sopenharmony_ci }, 37088c2ecf20Sopenharmony_ci { 37098c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_SKCIPHER, 37108c2ecf20Sopenharmony_ci .alg.skcipher = { 37118c2ecf20Sopenharmony_ci .base.cra_name = "ecb(aes)", 37128c2ecf20Sopenharmony_ci .base.cra_driver_name = "ecb-aes-iproc", 37138c2ecf20Sopenharmony_ci .base.cra_blocksize = AES_BLOCK_SIZE, 37148c2ecf20Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 37158c2ecf20Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 37168c2ecf20Sopenharmony_ci .ivsize = 0, 37178c2ecf20Sopenharmony_ci }, 37188c2ecf20Sopenharmony_ci .cipher_info = { 37198c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_AES, 37208c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_ECB, 37218c2ecf20Sopenharmony_ci }, 37228c2ecf20Sopenharmony_ci .auth_info = { 37238c2ecf20Sopenharmony_ci .alg = HASH_ALG_NONE, 37248c2ecf20Sopenharmony_ci .mode = HASH_MODE_NONE, 37258c2ecf20Sopenharmony_ci }, 37268c2ecf20Sopenharmony_ci }, 37278c2ecf20Sopenharmony_ci { 37288c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_SKCIPHER, 37298c2ecf20Sopenharmony_ci .alg.skcipher = { 37308c2ecf20Sopenharmony_ci .base.cra_name = "ctr(aes)", 37318c2ecf20Sopenharmony_ci .base.cra_driver_name = "ctr-aes-iproc", 37328c2ecf20Sopenharmony_ci .base.cra_blocksize = AES_BLOCK_SIZE, 37338c2ecf20Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 37348c2ecf20Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 37358c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 37368c2ecf20Sopenharmony_ci }, 37378c2ecf20Sopenharmony_ci .cipher_info = { 37388c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_AES, 37398c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_CTR, 37408c2ecf20Sopenharmony_ci }, 37418c2ecf20Sopenharmony_ci .auth_info = { 37428c2ecf20Sopenharmony_ci .alg = HASH_ALG_NONE, 37438c2ecf20Sopenharmony_ci .mode = HASH_MODE_NONE, 37448c2ecf20Sopenharmony_ci }, 37458c2ecf20Sopenharmony_ci }, 37468c2ecf20Sopenharmony_ci{ 37478c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_SKCIPHER, 37488c2ecf20Sopenharmony_ci .alg.skcipher = { 37498c2ecf20Sopenharmony_ci .base.cra_name = "xts(aes)", 37508c2ecf20Sopenharmony_ci .base.cra_driver_name = "xts-aes-iproc", 37518c2ecf20Sopenharmony_ci .base.cra_blocksize = AES_BLOCK_SIZE, 37528c2ecf20Sopenharmony_ci .min_keysize = 2 * AES_MIN_KEY_SIZE, 37538c2ecf20Sopenharmony_ci .max_keysize = 2 * AES_MAX_KEY_SIZE, 37548c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 37558c2ecf20Sopenharmony_ci }, 37568c2ecf20Sopenharmony_ci .cipher_info = { 37578c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_AES, 37588c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_XTS, 37598c2ecf20Sopenharmony_ci }, 37608c2ecf20Sopenharmony_ci .auth_info = { 37618c2ecf20Sopenharmony_ci .alg = HASH_ALG_NONE, 37628c2ecf20Sopenharmony_ci .mode = HASH_MODE_NONE, 37638c2ecf20Sopenharmony_ci }, 37648c2ecf20Sopenharmony_ci }, 37658c2ecf20Sopenharmony_ci 37668c2ecf20Sopenharmony_ci/* AHASH algorithms. */ 37678c2ecf20Sopenharmony_ci { 37688c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AHASH, 37698c2ecf20Sopenharmony_ci .alg.hash = { 37708c2ecf20Sopenharmony_ci .halg.digestsize = MD5_DIGEST_SIZE, 37718c2ecf20Sopenharmony_ci .halg.base = { 37728c2ecf20Sopenharmony_ci .cra_name = "md5", 37738c2ecf20Sopenharmony_ci .cra_driver_name = "md5-iproc", 37748c2ecf20Sopenharmony_ci .cra_blocksize = MD5_BLOCK_WORDS * 4, 37758c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 37768c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 37778c2ecf20Sopenharmony_ci } 37788c2ecf20Sopenharmony_ci }, 37798c2ecf20Sopenharmony_ci .cipher_info = { 37808c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_NONE, 37818c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_NONE, 37828c2ecf20Sopenharmony_ci }, 37838c2ecf20Sopenharmony_ci .auth_info = { 37848c2ecf20Sopenharmony_ci .alg = HASH_ALG_MD5, 37858c2ecf20Sopenharmony_ci .mode = HASH_MODE_HASH, 37868c2ecf20Sopenharmony_ci }, 37878c2ecf20Sopenharmony_ci }, 37888c2ecf20Sopenharmony_ci { 37898c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AHASH, 37908c2ecf20Sopenharmony_ci .alg.hash = { 37918c2ecf20Sopenharmony_ci .halg.digestsize = MD5_DIGEST_SIZE, 37928c2ecf20Sopenharmony_ci .halg.base = { 37938c2ecf20Sopenharmony_ci .cra_name = "hmac(md5)", 37948c2ecf20Sopenharmony_ci .cra_driver_name = "hmac-md5-iproc", 37958c2ecf20Sopenharmony_ci .cra_blocksize = MD5_BLOCK_WORDS * 4, 37968c2ecf20Sopenharmony_ci } 37978c2ecf20Sopenharmony_ci }, 37988c2ecf20Sopenharmony_ci .cipher_info = { 37998c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_NONE, 38008c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_NONE, 38018c2ecf20Sopenharmony_ci }, 38028c2ecf20Sopenharmony_ci .auth_info = { 38038c2ecf20Sopenharmony_ci .alg = HASH_ALG_MD5, 38048c2ecf20Sopenharmony_ci .mode = HASH_MODE_HMAC, 38058c2ecf20Sopenharmony_ci }, 38068c2ecf20Sopenharmony_ci }, 38078c2ecf20Sopenharmony_ci {.type = CRYPTO_ALG_TYPE_AHASH, 38088c2ecf20Sopenharmony_ci .alg.hash = { 38098c2ecf20Sopenharmony_ci .halg.digestsize = SHA1_DIGEST_SIZE, 38108c2ecf20Sopenharmony_ci .halg.base = { 38118c2ecf20Sopenharmony_ci .cra_name = "sha1", 38128c2ecf20Sopenharmony_ci .cra_driver_name = "sha1-iproc", 38138c2ecf20Sopenharmony_ci .cra_blocksize = SHA1_BLOCK_SIZE, 38148c2ecf20Sopenharmony_ci } 38158c2ecf20Sopenharmony_ci }, 38168c2ecf20Sopenharmony_ci .cipher_info = { 38178c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_NONE, 38188c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_NONE, 38198c2ecf20Sopenharmony_ci }, 38208c2ecf20Sopenharmony_ci .auth_info = { 38218c2ecf20Sopenharmony_ci .alg = HASH_ALG_SHA1, 38228c2ecf20Sopenharmony_ci .mode = HASH_MODE_HASH, 38238c2ecf20Sopenharmony_ci }, 38248c2ecf20Sopenharmony_ci }, 38258c2ecf20Sopenharmony_ci {.type = CRYPTO_ALG_TYPE_AHASH, 38268c2ecf20Sopenharmony_ci .alg.hash = { 38278c2ecf20Sopenharmony_ci .halg.digestsize = SHA1_DIGEST_SIZE, 38288c2ecf20Sopenharmony_ci .halg.base = { 38298c2ecf20Sopenharmony_ci .cra_name = "hmac(sha1)", 38308c2ecf20Sopenharmony_ci .cra_driver_name = "hmac-sha1-iproc", 38318c2ecf20Sopenharmony_ci .cra_blocksize = SHA1_BLOCK_SIZE, 38328c2ecf20Sopenharmony_ci } 38338c2ecf20Sopenharmony_ci }, 38348c2ecf20Sopenharmony_ci .cipher_info = { 38358c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_NONE, 38368c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_NONE, 38378c2ecf20Sopenharmony_ci }, 38388c2ecf20Sopenharmony_ci .auth_info = { 38398c2ecf20Sopenharmony_ci .alg = HASH_ALG_SHA1, 38408c2ecf20Sopenharmony_ci .mode = HASH_MODE_HMAC, 38418c2ecf20Sopenharmony_ci }, 38428c2ecf20Sopenharmony_ci }, 38438c2ecf20Sopenharmony_ci {.type = CRYPTO_ALG_TYPE_AHASH, 38448c2ecf20Sopenharmony_ci .alg.hash = { 38458c2ecf20Sopenharmony_ci .halg.digestsize = SHA224_DIGEST_SIZE, 38468c2ecf20Sopenharmony_ci .halg.base = { 38478c2ecf20Sopenharmony_ci .cra_name = "sha224", 38488c2ecf20Sopenharmony_ci .cra_driver_name = "sha224-iproc", 38498c2ecf20Sopenharmony_ci .cra_blocksize = SHA224_BLOCK_SIZE, 38508c2ecf20Sopenharmony_ci } 38518c2ecf20Sopenharmony_ci }, 38528c2ecf20Sopenharmony_ci .cipher_info = { 38538c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_NONE, 38548c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_NONE, 38558c2ecf20Sopenharmony_ci }, 38568c2ecf20Sopenharmony_ci .auth_info = { 38578c2ecf20Sopenharmony_ci .alg = HASH_ALG_SHA224, 38588c2ecf20Sopenharmony_ci .mode = HASH_MODE_HASH, 38598c2ecf20Sopenharmony_ci }, 38608c2ecf20Sopenharmony_ci }, 38618c2ecf20Sopenharmony_ci {.type = CRYPTO_ALG_TYPE_AHASH, 38628c2ecf20Sopenharmony_ci .alg.hash = { 38638c2ecf20Sopenharmony_ci .halg.digestsize = SHA224_DIGEST_SIZE, 38648c2ecf20Sopenharmony_ci .halg.base = { 38658c2ecf20Sopenharmony_ci .cra_name = "hmac(sha224)", 38668c2ecf20Sopenharmony_ci .cra_driver_name = "hmac-sha224-iproc", 38678c2ecf20Sopenharmony_ci .cra_blocksize = SHA224_BLOCK_SIZE, 38688c2ecf20Sopenharmony_ci } 38698c2ecf20Sopenharmony_ci }, 38708c2ecf20Sopenharmony_ci .cipher_info = { 38718c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_NONE, 38728c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_NONE, 38738c2ecf20Sopenharmony_ci }, 38748c2ecf20Sopenharmony_ci .auth_info = { 38758c2ecf20Sopenharmony_ci .alg = HASH_ALG_SHA224, 38768c2ecf20Sopenharmony_ci .mode = HASH_MODE_HMAC, 38778c2ecf20Sopenharmony_ci }, 38788c2ecf20Sopenharmony_ci }, 38798c2ecf20Sopenharmony_ci {.type = CRYPTO_ALG_TYPE_AHASH, 38808c2ecf20Sopenharmony_ci .alg.hash = { 38818c2ecf20Sopenharmony_ci .halg.digestsize = SHA256_DIGEST_SIZE, 38828c2ecf20Sopenharmony_ci .halg.base = { 38838c2ecf20Sopenharmony_ci .cra_name = "sha256", 38848c2ecf20Sopenharmony_ci .cra_driver_name = "sha256-iproc", 38858c2ecf20Sopenharmony_ci .cra_blocksize = SHA256_BLOCK_SIZE, 38868c2ecf20Sopenharmony_ci } 38878c2ecf20Sopenharmony_ci }, 38888c2ecf20Sopenharmony_ci .cipher_info = { 38898c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_NONE, 38908c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_NONE, 38918c2ecf20Sopenharmony_ci }, 38928c2ecf20Sopenharmony_ci .auth_info = { 38938c2ecf20Sopenharmony_ci .alg = HASH_ALG_SHA256, 38948c2ecf20Sopenharmony_ci .mode = HASH_MODE_HASH, 38958c2ecf20Sopenharmony_ci }, 38968c2ecf20Sopenharmony_ci }, 38978c2ecf20Sopenharmony_ci {.type = CRYPTO_ALG_TYPE_AHASH, 38988c2ecf20Sopenharmony_ci .alg.hash = { 38998c2ecf20Sopenharmony_ci .halg.digestsize = SHA256_DIGEST_SIZE, 39008c2ecf20Sopenharmony_ci .halg.base = { 39018c2ecf20Sopenharmony_ci .cra_name = "hmac(sha256)", 39028c2ecf20Sopenharmony_ci .cra_driver_name = "hmac-sha256-iproc", 39038c2ecf20Sopenharmony_ci .cra_blocksize = SHA256_BLOCK_SIZE, 39048c2ecf20Sopenharmony_ci } 39058c2ecf20Sopenharmony_ci }, 39068c2ecf20Sopenharmony_ci .cipher_info = { 39078c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_NONE, 39088c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_NONE, 39098c2ecf20Sopenharmony_ci }, 39108c2ecf20Sopenharmony_ci .auth_info = { 39118c2ecf20Sopenharmony_ci .alg = HASH_ALG_SHA256, 39128c2ecf20Sopenharmony_ci .mode = HASH_MODE_HMAC, 39138c2ecf20Sopenharmony_ci }, 39148c2ecf20Sopenharmony_ci }, 39158c2ecf20Sopenharmony_ci { 39168c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AHASH, 39178c2ecf20Sopenharmony_ci .alg.hash = { 39188c2ecf20Sopenharmony_ci .halg.digestsize = SHA384_DIGEST_SIZE, 39198c2ecf20Sopenharmony_ci .halg.base = { 39208c2ecf20Sopenharmony_ci .cra_name = "sha384", 39218c2ecf20Sopenharmony_ci .cra_driver_name = "sha384-iproc", 39228c2ecf20Sopenharmony_ci .cra_blocksize = SHA384_BLOCK_SIZE, 39238c2ecf20Sopenharmony_ci } 39248c2ecf20Sopenharmony_ci }, 39258c2ecf20Sopenharmony_ci .cipher_info = { 39268c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_NONE, 39278c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_NONE, 39288c2ecf20Sopenharmony_ci }, 39298c2ecf20Sopenharmony_ci .auth_info = { 39308c2ecf20Sopenharmony_ci .alg = HASH_ALG_SHA384, 39318c2ecf20Sopenharmony_ci .mode = HASH_MODE_HASH, 39328c2ecf20Sopenharmony_ci }, 39338c2ecf20Sopenharmony_ci }, 39348c2ecf20Sopenharmony_ci { 39358c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AHASH, 39368c2ecf20Sopenharmony_ci .alg.hash = { 39378c2ecf20Sopenharmony_ci .halg.digestsize = SHA384_DIGEST_SIZE, 39388c2ecf20Sopenharmony_ci .halg.base = { 39398c2ecf20Sopenharmony_ci .cra_name = "hmac(sha384)", 39408c2ecf20Sopenharmony_ci .cra_driver_name = "hmac-sha384-iproc", 39418c2ecf20Sopenharmony_ci .cra_blocksize = SHA384_BLOCK_SIZE, 39428c2ecf20Sopenharmony_ci } 39438c2ecf20Sopenharmony_ci }, 39448c2ecf20Sopenharmony_ci .cipher_info = { 39458c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_NONE, 39468c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_NONE, 39478c2ecf20Sopenharmony_ci }, 39488c2ecf20Sopenharmony_ci .auth_info = { 39498c2ecf20Sopenharmony_ci .alg = HASH_ALG_SHA384, 39508c2ecf20Sopenharmony_ci .mode = HASH_MODE_HMAC, 39518c2ecf20Sopenharmony_ci }, 39528c2ecf20Sopenharmony_ci }, 39538c2ecf20Sopenharmony_ci { 39548c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AHASH, 39558c2ecf20Sopenharmony_ci .alg.hash = { 39568c2ecf20Sopenharmony_ci .halg.digestsize = SHA512_DIGEST_SIZE, 39578c2ecf20Sopenharmony_ci .halg.base = { 39588c2ecf20Sopenharmony_ci .cra_name = "sha512", 39598c2ecf20Sopenharmony_ci .cra_driver_name = "sha512-iproc", 39608c2ecf20Sopenharmony_ci .cra_blocksize = SHA512_BLOCK_SIZE, 39618c2ecf20Sopenharmony_ci } 39628c2ecf20Sopenharmony_ci }, 39638c2ecf20Sopenharmony_ci .cipher_info = { 39648c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_NONE, 39658c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_NONE, 39668c2ecf20Sopenharmony_ci }, 39678c2ecf20Sopenharmony_ci .auth_info = { 39688c2ecf20Sopenharmony_ci .alg = HASH_ALG_SHA512, 39698c2ecf20Sopenharmony_ci .mode = HASH_MODE_HASH, 39708c2ecf20Sopenharmony_ci }, 39718c2ecf20Sopenharmony_ci }, 39728c2ecf20Sopenharmony_ci { 39738c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AHASH, 39748c2ecf20Sopenharmony_ci .alg.hash = { 39758c2ecf20Sopenharmony_ci .halg.digestsize = SHA512_DIGEST_SIZE, 39768c2ecf20Sopenharmony_ci .halg.base = { 39778c2ecf20Sopenharmony_ci .cra_name = "hmac(sha512)", 39788c2ecf20Sopenharmony_ci .cra_driver_name = "hmac-sha512-iproc", 39798c2ecf20Sopenharmony_ci .cra_blocksize = SHA512_BLOCK_SIZE, 39808c2ecf20Sopenharmony_ci } 39818c2ecf20Sopenharmony_ci }, 39828c2ecf20Sopenharmony_ci .cipher_info = { 39838c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_NONE, 39848c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_NONE, 39858c2ecf20Sopenharmony_ci }, 39868c2ecf20Sopenharmony_ci .auth_info = { 39878c2ecf20Sopenharmony_ci .alg = HASH_ALG_SHA512, 39888c2ecf20Sopenharmony_ci .mode = HASH_MODE_HMAC, 39898c2ecf20Sopenharmony_ci }, 39908c2ecf20Sopenharmony_ci }, 39918c2ecf20Sopenharmony_ci { 39928c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AHASH, 39938c2ecf20Sopenharmony_ci .alg.hash = { 39948c2ecf20Sopenharmony_ci .halg.digestsize = SHA3_224_DIGEST_SIZE, 39958c2ecf20Sopenharmony_ci .halg.base = { 39968c2ecf20Sopenharmony_ci .cra_name = "sha3-224", 39978c2ecf20Sopenharmony_ci .cra_driver_name = "sha3-224-iproc", 39988c2ecf20Sopenharmony_ci .cra_blocksize = SHA3_224_BLOCK_SIZE, 39998c2ecf20Sopenharmony_ci } 40008c2ecf20Sopenharmony_ci }, 40018c2ecf20Sopenharmony_ci .cipher_info = { 40028c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_NONE, 40038c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_NONE, 40048c2ecf20Sopenharmony_ci }, 40058c2ecf20Sopenharmony_ci .auth_info = { 40068c2ecf20Sopenharmony_ci .alg = HASH_ALG_SHA3_224, 40078c2ecf20Sopenharmony_ci .mode = HASH_MODE_HASH, 40088c2ecf20Sopenharmony_ci }, 40098c2ecf20Sopenharmony_ci }, 40108c2ecf20Sopenharmony_ci { 40118c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AHASH, 40128c2ecf20Sopenharmony_ci .alg.hash = { 40138c2ecf20Sopenharmony_ci .halg.digestsize = SHA3_224_DIGEST_SIZE, 40148c2ecf20Sopenharmony_ci .halg.base = { 40158c2ecf20Sopenharmony_ci .cra_name = "hmac(sha3-224)", 40168c2ecf20Sopenharmony_ci .cra_driver_name = "hmac-sha3-224-iproc", 40178c2ecf20Sopenharmony_ci .cra_blocksize = SHA3_224_BLOCK_SIZE, 40188c2ecf20Sopenharmony_ci } 40198c2ecf20Sopenharmony_ci }, 40208c2ecf20Sopenharmony_ci .cipher_info = { 40218c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_NONE, 40228c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_NONE, 40238c2ecf20Sopenharmony_ci }, 40248c2ecf20Sopenharmony_ci .auth_info = { 40258c2ecf20Sopenharmony_ci .alg = HASH_ALG_SHA3_224, 40268c2ecf20Sopenharmony_ci .mode = HASH_MODE_HMAC 40278c2ecf20Sopenharmony_ci }, 40288c2ecf20Sopenharmony_ci }, 40298c2ecf20Sopenharmony_ci { 40308c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AHASH, 40318c2ecf20Sopenharmony_ci .alg.hash = { 40328c2ecf20Sopenharmony_ci .halg.digestsize = SHA3_256_DIGEST_SIZE, 40338c2ecf20Sopenharmony_ci .halg.base = { 40348c2ecf20Sopenharmony_ci .cra_name = "sha3-256", 40358c2ecf20Sopenharmony_ci .cra_driver_name = "sha3-256-iproc", 40368c2ecf20Sopenharmony_ci .cra_blocksize = SHA3_256_BLOCK_SIZE, 40378c2ecf20Sopenharmony_ci } 40388c2ecf20Sopenharmony_ci }, 40398c2ecf20Sopenharmony_ci .cipher_info = { 40408c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_NONE, 40418c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_NONE, 40428c2ecf20Sopenharmony_ci }, 40438c2ecf20Sopenharmony_ci .auth_info = { 40448c2ecf20Sopenharmony_ci .alg = HASH_ALG_SHA3_256, 40458c2ecf20Sopenharmony_ci .mode = HASH_MODE_HASH, 40468c2ecf20Sopenharmony_ci }, 40478c2ecf20Sopenharmony_ci }, 40488c2ecf20Sopenharmony_ci { 40498c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AHASH, 40508c2ecf20Sopenharmony_ci .alg.hash = { 40518c2ecf20Sopenharmony_ci .halg.digestsize = SHA3_256_DIGEST_SIZE, 40528c2ecf20Sopenharmony_ci .halg.base = { 40538c2ecf20Sopenharmony_ci .cra_name = "hmac(sha3-256)", 40548c2ecf20Sopenharmony_ci .cra_driver_name = "hmac-sha3-256-iproc", 40558c2ecf20Sopenharmony_ci .cra_blocksize = SHA3_256_BLOCK_SIZE, 40568c2ecf20Sopenharmony_ci } 40578c2ecf20Sopenharmony_ci }, 40588c2ecf20Sopenharmony_ci .cipher_info = { 40598c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_NONE, 40608c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_NONE, 40618c2ecf20Sopenharmony_ci }, 40628c2ecf20Sopenharmony_ci .auth_info = { 40638c2ecf20Sopenharmony_ci .alg = HASH_ALG_SHA3_256, 40648c2ecf20Sopenharmony_ci .mode = HASH_MODE_HMAC, 40658c2ecf20Sopenharmony_ci }, 40668c2ecf20Sopenharmony_ci }, 40678c2ecf20Sopenharmony_ci { 40688c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AHASH, 40698c2ecf20Sopenharmony_ci .alg.hash = { 40708c2ecf20Sopenharmony_ci .halg.digestsize = SHA3_384_DIGEST_SIZE, 40718c2ecf20Sopenharmony_ci .halg.base = { 40728c2ecf20Sopenharmony_ci .cra_name = "sha3-384", 40738c2ecf20Sopenharmony_ci .cra_driver_name = "sha3-384-iproc", 40748c2ecf20Sopenharmony_ci .cra_blocksize = SHA3_224_BLOCK_SIZE, 40758c2ecf20Sopenharmony_ci } 40768c2ecf20Sopenharmony_ci }, 40778c2ecf20Sopenharmony_ci .cipher_info = { 40788c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_NONE, 40798c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_NONE, 40808c2ecf20Sopenharmony_ci }, 40818c2ecf20Sopenharmony_ci .auth_info = { 40828c2ecf20Sopenharmony_ci .alg = HASH_ALG_SHA3_384, 40838c2ecf20Sopenharmony_ci .mode = HASH_MODE_HASH, 40848c2ecf20Sopenharmony_ci }, 40858c2ecf20Sopenharmony_ci }, 40868c2ecf20Sopenharmony_ci { 40878c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AHASH, 40888c2ecf20Sopenharmony_ci .alg.hash = { 40898c2ecf20Sopenharmony_ci .halg.digestsize = SHA3_384_DIGEST_SIZE, 40908c2ecf20Sopenharmony_ci .halg.base = { 40918c2ecf20Sopenharmony_ci .cra_name = "hmac(sha3-384)", 40928c2ecf20Sopenharmony_ci .cra_driver_name = "hmac-sha3-384-iproc", 40938c2ecf20Sopenharmony_ci .cra_blocksize = SHA3_384_BLOCK_SIZE, 40948c2ecf20Sopenharmony_ci } 40958c2ecf20Sopenharmony_ci }, 40968c2ecf20Sopenharmony_ci .cipher_info = { 40978c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_NONE, 40988c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_NONE, 40998c2ecf20Sopenharmony_ci }, 41008c2ecf20Sopenharmony_ci .auth_info = { 41018c2ecf20Sopenharmony_ci .alg = HASH_ALG_SHA3_384, 41028c2ecf20Sopenharmony_ci .mode = HASH_MODE_HMAC, 41038c2ecf20Sopenharmony_ci }, 41048c2ecf20Sopenharmony_ci }, 41058c2ecf20Sopenharmony_ci { 41068c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AHASH, 41078c2ecf20Sopenharmony_ci .alg.hash = { 41088c2ecf20Sopenharmony_ci .halg.digestsize = SHA3_512_DIGEST_SIZE, 41098c2ecf20Sopenharmony_ci .halg.base = { 41108c2ecf20Sopenharmony_ci .cra_name = "sha3-512", 41118c2ecf20Sopenharmony_ci .cra_driver_name = "sha3-512-iproc", 41128c2ecf20Sopenharmony_ci .cra_blocksize = SHA3_512_BLOCK_SIZE, 41138c2ecf20Sopenharmony_ci } 41148c2ecf20Sopenharmony_ci }, 41158c2ecf20Sopenharmony_ci .cipher_info = { 41168c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_NONE, 41178c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_NONE, 41188c2ecf20Sopenharmony_ci }, 41198c2ecf20Sopenharmony_ci .auth_info = { 41208c2ecf20Sopenharmony_ci .alg = HASH_ALG_SHA3_512, 41218c2ecf20Sopenharmony_ci .mode = HASH_MODE_HASH, 41228c2ecf20Sopenharmony_ci }, 41238c2ecf20Sopenharmony_ci }, 41248c2ecf20Sopenharmony_ci { 41258c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AHASH, 41268c2ecf20Sopenharmony_ci .alg.hash = { 41278c2ecf20Sopenharmony_ci .halg.digestsize = SHA3_512_DIGEST_SIZE, 41288c2ecf20Sopenharmony_ci .halg.base = { 41298c2ecf20Sopenharmony_ci .cra_name = "hmac(sha3-512)", 41308c2ecf20Sopenharmony_ci .cra_driver_name = "hmac-sha3-512-iproc", 41318c2ecf20Sopenharmony_ci .cra_blocksize = SHA3_512_BLOCK_SIZE, 41328c2ecf20Sopenharmony_ci } 41338c2ecf20Sopenharmony_ci }, 41348c2ecf20Sopenharmony_ci .cipher_info = { 41358c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_NONE, 41368c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_NONE, 41378c2ecf20Sopenharmony_ci }, 41388c2ecf20Sopenharmony_ci .auth_info = { 41398c2ecf20Sopenharmony_ci .alg = HASH_ALG_SHA3_512, 41408c2ecf20Sopenharmony_ci .mode = HASH_MODE_HMAC, 41418c2ecf20Sopenharmony_ci }, 41428c2ecf20Sopenharmony_ci }, 41438c2ecf20Sopenharmony_ci { 41448c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AHASH, 41458c2ecf20Sopenharmony_ci .alg.hash = { 41468c2ecf20Sopenharmony_ci .halg.digestsize = AES_BLOCK_SIZE, 41478c2ecf20Sopenharmony_ci .halg.base = { 41488c2ecf20Sopenharmony_ci .cra_name = "xcbc(aes)", 41498c2ecf20Sopenharmony_ci .cra_driver_name = "xcbc-aes-iproc", 41508c2ecf20Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 41518c2ecf20Sopenharmony_ci } 41528c2ecf20Sopenharmony_ci }, 41538c2ecf20Sopenharmony_ci .cipher_info = { 41548c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_NONE, 41558c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_NONE, 41568c2ecf20Sopenharmony_ci }, 41578c2ecf20Sopenharmony_ci .auth_info = { 41588c2ecf20Sopenharmony_ci .alg = HASH_ALG_AES, 41598c2ecf20Sopenharmony_ci .mode = HASH_MODE_XCBC, 41608c2ecf20Sopenharmony_ci }, 41618c2ecf20Sopenharmony_ci }, 41628c2ecf20Sopenharmony_ci { 41638c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AHASH, 41648c2ecf20Sopenharmony_ci .alg.hash = { 41658c2ecf20Sopenharmony_ci .halg.digestsize = AES_BLOCK_SIZE, 41668c2ecf20Sopenharmony_ci .halg.base = { 41678c2ecf20Sopenharmony_ci .cra_name = "cmac(aes)", 41688c2ecf20Sopenharmony_ci .cra_driver_name = "cmac-aes-iproc", 41698c2ecf20Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 41708c2ecf20Sopenharmony_ci } 41718c2ecf20Sopenharmony_ci }, 41728c2ecf20Sopenharmony_ci .cipher_info = { 41738c2ecf20Sopenharmony_ci .alg = CIPHER_ALG_NONE, 41748c2ecf20Sopenharmony_ci .mode = CIPHER_MODE_NONE, 41758c2ecf20Sopenharmony_ci }, 41768c2ecf20Sopenharmony_ci .auth_info = { 41778c2ecf20Sopenharmony_ci .alg = HASH_ALG_AES, 41788c2ecf20Sopenharmony_ci .mode = HASH_MODE_CMAC, 41798c2ecf20Sopenharmony_ci }, 41808c2ecf20Sopenharmony_ci }, 41818c2ecf20Sopenharmony_ci}; 41828c2ecf20Sopenharmony_ci 41838c2ecf20Sopenharmony_cistatic int generic_cra_init(struct crypto_tfm *tfm, 41848c2ecf20Sopenharmony_ci struct iproc_alg_s *cipher_alg) 41858c2ecf20Sopenharmony_ci{ 41868c2ecf20Sopenharmony_ci struct spu_hw *spu = &iproc_priv.spu; 41878c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = crypto_tfm_ctx(tfm); 41888c2ecf20Sopenharmony_ci unsigned int blocksize = crypto_tfm_alg_blocksize(tfm); 41898c2ecf20Sopenharmony_ci 41908c2ecf20Sopenharmony_ci flow_log("%s()\n", __func__); 41918c2ecf20Sopenharmony_ci 41928c2ecf20Sopenharmony_ci ctx->alg = cipher_alg; 41938c2ecf20Sopenharmony_ci ctx->cipher = cipher_alg->cipher_info; 41948c2ecf20Sopenharmony_ci ctx->auth = cipher_alg->auth_info; 41958c2ecf20Sopenharmony_ci ctx->auth_first = cipher_alg->auth_first; 41968c2ecf20Sopenharmony_ci ctx->max_payload = spu->spu_ctx_max_payload(ctx->cipher.alg, 41978c2ecf20Sopenharmony_ci ctx->cipher.mode, 41988c2ecf20Sopenharmony_ci blocksize); 41998c2ecf20Sopenharmony_ci ctx->fallback_cipher = NULL; 42008c2ecf20Sopenharmony_ci 42018c2ecf20Sopenharmony_ci ctx->enckeylen = 0; 42028c2ecf20Sopenharmony_ci ctx->authkeylen = 0; 42038c2ecf20Sopenharmony_ci 42048c2ecf20Sopenharmony_ci atomic_inc(&iproc_priv.stream_count); 42058c2ecf20Sopenharmony_ci atomic_inc(&iproc_priv.session_count); 42068c2ecf20Sopenharmony_ci 42078c2ecf20Sopenharmony_ci return 0; 42088c2ecf20Sopenharmony_ci} 42098c2ecf20Sopenharmony_ci 42108c2ecf20Sopenharmony_cistatic int skcipher_init_tfm(struct crypto_skcipher *skcipher) 42118c2ecf20Sopenharmony_ci{ 42128c2ecf20Sopenharmony_ci struct crypto_tfm *tfm = crypto_skcipher_tfm(skcipher); 42138c2ecf20Sopenharmony_ci struct skcipher_alg *alg = crypto_skcipher_alg(skcipher); 42148c2ecf20Sopenharmony_ci struct iproc_alg_s *cipher_alg; 42158c2ecf20Sopenharmony_ci 42168c2ecf20Sopenharmony_ci flow_log("%s()\n", __func__); 42178c2ecf20Sopenharmony_ci 42188c2ecf20Sopenharmony_ci crypto_skcipher_set_reqsize(skcipher, sizeof(struct iproc_reqctx_s)); 42198c2ecf20Sopenharmony_ci 42208c2ecf20Sopenharmony_ci cipher_alg = container_of(alg, struct iproc_alg_s, alg.skcipher); 42218c2ecf20Sopenharmony_ci return generic_cra_init(tfm, cipher_alg); 42228c2ecf20Sopenharmony_ci} 42238c2ecf20Sopenharmony_ci 42248c2ecf20Sopenharmony_cistatic int ahash_cra_init(struct crypto_tfm *tfm) 42258c2ecf20Sopenharmony_ci{ 42268c2ecf20Sopenharmony_ci int err; 42278c2ecf20Sopenharmony_ci struct crypto_alg *alg = tfm->__crt_alg; 42288c2ecf20Sopenharmony_ci struct iproc_alg_s *cipher_alg; 42298c2ecf20Sopenharmony_ci 42308c2ecf20Sopenharmony_ci cipher_alg = container_of(__crypto_ahash_alg(alg), struct iproc_alg_s, 42318c2ecf20Sopenharmony_ci alg.hash); 42328c2ecf20Sopenharmony_ci 42338c2ecf20Sopenharmony_ci err = generic_cra_init(tfm, cipher_alg); 42348c2ecf20Sopenharmony_ci flow_log("%s()\n", __func__); 42358c2ecf20Sopenharmony_ci 42368c2ecf20Sopenharmony_ci /* 42378c2ecf20Sopenharmony_ci * export state size has to be < 512 bytes. So don't include msg bufs 42388c2ecf20Sopenharmony_ci * in state size. 42398c2ecf20Sopenharmony_ci */ 42408c2ecf20Sopenharmony_ci crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), 42418c2ecf20Sopenharmony_ci sizeof(struct iproc_reqctx_s)); 42428c2ecf20Sopenharmony_ci 42438c2ecf20Sopenharmony_ci return err; 42448c2ecf20Sopenharmony_ci} 42458c2ecf20Sopenharmony_ci 42468c2ecf20Sopenharmony_cistatic int aead_cra_init(struct crypto_aead *aead) 42478c2ecf20Sopenharmony_ci{ 42488c2ecf20Sopenharmony_ci struct crypto_tfm *tfm = crypto_aead_tfm(aead); 42498c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = crypto_tfm_ctx(tfm); 42508c2ecf20Sopenharmony_ci struct crypto_alg *alg = tfm->__crt_alg; 42518c2ecf20Sopenharmony_ci struct aead_alg *aalg = container_of(alg, struct aead_alg, base); 42528c2ecf20Sopenharmony_ci struct iproc_alg_s *cipher_alg = container_of(aalg, struct iproc_alg_s, 42538c2ecf20Sopenharmony_ci alg.aead); 42548c2ecf20Sopenharmony_ci 42558c2ecf20Sopenharmony_ci int err = generic_cra_init(tfm, cipher_alg); 42568c2ecf20Sopenharmony_ci 42578c2ecf20Sopenharmony_ci flow_log("%s()\n", __func__); 42588c2ecf20Sopenharmony_ci 42598c2ecf20Sopenharmony_ci crypto_aead_set_reqsize(aead, sizeof(struct iproc_reqctx_s)); 42608c2ecf20Sopenharmony_ci ctx->is_esp = false; 42618c2ecf20Sopenharmony_ci ctx->salt_len = 0; 42628c2ecf20Sopenharmony_ci ctx->salt_offset = 0; 42638c2ecf20Sopenharmony_ci 42648c2ecf20Sopenharmony_ci /* random first IV */ 42658c2ecf20Sopenharmony_ci get_random_bytes(ctx->iv, MAX_IV_SIZE); 42668c2ecf20Sopenharmony_ci flow_dump(" iv: ", ctx->iv, MAX_IV_SIZE); 42678c2ecf20Sopenharmony_ci 42688c2ecf20Sopenharmony_ci if (!err) { 42698c2ecf20Sopenharmony_ci if (alg->cra_flags & CRYPTO_ALG_NEED_FALLBACK) { 42708c2ecf20Sopenharmony_ci flow_log("%s() creating fallback cipher\n", __func__); 42718c2ecf20Sopenharmony_ci 42728c2ecf20Sopenharmony_ci ctx->fallback_cipher = 42738c2ecf20Sopenharmony_ci crypto_alloc_aead(alg->cra_name, 0, 42748c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 42758c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK); 42768c2ecf20Sopenharmony_ci if (IS_ERR(ctx->fallback_cipher)) { 42778c2ecf20Sopenharmony_ci pr_err("%s() Error: failed to allocate fallback for %s\n", 42788c2ecf20Sopenharmony_ci __func__, alg->cra_name); 42798c2ecf20Sopenharmony_ci return PTR_ERR(ctx->fallback_cipher); 42808c2ecf20Sopenharmony_ci } 42818c2ecf20Sopenharmony_ci } 42828c2ecf20Sopenharmony_ci } 42838c2ecf20Sopenharmony_ci 42848c2ecf20Sopenharmony_ci return err; 42858c2ecf20Sopenharmony_ci} 42868c2ecf20Sopenharmony_ci 42878c2ecf20Sopenharmony_cistatic void generic_cra_exit(struct crypto_tfm *tfm) 42888c2ecf20Sopenharmony_ci{ 42898c2ecf20Sopenharmony_ci atomic_dec(&iproc_priv.session_count); 42908c2ecf20Sopenharmony_ci} 42918c2ecf20Sopenharmony_ci 42928c2ecf20Sopenharmony_cistatic void skcipher_exit_tfm(struct crypto_skcipher *tfm) 42938c2ecf20Sopenharmony_ci{ 42948c2ecf20Sopenharmony_ci generic_cra_exit(crypto_skcipher_tfm(tfm)); 42958c2ecf20Sopenharmony_ci} 42968c2ecf20Sopenharmony_ci 42978c2ecf20Sopenharmony_cistatic void aead_cra_exit(struct crypto_aead *aead) 42988c2ecf20Sopenharmony_ci{ 42998c2ecf20Sopenharmony_ci struct crypto_tfm *tfm = crypto_aead_tfm(aead); 43008c2ecf20Sopenharmony_ci struct iproc_ctx_s *ctx = crypto_tfm_ctx(tfm); 43018c2ecf20Sopenharmony_ci 43028c2ecf20Sopenharmony_ci generic_cra_exit(tfm); 43038c2ecf20Sopenharmony_ci 43048c2ecf20Sopenharmony_ci if (ctx->fallback_cipher) { 43058c2ecf20Sopenharmony_ci crypto_free_aead(ctx->fallback_cipher); 43068c2ecf20Sopenharmony_ci ctx->fallback_cipher = NULL; 43078c2ecf20Sopenharmony_ci } 43088c2ecf20Sopenharmony_ci} 43098c2ecf20Sopenharmony_ci 43108c2ecf20Sopenharmony_ci/** 43118c2ecf20Sopenharmony_ci * spu_functions_register() - Specify hardware-specific SPU functions based on 43128c2ecf20Sopenharmony_ci * SPU type read from device tree. 43138c2ecf20Sopenharmony_ci * @dev: device structure 43148c2ecf20Sopenharmony_ci * @spu_type: SPU hardware generation 43158c2ecf20Sopenharmony_ci * @spu_subtype: SPU hardware version 43168c2ecf20Sopenharmony_ci */ 43178c2ecf20Sopenharmony_cistatic void spu_functions_register(struct device *dev, 43188c2ecf20Sopenharmony_ci enum spu_spu_type spu_type, 43198c2ecf20Sopenharmony_ci enum spu_spu_subtype spu_subtype) 43208c2ecf20Sopenharmony_ci{ 43218c2ecf20Sopenharmony_ci struct spu_hw *spu = &iproc_priv.spu; 43228c2ecf20Sopenharmony_ci 43238c2ecf20Sopenharmony_ci if (spu_type == SPU_TYPE_SPUM) { 43248c2ecf20Sopenharmony_ci dev_dbg(dev, "Registering SPUM functions"); 43258c2ecf20Sopenharmony_ci spu->spu_dump_msg_hdr = spum_dump_msg_hdr; 43268c2ecf20Sopenharmony_ci spu->spu_payload_length = spum_payload_length; 43278c2ecf20Sopenharmony_ci spu->spu_response_hdr_len = spum_response_hdr_len; 43288c2ecf20Sopenharmony_ci spu->spu_hash_pad_len = spum_hash_pad_len; 43298c2ecf20Sopenharmony_ci spu->spu_gcm_ccm_pad_len = spum_gcm_ccm_pad_len; 43308c2ecf20Sopenharmony_ci spu->spu_assoc_resp_len = spum_assoc_resp_len; 43318c2ecf20Sopenharmony_ci spu->spu_aead_ivlen = spum_aead_ivlen; 43328c2ecf20Sopenharmony_ci spu->spu_hash_type = spum_hash_type; 43338c2ecf20Sopenharmony_ci spu->spu_digest_size = spum_digest_size; 43348c2ecf20Sopenharmony_ci spu->spu_create_request = spum_create_request; 43358c2ecf20Sopenharmony_ci spu->spu_cipher_req_init = spum_cipher_req_init; 43368c2ecf20Sopenharmony_ci spu->spu_cipher_req_finish = spum_cipher_req_finish; 43378c2ecf20Sopenharmony_ci spu->spu_request_pad = spum_request_pad; 43388c2ecf20Sopenharmony_ci spu->spu_tx_status_len = spum_tx_status_len; 43398c2ecf20Sopenharmony_ci spu->spu_rx_status_len = spum_rx_status_len; 43408c2ecf20Sopenharmony_ci spu->spu_status_process = spum_status_process; 43418c2ecf20Sopenharmony_ci spu->spu_xts_tweak_in_payload = spum_xts_tweak_in_payload; 43428c2ecf20Sopenharmony_ci spu->spu_ccm_update_iv = spum_ccm_update_iv; 43438c2ecf20Sopenharmony_ci spu->spu_wordalign_padlen = spum_wordalign_padlen; 43448c2ecf20Sopenharmony_ci if (spu_subtype == SPU_SUBTYPE_SPUM_NS2) 43458c2ecf20Sopenharmony_ci spu->spu_ctx_max_payload = spum_ns2_ctx_max_payload; 43468c2ecf20Sopenharmony_ci else 43478c2ecf20Sopenharmony_ci spu->spu_ctx_max_payload = spum_nsp_ctx_max_payload; 43488c2ecf20Sopenharmony_ci } else { 43498c2ecf20Sopenharmony_ci dev_dbg(dev, "Registering SPU2 functions"); 43508c2ecf20Sopenharmony_ci spu->spu_dump_msg_hdr = spu2_dump_msg_hdr; 43518c2ecf20Sopenharmony_ci spu->spu_ctx_max_payload = spu2_ctx_max_payload; 43528c2ecf20Sopenharmony_ci spu->spu_payload_length = spu2_payload_length; 43538c2ecf20Sopenharmony_ci spu->spu_response_hdr_len = spu2_response_hdr_len; 43548c2ecf20Sopenharmony_ci spu->spu_hash_pad_len = spu2_hash_pad_len; 43558c2ecf20Sopenharmony_ci spu->spu_gcm_ccm_pad_len = spu2_gcm_ccm_pad_len; 43568c2ecf20Sopenharmony_ci spu->spu_assoc_resp_len = spu2_assoc_resp_len; 43578c2ecf20Sopenharmony_ci spu->spu_aead_ivlen = spu2_aead_ivlen; 43588c2ecf20Sopenharmony_ci spu->spu_hash_type = spu2_hash_type; 43598c2ecf20Sopenharmony_ci spu->spu_digest_size = spu2_digest_size; 43608c2ecf20Sopenharmony_ci spu->spu_create_request = spu2_create_request; 43618c2ecf20Sopenharmony_ci spu->spu_cipher_req_init = spu2_cipher_req_init; 43628c2ecf20Sopenharmony_ci spu->spu_cipher_req_finish = spu2_cipher_req_finish; 43638c2ecf20Sopenharmony_ci spu->spu_request_pad = spu2_request_pad; 43648c2ecf20Sopenharmony_ci spu->spu_tx_status_len = spu2_tx_status_len; 43658c2ecf20Sopenharmony_ci spu->spu_rx_status_len = spu2_rx_status_len; 43668c2ecf20Sopenharmony_ci spu->spu_status_process = spu2_status_process; 43678c2ecf20Sopenharmony_ci spu->spu_xts_tweak_in_payload = spu2_xts_tweak_in_payload; 43688c2ecf20Sopenharmony_ci spu->spu_ccm_update_iv = spu2_ccm_update_iv; 43698c2ecf20Sopenharmony_ci spu->spu_wordalign_padlen = spu2_wordalign_padlen; 43708c2ecf20Sopenharmony_ci } 43718c2ecf20Sopenharmony_ci} 43728c2ecf20Sopenharmony_ci 43738c2ecf20Sopenharmony_ci/** 43748c2ecf20Sopenharmony_ci * spu_mb_init() - Initialize mailbox client. Request ownership of a mailbox 43758c2ecf20Sopenharmony_ci * channel for the SPU being probed. 43768c2ecf20Sopenharmony_ci * @dev: SPU driver device structure 43778c2ecf20Sopenharmony_ci * 43788c2ecf20Sopenharmony_ci * Return: 0 if successful 43798c2ecf20Sopenharmony_ci * < 0 otherwise 43808c2ecf20Sopenharmony_ci */ 43818c2ecf20Sopenharmony_cistatic int spu_mb_init(struct device *dev) 43828c2ecf20Sopenharmony_ci{ 43838c2ecf20Sopenharmony_ci struct mbox_client *mcl = &iproc_priv.mcl; 43848c2ecf20Sopenharmony_ci int err, i; 43858c2ecf20Sopenharmony_ci 43868c2ecf20Sopenharmony_ci iproc_priv.mbox = devm_kcalloc(dev, iproc_priv.spu.num_chan, 43878c2ecf20Sopenharmony_ci sizeof(struct mbox_chan *), GFP_KERNEL); 43888c2ecf20Sopenharmony_ci if (!iproc_priv.mbox) 43898c2ecf20Sopenharmony_ci return -ENOMEM; 43908c2ecf20Sopenharmony_ci 43918c2ecf20Sopenharmony_ci mcl->dev = dev; 43928c2ecf20Sopenharmony_ci mcl->tx_block = false; 43938c2ecf20Sopenharmony_ci mcl->tx_tout = 0; 43948c2ecf20Sopenharmony_ci mcl->knows_txdone = true; 43958c2ecf20Sopenharmony_ci mcl->rx_callback = spu_rx_callback; 43968c2ecf20Sopenharmony_ci mcl->tx_done = NULL; 43978c2ecf20Sopenharmony_ci 43988c2ecf20Sopenharmony_ci for (i = 0; i < iproc_priv.spu.num_chan; i++) { 43998c2ecf20Sopenharmony_ci iproc_priv.mbox[i] = mbox_request_channel(mcl, i); 44008c2ecf20Sopenharmony_ci if (IS_ERR(iproc_priv.mbox[i])) { 44018c2ecf20Sopenharmony_ci err = PTR_ERR(iproc_priv.mbox[i]); 44028c2ecf20Sopenharmony_ci dev_err(dev, 44038c2ecf20Sopenharmony_ci "Mbox channel %d request failed with err %d", 44048c2ecf20Sopenharmony_ci i, err); 44058c2ecf20Sopenharmony_ci iproc_priv.mbox[i] = NULL; 44068c2ecf20Sopenharmony_ci goto free_channels; 44078c2ecf20Sopenharmony_ci } 44088c2ecf20Sopenharmony_ci } 44098c2ecf20Sopenharmony_ci 44108c2ecf20Sopenharmony_ci return 0; 44118c2ecf20Sopenharmony_cifree_channels: 44128c2ecf20Sopenharmony_ci for (i = 0; i < iproc_priv.spu.num_chan; i++) { 44138c2ecf20Sopenharmony_ci if (iproc_priv.mbox[i]) 44148c2ecf20Sopenharmony_ci mbox_free_channel(iproc_priv.mbox[i]); 44158c2ecf20Sopenharmony_ci } 44168c2ecf20Sopenharmony_ci 44178c2ecf20Sopenharmony_ci return err; 44188c2ecf20Sopenharmony_ci} 44198c2ecf20Sopenharmony_ci 44208c2ecf20Sopenharmony_cistatic void spu_mb_release(struct platform_device *pdev) 44218c2ecf20Sopenharmony_ci{ 44228c2ecf20Sopenharmony_ci int i; 44238c2ecf20Sopenharmony_ci 44248c2ecf20Sopenharmony_ci for (i = 0; i < iproc_priv.spu.num_chan; i++) 44258c2ecf20Sopenharmony_ci mbox_free_channel(iproc_priv.mbox[i]); 44268c2ecf20Sopenharmony_ci} 44278c2ecf20Sopenharmony_ci 44288c2ecf20Sopenharmony_cistatic void spu_counters_init(void) 44298c2ecf20Sopenharmony_ci{ 44308c2ecf20Sopenharmony_ci int i; 44318c2ecf20Sopenharmony_ci int j; 44328c2ecf20Sopenharmony_ci 44338c2ecf20Sopenharmony_ci atomic_set(&iproc_priv.session_count, 0); 44348c2ecf20Sopenharmony_ci atomic_set(&iproc_priv.stream_count, 0); 44358c2ecf20Sopenharmony_ci atomic_set(&iproc_priv.next_chan, (int)iproc_priv.spu.num_chan); 44368c2ecf20Sopenharmony_ci atomic64_set(&iproc_priv.bytes_in, 0); 44378c2ecf20Sopenharmony_ci atomic64_set(&iproc_priv.bytes_out, 0); 44388c2ecf20Sopenharmony_ci for (i = 0; i < SPU_OP_NUM; i++) { 44398c2ecf20Sopenharmony_ci atomic_set(&iproc_priv.op_counts[i], 0); 44408c2ecf20Sopenharmony_ci atomic_set(&iproc_priv.setkey_cnt[i], 0); 44418c2ecf20Sopenharmony_ci } 44428c2ecf20Sopenharmony_ci for (i = 0; i < CIPHER_ALG_LAST; i++) 44438c2ecf20Sopenharmony_ci for (j = 0; j < CIPHER_MODE_LAST; j++) 44448c2ecf20Sopenharmony_ci atomic_set(&iproc_priv.cipher_cnt[i][j], 0); 44458c2ecf20Sopenharmony_ci 44468c2ecf20Sopenharmony_ci for (i = 0; i < HASH_ALG_LAST; i++) { 44478c2ecf20Sopenharmony_ci atomic_set(&iproc_priv.hash_cnt[i], 0); 44488c2ecf20Sopenharmony_ci atomic_set(&iproc_priv.hmac_cnt[i], 0); 44498c2ecf20Sopenharmony_ci } 44508c2ecf20Sopenharmony_ci for (i = 0; i < AEAD_TYPE_LAST; i++) 44518c2ecf20Sopenharmony_ci atomic_set(&iproc_priv.aead_cnt[i], 0); 44528c2ecf20Sopenharmony_ci 44538c2ecf20Sopenharmony_ci atomic_set(&iproc_priv.mb_no_spc, 0); 44548c2ecf20Sopenharmony_ci atomic_set(&iproc_priv.mb_send_fail, 0); 44558c2ecf20Sopenharmony_ci atomic_set(&iproc_priv.bad_icv, 0); 44568c2ecf20Sopenharmony_ci} 44578c2ecf20Sopenharmony_ci 44588c2ecf20Sopenharmony_cistatic int spu_register_skcipher(struct iproc_alg_s *driver_alg) 44598c2ecf20Sopenharmony_ci{ 44608c2ecf20Sopenharmony_ci struct skcipher_alg *crypto = &driver_alg->alg.skcipher; 44618c2ecf20Sopenharmony_ci int err; 44628c2ecf20Sopenharmony_ci 44638c2ecf20Sopenharmony_ci crypto->base.cra_module = THIS_MODULE; 44648c2ecf20Sopenharmony_ci crypto->base.cra_priority = cipher_pri; 44658c2ecf20Sopenharmony_ci crypto->base.cra_alignmask = 0; 44668c2ecf20Sopenharmony_ci crypto->base.cra_ctxsize = sizeof(struct iproc_ctx_s); 44678c2ecf20Sopenharmony_ci crypto->base.cra_flags = CRYPTO_ALG_ASYNC | 44688c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 44698c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY; 44708c2ecf20Sopenharmony_ci 44718c2ecf20Sopenharmony_ci crypto->init = skcipher_init_tfm; 44728c2ecf20Sopenharmony_ci crypto->exit = skcipher_exit_tfm; 44738c2ecf20Sopenharmony_ci crypto->setkey = skcipher_setkey; 44748c2ecf20Sopenharmony_ci crypto->encrypt = skcipher_encrypt; 44758c2ecf20Sopenharmony_ci crypto->decrypt = skcipher_decrypt; 44768c2ecf20Sopenharmony_ci 44778c2ecf20Sopenharmony_ci err = crypto_register_skcipher(crypto); 44788c2ecf20Sopenharmony_ci /* Mark alg as having been registered, if successful */ 44798c2ecf20Sopenharmony_ci if (err == 0) 44808c2ecf20Sopenharmony_ci driver_alg->registered = true; 44818c2ecf20Sopenharmony_ci pr_debug(" registered skcipher %s\n", crypto->base.cra_driver_name); 44828c2ecf20Sopenharmony_ci return err; 44838c2ecf20Sopenharmony_ci} 44848c2ecf20Sopenharmony_ci 44858c2ecf20Sopenharmony_cistatic int spu_register_ahash(struct iproc_alg_s *driver_alg) 44868c2ecf20Sopenharmony_ci{ 44878c2ecf20Sopenharmony_ci struct spu_hw *spu = &iproc_priv.spu; 44888c2ecf20Sopenharmony_ci struct ahash_alg *hash = &driver_alg->alg.hash; 44898c2ecf20Sopenharmony_ci int err; 44908c2ecf20Sopenharmony_ci 44918c2ecf20Sopenharmony_ci /* AES-XCBC is the only AES hash type currently supported on SPU-M */ 44928c2ecf20Sopenharmony_ci if ((driver_alg->auth_info.alg == HASH_ALG_AES) && 44938c2ecf20Sopenharmony_ci (driver_alg->auth_info.mode != HASH_MODE_XCBC) && 44948c2ecf20Sopenharmony_ci (spu->spu_type == SPU_TYPE_SPUM)) 44958c2ecf20Sopenharmony_ci return 0; 44968c2ecf20Sopenharmony_ci 44978c2ecf20Sopenharmony_ci /* SHA3 algorithm variants are not registered for SPU-M or SPU2. */ 44988c2ecf20Sopenharmony_ci if ((driver_alg->auth_info.alg >= HASH_ALG_SHA3_224) && 44998c2ecf20Sopenharmony_ci (spu->spu_subtype != SPU_SUBTYPE_SPU2_V2)) 45008c2ecf20Sopenharmony_ci return 0; 45018c2ecf20Sopenharmony_ci 45028c2ecf20Sopenharmony_ci hash->halg.base.cra_module = THIS_MODULE; 45038c2ecf20Sopenharmony_ci hash->halg.base.cra_priority = hash_pri; 45048c2ecf20Sopenharmony_ci hash->halg.base.cra_alignmask = 0; 45058c2ecf20Sopenharmony_ci hash->halg.base.cra_ctxsize = sizeof(struct iproc_ctx_s); 45068c2ecf20Sopenharmony_ci hash->halg.base.cra_init = ahash_cra_init; 45078c2ecf20Sopenharmony_ci hash->halg.base.cra_exit = generic_cra_exit; 45088c2ecf20Sopenharmony_ci hash->halg.base.cra_flags = CRYPTO_ALG_ASYNC | 45098c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY; 45108c2ecf20Sopenharmony_ci hash->halg.statesize = sizeof(struct spu_hash_export_s); 45118c2ecf20Sopenharmony_ci 45128c2ecf20Sopenharmony_ci if (driver_alg->auth_info.mode != HASH_MODE_HMAC) { 45138c2ecf20Sopenharmony_ci hash->init = ahash_init; 45148c2ecf20Sopenharmony_ci hash->update = ahash_update; 45158c2ecf20Sopenharmony_ci hash->final = ahash_final; 45168c2ecf20Sopenharmony_ci hash->finup = ahash_finup; 45178c2ecf20Sopenharmony_ci hash->digest = ahash_digest; 45188c2ecf20Sopenharmony_ci if ((driver_alg->auth_info.alg == HASH_ALG_AES) && 45198c2ecf20Sopenharmony_ci ((driver_alg->auth_info.mode == HASH_MODE_XCBC) || 45208c2ecf20Sopenharmony_ci (driver_alg->auth_info.mode == HASH_MODE_CMAC))) { 45218c2ecf20Sopenharmony_ci hash->setkey = ahash_setkey; 45228c2ecf20Sopenharmony_ci } 45238c2ecf20Sopenharmony_ci } else { 45248c2ecf20Sopenharmony_ci hash->setkey = ahash_hmac_setkey; 45258c2ecf20Sopenharmony_ci hash->init = ahash_hmac_init; 45268c2ecf20Sopenharmony_ci hash->update = ahash_hmac_update; 45278c2ecf20Sopenharmony_ci hash->final = ahash_hmac_final; 45288c2ecf20Sopenharmony_ci hash->finup = ahash_hmac_finup; 45298c2ecf20Sopenharmony_ci hash->digest = ahash_hmac_digest; 45308c2ecf20Sopenharmony_ci } 45318c2ecf20Sopenharmony_ci hash->export = ahash_export; 45328c2ecf20Sopenharmony_ci hash->import = ahash_import; 45338c2ecf20Sopenharmony_ci 45348c2ecf20Sopenharmony_ci err = crypto_register_ahash(hash); 45358c2ecf20Sopenharmony_ci /* Mark alg as having been registered, if successful */ 45368c2ecf20Sopenharmony_ci if (err == 0) 45378c2ecf20Sopenharmony_ci driver_alg->registered = true; 45388c2ecf20Sopenharmony_ci pr_debug(" registered ahash %s\n", 45398c2ecf20Sopenharmony_ci hash->halg.base.cra_driver_name); 45408c2ecf20Sopenharmony_ci return err; 45418c2ecf20Sopenharmony_ci} 45428c2ecf20Sopenharmony_ci 45438c2ecf20Sopenharmony_cistatic int spu_register_aead(struct iproc_alg_s *driver_alg) 45448c2ecf20Sopenharmony_ci{ 45458c2ecf20Sopenharmony_ci struct aead_alg *aead = &driver_alg->alg.aead; 45468c2ecf20Sopenharmony_ci int err; 45478c2ecf20Sopenharmony_ci 45488c2ecf20Sopenharmony_ci aead->base.cra_module = THIS_MODULE; 45498c2ecf20Sopenharmony_ci aead->base.cra_priority = aead_pri; 45508c2ecf20Sopenharmony_ci aead->base.cra_alignmask = 0; 45518c2ecf20Sopenharmony_ci aead->base.cra_ctxsize = sizeof(struct iproc_ctx_s); 45528c2ecf20Sopenharmony_ci 45538c2ecf20Sopenharmony_ci aead->base.cra_flags |= CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY; 45548c2ecf20Sopenharmony_ci /* setkey set in alg initialization */ 45558c2ecf20Sopenharmony_ci aead->setauthsize = aead_setauthsize; 45568c2ecf20Sopenharmony_ci aead->encrypt = aead_encrypt; 45578c2ecf20Sopenharmony_ci aead->decrypt = aead_decrypt; 45588c2ecf20Sopenharmony_ci aead->init = aead_cra_init; 45598c2ecf20Sopenharmony_ci aead->exit = aead_cra_exit; 45608c2ecf20Sopenharmony_ci 45618c2ecf20Sopenharmony_ci err = crypto_register_aead(aead); 45628c2ecf20Sopenharmony_ci /* Mark alg as having been registered, if successful */ 45638c2ecf20Sopenharmony_ci if (err == 0) 45648c2ecf20Sopenharmony_ci driver_alg->registered = true; 45658c2ecf20Sopenharmony_ci pr_debug(" registered aead %s\n", aead->base.cra_driver_name); 45668c2ecf20Sopenharmony_ci return err; 45678c2ecf20Sopenharmony_ci} 45688c2ecf20Sopenharmony_ci 45698c2ecf20Sopenharmony_ci/* register crypto algorithms the device supports */ 45708c2ecf20Sopenharmony_cistatic int spu_algs_register(struct device *dev) 45718c2ecf20Sopenharmony_ci{ 45728c2ecf20Sopenharmony_ci int i, j; 45738c2ecf20Sopenharmony_ci int err; 45748c2ecf20Sopenharmony_ci 45758c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(driver_algs); i++) { 45768c2ecf20Sopenharmony_ci switch (driver_algs[i].type) { 45778c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_SKCIPHER: 45788c2ecf20Sopenharmony_ci err = spu_register_skcipher(&driver_algs[i]); 45798c2ecf20Sopenharmony_ci break; 45808c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_AHASH: 45818c2ecf20Sopenharmony_ci err = spu_register_ahash(&driver_algs[i]); 45828c2ecf20Sopenharmony_ci break; 45838c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_AEAD: 45848c2ecf20Sopenharmony_ci err = spu_register_aead(&driver_algs[i]); 45858c2ecf20Sopenharmony_ci break; 45868c2ecf20Sopenharmony_ci default: 45878c2ecf20Sopenharmony_ci dev_err(dev, 45888c2ecf20Sopenharmony_ci "iproc-crypto: unknown alg type: %d", 45898c2ecf20Sopenharmony_ci driver_algs[i].type); 45908c2ecf20Sopenharmony_ci err = -EINVAL; 45918c2ecf20Sopenharmony_ci } 45928c2ecf20Sopenharmony_ci 45938c2ecf20Sopenharmony_ci if (err) { 45948c2ecf20Sopenharmony_ci dev_err(dev, "alg registration failed with error %d\n", 45958c2ecf20Sopenharmony_ci err); 45968c2ecf20Sopenharmony_ci goto err_algs; 45978c2ecf20Sopenharmony_ci } 45988c2ecf20Sopenharmony_ci } 45998c2ecf20Sopenharmony_ci 46008c2ecf20Sopenharmony_ci return 0; 46018c2ecf20Sopenharmony_ci 46028c2ecf20Sopenharmony_cierr_algs: 46038c2ecf20Sopenharmony_ci for (j = 0; j < i; j++) { 46048c2ecf20Sopenharmony_ci /* Skip any algorithm not registered */ 46058c2ecf20Sopenharmony_ci if (!driver_algs[j].registered) 46068c2ecf20Sopenharmony_ci continue; 46078c2ecf20Sopenharmony_ci switch (driver_algs[j].type) { 46088c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_SKCIPHER: 46098c2ecf20Sopenharmony_ci crypto_unregister_skcipher(&driver_algs[j].alg.skcipher); 46108c2ecf20Sopenharmony_ci driver_algs[j].registered = false; 46118c2ecf20Sopenharmony_ci break; 46128c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_AHASH: 46138c2ecf20Sopenharmony_ci crypto_unregister_ahash(&driver_algs[j].alg.hash); 46148c2ecf20Sopenharmony_ci driver_algs[j].registered = false; 46158c2ecf20Sopenharmony_ci break; 46168c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_AEAD: 46178c2ecf20Sopenharmony_ci crypto_unregister_aead(&driver_algs[j].alg.aead); 46188c2ecf20Sopenharmony_ci driver_algs[j].registered = false; 46198c2ecf20Sopenharmony_ci break; 46208c2ecf20Sopenharmony_ci } 46218c2ecf20Sopenharmony_ci } 46228c2ecf20Sopenharmony_ci return err; 46238c2ecf20Sopenharmony_ci} 46248c2ecf20Sopenharmony_ci 46258c2ecf20Sopenharmony_ci/* ==================== Kernel Platform API ==================== */ 46268c2ecf20Sopenharmony_ci 46278c2ecf20Sopenharmony_cistatic struct spu_type_subtype spum_ns2_types = { 46288c2ecf20Sopenharmony_ci SPU_TYPE_SPUM, SPU_SUBTYPE_SPUM_NS2 46298c2ecf20Sopenharmony_ci}; 46308c2ecf20Sopenharmony_ci 46318c2ecf20Sopenharmony_cistatic struct spu_type_subtype spum_nsp_types = { 46328c2ecf20Sopenharmony_ci SPU_TYPE_SPUM, SPU_SUBTYPE_SPUM_NSP 46338c2ecf20Sopenharmony_ci}; 46348c2ecf20Sopenharmony_ci 46358c2ecf20Sopenharmony_cistatic struct spu_type_subtype spu2_types = { 46368c2ecf20Sopenharmony_ci SPU_TYPE_SPU2, SPU_SUBTYPE_SPU2_V1 46378c2ecf20Sopenharmony_ci}; 46388c2ecf20Sopenharmony_ci 46398c2ecf20Sopenharmony_cistatic struct spu_type_subtype spu2_v2_types = { 46408c2ecf20Sopenharmony_ci SPU_TYPE_SPU2, SPU_SUBTYPE_SPU2_V2 46418c2ecf20Sopenharmony_ci}; 46428c2ecf20Sopenharmony_ci 46438c2ecf20Sopenharmony_cistatic const struct of_device_id bcm_spu_dt_ids[] = { 46448c2ecf20Sopenharmony_ci { 46458c2ecf20Sopenharmony_ci .compatible = "brcm,spum-crypto", 46468c2ecf20Sopenharmony_ci .data = &spum_ns2_types, 46478c2ecf20Sopenharmony_ci }, 46488c2ecf20Sopenharmony_ci { 46498c2ecf20Sopenharmony_ci .compatible = "brcm,spum-nsp-crypto", 46508c2ecf20Sopenharmony_ci .data = &spum_nsp_types, 46518c2ecf20Sopenharmony_ci }, 46528c2ecf20Sopenharmony_ci { 46538c2ecf20Sopenharmony_ci .compatible = "brcm,spu2-crypto", 46548c2ecf20Sopenharmony_ci .data = &spu2_types, 46558c2ecf20Sopenharmony_ci }, 46568c2ecf20Sopenharmony_ci { 46578c2ecf20Sopenharmony_ci .compatible = "brcm,spu2-v2-crypto", 46588c2ecf20Sopenharmony_ci .data = &spu2_v2_types, 46598c2ecf20Sopenharmony_ci }, 46608c2ecf20Sopenharmony_ci { /* sentinel */ } 46618c2ecf20Sopenharmony_ci}; 46628c2ecf20Sopenharmony_ci 46638c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, bcm_spu_dt_ids); 46648c2ecf20Sopenharmony_ci 46658c2ecf20Sopenharmony_cistatic int spu_dt_read(struct platform_device *pdev) 46668c2ecf20Sopenharmony_ci{ 46678c2ecf20Sopenharmony_ci struct device *dev = &pdev->dev; 46688c2ecf20Sopenharmony_ci struct spu_hw *spu = &iproc_priv.spu; 46698c2ecf20Sopenharmony_ci struct resource *spu_ctrl_regs; 46708c2ecf20Sopenharmony_ci const struct spu_type_subtype *matched_spu_type; 46718c2ecf20Sopenharmony_ci struct device_node *dn = pdev->dev.of_node; 46728c2ecf20Sopenharmony_ci int err, i; 46738c2ecf20Sopenharmony_ci 46748c2ecf20Sopenharmony_ci /* Count number of mailbox channels */ 46758c2ecf20Sopenharmony_ci spu->num_chan = of_count_phandle_with_args(dn, "mboxes", "#mbox-cells"); 46768c2ecf20Sopenharmony_ci 46778c2ecf20Sopenharmony_ci matched_spu_type = of_device_get_match_data(dev); 46788c2ecf20Sopenharmony_ci if (!matched_spu_type) { 46798c2ecf20Sopenharmony_ci dev_err(dev, "Failed to match device\n"); 46808c2ecf20Sopenharmony_ci return -ENODEV; 46818c2ecf20Sopenharmony_ci } 46828c2ecf20Sopenharmony_ci 46838c2ecf20Sopenharmony_ci spu->spu_type = matched_spu_type->type; 46848c2ecf20Sopenharmony_ci spu->spu_subtype = matched_spu_type->subtype; 46858c2ecf20Sopenharmony_ci 46868c2ecf20Sopenharmony_ci for (i = 0; (i < MAX_SPUS) && ((spu_ctrl_regs = 46878c2ecf20Sopenharmony_ci platform_get_resource(pdev, IORESOURCE_MEM, i)) != NULL); i++) { 46888c2ecf20Sopenharmony_ci 46898c2ecf20Sopenharmony_ci spu->reg_vbase[i] = devm_ioremap_resource(dev, spu_ctrl_regs); 46908c2ecf20Sopenharmony_ci if (IS_ERR(spu->reg_vbase[i])) { 46918c2ecf20Sopenharmony_ci err = PTR_ERR(spu->reg_vbase[i]); 46928c2ecf20Sopenharmony_ci dev_err(dev, "Failed to map registers: %d\n", 46938c2ecf20Sopenharmony_ci err); 46948c2ecf20Sopenharmony_ci spu->reg_vbase[i] = NULL; 46958c2ecf20Sopenharmony_ci return err; 46968c2ecf20Sopenharmony_ci } 46978c2ecf20Sopenharmony_ci } 46988c2ecf20Sopenharmony_ci spu->num_spu = i; 46998c2ecf20Sopenharmony_ci dev_dbg(dev, "Device has %d SPUs", spu->num_spu); 47008c2ecf20Sopenharmony_ci 47018c2ecf20Sopenharmony_ci return 0; 47028c2ecf20Sopenharmony_ci} 47038c2ecf20Sopenharmony_ci 47048c2ecf20Sopenharmony_cistatic int bcm_spu_probe(struct platform_device *pdev) 47058c2ecf20Sopenharmony_ci{ 47068c2ecf20Sopenharmony_ci struct device *dev = &pdev->dev; 47078c2ecf20Sopenharmony_ci struct spu_hw *spu = &iproc_priv.spu; 47088c2ecf20Sopenharmony_ci int err; 47098c2ecf20Sopenharmony_ci 47108c2ecf20Sopenharmony_ci iproc_priv.pdev = pdev; 47118c2ecf20Sopenharmony_ci platform_set_drvdata(iproc_priv.pdev, 47128c2ecf20Sopenharmony_ci &iproc_priv); 47138c2ecf20Sopenharmony_ci 47148c2ecf20Sopenharmony_ci err = spu_dt_read(pdev); 47158c2ecf20Sopenharmony_ci if (err < 0) 47168c2ecf20Sopenharmony_ci goto failure; 47178c2ecf20Sopenharmony_ci 47188c2ecf20Sopenharmony_ci err = spu_mb_init(dev); 47198c2ecf20Sopenharmony_ci if (err < 0) 47208c2ecf20Sopenharmony_ci goto failure; 47218c2ecf20Sopenharmony_ci 47228c2ecf20Sopenharmony_ci if (spu->spu_type == SPU_TYPE_SPUM) 47238c2ecf20Sopenharmony_ci iproc_priv.bcm_hdr_len = 8; 47248c2ecf20Sopenharmony_ci else if (spu->spu_type == SPU_TYPE_SPU2) 47258c2ecf20Sopenharmony_ci iproc_priv.bcm_hdr_len = 0; 47268c2ecf20Sopenharmony_ci 47278c2ecf20Sopenharmony_ci spu_functions_register(dev, spu->spu_type, spu->spu_subtype); 47288c2ecf20Sopenharmony_ci 47298c2ecf20Sopenharmony_ci spu_counters_init(); 47308c2ecf20Sopenharmony_ci 47318c2ecf20Sopenharmony_ci spu_setup_debugfs(); 47328c2ecf20Sopenharmony_ci 47338c2ecf20Sopenharmony_ci err = spu_algs_register(dev); 47348c2ecf20Sopenharmony_ci if (err < 0) 47358c2ecf20Sopenharmony_ci goto fail_reg; 47368c2ecf20Sopenharmony_ci 47378c2ecf20Sopenharmony_ci return 0; 47388c2ecf20Sopenharmony_ci 47398c2ecf20Sopenharmony_cifail_reg: 47408c2ecf20Sopenharmony_ci spu_free_debugfs(); 47418c2ecf20Sopenharmony_cifailure: 47428c2ecf20Sopenharmony_ci spu_mb_release(pdev); 47438c2ecf20Sopenharmony_ci dev_err(dev, "%s failed with error %d.\n", __func__, err); 47448c2ecf20Sopenharmony_ci 47458c2ecf20Sopenharmony_ci return err; 47468c2ecf20Sopenharmony_ci} 47478c2ecf20Sopenharmony_ci 47488c2ecf20Sopenharmony_cistatic int bcm_spu_remove(struct platform_device *pdev) 47498c2ecf20Sopenharmony_ci{ 47508c2ecf20Sopenharmony_ci int i; 47518c2ecf20Sopenharmony_ci struct device *dev = &pdev->dev; 47528c2ecf20Sopenharmony_ci char *cdn; 47538c2ecf20Sopenharmony_ci 47548c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(driver_algs); i++) { 47558c2ecf20Sopenharmony_ci /* 47568c2ecf20Sopenharmony_ci * Not all algorithms were registered, depending on whether 47578c2ecf20Sopenharmony_ci * hardware is SPU or SPU2. So here we make sure to skip 47588c2ecf20Sopenharmony_ci * those algorithms that were not previously registered. 47598c2ecf20Sopenharmony_ci */ 47608c2ecf20Sopenharmony_ci if (!driver_algs[i].registered) 47618c2ecf20Sopenharmony_ci continue; 47628c2ecf20Sopenharmony_ci 47638c2ecf20Sopenharmony_ci switch (driver_algs[i].type) { 47648c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_SKCIPHER: 47658c2ecf20Sopenharmony_ci crypto_unregister_skcipher(&driver_algs[i].alg.skcipher); 47668c2ecf20Sopenharmony_ci dev_dbg(dev, " unregistered cipher %s\n", 47678c2ecf20Sopenharmony_ci driver_algs[i].alg.skcipher.base.cra_driver_name); 47688c2ecf20Sopenharmony_ci driver_algs[i].registered = false; 47698c2ecf20Sopenharmony_ci break; 47708c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_AHASH: 47718c2ecf20Sopenharmony_ci crypto_unregister_ahash(&driver_algs[i].alg.hash); 47728c2ecf20Sopenharmony_ci cdn = driver_algs[i].alg.hash.halg.base.cra_driver_name; 47738c2ecf20Sopenharmony_ci dev_dbg(dev, " unregistered hash %s\n", cdn); 47748c2ecf20Sopenharmony_ci driver_algs[i].registered = false; 47758c2ecf20Sopenharmony_ci break; 47768c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_AEAD: 47778c2ecf20Sopenharmony_ci crypto_unregister_aead(&driver_algs[i].alg.aead); 47788c2ecf20Sopenharmony_ci dev_dbg(dev, " unregistered aead %s\n", 47798c2ecf20Sopenharmony_ci driver_algs[i].alg.aead.base.cra_driver_name); 47808c2ecf20Sopenharmony_ci driver_algs[i].registered = false; 47818c2ecf20Sopenharmony_ci break; 47828c2ecf20Sopenharmony_ci } 47838c2ecf20Sopenharmony_ci } 47848c2ecf20Sopenharmony_ci spu_free_debugfs(); 47858c2ecf20Sopenharmony_ci spu_mb_release(pdev); 47868c2ecf20Sopenharmony_ci return 0; 47878c2ecf20Sopenharmony_ci} 47888c2ecf20Sopenharmony_ci 47898c2ecf20Sopenharmony_ci/* ===== Kernel Module API ===== */ 47908c2ecf20Sopenharmony_ci 47918c2ecf20Sopenharmony_cistatic struct platform_driver bcm_spu_pdriver = { 47928c2ecf20Sopenharmony_ci .driver = { 47938c2ecf20Sopenharmony_ci .name = "brcm-spu-crypto", 47948c2ecf20Sopenharmony_ci .of_match_table = of_match_ptr(bcm_spu_dt_ids), 47958c2ecf20Sopenharmony_ci }, 47968c2ecf20Sopenharmony_ci .probe = bcm_spu_probe, 47978c2ecf20Sopenharmony_ci .remove = bcm_spu_remove, 47988c2ecf20Sopenharmony_ci}; 47998c2ecf20Sopenharmony_cimodule_platform_driver(bcm_spu_pdriver); 48008c2ecf20Sopenharmony_ci 48018c2ecf20Sopenharmony_ciMODULE_AUTHOR("Rob Rice <rob.rice@broadcom.com>"); 48028c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Broadcom symmetric crypto offload driver"); 48038c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 4804