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