Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto: curve25519 - implement generic KPP driver

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>

authored by

Ard Biesheuvel and committed by
Herbert Xu
ee772cb6 f613457a

+96
+5
crypto/Kconfig
··· 264 264 standard algorithms (called GOST algorithms). Only signature verification 265 265 is implemented. 266 266 267 + config CRYPTO_CURVE25519 268 + tristate "Curve25519 algorithm" 269 + select CRYPTO_KPP 270 + select CRYPTO_LIB_CURVE25519_GENERIC 271 + 267 272 comment "Authenticated Encryption with Associated Data" 268 273 269 274 config CRYPTO_CCM
+1
crypto/Makefile
··· 168 168 obj-$(CONFIG_CRYPTO_OFB) += ofb.o 169 169 obj-$(CONFIG_CRYPTO_ECC) += ecc.o 170 170 obj-$(CONFIG_CRYPTO_ESSIV) += essiv.o 171 + obj-$(CONFIG_CRYPTO_CURVE25519) += curve25519-generic.o 171 172 172 173 ecdh_generic-y += ecdh.o 173 174 ecdh_generic-y += ecdh_helper.o
+90
crypto/curve25519-generic.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + 3 + #include <crypto/curve25519.h> 4 + #include <crypto/internal/kpp.h> 5 + #include <crypto/kpp.h> 6 + #include <linux/module.h> 7 + #include <linux/scatterlist.h> 8 + 9 + static int curve25519_set_secret(struct crypto_kpp *tfm, const void *buf, 10 + unsigned int len) 11 + { 12 + u8 *secret = kpp_tfm_ctx(tfm); 13 + 14 + if (!len) 15 + curve25519_generate_secret(secret); 16 + else if (len == CURVE25519_KEY_SIZE && 17 + crypto_memneq(buf, curve25519_null_point, CURVE25519_KEY_SIZE)) 18 + memcpy(secret, buf, CURVE25519_KEY_SIZE); 19 + else 20 + return -EINVAL; 21 + return 0; 22 + } 23 + 24 + static int curve25519_compute_value(struct kpp_request *req) 25 + { 26 + struct crypto_kpp *tfm = crypto_kpp_reqtfm(req); 27 + const u8 *secret = kpp_tfm_ctx(tfm); 28 + u8 public_key[CURVE25519_KEY_SIZE]; 29 + u8 buf[CURVE25519_KEY_SIZE]; 30 + int copied, nbytes; 31 + u8 const *bp; 32 + 33 + if (req->src) { 34 + copied = sg_copy_to_buffer(req->src, 35 + sg_nents_for_len(req->src, 36 + CURVE25519_KEY_SIZE), 37 + public_key, CURVE25519_KEY_SIZE); 38 + if (copied != CURVE25519_KEY_SIZE) 39 + return -EINVAL; 40 + bp = public_key; 41 + } else { 42 + bp = curve25519_base_point; 43 + } 44 + 45 + curve25519_generic(buf, secret, bp); 46 + 47 + /* might want less than we've got */ 48 + nbytes = min_t(size_t, CURVE25519_KEY_SIZE, req->dst_len); 49 + copied = sg_copy_from_buffer(req->dst, sg_nents_for_len(req->dst, 50 + nbytes), 51 + buf, nbytes); 52 + if (copied != nbytes) 53 + return -EINVAL; 54 + return 0; 55 + } 56 + 57 + static unsigned int curve25519_max_size(struct crypto_kpp *tfm) 58 + { 59 + return CURVE25519_KEY_SIZE; 60 + } 61 + 62 + static struct kpp_alg curve25519_alg = { 63 + .base.cra_name = "curve25519", 64 + .base.cra_driver_name = "curve25519-generic", 65 + .base.cra_priority = 100, 66 + .base.cra_module = THIS_MODULE, 67 + .base.cra_ctxsize = CURVE25519_KEY_SIZE, 68 + 69 + .set_secret = curve25519_set_secret, 70 + .generate_public_key = curve25519_compute_value, 71 + .compute_shared_secret = curve25519_compute_value, 72 + .max_size = curve25519_max_size, 73 + }; 74 + 75 + static int curve25519_init(void) 76 + { 77 + return crypto_register_kpp(&curve25519_alg); 78 + } 79 + 80 + static void curve25519_exit(void) 81 + { 82 + crypto_unregister_kpp(&curve25519_alg); 83 + } 84 + 85 + subsys_initcall(curve25519_init); 86 + module_exit(curve25519_exit); 87 + 88 + MODULE_ALIAS_CRYPTO("curve25519"); 89 + MODULE_ALIAS_CRYPTO("curve25519-generic"); 90 + MODULE_LICENSE("GPL");