X25519.c (2027B)
1 /* 2 * X25519 - Elliptic Curve Diffie-Hellman using Curve25519 3 * RFC 7748 4 * 5 * Fast, secure key exchange using Montgomery ladder 6 */ 7 8 #include "X25519.h" 9 #include <string.h> 10 11 /* External functions from Curve25519.c */ 12 extern void curve25519_scalarmult_base(uint8_t *q, const uint8_t *n); 13 extern void curve25519_scalarmult(uint8_t *q, const uint8_t *n, const uint8_t *p); 14 15 /* 16 * Generate X25519 public key from secret key 17 * 18 * Secret key should be 32 random bytes 19 * This function clamps the secret key according to RFC 7748 20 */ 21 void x25519_public_key(uint8_t public_key[32], const uint8_t secret_key[32]) { 22 uint8_t clamped[32]; 23 memcpy(clamped, secret_key, 32); 24 25 /* Clamp the secret key (RFC 7748 section 5) */ 26 clamped[0] &= 248; /* Clear bits 0, 1, 2 */ 27 clamped[31] &= 127; /* Clear bit 255 */ 28 clamped[31] |= 64; /* Set bit 254 */ 29 30 /* Compute public key = secret * G (base point) */ 31 curve25519_scalarmult_base(public_key, clamped); 32 33 /* Zero sensitive data */ 34 memset(clamped, 0, 32); 35 } 36 37 /* 38 * Compute X25519 shared secret 39 * 40 * Returns 0 on success, -1 if the public key is invalid (all-zero result) 41 * An all-zero result indicates a weak/invalid public key 42 */ 43 int x25519_shared_secret(uint8_t shared_secret[32], 44 const uint8_t my_secret_key[32], 45 const uint8_t their_public_key[32]) { 46 uint8_t clamped[32]; 47 memcpy(clamped, my_secret_key, 32); 48 49 /* Clamp the secret key */ 50 clamped[0] &= 248; 51 clamped[31] &= 127; 52 clamped[31] |= 64; 53 54 /* Compute shared secret = my_secret * their_public */ 55 curve25519_scalarmult(shared_secret, clamped, their_public_key); 56 57 /* Zero sensitive data */ 58 memset(clamped, 0, 32); 59 60 /* Check for all-zero result (weak public key) */ 61 uint8_t is_zero = 1; 62 for (int i = 0; i < 32; i++) { 63 is_zero &= (shared_secret[i] == 0); 64 } 65 66 if (is_zero) { 67 memset(shared_secret, 0, 32); 68 return -1; /* Invalid public key */ 69 } 70 71 return 0; 72 }