| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
| From: Ard Biesheuvel <ardb@kernel.org> |
| Date: Fri, 8 Nov 2019 13:22:34 +0100 |
| Subject: [PATCH] crypto: curve25519 - implement generic KPP driver |
| |
| commit ee772cb641135739c1530647391d5a04c39db192 upstream. |
| |
| Expose the generic Curve25519 library via the crypto API KPP interface. |
| |
| Signed-off-by: Ard Biesheuvel <ardb@kernel.org> |
| Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> |
| Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com> |
| --- |
| crypto/Kconfig | 5 +++ |
| crypto/Makefile | 1 + |
| crypto/curve25519-generic.c | 90 +++++++++++++++++++++++++++++++++++++ |
| 3 files changed, 96 insertions(+) |
| create mode 100644 crypto/curve25519-generic.c |
| |
| --- a/crypto/Kconfig |
| +++ b/crypto/Kconfig |
| @@ -264,6 +264,11 @@ config CRYPTO_ECRDSA |
| standard algorithms (called GOST algorithms). Only signature verification |
| is implemented. |
| |
| +config CRYPTO_CURVE25519 |
| + tristate "Curve25519 algorithm" |
| + select CRYPTO_KPP |
| + select CRYPTO_LIB_CURVE25519_GENERIC |
| + |
| comment "Authenticated Encryption with Associated Data" |
| |
| config CRYPTO_CCM |
| --- a/crypto/Makefile |
| +++ b/crypto/Makefile |
| @@ -167,6 +167,7 @@ obj-$(CONFIG_CRYPTO_ZSTD) += zstd.o |
| obj-$(CONFIG_CRYPTO_OFB) += ofb.o |
| obj-$(CONFIG_CRYPTO_ECC) += ecc.o |
| obj-$(CONFIG_CRYPTO_ESSIV) += essiv.o |
| +obj-$(CONFIG_CRYPTO_CURVE25519) += curve25519-generic.o |
| |
| ecdh_generic-y += ecdh.o |
| ecdh_generic-y += ecdh_helper.o |
| --- /dev/null |
| +++ b/crypto/curve25519-generic.c |
| @@ -0,0 +1,90 @@ |
| +// SPDX-License-Identifier: GPL-2.0-or-later |
| + |
| +#include <crypto/curve25519.h> |
| +#include <crypto/internal/kpp.h> |
| +#include <crypto/kpp.h> |
| +#include <linux/module.h> |
| +#include <linux/scatterlist.h> |
| + |
| +static int curve25519_set_secret(struct crypto_kpp *tfm, const void *buf, |
| + unsigned int len) |
| +{ |
| + u8 *secret = kpp_tfm_ctx(tfm); |
| + |
| + if (!len) |
| + curve25519_generate_secret(secret); |
| + else if (len == CURVE25519_KEY_SIZE && |
| + crypto_memneq(buf, curve25519_null_point, CURVE25519_KEY_SIZE)) |
| + memcpy(secret, buf, CURVE25519_KEY_SIZE); |
| + else |
| + return -EINVAL; |
| + return 0; |
| +} |
| + |
| +static int curve25519_compute_value(struct kpp_request *req) |
| +{ |
| + struct crypto_kpp *tfm = crypto_kpp_reqtfm(req); |
| + const u8 *secret = kpp_tfm_ctx(tfm); |
| + u8 public_key[CURVE25519_KEY_SIZE]; |
| + u8 buf[CURVE25519_KEY_SIZE]; |
| + int copied, nbytes; |
| + u8 const *bp; |
| + |
| + if (req->src) { |
| + copied = sg_copy_to_buffer(req->src, |
| + sg_nents_for_len(req->src, |
| + CURVE25519_KEY_SIZE), |
| + public_key, CURVE25519_KEY_SIZE); |
| + if (copied != CURVE25519_KEY_SIZE) |
| + return -EINVAL; |
| + bp = public_key; |
| + } else { |
| + bp = curve25519_base_point; |
| + } |
| + |
| + curve25519_generic(buf, secret, bp); |
| + |
| + /* might want less than we've got */ |
| + nbytes = min_t(size_t, CURVE25519_KEY_SIZE, req->dst_len); |
| + copied = sg_copy_from_buffer(req->dst, sg_nents_for_len(req->dst, |
| + nbytes), |
| + buf, nbytes); |
| + if (copied != nbytes) |
| + return -EINVAL; |
| + return 0; |
| +} |
| + |
| +static unsigned int curve25519_max_size(struct crypto_kpp *tfm) |
| +{ |
| + return CURVE25519_KEY_SIZE; |
| +} |
| + |
| +static struct kpp_alg curve25519_alg = { |
| + .base.cra_name = "curve25519", |
| + .base.cra_driver_name = "curve25519-generic", |
| + .base.cra_priority = 100, |
| + .base.cra_module = THIS_MODULE, |
| + .base.cra_ctxsize = CURVE25519_KEY_SIZE, |
| + |
| + .set_secret = curve25519_set_secret, |
| + .generate_public_key = curve25519_compute_value, |
| + .compute_shared_secret = curve25519_compute_value, |
| + .max_size = curve25519_max_size, |
| +}; |
| + |
| +static int curve25519_init(void) |
| +{ |
| + return crypto_register_kpp(&curve25519_alg); |
| +} |
| + |
| +static void curve25519_exit(void) |
| +{ |
| + crypto_unregister_kpp(&curve25519_alg); |
| +} |
| + |
| +subsys_initcall(curve25519_init); |
| +module_exit(curve25519_exit); |
| + |
| +MODULE_ALIAS_CRYPTO("curve25519"); |
| +MODULE_ALIAS_CRYPTO("curve25519-generic"); |
| +MODULE_LICENSE("GPL"); |