18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci 38c2ecf20Sopenharmony_ci#include <crypto/curve25519.h> 48c2ecf20Sopenharmony_ci#include <crypto/internal/kpp.h> 58c2ecf20Sopenharmony_ci#include <crypto/kpp.h> 68c2ecf20Sopenharmony_ci#include <linux/module.h> 78c2ecf20Sopenharmony_ci#include <linux/scatterlist.h> 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_cistatic int curve25519_set_secret(struct crypto_kpp *tfm, const void *buf, 108c2ecf20Sopenharmony_ci unsigned int len) 118c2ecf20Sopenharmony_ci{ 128c2ecf20Sopenharmony_ci u8 *secret = kpp_tfm_ctx(tfm); 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci if (!len) 158c2ecf20Sopenharmony_ci curve25519_generate_secret(secret); 168c2ecf20Sopenharmony_ci else if (len == CURVE25519_KEY_SIZE && 178c2ecf20Sopenharmony_ci crypto_memneq(buf, curve25519_null_point, CURVE25519_KEY_SIZE)) 188c2ecf20Sopenharmony_ci memcpy(secret, buf, CURVE25519_KEY_SIZE); 198c2ecf20Sopenharmony_ci else 208c2ecf20Sopenharmony_ci return -EINVAL; 218c2ecf20Sopenharmony_ci return 0; 228c2ecf20Sopenharmony_ci} 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_cistatic int curve25519_compute_value(struct kpp_request *req) 258c2ecf20Sopenharmony_ci{ 268c2ecf20Sopenharmony_ci struct crypto_kpp *tfm = crypto_kpp_reqtfm(req); 278c2ecf20Sopenharmony_ci const u8 *secret = kpp_tfm_ctx(tfm); 288c2ecf20Sopenharmony_ci u8 public_key[CURVE25519_KEY_SIZE]; 298c2ecf20Sopenharmony_ci u8 buf[CURVE25519_KEY_SIZE]; 308c2ecf20Sopenharmony_ci int copied, nbytes; 318c2ecf20Sopenharmony_ci u8 const *bp; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci if (req->src) { 348c2ecf20Sopenharmony_ci copied = sg_copy_to_buffer(req->src, 358c2ecf20Sopenharmony_ci sg_nents_for_len(req->src, 368c2ecf20Sopenharmony_ci CURVE25519_KEY_SIZE), 378c2ecf20Sopenharmony_ci public_key, CURVE25519_KEY_SIZE); 388c2ecf20Sopenharmony_ci if (copied != CURVE25519_KEY_SIZE) 398c2ecf20Sopenharmony_ci return -EINVAL; 408c2ecf20Sopenharmony_ci bp = public_key; 418c2ecf20Sopenharmony_ci } else { 428c2ecf20Sopenharmony_ci bp = curve25519_base_point; 438c2ecf20Sopenharmony_ci } 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci curve25519_generic(buf, secret, bp); 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci /* might want less than we've got */ 488c2ecf20Sopenharmony_ci nbytes = min_t(size_t, CURVE25519_KEY_SIZE, req->dst_len); 498c2ecf20Sopenharmony_ci copied = sg_copy_from_buffer(req->dst, sg_nents_for_len(req->dst, 508c2ecf20Sopenharmony_ci nbytes), 518c2ecf20Sopenharmony_ci buf, nbytes); 528c2ecf20Sopenharmony_ci if (copied != nbytes) 538c2ecf20Sopenharmony_ci return -EINVAL; 548c2ecf20Sopenharmony_ci return 0; 558c2ecf20Sopenharmony_ci} 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_cistatic unsigned int curve25519_max_size(struct crypto_kpp *tfm) 588c2ecf20Sopenharmony_ci{ 598c2ecf20Sopenharmony_ci return CURVE25519_KEY_SIZE; 608c2ecf20Sopenharmony_ci} 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_cistatic struct kpp_alg curve25519_alg = { 638c2ecf20Sopenharmony_ci .base.cra_name = "curve25519", 648c2ecf20Sopenharmony_ci .base.cra_driver_name = "curve25519-generic", 658c2ecf20Sopenharmony_ci .base.cra_priority = 100, 668c2ecf20Sopenharmony_ci .base.cra_module = THIS_MODULE, 678c2ecf20Sopenharmony_ci .base.cra_ctxsize = CURVE25519_KEY_SIZE, 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci .set_secret = curve25519_set_secret, 708c2ecf20Sopenharmony_ci .generate_public_key = curve25519_compute_value, 718c2ecf20Sopenharmony_ci .compute_shared_secret = curve25519_compute_value, 728c2ecf20Sopenharmony_ci .max_size = curve25519_max_size, 738c2ecf20Sopenharmony_ci}; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_cistatic int curve25519_init(void) 768c2ecf20Sopenharmony_ci{ 778c2ecf20Sopenharmony_ci return crypto_register_kpp(&curve25519_alg); 788c2ecf20Sopenharmony_ci} 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cistatic void curve25519_exit(void) 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci crypto_unregister_kpp(&curve25519_alg); 838c2ecf20Sopenharmony_ci} 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_cisubsys_initcall(curve25519_init); 868c2ecf20Sopenharmony_cimodule_exit(curve25519_exit); 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("curve25519"); 898c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("curve25519-generic"); 908c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 91