18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/**
38c2ecf20Sopenharmony_ci * AMCC SoC PPC4xx Crypto Driver
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (c) 2008 Applied Micro Circuits Corporation.
68c2ecf20Sopenharmony_ci * All rights reserved. James Hsiao <jhsiao@amcc.com>
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * This file implements the Linux crypto algorithms.
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/kernel.h>
128c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
138c2ecf20Sopenharmony_ci#include <linux/spinlock_types.h>
148c2ecf20Sopenharmony_ci#include <linux/scatterlist.h>
158c2ecf20Sopenharmony_ci#include <linux/crypto.h>
168c2ecf20Sopenharmony_ci#include <linux/hash.h>
178c2ecf20Sopenharmony_ci#include <crypto/internal/hash.h>
188c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h>
198c2ecf20Sopenharmony_ci#include <crypto/algapi.h>
208c2ecf20Sopenharmony_ci#include <crypto/aead.h>
218c2ecf20Sopenharmony_ci#include <crypto/aes.h>
228c2ecf20Sopenharmony_ci#include <crypto/gcm.h>
238c2ecf20Sopenharmony_ci#include <crypto/sha.h>
248c2ecf20Sopenharmony_ci#include <crypto/ctr.h>
258c2ecf20Sopenharmony_ci#include <crypto/skcipher.h>
268c2ecf20Sopenharmony_ci#include "crypto4xx_reg_def.h"
278c2ecf20Sopenharmony_ci#include "crypto4xx_core.h"
288c2ecf20Sopenharmony_ci#include "crypto4xx_sa.h"
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_cistatic void set_dynamic_sa_command_0(struct dynamic_sa_ctl *sa, u32 save_h,
318c2ecf20Sopenharmony_ci				     u32 save_iv, u32 ld_h, u32 ld_iv,
328c2ecf20Sopenharmony_ci				     u32 hdr_proc, u32 h, u32 c, u32 pad_type,
338c2ecf20Sopenharmony_ci				     u32 op_grp, u32 op, u32 dir)
348c2ecf20Sopenharmony_ci{
358c2ecf20Sopenharmony_ci	sa->sa_command_0.w = 0;
368c2ecf20Sopenharmony_ci	sa->sa_command_0.bf.save_hash_state = save_h;
378c2ecf20Sopenharmony_ci	sa->sa_command_0.bf.save_iv = save_iv;
388c2ecf20Sopenharmony_ci	sa->sa_command_0.bf.load_hash_state = ld_h;
398c2ecf20Sopenharmony_ci	sa->sa_command_0.bf.load_iv = ld_iv;
408c2ecf20Sopenharmony_ci	sa->sa_command_0.bf.hdr_proc = hdr_proc;
418c2ecf20Sopenharmony_ci	sa->sa_command_0.bf.hash_alg = h;
428c2ecf20Sopenharmony_ci	sa->sa_command_0.bf.cipher_alg = c;
438c2ecf20Sopenharmony_ci	sa->sa_command_0.bf.pad_type = pad_type & 3;
448c2ecf20Sopenharmony_ci	sa->sa_command_0.bf.extend_pad = pad_type >> 2;
458c2ecf20Sopenharmony_ci	sa->sa_command_0.bf.op_group = op_grp;
468c2ecf20Sopenharmony_ci	sa->sa_command_0.bf.opcode = op;
478c2ecf20Sopenharmony_ci	sa->sa_command_0.bf.dir = dir;
488c2ecf20Sopenharmony_ci}
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_cistatic void set_dynamic_sa_command_1(struct dynamic_sa_ctl *sa, u32 cm,
518c2ecf20Sopenharmony_ci				     u32 hmac_mc, u32 cfb, u32 esn,
528c2ecf20Sopenharmony_ci				     u32 sn_mask, u32 mute, u32 cp_pad,
538c2ecf20Sopenharmony_ci				     u32 cp_pay, u32 cp_hdr)
548c2ecf20Sopenharmony_ci{
558c2ecf20Sopenharmony_ci	sa->sa_command_1.w = 0;
568c2ecf20Sopenharmony_ci	sa->sa_command_1.bf.crypto_mode31 = (cm & 4) >> 2;
578c2ecf20Sopenharmony_ci	sa->sa_command_1.bf.crypto_mode9_8 = cm & 3;
588c2ecf20Sopenharmony_ci	sa->sa_command_1.bf.feedback_mode = cfb;
598c2ecf20Sopenharmony_ci	sa->sa_command_1.bf.sa_rev = 1;
608c2ecf20Sopenharmony_ci	sa->sa_command_1.bf.hmac_muting = hmac_mc;
618c2ecf20Sopenharmony_ci	sa->sa_command_1.bf.extended_seq_num = esn;
628c2ecf20Sopenharmony_ci	sa->sa_command_1.bf.seq_num_mask = sn_mask;
638c2ecf20Sopenharmony_ci	sa->sa_command_1.bf.mutable_bit_proc = mute;
648c2ecf20Sopenharmony_ci	sa->sa_command_1.bf.copy_pad = cp_pad;
658c2ecf20Sopenharmony_ci	sa->sa_command_1.bf.copy_payload = cp_pay;
668c2ecf20Sopenharmony_ci	sa->sa_command_1.bf.copy_hdr = cp_hdr;
678c2ecf20Sopenharmony_ci}
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_cistatic inline int crypto4xx_crypt(struct skcipher_request *req,
708c2ecf20Sopenharmony_ci				  const unsigned int ivlen, bool decrypt,
718c2ecf20Sopenharmony_ci				  bool check_blocksize)
728c2ecf20Sopenharmony_ci{
738c2ecf20Sopenharmony_ci	struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(req);
748c2ecf20Sopenharmony_ci	struct crypto4xx_ctx *ctx = crypto_skcipher_ctx(cipher);
758c2ecf20Sopenharmony_ci	__le32 iv[AES_IV_SIZE];
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	if (check_blocksize && !IS_ALIGNED(req->cryptlen, AES_BLOCK_SIZE))
788c2ecf20Sopenharmony_ci		return -EINVAL;
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	if (ivlen)
818c2ecf20Sopenharmony_ci		crypto4xx_memcpy_to_le32(iv, req->iv, ivlen);
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
848c2ecf20Sopenharmony_ci		req->cryptlen, iv, ivlen, decrypt ? ctx->sa_in : ctx->sa_out,
858c2ecf20Sopenharmony_ci		ctx->sa_len, 0, NULL);
868c2ecf20Sopenharmony_ci}
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ciint crypto4xx_encrypt_noiv_block(struct skcipher_request *req)
898c2ecf20Sopenharmony_ci{
908c2ecf20Sopenharmony_ci	return crypto4xx_crypt(req, 0, false, true);
918c2ecf20Sopenharmony_ci}
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ciint crypto4xx_encrypt_iv_stream(struct skcipher_request *req)
948c2ecf20Sopenharmony_ci{
958c2ecf20Sopenharmony_ci	return crypto4xx_crypt(req, AES_IV_SIZE, false, false);
968c2ecf20Sopenharmony_ci}
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ciint crypto4xx_decrypt_noiv_block(struct skcipher_request *req)
998c2ecf20Sopenharmony_ci{
1008c2ecf20Sopenharmony_ci	return crypto4xx_crypt(req, 0, true, true);
1018c2ecf20Sopenharmony_ci}
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ciint crypto4xx_decrypt_iv_stream(struct skcipher_request *req)
1048c2ecf20Sopenharmony_ci{
1058c2ecf20Sopenharmony_ci	return crypto4xx_crypt(req, AES_IV_SIZE, true, false);
1068c2ecf20Sopenharmony_ci}
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ciint crypto4xx_encrypt_iv_block(struct skcipher_request *req)
1098c2ecf20Sopenharmony_ci{
1108c2ecf20Sopenharmony_ci	return crypto4xx_crypt(req, AES_IV_SIZE, false, true);
1118c2ecf20Sopenharmony_ci}
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ciint crypto4xx_decrypt_iv_block(struct skcipher_request *req)
1148c2ecf20Sopenharmony_ci{
1158c2ecf20Sopenharmony_ci	return crypto4xx_crypt(req, AES_IV_SIZE, true, true);
1168c2ecf20Sopenharmony_ci}
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci/**
1198c2ecf20Sopenharmony_ci * AES Functions
1208c2ecf20Sopenharmony_ci */
1218c2ecf20Sopenharmony_cistatic int crypto4xx_setkey_aes(struct crypto_skcipher *cipher,
1228c2ecf20Sopenharmony_ci				const u8 *key,
1238c2ecf20Sopenharmony_ci				unsigned int keylen,
1248c2ecf20Sopenharmony_ci				unsigned char cm,
1258c2ecf20Sopenharmony_ci				u8 fb)
1268c2ecf20Sopenharmony_ci{
1278c2ecf20Sopenharmony_ci	struct crypto4xx_ctx *ctx = crypto_skcipher_ctx(cipher);
1288c2ecf20Sopenharmony_ci	struct dynamic_sa_ctl *sa;
1298c2ecf20Sopenharmony_ci	int    rc;
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	if (keylen != AES_KEYSIZE_256 && keylen != AES_KEYSIZE_192 &&
1328c2ecf20Sopenharmony_ci	    keylen != AES_KEYSIZE_128)
1338c2ecf20Sopenharmony_ci		return -EINVAL;
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci	/* Create SA */
1368c2ecf20Sopenharmony_ci	if (ctx->sa_in || ctx->sa_out)
1378c2ecf20Sopenharmony_ci		crypto4xx_free_sa(ctx);
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	rc = crypto4xx_alloc_sa(ctx, SA_AES128_LEN + (keylen-16) / 4);
1408c2ecf20Sopenharmony_ci	if (rc)
1418c2ecf20Sopenharmony_ci		return rc;
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	/* Setup SA */
1448c2ecf20Sopenharmony_ci	sa = ctx->sa_in;
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci	set_dynamic_sa_command_0(sa, SA_NOT_SAVE_HASH, (cm == CRYPTO_MODE_ECB ?
1478c2ecf20Sopenharmony_ci				 SA_NOT_SAVE_IV : SA_SAVE_IV),
1488c2ecf20Sopenharmony_ci				 SA_NOT_LOAD_HASH, (cm == CRYPTO_MODE_ECB ?
1498c2ecf20Sopenharmony_ci				 SA_LOAD_IV_FROM_SA : SA_LOAD_IV_FROM_STATE),
1508c2ecf20Sopenharmony_ci				 SA_NO_HEADER_PROC, SA_HASH_ALG_NULL,
1518c2ecf20Sopenharmony_ci				 SA_CIPHER_ALG_AES, SA_PAD_TYPE_ZERO,
1528c2ecf20Sopenharmony_ci				 SA_OP_GROUP_BASIC, SA_OPCODE_DECRYPT,
1538c2ecf20Sopenharmony_ci				 DIR_INBOUND);
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	set_dynamic_sa_command_1(sa, cm, SA_HASH_MODE_HASH,
1568c2ecf20Sopenharmony_ci				 fb, SA_EXTENDED_SN_OFF,
1578c2ecf20Sopenharmony_ci				 SA_SEQ_MASK_OFF, SA_MC_ENABLE,
1588c2ecf20Sopenharmony_ci				 SA_NOT_COPY_PAD, SA_NOT_COPY_PAYLOAD,
1598c2ecf20Sopenharmony_ci				 SA_NOT_COPY_HDR);
1608c2ecf20Sopenharmony_ci	crypto4xx_memcpy_to_le32(get_dynamic_sa_key_field(sa),
1618c2ecf20Sopenharmony_ci				 key, keylen);
1628c2ecf20Sopenharmony_ci	sa->sa_contents.w = SA_AES_CONTENTS | (keylen << 2);
1638c2ecf20Sopenharmony_ci	sa->sa_command_1.bf.key_len = keylen >> 3;
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	memcpy(ctx->sa_out, ctx->sa_in, ctx->sa_len * 4);
1668c2ecf20Sopenharmony_ci	sa = ctx->sa_out;
1678c2ecf20Sopenharmony_ci	sa->sa_command_0.bf.dir = DIR_OUTBOUND;
1688c2ecf20Sopenharmony_ci	/*
1698c2ecf20Sopenharmony_ci	 * SA_OPCODE_ENCRYPT is the same value as SA_OPCODE_DECRYPT.
1708c2ecf20Sopenharmony_ci	 * it's the DIR_(IN|OUT)BOUND that matters
1718c2ecf20Sopenharmony_ci	 */
1728c2ecf20Sopenharmony_ci	sa->sa_command_0.bf.opcode = SA_OPCODE_ENCRYPT;
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	return 0;
1758c2ecf20Sopenharmony_ci}
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ciint crypto4xx_setkey_aes_cbc(struct crypto_skcipher *cipher,
1788c2ecf20Sopenharmony_ci			     const u8 *key, unsigned int keylen)
1798c2ecf20Sopenharmony_ci{
1808c2ecf20Sopenharmony_ci	return crypto4xx_setkey_aes(cipher, key, keylen, CRYPTO_MODE_CBC,
1818c2ecf20Sopenharmony_ci				    CRYPTO_FEEDBACK_MODE_NO_FB);
1828c2ecf20Sopenharmony_ci}
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ciint crypto4xx_setkey_aes_cfb(struct crypto_skcipher *cipher,
1858c2ecf20Sopenharmony_ci			     const u8 *key, unsigned int keylen)
1868c2ecf20Sopenharmony_ci{
1878c2ecf20Sopenharmony_ci	return crypto4xx_setkey_aes(cipher, key, keylen, CRYPTO_MODE_CFB,
1888c2ecf20Sopenharmony_ci				    CRYPTO_FEEDBACK_MODE_128BIT_CFB);
1898c2ecf20Sopenharmony_ci}
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ciint crypto4xx_setkey_aes_ecb(struct crypto_skcipher *cipher,
1928c2ecf20Sopenharmony_ci			     const u8 *key, unsigned int keylen)
1938c2ecf20Sopenharmony_ci{
1948c2ecf20Sopenharmony_ci	return crypto4xx_setkey_aes(cipher, key, keylen, CRYPTO_MODE_ECB,
1958c2ecf20Sopenharmony_ci				    CRYPTO_FEEDBACK_MODE_NO_FB);
1968c2ecf20Sopenharmony_ci}
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ciint crypto4xx_setkey_aes_ofb(struct crypto_skcipher *cipher,
1998c2ecf20Sopenharmony_ci			     const u8 *key, unsigned int keylen)
2008c2ecf20Sopenharmony_ci{
2018c2ecf20Sopenharmony_ci	return crypto4xx_setkey_aes(cipher, key, keylen, CRYPTO_MODE_OFB,
2028c2ecf20Sopenharmony_ci				    CRYPTO_FEEDBACK_MODE_64BIT_OFB);
2038c2ecf20Sopenharmony_ci}
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ciint crypto4xx_setkey_rfc3686(struct crypto_skcipher *cipher,
2068c2ecf20Sopenharmony_ci			     const u8 *key, unsigned int keylen)
2078c2ecf20Sopenharmony_ci{
2088c2ecf20Sopenharmony_ci	struct crypto4xx_ctx *ctx = crypto_skcipher_ctx(cipher);
2098c2ecf20Sopenharmony_ci	int rc;
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci	rc = crypto4xx_setkey_aes(cipher, key, keylen - CTR_RFC3686_NONCE_SIZE,
2128c2ecf20Sopenharmony_ci		CRYPTO_MODE_CTR, CRYPTO_FEEDBACK_MODE_NO_FB);
2138c2ecf20Sopenharmony_ci	if (rc)
2148c2ecf20Sopenharmony_ci		return rc;
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci	ctx->iv_nonce = cpu_to_le32p((u32 *)&key[keylen -
2178c2ecf20Sopenharmony_ci						 CTR_RFC3686_NONCE_SIZE]);
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci	return 0;
2208c2ecf20Sopenharmony_ci}
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ciint crypto4xx_rfc3686_encrypt(struct skcipher_request *req)
2238c2ecf20Sopenharmony_ci{
2248c2ecf20Sopenharmony_ci	struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(req);
2258c2ecf20Sopenharmony_ci	struct crypto4xx_ctx *ctx = crypto_skcipher_ctx(cipher);
2268c2ecf20Sopenharmony_ci	__le32 iv[AES_IV_SIZE / 4] = {
2278c2ecf20Sopenharmony_ci		ctx->iv_nonce,
2288c2ecf20Sopenharmony_ci		cpu_to_le32p((u32 *) req->iv),
2298c2ecf20Sopenharmony_ci		cpu_to_le32p((u32 *) (req->iv + 4)),
2308c2ecf20Sopenharmony_ci		cpu_to_le32(1) };
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci	return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
2338c2ecf20Sopenharmony_ci				  req->cryptlen, iv, AES_IV_SIZE,
2348c2ecf20Sopenharmony_ci				  ctx->sa_out, ctx->sa_len, 0, NULL);
2358c2ecf20Sopenharmony_ci}
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ciint crypto4xx_rfc3686_decrypt(struct skcipher_request *req)
2388c2ecf20Sopenharmony_ci{
2398c2ecf20Sopenharmony_ci	struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(req);
2408c2ecf20Sopenharmony_ci	struct crypto4xx_ctx *ctx = crypto_skcipher_ctx(cipher);
2418c2ecf20Sopenharmony_ci	__le32 iv[AES_IV_SIZE / 4] = {
2428c2ecf20Sopenharmony_ci		ctx->iv_nonce,
2438c2ecf20Sopenharmony_ci		cpu_to_le32p((u32 *) req->iv),
2448c2ecf20Sopenharmony_ci		cpu_to_le32p((u32 *) (req->iv + 4)),
2458c2ecf20Sopenharmony_ci		cpu_to_le32(1) };
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
2488c2ecf20Sopenharmony_ci				  req->cryptlen, iv, AES_IV_SIZE,
2498c2ecf20Sopenharmony_ci				  ctx->sa_out, ctx->sa_len, 0, NULL);
2508c2ecf20Sopenharmony_ci}
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_cistatic int
2538c2ecf20Sopenharmony_cicrypto4xx_ctr_crypt(struct skcipher_request *req, bool encrypt)
2548c2ecf20Sopenharmony_ci{
2558c2ecf20Sopenharmony_ci	struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(req);
2568c2ecf20Sopenharmony_ci	struct crypto4xx_ctx *ctx = crypto_skcipher_ctx(cipher);
2578c2ecf20Sopenharmony_ci	size_t iv_len = crypto_skcipher_ivsize(cipher);
2588c2ecf20Sopenharmony_ci	unsigned int counter = be32_to_cpup((__be32 *)(req->iv + iv_len - 4));
2598c2ecf20Sopenharmony_ci	unsigned int nblks = ALIGN(req->cryptlen, AES_BLOCK_SIZE) /
2608c2ecf20Sopenharmony_ci			AES_BLOCK_SIZE;
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci	/*
2638c2ecf20Sopenharmony_ci	 * The hardware uses only the last 32-bits as the counter while the
2648c2ecf20Sopenharmony_ci	 * kernel tests (aes_ctr_enc_tv_template[4] for example) expect that
2658c2ecf20Sopenharmony_ci	 * the whole IV is a counter.  So fallback if the counter is going to
2668c2ecf20Sopenharmony_ci	 * overlow.
2678c2ecf20Sopenharmony_ci	 */
2688c2ecf20Sopenharmony_ci	if (counter + nblks < counter) {
2698c2ecf20Sopenharmony_ci		SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->sw_cipher.cipher);
2708c2ecf20Sopenharmony_ci		int ret;
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci		skcipher_request_set_sync_tfm(subreq, ctx->sw_cipher.cipher);
2738c2ecf20Sopenharmony_ci		skcipher_request_set_callback(subreq, req->base.flags,
2748c2ecf20Sopenharmony_ci			NULL, NULL);
2758c2ecf20Sopenharmony_ci		skcipher_request_set_crypt(subreq, req->src, req->dst,
2768c2ecf20Sopenharmony_ci			req->cryptlen, req->iv);
2778c2ecf20Sopenharmony_ci		ret = encrypt ? crypto_skcipher_encrypt(subreq)
2788c2ecf20Sopenharmony_ci			: crypto_skcipher_decrypt(subreq);
2798c2ecf20Sopenharmony_ci		skcipher_request_zero(subreq);
2808c2ecf20Sopenharmony_ci		return ret;
2818c2ecf20Sopenharmony_ci	}
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci	return encrypt ? crypto4xx_encrypt_iv_stream(req)
2848c2ecf20Sopenharmony_ci		       : crypto4xx_decrypt_iv_stream(req);
2858c2ecf20Sopenharmony_ci}
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_cistatic int crypto4xx_sk_setup_fallback(struct crypto4xx_ctx *ctx,
2888c2ecf20Sopenharmony_ci				       struct crypto_skcipher *cipher,
2898c2ecf20Sopenharmony_ci				       const u8 *key,
2908c2ecf20Sopenharmony_ci				       unsigned int keylen)
2918c2ecf20Sopenharmony_ci{
2928c2ecf20Sopenharmony_ci	crypto_sync_skcipher_clear_flags(ctx->sw_cipher.cipher,
2938c2ecf20Sopenharmony_ci				    CRYPTO_TFM_REQ_MASK);
2948c2ecf20Sopenharmony_ci	crypto_sync_skcipher_set_flags(ctx->sw_cipher.cipher,
2958c2ecf20Sopenharmony_ci		crypto_skcipher_get_flags(cipher) & CRYPTO_TFM_REQ_MASK);
2968c2ecf20Sopenharmony_ci	return crypto_sync_skcipher_setkey(ctx->sw_cipher.cipher, key, keylen);
2978c2ecf20Sopenharmony_ci}
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ciint crypto4xx_setkey_aes_ctr(struct crypto_skcipher *cipher,
3008c2ecf20Sopenharmony_ci			     const u8 *key, unsigned int keylen)
3018c2ecf20Sopenharmony_ci{
3028c2ecf20Sopenharmony_ci	struct crypto4xx_ctx *ctx = crypto_skcipher_ctx(cipher);
3038c2ecf20Sopenharmony_ci	int rc;
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	rc = crypto4xx_sk_setup_fallback(ctx, cipher, key, keylen);
3068c2ecf20Sopenharmony_ci	if (rc)
3078c2ecf20Sopenharmony_ci		return rc;
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci	return crypto4xx_setkey_aes(cipher, key, keylen,
3108c2ecf20Sopenharmony_ci		CRYPTO_MODE_CTR, CRYPTO_FEEDBACK_MODE_NO_FB);
3118c2ecf20Sopenharmony_ci}
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ciint crypto4xx_encrypt_ctr(struct skcipher_request *req)
3148c2ecf20Sopenharmony_ci{
3158c2ecf20Sopenharmony_ci	return crypto4xx_ctr_crypt(req, true);
3168c2ecf20Sopenharmony_ci}
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ciint crypto4xx_decrypt_ctr(struct skcipher_request *req)
3198c2ecf20Sopenharmony_ci{
3208c2ecf20Sopenharmony_ci	return crypto4xx_ctr_crypt(req, false);
3218c2ecf20Sopenharmony_ci}
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_cistatic inline bool crypto4xx_aead_need_fallback(struct aead_request *req,
3248c2ecf20Sopenharmony_ci						unsigned int len,
3258c2ecf20Sopenharmony_ci						bool is_ccm, bool decrypt)
3268c2ecf20Sopenharmony_ci{
3278c2ecf20Sopenharmony_ci	struct crypto_aead *aead = crypto_aead_reqtfm(req);
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci	/* authsize has to be a multiple of 4 */
3308c2ecf20Sopenharmony_ci	if (aead->authsize & 3)
3318c2ecf20Sopenharmony_ci		return true;
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci	/*
3348c2ecf20Sopenharmony_ci	 * hardware does not handle cases where plaintext
3358c2ecf20Sopenharmony_ci	 * is less than a block.
3368c2ecf20Sopenharmony_ci	 */
3378c2ecf20Sopenharmony_ci	if (len < AES_BLOCK_SIZE)
3388c2ecf20Sopenharmony_ci		return true;
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci	/* assoc len needs to be a multiple of 4 and <= 1020 */
3418c2ecf20Sopenharmony_ci	if (req->assoclen & 0x3 || req->assoclen > 1020)
3428c2ecf20Sopenharmony_ci		return true;
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_ci	/* CCM supports only counter field length of 2 and 4 bytes */
3458c2ecf20Sopenharmony_ci	if (is_ccm && !(req->iv[0] == 1 || req->iv[0] == 3))
3468c2ecf20Sopenharmony_ci		return true;
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_ci	return false;
3498c2ecf20Sopenharmony_ci}
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_cistatic int crypto4xx_aead_fallback(struct aead_request *req,
3528c2ecf20Sopenharmony_ci	struct crypto4xx_ctx *ctx, bool do_decrypt)
3538c2ecf20Sopenharmony_ci{
3548c2ecf20Sopenharmony_ci	struct aead_request *subreq = aead_request_ctx(req);
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ci	aead_request_set_tfm(subreq, ctx->sw_cipher.aead);
3578c2ecf20Sopenharmony_ci	aead_request_set_callback(subreq, req->base.flags,
3588c2ecf20Sopenharmony_ci				  req->base.complete, req->base.data);
3598c2ecf20Sopenharmony_ci	aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen,
3608c2ecf20Sopenharmony_ci			       req->iv);
3618c2ecf20Sopenharmony_ci	aead_request_set_ad(subreq, req->assoclen);
3628c2ecf20Sopenharmony_ci	return do_decrypt ? crypto_aead_decrypt(subreq) :
3638c2ecf20Sopenharmony_ci			    crypto_aead_encrypt(subreq);
3648c2ecf20Sopenharmony_ci}
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_cistatic int crypto4xx_aead_setup_fallback(struct crypto4xx_ctx *ctx,
3678c2ecf20Sopenharmony_ci					 struct crypto_aead *cipher,
3688c2ecf20Sopenharmony_ci					 const u8 *key,
3698c2ecf20Sopenharmony_ci					 unsigned int keylen)
3708c2ecf20Sopenharmony_ci{
3718c2ecf20Sopenharmony_ci	crypto_aead_clear_flags(ctx->sw_cipher.aead, CRYPTO_TFM_REQ_MASK);
3728c2ecf20Sopenharmony_ci	crypto_aead_set_flags(ctx->sw_cipher.aead,
3738c2ecf20Sopenharmony_ci		crypto_aead_get_flags(cipher) & CRYPTO_TFM_REQ_MASK);
3748c2ecf20Sopenharmony_ci	return crypto_aead_setkey(ctx->sw_cipher.aead, key, keylen);
3758c2ecf20Sopenharmony_ci}
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci/**
3788c2ecf20Sopenharmony_ci * AES-CCM Functions
3798c2ecf20Sopenharmony_ci */
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ciint crypto4xx_setkey_aes_ccm(struct crypto_aead *cipher, const u8 *key,
3828c2ecf20Sopenharmony_ci			     unsigned int keylen)
3838c2ecf20Sopenharmony_ci{
3848c2ecf20Sopenharmony_ci	struct crypto_tfm *tfm = crypto_aead_tfm(cipher);
3858c2ecf20Sopenharmony_ci	struct crypto4xx_ctx *ctx = crypto_tfm_ctx(tfm);
3868c2ecf20Sopenharmony_ci	struct dynamic_sa_ctl *sa;
3878c2ecf20Sopenharmony_ci	int rc = 0;
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci	rc = crypto4xx_aead_setup_fallback(ctx, cipher, key, keylen);
3908c2ecf20Sopenharmony_ci	if (rc)
3918c2ecf20Sopenharmony_ci		return rc;
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci	if (ctx->sa_in || ctx->sa_out)
3948c2ecf20Sopenharmony_ci		crypto4xx_free_sa(ctx);
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci	rc = crypto4xx_alloc_sa(ctx, SA_AES128_CCM_LEN + (keylen - 16) / 4);
3978c2ecf20Sopenharmony_ci	if (rc)
3988c2ecf20Sopenharmony_ci		return rc;
3998c2ecf20Sopenharmony_ci
4008c2ecf20Sopenharmony_ci	/* Setup SA */
4018c2ecf20Sopenharmony_ci	sa = (struct dynamic_sa_ctl *) ctx->sa_in;
4028c2ecf20Sopenharmony_ci	sa->sa_contents.w = SA_AES_CCM_CONTENTS | (keylen << 2);
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ci	set_dynamic_sa_command_0(sa, SA_SAVE_HASH, SA_NOT_SAVE_IV,
4058c2ecf20Sopenharmony_ci				 SA_LOAD_HASH_FROM_SA, SA_LOAD_IV_FROM_STATE,
4068c2ecf20Sopenharmony_ci				 SA_NO_HEADER_PROC, SA_HASH_ALG_CBC_MAC,
4078c2ecf20Sopenharmony_ci				 SA_CIPHER_ALG_AES,
4088c2ecf20Sopenharmony_ci				 SA_PAD_TYPE_ZERO, SA_OP_GROUP_BASIC,
4098c2ecf20Sopenharmony_ci				 SA_OPCODE_HASH_DECRYPT, DIR_INBOUND);
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	set_dynamic_sa_command_1(sa, CRYPTO_MODE_CTR, SA_HASH_MODE_HASH,
4128c2ecf20Sopenharmony_ci				 CRYPTO_FEEDBACK_MODE_NO_FB, SA_EXTENDED_SN_OFF,
4138c2ecf20Sopenharmony_ci				 SA_SEQ_MASK_OFF, SA_MC_ENABLE,
4148c2ecf20Sopenharmony_ci				 SA_NOT_COPY_PAD, SA_COPY_PAYLOAD,
4158c2ecf20Sopenharmony_ci				 SA_NOT_COPY_HDR);
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_ci	sa->sa_command_1.bf.key_len = keylen >> 3;
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci	crypto4xx_memcpy_to_le32(get_dynamic_sa_key_field(sa), key, keylen);
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci	memcpy(ctx->sa_out, ctx->sa_in, ctx->sa_len * 4);
4228c2ecf20Sopenharmony_ci	sa = (struct dynamic_sa_ctl *) ctx->sa_out;
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_ci	set_dynamic_sa_command_0(sa, SA_SAVE_HASH, SA_NOT_SAVE_IV,
4258c2ecf20Sopenharmony_ci				 SA_LOAD_HASH_FROM_SA, SA_LOAD_IV_FROM_STATE,
4268c2ecf20Sopenharmony_ci				 SA_NO_HEADER_PROC, SA_HASH_ALG_CBC_MAC,
4278c2ecf20Sopenharmony_ci				 SA_CIPHER_ALG_AES,
4288c2ecf20Sopenharmony_ci				 SA_PAD_TYPE_ZERO, SA_OP_GROUP_BASIC,
4298c2ecf20Sopenharmony_ci				 SA_OPCODE_ENCRYPT_HASH, DIR_OUTBOUND);
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_ci	set_dynamic_sa_command_1(sa, CRYPTO_MODE_CTR, SA_HASH_MODE_HASH,
4328c2ecf20Sopenharmony_ci				 CRYPTO_FEEDBACK_MODE_NO_FB, SA_EXTENDED_SN_OFF,
4338c2ecf20Sopenharmony_ci				 SA_SEQ_MASK_OFF, SA_MC_ENABLE,
4348c2ecf20Sopenharmony_ci				 SA_COPY_PAD, SA_COPY_PAYLOAD,
4358c2ecf20Sopenharmony_ci				 SA_NOT_COPY_HDR);
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci	sa->sa_command_1.bf.key_len = keylen >> 3;
4388c2ecf20Sopenharmony_ci	return 0;
4398c2ecf20Sopenharmony_ci}
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_cistatic int crypto4xx_crypt_aes_ccm(struct aead_request *req, bool decrypt)
4428c2ecf20Sopenharmony_ci{
4438c2ecf20Sopenharmony_ci	struct crypto4xx_ctx *ctx  = crypto_tfm_ctx(req->base.tfm);
4448c2ecf20Sopenharmony_ci	struct crypto4xx_aead_reqctx *rctx = aead_request_ctx(req);
4458c2ecf20Sopenharmony_ci	struct crypto_aead *aead = crypto_aead_reqtfm(req);
4468c2ecf20Sopenharmony_ci	__le32 iv[16];
4478c2ecf20Sopenharmony_ci	u32 tmp_sa[SA_AES128_CCM_LEN + 4];
4488c2ecf20Sopenharmony_ci	struct dynamic_sa_ctl *sa = (struct dynamic_sa_ctl *)tmp_sa;
4498c2ecf20Sopenharmony_ci	unsigned int len = req->cryptlen;
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_ci	if (decrypt)
4528c2ecf20Sopenharmony_ci		len -= crypto_aead_authsize(aead);
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci	if (crypto4xx_aead_need_fallback(req, len, true, decrypt))
4558c2ecf20Sopenharmony_ci		return crypto4xx_aead_fallback(req, ctx, decrypt);
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci	memcpy(tmp_sa, decrypt ? ctx->sa_in : ctx->sa_out, ctx->sa_len * 4);
4588c2ecf20Sopenharmony_ci	sa->sa_command_0.bf.digest_len = crypto_aead_authsize(aead) >> 2;
4598c2ecf20Sopenharmony_ci
4608c2ecf20Sopenharmony_ci	if (req->iv[0] == 1) {
4618c2ecf20Sopenharmony_ci		/* CRYPTO_MODE_AES_ICM */
4628c2ecf20Sopenharmony_ci		sa->sa_command_1.bf.crypto_mode9_8 = 1;
4638c2ecf20Sopenharmony_ci	}
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci	iv[3] = cpu_to_le32(0);
4668c2ecf20Sopenharmony_ci	crypto4xx_memcpy_to_le32(iv, req->iv, 16 - (req->iv[0] + 1));
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_ci	return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
4698c2ecf20Sopenharmony_ci				  len, iv, sizeof(iv),
4708c2ecf20Sopenharmony_ci				  sa, ctx->sa_len, req->assoclen, rctx->dst);
4718c2ecf20Sopenharmony_ci}
4728c2ecf20Sopenharmony_ci
4738c2ecf20Sopenharmony_ciint crypto4xx_encrypt_aes_ccm(struct aead_request *req)
4748c2ecf20Sopenharmony_ci{
4758c2ecf20Sopenharmony_ci	return crypto4xx_crypt_aes_ccm(req, false);
4768c2ecf20Sopenharmony_ci}
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ciint crypto4xx_decrypt_aes_ccm(struct aead_request *req)
4798c2ecf20Sopenharmony_ci{
4808c2ecf20Sopenharmony_ci	return crypto4xx_crypt_aes_ccm(req, true);
4818c2ecf20Sopenharmony_ci}
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ciint crypto4xx_setauthsize_aead(struct crypto_aead *cipher,
4848c2ecf20Sopenharmony_ci			       unsigned int authsize)
4858c2ecf20Sopenharmony_ci{
4868c2ecf20Sopenharmony_ci	struct crypto_tfm *tfm = crypto_aead_tfm(cipher);
4878c2ecf20Sopenharmony_ci	struct crypto4xx_ctx *ctx = crypto_tfm_ctx(tfm);
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_ci	return crypto_aead_setauthsize(ctx->sw_cipher.aead, authsize);
4908c2ecf20Sopenharmony_ci}
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ci/**
4938c2ecf20Sopenharmony_ci * AES-GCM Functions
4948c2ecf20Sopenharmony_ci */
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_cistatic int crypto4xx_aes_gcm_validate_keylen(unsigned int keylen)
4978c2ecf20Sopenharmony_ci{
4988c2ecf20Sopenharmony_ci	switch (keylen) {
4998c2ecf20Sopenharmony_ci	case 16:
5008c2ecf20Sopenharmony_ci	case 24:
5018c2ecf20Sopenharmony_ci	case 32:
5028c2ecf20Sopenharmony_ci		return 0;
5038c2ecf20Sopenharmony_ci	default:
5048c2ecf20Sopenharmony_ci		return -EINVAL;
5058c2ecf20Sopenharmony_ci	}
5068c2ecf20Sopenharmony_ci}
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_cistatic int crypto4xx_compute_gcm_hash_key_sw(__le32 *hash_start, const u8 *key,
5098c2ecf20Sopenharmony_ci					     unsigned int keylen)
5108c2ecf20Sopenharmony_ci{
5118c2ecf20Sopenharmony_ci	struct crypto_aes_ctx ctx;
5128c2ecf20Sopenharmony_ci	uint8_t src[16] = { 0 };
5138c2ecf20Sopenharmony_ci	int rc;
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_ci	rc = aes_expandkey(&ctx, key, keylen);
5168c2ecf20Sopenharmony_ci	if (rc) {
5178c2ecf20Sopenharmony_ci		pr_err("aes_expandkey() failed: %d\n", rc);
5188c2ecf20Sopenharmony_ci		return rc;
5198c2ecf20Sopenharmony_ci	}
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_ci	aes_encrypt(&ctx, src, src);
5228c2ecf20Sopenharmony_ci	crypto4xx_memcpy_to_le32(hash_start, src, 16);
5238c2ecf20Sopenharmony_ci	memzero_explicit(&ctx, sizeof(ctx));
5248c2ecf20Sopenharmony_ci	return 0;
5258c2ecf20Sopenharmony_ci}
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_ciint crypto4xx_setkey_aes_gcm(struct crypto_aead *cipher,
5288c2ecf20Sopenharmony_ci			     const u8 *key, unsigned int keylen)
5298c2ecf20Sopenharmony_ci{
5308c2ecf20Sopenharmony_ci	struct crypto_tfm *tfm = crypto_aead_tfm(cipher);
5318c2ecf20Sopenharmony_ci	struct crypto4xx_ctx *ctx = crypto_tfm_ctx(tfm);
5328c2ecf20Sopenharmony_ci	struct dynamic_sa_ctl *sa;
5338c2ecf20Sopenharmony_ci	int    rc = 0;
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ci	if (crypto4xx_aes_gcm_validate_keylen(keylen) != 0)
5368c2ecf20Sopenharmony_ci		return -EINVAL;
5378c2ecf20Sopenharmony_ci
5388c2ecf20Sopenharmony_ci	rc = crypto4xx_aead_setup_fallback(ctx, cipher, key, keylen);
5398c2ecf20Sopenharmony_ci	if (rc)
5408c2ecf20Sopenharmony_ci		return rc;
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_ci	if (ctx->sa_in || ctx->sa_out)
5438c2ecf20Sopenharmony_ci		crypto4xx_free_sa(ctx);
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_ci	rc = crypto4xx_alloc_sa(ctx, SA_AES128_GCM_LEN + (keylen - 16) / 4);
5468c2ecf20Sopenharmony_ci	if (rc)
5478c2ecf20Sopenharmony_ci		return rc;
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci	sa  = (struct dynamic_sa_ctl *) ctx->sa_in;
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci	sa->sa_contents.w = SA_AES_GCM_CONTENTS | (keylen << 2);
5528c2ecf20Sopenharmony_ci	set_dynamic_sa_command_0(sa, SA_SAVE_HASH, SA_NOT_SAVE_IV,
5538c2ecf20Sopenharmony_ci				 SA_LOAD_HASH_FROM_SA, SA_LOAD_IV_FROM_STATE,
5548c2ecf20Sopenharmony_ci				 SA_NO_HEADER_PROC, SA_HASH_ALG_GHASH,
5558c2ecf20Sopenharmony_ci				 SA_CIPHER_ALG_AES, SA_PAD_TYPE_ZERO,
5568c2ecf20Sopenharmony_ci				 SA_OP_GROUP_BASIC, SA_OPCODE_HASH_DECRYPT,
5578c2ecf20Sopenharmony_ci				 DIR_INBOUND);
5588c2ecf20Sopenharmony_ci	set_dynamic_sa_command_1(sa, CRYPTO_MODE_CTR, SA_HASH_MODE_HASH,
5598c2ecf20Sopenharmony_ci				 CRYPTO_FEEDBACK_MODE_NO_FB, SA_EXTENDED_SN_OFF,
5608c2ecf20Sopenharmony_ci				 SA_SEQ_MASK_ON, SA_MC_DISABLE,
5618c2ecf20Sopenharmony_ci				 SA_NOT_COPY_PAD, SA_COPY_PAYLOAD,
5628c2ecf20Sopenharmony_ci				 SA_NOT_COPY_HDR);
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_ci	sa->sa_command_1.bf.key_len = keylen >> 3;
5658c2ecf20Sopenharmony_ci
5668c2ecf20Sopenharmony_ci	crypto4xx_memcpy_to_le32(get_dynamic_sa_key_field(sa),
5678c2ecf20Sopenharmony_ci				 key, keylen);
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci	rc = crypto4xx_compute_gcm_hash_key_sw(get_dynamic_sa_inner_digest(sa),
5708c2ecf20Sopenharmony_ci		key, keylen);
5718c2ecf20Sopenharmony_ci	if (rc) {
5728c2ecf20Sopenharmony_ci		pr_err("GCM hash key setting failed = %d\n", rc);
5738c2ecf20Sopenharmony_ci		goto err;
5748c2ecf20Sopenharmony_ci	}
5758c2ecf20Sopenharmony_ci
5768c2ecf20Sopenharmony_ci	memcpy(ctx->sa_out, ctx->sa_in, ctx->sa_len * 4);
5778c2ecf20Sopenharmony_ci	sa = (struct dynamic_sa_ctl *) ctx->sa_out;
5788c2ecf20Sopenharmony_ci	sa->sa_command_0.bf.dir = DIR_OUTBOUND;
5798c2ecf20Sopenharmony_ci	sa->sa_command_0.bf.opcode = SA_OPCODE_ENCRYPT_HASH;
5808c2ecf20Sopenharmony_ci
5818c2ecf20Sopenharmony_ci	return 0;
5828c2ecf20Sopenharmony_cierr:
5838c2ecf20Sopenharmony_ci	crypto4xx_free_sa(ctx);
5848c2ecf20Sopenharmony_ci	return rc;
5858c2ecf20Sopenharmony_ci}
5868c2ecf20Sopenharmony_ci
5878c2ecf20Sopenharmony_cistatic inline int crypto4xx_crypt_aes_gcm(struct aead_request *req,
5888c2ecf20Sopenharmony_ci					  bool decrypt)
5898c2ecf20Sopenharmony_ci{
5908c2ecf20Sopenharmony_ci	struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
5918c2ecf20Sopenharmony_ci	struct crypto4xx_aead_reqctx *rctx = aead_request_ctx(req);
5928c2ecf20Sopenharmony_ci	__le32 iv[4];
5938c2ecf20Sopenharmony_ci	unsigned int len = req->cryptlen;
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci	if (decrypt)
5968c2ecf20Sopenharmony_ci		len -= crypto_aead_authsize(crypto_aead_reqtfm(req));
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_ci	if (crypto4xx_aead_need_fallback(req, len, false, decrypt))
5998c2ecf20Sopenharmony_ci		return crypto4xx_aead_fallback(req, ctx, decrypt);
6008c2ecf20Sopenharmony_ci
6018c2ecf20Sopenharmony_ci	crypto4xx_memcpy_to_le32(iv, req->iv, GCM_AES_IV_SIZE);
6028c2ecf20Sopenharmony_ci	iv[3] = cpu_to_le32(1);
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ci	return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
6058c2ecf20Sopenharmony_ci				  len, iv, sizeof(iv),
6068c2ecf20Sopenharmony_ci				  decrypt ? ctx->sa_in : ctx->sa_out,
6078c2ecf20Sopenharmony_ci				  ctx->sa_len, req->assoclen, rctx->dst);
6088c2ecf20Sopenharmony_ci}
6098c2ecf20Sopenharmony_ci
6108c2ecf20Sopenharmony_ciint crypto4xx_encrypt_aes_gcm(struct aead_request *req)
6118c2ecf20Sopenharmony_ci{
6128c2ecf20Sopenharmony_ci	return crypto4xx_crypt_aes_gcm(req, false);
6138c2ecf20Sopenharmony_ci}
6148c2ecf20Sopenharmony_ci
6158c2ecf20Sopenharmony_ciint crypto4xx_decrypt_aes_gcm(struct aead_request *req)
6168c2ecf20Sopenharmony_ci{
6178c2ecf20Sopenharmony_ci	return crypto4xx_crypt_aes_gcm(req, true);
6188c2ecf20Sopenharmony_ci}
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_ci/**
6218c2ecf20Sopenharmony_ci * HASH SHA1 Functions
6228c2ecf20Sopenharmony_ci */
6238c2ecf20Sopenharmony_cistatic int crypto4xx_hash_alg_init(struct crypto_tfm *tfm,
6248c2ecf20Sopenharmony_ci				   unsigned int sa_len,
6258c2ecf20Sopenharmony_ci				   unsigned char ha,
6268c2ecf20Sopenharmony_ci				   unsigned char hm)
6278c2ecf20Sopenharmony_ci{
6288c2ecf20Sopenharmony_ci	struct crypto_alg *alg = tfm->__crt_alg;
6298c2ecf20Sopenharmony_ci	struct crypto4xx_alg *my_alg;
6308c2ecf20Sopenharmony_ci	struct crypto4xx_ctx *ctx = crypto_tfm_ctx(tfm);
6318c2ecf20Sopenharmony_ci	struct dynamic_sa_hash160 *sa;
6328c2ecf20Sopenharmony_ci	int rc;
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_ci	my_alg = container_of(__crypto_ahash_alg(alg), struct crypto4xx_alg,
6358c2ecf20Sopenharmony_ci			      alg.u.hash);
6368c2ecf20Sopenharmony_ci	ctx->dev   = my_alg->dev;
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_ci	/* Create SA */
6398c2ecf20Sopenharmony_ci	if (ctx->sa_in || ctx->sa_out)
6408c2ecf20Sopenharmony_ci		crypto4xx_free_sa(ctx);
6418c2ecf20Sopenharmony_ci
6428c2ecf20Sopenharmony_ci	rc = crypto4xx_alloc_sa(ctx, sa_len);
6438c2ecf20Sopenharmony_ci	if (rc)
6448c2ecf20Sopenharmony_ci		return rc;
6458c2ecf20Sopenharmony_ci
6468c2ecf20Sopenharmony_ci	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
6478c2ecf20Sopenharmony_ci				 sizeof(struct crypto4xx_ctx));
6488c2ecf20Sopenharmony_ci	sa = (struct dynamic_sa_hash160 *)ctx->sa_in;
6498c2ecf20Sopenharmony_ci	set_dynamic_sa_command_0(&sa->ctrl, SA_SAVE_HASH, SA_NOT_SAVE_IV,
6508c2ecf20Sopenharmony_ci				 SA_NOT_LOAD_HASH, SA_LOAD_IV_FROM_SA,
6518c2ecf20Sopenharmony_ci				 SA_NO_HEADER_PROC, ha, SA_CIPHER_ALG_NULL,
6528c2ecf20Sopenharmony_ci				 SA_PAD_TYPE_ZERO, SA_OP_GROUP_BASIC,
6538c2ecf20Sopenharmony_ci				 SA_OPCODE_HASH, DIR_INBOUND);
6548c2ecf20Sopenharmony_ci	set_dynamic_sa_command_1(&sa->ctrl, 0, SA_HASH_MODE_HASH,
6558c2ecf20Sopenharmony_ci				 CRYPTO_FEEDBACK_MODE_NO_FB, SA_EXTENDED_SN_OFF,
6568c2ecf20Sopenharmony_ci				 SA_SEQ_MASK_OFF, SA_MC_ENABLE,
6578c2ecf20Sopenharmony_ci				 SA_NOT_COPY_PAD, SA_NOT_COPY_PAYLOAD,
6588c2ecf20Sopenharmony_ci				 SA_NOT_COPY_HDR);
6598c2ecf20Sopenharmony_ci	/* Need to zero hash digest in SA */
6608c2ecf20Sopenharmony_ci	memset(sa->inner_digest, 0, sizeof(sa->inner_digest));
6618c2ecf20Sopenharmony_ci	memset(sa->outer_digest, 0, sizeof(sa->outer_digest));
6628c2ecf20Sopenharmony_ci
6638c2ecf20Sopenharmony_ci	return 0;
6648c2ecf20Sopenharmony_ci}
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ciint crypto4xx_hash_init(struct ahash_request *req)
6678c2ecf20Sopenharmony_ci{
6688c2ecf20Sopenharmony_ci	struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
6698c2ecf20Sopenharmony_ci	int ds;
6708c2ecf20Sopenharmony_ci	struct dynamic_sa_ctl *sa;
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_ci	sa = ctx->sa_in;
6738c2ecf20Sopenharmony_ci	ds = crypto_ahash_digestsize(
6748c2ecf20Sopenharmony_ci			__crypto_ahash_cast(req->base.tfm));
6758c2ecf20Sopenharmony_ci	sa->sa_command_0.bf.digest_len = ds >> 2;
6768c2ecf20Sopenharmony_ci	sa->sa_command_0.bf.load_hash_state = SA_LOAD_HASH_FROM_SA;
6778c2ecf20Sopenharmony_ci
6788c2ecf20Sopenharmony_ci	return 0;
6798c2ecf20Sopenharmony_ci}
6808c2ecf20Sopenharmony_ci
6818c2ecf20Sopenharmony_ciint crypto4xx_hash_update(struct ahash_request *req)
6828c2ecf20Sopenharmony_ci{
6838c2ecf20Sopenharmony_ci	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
6848c2ecf20Sopenharmony_ci	struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
6858c2ecf20Sopenharmony_ci	struct scatterlist dst;
6868c2ecf20Sopenharmony_ci	unsigned int ds = crypto_ahash_digestsize(ahash);
6878c2ecf20Sopenharmony_ci
6888c2ecf20Sopenharmony_ci	sg_init_one(&dst, req->result, ds);
6898c2ecf20Sopenharmony_ci
6908c2ecf20Sopenharmony_ci	return crypto4xx_build_pd(&req->base, ctx, req->src, &dst,
6918c2ecf20Sopenharmony_ci				  req->nbytes, NULL, 0, ctx->sa_in,
6928c2ecf20Sopenharmony_ci				  ctx->sa_len, 0, NULL);
6938c2ecf20Sopenharmony_ci}
6948c2ecf20Sopenharmony_ci
6958c2ecf20Sopenharmony_ciint crypto4xx_hash_final(struct ahash_request *req)
6968c2ecf20Sopenharmony_ci{
6978c2ecf20Sopenharmony_ci	return 0;
6988c2ecf20Sopenharmony_ci}
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_ciint crypto4xx_hash_digest(struct ahash_request *req)
7018c2ecf20Sopenharmony_ci{
7028c2ecf20Sopenharmony_ci	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
7038c2ecf20Sopenharmony_ci	struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
7048c2ecf20Sopenharmony_ci	struct scatterlist dst;
7058c2ecf20Sopenharmony_ci	unsigned int ds = crypto_ahash_digestsize(ahash);
7068c2ecf20Sopenharmony_ci
7078c2ecf20Sopenharmony_ci	sg_init_one(&dst, req->result, ds);
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_ci	return crypto4xx_build_pd(&req->base, ctx, req->src, &dst,
7108c2ecf20Sopenharmony_ci				  req->nbytes, NULL, 0, ctx->sa_in,
7118c2ecf20Sopenharmony_ci				  ctx->sa_len, 0, NULL);
7128c2ecf20Sopenharmony_ci}
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_ci/**
7158c2ecf20Sopenharmony_ci * SHA1 Algorithm
7168c2ecf20Sopenharmony_ci */
7178c2ecf20Sopenharmony_ciint crypto4xx_sha1_alg_init(struct crypto_tfm *tfm)
7188c2ecf20Sopenharmony_ci{
7198c2ecf20Sopenharmony_ci	return crypto4xx_hash_alg_init(tfm, SA_HASH160_LEN, SA_HASH_ALG_SHA1,
7208c2ecf20Sopenharmony_ci				       SA_HASH_MODE_HASH);
7218c2ecf20Sopenharmony_ci}
722