b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame] | 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
| 2 | From: Ard Biesheuvel <ardb@kernel.org> |
| 3 | Date: Fri, 8 Nov 2019 13:22:34 +0100 |
| 4 | Subject: [PATCH] crypto: curve25519 - implement generic KPP driver |
| 5 | |
| 6 | commit ee772cb641135739c1530647391d5a04c39db192 upstream. |
| 7 | |
| 8 | Expose the generic Curve25519 library via the crypto API KPP interface. |
| 9 | |
| 10 | Signed-off-by: Ard Biesheuvel <ardb@kernel.org> |
| 11 | Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> |
| 12 | Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com> |
| 13 | --- |
| 14 | crypto/Kconfig | 5 +++ |
| 15 | crypto/Makefile | 1 + |
| 16 | crypto/curve25519-generic.c | 90 +++++++++++++++++++++++++++++++++++++ |
| 17 | 3 files changed, 96 insertions(+) |
| 18 | create mode 100644 crypto/curve25519-generic.c |
| 19 | |
| 20 | --- a/crypto/Kconfig |
| 21 | +++ b/crypto/Kconfig |
| 22 | @@ -264,6 +264,11 @@ config CRYPTO_ECRDSA |
| 23 | standard algorithms (called GOST algorithms). Only signature verification |
| 24 | is implemented. |
| 25 | |
| 26 | +config CRYPTO_CURVE25519 |
| 27 | + tristate "Curve25519 algorithm" |
| 28 | + select CRYPTO_KPP |
| 29 | + select CRYPTO_LIB_CURVE25519_GENERIC |
| 30 | + |
| 31 | comment "Authenticated Encryption with Associated Data" |
| 32 | |
| 33 | config CRYPTO_CCM |
| 34 | --- a/crypto/Makefile |
| 35 | +++ b/crypto/Makefile |
| 36 | @@ -167,6 +167,7 @@ obj-$(CONFIG_CRYPTO_ZSTD) += zstd.o |
| 37 | obj-$(CONFIG_CRYPTO_OFB) += ofb.o |
| 38 | obj-$(CONFIG_CRYPTO_ECC) += ecc.o |
| 39 | obj-$(CONFIG_CRYPTO_ESSIV) += essiv.o |
| 40 | +obj-$(CONFIG_CRYPTO_CURVE25519) += curve25519-generic.o |
| 41 | |
| 42 | ecdh_generic-y += ecdh.o |
| 43 | ecdh_generic-y += ecdh_helper.o |
| 44 | --- /dev/null |
| 45 | +++ b/crypto/curve25519-generic.c |
| 46 | @@ -0,0 +1,90 @@ |
| 47 | +// SPDX-License-Identifier: GPL-2.0-or-later |
| 48 | + |
| 49 | +#include <crypto/curve25519.h> |
| 50 | +#include <crypto/internal/kpp.h> |
| 51 | +#include <crypto/kpp.h> |
| 52 | +#include <linux/module.h> |
| 53 | +#include <linux/scatterlist.h> |
| 54 | + |
| 55 | +static int curve25519_set_secret(struct crypto_kpp *tfm, const void *buf, |
| 56 | + unsigned int len) |
| 57 | +{ |
| 58 | + u8 *secret = kpp_tfm_ctx(tfm); |
| 59 | + |
| 60 | + if (!len) |
| 61 | + curve25519_generate_secret(secret); |
| 62 | + else if (len == CURVE25519_KEY_SIZE && |
| 63 | + crypto_memneq(buf, curve25519_null_point, CURVE25519_KEY_SIZE)) |
| 64 | + memcpy(secret, buf, CURVE25519_KEY_SIZE); |
| 65 | + else |
| 66 | + return -EINVAL; |
| 67 | + return 0; |
| 68 | +} |
| 69 | + |
| 70 | +static int curve25519_compute_value(struct kpp_request *req) |
| 71 | +{ |
| 72 | + struct crypto_kpp *tfm = crypto_kpp_reqtfm(req); |
| 73 | + const u8 *secret = kpp_tfm_ctx(tfm); |
| 74 | + u8 public_key[CURVE25519_KEY_SIZE]; |
| 75 | + u8 buf[CURVE25519_KEY_SIZE]; |
| 76 | + int copied, nbytes; |
| 77 | + u8 const *bp; |
| 78 | + |
| 79 | + if (req->src) { |
| 80 | + copied = sg_copy_to_buffer(req->src, |
| 81 | + sg_nents_for_len(req->src, |
| 82 | + CURVE25519_KEY_SIZE), |
| 83 | + public_key, CURVE25519_KEY_SIZE); |
| 84 | + if (copied != CURVE25519_KEY_SIZE) |
| 85 | + return -EINVAL; |
| 86 | + bp = public_key; |
| 87 | + } else { |
| 88 | + bp = curve25519_base_point; |
| 89 | + } |
| 90 | + |
| 91 | + curve25519_generic(buf, secret, bp); |
| 92 | + |
| 93 | + /* might want less than we've got */ |
| 94 | + nbytes = min_t(size_t, CURVE25519_KEY_SIZE, req->dst_len); |
| 95 | + copied = sg_copy_from_buffer(req->dst, sg_nents_for_len(req->dst, |
| 96 | + nbytes), |
| 97 | + buf, nbytes); |
| 98 | + if (copied != nbytes) |
| 99 | + return -EINVAL; |
| 100 | + return 0; |
| 101 | +} |
| 102 | + |
| 103 | +static unsigned int curve25519_max_size(struct crypto_kpp *tfm) |
| 104 | +{ |
| 105 | + return CURVE25519_KEY_SIZE; |
| 106 | +} |
| 107 | + |
| 108 | +static struct kpp_alg curve25519_alg = { |
| 109 | + .base.cra_name = "curve25519", |
| 110 | + .base.cra_driver_name = "curve25519-generic", |
| 111 | + .base.cra_priority = 100, |
| 112 | + .base.cra_module = THIS_MODULE, |
| 113 | + .base.cra_ctxsize = CURVE25519_KEY_SIZE, |
| 114 | + |
| 115 | + .set_secret = curve25519_set_secret, |
| 116 | + .generate_public_key = curve25519_compute_value, |
| 117 | + .compute_shared_secret = curve25519_compute_value, |
| 118 | + .max_size = curve25519_max_size, |
| 119 | +}; |
| 120 | + |
| 121 | +static int curve25519_init(void) |
| 122 | +{ |
| 123 | + return crypto_register_kpp(&curve25519_alg); |
| 124 | +} |
| 125 | + |
| 126 | +static void curve25519_exit(void) |
| 127 | +{ |
| 128 | + crypto_unregister_kpp(&curve25519_alg); |
| 129 | +} |
| 130 | + |
| 131 | +subsys_initcall(curve25519_init); |
| 132 | +module_exit(curve25519_exit); |
| 133 | + |
| 134 | +MODULE_ALIAS_CRYPTO("curve25519"); |
| 135 | +MODULE_ALIAS_CRYPTO("curve25519-generic"); |
| 136 | +MODULE_LICENSE("GPL"); |