This commit is contained in:
NIIBE Yutaka 2013-09-20 17:17:59 +09:00
parent b2fb734d57
commit ee1e1ac851
10 changed files with 131 additions and 27 deletions

View File

@ -1,3 +1,18 @@
2013-09-20 Niibe Yutaka <gniibe@fsij.org>
* src/call-ec_p256.c (ecdsa_compute_public): Handle possible
error (where key_data is the order).
* src/ec_p256.c (on_the_curve): New.
(compute_kG, compute_kP): Handle errors.
* src/jpc.c (jpc_to_ac): Return -1 on error.
(jpc_add_ac_signed): Handle the case where A=inf.
* src/modp256.c (modp256_inv): Handle error case.
* src/bn.c (bn256_cmp): New.
2013-07-19 Niibe Yutaka <gniibe@fsij.org> 2013-07-19 Niibe Yutaka <gniibe@fsij.org>
* src/gnuk.ld.in: Layout change following NeuG. * src/gnuk.ld.in: Layout change following NeuG.

View File

@ -1,7 +1,7 @@
/* /*
* bn.c -- 256-bit (and 512-bit) bignum calculation * bn.c -- 256-bit (and 512-bit) bignum calculation
* *
* Copyright (C) 2011 Free Software Initiative of Japan * Copyright (C) 2011, 2013 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org> * Author: NIIBE Yutaka <gniibe@fsij.org>
* *
* This file is a part of Gnuk, a GnuPG USB Token implementation. * This file is a part of Gnuk, a GnuPG USB Token implementation.
@ -306,6 +306,22 @@ bn256_is_ge (const bn256 *A, const bn256 *B)
return 1; return 1;
} }
int
bn256_cmp (const bn256 *A, const bn256 *B)
{
int i;
for (i = BN256_WORDS - 1; i >= 0; i--)
if (A->words[i] > B->words[i])
return 1;
else if (A->words[i] < B->words[i])
return -1;
return 0;
}
void void
bn256_random (bn256 *X) bn256_random (bn256 *X)
{ {

View File

@ -19,4 +19,5 @@ uint32_t bn256_shift (bn256 *X, const bn256 *A, int shift);
int bn256_is_zero (const bn256 *X); int bn256_is_zero (const bn256 *X);
int bn256_is_even (const bn256 *X); int bn256_is_even (const bn256 *X);
int bn256_is_ge (const bn256 *A, const bn256 *B); int bn256_is_ge (const bn256 *A, const bn256 *B);
int bn256_cmp (const bn256 *A, const bn256 *B);
void bn256_random (bn256 *X); void bn256_random (bn256 *X);

View File

@ -77,7 +77,12 @@ ecdsa_compute_public (const uint8_t *key_data)
p = (uint8_t *)k; p = (uint8_t *)k;
for (i = 0; i < ECDSA_BYTE_SIZE; i++) for (i = 0; i < ECDSA_BYTE_SIZE; i++)
p[ECDSA_BYTE_SIZE - i - 1] = key_data[i]; p[ECDSA_BYTE_SIZE - i - 1] = key_data[i];
compute_kG (q, k); if (compute_kG (q, k) < 0)
{
free (p0);
return NULL;
}
p = p0; p = p0;
p1 = (uint8_t *)q->x; p1 = (uint8_t *)q->x;
for (i = 0; i < ECDSA_BYTE_SIZE; i++) for (i = 0; i < ECDSA_BYTE_SIZE; i++)

View File

@ -1,7 +1,7 @@
/* /*
* ec_p256.c - Elliptic curve over GF(p256) * ec_p256.c - Elliptic curve over GF(p256)
* *
* Copyright (C) 2011 Free Software Initiative of Japan * Copyright (C) 2011, 2013 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org> * Author: NIIBE Yutaka <gniibe@fsij.org>
* *
* This file is a part of Gnuk, a GnuPG USB Token implementation. * This file is a part of Gnuk, a GnuPG USB Token implementation.
@ -227,8 +227,11 @@ static const ac precomputed_2E_KG[15] = {
* @brief X = k * G * @brief X = k * G
* *
* @param K scalar k * @param K scalar k
*
* Return -1 on error.
* Return 0 on success.
*/ */
void int
compute_kG (ac *X, const bn256 *K) compute_kG (ac *X, const bn256 *K)
{ {
int i; int i;
@ -281,7 +284,7 @@ compute_kG (ac *X, const bn256 *K)
} }
} }
jpc_to_ac (X, Q); return jpc_to_ac (X, Q);
} }
@ -367,13 +370,30 @@ compute_naf4_257 (naf4_257 *NAF_K, const bn256 *K)
} }
} }
/**
* check if P is on the curve.
*
* Return -1 on error.
* Return 0 on success.
*/
static int
point_is_on_the_curve (const ac *P)
{
/* y^2 = x^3 + a*x + b */
/* XXX: Not yet */
return 0;
}
/** /**
* @brief X = k * P * @brief X = k * P
* *
* @param NAF_K NAF representation of k * @param NAF_K NAF representation of k
* @param P P in affin coordiate * @param P P in affin coordiate
*
* Return -1 on error.
* Return 0 on success.
*/ */
void int
compute_kP (ac *X, const naf4_257 *NAF_K, const ac *P) compute_kP (ac *X, const naf4_257 *NAF_K, const ac *P)
{ {
int i; int i;
@ -381,6 +401,10 @@ compute_kP (ac *X, const naf4_257 *NAF_K, const ac *P)
jpc Q[1]; jpc Q[1];
ac P3[1], P5[1], P7[1]; ac P3[1], P5[1], P7[1];
const ac *p_Pi[4]; const ac *p_Pi[4];
int Pi_is_infinite[4] = { 0, 0, 0, 0 };
if (point_is_on_the_curve (P) < 0)
return -1;
p_Pi[0] = P; p_Pi[0] = P;
p_Pi[1] = P3; p_Pi[1] = P3;
@ -397,18 +421,28 @@ compute_kP (ac *X, const naf4_257 *NAF_K, const ac *P)
jpc_double (Q, Q); jpc_double (Q, Q);
jpc_add_ac (Q1, Q, P); jpc_add_ac (Q1, Q, P);
jpc_to_ac (P3, Q1); if (jpc_to_ac (P3, Q1) < 0)
Pi_is_infinite[1] = 1;
jpc_double (Q, Q); jpc_double (Q, Q);
jpc_add_ac (Q1, Q, P); jpc_add_ac (Q1, Q, P);
jpc_to_ac (P5, Q1); if (jpc_to_ac (P5, Q1) < 0)
Pi_is_infinite[2] = 1;
if (Pi_is_infinite[1] == 0)
{
memcpy (Q->x, P3->x, sizeof (bn256)); memcpy (Q->x, P3->x, sizeof (bn256));
memcpy (Q->y, P3->y, sizeof (bn256)); memcpy (Q->y, P3->y, sizeof (bn256));
memset (Q->z, 0, sizeof (bn256)); memset (Q->z, 0, sizeof (bn256));
Q->z->words[0] = 1; Q->z->words[0] = 1;
jpc_double (Q, Q); jpc_double (Q, Q);
jpc_add_ac (Q1, Q, P); jpc_add_ac (Q1, Q, P);
jpc_to_ac (P7, Q1); if (jpc_to_ac (P7, Q1) < 0)
Pi_is_infinite[3] = 1;
}
else
{ /* P7 <= P4 */
if (jpc_to_ac (P7, Q) < 0)
Pi_is_infinite[3] = 1;
}
} }
for (i = 256; i >= 0; i--) for (i = 256; i >= 0; i--)
@ -419,7 +453,7 @@ compute_kP (ac *X, const naf4_257 *NAF_K, const ac *P)
jpc_double (Q, Q); jpc_double (Q, Q);
k_i = naf4_257_get (NAF_K, i); k_i = naf4_257_get (NAF_K, i);
if (k_i) if (k_i && Pi_is_infinite[NAF_K_INDEX(k_i)] == 0)
{ {
if (q_is_infinite) if (q_is_infinite)
{ {
@ -437,7 +471,7 @@ compute_kP (ac *X, const naf4_257 *NAF_K, const ac *P)
} }
} }
jpc_to_ac (X, Q); return jpc_to_ac (X, Q);
} }

View File

@ -5,8 +5,8 @@ typedef struct naf4_257 {
} naf4_257; } naf4_257;
void compute_naf4_257 (naf4_257 *NAF_K, const bn256 *K); void compute_naf4_257 (naf4_257 *NAF_K, const bn256 *K);
void compute_kP (ac *X, const naf4_257 *NAF_K, const ac *P); int compute_kP (ac *X, const naf4_257 *NAF_K, const ac *P);
void 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);

View File

@ -20,4 +20,4 @@ typedef struct
void jpc_double (jpc *X, const jpc *A); void jpc_double (jpc *X, const jpc *A);
void jpc_add_ac (jpc *X, const jpc *A, const ac *B); void jpc_add_ac (jpc *X, const jpc *A, const ac *B);
void jpc_add_ac_signed (jpc *X, const jpc *A, const ac *B, int minus); void jpc_add_ac_signed (jpc *X, const jpc *A, const ac *B, int minus);
void jpc_to_ac (ac *X, const jpc *A); int jpc_to_ac (ac *X, const jpc *A);

View File

@ -1,7 +1,7 @@
/* /*
* jpc.c -- arithmetic on Jacobian projective coordinates and Affin coordinates * jpc.c -- arithmetic on Jacobian projective coordinates and Affin coordinates
* *
* Copyright (C) 2011 Free Software Initiative of Japan * Copyright (C) 2011, 2013 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org> * Author: NIIBE Yutaka <gniibe@fsij.org>
* *
* This file is a part of Gnuk, a GnuPG USB Token implementation. * This file is a part of Gnuk, a GnuPG USB Token implementation.
@ -88,6 +88,18 @@ jpc_add_ac_signed (jpc *X, const jpc *A, const ac *B, int minus)
#define y3_tmp c #define y3_tmp c
#define y1_c_cube a #define y1_c_cube a
if (A->z == 0) /* A is infinite */
{
memcpy (X->x, B->x, sizeof (bn256));
if (minus)
bn256_sub (X->y, P256, B->y);
else
memcpy (X->y, B->y, sizeof (bn256));
memset (X->z, 0, sizeof (bn256));
X->z->words[0] = 1;
return;
}
modp256_sqr (a, A->z); modp256_sqr (a, A->z);
memcpy (b, a, sizeof (bn256)); memcpy (b, a, sizeof (bn256));
modp256_mul (a, a, B->x); modp256_mul (a, a, B->x);
@ -101,6 +113,13 @@ jpc_add_ac_signed (jpc *X, const jpc *A, const ac *B, int minus)
else else
modp256_mul (b, b, B->y); modp256_mul (b, b, B->y);
if (bn256_cmp (A->x, a) == 0)
if (bn256_cmp (A->y, b) == 0)
{
jpc_double (X, A);
return;
}
modp256_sub (c, a, A->x); modp256_sub (c, a, A->x);
modp256_sub (d, b, A->y); modp256_sub (d, b, A->y);
@ -141,16 +160,22 @@ jpc_add_ac (jpc *X, const jpc *A, const ac *B)
* *
* @param X Destination AC * @param X Destination AC
* @param A JPC * @param A JPC
*
* Return -1 on error (infinite).
* Return 0 on success.
*/ */
void int
jpc_to_ac (ac *X, const jpc *A) jpc_to_ac (ac *X, const jpc *A)
{ {
bn256 z_inv[1], z_inv_sqr[1]; bn256 z_inv[1], z_inv_sqr[1];
modp256_inv (z_inv, A->z); if (modp256_inv (z_inv, A->z) < 0)
return -1;
modp256_sqr (z_inv_sqr, z_inv); modp256_sqr (z_inv_sqr, z_inv);
modp256_mul (z_inv, z_inv, z_inv_sqr); modp256_mul (z_inv, z_inv, z_inv_sqr);
modp256_mul (X->x, A->x, z_inv_sqr); modp256_mul (X->x, A->x, z_inv_sqr);
modp256_mul (X->y, A->y, z_inv); modp256_mul (X->y, A->y, z_inv);
return 0;
} }

View File

@ -1,7 +1,7 @@
/* /*
* modp256.c -- modulo P256 arithmetic * modp256.c -- modulo P256 arithmetic
* *
* Copyright (C) 2011 Free Software Initiative of Japan * Copyright (C) 2011, 2013 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org> * Author: NIIBE Yutaka <gniibe@fsij.org>
* *
* This file is a part of Gnuk, a GnuPG USB Token implementation. * This file is a part of Gnuk, a GnuPG USB Token implementation.
@ -211,13 +211,19 @@ modp256_sqr (bn256 *X, const bn256 *A)
/** /**
* @brief C = (1 / a) mod p256 * @brief C = (1 / a) mod p256
*
* Return -1 on error.
* Return 0 on success.
*/ */
void int
modp256_inv (bn256 *C, const bn256 *a) modp256_inv (bn256 *C, const bn256 *a)
{ {
bn256 u[1], v[1]; bn256 u[1], v[1];
bn256 A[1] = { { { 1, 0, 0, 0, 0, 0, 0, 0 } } }; bn256 A[1] = { { { 1, 0, 0, 0, 0, 0, 0, 0 } } };
if (bn256_is_zero (a))
return -1;
memset (C, 0, sizeof (bn256)); memset (C, 0, sizeof (bn256));
memcpy (u, a, sizeof (bn256)); memcpy (u, a, sizeof (bn256));
memcpy (v, P256, sizeof (bn256)); memcpy (v, P256, sizeof (bn256));
@ -265,6 +271,8 @@ modp256_inv (bn256 *C, const bn256 *a)
modp256_sub (C, C, A); modp256_sub (C, C, A);
} }
} }
return 0;
} }
/** /**

View File

@ -6,5 +6,5 @@ void modp256_sub (bn256 *X, const bn256 *A, const bn256 *B);
void modp256_reduce (bn256 *X, const bn512 *A); void modp256_reduce (bn256 *X, const bn512 *A);
void modp256_mul (bn256 *X, const bn256 *A, const bn256 *B); void modp256_mul (bn256 *X, const bn256 *A, const bn256 *B);
void modp256_sqr (bn256 *X, const bn256 *A); void modp256_sqr (bn256 *X, const bn256 *A);
void modp256_inv (bn256 *C, const bn256 *a);
void modp256_shift (bn256 *X, const bn256 *A, int shift); void modp256_shift (bn256 *X, const bn256 *A, int shift);
int modp256_inv (bn256 *C, const bn256 *a);