18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 OR MIT */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2015-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#ifndef CURVE25519_H 78c2ecf20Sopenharmony_ci#define CURVE25519_H 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <crypto/algapi.h> // For crypto_memneq. 108c2ecf20Sopenharmony_ci#include <linux/types.h> 118c2ecf20Sopenharmony_ci#include <linux/random.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_cienum curve25519_lengths { 148c2ecf20Sopenharmony_ci CURVE25519_KEY_SIZE = 32 158c2ecf20Sopenharmony_ci}; 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ciextern const u8 curve25519_null_point[]; 188c2ecf20Sopenharmony_ciextern const u8 curve25519_base_point[]; 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_civoid curve25519_generic(u8 out[CURVE25519_KEY_SIZE], 218c2ecf20Sopenharmony_ci const u8 scalar[CURVE25519_KEY_SIZE], 228c2ecf20Sopenharmony_ci const u8 point[CURVE25519_KEY_SIZE]); 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_civoid curve25519_arch(u8 out[CURVE25519_KEY_SIZE], 258c2ecf20Sopenharmony_ci const u8 scalar[CURVE25519_KEY_SIZE], 268c2ecf20Sopenharmony_ci const u8 point[CURVE25519_KEY_SIZE]); 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_civoid curve25519_base_arch(u8 pub[CURVE25519_KEY_SIZE], 298c2ecf20Sopenharmony_ci const u8 secret[CURVE25519_KEY_SIZE]); 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistatic inline 328c2ecf20Sopenharmony_cibool __must_check curve25519(u8 mypublic[CURVE25519_KEY_SIZE], 338c2ecf20Sopenharmony_ci const u8 secret[CURVE25519_KEY_SIZE], 348c2ecf20Sopenharmony_ci const u8 basepoint[CURVE25519_KEY_SIZE]) 358c2ecf20Sopenharmony_ci{ 368c2ecf20Sopenharmony_ci if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_CURVE25519)) 378c2ecf20Sopenharmony_ci curve25519_arch(mypublic, secret, basepoint); 388c2ecf20Sopenharmony_ci else 398c2ecf20Sopenharmony_ci curve25519_generic(mypublic, secret, basepoint); 408c2ecf20Sopenharmony_ci return crypto_memneq(mypublic, curve25519_null_point, 418c2ecf20Sopenharmony_ci CURVE25519_KEY_SIZE); 428c2ecf20Sopenharmony_ci} 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_cistatic inline bool 458c2ecf20Sopenharmony_ci__must_check curve25519_generate_public(u8 pub[CURVE25519_KEY_SIZE], 468c2ecf20Sopenharmony_ci const u8 secret[CURVE25519_KEY_SIZE]) 478c2ecf20Sopenharmony_ci{ 488c2ecf20Sopenharmony_ci if (unlikely(!crypto_memneq(secret, curve25519_null_point, 498c2ecf20Sopenharmony_ci CURVE25519_KEY_SIZE))) 508c2ecf20Sopenharmony_ci return false; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_CURVE25519)) 538c2ecf20Sopenharmony_ci curve25519_base_arch(pub, secret); 548c2ecf20Sopenharmony_ci else 558c2ecf20Sopenharmony_ci curve25519_generic(pub, secret, curve25519_base_point); 568c2ecf20Sopenharmony_ci return crypto_memneq(pub, curve25519_null_point, CURVE25519_KEY_SIZE); 578c2ecf20Sopenharmony_ci} 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cistatic inline void curve25519_clamp_secret(u8 secret[CURVE25519_KEY_SIZE]) 608c2ecf20Sopenharmony_ci{ 618c2ecf20Sopenharmony_ci secret[0] &= 248; 628c2ecf20Sopenharmony_ci secret[31] = (secret[31] & 127) | 64; 638c2ecf20Sopenharmony_ci} 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_cistatic inline void curve25519_generate_secret(u8 secret[CURVE25519_KEY_SIZE]) 668c2ecf20Sopenharmony_ci{ 678c2ecf20Sopenharmony_ci get_random_bytes_wait(secret, CURVE25519_KEY_SIZE); 688c2ecf20Sopenharmony_ci curve25519_clamp_secret(secret); 698c2ecf20Sopenharmony_ci} 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci#endif /* CURVE25519_H */ 72