update and add ecc-cdh.c

This commit is contained in:
NIIBE Yutaka
2013-02-17 22:20:30 +09:00
parent cb1a4c09b5
commit d70951e941
5 changed files with 141 additions and 16 deletions

View File

@@ -1,5 +1,5 @@
/*
* 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
* Author: NIIBE Yutaka <gniibe@fsij.org>

View File

@@ -1,5 +1,37 @@
/*
* ec_p256.c - Elliptic curve over GF(p256)
*
* Copyright (C) 2011 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
*
* Gnuk is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Gnuk is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* 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
*/
#include <stdint.h>
@@ -10,7 +42,7 @@
#include "mod.h"
#include "ec_p256.h"
#if 0
#if TEST
/*
* Generator of Elliptic curve over GF(p256)
*/
@@ -25,6 +57,7 @@ bn256 Gy[1] = {
};
#endif
/*
* w = 4
* m = 256
@@ -190,18 +223,23 @@ static const ac precomputed_2E_KG[15] = {
}
};
/**
* @brief X = k * G
*
* @param K scalar k
*/
void
compute_kG (ac *X, const bn256 *K)
{
int i;
int q_infinite = 1;
int q_is_infinite = 1;
jpc Q[1];
for (i = 31; i >= 0; i--)
{
int k_i, k_i_e;
if (!q_infinite)
if (!q_is_infinite)
jpc_double (Q, Q);
k_i = (((K->words[6] >> i) & 1) << 3)
@@ -215,7 +253,7 @@ compute_kG (ac *X, const bn256 *K)
if (k_i)
{
if (q_infinite)
if (q_is_infinite)
{
memcpy (Q->x, (&precomputed_KG[k_i - 1])->x, sizeof (bn256));
memcpy (Q->y, (&precomputed_KG[k_i - 1])->y, sizeof (bn256));
@@ -223,20 +261,20 @@ compute_kG (ac *X, const bn256 *K)
Q->z->words[1] = Q->z->words[2] = Q->z->words[3]
= Q->z->words[4] = Q->z->words[5] = Q->z->words[6]
= Q->z->words[7] = 0;
q_infinite = 0;
q_is_infinite = 0;
}
else
jpc_add_ac (Q, Q, &precomputed_KG[k_i - 1]);
}
if (k_i_e)
{
if (q_infinite)
if (q_is_infinite)
{
memcpy (Q->x, (&precomputed_2E_KG[k_i_e - 1])->x, sizeof (bn256));
memcpy (Q->y, (&precomputed_2E_KG[k_i_e - 1])->y, sizeof (bn256));
memset (Q->z, 0, sizeof (bn256));
Q->z->words[0] = 1;
q_infinite = 0;
q_is_infinite = 0;
}
else
jpc_add_ac (Q, Q, &precomputed_2E_KG[k_i_e - 1]);
@@ -250,7 +288,7 @@ compute_kG (ac *X, const bn256 *K)
#define NAF_K_SIGN(k) (k&8)
#define NAF_K_INDEX(k) ((k&7)-1)
void
static void
naf4_257_set (naf4_257 *NAF_K, int i, int ki)
{
if (ki != 0)
@@ -270,7 +308,7 @@ naf4_257_set (naf4_257 *NAF_K, int i, int ki)
}
}
int
static int
naf4_257_get (const naf4_257 *NAF_K, int i)
{
int ki;
@@ -286,6 +324,10 @@ naf4_257_get (const naf4_257 *NAF_K, int i)
return ki;
}
/*
* convert 256-bit bignum into non-adjacent form (NAF)
*/
void
compute_naf4_257 (naf4_257 *NAF_K, const bn256 *K)
{
@@ -325,11 +367,17 @@ compute_naf4_257 (naf4_257 *NAF_K, const bn256 *K)
}
}
/**
* @brief X = k * P
*
* @param NAF_K NAF representation of k
* @param P P in affin coordiate
*/
void
compute_kP (ac *X, const naf4_257 *NAF_K, const ac *P)
{
int i;
int q_infinite = 1;
int q_is_infinite = 1;
jpc Q[1];
ac P3[1], P5[1], P7[1];
const ac *p_Pi[4];
@@ -367,13 +415,13 @@ compute_kP (ac *X, const naf4_257 *NAF_K, const ac *P)
{
int k_i;
if (!q_infinite)
if (!q_is_infinite)
jpc_double (Q, Q);
k_i = naf4_257_get (NAF_K, i);
if (k_i)
{
if (q_infinite)
if (q_is_infinite)
{
memcpy (Q->x, p_Pi[NAF_K_INDEX(k_i)]->x, sizeof (bn256));
if (NAF_K_SIGN (k_i))
@@ -382,7 +430,7 @@ compute_kP (ac *X, const naf4_257 *NAF_K, const ac *P)
memcpy (Q->y, p_Pi[NAF_K_INDEX(k_i)]->y, sizeof (bn256));
memset (Q->z, 0, sizeof (bn256));
Q->z->words[0] = 1;
q_infinite = 0;
q_is_infinite = 0;
}
else
jpc_add_ac_signed (Q, Q, p_Pi[NAF_K_INDEX(k_i)], NAF_K_SIGN (k_i));
@@ -412,7 +460,7 @@ static const bn256 MU_lower[1] = {
/**
* @brief Compute signature (r,s) of hash string z with secret key dA
* @brief Compute signature (r,s) of hash string z with secret key d
*/
void
ecdsa (bn256 *r, bn256 *s, const bn256 *z, const bn256 *d)
@@ -423,11 +471,18 @@ ecdsa (bn256 *r, bn256 *s, const bn256 *z, const bn256 *d)
bn256 k_inv[1];
uint32_t carry;
#define tmp_k k_inv
do
{
do
{
bn256_random (k);
if (bn256_sub (tmp_k, k, N) == 0) /* > N, it's too big. */
continue;
if (bn256_add_uint (tmp_k, tmp_k, 2)) /* > N - 2, still big. */
continue;
bn256_add_uint (k, 1);
compute_kG (KG, k);
if (bn256_is_ge (KG->x, N))
bn256_sub (r, KG->x, N);

View File

@@ -1,3 +1,4 @@
/* Non-adjacent form */
typedef struct naf4_257 {
uint32_t words[ BN256_WORDS*4 ]; /* Little endian */
uint8_t last_nibble; /* most significant nibble */

68
src/ecc-cdh.c Normal file
View File

@@ -0,0 +1,68 @@
/*
* ecc-cdh.c - One-Pass Diffie-Hellman method implementation
* C(1, 1, ECC CDH) for EC DH of OpenPGP ECC
*
* Copyright (C) 2013 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
*
* Gnuk is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Gnuk is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* References:
*
* [1] A. Jivsov, Elliptic Curve Cryptography (ECC) in OpenPGP, RFC 6637,
* June 2012.
*
* [2] Suite B Implementer's Guide to NIST SP 800-56A, July 28, 2009.
*
*/
static const char param[] = {
/**/
curve_OID_len,
curve_OID,
public-key_alg_ID, /*ecdh*/
0x03,
0x01,
KDF_hash_ID, /*sha256*/
KEK_alg_ID, /*aes128*/
"Anonymous Sender ",
my_finger_print /*20-byte*/
};
/*
*
*/
int
ecdh (unsigned char *key,
const unsigned char *key_encrypted, const ac *P,
const naf4_257 *naf_d, const unsigned char *fp)
{
ac S[1];
sha256_context ctx;
unsigned char kek[32];
compute_kP (S, naf_d, P); /* Get shared key. */
/* kdf (kek, S, parameter) */
sha256_start (&ctx);
sha256_update (&ctx, "\x00\x00\x00\x01", 4);
sha256_update (&ctx, (const char *)S, size of S); /* XXX 04, X, Y bigendian!! */
sha256_update (&ctx, (const char *)param, size of param);
sha256_finish (&ctx, kek);
}

View File

@@ -1,2 +1,3 @@
void mod_reduce (bn256 *X, const bn512 *A, const bn256 *B, const bn256 *MU_lower);
void mod_reduce (bn256 *X, const bn512 *A, const bn256 *B,
const bn256 *MU_lower);
void mod_inv (bn256 *X, const bn256 *A, const bn256 *N);