ccp-crypto-aes.c revision 2b789435d7f36ed918d92db647f3a2f3fec9bb1f
1/* 2 * AMD Cryptographic Coprocessor (CCP) AES crypto API support 3 * 4 * Copyright (C) 2013 Advanced Micro Devices, Inc. 5 * 6 * Author: Tom Lendacky <thomas.lendacky@amd.com> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 */ 12 13#include <linux/module.h> 14#include <linux/sched.h> 15#include <linux/delay.h> 16#include <linux/scatterlist.h> 17#include <linux/crypto.h> 18#include <crypto/algapi.h> 19#include <crypto/aes.h> 20#include <crypto/ctr.h> 21#include <crypto/scatterwalk.h> 22 23#include "ccp-crypto.h" 24 25 26static int ccp_aes_complete(struct crypto_async_request *async_req, int ret) 27{ 28 struct ablkcipher_request *req = ablkcipher_request_cast(async_req); 29 struct ccp_ctx *ctx = crypto_tfm_ctx(req->base.tfm); 30 struct ccp_aes_req_ctx *rctx = ablkcipher_request_ctx(req); 31 32 if (ret) 33 return ret; 34 35 if (ctx->u.aes.mode != CCP_AES_MODE_ECB) 36 memcpy(req->info, rctx->iv, AES_BLOCK_SIZE); 37 38 return 0; 39} 40 41static int ccp_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, 42 unsigned int key_len) 43{ 44 struct ccp_ctx *ctx = crypto_tfm_ctx(crypto_ablkcipher_tfm(tfm)); 45 struct ccp_crypto_ablkcipher_alg *alg = 46 ccp_crypto_ablkcipher_alg(crypto_ablkcipher_tfm(tfm)); 47 48 switch (key_len) { 49 case AES_KEYSIZE_128: 50 ctx->u.aes.type = CCP_AES_TYPE_128; 51 break; 52 case AES_KEYSIZE_192: 53 ctx->u.aes.type = CCP_AES_TYPE_192; 54 break; 55 case AES_KEYSIZE_256: 56 ctx->u.aes.type = CCP_AES_TYPE_256; 57 break; 58 default: 59 crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); 60 return -EINVAL; 61 } 62 ctx->u.aes.mode = alg->mode; 63 ctx->u.aes.key_len = key_len; 64 65 memcpy(ctx->u.aes.key, key, key_len); 66 sg_init_one(&ctx->u.aes.key_sg, ctx->u.aes.key, key_len); 67 68 return 0; 69} 70 71static int ccp_aes_crypt(struct ablkcipher_request *req, bool encrypt) 72{ 73 struct ccp_ctx *ctx = crypto_tfm_ctx(req->base.tfm); 74 struct ccp_aes_req_ctx *rctx = ablkcipher_request_ctx(req); 75 struct scatterlist *iv_sg = NULL; 76 unsigned int iv_len = 0; 77 int ret; 78 79 if (!ctx->u.aes.key_len) { 80 pr_err("AES key not set\n"); 81 return -EINVAL; 82 } 83 84 if (((ctx->u.aes.mode == CCP_AES_MODE_ECB) || 85 (ctx->u.aes.mode == CCP_AES_MODE_CBC) || 86 (ctx->u.aes.mode == CCP_AES_MODE_CFB)) && 87 (req->nbytes & (AES_BLOCK_SIZE - 1))) { 88 pr_err("AES request size is not a multiple of the block size\n"); 89 return -EINVAL; 90 } 91 92 if (ctx->u.aes.mode != CCP_AES_MODE_ECB) { 93 if (!req->info) { 94 pr_err("AES IV not supplied"); 95 return -EINVAL; 96 } 97 98 memcpy(rctx->iv, req->info, AES_BLOCK_SIZE); 99 iv_sg = &rctx->iv_sg; 100 iv_len = AES_BLOCK_SIZE; 101 sg_init_one(iv_sg, rctx->iv, iv_len); 102 } 103 104 memset(&rctx->cmd, 0, sizeof(rctx->cmd)); 105 INIT_LIST_HEAD(&rctx->cmd.entry); 106 rctx->cmd.engine = CCP_ENGINE_AES; 107 rctx->cmd.u.aes.type = ctx->u.aes.type; 108 rctx->cmd.u.aes.mode = ctx->u.aes.mode; 109 rctx->cmd.u.aes.action = 110 (encrypt) ? CCP_AES_ACTION_ENCRYPT : CCP_AES_ACTION_DECRYPT; 111 rctx->cmd.u.aes.key = &ctx->u.aes.key_sg; 112 rctx->cmd.u.aes.key_len = ctx->u.aes.key_len; 113 rctx->cmd.u.aes.iv = iv_sg; 114 rctx->cmd.u.aes.iv_len = iv_len; 115 rctx->cmd.u.aes.src = req->src; 116 rctx->cmd.u.aes.src_len = req->nbytes; 117 rctx->cmd.u.aes.dst = req->dst; 118 119 ret = ccp_crypto_enqueue_request(&req->base, &rctx->cmd); 120 121 return ret; 122} 123 124static int ccp_aes_encrypt(struct ablkcipher_request *req) 125{ 126 return ccp_aes_crypt(req, true); 127} 128 129static int ccp_aes_decrypt(struct ablkcipher_request *req) 130{ 131 return ccp_aes_crypt(req, false); 132} 133 134static int ccp_aes_cra_init(struct crypto_tfm *tfm) 135{ 136 struct ccp_ctx *ctx = crypto_tfm_ctx(tfm); 137 138 ctx->complete = ccp_aes_complete; 139 ctx->u.aes.key_len = 0; 140 141 tfm->crt_ablkcipher.reqsize = sizeof(struct ccp_aes_req_ctx); 142 143 return 0; 144} 145 146static void ccp_aes_cra_exit(struct crypto_tfm *tfm) 147{ 148} 149 150static int ccp_aes_rfc3686_complete(struct crypto_async_request *async_req, 151 int ret) 152{ 153 struct ablkcipher_request *req = ablkcipher_request_cast(async_req); 154 struct ccp_aes_req_ctx *rctx = ablkcipher_request_ctx(req); 155 156 /* Restore the original pointer */ 157 req->info = rctx->rfc3686_info; 158 159 return ccp_aes_complete(async_req, ret); 160} 161 162static int ccp_aes_rfc3686_setkey(struct crypto_ablkcipher *tfm, const u8 *key, 163 unsigned int key_len) 164{ 165 struct ccp_ctx *ctx = crypto_tfm_ctx(crypto_ablkcipher_tfm(tfm)); 166 167 if (key_len < CTR_RFC3686_NONCE_SIZE) 168 return -EINVAL; 169 170 key_len -= CTR_RFC3686_NONCE_SIZE; 171 memcpy(ctx->u.aes.nonce, key + key_len, CTR_RFC3686_NONCE_SIZE); 172 173 return ccp_aes_setkey(tfm, key, key_len); 174} 175 176static int ccp_aes_rfc3686_crypt(struct ablkcipher_request *req, bool encrypt) 177{ 178 struct ccp_ctx *ctx = crypto_tfm_ctx(req->base.tfm); 179 struct ccp_aes_req_ctx *rctx = ablkcipher_request_ctx(req); 180 u8 *iv; 181 182 /* Initialize the CTR block */ 183 iv = rctx->rfc3686_iv; 184 memcpy(iv, ctx->u.aes.nonce, CTR_RFC3686_NONCE_SIZE); 185 186 iv += CTR_RFC3686_NONCE_SIZE; 187 memcpy(iv, req->info, CTR_RFC3686_IV_SIZE); 188 189 iv += CTR_RFC3686_IV_SIZE; 190 *(__be32 *)iv = cpu_to_be32(1); 191 192 /* Point to the new IV */ 193 rctx->rfc3686_info = req->info; 194 req->info = rctx->rfc3686_iv; 195 196 return ccp_aes_crypt(req, encrypt); 197} 198 199static int ccp_aes_rfc3686_encrypt(struct ablkcipher_request *req) 200{ 201 return ccp_aes_rfc3686_crypt(req, true); 202} 203 204static int ccp_aes_rfc3686_decrypt(struct ablkcipher_request *req) 205{ 206 return ccp_aes_rfc3686_crypt(req, false); 207} 208 209static int ccp_aes_rfc3686_cra_init(struct crypto_tfm *tfm) 210{ 211 struct ccp_ctx *ctx = crypto_tfm_ctx(tfm); 212 213 ctx->complete = ccp_aes_rfc3686_complete; 214 ctx->u.aes.key_len = 0; 215 216 tfm->crt_ablkcipher.reqsize = sizeof(struct ccp_aes_req_ctx); 217 218 return 0; 219} 220 221static void ccp_aes_rfc3686_cra_exit(struct crypto_tfm *tfm) 222{ 223} 224 225static struct crypto_alg ccp_aes_defaults = { 226 .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | 227 CRYPTO_ALG_ASYNC | 228 CRYPTO_ALG_KERN_DRIVER_ONLY | 229 CRYPTO_ALG_NEED_FALLBACK, 230 .cra_blocksize = AES_BLOCK_SIZE, 231 .cra_ctxsize = sizeof(struct ccp_ctx), 232 .cra_priority = CCP_CRA_PRIORITY, 233 .cra_type = &crypto_ablkcipher_type, 234 .cra_init = ccp_aes_cra_init, 235 .cra_exit = ccp_aes_cra_exit, 236 .cra_module = THIS_MODULE, 237 .cra_ablkcipher = { 238 .setkey = ccp_aes_setkey, 239 .encrypt = ccp_aes_encrypt, 240 .decrypt = ccp_aes_decrypt, 241 .min_keysize = AES_MIN_KEY_SIZE, 242 .max_keysize = AES_MAX_KEY_SIZE, 243 }, 244}; 245 246static struct crypto_alg ccp_aes_rfc3686_defaults = { 247 .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | 248 CRYPTO_ALG_ASYNC | 249 CRYPTO_ALG_KERN_DRIVER_ONLY | 250 CRYPTO_ALG_NEED_FALLBACK, 251 .cra_blocksize = CTR_RFC3686_BLOCK_SIZE, 252 .cra_ctxsize = sizeof(struct ccp_ctx), 253 .cra_priority = CCP_CRA_PRIORITY, 254 .cra_type = &crypto_ablkcipher_type, 255 .cra_init = ccp_aes_rfc3686_cra_init, 256 .cra_exit = ccp_aes_rfc3686_cra_exit, 257 .cra_module = THIS_MODULE, 258 .cra_ablkcipher = { 259 .setkey = ccp_aes_rfc3686_setkey, 260 .encrypt = ccp_aes_rfc3686_encrypt, 261 .decrypt = ccp_aes_rfc3686_decrypt, 262 .min_keysize = AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE, 263 .max_keysize = AES_MAX_KEY_SIZE + CTR_RFC3686_NONCE_SIZE, 264 }, 265}; 266 267struct ccp_aes_def { 268 enum ccp_aes_mode mode; 269 const char *name; 270 const char *driver_name; 271 unsigned int blocksize; 272 unsigned int ivsize; 273 struct crypto_alg *alg_defaults; 274}; 275 276static struct ccp_aes_def aes_algs[] = { 277 { 278 .mode = CCP_AES_MODE_ECB, 279 .name = "ecb(aes)", 280 .driver_name = "ecb-aes-ccp", 281 .blocksize = AES_BLOCK_SIZE, 282 .ivsize = 0, 283 .alg_defaults = &ccp_aes_defaults, 284 }, 285 { 286 .mode = CCP_AES_MODE_CBC, 287 .name = "cbc(aes)", 288 .driver_name = "cbc-aes-ccp", 289 .blocksize = AES_BLOCK_SIZE, 290 .ivsize = AES_BLOCK_SIZE, 291 .alg_defaults = &ccp_aes_defaults, 292 }, 293 { 294 .mode = CCP_AES_MODE_CFB, 295 .name = "cfb(aes)", 296 .driver_name = "cfb-aes-ccp", 297 .blocksize = AES_BLOCK_SIZE, 298 .ivsize = AES_BLOCK_SIZE, 299 .alg_defaults = &ccp_aes_defaults, 300 }, 301 { 302 .mode = CCP_AES_MODE_OFB, 303 .name = "ofb(aes)", 304 .driver_name = "ofb-aes-ccp", 305 .blocksize = 1, 306 .ivsize = AES_BLOCK_SIZE, 307 .alg_defaults = &ccp_aes_defaults, 308 }, 309 { 310 .mode = CCP_AES_MODE_CTR, 311 .name = "ctr(aes)", 312 .driver_name = "ctr-aes-ccp", 313 .blocksize = 1, 314 .ivsize = AES_BLOCK_SIZE, 315 .alg_defaults = &ccp_aes_defaults, 316 }, 317 { 318 .mode = CCP_AES_MODE_CTR, 319 .name = "rfc3686(ctr(aes))", 320 .driver_name = "rfc3686-ctr-aes-ccp", 321 .blocksize = 1, 322 .ivsize = CTR_RFC3686_IV_SIZE, 323 .alg_defaults = &ccp_aes_rfc3686_defaults, 324 }, 325}; 326 327static int ccp_register_aes_alg(struct list_head *head, 328 const struct ccp_aes_def *def) 329{ 330 struct ccp_crypto_ablkcipher_alg *ccp_alg; 331 struct crypto_alg *alg; 332 int ret; 333 334 ccp_alg = kzalloc(sizeof(*ccp_alg), GFP_KERNEL); 335 if (!ccp_alg) 336 return -ENOMEM; 337 338 INIT_LIST_HEAD(&ccp_alg->entry); 339 340 ccp_alg->mode = def->mode; 341 342 /* Copy the defaults and override as necessary */ 343 alg = &ccp_alg->alg; 344 memcpy(alg, def->alg_defaults, sizeof(*alg)); 345 snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name); 346 snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", 347 def->driver_name); 348 alg->cra_blocksize = def->blocksize; 349 alg->cra_ablkcipher.ivsize = def->ivsize; 350 351 ret = crypto_register_alg(alg); 352 if (ret) { 353 pr_err("%s ablkcipher algorithm registration error (%d)\n", 354 alg->cra_name, ret); 355 kfree(ccp_alg); 356 return ret; 357 } 358 359 list_add(&ccp_alg->entry, head); 360 361 return 0; 362} 363 364int ccp_register_aes_algs(struct list_head *head) 365{ 366 int i, ret; 367 368 for (i = 0; i < ARRAY_SIZE(aes_algs); i++) { 369 ret = ccp_register_aes_alg(head, &aes_algs[i]); 370 if (ret) 371 return ret; 372 } 373 374 return 0; 375} 376