Path: blob/master/drivers/crypto/ccp/ccp-crypto-aes-galois.c
26282 views
// SPDX-License-Identifier: GPL-2.0-only1/*2* AMD Cryptographic Coprocessor (CCP) AES GCM crypto API support3*4* Copyright (C) 2016,2017 Advanced Micro Devices, Inc.5*6* Author: Gary R Hook <[email protected]>7*/89#include <linux/module.h>10#include <linux/sched.h>11#include <linux/delay.h>12#include <linux/scatterlist.h>13#include <linux/crypto.h>14#include <crypto/internal/aead.h>15#include <crypto/algapi.h>16#include <crypto/aes.h>17#include <crypto/ctr.h>18#include <crypto/gcm.h>19#include <crypto/scatterwalk.h>2021#include "ccp-crypto.h"2223static int ccp_aes_gcm_complete(struct crypto_async_request *async_req, int ret)24{25return ret;26}2728static int ccp_aes_gcm_setkey(struct crypto_aead *tfm, const u8 *key,29unsigned int key_len)30{31struct ccp_ctx *ctx = crypto_aead_ctx_dma(tfm);3233switch (key_len) {34case AES_KEYSIZE_128:35ctx->u.aes.type = CCP_AES_TYPE_128;36break;37case AES_KEYSIZE_192:38ctx->u.aes.type = CCP_AES_TYPE_192;39break;40case AES_KEYSIZE_256:41ctx->u.aes.type = CCP_AES_TYPE_256;42break;43default:44return -EINVAL;45}4647ctx->u.aes.mode = CCP_AES_MODE_GCM;48ctx->u.aes.key_len = key_len;4950memcpy(ctx->u.aes.key, key, key_len);51sg_init_one(&ctx->u.aes.key_sg, ctx->u.aes.key, key_len);5253return 0;54}5556static int ccp_aes_gcm_setauthsize(struct crypto_aead *tfm,57unsigned int authsize)58{59switch (authsize) {60case 16:61case 15:62case 14:63case 13:64case 12:65case 8:66case 4:67break;68default:69return -EINVAL;70}7172return 0;73}7475static int ccp_aes_gcm_crypt(struct aead_request *req, bool encrypt)76{77struct crypto_aead *tfm = crypto_aead_reqtfm(req);78struct ccp_ctx *ctx = crypto_aead_ctx_dma(tfm);79struct ccp_aes_req_ctx *rctx = aead_request_ctx_dma(req);80struct scatterlist *iv_sg = NULL;81unsigned int iv_len = 0;82int i;83int ret = 0;8485if (!ctx->u.aes.key_len)86return -EINVAL;8788if (ctx->u.aes.mode != CCP_AES_MODE_GCM)89return -EINVAL;9091if (!req->iv)92return -EINVAL;9394/*95* 5 parts:96* plaintext/ciphertext input97* AAD98* key99* IV100* Destination+tag buffer101*/102103/* Prepare the IV: 12 bytes + an integer (counter) */104memcpy(rctx->iv, req->iv, GCM_AES_IV_SIZE);105for (i = 0; i < 3; i++)106rctx->iv[i + GCM_AES_IV_SIZE] = 0;107rctx->iv[AES_BLOCK_SIZE - 1] = 1;108109/* Set up a scatterlist for the IV */110iv_sg = &rctx->iv_sg;111iv_len = AES_BLOCK_SIZE;112sg_init_one(iv_sg, rctx->iv, iv_len);113114/* The AAD + plaintext are concatenated in the src buffer */115memset(&rctx->cmd, 0, sizeof(rctx->cmd));116INIT_LIST_HEAD(&rctx->cmd.entry);117rctx->cmd.engine = CCP_ENGINE_AES;118rctx->cmd.u.aes.authsize = crypto_aead_authsize(tfm);119rctx->cmd.u.aes.type = ctx->u.aes.type;120rctx->cmd.u.aes.mode = ctx->u.aes.mode;121rctx->cmd.u.aes.action = encrypt;122rctx->cmd.u.aes.key = &ctx->u.aes.key_sg;123rctx->cmd.u.aes.key_len = ctx->u.aes.key_len;124rctx->cmd.u.aes.iv = iv_sg;125rctx->cmd.u.aes.iv_len = iv_len;126rctx->cmd.u.aes.src = req->src;127rctx->cmd.u.aes.src_len = req->cryptlen;128rctx->cmd.u.aes.aad_len = req->assoclen;129130/* The cipher text + the tag are in the dst buffer */131rctx->cmd.u.aes.dst = req->dst;132133ret = ccp_crypto_enqueue_request(&req->base, &rctx->cmd);134135return ret;136}137138static int ccp_aes_gcm_encrypt(struct aead_request *req)139{140return ccp_aes_gcm_crypt(req, CCP_AES_ACTION_ENCRYPT);141}142143static int ccp_aes_gcm_decrypt(struct aead_request *req)144{145return ccp_aes_gcm_crypt(req, CCP_AES_ACTION_DECRYPT);146}147148static int ccp_aes_gcm_cra_init(struct crypto_aead *tfm)149{150struct ccp_ctx *ctx = crypto_aead_ctx_dma(tfm);151152ctx->complete = ccp_aes_gcm_complete;153ctx->u.aes.key_len = 0;154155crypto_aead_set_reqsize_dma(tfm, sizeof(struct ccp_aes_req_ctx));156157return 0;158}159160static void ccp_aes_gcm_cra_exit(struct crypto_tfm *tfm)161{162}163164static struct aead_alg ccp_aes_gcm_defaults = {165.setkey = ccp_aes_gcm_setkey,166.setauthsize = ccp_aes_gcm_setauthsize,167.encrypt = ccp_aes_gcm_encrypt,168.decrypt = ccp_aes_gcm_decrypt,169.init = ccp_aes_gcm_cra_init,170.ivsize = GCM_AES_IV_SIZE,171.maxauthsize = AES_BLOCK_SIZE,172.base = {173.cra_flags = CRYPTO_ALG_ASYNC |174CRYPTO_ALG_ALLOCATES_MEMORY |175CRYPTO_ALG_KERN_DRIVER_ONLY |176CRYPTO_ALG_NEED_FALLBACK,177.cra_blocksize = AES_BLOCK_SIZE,178.cra_ctxsize = sizeof(struct ccp_ctx) + CRYPTO_DMA_PADDING,179.cra_priority = CCP_CRA_PRIORITY,180.cra_exit = ccp_aes_gcm_cra_exit,181.cra_module = THIS_MODULE,182},183};184185struct ccp_aes_aead_def {186enum ccp_aes_mode mode;187unsigned int version;188const char *name;189const char *driver_name;190unsigned int blocksize;191unsigned int ivsize;192struct aead_alg *alg_defaults;193};194195static struct ccp_aes_aead_def aes_aead_algs[] = {196{197.mode = CCP_AES_MODE_GHASH,198.version = CCP_VERSION(5, 0),199.name = "gcm(aes)",200.driver_name = "gcm-aes-ccp",201.blocksize = 1,202.ivsize = AES_BLOCK_SIZE,203.alg_defaults = &ccp_aes_gcm_defaults,204},205};206207static int ccp_register_aes_aead(struct list_head *head,208const struct ccp_aes_aead_def *def)209{210struct ccp_crypto_aead *ccp_aead;211struct aead_alg *alg;212int ret;213214ccp_aead = kzalloc(sizeof(*ccp_aead), GFP_KERNEL);215if (!ccp_aead)216return -ENOMEM;217218INIT_LIST_HEAD(&ccp_aead->entry);219220ccp_aead->mode = def->mode;221222/* Copy the defaults and override as necessary */223alg = &ccp_aead->alg;224*alg = *def->alg_defaults;225snprintf(alg->base.cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name);226snprintf(alg->base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",227def->driver_name);228alg->base.cra_blocksize = def->blocksize;229230ret = crypto_register_aead(alg);231if (ret) {232pr_err("%s aead algorithm registration error (%d)\n",233alg->base.cra_name, ret);234kfree(ccp_aead);235return ret;236}237238list_add(&ccp_aead->entry, head);239240return 0;241}242243int ccp_register_aes_aeads(struct list_head *head)244{245int i, ret;246unsigned int ccpversion = ccp_version();247248for (i = 0; i < ARRAY_SIZE(aes_aead_algs); i++) {249if (aes_aead_algs[i].version > ccpversion)250continue;251ret = ccp_register_aes_aead(head, &aes_aead_algs[i]);252if (ret)253return ret;254}255256return 0;257}258259260