18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * AMD Cryptographic Coprocessor (CCP) AES CMAC crypto API support 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2013,2018 Advanced Micro Devices, Inc. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Author: Tom Lendacky <thomas.lendacky@amd.com> 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/module.h> 118c2ecf20Sopenharmony_ci#include <linux/sched.h> 128c2ecf20Sopenharmony_ci#include <linux/delay.h> 138c2ecf20Sopenharmony_ci#include <linux/scatterlist.h> 148c2ecf20Sopenharmony_ci#include <linux/crypto.h> 158c2ecf20Sopenharmony_ci#include <crypto/algapi.h> 168c2ecf20Sopenharmony_ci#include <crypto/aes.h> 178c2ecf20Sopenharmony_ci#include <crypto/hash.h> 188c2ecf20Sopenharmony_ci#include <crypto/internal/hash.h> 198c2ecf20Sopenharmony_ci#include <crypto/scatterwalk.h> 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#include "ccp-crypto.h" 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_cistatic int ccp_aes_cmac_complete(struct crypto_async_request *async_req, 248c2ecf20Sopenharmony_ci int ret) 258c2ecf20Sopenharmony_ci{ 268c2ecf20Sopenharmony_ci struct ahash_request *req = ahash_request_cast(async_req); 278c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 288c2ecf20Sopenharmony_ci struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx(req); 298c2ecf20Sopenharmony_ci unsigned int digest_size = crypto_ahash_digestsize(tfm); 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci if (ret) 328c2ecf20Sopenharmony_ci goto e_free; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci if (rctx->hash_rem) { 358c2ecf20Sopenharmony_ci /* Save remaining data to buffer */ 368c2ecf20Sopenharmony_ci unsigned int offset = rctx->nbytes - rctx->hash_rem; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci scatterwalk_map_and_copy(rctx->buf, rctx->src, 398c2ecf20Sopenharmony_ci offset, rctx->hash_rem, 0); 408c2ecf20Sopenharmony_ci rctx->buf_count = rctx->hash_rem; 418c2ecf20Sopenharmony_ci } else { 428c2ecf20Sopenharmony_ci rctx->buf_count = 0; 438c2ecf20Sopenharmony_ci } 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci /* Update result area if supplied */ 468c2ecf20Sopenharmony_ci if (req->result && rctx->final) 478c2ecf20Sopenharmony_ci memcpy(req->result, rctx->iv, digest_size); 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_cie_free: 508c2ecf20Sopenharmony_ci sg_free_table(&rctx->data_sg); 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci return ret; 538c2ecf20Sopenharmony_ci} 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_cistatic int ccp_do_cmac_update(struct ahash_request *req, unsigned int nbytes, 568c2ecf20Sopenharmony_ci unsigned int final) 578c2ecf20Sopenharmony_ci{ 588c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 598c2ecf20Sopenharmony_ci struct ccp_ctx *ctx = crypto_ahash_ctx(tfm); 608c2ecf20Sopenharmony_ci struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx(req); 618c2ecf20Sopenharmony_ci struct scatterlist *sg, *cmac_key_sg = NULL; 628c2ecf20Sopenharmony_ci unsigned int block_size = 638c2ecf20Sopenharmony_ci crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); 648c2ecf20Sopenharmony_ci unsigned int need_pad, sg_count; 658c2ecf20Sopenharmony_ci gfp_t gfp; 668c2ecf20Sopenharmony_ci u64 len; 678c2ecf20Sopenharmony_ci int ret; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci if (!ctx->u.aes.key_len) 708c2ecf20Sopenharmony_ci return -EINVAL; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci if (nbytes) 738c2ecf20Sopenharmony_ci rctx->null_msg = 0; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci len = (u64)rctx->buf_count + (u64)nbytes; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci if (!final && (len <= block_size)) { 788c2ecf20Sopenharmony_ci scatterwalk_map_and_copy(rctx->buf + rctx->buf_count, req->src, 798c2ecf20Sopenharmony_ci 0, nbytes, 0); 808c2ecf20Sopenharmony_ci rctx->buf_count += nbytes; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci return 0; 838c2ecf20Sopenharmony_ci } 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci rctx->src = req->src; 868c2ecf20Sopenharmony_ci rctx->nbytes = nbytes; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci rctx->final = final; 898c2ecf20Sopenharmony_ci rctx->hash_rem = final ? 0 : len & (block_size - 1); 908c2ecf20Sopenharmony_ci rctx->hash_cnt = len - rctx->hash_rem; 918c2ecf20Sopenharmony_ci if (!final && !rctx->hash_rem) { 928c2ecf20Sopenharmony_ci /* CCP can't do zero length final, so keep some data around */ 938c2ecf20Sopenharmony_ci rctx->hash_cnt -= block_size; 948c2ecf20Sopenharmony_ci rctx->hash_rem = block_size; 958c2ecf20Sopenharmony_ci } 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci if (final && (rctx->null_msg || (len & (block_size - 1)))) 988c2ecf20Sopenharmony_ci need_pad = 1; 998c2ecf20Sopenharmony_ci else 1008c2ecf20Sopenharmony_ci need_pad = 0; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci sg_init_one(&rctx->iv_sg, rctx->iv, sizeof(rctx->iv)); 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci /* Build the data scatterlist table - allocate enough entries for all 1058c2ecf20Sopenharmony_ci * possible data pieces (buffer, input data, padding) 1068c2ecf20Sopenharmony_ci */ 1078c2ecf20Sopenharmony_ci sg_count = (nbytes) ? sg_nents(req->src) + 2 : 2; 1088c2ecf20Sopenharmony_ci gfp = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? 1098c2ecf20Sopenharmony_ci GFP_KERNEL : GFP_ATOMIC; 1108c2ecf20Sopenharmony_ci ret = sg_alloc_table(&rctx->data_sg, sg_count, gfp); 1118c2ecf20Sopenharmony_ci if (ret) 1128c2ecf20Sopenharmony_ci return ret; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci sg = NULL; 1158c2ecf20Sopenharmony_ci if (rctx->buf_count) { 1168c2ecf20Sopenharmony_ci sg_init_one(&rctx->buf_sg, rctx->buf, rctx->buf_count); 1178c2ecf20Sopenharmony_ci sg = ccp_crypto_sg_table_add(&rctx->data_sg, &rctx->buf_sg); 1188c2ecf20Sopenharmony_ci if (!sg) { 1198c2ecf20Sopenharmony_ci ret = -EINVAL; 1208c2ecf20Sopenharmony_ci goto e_free; 1218c2ecf20Sopenharmony_ci } 1228c2ecf20Sopenharmony_ci } 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci if (nbytes) { 1258c2ecf20Sopenharmony_ci sg = ccp_crypto_sg_table_add(&rctx->data_sg, req->src); 1268c2ecf20Sopenharmony_ci if (!sg) { 1278c2ecf20Sopenharmony_ci ret = -EINVAL; 1288c2ecf20Sopenharmony_ci goto e_free; 1298c2ecf20Sopenharmony_ci } 1308c2ecf20Sopenharmony_ci } 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci if (need_pad) { 1338c2ecf20Sopenharmony_ci int pad_length = block_size - (len & (block_size - 1)); 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci rctx->hash_cnt += pad_length; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci memset(rctx->pad, 0, sizeof(rctx->pad)); 1388c2ecf20Sopenharmony_ci rctx->pad[0] = 0x80; 1398c2ecf20Sopenharmony_ci sg_init_one(&rctx->pad_sg, rctx->pad, pad_length); 1408c2ecf20Sopenharmony_ci sg = ccp_crypto_sg_table_add(&rctx->data_sg, &rctx->pad_sg); 1418c2ecf20Sopenharmony_ci if (!sg) { 1428c2ecf20Sopenharmony_ci ret = -EINVAL; 1438c2ecf20Sopenharmony_ci goto e_free; 1448c2ecf20Sopenharmony_ci } 1458c2ecf20Sopenharmony_ci } 1468c2ecf20Sopenharmony_ci if (sg) { 1478c2ecf20Sopenharmony_ci sg_mark_end(sg); 1488c2ecf20Sopenharmony_ci sg = rctx->data_sg.sgl; 1498c2ecf20Sopenharmony_ci } 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci /* Initialize the K1/K2 scatterlist */ 1528c2ecf20Sopenharmony_ci if (final) 1538c2ecf20Sopenharmony_ci cmac_key_sg = (need_pad) ? &ctx->u.aes.k2_sg 1548c2ecf20Sopenharmony_ci : &ctx->u.aes.k1_sg; 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci memset(&rctx->cmd, 0, sizeof(rctx->cmd)); 1578c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&rctx->cmd.entry); 1588c2ecf20Sopenharmony_ci rctx->cmd.engine = CCP_ENGINE_AES; 1598c2ecf20Sopenharmony_ci rctx->cmd.u.aes.type = ctx->u.aes.type; 1608c2ecf20Sopenharmony_ci rctx->cmd.u.aes.mode = ctx->u.aes.mode; 1618c2ecf20Sopenharmony_ci rctx->cmd.u.aes.action = CCP_AES_ACTION_ENCRYPT; 1628c2ecf20Sopenharmony_ci rctx->cmd.u.aes.key = &ctx->u.aes.key_sg; 1638c2ecf20Sopenharmony_ci rctx->cmd.u.aes.key_len = ctx->u.aes.key_len; 1648c2ecf20Sopenharmony_ci rctx->cmd.u.aes.iv = &rctx->iv_sg; 1658c2ecf20Sopenharmony_ci rctx->cmd.u.aes.iv_len = AES_BLOCK_SIZE; 1668c2ecf20Sopenharmony_ci rctx->cmd.u.aes.src = sg; 1678c2ecf20Sopenharmony_ci rctx->cmd.u.aes.src_len = rctx->hash_cnt; 1688c2ecf20Sopenharmony_ci rctx->cmd.u.aes.dst = NULL; 1698c2ecf20Sopenharmony_ci rctx->cmd.u.aes.cmac_key = cmac_key_sg; 1708c2ecf20Sopenharmony_ci rctx->cmd.u.aes.cmac_key_len = ctx->u.aes.kn_len; 1718c2ecf20Sopenharmony_ci rctx->cmd.u.aes.cmac_final = final; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci ret = ccp_crypto_enqueue_request(&req->base, &rctx->cmd); 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci return ret; 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_cie_free: 1788c2ecf20Sopenharmony_ci sg_free_table(&rctx->data_sg); 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci return ret; 1818c2ecf20Sopenharmony_ci} 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_cistatic int ccp_aes_cmac_init(struct ahash_request *req) 1848c2ecf20Sopenharmony_ci{ 1858c2ecf20Sopenharmony_ci struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx(req); 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci memset(rctx, 0, sizeof(*rctx)); 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci rctx->null_msg = 1; 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci return 0; 1928c2ecf20Sopenharmony_ci} 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_cistatic int ccp_aes_cmac_update(struct ahash_request *req) 1958c2ecf20Sopenharmony_ci{ 1968c2ecf20Sopenharmony_ci return ccp_do_cmac_update(req, req->nbytes, 0); 1978c2ecf20Sopenharmony_ci} 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_cistatic int ccp_aes_cmac_final(struct ahash_request *req) 2008c2ecf20Sopenharmony_ci{ 2018c2ecf20Sopenharmony_ci return ccp_do_cmac_update(req, 0, 1); 2028c2ecf20Sopenharmony_ci} 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_cistatic int ccp_aes_cmac_finup(struct ahash_request *req) 2058c2ecf20Sopenharmony_ci{ 2068c2ecf20Sopenharmony_ci return ccp_do_cmac_update(req, req->nbytes, 1); 2078c2ecf20Sopenharmony_ci} 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_cistatic int ccp_aes_cmac_digest(struct ahash_request *req) 2108c2ecf20Sopenharmony_ci{ 2118c2ecf20Sopenharmony_ci int ret; 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci ret = ccp_aes_cmac_init(req); 2148c2ecf20Sopenharmony_ci if (ret) 2158c2ecf20Sopenharmony_ci return ret; 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci return ccp_aes_cmac_finup(req); 2188c2ecf20Sopenharmony_ci} 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_cistatic int ccp_aes_cmac_export(struct ahash_request *req, void *out) 2218c2ecf20Sopenharmony_ci{ 2228c2ecf20Sopenharmony_ci struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx(req); 2238c2ecf20Sopenharmony_ci struct ccp_aes_cmac_exp_ctx state; 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci /* Don't let anything leak to 'out' */ 2268c2ecf20Sopenharmony_ci memset(&state, 0, sizeof(state)); 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci state.null_msg = rctx->null_msg; 2298c2ecf20Sopenharmony_ci memcpy(state.iv, rctx->iv, sizeof(state.iv)); 2308c2ecf20Sopenharmony_ci state.buf_count = rctx->buf_count; 2318c2ecf20Sopenharmony_ci memcpy(state.buf, rctx->buf, sizeof(state.buf)); 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci /* 'out' may not be aligned so memcpy from local variable */ 2348c2ecf20Sopenharmony_ci memcpy(out, &state, sizeof(state)); 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci return 0; 2378c2ecf20Sopenharmony_ci} 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_cistatic int ccp_aes_cmac_import(struct ahash_request *req, const void *in) 2408c2ecf20Sopenharmony_ci{ 2418c2ecf20Sopenharmony_ci struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx(req); 2428c2ecf20Sopenharmony_ci struct ccp_aes_cmac_exp_ctx state; 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci /* 'in' may not be aligned so memcpy to local variable */ 2458c2ecf20Sopenharmony_ci memcpy(&state, in, sizeof(state)); 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci memset(rctx, 0, sizeof(*rctx)); 2488c2ecf20Sopenharmony_ci rctx->null_msg = state.null_msg; 2498c2ecf20Sopenharmony_ci memcpy(rctx->iv, state.iv, sizeof(rctx->iv)); 2508c2ecf20Sopenharmony_ci rctx->buf_count = state.buf_count; 2518c2ecf20Sopenharmony_ci memcpy(rctx->buf, state.buf, sizeof(rctx->buf)); 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci return 0; 2548c2ecf20Sopenharmony_ci} 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_cistatic int ccp_aes_cmac_setkey(struct crypto_ahash *tfm, const u8 *key, 2578c2ecf20Sopenharmony_ci unsigned int key_len) 2588c2ecf20Sopenharmony_ci{ 2598c2ecf20Sopenharmony_ci struct ccp_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 2608c2ecf20Sopenharmony_ci struct ccp_crypto_ahash_alg *alg = 2618c2ecf20Sopenharmony_ci ccp_crypto_ahash_alg(crypto_ahash_tfm(tfm)); 2628c2ecf20Sopenharmony_ci u64 k0_hi, k0_lo, k1_hi, k1_lo, k2_hi, k2_lo; 2638c2ecf20Sopenharmony_ci u64 rb_hi = 0x00, rb_lo = 0x87; 2648c2ecf20Sopenharmony_ci struct crypto_aes_ctx aes; 2658c2ecf20Sopenharmony_ci __be64 *gk; 2668c2ecf20Sopenharmony_ci int ret; 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci switch (key_len) { 2698c2ecf20Sopenharmony_ci case AES_KEYSIZE_128: 2708c2ecf20Sopenharmony_ci ctx->u.aes.type = CCP_AES_TYPE_128; 2718c2ecf20Sopenharmony_ci break; 2728c2ecf20Sopenharmony_ci case AES_KEYSIZE_192: 2738c2ecf20Sopenharmony_ci ctx->u.aes.type = CCP_AES_TYPE_192; 2748c2ecf20Sopenharmony_ci break; 2758c2ecf20Sopenharmony_ci case AES_KEYSIZE_256: 2768c2ecf20Sopenharmony_ci ctx->u.aes.type = CCP_AES_TYPE_256; 2778c2ecf20Sopenharmony_ci break; 2788c2ecf20Sopenharmony_ci default: 2798c2ecf20Sopenharmony_ci return -EINVAL; 2808c2ecf20Sopenharmony_ci } 2818c2ecf20Sopenharmony_ci ctx->u.aes.mode = alg->mode; 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci /* Set to zero until complete */ 2848c2ecf20Sopenharmony_ci ctx->u.aes.key_len = 0; 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci /* Set the key for the AES cipher used to generate the keys */ 2878c2ecf20Sopenharmony_ci ret = aes_expandkey(&aes, key, key_len); 2888c2ecf20Sopenharmony_ci if (ret) 2898c2ecf20Sopenharmony_ci return ret; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci /* Encrypt a block of zeroes - use key area in context */ 2928c2ecf20Sopenharmony_ci memset(ctx->u.aes.key, 0, sizeof(ctx->u.aes.key)); 2938c2ecf20Sopenharmony_ci aes_encrypt(&aes, ctx->u.aes.key, ctx->u.aes.key); 2948c2ecf20Sopenharmony_ci memzero_explicit(&aes, sizeof(aes)); 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci /* Generate K1 and K2 */ 2978c2ecf20Sopenharmony_ci k0_hi = be64_to_cpu(*((__be64 *)ctx->u.aes.key)); 2988c2ecf20Sopenharmony_ci k0_lo = be64_to_cpu(*((__be64 *)ctx->u.aes.key + 1)); 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci k1_hi = (k0_hi << 1) | (k0_lo >> 63); 3018c2ecf20Sopenharmony_ci k1_lo = k0_lo << 1; 3028c2ecf20Sopenharmony_ci if (ctx->u.aes.key[0] & 0x80) { 3038c2ecf20Sopenharmony_ci k1_hi ^= rb_hi; 3048c2ecf20Sopenharmony_ci k1_lo ^= rb_lo; 3058c2ecf20Sopenharmony_ci } 3068c2ecf20Sopenharmony_ci gk = (__be64 *)ctx->u.aes.k1; 3078c2ecf20Sopenharmony_ci *gk = cpu_to_be64(k1_hi); 3088c2ecf20Sopenharmony_ci gk++; 3098c2ecf20Sopenharmony_ci *gk = cpu_to_be64(k1_lo); 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci k2_hi = (k1_hi << 1) | (k1_lo >> 63); 3128c2ecf20Sopenharmony_ci k2_lo = k1_lo << 1; 3138c2ecf20Sopenharmony_ci if (ctx->u.aes.k1[0] & 0x80) { 3148c2ecf20Sopenharmony_ci k2_hi ^= rb_hi; 3158c2ecf20Sopenharmony_ci k2_lo ^= rb_lo; 3168c2ecf20Sopenharmony_ci } 3178c2ecf20Sopenharmony_ci gk = (__be64 *)ctx->u.aes.k2; 3188c2ecf20Sopenharmony_ci *gk = cpu_to_be64(k2_hi); 3198c2ecf20Sopenharmony_ci gk++; 3208c2ecf20Sopenharmony_ci *gk = cpu_to_be64(k2_lo); 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci ctx->u.aes.kn_len = sizeof(ctx->u.aes.k1); 3238c2ecf20Sopenharmony_ci sg_init_one(&ctx->u.aes.k1_sg, ctx->u.aes.k1, sizeof(ctx->u.aes.k1)); 3248c2ecf20Sopenharmony_ci sg_init_one(&ctx->u.aes.k2_sg, ctx->u.aes.k2, sizeof(ctx->u.aes.k2)); 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci /* Save the supplied key */ 3278c2ecf20Sopenharmony_ci memset(ctx->u.aes.key, 0, sizeof(ctx->u.aes.key)); 3288c2ecf20Sopenharmony_ci memcpy(ctx->u.aes.key, key, key_len); 3298c2ecf20Sopenharmony_ci ctx->u.aes.key_len = key_len; 3308c2ecf20Sopenharmony_ci sg_init_one(&ctx->u.aes.key_sg, ctx->u.aes.key, key_len); 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci return ret; 3338c2ecf20Sopenharmony_ci} 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_cistatic int ccp_aes_cmac_cra_init(struct crypto_tfm *tfm) 3368c2ecf20Sopenharmony_ci{ 3378c2ecf20Sopenharmony_ci struct ccp_ctx *ctx = crypto_tfm_ctx(tfm); 3388c2ecf20Sopenharmony_ci struct crypto_ahash *ahash = __crypto_ahash_cast(tfm); 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci ctx->complete = ccp_aes_cmac_complete; 3418c2ecf20Sopenharmony_ci ctx->u.aes.key_len = 0; 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci crypto_ahash_set_reqsize(ahash, sizeof(struct ccp_aes_cmac_req_ctx)); 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci return 0; 3468c2ecf20Sopenharmony_ci} 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ciint ccp_register_aes_cmac_algs(struct list_head *head) 3498c2ecf20Sopenharmony_ci{ 3508c2ecf20Sopenharmony_ci struct ccp_crypto_ahash_alg *ccp_alg; 3518c2ecf20Sopenharmony_ci struct ahash_alg *alg; 3528c2ecf20Sopenharmony_ci struct hash_alg_common *halg; 3538c2ecf20Sopenharmony_ci struct crypto_alg *base; 3548c2ecf20Sopenharmony_ci int ret; 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci ccp_alg = kzalloc(sizeof(*ccp_alg), GFP_KERNEL); 3578c2ecf20Sopenharmony_ci if (!ccp_alg) 3588c2ecf20Sopenharmony_ci return -ENOMEM; 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ccp_alg->entry); 3618c2ecf20Sopenharmony_ci ccp_alg->mode = CCP_AES_MODE_CMAC; 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci alg = &ccp_alg->alg; 3648c2ecf20Sopenharmony_ci alg->init = ccp_aes_cmac_init; 3658c2ecf20Sopenharmony_ci alg->update = ccp_aes_cmac_update; 3668c2ecf20Sopenharmony_ci alg->final = ccp_aes_cmac_final; 3678c2ecf20Sopenharmony_ci alg->finup = ccp_aes_cmac_finup; 3688c2ecf20Sopenharmony_ci alg->digest = ccp_aes_cmac_digest; 3698c2ecf20Sopenharmony_ci alg->export = ccp_aes_cmac_export; 3708c2ecf20Sopenharmony_ci alg->import = ccp_aes_cmac_import; 3718c2ecf20Sopenharmony_ci alg->setkey = ccp_aes_cmac_setkey; 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci halg = &alg->halg; 3748c2ecf20Sopenharmony_ci halg->digestsize = AES_BLOCK_SIZE; 3758c2ecf20Sopenharmony_ci halg->statesize = sizeof(struct ccp_aes_cmac_exp_ctx); 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci base = &halg->base; 3788c2ecf20Sopenharmony_ci snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, "cmac(aes)"); 3798c2ecf20Sopenharmony_ci snprintf(base->cra_driver_name, CRYPTO_MAX_ALG_NAME, "cmac-aes-ccp"); 3808c2ecf20Sopenharmony_ci base->cra_flags = CRYPTO_ALG_ASYNC | 3818c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 3828c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY | 3838c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK; 3848c2ecf20Sopenharmony_ci base->cra_blocksize = AES_BLOCK_SIZE; 3858c2ecf20Sopenharmony_ci base->cra_ctxsize = sizeof(struct ccp_ctx); 3868c2ecf20Sopenharmony_ci base->cra_priority = CCP_CRA_PRIORITY; 3878c2ecf20Sopenharmony_ci base->cra_init = ccp_aes_cmac_cra_init; 3888c2ecf20Sopenharmony_ci base->cra_module = THIS_MODULE; 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci ret = crypto_register_ahash(alg); 3918c2ecf20Sopenharmony_ci if (ret) { 3928c2ecf20Sopenharmony_ci pr_err("%s ahash algorithm registration error (%d)\n", 3938c2ecf20Sopenharmony_ci base->cra_name, ret); 3948c2ecf20Sopenharmony_ci kfree(ccp_alg); 3958c2ecf20Sopenharmony_ci return ret; 3968c2ecf20Sopenharmony_ci } 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci list_add(&ccp_alg->entry, head); 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci return 0; 4018c2ecf20Sopenharmony_ci} 402