···1717#include <linux/ccp.h>1818#include <linux/scatterlist.h>1919#include <crypto/internal/hash.h>2020+#include <crypto/internal/akcipher.h>20212122#include "ccp-crypto.h"2223···3837module_param(des3_disable, uint, 0444);3938MODULE_PARM_DESC(des3_disable, "Disable use of 3DES - any non-zero value");40394040+static unsigned int rsa_disable;4141+module_param(rsa_disable, uint, 0444);4242+MODULE_PARM_DESC(rsa_disable, "Disable use of RSA - any non-zero value");4343+4144/* List heads for the supported algorithms */4245static LIST_HEAD(hash_algs);4346static LIST_HEAD(cipher_algs);4447static LIST_HEAD(aead_algs);4848+static LIST_HEAD(akcipher_algs);45494650/* For any tfm, requests for that tfm must be returned on the order4751 * received. With multiple queues available, the CCP can process more···364358 return ret;365359 }366360361361+ if (!rsa_disable) {362362+ ret = ccp_register_rsa_algs(&akcipher_algs);363363+ if (ret)364364+ return ret;365365+ }366366+367367 return 0;368368}369369···378366 struct ccp_crypto_ahash_alg *ahash_alg, *ahash_tmp;379367 struct ccp_crypto_ablkcipher_alg *ablk_alg, *ablk_tmp;380368 struct ccp_crypto_aead *aead_alg, *aead_tmp;369369+ struct ccp_crypto_akcipher_alg *akc_alg, *akc_tmp;381370382371 list_for_each_entry_safe(ahash_alg, ahash_tmp, &hash_algs, entry) {383372 crypto_unregister_ahash(&ahash_alg->alg);···396383 crypto_unregister_aead(&aead_alg->alg);397384 list_del(&aead_alg->entry);398385 kfree(aead_alg);386386+ }387387+388388+ list_for_each_entry_safe(akc_alg, akc_tmp, &akcipher_algs, entry) {389389+ crypto_unregister_akcipher(&akc_alg->alg);390390+ list_del(&akc_alg->entry);391391+ kfree(akc_alg);399392 }400393}401394
+296
drivers/crypto/ccp/ccp-crypto-rsa.c
···11+/*22+ * AMD Cryptographic Coprocessor (CCP) RSA crypto API support33+ *44+ * Copyright (C) 2017 Advanced Micro Devices, Inc.55+ *66+ * Author: Gary R Hook <gary.hook@amd.com>77+ *88+ * This program is free software; you can redistribute it and/or modify99+ * it under the terms of the GNU General Public License version 2 as1010+ * published by the Free Software Foundation.1111+ */1212+1313+#include <linux/module.h>1414+#include <linux/sched.h>1515+#include <linux/scatterlist.h>1616+#include <linux/crypto.h>1717+#include <crypto/algapi.h>1818+#include <crypto/internal/rsa.h>1919+#include <crypto/internal/akcipher.h>2020+#include <crypto/akcipher.h>2121+#include <crypto/scatterwalk.h>2222+2323+#include "ccp-crypto.h"2424+2525+static inline struct akcipher_request *akcipher_request_cast(2626+ struct crypto_async_request *req)2727+{2828+ return container_of(req, struct akcipher_request, base);2929+}3030+3131+static inline int ccp_copy_and_save_keypart(u8 **kpbuf, unsigned int *kplen,3232+ const u8 *buf, size_t sz)3333+{3434+ int nskip;3535+3636+ for (nskip = 0; nskip < sz; nskip++)3737+ if (buf[nskip])3838+ break;3939+ *kplen = sz - nskip;4040+ *kpbuf = kzalloc(*kplen, GFP_KERNEL);4141+ if (!*kpbuf)4242+ return -ENOMEM;4343+ memcpy(*kpbuf, buf + nskip, *kplen);4444+4545+ return 0;4646+}4747+4848+static int ccp_rsa_complete(struct crypto_async_request *async_req, int ret)4949+{5050+ struct akcipher_request *req = akcipher_request_cast(async_req);5151+ struct ccp_rsa_req_ctx *rctx = akcipher_request_ctx(req);5252+5353+ if (ret)5454+ return ret;5555+5656+ req->dst_len = rctx->cmd.u.rsa.key_size >> 3;5757+5858+ return 0;5959+}6060+6161+static unsigned int ccp_rsa_maxsize(struct crypto_akcipher *tfm)6262+{6363+ return CCP_RSA_MAXMOD;6464+}6565+6666+static int ccp_rsa_crypt(struct akcipher_request *req, bool encrypt)6767+{6868+ struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);6969+ struct ccp_ctx *ctx = akcipher_tfm_ctx(tfm);7070+ struct ccp_rsa_req_ctx *rctx = akcipher_request_ctx(req);7171+ int ret = 0;7272+7373+ memset(&rctx->cmd, 0, sizeof(rctx->cmd));7474+ INIT_LIST_HEAD(&rctx->cmd.entry);7575+ rctx->cmd.engine = CCP_ENGINE_RSA;7676+7777+ rctx->cmd.u.rsa.key_size = ctx->u.rsa.key_len; /* in bits */7878+ if (encrypt) {7979+ rctx->cmd.u.rsa.exp = &ctx->u.rsa.e_sg;8080+ rctx->cmd.u.rsa.exp_len = ctx->u.rsa.e_len;8181+ } else {8282+ rctx->cmd.u.rsa.exp = &ctx->u.rsa.d_sg;8383+ rctx->cmd.u.rsa.exp_len = ctx->u.rsa.d_len;8484+ }8585+ rctx->cmd.u.rsa.mod = &ctx->u.rsa.n_sg;8686+ rctx->cmd.u.rsa.mod_len = ctx->u.rsa.n_len;8787+ rctx->cmd.u.rsa.src = req->src;8888+ rctx->cmd.u.rsa.src_len = req->src_len;8989+ rctx->cmd.u.rsa.dst = req->dst;9090+9191+ ret = ccp_crypto_enqueue_request(&req->base, &rctx->cmd);9292+9393+ return ret;9494+}9595+9696+static int ccp_rsa_encrypt(struct akcipher_request *req)9797+{9898+ return ccp_rsa_crypt(req, true);9999+}100100+101101+static int ccp_rsa_decrypt(struct akcipher_request *req)102102+{103103+ return ccp_rsa_crypt(req, false);104104+}105105+106106+static int ccp_check_key_length(unsigned int len)107107+{108108+ /* In bits */109109+ if (len < 8 || len > 4096)110110+ return -EINVAL;111111+ return 0;112112+}113113+114114+static void ccp_rsa_free_key_bufs(struct ccp_ctx *ctx)115115+{116116+ /* Clean up old key data */117117+ kzfree(ctx->u.rsa.e_buf);118118+ ctx->u.rsa.e_buf = NULL;119119+ ctx->u.rsa.e_len = 0;120120+ kzfree(ctx->u.rsa.n_buf);121121+ ctx->u.rsa.n_buf = NULL;122122+ ctx->u.rsa.n_len = 0;123123+ kzfree(ctx->u.rsa.d_buf);124124+ ctx->u.rsa.d_buf = NULL;125125+ ctx->u.rsa.d_len = 0;126126+}127127+128128+static int ccp_rsa_setkey(struct crypto_akcipher *tfm, const void *key,129129+ unsigned int keylen, bool private)130130+{131131+ struct ccp_ctx *ctx = akcipher_tfm_ctx(tfm);132132+ struct rsa_key raw_key;133133+ int ret;134134+135135+ ccp_rsa_free_key_bufs(ctx);136136+ memset(&raw_key, 0, sizeof(raw_key));137137+138138+ /* Code borrowed from crypto/rsa.c */139139+ if (private)140140+ ret = rsa_parse_priv_key(&raw_key, key, keylen);141141+ else142142+ ret = rsa_parse_pub_key(&raw_key, key, keylen);143143+ if (ret)144144+ goto n_key;145145+146146+ ret = ccp_copy_and_save_keypart(&ctx->u.rsa.n_buf, &ctx->u.rsa.n_len,147147+ raw_key.n, raw_key.n_sz);148148+ if (ret)149149+ goto key_err;150150+ sg_init_one(&ctx->u.rsa.n_sg, ctx->u.rsa.n_buf, ctx->u.rsa.n_len);151151+152152+ ctx->u.rsa.key_len = ctx->u.rsa.n_len << 3; /* convert to bits */153153+ if (ccp_check_key_length(ctx->u.rsa.key_len)) {154154+ ret = -EINVAL;155155+ goto key_err;156156+ }157157+158158+ ret = ccp_copy_and_save_keypart(&ctx->u.rsa.e_buf, &ctx->u.rsa.e_len,159159+ raw_key.e, raw_key.e_sz);160160+ if (ret)161161+ goto key_err;162162+ sg_init_one(&ctx->u.rsa.e_sg, ctx->u.rsa.e_buf, ctx->u.rsa.e_len);163163+164164+ if (private) {165165+ ret = ccp_copy_and_save_keypart(&ctx->u.rsa.d_buf,166166+ &ctx->u.rsa.d_len,167167+ raw_key.d, raw_key.d_sz);168168+ if (ret)169169+ goto key_err;170170+ sg_init_one(&ctx->u.rsa.d_sg,171171+ ctx->u.rsa.d_buf, ctx->u.rsa.d_len);172172+ }173173+174174+ return 0;175175+176176+key_err:177177+ ccp_rsa_free_key_bufs(ctx);178178+179179+n_key:180180+ return ret;181181+}182182+183183+static int ccp_rsa_setprivkey(struct crypto_akcipher *tfm, const void *key,184184+ unsigned int keylen)185185+{186186+ return ccp_rsa_setkey(tfm, key, keylen, true);187187+}188188+189189+static int ccp_rsa_setpubkey(struct crypto_akcipher *tfm, const void *key,190190+ unsigned int keylen)191191+{192192+ return ccp_rsa_setkey(tfm, key, keylen, false);193193+}194194+195195+static int ccp_rsa_init_tfm(struct crypto_akcipher *tfm)196196+{197197+ struct ccp_ctx *ctx = akcipher_tfm_ctx(tfm);198198+199199+ akcipher_set_reqsize(tfm, sizeof(struct ccp_rsa_req_ctx));200200+ ctx->complete = ccp_rsa_complete;201201+202202+ return 0;203203+}204204+205205+static void ccp_rsa_exit_tfm(struct crypto_akcipher *tfm)206206+{207207+ struct ccp_ctx *ctx = crypto_tfm_ctx(&tfm->base);208208+209209+ ccp_rsa_free_key_bufs(ctx);210210+}211211+212212+static struct akcipher_alg ccp_rsa_defaults = {213213+ .encrypt = ccp_rsa_encrypt,214214+ .decrypt = ccp_rsa_decrypt,215215+ .sign = ccp_rsa_decrypt,216216+ .verify = ccp_rsa_encrypt,217217+ .set_pub_key = ccp_rsa_setpubkey,218218+ .set_priv_key = ccp_rsa_setprivkey,219219+ .max_size = ccp_rsa_maxsize,220220+ .init = ccp_rsa_init_tfm,221221+ .exit = ccp_rsa_exit_tfm,222222+ .base = {223223+ .cra_name = "rsa",224224+ .cra_driver_name = "rsa-ccp",225225+ .cra_priority = CCP_CRA_PRIORITY,226226+ .cra_module = THIS_MODULE,227227+ .cra_ctxsize = 2 * sizeof(struct ccp_ctx),228228+ },229229+};230230+231231+struct ccp_rsa_def {232232+ unsigned int version;233233+ const char *name;234234+ const char *driver_name;235235+ unsigned int reqsize;236236+ struct akcipher_alg *alg_defaults;237237+};238238+239239+static struct ccp_rsa_def rsa_algs[] = {240240+ {241241+ .version = CCP_VERSION(3, 0),242242+ .name = "rsa",243243+ .driver_name = "rsa-ccp",244244+ .reqsize = sizeof(struct ccp_rsa_req_ctx),245245+ .alg_defaults = &ccp_rsa_defaults,246246+ }247247+};248248+249249+int ccp_register_rsa_alg(struct list_head *head, const struct ccp_rsa_def *def)250250+{251251+ struct ccp_crypto_akcipher_alg *ccp_alg;252252+ struct akcipher_alg *alg;253253+ int ret;254254+255255+ ccp_alg = kzalloc(sizeof(*ccp_alg), GFP_KERNEL);256256+ if (!ccp_alg)257257+ return -ENOMEM;258258+259259+ INIT_LIST_HEAD(&ccp_alg->entry);260260+261261+ alg = &ccp_alg->alg;262262+ *alg = *def->alg_defaults;263263+ snprintf(alg->base.cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name);264264+ snprintf(alg->base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",265265+ def->driver_name);266266+ ret = crypto_register_akcipher(alg);267267+ if (ret) {268268+ pr_err("%s akcipher algorithm registration error (%d)\n",269269+ alg->base.cra_name, ret);270270+ kfree(ccp_alg);271271+ return ret;272272+ }273273+274274+ list_add(&ccp_alg->entry, head);275275+276276+ return 0;277277+}278278+279279+int ccp_register_rsa_algs(struct list_head *head)280280+{281281+ int i, ret;282282+ unsigned int ccpversion = ccp_version();283283+284284+ /* Register the RSA algorithm in standard mode285285+ * This works for CCP v3 and later286286+ */287287+ for (i = 0; i < ARRAY_SIZE(rsa_algs); i++) {288288+ if (rsa_algs[i].version > ccpversion)289289+ continue;290290+ ret = ccp_register_rsa_alg(head, &rsa_algs[i]);291291+ if (ret)292292+ return ret;293293+ }294294+295295+ return 0;296296+}