1167514Skmacy// SPDX-License-Identifier: GPL-2.0-only 2167514Skmacy/* 3177340Skmacy * AMD Cryptographic Coprocessor (CCP) AES GCM crypto API support 4167514Skmacy * 5167514Skmacy * Copyright (C) 2016,2017 Advanced Micro Devices, Inc. 6167514Skmacy * 7167514Skmacy * Author: Gary R Hook <gary.hook@amd.com> 8167514Skmacy */ 9167514Skmacy 10167514Skmacy#include <linux/module.h> 11167514Skmacy#include <linux/sched.h> 12169978Skmacy#include <linux/delay.h> 13167514Skmacy#include <linux/scatterlist.h> 14167514Skmacy#include <linux/crypto.h> 15167514Skmacy#include <crypto/internal/aead.h> 16167514Skmacy#include <crypto/algapi.h> 17167514Skmacy#include <crypto/aes.h> 18167514Skmacy#include <crypto/ctr.h> 19167514Skmacy#include <crypto/gcm.h> 20167514Skmacy#include <crypto/scatterwalk.h> 21167514Skmacy 22167514Skmacy#include "ccp-crypto.h" 23167514Skmacy 24167514Skmacystatic int ccp_aes_gcm_complete(struct crypto_async_request *async_req, int ret) 25167514Skmacy{ 26167514Skmacy return ret; 27167514Skmacy} 28167514Skmacy 29167514Skmacystatic int ccp_aes_gcm_setkey(struct crypto_aead *tfm, const u8 *key, 30167514Skmacy unsigned int key_len) 31167514Skmacy{ 32167514Skmacy struct ccp_ctx *ctx = crypto_aead_ctx_dma(tfm); 33167514Skmacy 34167514Skmacy switch (key_len) { 35167514Skmacy case AES_KEYSIZE_128: 36167514Skmacy ctx->u.aes.type = CCP_AES_TYPE_128; 37167514Skmacy break; 38167514Skmacy case AES_KEYSIZE_192: 39167514Skmacy ctx->u.aes.type = CCP_AES_TYPE_192; 40167514Skmacy break; 41167514Skmacy case AES_KEYSIZE_256: 42167514Skmacy ctx->u.aes.type = CCP_AES_TYPE_256; 43167514Skmacy break; 44167514Skmacy default: 45167514Skmacy return -EINVAL; 46167514Skmacy } 47167514Skmacy 48167514Skmacy ctx->u.aes.mode = CCP_AES_MODE_GCM; 49167514Skmacy ctx->u.aes.key_len = key_len; 50167514Skmacy 51167514Skmacy memcpy(ctx->u.aes.key, key, key_len); 52167514Skmacy sg_init_one(&ctx->u.aes.key_sg, ctx->u.aes.key, key_len); 53167514Skmacy 54182679Skmacy return 0; 55182679Skmacy} 56182679Skmacy 57169978Skmacystatic int ccp_aes_gcm_setauthsize(struct crypto_aead *tfm, 58182679Skmacy unsigned int authsize) 59182679Skmacy{ 60189643Sgnn switch (authsize) { 61189643Sgnn case 16: 62167514Skmacy case 15: 63167514Skmacy case 14: 64182679Skmacy case 13: 65182679Skmacy case 12: 66182679Skmacy case 8: 67182679Skmacy case 4: 68182679Skmacy break; 69182679Skmacy default: 70167514Skmacy return -EINVAL; 71167514Skmacy } 72167514Skmacy 73167514Skmacy return 0; 74167514Skmacy} 75167514Skmacy 76167514Skmacystatic int ccp_aes_gcm_crypt(struct aead_request *req, bool encrypt) 77167514Skmacy{ 78167514Skmacy struct crypto_aead *tfm = crypto_aead_reqtfm(req); 79167514Skmacy struct ccp_ctx *ctx = crypto_aead_ctx_dma(tfm); 80167514Skmacy struct ccp_aes_req_ctx *rctx = aead_request_ctx_dma(req); 81167514Skmacy struct scatterlist *iv_sg = NULL; 82167514Skmacy unsigned int iv_len = 0; 83167514Skmacy int i; 84167514Skmacy int ret = 0; 85167514Skmacy 86167514Skmacy if (!ctx->u.aes.key_len) 87167514Skmacy return -EINVAL; 88167514Skmacy 89167514Skmacy if (ctx->u.aes.mode != CCP_AES_MODE_GCM) 90167514Skmacy return -EINVAL; 91167514Skmacy 92167514Skmacy if (!req->iv) 93167514Skmacy return -EINVAL; 94167514Skmacy 95167514Skmacy /* 96167514Skmacy * 5 parts: 97167514Skmacy * plaintext/ciphertext input 98167514Skmacy * AAD 99182679Skmacy * key 100182679Skmacy * IV 101167514Skmacy * Destination+tag buffer 102182679Skmacy */ 103182679Skmacy 104182679Skmacy /* Prepare the IV: 12 bytes + an integer (counter) */ 105182679Skmacy memcpy(rctx->iv, req->iv, GCM_AES_IV_SIZE); 106182679Skmacy for (i = 0; i < 3; i++) 107182679Skmacy rctx->iv[i + GCM_AES_IV_SIZE] = 0; 108182679Skmacy rctx->iv[AES_BLOCK_SIZE - 1] = 1; 109182679Skmacy 110182679Skmacy /* Set up a scatterlist for the IV */ 111182679Skmacy iv_sg = &rctx->iv_sg; 112167514Skmacy iv_len = AES_BLOCK_SIZE; 113167514Skmacy sg_init_one(iv_sg, rctx->iv, iv_len); 114167514Skmacy 115167514Skmacy /* The AAD + plaintext are concatenated in the src buffer */ 116167514Skmacy memset(&rctx->cmd, 0, sizeof(rctx->cmd)); 117167514Skmacy INIT_LIST_HEAD(&rctx->cmd.entry); 118167514Skmacy rctx->cmd.engine = CCP_ENGINE_AES; 119167514Skmacy rctx->cmd.u.aes.authsize = crypto_aead_authsize(tfm); 120167514Skmacy rctx->cmd.u.aes.type = ctx->u.aes.type; 121167514Skmacy rctx->cmd.u.aes.mode = ctx->u.aes.mode; 122167746Skmacy rctx->cmd.u.aes.action = encrypt; 123167746Skmacy rctx->cmd.u.aes.key = &ctx->u.aes.key_sg; 124167746Skmacy rctx->cmd.u.aes.key_len = ctx->u.aes.key_len; 125167746Skmacy rctx->cmd.u.aes.iv = iv_sg; 126167746Skmacy rctx->cmd.u.aes.iv_len = iv_len; 127167746Skmacy rctx->cmd.u.aes.src = req->src; 128182679Skmacy rctx->cmd.u.aes.src_len = req->cryptlen; 129167746Skmacy rctx->cmd.u.aes.aad_len = req->assoclen; 130167746Skmacy 131167514Skmacy /* The cipher text + the tag are in the dst buffer */ 132167514Skmacy rctx->cmd.u.aes.dst = req->dst; 133167514Skmacy 134167514Skmacy ret = ccp_crypto_enqueue_request(&req->base, &rctx->cmd); 135167514Skmacy 136167514Skmacy return ret; 137167514Skmacy} 138167514Skmacy 139167514Skmacystatic int ccp_aes_gcm_encrypt(struct aead_request *req) 140167514Skmacy{ 141167514Skmacy return ccp_aes_gcm_crypt(req, CCP_AES_ACTION_ENCRYPT); 142167514Skmacy} 143167514Skmacy 144167514Skmacystatic int ccp_aes_gcm_decrypt(struct aead_request *req) 145167514Skmacy{ 146167514Skmacy return ccp_aes_gcm_crypt(req, CCP_AES_ACTION_DECRYPT); 147167514Skmacy} 148167514Skmacy 149167514Skmacystatic int ccp_aes_gcm_cra_init(struct crypto_aead *tfm) 150167514Skmacy{ 151167514Skmacy struct ccp_ctx *ctx = crypto_aead_ctx_dma(tfm); 152167514Skmacy 153167514Skmacy ctx->complete = ccp_aes_gcm_complete; 154167514Skmacy ctx->u.aes.key_len = 0; 155167514Skmacy 156167514Skmacy crypto_aead_set_reqsize_dma(tfm, sizeof(struct ccp_aes_req_ctx)); 157167514Skmacy 158182679Skmacy return 0; 159182679Skmacy} 160182679Skmacy 161182679Skmacystatic void ccp_aes_gcm_cra_exit(struct crypto_tfm *tfm) 162167514Skmacy{ 163167514Skmacy} 164182679Skmacy 165182679Skmacystatic struct aead_alg ccp_aes_gcm_defaults = { 166182679Skmacy .setkey = ccp_aes_gcm_setkey, 167182679Skmacy .setauthsize = ccp_aes_gcm_setauthsize, 168182679Skmacy .encrypt = ccp_aes_gcm_encrypt, 169167514Skmacy .decrypt = ccp_aes_gcm_decrypt, 170167514Skmacy .init = ccp_aes_gcm_cra_init, 171167514Skmacy .ivsize = GCM_AES_IV_SIZE, 172167514Skmacy .maxauthsize = AES_BLOCK_SIZE, 173182679Skmacy .base = { 174167514Skmacy .cra_flags = CRYPTO_ALG_ASYNC | 175167514Skmacy CRYPTO_ALG_ALLOCATES_MEMORY | 176167514Skmacy CRYPTO_ALG_KERN_DRIVER_ONLY | 177167514Skmacy CRYPTO_ALG_NEED_FALLBACK, 178167514Skmacy .cra_blocksize = AES_BLOCK_SIZE, 179182679Skmacy .cra_ctxsize = sizeof(struct ccp_ctx) + CRYPTO_DMA_PADDING, 180167514Skmacy .cra_priority = CCP_CRA_PRIORITY, 181167514Skmacy .cra_exit = ccp_aes_gcm_cra_exit, 182167514Skmacy .cra_module = THIS_MODULE, 183167514Skmacy }, 184167514Skmacy}; 185167514Skmacy 186182679Skmacystruct ccp_aes_aead_def { 187182679Skmacy enum ccp_aes_mode mode; 188182679Skmacy unsigned int version; 189182679Skmacy const char *name; 190182679Skmacy const char *driver_name; 191182679Skmacy unsigned int blocksize; 192167514Skmacy unsigned int ivsize; 193189643Sgnn struct aead_alg *alg_defaults; 194189643Sgnn}; 195189643Sgnn 196189643Sgnnstatic struct ccp_aes_aead_def aes_aead_algs[] = { 197189643Sgnn { 198189643Sgnn .mode = CCP_AES_MODE_GHASH, 199189643Sgnn .version = CCP_VERSION(5, 0), 200189643Sgnn .name = "gcm(aes)", 201189643Sgnn .driver_name = "gcm-aes-ccp", 202189643Sgnn .blocksize = 1, 203189643Sgnn .ivsize = AES_BLOCK_SIZE, 204189643Sgnn .alg_defaults = &ccp_aes_gcm_defaults, 205189643Sgnn }, 206189643Sgnn}; 207189643Sgnn 208189643Sgnnstatic int ccp_register_aes_aead(struct list_head *head, 209189643Sgnn const struct ccp_aes_aead_def *def) 210189643Sgnn{ 211189643Sgnn struct ccp_crypto_aead *ccp_aead; 212189643Sgnn struct aead_alg *alg; 213189643Sgnn int ret; 214189643Sgnn 215189643Sgnn ccp_aead = kzalloc(sizeof(*ccp_aead), GFP_KERNEL); 216189643Sgnn if (!ccp_aead) 217189643Sgnn return -ENOMEM; 218182679Skmacy 219182679Skmacy INIT_LIST_HEAD(&ccp_aead->entry); 220182679Skmacy 221182679Skmacy ccp_aead->mode = def->mode; 222182679Skmacy 223182679Skmacy /* Copy the defaults and override as necessary */ 224182679Skmacy alg = &ccp_aead->alg; 225182679Skmacy *alg = *def->alg_defaults; 226182679Skmacy snprintf(alg->base.cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name); 227182679Skmacy snprintf(alg->base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", 228182679Skmacy def->driver_name); 229182679Skmacy alg->base.cra_blocksize = def->blocksize; 230182679Skmacy 231182679Skmacy ret = crypto_register_aead(alg); 232182679Skmacy if (ret) { 233182679Skmacy pr_err("%s aead algorithm registration error (%d)\n", 234182679Skmacy alg->base.cra_name, ret); 235182679Skmacy kfree(ccp_aead); 236182679Skmacy return ret; 237182679Skmacy } 238182679Skmacy 239182679Skmacy list_add(&ccp_aead->entry, head); 240189643Sgnn 241189643Sgnn return 0; 242167514Skmacy} 243 244int ccp_register_aes_aeads(struct list_head *head) 245{ 246 int i, ret; 247 unsigned int ccpversion = ccp_version(); 248 249 for (i = 0; i < ARRAY_SIZE(aes_aead_algs); i++) { 250 if (aes_aead_algs[i].version > ccpversion) 251 continue; 252 ret = ccp_register_aes_aead(head, &aes_aead_algs[i]); 253 if (ret) 254 return ret; 255 } 256 257 return 0; 258} 259