Support VERIFY reset feature
[gnuk/gnuk.git] / src / jpc.c
1 /*
2  * jpc.c -- arithmetic on Jacobian projective coordinates.
3  *
4  * Copyright (C) 2011, 2013 Free Software Initiative of Japan
5  * Author: NIIBE Yutaka <gniibe@fsij.org>
6  *
7  * This file is a part of Gnuk, a GnuPG USB Token implementation.
8  *
9  * Gnuk is free software: you can redistribute it and/or modify it
10  * under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * Gnuk is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
17  * License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 #include "field-group-select.h"
25
26 /**
27  * @brief       X = 2 * A
28  *
29  * @param X     Destination JPC
30  * @param A     JPC
31  */
32 void
33 FUNC(jpc_double) (jpc *X, const jpc *A)
34 {
35   bn256 a[1], b[1], c[1], tmp0[1];
36   bn256 *d;
37
38   if (bn256_is_zero (A->z))             /* A is infinite */
39     return;
40
41   d = X->x;
42   MFNC(sqr) (a, A->y);
43   memcpy (b, a, sizeof (bn256));
44   MFNC(mul) (a, a, A->x);
45   MFNC(shift) (a, a, 2);
46
47   MFNC(sqr) (b, b);
48   MFNC(shift) (b, b, 3);
49
50 #if defined(COEFFICIENT_A_IS_MINUS_3)
51   MFNC(sqr) (tmp0, A->z);
52   MFNC(sub) (c, A->x, tmp0);
53   MFNC(add) (tmp0, tmp0, A->x);
54   MFNC(mul) (tmp0, tmp0, c);
55   MFNC(shift) (c, tmp0, 1);
56   MFNC(add) (c, c, tmp0);
57 #elif defined (COEFFICIENT_A_IS_ZERO)
58   MFNC(sqr) (tmp0, A->x);
59   MFNC(shift) (c, tmp0, 1);
60   MFNC(add) (c, c, tmp0);
61 #else
62 #error "not supported."
63 #endif
64
65   MFNC(sqr) (d, c);
66   MFNC(shift) (tmp0, a, 1);
67   MFNC(sub) (d, d, tmp0);
68
69   MFNC(mul) (X->z, A->y, A->z);
70   MFNC(shift) (X->z, X->z, 1);
71
72   MFNC(sub) (tmp0, a, d);
73   MFNC(mul) (tmp0, c, tmp0);
74   MFNC(sub) (X->y, tmp0, b);
75 }
76
77 /**
78  * @brief       X = A + B
79  *
80  * @param X     Destination JPC
81  * @param A     JPC
82  * @param B     AC
83  * @param MINUS if 1 subtraction, addition otherwise.
84  */
85 void
86 FUNC(jpc_add_ac_signed) (jpc *X, const jpc *A, const ac *B, int minus)
87 {
88   bn256 a[1], b[1], c[1], d[1], tmp[1];
89 #define minus_B_y c
90 #define c_sqr a
91 #define c_cube b
92 #define x1_c_sqr c
93 #define x1_c_sqr_2 c
94 #define c_cube_plus_x1_c_sqr_2 c
95 #define x1_c_sqr_copy a
96 #define y3_tmp c
97 #define y1_c_cube a
98
99   if (bn256_is_zero (A->z))             /* A is infinite */
100     {
101       memcpy (X->x, B->x, sizeof (bn256));
102       if (minus)
103         {
104           memcpy (tmp, B->y, sizeof (bn256));
105           bn256_sub (X->y, CONST_P256, B->y);
106         }
107       else
108         {
109           memcpy (X->y, B->y, sizeof (bn256));
110           bn256_sub (tmp, CONST_P256, B->y);
111         }
112       memset (X->z, 0, sizeof (bn256));
113       X->z->word[0] = 1;
114       return;
115     }
116
117   MFNC(sqr) (a, A->z);
118   memcpy (b, a, sizeof (bn256));
119   MFNC(mul) (a, a, B->x);
120
121   MFNC(mul) (b, b, A->z);
122   if (minus)
123     {
124       bn256_sub (minus_B_y, CONST_P256, B->y);
125       MFNC(mul) (b, b, minus_B_y);
126     }
127   else
128     {
129       bn256_sub (tmp, CONST_P256, B->y);
130       MFNC(mul) (b, b, B->y);
131     }
132
133   if (bn256_cmp (A->x, a) == 0 && bn256_cmp (A->y, b) == 0)
134     {
135       FUNC(jpc_double) (X, A);
136       return;
137     }
138
139   MFNC(sub) (c, a, A->x);
140   MFNC(sub) (d, b, A->y);
141
142   MFNC(mul) (X->z, A->z, c);
143
144   MFNC(sqr) (c_sqr, c);
145   MFNC(mul) (c_cube, c_sqr, c);
146
147   MFNC(mul) (x1_c_sqr, A->x, c_sqr);
148
149   MFNC(sqr) (X->x, d);
150   memcpy (x1_c_sqr_copy, x1_c_sqr, sizeof (bn256));
151   MFNC(shift) (x1_c_sqr_2, x1_c_sqr, 1);
152   MFNC(add) (c_cube_plus_x1_c_sqr_2, x1_c_sqr_2, c_cube);
153   MFNC(sub) (X->x, X->x, c_cube_plus_x1_c_sqr_2);
154
155   MFNC(sub) (y3_tmp, x1_c_sqr_copy, X->x);
156   MFNC(mul) (y3_tmp, y3_tmp, d);
157   MFNC(mul) (y1_c_cube, A->y, c_cube);
158   MFNC(sub) (X->y, y3_tmp, y1_c_cube);
159 }
160
161 /**
162  * @brief       X = A + B
163  *
164  * @param X     Destination JPC
165  * @param A     JPC
166  * @param B     AC
167  */
168 void
169 FUNC(jpc_add_ac) (jpc *X, const jpc *A, const ac *B)
170 {
171   FUNC(jpc_add_ac_signed) (X, A, B, 0);
172 }
173
174 /**
175  * @brief       X = convert A
176  *
177  * @param X     Destination AC
178  * @param A     JPC
179  *
180  * Return -1 on error (infinite).
181  * Return 0 on success.
182  */
183 int
184 FUNC(jpc_to_ac) (ac *X, const jpc *A)
185 {
186   bn256 z_inv[1], z_inv_sqr[1];
187
188   if (bn256_is_zero (A->z))
189     return -1;
190
191   mod_inv (z_inv, A->z, CONST_P256);
192
193   MFNC(sqr) (z_inv_sqr, z_inv);
194   MFNC(mul) (z_inv, z_inv, z_inv_sqr);
195
196   MFNC(mul) (X->x, A->x, z_inv_sqr);
197   MFNC(mul) (X->y, A->y, z_inv);
198   return 0;
199 }