162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * AMD Cryptographic Coprocessor (CCP) AES CMAC crypto API support 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2013,2018 Advanced Micro Devices, Inc. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Author: Tom Lendacky <thomas.lendacky@amd.com> 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/module.h> 1162306a36Sopenharmony_ci#include <linux/sched.h> 1262306a36Sopenharmony_ci#include <linux/delay.h> 1362306a36Sopenharmony_ci#include <linux/scatterlist.h> 1462306a36Sopenharmony_ci#include <linux/crypto.h> 1562306a36Sopenharmony_ci#include <crypto/algapi.h> 1662306a36Sopenharmony_ci#include <crypto/aes.h> 1762306a36Sopenharmony_ci#include <crypto/hash.h> 1862306a36Sopenharmony_ci#include <crypto/internal/hash.h> 1962306a36Sopenharmony_ci#include <crypto/scatterwalk.h> 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#include "ccp-crypto.h" 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistatic int ccp_aes_cmac_complete(struct crypto_async_request *async_req, 2462306a36Sopenharmony_ci int ret) 2562306a36Sopenharmony_ci{ 2662306a36Sopenharmony_ci struct ahash_request *req = ahash_request_cast(async_req); 2762306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 2862306a36Sopenharmony_ci struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx_dma(req); 2962306a36Sopenharmony_ci unsigned int digest_size = crypto_ahash_digestsize(tfm); 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci if (ret) 3262306a36Sopenharmony_ci goto e_free; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci if (rctx->hash_rem) { 3562306a36Sopenharmony_ci /* Save remaining data to buffer */ 3662306a36Sopenharmony_ci unsigned int offset = rctx->nbytes - rctx->hash_rem; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci scatterwalk_map_and_copy(rctx->buf, rctx->src, 3962306a36Sopenharmony_ci offset, rctx->hash_rem, 0); 4062306a36Sopenharmony_ci rctx->buf_count = rctx->hash_rem; 4162306a36Sopenharmony_ci } else { 4262306a36Sopenharmony_ci rctx->buf_count = 0; 4362306a36Sopenharmony_ci } 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci /* Update result area if supplied */ 4662306a36Sopenharmony_ci if (req->result && rctx->final) 4762306a36Sopenharmony_ci memcpy(req->result, rctx->iv, digest_size); 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_cie_free: 5062306a36Sopenharmony_ci sg_free_table(&rctx->data_sg); 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci return ret; 5362306a36Sopenharmony_ci} 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_cistatic int ccp_do_cmac_update(struct ahash_request *req, unsigned int nbytes, 5662306a36Sopenharmony_ci unsigned int final) 5762306a36Sopenharmony_ci{ 5862306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 5962306a36Sopenharmony_ci struct ccp_ctx *ctx = crypto_ahash_ctx_dma(tfm); 6062306a36Sopenharmony_ci struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx_dma(req); 6162306a36Sopenharmony_ci struct scatterlist *sg, *cmac_key_sg = NULL; 6262306a36Sopenharmony_ci unsigned int block_size = 6362306a36Sopenharmony_ci crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); 6462306a36Sopenharmony_ci unsigned int need_pad, sg_count; 6562306a36Sopenharmony_ci gfp_t gfp; 6662306a36Sopenharmony_ci u64 len; 6762306a36Sopenharmony_ci int ret; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci if (!ctx->u.aes.key_len) 7062306a36Sopenharmony_ci return -EINVAL; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci if (nbytes) 7362306a36Sopenharmony_ci rctx->null_msg = 0; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci len = (u64)rctx->buf_count + (u64)nbytes; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci if (!final && (len <= block_size)) { 7862306a36Sopenharmony_ci scatterwalk_map_and_copy(rctx->buf + rctx->buf_count, req->src, 7962306a36Sopenharmony_ci 0, nbytes, 0); 8062306a36Sopenharmony_ci rctx->buf_count += nbytes; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci return 0; 8362306a36Sopenharmony_ci } 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci rctx->src = req->src; 8662306a36Sopenharmony_ci rctx->nbytes = nbytes; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci rctx->final = final; 8962306a36Sopenharmony_ci rctx->hash_rem = final ? 0 : len & (block_size - 1); 9062306a36Sopenharmony_ci rctx->hash_cnt = len - rctx->hash_rem; 9162306a36Sopenharmony_ci if (!final && !rctx->hash_rem) { 9262306a36Sopenharmony_ci /* CCP can't do zero length final, so keep some data around */ 9362306a36Sopenharmony_ci rctx->hash_cnt -= block_size; 9462306a36Sopenharmony_ci rctx->hash_rem = block_size; 9562306a36Sopenharmony_ci } 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci if (final && (rctx->null_msg || (len & (block_size - 1)))) 9862306a36Sopenharmony_ci need_pad = 1; 9962306a36Sopenharmony_ci else 10062306a36Sopenharmony_ci need_pad = 0; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci sg_init_one(&rctx->iv_sg, rctx->iv, sizeof(rctx->iv)); 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci /* Build the data scatterlist table - allocate enough entries for all 10562306a36Sopenharmony_ci * possible data pieces (buffer, input data, padding) 10662306a36Sopenharmony_ci */ 10762306a36Sopenharmony_ci sg_count = (nbytes) ? sg_nents(req->src) + 2 : 2; 10862306a36Sopenharmony_ci gfp = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? 10962306a36Sopenharmony_ci GFP_KERNEL : GFP_ATOMIC; 11062306a36Sopenharmony_ci ret = sg_alloc_table(&rctx->data_sg, sg_count, gfp); 11162306a36Sopenharmony_ci if (ret) 11262306a36Sopenharmony_ci return ret; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci sg = NULL; 11562306a36Sopenharmony_ci if (rctx->buf_count) { 11662306a36Sopenharmony_ci sg_init_one(&rctx->buf_sg, rctx->buf, rctx->buf_count); 11762306a36Sopenharmony_ci sg = ccp_crypto_sg_table_add(&rctx->data_sg, &rctx->buf_sg); 11862306a36Sopenharmony_ci if (!sg) { 11962306a36Sopenharmony_ci ret = -EINVAL; 12062306a36Sopenharmony_ci goto e_free; 12162306a36Sopenharmony_ci } 12262306a36Sopenharmony_ci } 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci if (nbytes) { 12562306a36Sopenharmony_ci sg = ccp_crypto_sg_table_add(&rctx->data_sg, req->src); 12662306a36Sopenharmony_ci if (!sg) { 12762306a36Sopenharmony_ci ret = -EINVAL; 12862306a36Sopenharmony_ci goto e_free; 12962306a36Sopenharmony_ci } 13062306a36Sopenharmony_ci } 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci if (need_pad) { 13362306a36Sopenharmony_ci int pad_length = block_size - (len & (block_size - 1)); 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci rctx->hash_cnt += pad_length; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci memset(rctx->pad, 0, sizeof(rctx->pad)); 13862306a36Sopenharmony_ci rctx->pad[0] = 0x80; 13962306a36Sopenharmony_ci sg_init_one(&rctx->pad_sg, rctx->pad, pad_length); 14062306a36Sopenharmony_ci sg = ccp_crypto_sg_table_add(&rctx->data_sg, &rctx->pad_sg); 14162306a36Sopenharmony_ci if (!sg) { 14262306a36Sopenharmony_ci ret = -EINVAL; 14362306a36Sopenharmony_ci goto e_free; 14462306a36Sopenharmony_ci } 14562306a36Sopenharmony_ci } 14662306a36Sopenharmony_ci if (sg) { 14762306a36Sopenharmony_ci sg_mark_end(sg); 14862306a36Sopenharmony_ci sg = rctx->data_sg.sgl; 14962306a36Sopenharmony_ci } 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci /* Initialize the K1/K2 scatterlist */ 15262306a36Sopenharmony_ci if (final) 15362306a36Sopenharmony_ci cmac_key_sg = (need_pad) ? &ctx->u.aes.k2_sg 15462306a36Sopenharmony_ci : &ctx->u.aes.k1_sg; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci memset(&rctx->cmd, 0, sizeof(rctx->cmd)); 15762306a36Sopenharmony_ci INIT_LIST_HEAD(&rctx->cmd.entry); 15862306a36Sopenharmony_ci rctx->cmd.engine = CCP_ENGINE_AES; 15962306a36Sopenharmony_ci rctx->cmd.u.aes.type = ctx->u.aes.type; 16062306a36Sopenharmony_ci rctx->cmd.u.aes.mode = ctx->u.aes.mode; 16162306a36Sopenharmony_ci rctx->cmd.u.aes.action = CCP_AES_ACTION_ENCRYPT; 16262306a36Sopenharmony_ci rctx->cmd.u.aes.key = &ctx->u.aes.key_sg; 16362306a36Sopenharmony_ci rctx->cmd.u.aes.key_len = ctx->u.aes.key_len; 16462306a36Sopenharmony_ci rctx->cmd.u.aes.iv = &rctx->iv_sg; 16562306a36Sopenharmony_ci rctx->cmd.u.aes.iv_len = AES_BLOCK_SIZE; 16662306a36Sopenharmony_ci rctx->cmd.u.aes.src = sg; 16762306a36Sopenharmony_ci rctx->cmd.u.aes.src_len = rctx->hash_cnt; 16862306a36Sopenharmony_ci rctx->cmd.u.aes.dst = NULL; 16962306a36Sopenharmony_ci rctx->cmd.u.aes.cmac_key = cmac_key_sg; 17062306a36Sopenharmony_ci rctx->cmd.u.aes.cmac_key_len = ctx->u.aes.kn_len; 17162306a36Sopenharmony_ci rctx->cmd.u.aes.cmac_final = final; 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci ret = ccp_crypto_enqueue_request(&req->base, &rctx->cmd); 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci return ret; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_cie_free: 17862306a36Sopenharmony_ci sg_free_table(&rctx->data_sg); 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci return ret; 18162306a36Sopenharmony_ci} 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_cistatic int ccp_aes_cmac_init(struct ahash_request *req) 18462306a36Sopenharmony_ci{ 18562306a36Sopenharmony_ci struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx_dma(req); 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci memset(rctx, 0, sizeof(*rctx)); 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci rctx->null_msg = 1; 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci return 0; 19262306a36Sopenharmony_ci} 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_cistatic int ccp_aes_cmac_update(struct ahash_request *req) 19562306a36Sopenharmony_ci{ 19662306a36Sopenharmony_ci return ccp_do_cmac_update(req, req->nbytes, 0); 19762306a36Sopenharmony_ci} 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_cistatic int ccp_aes_cmac_final(struct ahash_request *req) 20062306a36Sopenharmony_ci{ 20162306a36Sopenharmony_ci return ccp_do_cmac_update(req, 0, 1); 20262306a36Sopenharmony_ci} 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_cistatic int ccp_aes_cmac_finup(struct ahash_request *req) 20562306a36Sopenharmony_ci{ 20662306a36Sopenharmony_ci return ccp_do_cmac_update(req, req->nbytes, 1); 20762306a36Sopenharmony_ci} 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_cistatic int ccp_aes_cmac_digest(struct ahash_request *req) 21062306a36Sopenharmony_ci{ 21162306a36Sopenharmony_ci int ret; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci ret = ccp_aes_cmac_init(req); 21462306a36Sopenharmony_ci if (ret) 21562306a36Sopenharmony_ci return ret; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci return ccp_aes_cmac_finup(req); 21862306a36Sopenharmony_ci} 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_cistatic int ccp_aes_cmac_export(struct ahash_request *req, void *out) 22162306a36Sopenharmony_ci{ 22262306a36Sopenharmony_ci struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx_dma(req); 22362306a36Sopenharmony_ci struct ccp_aes_cmac_exp_ctx state; 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci /* Don't let anything leak to 'out' */ 22662306a36Sopenharmony_ci memset(&state, 0, sizeof(state)); 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci state.null_msg = rctx->null_msg; 22962306a36Sopenharmony_ci memcpy(state.iv, rctx->iv, sizeof(state.iv)); 23062306a36Sopenharmony_ci state.buf_count = rctx->buf_count; 23162306a36Sopenharmony_ci memcpy(state.buf, rctx->buf, sizeof(state.buf)); 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci /* 'out' may not be aligned so memcpy from local variable */ 23462306a36Sopenharmony_ci memcpy(out, &state, sizeof(state)); 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci return 0; 23762306a36Sopenharmony_ci} 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_cistatic int ccp_aes_cmac_import(struct ahash_request *req, const void *in) 24062306a36Sopenharmony_ci{ 24162306a36Sopenharmony_ci struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx_dma(req); 24262306a36Sopenharmony_ci struct ccp_aes_cmac_exp_ctx state; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci /* 'in' may not be aligned so memcpy to local variable */ 24562306a36Sopenharmony_ci memcpy(&state, in, sizeof(state)); 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci memset(rctx, 0, sizeof(*rctx)); 24862306a36Sopenharmony_ci rctx->null_msg = state.null_msg; 24962306a36Sopenharmony_ci memcpy(rctx->iv, state.iv, sizeof(rctx->iv)); 25062306a36Sopenharmony_ci rctx->buf_count = state.buf_count; 25162306a36Sopenharmony_ci memcpy(rctx->buf, state.buf, sizeof(rctx->buf)); 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci return 0; 25462306a36Sopenharmony_ci} 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_cistatic int ccp_aes_cmac_setkey(struct crypto_ahash *tfm, const u8 *key, 25762306a36Sopenharmony_ci unsigned int key_len) 25862306a36Sopenharmony_ci{ 25962306a36Sopenharmony_ci struct ccp_ctx *ctx = crypto_ahash_ctx_dma(tfm); 26062306a36Sopenharmony_ci struct ccp_crypto_ahash_alg *alg = 26162306a36Sopenharmony_ci ccp_crypto_ahash_alg(crypto_ahash_tfm(tfm)); 26262306a36Sopenharmony_ci u64 k0_hi, k0_lo, k1_hi, k1_lo, k2_hi, k2_lo; 26362306a36Sopenharmony_ci u64 rb_hi = 0x00, rb_lo = 0x87; 26462306a36Sopenharmony_ci struct crypto_aes_ctx aes; 26562306a36Sopenharmony_ci __be64 *gk; 26662306a36Sopenharmony_ci int ret; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci switch (key_len) { 26962306a36Sopenharmony_ci case AES_KEYSIZE_128: 27062306a36Sopenharmony_ci ctx->u.aes.type = CCP_AES_TYPE_128; 27162306a36Sopenharmony_ci break; 27262306a36Sopenharmony_ci case AES_KEYSIZE_192: 27362306a36Sopenharmony_ci ctx->u.aes.type = CCP_AES_TYPE_192; 27462306a36Sopenharmony_ci break; 27562306a36Sopenharmony_ci case AES_KEYSIZE_256: 27662306a36Sopenharmony_ci ctx->u.aes.type = CCP_AES_TYPE_256; 27762306a36Sopenharmony_ci break; 27862306a36Sopenharmony_ci default: 27962306a36Sopenharmony_ci return -EINVAL; 28062306a36Sopenharmony_ci } 28162306a36Sopenharmony_ci ctx->u.aes.mode = alg->mode; 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci /* Set to zero until complete */ 28462306a36Sopenharmony_ci ctx->u.aes.key_len = 0; 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci /* Set the key for the AES cipher used to generate the keys */ 28762306a36Sopenharmony_ci ret = aes_expandkey(&aes, key, key_len); 28862306a36Sopenharmony_ci if (ret) 28962306a36Sopenharmony_ci return ret; 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci /* Encrypt a block of zeroes - use key area in context */ 29262306a36Sopenharmony_ci memset(ctx->u.aes.key, 0, sizeof(ctx->u.aes.key)); 29362306a36Sopenharmony_ci aes_encrypt(&aes, ctx->u.aes.key, ctx->u.aes.key); 29462306a36Sopenharmony_ci memzero_explicit(&aes, sizeof(aes)); 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci /* Generate K1 and K2 */ 29762306a36Sopenharmony_ci k0_hi = be64_to_cpu(*((__be64 *)ctx->u.aes.key)); 29862306a36Sopenharmony_ci k0_lo = be64_to_cpu(*((__be64 *)ctx->u.aes.key + 1)); 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci k1_hi = (k0_hi << 1) | (k0_lo >> 63); 30162306a36Sopenharmony_ci k1_lo = k0_lo << 1; 30262306a36Sopenharmony_ci if (ctx->u.aes.key[0] & 0x80) { 30362306a36Sopenharmony_ci k1_hi ^= rb_hi; 30462306a36Sopenharmony_ci k1_lo ^= rb_lo; 30562306a36Sopenharmony_ci } 30662306a36Sopenharmony_ci gk = (__be64 *)ctx->u.aes.k1; 30762306a36Sopenharmony_ci *gk = cpu_to_be64(k1_hi); 30862306a36Sopenharmony_ci gk++; 30962306a36Sopenharmony_ci *gk = cpu_to_be64(k1_lo); 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci k2_hi = (k1_hi << 1) | (k1_lo >> 63); 31262306a36Sopenharmony_ci k2_lo = k1_lo << 1; 31362306a36Sopenharmony_ci if (ctx->u.aes.k1[0] & 0x80) { 31462306a36Sopenharmony_ci k2_hi ^= rb_hi; 31562306a36Sopenharmony_ci k2_lo ^= rb_lo; 31662306a36Sopenharmony_ci } 31762306a36Sopenharmony_ci gk = (__be64 *)ctx->u.aes.k2; 31862306a36Sopenharmony_ci *gk = cpu_to_be64(k2_hi); 31962306a36Sopenharmony_ci gk++; 32062306a36Sopenharmony_ci *gk = cpu_to_be64(k2_lo); 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci ctx->u.aes.kn_len = sizeof(ctx->u.aes.k1); 32362306a36Sopenharmony_ci sg_init_one(&ctx->u.aes.k1_sg, ctx->u.aes.k1, sizeof(ctx->u.aes.k1)); 32462306a36Sopenharmony_ci sg_init_one(&ctx->u.aes.k2_sg, ctx->u.aes.k2, sizeof(ctx->u.aes.k2)); 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci /* Save the supplied key */ 32762306a36Sopenharmony_ci memset(ctx->u.aes.key, 0, sizeof(ctx->u.aes.key)); 32862306a36Sopenharmony_ci memcpy(ctx->u.aes.key, key, key_len); 32962306a36Sopenharmony_ci ctx->u.aes.key_len = key_len; 33062306a36Sopenharmony_ci sg_init_one(&ctx->u.aes.key_sg, ctx->u.aes.key, key_len); 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci return ret; 33362306a36Sopenharmony_ci} 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_cistatic int ccp_aes_cmac_cra_init(struct crypto_tfm *tfm) 33662306a36Sopenharmony_ci{ 33762306a36Sopenharmony_ci struct ccp_ctx *ctx = crypto_tfm_ctx_dma(tfm); 33862306a36Sopenharmony_ci struct crypto_ahash *ahash = __crypto_ahash_cast(tfm); 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci ctx->complete = ccp_aes_cmac_complete; 34162306a36Sopenharmony_ci ctx->u.aes.key_len = 0; 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci crypto_ahash_set_reqsize_dma(ahash, 34462306a36Sopenharmony_ci sizeof(struct ccp_aes_cmac_req_ctx)); 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci return 0; 34762306a36Sopenharmony_ci} 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ciint ccp_register_aes_cmac_algs(struct list_head *head) 35062306a36Sopenharmony_ci{ 35162306a36Sopenharmony_ci struct ccp_crypto_ahash_alg *ccp_alg; 35262306a36Sopenharmony_ci struct ahash_alg *alg; 35362306a36Sopenharmony_ci struct hash_alg_common *halg; 35462306a36Sopenharmony_ci struct crypto_alg *base; 35562306a36Sopenharmony_ci int ret; 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci ccp_alg = kzalloc(sizeof(*ccp_alg), GFP_KERNEL); 35862306a36Sopenharmony_ci if (!ccp_alg) 35962306a36Sopenharmony_ci return -ENOMEM; 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci INIT_LIST_HEAD(&ccp_alg->entry); 36262306a36Sopenharmony_ci ccp_alg->mode = CCP_AES_MODE_CMAC; 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci alg = &ccp_alg->alg; 36562306a36Sopenharmony_ci alg->init = ccp_aes_cmac_init; 36662306a36Sopenharmony_ci alg->update = ccp_aes_cmac_update; 36762306a36Sopenharmony_ci alg->final = ccp_aes_cmac_final; 36862306a36Sopenharmony_ci alg->finup = ccp_aes_cmac_finup; 36962306a36Sopenharmony_ci alg->digest = ccp_aes_cmac_digest; 37062306a36Sopenharmony_ci alg->export = ccp_aes_cmac_export; 37162306a36Sopenharmony_ci alg->import = ccp_aes_cmac_import; 37262306a36Sopenharmony_ci alg->setkey = ccp_aes_cmac_setkey; 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci halg = &alg->halg; 37562306a36Sopenharmony_ci halg->digestsize = AES_BLOCK_SIZE; 37662306a36Sopenharmony_ci halg->statesize = sizeof(struct ccp_aes_cmac_exp_ctx); 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci base = &halg->base; 37962306a36Sopenharmony_ci snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, "cmac(aes)"); 38062306a36Sopenharmony_ci snprintf(base->cra_driver_name, CRYPTO_MAX_ALG_NAME, "cmac-aes-ccp"); 38162306a36Sopenharmony_ci base->cra_flags = CRYPTO_ALG_ASYNC | 38262306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 38362306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY | 38462306a36Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK; 38562306a36Sopenharmony_ci base->cra_blocksize = AES_BLOCK_SIZE; 38662306a36Sopenharmony_ci base->cra_ctxsize = sizeof(struct ccp_ctx) + crypto_dma_padding(); 38762306a36Sopenharmony_ci base->cra_priority = CCP_CRA_PRIORITY; 38862306a36Sopenharmony_ci base->cra_init = ccp_aes_cmac_cra_init; 38962306a36Sopenharmony_ci base->cra_module = THIS_MODULE; 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci ret = crypto_register_ahash(alg); 39262306a36Sopenharmony_ci if (ret) { 39362306a36Sopenharmony_ci pr_err("%s ahash algorithm registration error (%d)\n", 39462306a36Sopenharmony_ci base->cra_name, ret); 39562306a36Sopenharmony_ci kfree(ccp_alg); 39662306a36Sopenharmony_ci return ret; 39762306a36Sopenharmony_ci } 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci list_add(&ccp_alg->entry, head); 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci return 0; 40262306a36Sopenharmony_ci} 403