mirror of
https://github.com/oxen-io/lokinet.git
synced 2024-11-02 03:40:12 +00:00
189 lines
5.8 KiB
C
189 lines
5.8 KiB
C
|
|
||
|
#include <stddef.h>
|
||
|
#include <stdint.h>
|
||
|
|
||
|
#include "../scalarmult_curve25519.h"
|
||
|
#include <sodium/export.h>
|
||
|
#include <sodium/private/ed25519_ref10.h>
|
||
|
#include <sodium/utils.h>
|
||
|
#include "x25519_ref10.h"
|
||
|
|
||
|
/*
|
||
|
* Reject small order points early to mitigate the implications of
|
||
|
* unexpected optimizations that would affect the ref10 code.
|
||
|
* See https://eprint.iacr.org/2017/806.pdf for reference.
|
||
|
*/
|
||
|
static int
|
||
|
has_small_order(const unsigned char s[32])
|
||
|
{
|
||
|
CRYPTO_ALIGN(16)
|
||
|
static const unsigned char blacklist[][32] = {
|
||
|
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||
|
{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||
|
{0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 0x16, 0x56, 0xe3,
|
||
|
0xfa, 0xf1, 0x9f, 0xc4, 0x6a, 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32,
|
||
|
0xb1, 0xfd, 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x00},
|
||
|
{0x5f, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24, 0xb1, 0xd0, 0xb1,
|
||
|
0x55, 0x9c, 0x83, 0xef, 0x5b, 0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c,
|
||
|
0x8e, 0x86, 0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0x57},
|
||
|
{0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f},
|
||
|
{0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f},
|
||
|
{0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f},
|
||
|
{0xcd, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 0x16, 0x56, 0xe3,
|
||
|
0xfa, 0xf1, 0x9f, 0xc4, 0x6a, 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32,
|
||
|
0xb1, 0xfd, 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x80},
|
||
|
{0x4c, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24, 0xb1, 0xd0, 0xb1,
|
||
|
0x55, 0x9c, 0x83, 0xef, 0x5b, 0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c,
|
||
|
0x8e, 0x86, 0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0xd7},
|
||
|
{0xd9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
|
||
|
{0xda, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
|
||
|
{0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
|
||
|
unsigned char c[12] = {0};
|
||
|
unsigned int k;
|
||
|
size_t i, j;
|
||
|
|
||
|
COMPILER_ASSERT(12 == sizeof blacklist / sizeof blacklist[0]);
|
||
|
for(j = 0; j < 32; j++)
|
||
|
{
|
||
|
for(i = 0; i < sizeof blacklist / sizeof blacklist[0]; i++)
|
||
|
{
|
||
|
c[i] |= s[j] ^ blacklist[i][j];
|
||
|
}
|
||
|
}
|
||
|
k = 0;
|
||
|
for(i = 0; i < sizeof blacklist / sizeof blacklist[0]; i++)
|
||
|
{
|
||
|
k |= (c[i] - 1);
|
||
|
}
|
||
|
return (int)((k >> 8) & 1);
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
crypto_scalarmult_curve25519_ref10(unsigned char *q, const unsigned char *n,
|
||
|
const unsigned char *p)
|
||
|
{
|
||
|
unsigned char *t = q;
|
||
|
unsigned int i;
|
||
|
fe25519 x1;
|
||
|
fe25519 x2;
|
||
|
fe25519 z2;
|
||
|
fe25519 x3;
|
||
|
fe25519 z3;
|
||
|
fe25519 tmp0;
|
||
|
fe25519 tmp1;
|
||
|
int pos;
|
||
|
unsigned int swap;
|
||
|
unsigned int b;
|
||
|
|
||
|
if(has_small_order(p))
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
for(i = 0; i < 32; i++)
|
||
|
{
|
||
|
t[i] = n[i];
|
||
|
}
|
||
|
t[0] &= 248;
|
||
|
t[31] &= 127;
|
||
|
t[31] |= 64;
|
||
|
fe25519_frombytes(x1, p);
|
||
|
fe25519_1(x2);
|
||
|
fe25519_0(z2);
|
||
|
fe25519_copy(x3, x1);
|
||
|
fe25519_1(z3);
|
||
|
|
||
|
swap = 0;
|
||
|
for(pos = 254; pos >= 0; --pos)
|
||
|
{
|
||
|
b = t[pos / 8] >> (pos & 7);
|
||
|
b &= 1;
|
||
|
swap ^= b;
|
||
|
fe25519_cswap(x2, x3, swap);
|
||
|
fe25519_cswap(z2, z3, swap);
|
||
|
swap = b;
|
||
|
fe25519_sub(tmp0, x3, z3);
|
||
|
fe25519_sub(tmp1, x2, z2);
|
||
|
fe25519_add(x2, x2, z2);
|
||
|
fe25519_add(z2, x3, z3);
|
||
|
fe25519_mul(z3, tmp0, x2);
|
||
|
fe25519_mul(z2, z2, tmp1);
|
||
|
fe25519_sq(tmp0, tmp1);
|
||
|
fe25519_sq(tmp1, x2);
|
||
|
fe25519_add(x3, z3, z2);
|
||
|
fe25519_sub(z2, z3, z2);
|
||
|
fe25519_mul(x2, tmp1, tmp0);
|
||
|
fe25519_sub(tmp1, tmp1, tmp0);
|
||
|
fe25519_sq(z2, z2);
|
||
|
fe25519_scalar_product(z3, tmp1, 121666);
|
||
|
fe25519_sq(x3, x3);
|
||
|
fe25519_add(tmp0, tmp0, z3);
|
||
|
fe25519_mul(z3, x1, z2);
|
||
|
fe25519_mul(z2, tmp1, tmp0);
|
||
|
}
|
||
|
fe25519_cswap(x2, x3, swap);
|
||
|
fe25519_cswap(z2, z3, swap);
|
||
|
|
||
|
fe25519_invert(z2, z2);
|
||
|
fe25519_mul(x2, x2, z2);
|
||
|
fe25519_tobytes(q, x2);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
edwards_to_montgomery(fe25519 montgomeryX, const fe25519 edwardsY,
|
||
|
const fe25519 edwardsZ)
|
||
|
{
|
||
|
fe25519 tempX;
|
||
|
fe25519 tempZ;
|
||
|
|
||
|
fe25519_add(tempX, edwardsZ, edwardsY);
|
||
|
fe25519_sub(tempZ, edwardsZ, edwardsY);
|
||
|
fe25519_invert(tempZ, tempZ);
|
||
|
fe25519_mul(montgomeryX, tempX, tempZ);
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
crypto_scalarmult_curve25519_ref10_base(unsigned char *q,
|
||
|
const unsigned char *n)
|
||
|
{
|
||
|
unsigned char *t = q;
|
||
|
ge25519_p3 A;
|
||
|
fe25519 pk;
|
||
|
unsigned int i;
|
||
|
|
||
|
for(i = 0; i < 32; i++)
|
||
|
{
|
||
|
t[i] = n[i];
|
||
|
}
|
||
|
t[0] &= 248;
|
||
|
t[31] &= 127;
|
||
|
t[31] |= 64;
|
||
|
ge25519_scalarmult_base(&A, t);
|
||
|
edwards_to_montgomery(pk, A.Y, A.Z);
|
||
|
fe25519_tobytes(q, pk);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
struct crypto_scalarmult_curve25519_implementation
|
||
|
crypto_scalarmult_curve25519_ref10_implementation = {
|
||
|
SODIUM_C99(.mult =) crypto_scalarmult_curve25519_ref10,
|
||
|
SODIUM_C99(.mult_base =) crypto_scalarmult_curve25519_ref10_base};
|