Dedicated to RSA (hardware) implementations that want to use raw integers instead of MPI keys. Signed-off-by: Tudor Ambarus <tudor-dan.ambarus@xxxxxxx> --- crypto/rsa.c | 15 ---- crypto/rsa_helper.c | 182 ++++++++++++++++++++++++++++++++++++++++++ include/crypto/internal/rsa.h | 28 +++++++ 3 files changed, 210 insertions(+), 15 deletions(-) diff --git a/crypto/rsa.c b/crypto/rsa.c index 7cb0153..37ac189 100644 --- a/crypto/rsa.c +++ b/crypto/rsa.c @@ -235,21 +235,6 @@ err_free_m: return ret; } -static int rsa_check_key_length(unsigned int len) -{ - switch (len) { - case 512: - case 1024: - case 1536: - case 2048: - case 3072: - case 4096: - return 0; - } - - return -EINVAL; -} - static int rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key, unsigned int keylen) { diff --git a/crypto/rsa_helper.c b/crypto/rsa_helper.c index 0149ed3..df1f480 100644 --- a/crypto/rsa_helper.c +++ b/crypto/rsa_helper.c @@ -14,6 +14,9 @@ #include <linux/export.h> #include <linux/err.h> #include <linux/fips.h> +#include <linux/slab.h> +#include <linux/dma-mapping.h> +#include <linux/device.h> #include <crypto/internal/rsa.h> #include "rsapubkey-asn1.h" #include "rsaprivkey-asn1.h" @@ -239,3 +242,182 @@ error: return ret; } EXPORT_SYMBOL_GPL(rsa_parse_mpi_priv_key); + +int rsa_check_key_length(unsigned int len) +{ + switch (len) { + case 512: + case 1024: + case 1536: + case 2048: + case 3072: + case 4096: + return 0; + } + + return -EINVAL; +} +EXPORT_SYMBOL_GPL(rsa_check_key_length); + +void raw_rsa_free_key(struct rsa_raw_key *key) +{ + kzfree(key->d); + key->d = NULL; + + kfree(key->e); + key->e = NULL; + + kfree(key->n); + key->n = NULL; + + key->n_sz = 0; + key->e_sz = 0; +} +EXPORT_SYMBOL_GPL(raw_rsa_free_key); + +void raw_rsa_free_coherent_key(struct device *dev, struct rsa_raw_key *key) +{ + if (key->d) { + memset(key->d, '\0', key->n_sz); + dma_free_coherent(dev, key->n_sz, key->d, key->dma_d); + key->d = NULL; + } + + if (key->e) { + dma_free_coherent(dev, key->n_sz, key->e, key->dma_e); + key->e = NULL; + } + + if (key->n) { + dma_free_coherent(dev, key->n_sz, key->n, key->dma_n); + key->n = NULL; + } + + key->n_sz = 0; + key->e_sz = 0; +} +EXPORT_SYMBOL_GPL(raw_rsa_free_coherent_key); + +int raw_rsa_get_n(void *context, const void *value, size_t vlen) +{ + struct rsa_raw_ctx *ctx = context; + struct rsa_raw_key *key = &ctx->key; + const char *ptr = value; + int ret = -EINVAL; + + while (!*ptr && vlen) { + ptr++; + vlen--; + } + + key->n_sz = vlen; + /* In FIPS mode only allow key size 2K & 3K */ + if (fips_enabled && (key->n_sz != 256 && key->n_sz != 384)) { + dev_err(ctx->dev, "RSA: key size not allowed in FIPS mode\n"); + goto err; + } + /* invalid key size provided */ + ret = rsa_check_key_length(key->n_sz << 3); + if (ret) + goto err; + + if (key->is_coherent) + key->n = kzalloc(key->n_sz, key->flags); + else + key->n = dma_zalloc_coherent(ctx->dev, key->n_sz, &key->dma_n, + key->flags); + + if (!key->n) { + ret = -ENOMEM; + goto err; + } + + memcpy(key->n, ptr, key->n_sz); + + return 0; +err: + key->n_sz = 0; + key->n = NULL; + return ret; +} +EXPORT_SYMBOL_GPL(raw_rsa_get_n); + +int raw_rsa_get_e(void *context, const void *value, size_t vlen) +{ + struct rsa_raw_ctx *ctx = context; + struct rsa_raw_key *key = &ctx->key; + const char *ptr = value; + size_t offset = 0; + + while (!*ptr && vlen) { + ptr++; + vlen--; + } + + key->e_sz = vlen; + + if (!key->n_sz || !vlen || vlen > key->n_sz) { + key->e = NULL; + return -EINVAL; + } + + if (key->is_coherent) { + key->e = kzalloc(key->e_sz, key->flags); + } else { + key->e = dma_zalloc_coherent(ctx->dev, key->n_sz, &key->dma_e, + key->flags); + offset = key->n_sz - vlen; + } + + if (!key->e) + return -ENOMEM; + + memcpy(key->e + offset, ptr, vlen); + + return 0; +} +EXPORT_SYMBOL_GPL(raw_rsa_get_e); + +int raw_rsa_get_d(void *context, const void *value, size_t vlen) +{ + struct rsa_raw_ctx *ctx = context; + struct rsa_raw_key *key = &ctx->key; + const char *ptr = value; + size_t offset = 0; + int ret = -EINVAL; + + while (!*ptr && vlen) { + ptr++; + vlen--; + } + + if (!key->n_sz || !vlen || vlen > key->n_sz) + goto err; + + /* In FIPS mode only allow key size 2K & 3K */ + if (fips_enabled && (vlen != 256 && vlen != 384)) { + dev_err(ctx->dev, "RSA: key size not allowed in FIPS mode\n"); + goto err; + } + + if (key->is_coherent) { + key->d = kzalloc(key->n_sz, key->flags); + } else { + key->d = dma_zalloc_coherent(ctx->dev, key->n_sz, &key->dma_d, + key->flags); + offset = key->n_sz - vlen; + } + + if (!key->d) { + ret = -ENOMEM; + goto err; + } + + memcpy(key->d + offset, ptr, vlen); + + return 0; +err: + key->d = NULL; + return ret; +} +EXPORT_SYMBOL_GPL(raw_rsa_get_d); diff --git a/include/crypto/internal/rsa.h b/include/crypto/internal/rsa.h index f8ef7b1..854b9b7 100644 --- a/include/crypto/internal/rsa.h +++ b/include/crypto/internal/rsa.h @@ -31,11 +31,30 @@ struct rsa_mpi_key { MPI d; }; +struct rsa_raw_key { + u8 *n; + u8 *e; + u8 *d; + dma_addr_t dma_n; + dma_addr_t dma_e; + dma_addr_t dma_d; + size_t n_sz; + size_t e_sz; + bool is_coherent; + gfp_t flags; +}; + struct rsa_ctx { const struct rsa_asn1_action *action; struct rsa_mpi_key key; }; +struct rsa_raw_ctx { + const struct rsa_asn1_action *action; + struct rsa_raw_key key; + struct device *dev; +}; + int rsa_get_mpi_n(void *context, const void *value, size_t vlen); int rsa_get_mpi_e(void *context, const void *value, size_t vlen); int rsa_get_mpi_d(void *context, const void *value, size_t vlen); @@ -47,5 +66,14 @@ int rsa_parse_mpi_pub_key(struct rsa_ctx *ctx, const void *key, int rsa_parse_mpi_priv_key(struct rsa_ctx *ctx, const void *key, unsigned int key_len); +int rsa_check_key_length(unsigned int len); + +void raw_rsa_free_key(struct rsa_raw_key *key); +void raw_rsa_free_coherent_key(struct device *dev, struct rsa_raw_key *key); + +int raw_rsa_get_n(void *context, const void *value, size_t vlen); +int raw_rsa_get_e(void *context, const void *value, size_t vlen); +int raw_rsa_get_d(void *context, const void *value, size_t vlen); + extern struct crypto_template rsa_pkcs1pad_tmpl; #endif -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html