From df4e8c5481a86c8f3e063e0545c03001828cde1c Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 18 Feb 2014 15:54:28 +0900 Subject: [PATCH] Use CPP for jpc_p256[kr]1 --- ChangeLog | 4 + src/jpc-ac_p256k1.h | 23 ++++++ src/jpc.c | 195 ++++++++++++++++++++++++++++++++++++++++++++ src/jpc_p256k1.c | 33 ++++++++ src/jpc_p256r1.c | 168 +------------------------------------- 5 files changed, 259 insertions(+), 164 deletions(-) create mode 100644 src/jpc-ac_p256k1.h create mode 100644 src/jpc.c create mode 100644 src/jpc_p256k1.c diff --git a/ChangeLog b/ChangeLog index 795ff06..658178f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2014-02-18 Niibe Yutaka + * src/jpc_p256k1.c: New. Use jpc.c. + * src/jpc_p256r1.c: Use jpc.c. + * src/jpc.c: New. + * src/sha256.c (memcpy_output_bswap32): Bug fix. * src/modp256k1.h, src/modp256k1.c: New. diff --git a/src/jpc-ac_p256k1.h b/src/jpc-ac_p256k1.h new file mode 100644 index 0000000..a614350 --- /dev/null +++ b/src/jpc-ac_p256k1.h @@ -0,0 +1,23 @@ +/** + * @brief Jacobian projective coordinates + */ +typedef struct +{ + bn256 x[1]; + bn256 y[1]; + bn256 z[1]; +} jpc; + +/** + * @brief Affin coordinates + */ +typedef struct +{ + bn256 x[1]; + bn256 y[1]; +} ac; + +void jpc_double_p256k1 (jpc *X, const jpc *A); +void jpc_add_ac_p256k1 (jpc *X, const jpc *A, const ac *B); +void jpc_add_ac_signed_p256k1 (jpc *X, const jpc *A, const ac *B, int minus); +int jpc_to_ac_p256k1 (ac *X, const jpc *A); diff --git a/src/jpc.c b/src/jpc.c new file mode 100644 index 0000000..d34bf25 --- /dev/null +++ b/src/jpc.c @@ -0,0 +1,195 @@ +/* + * jpc.c -- arithmetic on Jacobian projective coordinates. + * + * Copyright (C) 2011, 2013 Free Software Initiative of Japan + * Author: NIIBE Yutaka + * + * 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 . + * + */ + +#define CONCAT0(a,b) a##b +#define CONCAT1(a,b) CONCAT0(a,b) +#define CONCAT2(a,b,c) CONCAT1(a,b##c) +#define CONCAT3(a,b,c) CONCAT2(a,b,c) + +#define FUNC(func) CONCAT1(func##_,FIELD) +#define MFNC(func) CONCAT3(mod,FIELD,_##func) + +/** + * @brief X = 2 * A + * + * @param X Destination JPC + * @param A JPC + */ +void +FUNC(jpc_double) (jpc *X, const jpc *A) +{ + bn256 a[1], b[1], c[1], tmp0[1]; + bn256 *d; + + if (bn256_is_zero (A->z)) /* A is infinite */ + return; + + d = X->x; + MFNC(sqr) (a, A->y); + memcpy (b, a, sizeof (bn256)); + MFNC(mul) (a, a, A->x); + MFNC(shift) (a, a, 2); + + MFNC(sqr) (b, b); + MFNC(shift) (b, b, 3); + + MFNC(sqr) (tmp0, A->z); + MFNC(sub) (c, A->x, tmp0); + MFNC(add) (tmp0, tmp0, A->x); + MFNC(mul) (tmp0, tmp0, c); + MFNC(shift) (c, tmp0, 1); + MFNC(add) (c, c, tmp0); + + MFNC(sqr) (d, c); + MFNC(shift) (tmp0, a, 1); + MFNC(sub) (d, d, tmp0); + + MFNC(mul) (X->z, A->y, A->z); + MFNC(shift) (X->z, X->z, 1); + + MFNC(sub) (tmp0, a, d); + MFNC(mul) (tmp0, c, tmp0); + MFNC(sub) (X->y, tmp0, b); +} + +/** + * @brief X = A + B + * + * @param X Destination JPC + * @param A JPC + * @param B AC + * @param MINUS if 1 subtraction, addition otherwise. + */ +void +FUNC(jpc_add_ac_signed) (jpc *X, const jpc *A, const ac *B, int minus) +{ + bn256 a[1], b[1], c[1], d[1], tmp[1]; +#define minus_B_y c +#define c_sqr a +#define c_cube b +#define x1_c_sqr c +#define x1_c_sqr_2 c +#define c_cube_plus_x1_c_sqr_2 c +#define x1_c_sqr_copy a +#define y3_tmp c +#define y1_c_cube a + + if (bn256_is_zero (A->z)) /* A is infinite */ + { + memcpy (X->x, B->x, sizeof (bn256)); + if (minus) + { + memcpy (tmp, B->y, sizeof (bn256)); + bn256_sub (X->y, CONST_P256, B->y); + } + else + { + memcpy (X->y, B->y, sizeof (bn256)); + bn256_sub (tmp, CONST_P256, B->y); + } + memset (X->z, 0, sizeof (bn256)); + X->z->word[0] = 1; + return; + } + + MFNC(sqr) (a, A->z); + memcpy (b, a, sizeof (bn256)); + MFNC(mul) (a, a, B->x); + + MFNC(mul) (b, b, A->z); + if (minus) + { + bn256_sub (minus_B_y, CONST_P256, B->y); + MFNC(mul) (b, b, minus_B_y); + } + else + { + bn256_sub (tmp, CONST_P256, B->y); + MFNC(mul) (b, b, B->y); + } + + if (bn256_cmp (A->x, a) == 0 && bn256_cmp (A->y, b) == 0) + { + FUNC(jpc_double) (X, A); + return; + } + + MFNC(sub) (c, a, A->x); + MFNC(sub) (d, b, A->y); + + MFNC(mul) (X->z, A->z, c); + + MFNC(sqr) (c_sqr, c); + MFNC(mul) (c_cube, c_sqr, c); + + MFNC(mul) (x1_c_sqr, A->x, c_sqr); + + MFNC(sqr) (X->x, d); + memcpy (x1_c_sqr_copy, x1_c_sqr, sizeof (bn256)); + MFNC(shift) (x1_c_sqr_2, x1_c_sqr, 1); + MFNC(add) (c_cube_plus_x1_c_sqr_2, x1_c_sqr_2, c_cube); + MFNC(sub) (X->x, X->x, c_cube_plus_x1_c_sqr_2); + + MFNC(sub) (y3_tmp, x1_c_sqr_copy, X->x); + MFNC(mul) (y3_tmp, y3_tmp, d); + MFNC(mul) (y1_c_cube, A->y, c_cube); + MFNC(sub) (X->y, y3_tmp, y1_c_cube); +} + +/** + * @brief X = A + B + * + * @param X Destination JPC + * @param A JPC + * @param B AC + */ +void +FUNC(jpc_add_ac) (jpc *X, const jpc *A, const ac *B) +{ + FUNC(jpc_add_ac_signed) (X, A, B, 0); +} + +/** + * @brief X = convert A + * + * @param X Destination AC + * @param A JPC + * + * Return -1 on error (infinite). + * Return 0 on success. + */ +int +FUNC(jpc_to_ac) (ac *X, const jpc *A) +{ + bn256 z_inv[1], z_inv_sqr[1]; + + if (MFNC(inv) (z_inv, A->z) < 0) + return -1; + + MFNC(sqr) (z_inv_sqr, z_inv); + MFNC(mul) (z_inv, z_inv, z_inv_sqr); + + MFNC(mul) (X->x, A->x, z_inv_sqr); + MFNC(mul) (X->y, A->y, z_inv); + return 0; +} diff --git a/src/jpc_p256k1.c b/src/jpc_p256k1.c new file mode 100644 index 0000000..0b1915f --- /dev/null +++ b/src/jpc_p256k1.c @@ -0,0 +1,33 @@ +/* + * jpc_p256k1.c -- arithmetic on Jacobian projective coordinates for p256k1. + * + * Copyright (C) 2014 Free Software Initiative of Japan + * Author: NIIBE Yutaka + * + * 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 . + * + */ + +#include +#include +#include "bn.h" +#include "modp256k1.h" +#include "jpc-ac_p256k1.h" + +#define FIELD p256k1 +#define CONST_P256 P256K1 + +#include "jpc.c" diff --git a/src/jpc_p256r1.c b/src/jpc_p256r1.c index 8b525dd..36ffb4b 100644 --- a/src/jpc_p256r1.c +++ b/src/jpc_p256r1.c @@ -1,7 +1,7 @@ /* * jpc_p256r1.c -- arithmetic on Jacobian projective coordinates for p256r1. * - * Copyright (C) 2011, 2013 Free Software Initiative of Japan + * Copyright (C) 2014 Free Software Initiative of Japan * Author: NIIBE Yutaka * * This file is a part of Gnuk, a GnuPG USB Token implementation. @@ -27,167 +27,7 @@ #include "modp256r1.h" #include "jpc-ac_p256r1.h" -/** - * @brief X = 2 * A - * - * @param X Destination JPC - * @param A JPC - */ -void -jpc_double_p256r1 (jpc *X, const jpc *A) -{ - bn256 a[1], b[1], c[1], tmp0[1]; - bn256 *d; +#define FIELD p256r1 +#define CONST_P256 P256R1 - if (bn256_is_zero (A->z)) /* A is infinite */ - return; - - d = X->x; - modp256r1_sqr (a, A->y); - memcpy (b, a, sizeof (bn256)); - modp256r1_mul (a, a, A->x); - modp256r1_shift (a, a, 2); - - modp256r1_sqr (b, b); - modp256r1_shift (b, b, 3); - - modp256r1_sqr (tmp0, A->z); - modp256r1_sub (c, A->x, tmp0); - modp256r1_add (tmp0, tmp0, A->x); - modp256r1_mul (tmp0, tmp0, c); - modp256r1_shift (c, tmp0, 1); - modp256r1_add (c, c, tmp0); - - modp256r1_sqr (d, c); - modp256r1_shift (tmp0, a, 1); - modp256r1_sub (d, d, tmp0); - - modp256r1_mul (X->z, A->y, A->z); - modp256r1_shift (X->z, X->z, 1); - - modp256r1_sub (tmp0, a, d); - modp256r1_mul (tmp0, c, tmp0); - modp256r1_sub (X->y, tmp0, b); -} - -/** - * @brief X = A + B - * - * @param X Destination JPC - * @param A JPC - * @param B AC - * @param MINUS if 1 subtraction, addition otherwise. - */ -void -jpc_add_ac_signed_p256r1 (jpc *X, const jpc *A, const ac *B, int minus) -{ - bn256 a[1], b[1], c[1], d[1], tmp[1]; -#define minus_B_y c -#define c_sqr a -#define c_cube b -#define x1_c_sqr c -#define x1_c_sqr_2 c -#define c_cube_plus_x1_c_sqr_2 c -#define x1_c_sqr_copy a -#define y3_tmp c -#define y1_c_cube a - - if (bn256_is_zero (A->z)) /* A is infinite */ - { - memcpy (X->x, B->x, sizeof (bn256)); - if (minus) - { - memcpy (tmp, B->y, sizeof (bn256)); - bn256_sub (X->y, P256R1, B->y); - } - else - { - memcpy (X->y, B->y, sizeof (bn256)); - bn256_sub (tmp, P256R1, B->y); - } - memset (X->z, 0, sizeof (bn256)); - X->z->word[0] = 1; - return; - } - - modp256r1_sqr (a, A->z); - memcpy (b, a, sizeof (bn256)); - modp256r1_mul (a, a, B->x); - - modp256r1_mul (b, b, A->z); - if (minus) - { - bn256_sub (minus_B_y, P256R1, B->y); - modp256r1_mul (b, b, minus_B_y); - } - else - { - bn256_sub (tmp, P256R1, B->y); - modp256r1_mul (b, b, B->y); - } - - if (bn256_cmp (A->x, a) == 0 && bn256_cmp (A->y, b) == 0) - { - jpc_double (X, A); - return; - } - - modp256r1_sub (c, a, A->x); - modp256r1_sub (d, b, A->y); - - modp256r1_mul (X->z, A->z, c); - - modp256r1_sqr (c_sqr, c); - modp256r1_mul (c_cube, c_sqr, c); - - modp256r1_mul (x1_c_sqr, A->x, c_sqr); - - modp256r1_sqr (X->x, d); - memcpy (x1_c_sqr_copy, x1_c_sqr, sizeof (bn256)); - modp256r1_shift (x1_c_sqr_2, x1_c_sqr, 1); - modp256r1_add (c_cube_plus_x1_c_sqr_2, x1_c_sqr_2, c_cube); - modp256r1_sub (X->x, X->x, c_cube_plus_x1_c_sqr_2); - - modp256r1_sub (y3_tmp, x1_c_sqr_copy, X->x); - modp256r1_mul (y3_tmp, y3_tmp, d); - modp256r1_mul (y1_c_cube, A->y, c_cube); - modp256r1_sub (X->y, y3_tmp, y1_c_cube); -} - -/** - * @brief X = A + B - * - * @param X Destination JPC - * @param A JPC - * @param B AC - */ -void -jpc_add_ac_p256r1 (jpc *X, const jpc *A, const ac *B) -{ - jpc_add_ac_signed_p256r1 (X, A, B, 0); -} - -/** - * @brief X = convert A - * - * @param X Destination AC - * @param A JPC - * - * Return -1 on error (infinite). - * Return 0 on success. - */ -int -jpc_to_ac_p256r1 (ac *X, const jpc *A) -{ - bn256 z_inv[1], z_inv_sqr[1]; - - if (modp256r1_inv (z_inv, A->z) < 0) - return -1; - - modp256r1_sqr (z_inv_sqr, z_inv); - modp256r1_mul (z_inv, z_inv, z_inv_sqr); - - modp256r1_mul (X->x, A->x, z_inv_sqr); - modp256r1_mul (X->y, A->y, z_inv); - return 0; -} +#include "jpc.c"