2 * modp256r1.c -- modulo arithmetic for p256r1
4 * Copyright (C) 2011, 2013, 2014 Free Software Initiative of Japan
5 * Author: NIIBE Yutaka <gniibe@fsij.org>
7 * This file is a part of Gnuk, a GnuPG USB Token implementation.
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.
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.
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/>.
25 * p256 = 2^256 - 2^224 + 2^192 + 2^96 - 1
31 #include "modp256r1.h"
34 256 224 192 160 128 96 64 32 0
36 1 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
38 0 ffffffff 00000000 00000000 00000000 00000000 00000000 00000000 00000000
40 0 ffffffff 00000001 00000000 00000000 00000000 00000000 00000000 00000000
41 2^256 - 2^224 + 2^192 + 2^96
42 0 ffffffff 00000001 00000000 00000000 00000001 00000000 00000000 00000000
43 2^256 - 2^224 + 2^192 + 2^96 - 1
44 0 ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff ffffffff
46 const bn256 p256r1 = { {0xffffffff, 0xffffffff, 0xffffffff, 0x00000000,
47 0x00000000, 0x00000000, 0x00000001, 0xffffffff} };
50 * @brief X = (A + B) mod p256r1
53 modp256r1_add (bn256 *X, const bn256 *A, const bn256 *B)
58 carry = bn256_add (X, A, B);
60 bn256_sub (X, X, P256R1);
62 bn256_sub (tmp, X, P256R1);
66 * @brief X = (A - B) mod p256r1
69 modp256r1_sub (bn256 *X, const bn256 *A, const bn256 *B)
74 borrow = bn256_sub (X, A, B);
76 bn256_add (X, X, P256R1);
78 bn256_add (tmp, X, P256R1);
82 * @brief X = A mod p256r1
85 modp256r1_reduce (bn256 *X, const bn512 *A)
100 S1->word[7] = A->word[7];
101 S1->word[6] = A->word[6];
102 S1->word[5] = A->word[5];
103 S1->word[4] = A->word[4];
104 S1->word[3] = A->word[3];
105 S1->word[2] = A->word[2];
106 S1->word[1] = A->word[1];
107 S1->word[0] = A->word[0];
110 S2->word[7] = A->word[15];
111 S2->word[6] = A->word[14];
112 S2->word[5] = A->word[13];
113 S2->word[4] = A->word[12];
114 S2->word[3] = A->word[11];
115 S2->word[2] = S2->word[1] = S2->word[0] = 0;
117 modp256r1_add (X, X, S2);
118 modp256r1_add (X, X, S2);
121 S3->word[6] = A->word[15];
122 S3->word[5] = A->word[14];
123 S3->word[4] = A->word[13];
124 S3->word[3] = A->word[12];
125 S3->word[2] = S3->word[1] = S3->word[0] = 0;
127 modp256r1_add (X, X, S3);
128 modp256r1_add (X, X, S3);
130 S4->word[7] = A->word[15];
131 S4->word[6] = A->word[14];
132 S4->word[5] = S4->word[4] = S4->word[3] = 0;
133 S4->word[2] = A->word[10];
134 S4->word[1] = A->word[9];
135 S4->word[0] = A->word[8];
137 modp256r1_add (X, X, S4);
139 S5->word[7] = A->word[8];
140 S5->word[6] = A->word[13];
141 S5->word[5] = A->word[15];
142 S5->word[4] = A->word[14];
143 S5->word[3] = A->word[13];
144 S5->word[2] = A->word[11];
145 S5->word[1] = A->word[10];
146 S5->word[0] = A->word[9];
148 modp256r1_add (X, X, S5);
150 S6->word[7] = A->word[10];
151 S6->word[6] = A->word[8];
152 S6->word[5] = S6->word[4] = S6->word[3] = 0;
153 S6->word[2] = A->word[13];
154 S6->word[1] = A->word[12];
155 S6->word[0] = A->word[11];
157 modp256r1_sub (X, X, S6);
159 S7->word[7] = A->word[11];
160 S7->word[6] = A->word[9];
161 S7->word[5] = S7->word[4] = 0;
162 S7->word[3] = A->word[15];
163 S7->word[2] = A->word[14];
164 S7->word[1] = A->word[13];
165 S7->word[0] = A->word[12];
167 modp256r1_sub (X, X, S7);
169 S8->word[7] = A->word[12];
171 S8->word[5] = A->word[10];
172 S8->word[4] = A->word[9];
173 S8->word[3] = A->word[8];
174 S8->word[2] = A->word[15];
175 S8->word[1] = A->word[14];
176 S8->word[0] = A->word[13];
178 modp256r1_sub (X, X, S8);
180 S9->word[7] = A->word[13];
182 S9->word[5] = A->word[11];
183 S9->word[4] = A->word[10];
184 S9->word[3] = A->word[9];
186 S9->word[1] = A->word[15];
187 S9->word[0] = A->word[14];
189 modp256r1_sub (X, X, S9);
191 borrow = bn256_sub (tmp, X, P256R1);
193 memcpy (tmp, X, sizeof (bn256));
195 memcpy (X, tmp, sizeof (bn256));
209 * @brief X = (A * B) mod p256r1
212 modp256r1_mul (bn256 *X, const bn256 *A, const bn256 *B)
216 bn256_mul (AB, A, B);
217 modp256r1_reduce (X, AB);
221 * @brief X = A * A mod p256r1
224 modp256r1_sqr (bn256 *X, const bn256 *A)
229 modp256r1_reduce (X, AA);
233 * @brief C = (1 / a) mod p256r1
235 * Return -1 on error.
236 * Return 0 on success.
238 #define MAX_N_BITS 256
241 modp256r1_inv (bn256 *C, const bn256 *a)
243 bn256 u[1], v[1], tmp[1];
244 bn256 A[1] = { { { 1, 0, 0, 0, 0, 0, 0, 0 } } };
246 int n = MAX_N_BITS * 3;
248 if (bn256_is_zero (a))
251 memset (C, 0, sizeof (bn256));
252 memcpy (u, a, sizeof (bn256));
253 memcpy (v, P256R1, sizeof (bn256));
257 int c = (bn256_is_even (u) << 1) + bn256_is_even (v);
262 bn256_shift (u, u, -1);
263 if (bn256_is_even (A))
265 bn256_add (tmp, A, P256R1);
269 carry = bn256_add (A, A, P256R1);
271 bn256_shift (A, A, -1);
272 A->word[7] |= carry * 0x80000000;
274 bn256_shift (v, v, -1);
275 if (bn256_is_even (C))
277 bn256_add (tmp, C, P256R1);
281 carry = bn256_add (C, C, P256R1);
283 bn256_shift (C, C, -1);
284 C->word[7] |= carry * 0x80000000;
286 if (bn256_is_ge (tmp, tmp))
288 bn256_sub (tmp, tmp, tmp);
289 modp256r1_sub (tmp, tmp, tmp);
293 bn256_sub (tmp, tmp, tmp);
294 modp256r1_sub (tmp, tmp, A);
299 bn256_shift (tmp, tmp, -1);
300 if (bn256_is_even (tmp))
302 bn256_add (tmp, tmp, P256R1);
306 carry = bn256_add (tmp, tmp, P256R1);
308 bn256_shift (tmp, tmp, -1);
309 tmp->word[7] |= carry * 0x80000000;
311 bn256_shift (v, v, -1);
312 if (bn256_is_even (C))
314 bn256_add (tmp, C, P256R1);
318 carry = bn256_add (C, C, P256R1);
320 bn256_shift (C, C, -1);
321 C->word[7] |= carry * 0x80000000;
323 if (bn256_is_ge (tmp, tmp))
325 bn256_sub (tmp, tmp, tmp);
326 modp256r1_sub (tmp, tmp, tmp);
330 bn256_sub (tmp, tmp, tmp);
331 modp256r1_sub (tmp, tmp, A);
336 bn256_shift (u, u, -1);
337 if (bn256_is_even (A))
339 bn256_add (tmp, A, P256R1);
343 carry = bn256_add (A, A, P256R1);
345 bn256_shift (A, A, -1);
346 A->word[7] |= carry * 0x80000000;
348 bn256_shift (tmp, tmp, -1);
349 if (bn256_is_even (tmp))
351 bn256_add (tmp, tmp, P256R1);
355 carry = bn256_add (tmp, tmp, P256R1);
357 bn256_shift (tmp, tmp, -1);
358 tmp->word[7] |= carry * 0x80000000;
360 if (bn256_is_ge (tmp, tmp))
362 bn256_sub (tmp, tmp, tmp);
363 modp256r1_sub (tmp, tmp, tmp);
367 bn256_sub (tmp, tmp, tmp);
368 modp256r1_sub (tmp, tmp, A);
373 bn256_shift (tmp, tmp, -1);
374 if (bn256_is_even (tmp))
376 bn256_add (tmp, tmp, P256R1);
380 carry = bn256_add (tmp, tmp, P256R1);
382 bn256_shift (tmp, tmp, -1);
383 tmp->word[7] |= carry * 0x80000000;
385 bn256_shift (tmp, tmp, -1);
386 if (bn256_is_even (tmp))
388 bn256_add (tmp, tmp, P256R1);
392 carry = bn256_add (tmp, tmp, P256R1);
394 bn256_shift (tmp, tmp, -1);
395 tmp->word[7] |= carry * 0x80000000;
397 if (bn256_is_ge (u, v))
400 modp256r1_sub (A, A, C);
405 modp256r1_sub (C, C, A);
415 * @brief X = (A << shift) mod p256r1
419 modp256r1_shift (bn256 *X, const bn256 *A, int shift)
425 carry = bn256_shift (X, A, shift);
429 memset (tmp, 0, sizeof (bn256));
430 tmp->word[7] = carry;
431 tmp->word[0] = carry;
432 modp256r1_add (X, X, tmp);
436 tmp->word[6] = carry;
437 tmp->word[3] = carry;
438 modp256r1_sub (X, X, tmp);
440 borrow = bn256_sub (tmp, X, P256R1);
442 memcpy (tmp, X, sizeof (bn256));
444 memcpy (X, tmp, sizeof (bn256));