root/drivers/crypto/ccp/ccp-crypto-aes-galois.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ccp_aes_gcm_complete
  2. ccp_aes_gcm_setkey
  3. ccp_aes_gcm_setauthsize
  4. ccp_aes_gcm_crypt
  5. ccp_aes_gcm_encrypt
  6. ccp_aes_gcm_decrypt
  7. ccp_aes_gcm_cra_init
  8. ccp_aes_gcm_cra_exit
  9. ccp_register_aes_aead
  10. ccp_register_aes_aeads

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * AMD Cryptographic Coprocessor (CCP) AES GCM crypto API support
   4  *
   5  * Copyright (C) 2016,2017 Advanced Micro Devices, Inc.
   6  *
   7  * Author: Gary R Hook <gary.hook@amd.com>
   8  */
   9 
  10 #include <linux/module.h>
  11 #include <linux/sched.h>
  12 #include <linux/delay.h>
  13 #include <linux/scatterlist.h>
  14 #include <linux/crypto.h>
  15 #include <crypto/internal/aead.h>
  16 #include <crypto/algapi.h>
  17 #include <crypto/aes.h>
  18 #include <crypto/ctr.h>
  19 #include <crypto/gcm.h>
  20 #include <crypto/scatterwalk.h>
  21 
  22 #include "ccp-crypto.h"
  23 
  24 static int ccp_aes_gcm_complete(struct crypto_async_request *async_req, int ret)
  25 {
  26         return ret;
  27 }
  28 
  29 static int ccp_aes_gcm_setkey(struct crypto_aead *tfm, const u8 *key,
  30                               unsigned int key_len)
  31 {
  32         struct ccp_ctx *ctx = crypto_aead_ctx(tfm);
  33 
  34         switch (key_len) {
  35         case AES_KEYSIZE_128:
  36                 ctx->u.aes.type = CCP_AES_TYPE_128;
  37                 break;
  38         case AES_KEYSIZE_192:
  39                 ctx->u.aes.type = CCP_AES_TYPE_192;
  40                 break;
  41         case AES_KEYSIZE_256:
  42                 ctx->u.aes.type = CCP_AES_TYPE_256;
  43                 break;
  44         default:
  45                 crypto_aead_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
  46                 return -EINVAL;
  47         }
  48 
  49         ctx->u.aes.mode = CCP_AES_MODE_GCM;
  50         ctx->u.aes.key_len = key_len;
  51 
  52         memcpy(ctx->u.aes.key, key, key_len);
  53         sg_init_one(&ctx->u.aes.key_sg, ctx->u.aes.key, key_len);
  54 
  55         return 0;
  56 }
  57 
  58 static int ccp_aes_gcm_setauthsize(struct crypto_aead *tfm,
  59                                    unsigned int authsize)
  60 {
  61         switch (authsize) {
  62         case 16:
  63         case 15:
  64         case 14:
  65         case 13:
  66         case 12:
  67         case 8:
  68         case 4:
  69                 break;
  70         default:
  71                 return -EINVAL;
  72         }
  73 
  74         return 0;
  75 }
  76 
  77 static int ccp_aes_gcm_crypt(struct aead_request *req, bool encrypt)
  78 {
  79         struct crypto_aead *tfm = crypto_aead_reqtfm(req);
  80         struct ccp_ctx *ctx = crypto_aead_ctx(tfm);
  81         struct ccp_aes_req_ctx *rctx = aead_request_ctx(req);
  82         struct scatterlist *iv_sg = NULL;
  83         unsigned int iv_len = 0;
  84         int i;
  85         int ret = 0;
  86 
  87         if (!ctx->u.aes.key_len)
  88                 return -EINVAL;
  89 
  90         if (ctx->u.aes.mode != CCP_AES_MODE_GCM)
  91                 return -EINVAL;
  92 
  93         if (!req->iv)
  94                 return -EINVAL;
  95 
  96         /*
  97          * 5 parts:
  98          *   plaintext/ciphertext input
  99          *   AAD
 100          *   key
 101          *   IV
 102          *   Destination+tag buffer
 103          */
 104 
 105         /* Prepare the IV: 12 bytes + an integer (counter) */
 106         memcpy(rctx->iv, req->iv, GCM_AES_IV_SIZE);
 107         for (i = 0; i < 3; i++)
 108                 rctx->iv[i + GCM_AES_IV_SIZE] = 0;
 109         rctx->iv[AES_BLOCK_SIZE - 1] = 1;
 110 
 111         /* Set up a scatterlist for the IV */
 112         iv_sg = &rctx->iv_sg;
 113         iv_len = AES_BLOCK_SIZE;
 114         sg_init_one(iv_sg, rctx->iv, iv_len);
 115 
 116         /* The AAD + plaintext are concatenated in the src buffer */
 117         memset(&rctx->cmd, 0, sizeof(rctx->cmd));
 118         INIT_LIST_HEAD(&rctx->cmd.entry);
 119         rctx->cmd.engine = CCP_ENGINE_AES;
 120         rctx->cmd.u.aes.authsize = crypto_aead_authsize(tfm);
 121         rctx->cmd.u.aes.type = ctx->u.aes.type;
 122         rctx->cmd.u.aes.mode = ctx->u.aes.mode;
 123         rctx->cmd.u.aes.action = encrypt;
 124         rctx->cmd.u.aes.key = &ctx->u.aes.key_sg;
 125         rctx->cmd.u.aes.key_len = ctx->u.aes.key_len;
 126         rctx->cmd.u.aes.iv = iv_sg;
 127         rctx->cmd.u.aes.iv_len = iv_len;
 128         rctx->cmd.u.aes.src = req->src;
 129         rctx->cmd.u.aes.src_len = req->cryptlen;
 130         rctx->cmd.u.aes.aad_len = req->assoclen;
 131 
 132         /* The cipher text + the tag are in the dst buffer */
 133         rctx->cmd.u.aes.dst = req->dst;
 134 
 135         ret = ccp_crypto_enqueue_request(&req->base, &rctx->cmd);
 136 
 137         return ret;
 138 }
 139 
 140 static int ccp_aes_gcm_encrypt(struct aead_request *req)
 141 {
 142         return ccp_aes_gcm_crypt(req, CCP_AES_ACTION_ENCRYPT);
 143 }
 144 
 145 static int ccp_aes_gcm_decrypt(struct aead_request *req)
 146 {
 147         return ccp_aes_gcm_crypt(req, CCP_AES_ACTION_DECRYPT);
 148 }
 149 
 150 static int ccp_aes_gcm_cra_init(struct crypto_aead *tfm)
 151 {
 152         struct ccp_ctx *ctx = crypto_aead_ctx(tfm);
 153 
 154         ctx->complete = ccp_aes_gcm_complete;
 155         ctx->u.aes.key_len = 0;
 156 
 157         crypto_aead_set_reqsize(tfm, sizeof(struct ccp_aes_req_ctx));
 158 
 159         return 0;
 160 }
 161 
 162 static void ccp_aes_gcm_cra_exit(struct crypto_tfm *tfm)
 163 {
 164 }
 165 
 166 static struct aead_alg ccp_aes_gcm_defaults = {
 167         .setkey = ccp_aes_gcm_setkey,
 168         .setauthsize = ccp_aes_gcm_setauthsize,
 169         .encrypt = ccp_aes_gcm_encrypt,
 170         .decrypt = ccp_aes_gcm_decrypt,
 171         .init = ccp_aes_gcm_cra_init,
 172         .ivsize = GCM_AES_IV_SIZE,
 173         .maxauthsize = AES_BLOCK_SIZE,
 174         .base = {
 175                 .cra_flags      = CRYPTO_ALG_TYPE_ABLKCIPHER |
 176                                   CRYPTO_ALG_ASYNC |
 177                                   CRYPTO_ALG_KERN_DRIVER_ONLY |
 178                                   CRYPTO_ALG_NEED_FALLBACK,
 179                 .cra_blocksize  = AES_BLOCK_SIZE,
 180                 .cra_ctxsize    = sizeof(struct ccp_ctx),
 181                 .cra_priority   = CCP_CRA_PRIORITY,
 182                 .cra_type       = &crypto_ablkcipher_type,
 183                 .cra_exit       = ccp_aes_gcm_cra_exit,
 184                 .cra_module     = THIS_MODULE,
 185         },
 186 };
 187 
 188 struct ccp_aes_aead_def {
 189         enum ccp_aes_mode mode;
 190         unsigned int version;
 191         const char *name;
 192         const char *driver_name;
 193         unsigned int blocksize;
 194         unsigned int ivsize;
 195         struct aead_alg *alg_defaults;
 196 };
 197 
 198 static struct ccp_aes_aead_def aes_aead_algs[] = {
 199         {
 200                 .mode           = CCP_AES_MODE_GHASH,
 201                 .version        = CCP_VERSION(5, 0),
 202                 .name           = "gcm(aes)",
 203                 .driver_name    = "gcm-aes-ccp",
 204                 .blocksize      = 1,
 205                 .ivsize         = AES_BLOCK_SIZE,
 206                 .alg_defaults   = &ccp_aes_gcm_defaults,
 207         },
 208 };
 209 
 210 static int ccp_register_aes_aead(struct list_head *head,
 211                                  const struct ccp_aes_aead_def *def)
 212 {
 213         struct ccp_crypto_aead *ccp_aead;
 214         struct aead_alg *alg;
 215         int ret;
 216 
 217         ccp_aead = kzalloc(sizeof(*ccp_aead), GFP_KERNEL);
 218         if (!ccp_aead)
 219                 return -ENOMEM;
 220 
 221         INIT_LIST_HEAD(&ccp_aead->entry);
 222 
 223         ccp_aead->mode = def->mode;
 224 
 225         /* Copy the defaults and override as necessary */
 226         alg = &ccp_aead->alg;
 227         *alg = *def->alg_defaults;
 228         snprintf(alg->base.cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name);
 229         snprintf(alg->base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
 230                  def->driver_name);
 231         alg->base.cra_blocksize = def->blocksize;
 232         alg->base.cra_ablkcipher.ivsize = def->ivsize;
 233 
 234         ret = crypto_register_aead(alg);
 235         if (ret) {
 236                 pr_err("%s ablkcipher algorithm registration error (%d)\n",
 237                        alg->base.cra_name, ret);
 238                 kfree(ccp_aead);
 239                 return ret;
 240         }
 241 
 242         list_add(&ccp_aead->entry, head);
 243 
 244         return 0;
 245 }
 246 
 247 int ccp_register_aes_aeads(struct list_head *head)
 248 {
 249         int i, ret;
 250         unsigned int ccpversion = ccp_version();
 251 
 252         for (i = 0; i < ARRAY_SIZE(aes_aead_algs); i++) {
 253                 if (aes_aead_algs[i].version > ccpversion)
 254                         continue;
 255                 ret = ccp_register_aes_aead(head, &aes_aead_algs[i]);
 256                 if (ret)
 257                         return ret;
 258         }
 259 
 260         return 0;
 261 }

/* [<][>][^][v][top][bottom][index][help] */