You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
118 lines
2.4 KiB
118 lines
2.4 KiB
#include "private/quirks.h"
|
|
|
|
/*
|
|
Ignores top bit of h.
|
|
*/
|
|
|
|
void
|
|
fe25519_frombytes(fe25519 h, const unsigned char *s)
|
|
{
|
|
const uint64_t mask = 0x7ffffffffffffULL;
|
|
uint64_t h0, h1, h2, h3, h4;
|
|
|
|
h0 = (LOAD64_LE(s ) ) & mask;
|
|
h1 = (LOAD64_LE(s + 6) >> 3) & mask;
|
|
h2 = (LOAD64_LE(s + 12) >> 6) & mask;
|
|
h3 = (LOAD64_LE(s + 19) >> 1) & mask;
|
|
h4 = (LOAD64_LE(s + 24) >> 12) & mask;
|
|
|
|
h[0] = h0;
|
|
h[1] = h1;
|
|
h[2] = h2;
|
|
h[3] = h3;
|
|
h[4] = h4;
|
|
}
|
|
|
|
static void
|
|
fe25519_reduce(fe25519 h, const fe25519 f)
|
|
{
|
|
const uint64_t mask = 0x7ffffffffffffULL;
|
|
uint128_t t[5];
|
|
|
|
t[0] = f[0];
|
|
t[1] = f[1];
|
|
t[2] = f[2];
|
|
t[3] = f[3];
|
|
t[4] = f[4];
|
|
|
|
t[1] += t[0] >> 51;
|
|
t[0] &= mask;
|
|
t[2] += t[1] >> 51;
|
|
t[1] &= mask;
|
|
t[3] += t[2] >> 51;
|
|
t[2] &= mask;
|
|
t[4] += t[3] >> 51;
|
|
t[3] &= mask;
|
|
t[0] += 19 * (t[4] >> 51);
|
|
t[4] &= mask;
|
|
|
|
t[1] += t[0] >> 51;
|
|
t[0] &= mask;
|
|
t[2] += t[1] >> 51;
|
|
t[1] &= mask;
|
|
t[3] += t[2] >> 51;
|
|
t[2] &= mask;
|
|
t[4] += t[3] >> 51;
|
|
t[3] &= mask;
|
|
t[0] += 19 * (t[4] >> 51);
|
|
t[4] &= mask;
|
|
|
|
/* now t is between 0 and 2^255-1, properly carried. */
|
|
/* case 1: between 0 and 2^255-20. case 2: between 2^255-19 and 2^255-1. */
|
|
|
|
t[0] += 19ULL;
|
|
|
|
t[1] += t[0] >> 51;
|
|
t[0] &= mask;
|
|
t[2] += t[1] >> 51;
|
|
t[1] &= mask;
|
|
t[3] += t[2] >> 51;
|
|
t[2] &= mask;
|
|
t[4] += t[3] >> 51;
|
|
t[3] &= mask;
|
|
t[0] += 19ULL * (t[4] >> 51);
|
|
t[4] &= mask;
|
|
|
|
/* now between 19 and 2^255-1 in both cases, and offset by 19. */
|
|
|
|
t[0] += 0x8000000000000 - 19ULL;
|
|
t[1] += 0x8000000000000 - 1ULL;
|
|
t[2] += 0x8000000000000 - 1ULL;
|
|
t[3] += 0x8000000000000 - 1ULL;
|
|
t[4] += 0x8000000000000 - 1ULL;
|
|
|
|
/* now between 2^255 and 2^256-20, and offset by 2^255. */
|
|
|
|
t[1] += t[0] >> 51;
|
|
t[0] &= mask;
|
|
t[2] += t[1] >> 51;
|
|
t[1] &= mask;
|
|
t[3] += t[2] >> 51;
|
|
t[2] &= mask;
|
|
t[4] += t[3] >> 51;
|
|
t[3] &= mask;
|
|
t[4] &= mask;
|
|
|
|
h[0] = t[0];
|
|
h[1] = t[1];
|
|
h[2] = t[2];
|
|
h[3] = t[3];
|
|
h[4] = t[4];
|
|
}
|
|
|
|
void
|
|
fe25519_tobytes(unsigned char *s, const fe25519 h)
|
|
{
|
|
fe25519 t;
|
|
uint64_t t0, t1, t2, t3;
|
|
|
|
fe25519_reduce(t, h);
|
|
t0 = t[0] | (t[1] << 51);
|
|
t1 = (t[1] >> 13) | (t[2] << 38);
|
|
t2 = (t[2] >> 26) | (t[3] << 25);
|
|
t3 = (t[3] >> 39) | (t[4] << 12);
|
|
STORE64_LE(s + 0, t0);
|
|
STORE64_LE(s + 8, t1);
|
|
STORE64_LE(s + 16, t2);
|
|
STORE64_LE(s + 24, t3);
|
|
}
|
|
|