- x25519 implementation not working (don't optimize cause that would be cheating)
- 09 Jan 2026 02:04:47 pm
Before I start on my entry to the x25519 contest I am making a slow c implementation but I can't seem to get it to work.
My output is
Code:
and my code is
Code:
The code is an almost exact copy of the second paper linked so I don't know why it isn't working.
EDIT: The code was fine , the test was timing out.
Thank you for any help and good luck for the competition.
My output is
Code:
[Test failed!] Hash #1 ("test 1 - Alice * Bob") did not match the expected CRC 4013917A (got 349F4775).
[Test failed!] Hash #2 ("test 2 - Bob * Alice") did not match the expected CRC E0AEF5AA (got 349F4775).
[Test failed!] Hash #3 ("test 3 - public key generation") did not match the expected CRC DB48F62D (got 349F4775).
[Test failed!] Hash #4 ("test 4 - iterative (k=9, u=9)") did not match the expected CRC C08FD34D (got 349F4775).
[Test failed!] Hash #5 ("test 5 - clamping") did not match the expected CRC 42229300 (got 349F4775).and my code is
Code:
/**
* @file main.c
* @brief X25519 Test Suite - RFC 7748 Test Vectors
*
* This test suite validates X25519 implementations against official RFC 7748
* test vectors. Each test is displayed separately for automated verification.
*/
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <ti/screen.h>
#include <ti/getkey.h>
#include <sys/timers.h>
/* Include contestant's X25519 implementation */
// #include "x25519.h"
#define x25519_p 2^255 - 19
#define x25519_q 2^252+0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed
/* Placeholder stub functions - contestants will replace these */
/*
bool tls_x25519_secret(
uint8_t shared_secret[32],
const uint8_t my_private[32],
const uint8_t their_public[32],
void (*yield_fn)(void *),
void *yield_data)
{
(void)shared_secret;
(void)my_private;
(void)their_public;
(void)yield_fn;
(void)yield_data;
return true; // Stub: always succeeds
}
bool tls_x25519_publickey(
uint8_t public_key[32],
const uint8_t private_key[32],
void (*yield_fn)(void *),
void *yield_data)
{
(void)public_key;
(void)private_key;
(void)yield_fn;
(void)yield_data;
return true;
} */
typedef unsigned char u8;
typedef long long i64;
typedef i64 field_elem[16];
static void unpack25519(field_elem out, const u8 *in)
{
int i;
for (i = 0; i < 16; ++i) out[i] = in[2*i] + ((i64) in[2*i + 1] << 8);
out[15] &= 0x7fff;
}
static void carry25519(field_elem elem)
{
int i;
i64 carry;
for (i = 0; i < 16; ++i) {
carry = elem[i] >> 16;
elem[i] -= carry << 16;
if (i < 15) elem[i + 1] += carry; else elem[0] += 38 * carry;
}
}
static void fadd(field_elem out, const field_elem a, const field_elem b) // out = a + b
{
int i;
for (i = 0; i < 16; ++i) out[i] = a[i] + b[i];
}
static void fsub(field_elem out, const field_elem a, const field_elem b) // out = a - b
{
int i;
for (i = 0; i < 16; ++i) out[i] = a[i] - b[i];
}
static void fmul(field_elem out, const field_elem a, const field_elem b) // out = a * b //
{
i64 i, j, product[31];
for (i = 0; i < 31; ++i) product[i] = 0;
for (i = 0; i < 16; ++i) {
for (j = 0; j < 16; ++j) product[i+j] += a[i] * b[j];
}
for (i = 0; i < 15; ++i) product[i] += 38 * product[i + 16];
for (i = 0; i < 16; ++i) out[i] = product[i];
carry25519(out);
carry25519(out);
}
static void finverse(field_elem out, const field_elem in) {
field_elem c;
int i;
for (i=0; i<16; i++) c[i] = in[i];
for (i=253; i>=0; i--) {
fmul(c, c, c);
if (i!=2 && i!=4) fmul(c, c, in);
}
for (i = 0; i < 16; ++i) out[i] = c[i];
}
static void swap25519(field_elem p, field_elem q, int bit)
{
i64 t, i, c = ~(bit - 1);
for (i = 0; i < 16; ++i) {
t = c & (p[i] ^ q[i]);
p[i] ^= t;
q[i] ^= t;
}
}
static void pack25519(u8 *out, const field_elem in)
{
int i, j, carry;
field_elem m, t;
for (i = 0; i < 16; ++i) t[i] = in[i];
carry25519(t); carry25519(t); carry25519(t);
for (j = 0; j < 2; ++j) {
m[0] = t[0] - 0xffed;
for(i = 1; i < 15; i++) {
m[i] = t[i] - 0xffff - ((m[i - 1] >> 16) & 1);
m[i - 1] &= 0xffff;
}
m[15] = t[15] - 0x7fff - ((m[14] >> 16) & 1);
carry = (m[15] >> 16) & 1;
m[14] &= 0xffff;
swap25519(t, m, 1 - carry);
}
for (i = 0; i < 16; ++i) {
out[2*i] = t[i] & 0xff;
out[2*i + 1] = t[i] >> 8;
}
}
static const field_elem _121665 = {0xDB41, 1};
void scalarmult(u8 *out, const u8 *scalar, const u8 *point)
{
u8 clamped[32];
i64 bit, i;
field_elem a, b, c, d, e, f, x;
for (i = 0; i < 32; ++i) clamped[i] = scalar[i];
clamped[0] &= 0xf8;
clamped[31] = (clamped[31] & 0x7f) | 0x40;
unpack25519(x, point);
for (i = 0; i < 16; ++i) {
b[i] = x[i];
d[i] = a[i] = c[i] = 0;
}
a[0] = d[0] = 1;
for (i = 254; i >= 0; --i) {
bit = (clamped[i >> 3] >> (i & 7)) & 1;
swap25519(a, b, bit);
swap25519(c, d, bit);
fadd(e, a, c);
fsub(a, a, c);
fadd(c, b, d);
fsub(b, b, d);
fmul(d, e, e);
fmul(f, a, a);
fmul(a, c, a);
fmul(c, b, e);
fadd(e, a, c);
fsub(a, a, c);
fmul(b, a, a);
fsub(c, d, f);
fmul(a, c, _121665);
fadd(a, a, d);
fmul(c, c, a);
fmul(a, d, f);
fmul(d, b, x);
fmul(b, e, e);
swap25519(a, b, bit);
swap25519(c, d, bit);
}
finverse(c, c);
fmul(a, a, c);
pack25519(out, a);
}
static const uint8_t x25519_basepoint[32] = { 9 };
bool tls_x25519_secret(
uint8_t shared_secret[32],
const uint8_t my_private[32],
const uint8_t their_public[32],
void (*yield_fn)(void *),
void *yield_data)
{
(void)yield_fn;
(void)yield_data;
scalarmult(shared_secret, my_private, their_public);
return true;
}
bool tls_x25519_publickey(
uint8_t public_key[32],
const uint8_t private_key[32],
void (*yield_fn)(void *),
void *yield_data)
{
(void)yield_fn;
(void)yield_data;
scalarmult(public_key, private_key, x25519_basepoint);
return true;
}
The code is an almost exact copy of the second paper linked so I don't know why it isn't working.
EDIT: The code was fine , the test was timing out.
Thank you for any help and good luck for the competition.