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"); 91