add ec_p256k1
This commit is contained in:
324
src/ec_p256r1.c
324
src/ec_p256r1.c
@@ -1,7 +1,7 @@
|
||||
/* -*- coding: utf-8 -*-
|
||||
* ec_p256r1.c - Elliptic curve over GF(p256r1)
|
||||
*
|
||||
* Copyright (C) 2011, 2013, 2014 Free Software Initiative of Japan
|
||||
* Copyright (C) 2014 Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -21,23 +21,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* References:
|
||||
*
|
||||
* [1] Suite B Implementer's Guide to FIPS 186-3 (ECDSA), February 3, 2010.
|
||||
*
|
||||
* [2] Michael Brown, Darrel Hankerson, Julio López, and Alfred Menezes,
|
||||
* Software Implementation of the NIST Elliptic Curves Over Prime Fields,
|
||||
* Proceedings of the 2001 Conference on Topics in Cryptology: The
|
||||
* Cryptographer's Track at RSA
|
||||
* Pages 250-265, Springer-Verlag London, UK, 2001
|
||||
* ISBN:3-540-41898-9
|
||||
*
|
||||
* [3] Mustapha Hedabou, Pierre Pinel, Lucien Bénéteau,
|
||||
* A comb method to render ECC resistant against Side Channel Attacks,
|
||||
* 2004
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "bn.h"
|
||||
@@ -46,8 +29,10 @@
|
||||
#include "mod.h"
|
||||
#include "ec_p256r1.h"
|
||||
|
||||
#define FIELD p256r1
|
||||
|
||||
/*
|
||||
* a = -3 mod p256
|
||||
* a = -3 mod p256r1
|
||||
*/
|
||||
static const bn256 coefficient_a[1] = {
|
||||
{{ 0xfffffffc, 0xffffffff, 0xffffffff, 0x00000000,
|
||||
@@ -60,13 +45,6 @@ static const bn256 coefficient_b[1] = {
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* w = 4
|
||||
* m = 256
|
||||
* d = 64
|
||||
* e = 32
|
||||
*/
|
||||
|
||||
static const ac precomputed_KG[15] = {
|
||||
{
|
||||
{{{ 0xd898c296, 0xf4a13945, 0x2deb33a0, 0x77037d81,
|
||||
@@ -225,115 +203,6 @@ static const ac precomputed_2E_KG[15] = {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#if TEST
|
||||
/*
|
||||
* Generator of Elliptic curve over GF(p256)
|
||||
*/
|
||||
const ac *G = &precomputed_KG[0];
|
||||
#endif
|
||||
|
||||
|
||||
static int
|
||||
get_vk (const bn256 *K, int i)
|
||||
{
|
||||
uint32_t w0, w1, w2, w3;
|
||||
|
||||
if (i < 32)
|
||||
{
|
||||
w3 = K->word[6]; w2 = K->word[4]; w1 = K->word[2]; w0 = K->word[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
w3 = K->word[7]; w2 = K->word[5]; w1 = K->word[3]; w0 = K->word[1];
|
||||
i -= 32;
|
||||
}
|
||||
|
||||
w3 >>= i; w2 >>= i; w1 >>= i; w0 >>= i;
|
||||
return ((w3 & 1) << 3) | ((w2 & 1) << 2) | ((w1 & 1) << 1) | (w0 & 1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief X = k * G
|
||||
*
|
||||
* @param K scalar k
|
||||
*
|
||||
* Return -1 on error.
|
||||
* Return 0 on success.
|
||||
*/
|
||||
int
|
||||
compute_kG_p256r1 (ac *X, const bn256 *K)
|
||||
{
|
||||
uint8_t index[64]; /* Lower 4-bit for index absolute value, msb is
|
||||
for sign (encoded as: 0 means 1, 1 means -1). */
|
||||
bn256 K_dash[1];
|
||||
jpc Q[1], tmp[1], *dst;
|
||||
int i;
|
||||
int vk;
|
||||
uint32_t k_is_even = bn256_is_even (K);
|
||||
|
||||
bn256_sub_uint (K_dash, K, k_is_even);
|
||||
/* It keeps the condition: 1 <= K' <= N - 2, and K' is odd. */
|
||||
|
||||
/* Fill index. */
|
||||
vk = get_vk (K_dash, 0);
|
||||
for (i = 1; i < 64; i++)
|
||||
{
|
||||
int vk_next, is_zero;
|
||||
|
||||
vk_next = get_vk (K_dash, i);
|
||||
is_zero = (vk_next == 0);
|
||||
index[i-1] = (vk - 1) | (is_zero << 7);
|
||||
vk = (is_zero ? vk : vk_next);
|
||||
}
|
||||
index[63] = vk - 1;
|
||||
|
||||
memset (Q->z, 0, sizeof (bn256)); /* infinity */
|
||||
for (i = 31; i >= 0; i--)
|
||||
{
|
||||
jpc_double_p256r1 (Q, Q);
|
||||
|
||||
jpc_add_ac_signed_p256r1 (Q, Q, &precomputed_KG[index[i]&0x0f],
|
||||
index[i] >> 7);
|
||||
jpc_add_ac_signed_p256r1 (Q, Q, &precomputed_2E_KG[index[i+32]&0x0f],
|
||||
index[i+32] >> 7);
|
||||
}
|
||||
|
||||
dst = k_is_even ? Q : tmp;
|
||||
jpc_add_ac_p256r1 (dst, Q, &precomputed_KG[0]);
|
||||
|
||||
return jpc_to_ac_p256r1 (X, Q);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
bn256 s[1], t[1];
|
||||
|
||||
/* Elliptic curve: y^2 = x^3 + a*x + b */
|
||||
modp256r1_sqr (s, P->x);
|
||||
modp256r1_mul (s, s, P->x);
|
||||
|
||||
modp256r1_mul (t, coefficient_a, P->x);
|
||||
modp256r1_add (s, s, t);
|
||||
modp256r1_add (s, s, coefficient_b);
|
||||
|
||||
modp256r1_sqr (t, P->y);
|
||||
if (bn256_cmp (s, t) == 0)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* N: order of G
|
||||
*/
|
||||
@@ -342,141 +211,6 @@ static const bn256 N[1] = {
|
||||
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 (word_index < 7 && (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
|
||||
*
|
||||
* @param K scalar k
|
||||
* @param P P in affine coordiate
|
||||
*
|
||||
* Return -1 on error.
|
||||
* Return 0 on success.
|
||||
*
|
||||
* For the curve (cofactor is 1 and n is prime), possible error cases are:
|
||||
*
|
||||
* P is not on the curve.
|
||||
* P = G, k = n
|
||||
* Something wrong in the code.
|
||||
*
|
||||
* Mathmatically, k=1 and P=O is another possible case, but O cannot be
|
||||
* represented by affine coordinate.
|
||||
*/
|
||||
int
|
||||
compute_kP_p256r1 (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 vk;
|
||||
ac P3[1], P5[1], P7[1];
|
||||
const ac *p_Pi[4];
|
||||
|
||||
if (point_is_on_the_curve (P) < 0)
|
||||
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[1] = P3;
|
||||
p_Pi[2] = P5;
|
||||
p_Pi[3] = P7;
|
||||
|
||||
{
|
||||
jpc Q1[1];
|
||||
|
||||
memcpy (Q->x, P->x, sizeof (bn256));
|
||||
memcpy (Q->y, P->y, sizeof (bn256));
|
||||
memset (Q->z, 0, sizeof (bn256));
|
||||
Q->z->word[0] = 1;
|
||||
|
||||
jpc_double_p256r1 (Q, Q);
|
||||
jpc_add_ac_p256r1 (Q1, Q, P);
|
||||
if (jpc_to_ac_p256r1 (P3, Q1) < 0) /* Never occurs, except coding errors. */
|
||||
return -1;
|
||||
jpc_double_p256r1 (Q, Q);
|
||||
jpc_add_ac_p256r1 (Q1, Q, P);
|
||||
if (jpc_to_ac_p256r1 (P5, Q1) < 0) /* Never occurs, except coding errors. */
|
||||
return -1;
|
||||
|
||||
memcpy (Q->x, P3->x, sizeof (bn256));
|
||||
memcpy (Q->y, P3->y, sizeof (bn256));
|
||||
memset (Q->z, 0, sizeof (bn256));
|
||||
Q->z->word[0] = 1;
|
||||
jpc_double_p256r1 (Q, Q);
|
||||
jpc_add_ac_p256r1 (Q1, Q, P);
|
||||
if (jpc_to_ac_p256r1 (P7, Q1) < 0) /* Never occurs, except coding errors. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Fill index. */
|
||||
vk = get_vk_kP (K_dash, 0);
|
||||
for (i = 1; i < 86; i++)
|
||||
{
|
||||
int vk_next, is_even;
|
||||
|
||||
vk_next = get_vk_kP (K_dash, i);
|
||||
is_even = ((vk_next & 1) == 0);
|
||||
index[i-1] = (is_even << 7) | ((is_even?7-vk:vk-1) >> 1);
|
||||
vk = vk_next + is_even;
|
||||
}
|
||||
index[85] = ((vk - 1) >> 1);
|
||||
|
||||
memset (Q->z, 0, sizeof (bn256)); /* infinity */
|
||||
for (i = 85; i >= 0; i--)
|
||||
{
|
||||
jpc_double_p256r1 (Q, Q);
|
||||
jpc_double_p256r1 (Q, Q);
|
||||
jpc_double_p256r1 (Q, Q);
|
||||
jpc_add_ac_signed_p256r1 (Q, Q, p_Pi[index[i]&0x03], index[i] >> 7);
|
||||
}
|
||||
|
||||
dst = k_is_even ? Q : tmp;
|
||||
jpc_add_ac_p256r1 (dst, Q, &precomputed_KG[0]);
|
||||
|
||||
return jpc_to_ac_p256r1 (X, Q);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* MU = 2^512 / N
|
||||
* MU = ( (1 << 256) | MU_lower )
|
||||
@@ -487,52 +221,4 @@ static const bn256 MU_lower[1] = {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Compute signature (r,s) of hash string z with secret key d
|
||||
*/
|
||||
void
|
||||
ecdsa_p256r1 (bn256 *r, bn256 *s, const bn256 *z, const bn256 *d)
|
||||
{
|
||||
bn256 k[1];
|
||||
ac KG[1];
|
||||
bn512 tmp[1];
|
||||
bn256 k_inv[1];
|
||||
uint32_t carry;
|
||||
#define borrow carry
|
||||
#define tmp_k k_inv
|
||||
|
||||
do
|
||||
{
|
||||
do
|
||||
{
|
||||
bn256_random (k);
|
||||
if (bn256_add_uint (k, k, 1))
|
||||
continue;
|
||||
if (bn256_sub (tmp_k, k, N) == 0) /* >= N, it's too big. */
|
||||
continue;
|
||||
/* 1 <= k <= N - 1 */
|
||||
compute_kG_p256r1 (KG, k);
|
||||
borrow = bn256_sub (r, KG->x, N);
|
||||
if (borrow)
|
||||
memcpy (r, KG->x, sizeof (bn256));
|
||||
else
|
||||
memcpy (KG->x, r, sizeof (bn256));
|
||||
}
|
||||
while (bn256_is_zero (r));
|
||||
|
||||
mod_inv (k_inv, k, N);
|
||||
bn256_mul (tmp, r, d);
|
||||
mod_reduce (s, tmp, N, MU_lower);
|
||||
carry = bn256_add (s, s, z);
|
||||
if (carry)
|
||||
bn256_sub (s, s, N);
|
||||
else
|
||||
bn256_sub ((bn256 *)tmp, s, N);
|
||||
bn256_mul (tmp, s, k_inv);
|
||||
mod_reduce (s, tmp, N, MU_lower);
|
||||
}
|
||||
while (bn256_is_zero (s));
|
||||
|
||||
#undef tmp_k
|
||||
#undef borrow
|
||||
}
|
||||
#include "ecc.c"
|
||||
|
||||
Reference in New Issue
Block a user