Fix for constant time: compute_kP (for ECDH in future)
This commit is contained in:
@@ -1,6 +1,12 @@
|
|||||||
|
2014-01-27 Niibe Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* src/ec_p256.c (get_vk_kP): New.
|
||||||
|
(naf4_257_set, naf4_257_get, compute_naf4_257): Remove.
|
||||||
|
(compute_kP): Change the argument, fixing for constant time.
|
||||||
|
|
||||||
2014-01-24 Niibe Yutaka <gniibe@fsij.org>
|
2014-01-24 Niibe Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
* src/ec_p256.c (get_v_k_i): New.
|
* src/ec_p256.c (get_vk): New.
|
||||||
(compute_kG): Fix for constant time.
|
(compute_kG): Fix for constant time.
|
||||||
(compute_kP): Simplify.
|
(compute_kP): Simplify.
|
||||||
|
|
||||||
|
|||||||
199
src/ec_p256.c
199
src/ec_p256.c
@@ -236,7 +236,7 @@ const bn256 *Gy = precomputed_KG[0].y;
|
|||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
get_vk_i (const bn256 *K, int i)
|
get_vk (const bn256 *K, int i)
|
||||||
{
|
{
|
||||||
uint32_t w0, w1, w2, w3;
|
uint32_t w0, w1, w2, w3;
|
||||||
|
|
||||||
@@ -271,25 +271,24 @@ compute_kG (ac *X, const bn256 *K)
|
|||||||
bn256 K_dash[1];
|
bn256 K_dash[1];
|
||||||
jpc Q[1], tmp[1], *dst;
|
jpc Q[1], tmp[1], *dst;
|
||||||
int i;
|
int i;
|
||||||
int vk_i_prev;
|
int vk;
|
||||||
uint32_t k_is_even = bn256_is_even (K);
|
uint32_t k_is_even = bn256_is_even (K);
|
||||||
|
|
||||||
bn256_sub_uint (K_dash, K, k_is_even);
|
bn256_sub_uint (K_dash, K, k_is_even);
|
||||||
/* It keeps the condition: 1 <= K <= N - 2, and K is odd. */
|
/* It keeps the condition: 1 <= K' <= N - 2, and K' is odd. */
|
||||||
|
|
||||||
/* Fill index. */
|
/* Fill index. */
|
||||||
vk_i_prev = get_vk_i (K_dash, 0);
|
vk = get_vk (K_dash, 0);
|
||||||
index[0] = vk_i_prev - 1;
|
|
||||||
for (i = 1; i < 64; i++)
|
for (i = 1; i < 64; i++)
|
||||||
{
|
{
|
||||||
int vk_i, is_zero;
|
int vk_next, is_zero;
|
||||||
|
|
||||||
vk_i = get_vk_i (K_dash, i);
|
vk_next = get_vk (K_dash, i);
|
||||||
is_zero = (vk_i == 0);
|
is_zero = (vk_next == 0);
|
||||||
index[i-1] = (vk_i_prev - 1) | (is_zero << 7);
|
index[i-1] = (vk - 1) | (is_zero << 7);
|
||||||
vk_i_prev = (is_zero ? vk_i_prev : vk_i);
|
vk = (is_zero ? vk : vk_next);
|
||||||
}
|
}
|
||||||
index[63] = vk_i_prev - 1;
|
index[63] = vk - 1;
|
||||||
|
|
||||||
memset (Q->z, 0, sizeof (bn256)); /* infinity */
|
memset (Q->z, 0, sizeof (bn256)); /* infinity */
|
||||||
for (i = 31; i >= 0; i--)
|
for (i = 31; i >= 0; i--)
|
||||||
@@ -309,85 +308,6 @@ compute_kG (ac *X, const bn256 *K)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define NAF_K_SIGN(k) (k&8)
|
|
||||||
#define NAF_K_INDEX(k) ((k&7)-1)
|
|
||||||
|
|
||||||
static void
|
|
||||||
naf4_257_set (naf4_257 *NAF_K, int i, int ki)
|
|
||||||
{
|
|
||||||
if (ki != 0)
|
|
||||||
{
|
|
||||||
if (ki > 0)
|
|
||||||
ki = (ki+1)/2;
|
|
||||||
else
|
|
||||||
ki = (1-ki)/2 | 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == 256)
|
|
||||||
NAF_K->last_nibble = ki;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
NAF_K->word[i/8] &= ~(0x0f << ((i & 0x07)*4));
|
|
||||||
NAF_K->word[i/8] |= (ki << ((i & 0x07)*4));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
naf4_257_get (const naf4_257 *NAF_K, int i)
|
|
||||||
{
|
|
||||||
int ki;
|
|
||||||
|
|
||||||
if (i == 256)
|
|
||||||
ki = NAF_K->last_nibble;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ki = NAF_K->word[i/8] >> ((i & 0x07)*4);
|
|
||||||
ki &= 0x0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ki;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* convert 256-bit bignum into non-adjacent form (NAF)
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
compute_naf4_257 (naf4_257 *NAF_K, const bn256 *K)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
bn256 K_tmp[1];
|
|
||||||
|
|
||||||
memcpy (K_tmp, K, sizeof (bn256));
|
|
||||||
memset (NAF_K, 0, sizeof (naf4_257));
|
|
||||||
|
|
||||||
while (!bn256_is_zero (K_tmp))
|
|
||||||
{
|
|
||||||
uint32_t carry = 0;
|
|
||||||
|
|
||||||
if (bn256_is_even (K_tmp))
|
|
||||||
naf4_257_set (NAF_K, i, 0);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int ki = (K_tmp->word[0]) & 0x0f;
|
|
||||||
|
|
||||||
if ((ki & 0x08))
|
|
||||||
{
|
|
||||||
carry = bn256_add_uint (K_tmp, K_tmp, 16 - ki);
|
|
||||||
ki = ki - 16;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
K_tmp->word[0] &= 0xfffffff0;
|
|
||||||
|
|
||||||
naf4_257_set (NAF_K, i, ki);
|
|
||||||
}
|
|
||||||
|
|
||||||
bn256_shift (K_tmp, K_tmp, -1);
|
|
||||||
if (carry)
|
|
||||||
K_tmp->word[7] |= 0x80000000;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* check if P is on the curve.
|
* check if P is on the curve.
|
||||||
@@ -415,10 +335,52 @@ point_is_on_the_curve (const ac *P)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* N: order of G
|
||||||
|
*/
|
||||||
|
static const bn256 N[1] = {
|
||||||
|
{{ 0xfc632551, 0xf3b9cac2, 0xa7179e84, 0xbce6faad,
|
||||||
|
0xffffffff, 0xffffffff, 0x00000000, 0xffffffff }}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
get_vk_kP (const bn256 *K, int i)
|
||||||
|
{
|
||||||
|
uint32_t w;
|
||||||
|
uint8_t blk = i/32;
|
||||||
|
uint8_t pos = i%32;
|
||||||
|
uint8_t col = 3*(pos % 11) + (pos >= 11) + (pos >= 22);
|
||||||
|
uint8_t word_index = (blk * 3) + (pos / 11);
|
||||||
|
|
||||||
|
w = ((K->word[word_index] >> col) & 7);
|
||||||
|
if (pos == 10 || pos == 21)
|
||||||
|
{
|
||||||
|
uint8_t mask;
|
||||||
|
uint8_t shift;
|
||||||
|
|
||||||
|
word_index++;
|
||||||
|
if (pos == 10)
|
||||||
|
{
|
||||||
|
shift = 2;
|
||||||
|
mask = 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
shift = 1;
|
||||||
|
mask = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
w |= ((K->word[word_index] << shift) & mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief X = k * P
|
* @brief X = k * P
|
||||||
*
|
*
|
||||||
* @param NAF_K NAF representation of k
|
* @param K scalar k
|
||||||
* @param P P in affine coordiate
|
* @param P P in affine coordiate
|
||||||
*
|
*
|
||||||
* Return -1 on error.
|
* Return -1 on error.
|
||||||
@@ -434,18 +396,27 @@ point_is_on_the_curve (const ac *P)
|
|||||||
* represented by affine coordinate.
|
* represented by affine coordinate.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
compute_kP (ac *X, const naf4_257 *NAF_K, const ac *P)
|
compute_kP (ac *X, const bn256 *K, const ac *P)
|
||||||
{
|
{
|
||||||
|
uint8_t index[86]; /* Lower 2-bit for index absolute value, msb is
|
||||||
|
for sign (encoded as: 0 means 1, 1 means -1). */
|
||||||
|
bn256 K_dash[1];
|
||||||
|
uint32_t k_is_even = bn256_is_even (K);
|
||||||
|
jpc Q[1], tmp[1], *dst;
|
||||||
int i;
|
int i;
|
||||||
jpc Q[1];
|
int vk;
|
||||||
ac P3[1], P5[1], P7[1];
|
ac P3[1], P5[1], P7[1];
|
||||||
const ac *p_Pi[4];
|
const ac *p_Pi[4];
|
||||||
uint8_t index[64]; /* Lower 4-bit for index absolute value, msb is
|
|
||||||
for sign (encoded as: 0 means 1, 1 means -1). */
|
|
||||||
|
|
||||||
if (point_is_on_the_curve (P) < 0)
|
if (point_is_on_the_curve (P) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (bn256_sub (K_dash, K, N) == 0) /* >= N, it's too big. */
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
bn256_sub_uint (K_dash, K, k_is_even);
|
||||||
|
/* It keeps the condition: 1 <= K' <= N - 2, and K' is odd. */
|
||||||
|
|
||||||
p_Pi[0] = P;
|
p_Pi[0] = P;
|
||||||
p_Pi[1] = P3;
|
p_Pi[1] = P3;
|
||||||
p_Pi[2] = P5;
|
p_Pi[2] = P5;
|
||||||
@@ -478,30 +449,33 @@ compute_kP (ac *X, const naf4_257 *NAF_K, const ac *P)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset (Q->z, 0, sizeof (bn256)); /* infinity */
|
/* Fill index. */
|
||||||
for (i = 256; i >= 0; i--)
|
vk = get_vk_kP (K_dash, 0);
|
||||||
|
for (i = 1; i < 85; i++)
|
||||||
{
|
{
|
||||||
int k_i;
|
int vk_next, is_even;
|
||||||
|
|
||||||
jpc_double (Q, Q);
|
vk_next = get_vk_kP (K_dash, i);
|
||||||
|
is_even = ((vk_next & 1) == 0);
|
||||||
k_i = naf4_257_get (NAF_K, i);
|
index[i-1] = (is_even << 7) | ((is_even?7-vk:vk-1) >> 1);
|
||||||
if (k_i)
|
vk = vk_next + is_even;
|
||||||
jpc_add_ac_signed (Q, Q, p_Pi[NAF_K_INDEX(k_i)], NAF_K_SIGN (k_i));
|
|
||||||
}
|
}
|
||||||
|
index[85] = ((vk - 1) >> 1);
|
||||||
|
|
||||||
|
memset (Q->z, 0, sizeof (bn256)); /* infinity */
|
||||||
|
for (i = 85; i >= 0; i--)
|
||||||
|
{
|
||||||
|
jpc_double (Q, Q); jpc_double (Q, Q); jpc_double (Q, Q);
|
||||||
|
jpc_add_ac_signed (Q, Q, p_Pi[index[i]&0x03], index[i] >> 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
dst = k_is_even ? Q : tmp;
|
||||||
|
jpc_add_ac (dst, Q, &precomputed_KG[0]);
|
||||||
|
|
||||||
return jpc_to_ac (X, Q);
|
return jpc_to_ac (X, Q);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* N: order of G
|
|
||||||
*/
|
|
||||||
static const bn256 N[1] = {
|
|
||||||
{{ 0xfc632551, 0xf3b9cac2, 0xa7179e84, 0xbce6faad,
|
|
||||||
0xffffffff, 0xffffffff, 0x00000000, 0xffffffff }}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* MU = 2^512 / N
|
* MU = 2^512 / N
|
||||||
* MU = ( (1 << 256) | MU_lower )
|
* MU = ( (1 << 256) | MU_lower )
|
||||||
@@ -557,4 +531,7 @@ ecdsa (bn256 *r, bn256 *s, const bn256 *z, const bn256 *d)
|
|||||||
mod_reduce (s, tmp, N, MU_lower);
|
mod_reduce (s, tmp, N, MU_lower);
|
||||||
}
|
}
|
||||||
while (bn256_is_zero (s));
|
while (bn256_is_zero (s));
|
||||||
|
|
||||||
|
#undef tmp_k
|
||||||
|
#undef borrow
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,4 @@
|
|||||||
/* Non-adjacent form */
|
int compute_kP (ac *X, const bn256 *K, const ac *P);
|
||||||
typedef struct naf4_257 {
|
|
||||||
uint32_t word[ BN256_WORDS*4 ]; /* Little endian */
|
|
||||||
uint8_t last_nibble; /* most significant nibble */
|
|
||||||
} naf4_257;
|
|
||||||
|
|
||||||
void compute_naf4_257 (naf4_257 *NAF_K, const bn256 *K);
|
|
||||||
int compute_kP (ac *X, const naf4_257 *NAF_K, const ac *P);
|
|
||||||
|
|
||||||
int compute_kG (ac *X, const bn256 *K);
|
int compute_kG (ac *X, const bn256 *K);
|
||||||
void ecdsa (bn256 *r, bn256 *s, const bn256 *z, const bn256 *d);
|
void ecdsa (bn256 *r, bn256 *s, const bn256 *z, const bn256 *d);
|
||||||
|
|||||||
Reference in New Issue
Block a user