1 // SPDX-License-Identifier: GPL-2.0 OR MIT 2 /* 3 * Copyright (C) 2018-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. 4 */ 5 6 #include "curve25519.h" 7 8 #include <stdint.h> 9 #include <string.h> 10 11 #ifndef __BYTE_ORDER__ 12 #include <sys/param.h> 13 #if !defined(BYTE_ORDER) || !defined(BIG_ENDIAN) || !defined(LITTLE_ENDIAN) 14 #error "Unable to determine endianness." 15 #endif 16 #define __BYTE_ORDER__ BYTE_ORDER 17 #define __ORDER_BIG_ENDIAN__ BIG_ENDIAN 18 #define __ORDER_LITTLE_ENDIAN__ LITTLE_ENDIAN 19 #endif 20 21 #ifdef __linux__ 22 #include <linux/types.h> 23 typedef __u64 u64; 24 typedef __u32 u32; 25 typedef __u8 u8; 26 typedef __s64 s64; 27 #else 28 typedef uint64_t u64, __le64; 29 typedef uint32_t u32, __le32; 30 typedef uint8_t u8; 31 typedef int64_t s64; 32 #endif 33 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 34 #define le64_to_cpup(a) __builtin_bswap64(*(a)) 35 #define le32_to_cpup(a) __builtin_bswap32(*(a)) 36 #define cpu_to_le64(a) __builtin_bswap64(a) 37 #else 38 #define le64_to_cpup(a) (*(a)) 39 #define le32_to_cpup(a) (*(a)) 40 #define cpu_to_le64(a) (a) 41 #endif 42 #ifndef __unused 43 #define __unused __attribute__((unused)) 44 #endif 45 #ifndef __always_inline 46 #define __always_inline __inline __attribute__((__always_inline__)) 47 #endif 48 #ifndef noinline 49 #define noinline __attribute__((noinline)) 50 #endif 51 #ifndef __aligned 52 #define __aligned(x) __attribute__((aligned(x))) 53 #endif 54 #ifndef __force 55 #define __force 56 #endif 57 58 static __always_inline __unused __le32 get_unaligned_le32(const u8 *a) 59 { 60 __le32 l; 61 __builtin_memcpy(&l, a, sizeof(l)); 62 return le32_to_cpup(&l); 63 } 64 static __always_inline __unused __le64 get_unaligned_le64(const u8 *a) 65 { 66 __le64 l; 67 __builtin_memcpy(&l, a, sizeof(l)); 68 return le64_to_cpup(&l); 69 } 70 static __always_inline __unused void put_unaligned_le64(u64 s, u8 *d) 71 { 72 __le64 l = cpu_to_le64(s); 73 __builtin_memcpy(d, &l, sizeof(l)); 74 } 75 76 static noinline void memzero_explicit(void *s, size_t count) 77 { 78 memset(s, 0, count); 79 asm volatile("": :"r"(s) : "memory"); 80 } 81 82 #ifdef __SIZEOF_INT128__ 83 #include "curve25519-hacl64.h" 84 #else 85 #include "curve25519-fiat32.h" 86 #endif 87 88 void curve25519_generate_public(uint8_t pub[static CURVE25519_KEY_SIZE], const uint8_t secret[static CURVE25519_KEY_SIZE]) 89 { 90 static const uint8_t basepoint[CURVE25519_KEY_SIZE] __aligned(sizeof(uintptr_t)) = { 9 }; 91 92 curve25519(pub, secret, basepoint); 93 } 94 95 void curve25519(uint8_t mypublic[static CURVE25519_KEY_SIZE], const uint8_t secret[static CURVE25519_KEY_SIZE], const uint8_t basepoint[static CURVE25519_KEY_SIZE]) 96 { 97 curve25519_generic(mypublic, secret, basepoint); 98 } 99