blob: e12e6c9d4f6c686d6133723770f0c0ddcc0e0ada [file] [log] [blame]
Denys Vlasenko11d00962017-01-15 00:12:42 +01001/*
2 * Copyright (C) 2017 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6#include "tls.h"
7
Denys Vlasenko3f8ecd92017-01-15 14:16:51 +01008/* The file is taken almost verbatim from matrixssl-3-7-2b-open/crypto/math/.
Denys Vlasenko6b1b0042017-01-19 15:51:00 +01009 * Changes are flagged with //bbox
Denys Vlasenko3f8ecd92017-01-15 14:16:51 +010010 */
11
Denys Vlasenko11d00962017-01-15 00:12:42 +010012/**
13 * @file pstm.c
14 * @version 33ef80f (HEAD, tag: MATRIXSSL-3-7-2-OPEN, tag: MATRIXSSL-3-7-2-COMM, origin/master, origin/HEAD, master)
15 *
16 * Multiprecision number implementation.
17 */
18/*
19 * Copyright (c) 2013-2015 INSIDE Secure Corporation
20 * Copyright (c) PeerSec Networks, 2002-2011
21 * All Rights Reserved
22 *
23 * The latest version of this code is available at http://www.matrixssl.org
24 *
25 * This software is open source; you can redistribute it and/or modify
26 * it under the terms of the GNU General Public License as published by
27 * the Free Software Foundation; either version 2 of the License, or
28 * (at your option) any later version.
29 *
30 * This General Public License does NOT permit incorporating this software
31 * into proprietary programs. If you are unable to comply with the GPL, a
32 * commercial license for this software may be purchased from INSIDE at
33 * http://www.insidesecure.com/eng/Company/Locations
34 *
35 * This program is distributed in WITHOUT ANY WARRANTY; without even the
36 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
37 * See the GNU General Public License for more details.
38 *
39 * You should have received a copy of the GNU General Public License
40 * along with this program; if not, write to the Free Software
41 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
42 * http://www.gnu.org/copyleft/gpl.html
43 */
44/******************************************************************************/
45
Denys Vlasenko6b1b0042017-01-19 15:51:00 +010046//bbox
Denys Vlasenko11d00962017-01-15 00:12:42 +010047//#include "../cryptoApi.h"
48#ifndef DISABLE_PSTM
49
Denys Vlasenko229d3c42017-04-03 21:53:29 +020050static int32 pstm_mul_2d(pstm_int *a, int b, pstm_int *c); //bbox: was int16 b
Denys Vlasenko11d00962017-01-15 00:12:42 +010051
52/******************************************************************************/
53/*
54 init an pstm_int for a given size
55 */
56int32 pstm_init_size(psPool_t *pool, pstm_int * a, uint32 size)
57{
Denys Vlasenko6b1b0042017-01-19 15:51:00 +010058//bbox
Denys Vlasenko11d00962017-01-15 00:12:42 +010059// uint16 x;
60
61/*
62 alloc mem
63 */
Denys Vlasenko6b1b0042017-01-19 15:51:00 +010064 a->dp = xzalloc(sizeof (pstm_digit) * size);//bbox
65//bbox a->pool = pool;
Denys Vlasenko11d00962017-01-15 00:12:42 +010066 a->used = 0;
Denys Vlasenko229d3c42017-04-03 21:53:29 +020067 a->alloc = size;
Denys Vlasenko11d00962017-01-15 00:12:42 +010068 a->sign = PSTM_ZPOS;
69/*
70 zero the digits
71 */
Denys Vlasenko6b1b0042017-01-19 15:51:00 +010072//bbox
Denys Vlasenko11d00962017-01-15 00:12:42 +010073// for (x = 0; x < size; x++) {
74// a->dp[x] = 0;
75// }
76 return PSTM_OKAY;
77}
78
79/******************************************************************************/
80/*
81 Init a new pstm_int.
82*/
83int32 pstm_init(psPool_t *pool, pstm_int * a)
84{
Denys Vlasenko6b1b0042017-01-19 15:51:00 +010085//bbox
Denys Vlasenko11d00962017-01-15 00:12:42 +010086// int32 i;
87/*
88 allocate memory required and clear it
89 */
Denys Vlasenko6b1b0042017-01-19 15:51:00 +010090 a->dp = xzalloc(sizeof (pstm_digit) * PSTM_DEFAULT_INIT);//bbox
Denys Vlasenko11d00962017-01-15 00:12:42 +010091/*
92 set the digits to zero
93 */
Denys Vlasenko6b1b0042017-01-19 15:51:00 +010094//bbox
Denys Vlasenko11d00962017-01-15 00:12:42 +010095// for (i = 0; i < PSTM_DEFAULT_INIT; i++) {
96// a->dp[i] = 0;
97// }
98/*
99 set the used to zero, allocated digits to the default precision and sign
100 to positive
101 */
Denys Vlasenko6b1b0042017-01-19 15:51:00 +0100102//bbox a->pool = pool;
Denys Vlasenko11d00962017-01-15 00:12:42 +0100103 a->used = 0;
104 a->alloc = PSTM_DEFAULT_INIT;
105 a->sign = PSTM_ZPOS;
106
107 return PSTM_OKAY;
108}
109
110/******************************************************************************/
111/*
112 Grow as required
113 */
Denys Vlasenko229d3c42017-04-03 21:53:29 +0200114int32 pstm_grow(pstm_int * a, int size)
Denys Vlasenko11d00962017-01-15 00:12:42 +0100115{
Denys Vlasenko229d3c42017-04-03 21:53:29 +0200116 int i; //bbox: was int16
Denys Vlasenko11d00962017-01-15 00:12:42 +0100117 pstm_digit *tmp;
118
119/*
120 If the alloc size is smaller alloc more ram.
121 */
122 if (a->alloc < size) {
123/*
124 Reallocate the array a->dp
125
126 We store the return in a temporary variable in case the operation
127 failed we don't want to overwrite the dp member of a.
128*/
Denys Vlasenko6b1b0042017-01-19 15:51:00 +0100129 tmp = xrealloc(a->dp, sizeof (pstm_digit) * size);//bbox
Denys Vlasenko11d00962017-01-15 00:12:42 +0100130/*
131 reallocation succeeded so set a->dp
132 */
133 a->dp = tmp;
134/*
135 zero excess digits
136 */
137 i = a->alloc;
138 a->alloc = size;
139 for (; i < a->alloc; i++) {
140 a->dp[i] = 0;
141 }
142 }
143 return PSTM_OKAY;
144}
145
146/******************************************************************************/
147/*
148 copy, b = a (b must be pre-allocated)
149 */
150int32 pstm_copy(pstm_int * a, pstm_int * b)
151{
152 int32 res, n;
153
154/*
155 If dst == src do nothing
156 */
157 if (a == b) {
158 return PSTM_OKAY;
159 }
160/*
161 Grow dest
162 */
163 if (b->alloc < a->used) {
164 if ((res = pstm_grow (b, a->used)) != PSTM_OKAY) {
165 return res;
166 }
167 }
168/*
169 Zero b and copy the parameters over
170 */
171 {
172 register pstm_digit *tmpa, *tmpb;
173
174 /* pointer aliases */
175 /* source */
176 tmpa = a->dp;
177
178 /* destination */
179 tmpb = b->dp;
180
181 /* copy all the digits */
182 for (n = 0; n < a->used; n++) {
183 *tmpb++ = *tmpa++;
184 }
185
186 /* clear high digits */
187 for (; n < b->used; n++) {
188 *tmpb++ = 0;
189 }
190 }
191/*
192 copy used count and sign
193 */
194 b->used = a->used;
195 b->sign = a->sign;
196 return PSTM_OKAY;
197}
198
199/******************************************************************************/
200/*
201 Trim unused digits
202
203 This is used to ensure that leading zero digits are trimed and the
204 leading "used" digit will be non-zero. Typically very fast. Also fixes
205 the sign if there are no more leading digits
206*/
207void pstm_clamp(pstm_int * a)
208{
209/* decrease used while the most significant digit is zero. */
210 while (a->used > 0 && a->dp[a->used - 1] == 0) {
211 --(a->used);
212 }
213/* reset the sign flag if used == 0 */
214 if (a->used == 0) {
215 a->sign = PSTM_ZPOS;
216 }
217}
218
219/******************************************************************************/
220/*
221 clear one (frees).
222 */
223void pstm_clear(pstm_int * a)
224{
225 int32 i;
226/*
227 only do anything if a hasn't been freed previously
228 */
229 if (a != NULL && a->dp != NULL) {
230/*
231 first zero the digits
232 */
233 for (i = 0; i < a->used; i++) {
234 a->dp[i] = 0;
235 }
236
237 psFree (a->dp, a->pool);
238/*
239 reset members to make debugging easier
240 */
241 a->dp = NULL;
242 a->alloc = a->used = 0;
243 a->sign = PSTM_ZPOS;
244 }
245}
246
247/******************************************************************************/
248/*
249 clear many (frees).
250 */
251void pstm_clear_multi(pstm_int *mp0, pstm_int *mp1, pstm_int *mp2,
252 pstm_int *mp3, pstm_int *mp4, pstm_int *mp5,
253 pstm_int *mp6, pstm_int *mp7)
254{
255 int32 n; /* Number of ok inits */
256
257 pstm_int *tempArray[9];
258
259 tempArray[0] = mp0;
260 tempArray[1] = mp1;
261 tempArray[2] = mp2;
262 tempArray[3] = mp3;
263 tempArray[4] = mp4;
264 tempArray[5] = mp5;
265 tempArray[6] = mp6;
266 tempArray[7] = mp7;
267 tempArray[8] = NULL;
268
269 for (n = 0; tempArray[n] != NULL; n++) {
270 if ((tempArray[n] != NULL) && (tempArray[n]->dp != NULL)) {
271 pstm_clear(tempArray[n]);
272 }
273 }
274}
275
276/******************************************************************************/
277/*
278 Set to zero.
279 */
280void pstm_zero(pstm_int * a)
281{
282 int32 n;
283 pstm_digit *tmp;
284
285 a->sign = PSTM_ZPOS;
286 a->used = 0;
287
288 tmp = a->dp;
289 for (n = 0; n < a->alloc; n++) {
290 *tmp++ = 0;
291 }
292}
293
294
295/******************************************************************************/
296/*
297 Compare maginitude of two ints (unsigned).
298 */
299int32 pstm_cmp_mag(pstm_int * a, pstm_int * b)
300{
Denys Vlasenko229d3c42017-04-03 21:53:29 +0200301 int n; //bbox: was int16
Denys Vlasenko11d00962017-01-15 00:12:42 +0100302 pstm_digit *tmpa, *tmpb;
303
304/*
305 compare based on # of non-zero digits
306 */
307 if (a->used > b->used) {
308 return PSTM_GT;
309 }
310
311 if (a->used < b->used) {
312 return PSTM_LT;
313 }
314
315 /* alias for a */
316 tmpa = a->dp + (a->used - 1);
317
318 /* alias for b */
319 tmpb = b->dp + (a->used - 1);
320
321/*
322 compare based on digits
323 */
324 for (n = 0; n < a->used; ++n, --tmpa, --tmpb) {
325 if (*tmpa > *tmpb) {
326 return PSTM_GT;
327 }
328 if (*tmpa < *tmpb) {
329 return PSTM_LT;
330 }
331 }
332 return PSTM_EQ;
333}
334
335/******************************************************************************/
336/*
337 Compare two ints (signed)
338 */
339int32 pstm_cmp(pstm_int * a, pstm_int * b)
340{
341/*
342 compare based on sign
343 */
344 if (a->sign != b->sign) {
345 if (a->sign == PSTM_NEG) {
346 return PSTM_LT;
347 } else {
348 return PSTM_GT;
349 }
350 }
351/*
352 compare digits
353 */
354 if (a->sign == PSTM_NEG) {
355 /* if negative compare opposite direction */
356 return pstm_cmp_mag(b, a);
357 } else {
358 return pstm_cmp_mag(a, b);
359 }
360}
361
362/******************************************************************************/
363/*
364 pstm_ints can be initialized more precisely when they will populated
365 using pstm_read_unsigned_bin since the length of the byte stream is known
366*/
367int32 pstm_init_for_read_unsigned_bin(psPool_t *pool, pstm_int *a, uint32 len)
368{
369 int32 size;
370/*
371 Need to set this based on how many words max it will take to store the bin.
372 The magic + 2:
373 1 to round up for the remainder of this integer math
374 1 for the initial carry of '1' bits that fall between DIGIT_BIT and 8
375*/
376 size = (((len / sizeof(pstm_digit)) * (sizeof(pstm_digit) * CHAR_BIT))
377 / DIGIT_BIT) + 2;
378 return pstm_init_size(pool, a, size);
379}
380
381
382/******************************************************************************/
383/*
384 Reads a unsigned char array into pstm_int format. User should have
385 called pstm_init_for_read_unsigned_bin first. There is some grow logic
386 here if the default pstm_init was used but we don't really want to hit it.
387*/
388int32 pstm_read_unsigned_bin(pstm_int *a, unsigned char *b, int32 c)
389{
390 /* zero the int */
391 pstm_zero (a);
392
393/*
394 If we know the endianness of this architecture, and we're using
395 32-bit pstm_digits, we can optimize this
396*/
397#if (defined(ENDIAN_LITTLE) || defined(ENDIAN_BIG)) && !defined(PSTM_64BIT)
398 /* But not for both simultaneously */
399#if defined(ENDIAN_LITTLE) && defined(ENDIAN_BIG)
400#error Both ENDIAN_LITTLE and ENDIAN_BIG defined.
401#endif
402 {
403 unsigned char *pd;
404 if ((unsigned)c > (PSTM_MAX_SIZE * sizeof(pstm_digit))) {
405 uint32 excess = c - (PSTM_MAX_SIZE * sizeof(pstm_digit));
406 c -= excess;
407 b += excess;
408 }
Denys Vlasenko229d3c42017-04-03 21:53:29 +0200409 a->used = ((c + sizeof(pstm_digit) - 1)/sizeof(pstm_digit));
Denys Vlasenko11d00962017-01-15 00:12:42 +0100410 if (a->alloc < a->used) {
411 if (pstm_grow(a, a->used) != PSTM_OKAY) {
412 return PSTM_MEM;
413 }
414 }
415 pd = (unsigned char *)a->dp;
416 /* read the bytes in */
417#ifdef ENDIAN_BIG
418 {
419 /* Use Duff's device to unroll the loop. */
420 int32 idx = (c - 1) & ~3;
421 switch (c % 4) {
422 case 0: do { pd[idx+0] = *b++;
423 case 3: pd[idx+1] = *b++;
424 case 2: pd[idx+2] = *b++;
425 case 1: pd[idx+3] = *b++;
426 idx -= 4;
427 } while ((c -= 4) > 0);
428 }
429 }
430#else
431 for (c -= 1; c >= 0; c -= 1) {
432 pd[c] = *b++;
433 }
434#endif
435 }
436#else
437 /* Big enough based on the len? */
438 a->used = (((c / sizeof(pstm_digit)) * (sizeof(pstm_digit) * CHAR_BIT))
439 / DIGIT_BIT) + 2;
440
441 if (a->alloc < a->used) {
442 if (pstm_grow(a, a->used) != PSTM_OKAY) {
443 return PSTM_MEM;
444 }
445 }
446 /* read the bytes in */
447 for (; c > 0; c--) {
448 if (pstm_mul_2d (a, 8, a) != PSTM_OKAY) {
449 return PS_MEM_FAIL;
450 }
451 a->dp[0] |= *b++;
452 a->used += 1;
453 }
454#endif
455
456 pstm_clamp (a);
457 return PS_SUCCESS;
458}
459
460/******************************************************************************/
461/*
462*/
Denys Vlasenko229d3c42017-04-03 21:53:29 +0200463int pstm_count_bits (pstm_int * a)
Denys Vlasenko11d00962017-01-15 00:12:42 +0100464{
Denys Vlasenko229d3c42017-04-03 21:53:29 +0200465 int r; //bbox: was int16
Denys Vlasenko11d00962017-01-15 00:12:42 +0100466 pstm_digit q;
467
468 if (a->used == 0) {
469 return 0;
470 }
471
472 /* get number of digits and add that */
473 r = (a->used - 1) * DIGIT_BIT;
474
475 /* take the last digit and count the bits in it */
476 q = a->dp[a->used - 1];
477 while (q > ((pstm_digit) 0)) {
478 ++r;
479 q >>= ((pstm_digit) 1);
480 }
481 return r;
482}
483
484/******************************************************************************/
485int32 pstm_unsigned_bin_size(pstm_int *a)
486{
487 int32 size = pstm_count_bits (a);
488 return (size / 8 + ((size & 7) != 0 ? 1 : 0));
489}
490
491/******************************************************************************/
492void pstm_set(pstm_int *a, pstm_digit b)
493{
494 pstm_zero(a);
495 a->dp[0] = b;
496 a->used = a->dp[0] ? 1 : 0;
497}
498
499/******************************************************************************/
500/*
501 Right shift
502*/
Denys Vlasenko229d3c42017-04-03 21:53:29 +0200503void pstm_rshd(pstm_int *a, int x)
Denys Vlasenko11d00962017-01-15 00:12:42 +0100504{
Denys Vlasenko229d3c42017-04-03 21:53:29 +0200505 int y; //bbox: was int16
Denys Vlasenko11d00962017-01-15 00:12:42 +0100506
507 /* too many digits just zero and return */
508 if (x >= a->used) {
509 pstm_zero(a);
510 return;
511 }
512
513 /* shift */
514 for (y = 0; y < a->used - x; y++) {
515 a->dp[y] = a->dp[y+x];
516 }
517
518 /* zero rest */
519 for (; y < a->used; y++) {
520 a->dp[y] = 0;
521 }
522
523 /* decrement count */
524 a->used -= x;
525 pstm_clamp(a);
526}
527
528/******************************************************************************/
529/*
530 Shift left a certain amount of digits.
531 */
Denys Vlasenko229d3c42017-04-03 21:53:29 +0200532int32 pstm_lshd(pstm_int * a, int b)
Denys Vlasenko11d00962017-01-15 00:12:42 +0100533{
Denys Vlasenko229d3c42017-04-03 21:53:29 +0200534 int x; //bbox: was int16
Denys Vlasenko11d00962017-01-15 00:12:42 +0100535 int32 res;
536
537/*
538 If its less than zero return.
539 */
540 if (b <= 0) {
541 return PSTM_OKAY;
542 }
543/*
544 Grow to fit the new digits.
545 */
546 if (a->alloc < a->used + b) {
547 if ((res = pstm_grow (a, a->used + b)) != PSTM_OKAY) {
548 return res;
549 }
550 }
551
552 {
553 register pstm_digit *top, *bottom;
554/*
555 Increment the used by the shift amount then copy upwards.
556 */
557 a->used += b;
558
559 /* top */
560 top = a->dp + a->used - 1;
561
562 /* base */
563 bottom = a->dp + a->used - 1 - b;
564/*
565 This is implemented using a sliding window except the window goes the
566 other way around. Copying from the bottom to the top.
567 */
568 for (x = a->used - 1; x >= b; x--) {
569 *top-- = *bottom--;
570 }
571
572 /* zero the lower digits */
573 top = a->dp;
574 for (x = 0; x < b; x++) {
575 *top++ = 0;
576 }
577 }
578 return PSTM_OKAY;
579}
580
581/******************************************************************************/
582/*
583 computes a = 2**b
584*/
Denys Vlasenko229d3c42017-04-03 21:53:29 +0200585int32 pstm_2expt(pstm_int *a, int b)
Denys Vlasenko11d00962017-01-15 00:12:42 +0100586{
Denys Vlasenko229d3c42017-04-03 21:53:29 +0200587 int z; //bbox: was int16
Denys Vlasenko11d00962017-01-15 00:12:42 +0100588
589 /* zero a as per default */
590 pstm_zero (a);
591
592 if (b < 0) {
593 return PSTM_OKAY;
594 }
595
596 z = b / DIGIT_BIT;
597 if (z >= PSTM_MAX_SIZE) {
598 return PS_LIMIT_FAIL;
599 }
600
601 /* set the used count of where the bit will go */
602 a->used = z + 1;
603
604 if (a->used > a->alloc) {
605 if (pstm_grow(a, a->used) != PSTM_OKAY) {
606 return PS_MEM_FAIL;
607 }
608 }
609
610 /* put the single bit in its place */
611 a->dp[z] = ((pstm_digit)1) << (b % DIGIT_BIT);
612 return PSTM_OKAY;
613}
614
615/******************************************************************************/
616/*
617
618*/
619int32 pstm_mul_2(pstm_int * a, pstm_int * b)
620{
621 int32 res;
Denys Vlasenko229d3c42017-04-03 21:53:29 +0200622 int x, oldused; //bbox: was int16
Denys Vlasenko11d00962017-01-15 00:12:42 +0100623
624/*
625 grow to accomodate result
626 */
627 if (b->alloc < a->used + 1) {
628 if ((res = pstm_grow (b, a->used + 1)) != PSTM_OKAY) {
629 return res;
630 }
631 }
632 oldused = b->used;
633 b->used = a->used;
634
635 {
636 register pstm_digit r, rr, *tmpa, *tmpb;
637
638 /* alias for source */
639 tmpa = a->dp;
640
641 /* alias for dest */
642 tmpb = b->dp;
643
644 /* carry */
645 r = 0;
646 for (x = 0; x < a->used; x++) {
647/*
648 get what will be the *next* carry bit from the
649 MSB of the current digit
650*/
651 rr = *tmpa >> ((pstm_digit)(DIGIT_BIT - 1));
652/*
653 now shift up this digit, add in the carry [from the previous]
654*/
655 *tmpb++ = ((*tmpa++ << ((pstm_digit)1)) | r);
656/*
657 copy the carry that would be from the source
658 digit into the next iteration
659*/
660 r = rr;
661 }
662
663 /* new leading digit? */
664 if (r != 0 && b->used != (PSTM_MAX_SIZE-1)) {
665 /* add a MSB which is always 1 at this point */
666 *tmpb = 1;
667 ++(b->used);
668 }
669/*
670 now zero any excess digits on the destination that we didn't write to
671*/
672 tmpb = b->dp + b->used;
673 for (x = b->used; x < oldused; x++) {
674 *tmpb++ = 0;
675 }
676 }
677 b->sign = a->sign;
678 return PSTM_OKAY;
679}
680
681/******************************************************************************/
682/*
683 unsigned subtraction ||a|| >= ||b|| ALWAYS!
684*/
685int32 s_pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c)
686{
Denys Vlasenko229d3c42017-04-03 21:53:29 +0200687 int oldbused, oldused; //bbox: was int16
Denys Vlasenko11d00962017-01-15 00:12:42 +0100688 int32 x;
689 pstm_word t;
690
691 if (b->used > a->used) {
692 return PS_LIMIT_FAIL;
693 }
694 if (c->alloc < a->used) {
695 if ((x = pstm_grow (c, a->used)) != PSTM_OKAY) {
696 return x;
697 }
698 }
699 oldused = c->used;
700 oldbused = b->used;
701 c->used = a->used;
702 t = 0;
703
704 for (x = 0; x < oldbused; x++) {
705 t = ((pstm_word)a->dp[x]) - (((pstm_word)b->dp[x]) + t);
706 c->dp[x] = (pstm_digit)t;
707 t = (t >> DIGIT_BIT)&1;
708 }
709 for (; x < a->used; x++) {
710 t = ((pstm_word)a->dp[x]) - t;
711 c->dp[x] = (pstm_digit)t;
712 t = (t >> DIGIT_BIT);
713 }
714 for (; x < oldused; x++) {
715 c->dp[x] = 0;
716 }
717 pstm_clamp(c);
718 return PSTM_OKAY;
719}
720
721/******************************************************************************/
722/*
723 unsigned addition
724*/
725static int32 s_pstm_add(pstm_int *a, pstm_int *b, pstm_int *c)
726{
Denys Vlasenko229d3c42017-04-03 21:53:29 +0200727 int x, y, oldused; //bbox: was int16
Denys Vlasenko11d00962017-01-15 00:12:42 +0100728 register pstm_word t, adp, bdp;
729
730 y = a->used;
731 if (b->used > y) {
732 y = b->used;
733 }
734 oldused = c->used;
735 c->used = y;
736
737 if (c->used > c->alloc) {
738 if (pstm_grow(c, c->used) != PSTM_OKAY) {
739 return PS_MEM_FAIL;
740 }
741 }
742
743 t = 0;
744 for (x = 0; x < y; x++) {
745 if (a->used < x) {
746 adp = 0;
747 } else {
748 adp = (pstm_word)a->dp[x];
749 }
750 if (b->used < x) {
751 bdp = 0;
752 } else {
753 bdp = (pstm_word)b->dp[x];
754 }
755 t += (adp) + (bdp);
756 c->dp[x] = (pstm_digit)t;
757 t >>= DIGIT_BIT;
758 }
759 if (t != 0 && x < PSTM_MAX_SIZE) {
760 if (c->used == c->alloc) {
761 if (pstm_grow(c, c->alloc + 1) != PSTM_OKAY) {
762 return PS_MEM_FAIL;
763 }
764 }
765 c->dp[c->used++] = (pstm_digit)t;
766 ++x;
767 }
768
769 c->used = x;
770 for (; x < oldused; x++) {
771 c->dp[x] = 0;
772 }
773 pstm_clamp(c);
774 return PSTM_OKAY;
775}
776
777
778/******************************************************************************/
779/*
780
781*/
782int32 pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c)
783{
Denys Vlasenko229d3c42017-04-03 21:53:29 +0200784 int32 res;
785 int sa, sb; //bbox: was int16
Denys Vlasenko11d00962017-01-15 00:12:42 +0100786
787 sa = a->sign;
788 sb = b->sign;
789
790 if (sa != sb) {
791/*
792 subtract a negative from a positive, OR a positive from a negative.
793 For both, ADD their magnitudes, and use the sign of the first number.
794 */
795 c->sign = sa;
796 if ((res = s_pstm_add (a, b, c)) != PSTM_OKAY) {
797 return res;
798 }
799 } else {
800/*
801 subtract a positive from a positive, OR a negative from a negative.
802 First, take the difference between their magnitudes, then...
803 */
804 if (pstm_cmp_mag (a, b) != PSTM_LT) {
805 /* Copy the sign from the first */
806 c->sign = sa;
807 /* The first has a larger or equal magnitude */
808 if ((res = s_pstm_sub (a, b, c)) != PSTM_OKAY) {
809 return res;
810 }
811 } else {
812 /* The result has the _opposite_ sign from the first number. */
813 c->sign = (sa == PSTM_ZPOS) ? PSTM_NEG : PSTM_ZPOS;
814 /* The second has a larger magnitude */
815 if ((res = s_pstm_sub (b, a, c)) != PSTM_OKAY) {
816 return res;
817 }
818 }
819 }
820 return PS_SUCCESS;
821}
822
823/******************************************************************************/
824/*
825 c = a - b
826*/
827int32 pstm_sub_d(psPool_t *pool, pstm_int *a, pstm_digit b, pstm_int *c)
828{
829 pstm_int tmp;
830 int32 res;
831
832 if (pstm_init_size(pool, &tmp, sizeof(pstm_digit)) != PSTM_OKAY) {
833 return PS_MEM_FAIL;
834 }
835 pstm_set(&tmp, b);
836 res = pstm_sub(a, &tmp, c);
837 pstm_clear(&tmp);
838 return res;
839}
840
841/******************************************************************************/
842/*
843 setups the montgomery reduction
844*/
845int32 pstm_montgomery_setup(pstm_int *a, pstm_digit *rho)
846{
847 pstm_digit x, b;
848
849/*
850 fast inversion mod 2**k
851 Based on the fact that
852 XA = 1 (mod 2**n) => (X(2-XA)) A = 1 (mod 2**2n)
853 => 2*X*A - X*X*A*A = 1
854 => 2*(1) - (1) = 1
855 */
856 b = a->dp[0];
857
858 if ((b & 1) == 0) {
859 psTraceCrypto("pstm_montogomery_setup failure\n");
860 return PS_ARG_FAIL;
861 }
862
863 x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
864 x *= 2 - b * x; /* here x*a==1 mod 2**8 */
865 x *= 2 - b * x; /* here x*a==1 mod 2**16 */
866 x *= 2 - b * x; /* here x*a==1 mod 2**32 */
867#ifdef PSTM_64BIT
868 x *= 2 - b * x; /* here x*a==1 mod 2**64 */
869#endif
870 /* rho = -1/m mod b */
871 *rho = (pstm_digit)(((pstm_word) 1 << ((pstm_word) DIGIT_BIT)) -
872 ((pstm_word)x));
873 return PSTM_OKAY;
874}
875
876/******************************************************************************/
877/*
878 * computes a = B**n mod b without division or multiplication useful for
879 * normalizing numbers in a Montgomery system.
880 */
881int32 pstm_montgomery_calc_normalization(pstm_int *a, pstm_int *b)
882{
883 int32 x;
Denys Vlasenko229d3c42017-04-03 21:53:29 +0200884 int bits; //bbox: was int16
Denys Vlasenko11d00962017-01-15 00:12:42 +0100885
886 /* how many bits of last digit does b use */
887 bits = pstm_count_bits (b) % DIGIT_BIT;
888 if (!bits) bits = DIGIT_BIT;
889
890 /* compute A = B^(n-1) * 2^(bits-1) */
891 if (b->used > 1) {
892 if ((x = pstm_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) !=
893 PSTM_OKAY) {
894 return x;
895 }
896 } else {
897 pstm_set(a, 1);
898 bits = 1;
899 }
900
901 /* now compute C = A * B mod b */
902 for (x = bits - 1; x < (int32)DIGIT_BIT; x++) {
903 if (pstm_mul_2 (a, a) != PSTM_OKAY) {
904 return PS_MEM_FAIL;
905 }
906 if (pstm_cmp_mag (a, b) != PSTM_LT) {
907 if (s_pstm_sub (a, b, a) != PSTM_OKAY) {
908 return PS_MEM_FAIL;
909 }
910 }
911 }
912 return PSTM_OKAY;
913}
914
915/******************************************************************************/
916/*
917 c = a * 2**d
918*/
Denys Vlasenko229d3c42017-04-03 21:53:29 +0200919static int32 pstm_mul_2d(pstm_int *a, int b, pstm_int *c)
Denys Vlasenko11d00962017-01-15 00:12:42 +0100920{
921 pstm_digit carry, carrytmp, shift;
Denys Vlasenko229d3c42017-04-03 21:53:29 +0200922 int x; //bbox: was int16
Denys Vlasenko11d00962017-01-15 00:12:42 +0100923
924 /* copy it */
925 if (pstm_copy(a, c) != PSTM_OKAY) {
926 return PS_MEM_FAIL;
927 }
928
929 /* handle whole digits */
930 if (b >= DIGIT_BIT) {
931 if (pstm_lshd(c, b/DIGIT_BIT) != PSTM_OKAY) {
932 return PS_MEM_FAIL;
933 }
934 }
935 b %= DIGIT_BIT;
936
937 /* shift the digits */
938 if (b != 0) {
939 carry = 0;
940 shift = DIGIT_BIT - b;
941 for (x = 0; x < c->used; x++) {
942 carrytmp = c->dp[x] >> shift;
943 c->dp[x] = (c->dp[x] << b) + carry;
944 carry = carrytmp;
945 }
946 /* store last carry if room */
947 if (carry && x < PSTM_MAX_SIZE) {
948 if (c->used == c->alloc) {
949 if (pstm_grow(c, c->alloc + 1) != PSTM_OKAY) {
950 return PS_MEM_FAIL;
951 }
952 }
953 c->dp[c->used++] = carry;
954 }
955 }
956 pstm_clamp(c);
957 return PSTM_OKAY;
958}
959
960/******************************************************************************/
961/*
962 c = a mod 2**d
963*/
Denys Vlasenko229d3c42017-04-03 21:53:29 +0200964static int32 pstm_mod_2d(pstm_int *a, int b, pstm_int *c) //bbox: was int16 b
Denys Vlasenko11d00962017-01-15 00:12:42 +0100965{
Denys Vlasenko229d3c42017-04-03 21:53:29 +0200966 int x; //bbox: was int16
Denys Vlasenko11d00962017-01-15 00:12:42 +0100967
968 /* zero if count less than or equal to zero */
969 if (b <= 0) {
970 pstm_zero(c);
971 return PSTM_OKAY;
972 }
973
974 /* get copy of input */
975 if (pstm_copy(a, c) != PSTM_OKAY) {
976 return PS_MEM_FAIL;
977 }
978
979 /* if 2**d is larger than we just return */
980 if (b >= (DIGIT_BIT * a->used)) {
981 return PSTM_OKAY;
982 }
983
984 /* zero digits above the last digit of the modulus */
985 for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++)
986 {
987 c->dp[x] = 0;
988 }
989 /* clear the digit that is not completely outside/inside the modulus */
990 c->dp[b / DIGIT_BIT] &= ~((pstm_digit)0) >> (DIGIT_BIT - b);
991 pstm_clamp (c);
992 return PSTM_OKAY;
993}
994
995
996/******************************************************************************/
997/*
998 c = a * b
999*/
1000int32 pstm_mul_d(pstm_int *a, pstm_digit b, pstm_int *c)
1001{
1002 pstm_word w;
1003 int32 res;
Denys Vlasenko229d3c42017-04-03 21:53:29 +02001004 int x, oldused; //bbox: was int16
Denys Vlasenko11d00962017-01-15 00:12:42 +01001005
1006 if (c->alloc < a->used + 1) {
1007 if ((res = pstm_grow (c, a->used + 1)) != PSTM_OKAY) {
1008 return res;
1009 }
1010 }
1011 oldused = c->used;
1012 c->used = a->used;
1013 c->sign = a->sign;
1014 w = 0;
1015 for (x = 0; x < a->used; x++) {
1016 w = ((pstm_word)a->dp[x]) * ((pstm_word)b) + w;
1017 c->dp[x] = (pstm_digit)w;
1018 w = w >> DIGIT_BIT;
1019 }
1020 if (w != 0 && (a->used != PSTM_MAX_SIZE)) {
1021 c->dp[c->used++] = (pstm_digit)w;
1022 ++x;
1023 }
1024 for (; x < oldused; x++) {
1025 c->dp[x] = 0;
1026 }
1027 pstm_clamp(c);
1028 return PSTM_OKAY;
1029}
1030
1031/******************************************************************************/
1032/*
1033 c = a / 2**b
1034*/
Denys Vlasenko229d3c42017-04-03 21:53:29 +02001035int32 pstm_div_2d(psPool_t *pool, pstm_int *a, int b, pstm_int *c,
Denys Vlasenko11d00962017-01-15 00:12:42 +01001036 pstm_int *d)
1037{
1038 pstm_digit D, r, rr;
1039 int32 res;
Denys Vlasenko229d3c42017-04-03 21:53:29 +02001040 int x; //bbox: was int16
Denys Vlasenko11d00962017-01-15 00:12:42 +01001041 pstm_int t;
1042
1043 /* if the shift count is <= 0 then we do no work */
1044 if (b <= 0) {
1045 if (pstm_copy (a, c) != PSTM_OKAY) {
1046 return PS_MEM_FAIL;
1047 }
1048 if (d != NULL) {
1049 pstm_zero (d);
1050 }
1051 return PSTM_OKAY;
1052 }
1053
1054 /* get the remainder */
1055 if (d != NULL) {
1056 if (pstm_init(pool, &t) != PSTM_OKAY) {
1057 return PS_MEM_FAIL;
1058 }
1059 if (pstm_mod_2d (a, b, &t) != PSTM_OKAY) {
1060 res = PS_MEM_FAIL;
1061 goto LBL_DONE;
1062 }
1063 }
1064
1065 /* copy */
1066 if (pstm_copy(a, c) != PSTM_OKAY) {
1067 res = PS_MEM_FAIL;
1068 goto LBL_DONE;
1069 }
1070
1071 /* shift by as many digits in the bit count */
1072 if (b >= (int32)DIGIT_BIT) {
1073 pstm_rshd (c, b / DIGIT_BIT);
1074 }
1075
1076 /* shift any bit count < DIGIT_BIT */
1077 D = (pstm_digit) (b % DIGIT_BIT);
1078 if (D != 0) {
1079 register pstm_digit *tmpc, mask, shift;
1080
1081 /* mask */
1082 mask = (((pstm_digit)1) << D) - 1;
1083
1084 /* shift for lsb */
1085 shift = DIGIT_BIT - D;
1086
1087 /* alias */
1088 tmpc = c->dp + (c->used - 1);
1089
1090 /* carry */
1091 r = 0;
1092 for (x = c->used - 1; x >= 0; x--) {
1093 /* get the lower bits of this word in a temp */
1094 rr = *tmpc & mask;
1095
1096 /* shift the current word and mix in the carry bits from previous */
1097 *tmpc = (*tmpc >> D) | (r << shift);
1098 --tmpc;
1099
1100 /* set the carry to the carry bits of the current word above */
1101 r = rr;
1102 }
1103 }
1104 pstm_clamp (c);
1105
1106 res = PSTM_OKAY;
1107LBL_DONE:
1108 if (d != NULL) {
1109 if (pstm_copy(&t, d) != PSTM_OKAY) {
1110 res = PS_MEM_FAIL;
1111 }
1112 pstm_clear(&t);
1113 }
1114 return res;
1115}
1116
1117/******************************************************************************/
1118/*
1119 b = a/2
1120*/
1121int32 pstm_div_2(pstm_int * a, pstm_int * b)
1122{
Denys Vlasenko229d3c42017-04-03 21:53:29 +02001123 int x, oldused; //bbox: was int16
Denys Vlasenko11d00962017-01-15 00:12:42 +01001124
1125 if (b->alloc < a->used) {
1126 if (pstm_grow(b, a->used) != PSTM_OKAY) {
1127 return PS_MEM_FAIL;
1128 }
1129 }
1130 oldused = b->used;
1131 b->used = a->used;
1132 {
1133 register pstm_digit r, rr, *tmpa, *tmpb;
1134
1135 /* source alias */
1136 tmpa = a->dp + b->used - 1;
1137
1138 /* dest alias */
1139 tmpb = b->dp + b->used - 1;
1140
1141 /* carry */
1142 r = 0;
1143 for (x = b->used - 1; x >= 0; x--) {
1144 /* get the carry for the next iteration */
1145 rr = *tmpa & 1;
1146
1147 /* shift the current digit, add in carry and store */
1148 *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1));
1149
1150 /* forward carry to next iteration */
1151 r = rr;
1152 }
1153
1154 /* zero excess digits */
1155 tmpb = b->dp + b->used;
1156 for (x = b->used; x < oldused; x++) {
1157 *tmpb++ = 0;
1158 }
1159 }
1160 b->sign = a->sign;
1161 pstm_clamp (b);
1162 return PSTM_OKAY;
1163}
1164
1165/******************************************************************************/
1166/*
1167 Creates "a" then copies b into it
1168 */
Denys Vlasenko229d3c42017-04-03 21:53:29 +02001169int32 pstm_init_copy(psPool_t *pool, pstm_int * a, pstm_int * b, int toSqr)
Denys Vlasenko11d00962017-01-15 00:12:42 +01001170{
Denys Vlasenko229d3c42017-04-03 21:53:29 +02001171 int x; //bbox: was int16
Denys Vlasenko11d00962017-01-15 00:12:42 +01001172 int32 res;
1173
1174 if (a == b) {
1175 return PSTM_OKAY;
1176 }
1177 x = b->alloc;
1178
1179 if (toSqr) {
1180/*
1181 Smart-size: Increasing size of a if b->used is roughly half
1182 of b->alloc because usage has shown that a lot of these copies
1183 go on to be squared and need these extra digits
1184*/
1185 if ((b->used * 2) + 2 >= x) {
1186 x = (b->used * 2) + 3;
1187 }
1188 }
1189 if ((res = pstm_init_size(pool, a, x)) != PSTM_OKAY) {
1190 return res;
1191 }
1192 return pstm_copy(b, a);
1193}
1194
1195/******************************************************************************/
1196/*
1197 With some compilers, we have seen issues linking with the builtin
1198 64 bit division routine. The issues with either manifest in a failure
1199 to find 'udivdi3' at link time, or a runtime invalid instruction fault
1200 during an RSA operation.
1201 The routine below divides a 64 bit unsigned int by a 32 bit unsigned int
1202 explicitly, rather than using the division operation
1203 The 64 bit result is placed in the 'numerator' parameter
1204 The 32 bit mod (remainder) of the division is the return parameter
1205 Based on implementations by:
1206 Copyright (C) 2003 Bernardo Innocenti <bernie@develer.com>
1207 Copyright (C) 1999 Hewlett-Packard Co
1208 Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
1209*/
1210#if defined(USE_MATRIX_DIV64) && defined(PSTM_32BIT)
1211static uint32 psDiv64(uint64 *numerator, uint32 denominator)
1212{
1213 uint64 rem = *numerator;
1214 uint64 b = denominator;
1215 uint64 res = 0;
1216 uint64 d = 1;
1217 uint32 high = rem >> 32;
1218
1219 if (high >= denominator) {
1220 high /= denominator;
1221 res = (uint64) high << 32;
1222 rem -= (uint64) (high * denominator) << 32;
1223 }
1224 while ((int64)b > 0 && b < rem) {
1225 b = b+b;
1226 d = d+d;
1227 }
1228 do {
1229 if (rem >= b) {
1230 rem -= b;
1231 res += d;
1232 }
1233 b >>= 1;
1234 d >>= 1;
1235 } while (d);
1236 *numerator = res;
1237 return rem;
1238}
1239#endif /* USE_MATRIX_DIV64 */
1240
1241#if defined(USE_MATRIX_DIV128) && defined(PSTM_64BIT)
1242typedef unsigned long uint128 __attribute__ ((mode(TI)));
1243static uint64 psDiv128(uint128 *numerator, uint64 denominator)
1244{
1245 uint128 rem = *numerator;
1246 uint128 b = denominator;
1247 uint128 res = 0;
1248 uint128 d = 1;
1249 uint64 high = rem >> 64;
1250
1251 if (high >= denominator) {
1252 high /= denominator;
1253 res = (uint128) high << 64;
1254 rem -= (uint128) (high * denominator) << 64;
1255 }
1256 while ((uint128)b > 0 && b < rem) {
1257 b = b+b;
1258 d = d+d;
1259 }
1260 do {
1261 if (rem >= b) {
1262 rem -= b;
1263 res += d;
1264 }
1265 b >>= 1;
1266 d >>= 1;
1267 } while (d);
1268 *numerator = res;
1269 return rem;
1270}
1271#endif /* USE_MATRIX_DIV128 */
1272
1273/******************************************************************************/
1274/*
1275 a/b => cb + d == a
1276*/
1277int32 pstm_div(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c,
1278 pstm_int *d)
1279{
1280 pstm_int q, x, y, t1, t2;
1281 int32 res;
Denys Vlasenko229d3c42017-04-03 21:53:29 +02001282 int n, t, i, norm, neg; //bbox: was int16
Denys Vlasenko11d00962017-01-15 00:12:42 +01001283
1284 /* is divisor zero ? */
1285 if (pstm_iszero (b) == 1) {
1286 return PS_LIMIT_FAIL;
1287 }
1288
1289 /* if a < b then q=0, r = a */
1290 if (pstm_cmp_mag (a, b) == PSTM_LT) {
1291 if (d != NULL) {
1292 if (pstm_copy(a, d) != PSTM_OKAY) {
1293 return PS_MEM_FAIL;
1294 }
1295 }
1296 if (c != NULL) {
1297 pstm_zero (c);
1298 }
1299 return PSTM_OKAY;
1300 }
1301/*
1302 Smart-size inits
1303*/
1304 if ((res = pstm_init_size(pool, &t1, a->alloc)) != PSTM_OKAY) {
1305 return res;
1306 }
1307 if ((res = pstm_init_size(pool, &t2, 3)) != PSTM_OKAY) {
1308 goto LBL_T1;
1309 }
1310 if ((res = pstm_init_copy(pool, &x, a, 0)) != PSTM_OKAY) {
1311 goto LBL_T2;
1312 }
1313/*
1314 Used to be an init_copy on b but pstm_grow was always hit with triple size
1315*/
1316 if ((res = pstm_init_size(pool, &y, b->used * 3)) != PSTM_OKAY) {
1317 goto LBL_X;
1318 }
1319 if ((res = pstm_copy(b, &y)) != PSTM_OKAY) {
1320 goto LBL_Y;
1321 }
1322
1323 /* fix the sign */
1324 neg = (a->sign == b->sign) ? PSTM_ZPOS : PSTM_NEG;
1325 x.sign = y.sign = PSTM_ZPOS;
1326
1327 /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */
1328 norm = pstm_count_bits(&y) % DIGIT_BIT;
1329 if (norm < (int32)(DIGIT_BIT-1)) {
1330 norm = (DIGIT_BIT-1) - norm;
1331 if ((res = pstm_mul_2d(&x, norm, &x)) != PSTM_OKAY) {
1332 goto LBL_Y;
1333 }
1334 if ((res = pstm_mul_2d(&y, norm, &y)) != PSTM_OKAY) {
1335 goto LBL_Y;
1336 }
1337 } else {
1338 norm = 0;
1339 }
1340
1341 /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */
1342 n = x.used - 1;
1343 t = y.used - 1;
1344
1345 if ((res = pstm_init_size(pool, &q, n - t + 1)) != PSTM_OKAY) {
1346 goto LBL_Y;
1347 }
1348 q.used = n - t + 1;
1349
1350 /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */
1351 if ((res = pstm_lshd(&y, n - t)) != PSTM_OKAY) { /* y = y*b**{n-t} */
1352 goto LBL_Q;
1353 }
1354
1355 while (pstm_cmp (&x, &y) != PSTM_LT) {
1356 ++(q.dp[n - t]);
1357 if ((res = pstm_sub(&x, &y, &x)) != PSTM_OKAY) {
1358 goto LBL_Q;
1359 }
1360 }
1361
1362 /* reset y by shifting it back down */
1363 pstm_rshd (&y, n - t);
1364
1365 /* step 3. for i from n down to (t + 1) */
1366 for (i = n; i >= (t + 1); i--) {
1367 if (i > x.used) {
1368 continue;
1369 }
1370
1371 /* step 3.1 if xi == yt then set q{i-t-1} to b-1,
1372 * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */
1373 if (x.dp[i] == y.dp[t]) {
1374 q.dp[i - t - 1] = (pstm_digit)((((pstm_word)1) << DIGIT_BIT) - 1);
1375 } else {
1376 pstm_word tmp;
1377 tmp = ((pstm_word) x.dp[i]) << ((pstm_word) DIGIT_BIT);
1378 tmp |= ((pstm_word) x.dp[i - 1]);
1379#if defined(USE_MATRIX_DIV64) && defined(PSTM_32BIT)
1380 psDiv64(&tmp, y.dp[t]);
1381#elif defined(USE_MATRIX_DIV128) && defined(PSTM_64BIT)
1382 psDiv128(&tmp, y.dp[t]);
1383#else
1384 tmp /= ((pstm_word) y.dp[t]);
1385#endif /* USE_MATRIX_DIV64 */
1386 q.dp[i - t - 1] = (pstm_digit) (tmp);
1387 }
1388
1389 /* while (q{i-t-1} * (yt * b + y{t-1})) >
1390 xi * b**2 + xi-1 * b + xi-2
1391
1392 do q{i-t-1} -= 1;
1393 */
1394 q.dp[i - t - 1] = (q.dp[i - t - 1] + 1);
1395 do {
1396 q.dp[i - t - 1] = (q.dp[i - t - 1] - 1);
1397
1398 /* find left hand */
1399 pstm_zero (&t1);
1400 t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1];
1401 t1.dp[1] = y.dp[t];
1402 t1.used = 2;
1403 if ((res = pstm_mul_d (&t1, q.dp[i - t - 1], &t1)) != PSTM_OKAY) {
1404 goto LBL_Q;
1405 }
1406
1407 /* find right hand */
1408 t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2];
1409 t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1];
1410 t2.dp[2] = x.dp[i];
1411 t2.used = 3;
1412 } while (pstm_cmp_mag(&t1, &t2) == PSTM_GT);
1413
1414 /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */
1415 if ((res = pstm_mul_d(&y, q.dp[i - t - 1], &t1)) != PSTM_OKAY) {
1416 goto LBL_Q;
1417 }
1418
1419 if ((res = pstm_lshd(&t1, i - t - 1)) != PSTM_OKAY) {
1420 goto LBL_Q;
1421 }
1422
1423 if ((res = pstm_sub(&x, &t1, &x)) != PSTM_OKAY) {
1424 goto LBL_Q;
1425 }
1426
1427 /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */
1428 if (x.sign == PSTM_NEG) {
1429 if ((res = pstm_copy(&y, &t1)) != PSTM_OKAY) {
1430 goto LBL_Q;
1431 }
1432 if ((res = pstm_lshd (&t1, i - t - 1)) != PSTM_OKAY) {
1433 goto LBL_Q;
1434 }
1435 if ((res = pstm_add (&x, &t1, &x)) != PSTM_OKAY) {
1436 goto LBL_Q;
1437 }
1438 q.dp[i - t - 1] = q.dp[i - t - 1] - 1;
1439 }
1440 }
1441/*
1442 now q is the quotient and x is the remainder (which we have to normalize)
1443*/
1444 /* get sign before writing to c */
1445 x.sign = x.used == 0 ? PSTM_ZPOS : a->sign;
1446
1447 if (c != NULL) {
1448 pstm_clamp (&q);
1449 if (pstm_copy (&q, c) != PSTM_OKAY) {
1450 res = PS_MEM_FAIL;
1451 goto LBL_Q;
1452 }
1453 c->sign = neg;
1454 }
1455
1456 if (d != NULL) {
1457 if ((res = pstm_div_2d (pool, &x, norm, &x, NULL)) != PSTM_OKAY) {
1458 goto LBL_Q;
1459 }
1460/*
1461 the following is a kludge, essentially we were seeing the right
1462 remainder but with excess digits that should have been zero
1463 */
1464 for (i = b->used; i < x.used; i++) {
1465 x.dp[i] = 0;
1466 }
1467 pstm_clamp(&x);
1468 if (pstm_copy (&x, d) != PSTM_OKAY) {
1469 res = PS_MEM_FAIL;
1470 goto LBL_Q;
1471 }
1472 }
1473
1474 res = PSTM_OKAY;
1475
1476LBL_Q:pstm_clear (&q);
1477LBL_Y:pstm_clear (&y);
1478LBL_X:pstm_clear (&x);
1479LBL_T2:pstm_clear (&t2);
1480LBL_T1:pstm_clear (&t1);
1481
1482 return res;
1483}
1484
1485/******************************************************************************/
1486/*
1487 Swap the elements of two integers, for cases where you can't simply swap
1488 the pstm_int pointers around
1489*/
1490void pstm_exch(pstm_int * a, pstm_int * b)
1491{
1492 pstm_int t;
1493
1494 t = *a;
1495 *a = *b;
1496 *b = t;
1497}
1498
1499/******************************************************************************/
1500/*
1501 c = a mod b, 0 <= c < b
1502*/
1503int32 pstm_mod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c)
1504{
1505 pstm_int t;
1506 int32 err;
1507/*
1508 Smart-size
1509*/
1510 if ((err = pstm_init_size(pool, &t, b->alloc)) != PSTM_OKAY) {
1511 return err;
1512 }
1513 if ((err = pstm_div(pool, a, b, NULL, &t)) != PSTM_OKAY) {
1514 pstm_clear (&t);
1515 return err;
1516 }
1517 if (t.sign != b->sign) {
1518 err = pstm_add(&t, b, c);
1519 } else {
1520 pstm_exch (&t, c);
1521 }
1522 pstm_clear (&t);
1523 return err;
1524}
1525
1526/******************************************************************************/
1527/*
1528 d = a * b (mod c)
1529*/
1530int32 pstm_mulmod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c,
1531 pstm_int *d)
1532{
1533 int32 res;
Denys Vlasenko229d3c42017-04-03 21:53:29 +02001534 int size; //bbox: was int16
Denys Vlasenko11d00962017-01-15 00:12:42 +01001535 pstm_int tmp;
1536
1537/*
1538 Smart-size pstm_inits. d is an output that is influenced by this local 't'
1539 so don't shrink 'd' if it wants to becuase this will lead to an pstm_grow
1540 in RSA operations
1541*/
1542 size = a->used + b->used + 1;
1543 if ((a == d) && (size < a->alloc)) {
1544 size = a->alloc;
1545 }
1546 if ((res = pstm_init_size(pool, &tmp, size)) != PSTM_OKAY) {
1547 return res;
1548 }
1549 if ((res = pstm_mul_comba(pool, a, b, &tmp, NULL, 0)) != PSTM_OKAY) {
1550 pstm_clear(&tmp);
1551 return res;
1552 }
1553 res = pstm_mod(pool, &tmp, c, d);
1554 pstm_clear(&tmp);
1555 return res;
1556}
1557
1558/******************************************************************************/
1559/*
1560 * y = g**x (mod b)
1561 * Some restrictions... x must be positive and < b
1562 */
1563int32 pstm_exptmod(psPool_t *pool, pstm_int *G, pstm_int *X, pstm_int *P,
1564 pstm_int *Y)
1565{
1566 pstm_int M[32], res; /* Keep this winsize based: (1 << max_winsize) */
1567 pstm_digit buf, mp;
1568 pstm_digit *paD;
1569 int32 err, bitbuf;
Denys Vlasenko229d3c42017-04-03 21:53:29 +02001570 int bitcpy, bitcnt, mode, digidx, x, y, winsize; //bbox: was int16
Denys Vlasenko11d00962017-01-15 00:12:42 +01001571 uint32 paDlen;
1572
1573 /* set window size from what user set as optimization */
1574 x = pstm_count_bits(X);
1575 if (x < 50) {
1576 winsize = 2;
1577 } else {
1578 winsize = PS_EXPTMOD_WINSIZE;
1579 }
1580
1581 /* now setup montgomery */
1582 if ((err = pstm_montgomery_setup (P, &mp)) != PSTM_OKAY) {
1583 return err;
1584 }
1585
1586 /* setup result */
1587 if ((err = pstm_init_size(pool, &res, (P->used * 2) + 1)) != PSTM_OKAY) {
1588 return err;
1589 }
1590/*
1591 create M table
1592 The M table contains powers of the input base, e.g. M[x] = G^x mod P
1593 The first half of the table is not computed though except for M[0] and M[1]
1594 */
1595 /* now we need R mod m */
1596 if ((err = pstm_montgomery_calc_normalization (&res, P)) != PSTM_OKAY) {
1597 goto LBL_RES;
1598 }
1599/*
1600 init M array
1601 init first cell
1602 */
1603 if ((err = pstm_init_size(pool, &M[1], res.used)) != PSTM_OKAY) {
1604 goto LBL_RES;
1605 }
1606
1607 /* now set M[1] to G * R mod m */
1608 if (pstm_cmp_mag(P, G) != PSTM_GT) {
1609 /* G > P so we reduce it first */
1610 if ((err = pstm_mod(pool, G, P, &M[1])) != PSTM_OKAY) {
1611 goto LBL_M;
1612 }
1613 } else {
1614 if ((err = pstm_copy(G, &M[1])) != PSTM_OKAY) {
1615 goto LBL_M;
1616 }
1617 }
1618 if ((err = pstm_mulmod (pool, &M[1], &res, P, &M[1])) != PSTM_OKAY) {
1619 goto LBL_M;
1620 }
1621/*
1622 Pre-allocated digit. Used for mul, sqr, AND reduce
1623*/
1624 paDlen = ((M[1].used + 3) * 2) * sizeof(pstm_digit);
Denys Vlasenko6b1b0042017-01-19 15:51:00 +01001625 paD = xzalloc(paDlen);//bbox
Denys Vlasenko11d00962017-01-15 00:12:42 +01001626/*
Denys Vlasenko876c1212017-03-24 15:00:12 +01001627 compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times
Denys Vlasenko11d00962017-01-15 00:12:42 +01001628 */
1629 if (pstm_init_copy(pool, &M[1 << (winsize - 1)], &M[1], 1) != PSTM_OKAY) {
1630 err = PS_MEM_FAIL;
1631 goto LBL_PAD;
1632 }
1633 for (x = 0; x < (winsize - 1); x++) {
1634 if ((err = pstm_sqr_comba (pool, &M[1 << (winsize - 1)],
1635 &M[1 << (winsize - 1)], paD, paDlen)) != PSTM_OKAY) {
1636 goto LBL_PAD;
1637 }
1638 if ((err = pstm_montgomery_reduce(pool, &M[1 << (winsize - 1)], P, mp,
1639 paD, paDlen)) != PSTM_OKAY) {
1640 goto LBL_PAD;
1641 }
1642 }
1643/*
1644 now init the second half of the array
1645*/
1646 for (x = (1<<(winsize-1)) + 1; x < (1 << winsize); x++) {
1647 if ((err = pstm_init_size(pool, &M[x], M[1<<(winsize-1)].alloc + 1))
1648 != PSTM_OKAY) {
1649 for (y = 1<<(winsize-1); y < x; y++) {
1650 pstm_clear(&M[y]);
1651 }
1652 goto LBL_PAD;
1653 }
1654 }
1655
1656 /* create upper table */
1657 for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
1658 if ((err = pstm_mul_comba(pool, &M[x - 1], &M[1], &M[x], paD, paDlen))
1659 != PSTM_OKAY) {
1660 goto LBL_MARRAY;
1661 }
1662 if ((err = pstm_montgomery_reduce(pool, &M[x], P, mp, paD, paDlen)) !=
1663 PSTM_OKAY) {
1664 goto LBL_MARRAY;
1665 }
1666 }
1667
1668 /* set initial mode and bit cnt */
1669 mode = 0;
1670 bitcnt = 1;
1671 buf = 0;
1672 digidx = X->used - 1;
1673 bitcpy = 0;
1674 bitbuf = 0;
1675
1676 for (;;) {
1677 /* grab next digit as required */
1678 if (--bitcnt == 0) {
1679 /* if digidx == -1 we are out of digits so break */
1680 if (digidx == -1) {
1681 break;
1682 }
1683 /* read next digit and reset bitcnt */
1684 buf = X->dp[digidx--];
1685 bitcnt = (int32)DIGIT_BIT;
1686 }
1687
1688 /* grab the next msb from the exponent */
1689 y = (pstm_digit)(buf >> (DIGIT_BIT - 1)) & 1;
1690 buf <<= (pstm_digit)1;
1691/*
1692 If the bit is zero and mode == 0 then we ignore it.
1693 These represent the leading zero bits before the first 1 bit
1694 in the exponent. Technically this opt is not required but it
1695 does lower the # of trivial squaring/reductions used
1696*/
1697 if (mode == 0 && y == 0) {
1698 continue;
1699 }
1700
1701 /* if the bit is zero and mode == 1 then we square */
1702 if (mode == 1 && y == 0) {
1703 if ((err = pstm_sqr_comba(pool, &res, &res, paD, paDlen)) !=
1704 PSTM_OKAY) {
1705 goto LBL_MARRAY;
1706 }
1707 if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD, paDlen))
1708 != PSTM_OKAY) {
1709 goto LBL_MARRAY;
1710 }
1711 continue;
1712 }
1713
1714 /* else we add it to the window */
1715 bitbuf |= (y << (winsize - ++bitcpy));
1716 mode = 2;
1717
1718 if (bitcpy == winsize) {
1719 /* ok window is filled so square as required and mul square first */
1720 for (x = 0; x < winsize; x++) {
1721 if ((err = pstm_sqr_comba(pool, &res, &res, paD, paDlen)) !=
1722 PSTM_OKAY) {
1723 goto LBL_MARRAY;
1724 }
1725 if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD,
1726 paDlen)) != PSTM_OKAY) {
1727 goto LBL_MARRAY;
1728 }
1729 }
1730
1731 /* then multiply */
1732 if ((err = pstm_mul_comba(pool, &res, &M[bitbuf], &res, paD,
1733 paDlen)) != PSTM_OKAY) {
1734 goto LBL_MARRAY;
1735 }
1736 if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD, paDlen))
1737 != PSTM_OKAY) {
1738 goto LBL_MARRAY;
1739 }
1740
1741 /* empty window and reset */
1742 bitcpy = 0;
1743 bitbuf = 0;
1744 mode = 1;
1745 }
1746 }
1747
1748 /* if bits remain then square/multiply */
1749 if (mode == 2 && bitcpy > 0) {
1750 /* square then multiply if the bit is set */
1751 for (x = 0; x < bitcpy; x++) {
1752 if ((err = pstm_sqr_comba(pool, &res, &res, paD, paDlen)) !=
1753 PSTM_OKAY) {
1754 goto LBL_MARRAY;
1755 }
1756 if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD, paDlen))
1757 != PSTM_OKAY) {
1758 goto LBL_MARRAY;
1759 }
1760
1761 /* get next bit of the window */
1762 bitbuf <<= 1;
1763 if ((bitbuf & (1 << winsize)) != 0) {
1764 /* then multiply */
1765 if ((err = pstm_mul_comba(pool, &res, &M[1], &res, paD, paDlen))
1766 != PSTM_OKAY) {
1767 goto LBL_MARRAY;
1768 }
1769 if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD,
1770 paDlen)) != PSTM_OKAY) {
1771 goto LBL_MARRAY;
1772 }
1773 }
1774 }
1775 }
1776/*
1777 Fix up result if Montgomery reduction is used recall that any value in a
1778 Montgomery system is actually multiplied by R mod n. So we have to reduce
1779 one more time to cancel out the factor of R.
1780*/
1781 if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD, paDlen)) !=
1782 PSTM_OKAY) {
1783 goto LBL_MARRAY;
1784 }
1785 /* swap res with Y */
1786 if ((err = pstm_copy (&res, Y)) != PSTM_OKAY) {
1787 goto LBL_MARRAY;
1788 }
1789 err = PSTM_OKAY;
1790LBL_MARRAY:
1791 for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
1792 pstm_clear(&M[x]);
1793 }
1794LBL_PAD:psFree(paD, pool);
1795LBL_M: pstm_clear(&M[1]);
1796LBL_RES:pstm_clear(&res);
1797 return err;
1798}
1799
1800/******************************************************************************/
1801/*
1802
1803*/
1804int32 pstm_add(pstm_int *a, pstm_int *b, pstm_int *c)
1805{
1806 int32 res;
Denys Vlasenko229d3c42017-04-03 21:53:29 +02001807 int sa, sb; //bbox: was int16
Denys Vlasenko11d00962017-01-15 00:12:42 +01001808
1809 /* get sign of both inputs */
1810 sa = a->sign;
1811 sb = b->sign;
1812
1813 /* handle two cases, not four */
1814 if (sa == sb) {
1815 /* both positive or both negative, add their mags, copy the sign */
1816 c->sign = sa;
1817 if ((res = s_pstm_add (a, b, c)) != PSTM_OKAY) {
1818 return res;
1819 }
Denys Vlasenko229d3c42017-04-03 21:53:29 +02001820 } else {
Denys Vlasenko11d00962017-01-15 00:12:42 +01001821/*
1822 one positive, the other negative
1823 subtract the one with the greater magnitude from the one of the lesser
1824 magnitude. The result gets the sign of the one with the greater mag.
1825 */
1826 if (pstm_cmp_mag (a, b) == PSTM_LT) {
1827 c->sign = sb;
1828 if ((res = s_pstm_sub (b, a, c)) != PSTM_OKAY) {
1829 return res;
1830 }
1831 } else {
1832 c->sign = sa;
1833 if ((res = s_pstm_sub (a, b, c)) != PSTM_OKAY) {
1834 return res;
1835 }
1836 }
1837 }
1838 return PS_SUCCESS;
1839}
1840
1841/******************************************************************************/
1842/*
1843 reverse an array, used for radix code
1844*/
Denys Vlasenko229d3c42017-04-03 21:53:29 +02001845static void pstm_reverse (unsigned char *s, int len) //bbox: was int16 len
Denys Vlasenko11d00962017-01-15 00:12:42 +01001846{
1847 int32 ix, iy;
1848 unsigned char t;
1849
1850 ix = 0;
1851 iy = len - 1;
1852 while (ix < iy) {
1853 t = s[ix];
1854 s[ix] = s[iy];
1855 s[iy] = t;
1856 ++ix;
1857 --iy;
1858 }
1859}
1860/******************************************************************************/
1861/*
1862 No reverse. Useful in some of the EIP-154 PKA stuff where special byte
1863 order seems to come into play more often
1864*/
1865int32 pstm_to_unsigned_bin_nr(psPool_t *pool, pstm_int *a, unsigned char *b)
1866{
1867 int32 res;
Denys Vlasenko229d3c42017-04-03 21:53:29 +02001868 int x; //bbox: was int16
Denys Vlasenko11d00962017-01-15 00:12:42 +01001869 pstm_int t = { 0 };
1870
1871 if ((res = pstm_init_copy(pool, &t, a, 0)) != PSTM_OKAY) {
1872 return res;
1873 }
1874
1875 x = 0;
1876 while (pstm_iszero (&t) == 0) {
1877 b[x++] = (unsigned char) (t.dp[0] & 255);
1878 if ((res = pstm_div_2d (pool, &t, 8, &t, NULL)) != PSTM_OKAY) {
1879 pstm_clear(&t);
1880 return res;
1881 }
1882 }
1883 pstm_clear(&t);
1884 return PS_SUCCESS;
1885}
1886/******************************************************************************/
1887/*
1888
1889*/
1890int32 pstm_to_unsigned_bin(psPool_t *pool, pstm_int *a, unsigned char *b)
1891{
1892 int32 res;
Denys Vlasenko229d3c42017-04-03 21:53:29 +02001893 int x; //bbox: was int16
Denys Vlasenko11d00962017-01-15 00:12:42 +01001894 pstm_int t = { 0 };
1895
1896 if ((res = pstm_init_copy(pool, &t, a, 0)) != PSTM_OKAY) {
1897 return res;
1898 }
1899
1900 x = 0;
1901 while (pstm_iszero (&t) == 0) {
1902 b[x++] = (unsigned char) (t.dp[0] & 255);
1903 if ((res = pstm_div_2d (pool, &t, 8, &t, NULL)) != PSTM_OKAY) {
1904 pstm_clear(&t);
1905 return res;
1906 }
1907 }
1908 pstm_reverse (b, x);
1909 pstm_clear(&t);
1910 return PS_SUCCESS;
1911}
1912
1913/******************************************************************************/
1914/*
1915 compare against a single digit
1916*/
1917int32 pstm_cmp_d(pstm_int *a, pstm_digit b)
1918{
1919 /* compare based on sign */
1920 if ((b && a->used == 0) || a->sign == PSTM_NEG) {
1921 return PSTM_LT;
1922 }
1923
1924 /* compare based on magnitude */
1925 if (a->used > 1) {
1926 return PSTM_GT;
1927 }
1928
1929 /* compare the only digit of a to b */
1930 if (a->dp[0] > b) {
1931 return PSTM_GT;
1932 } else if (a->dp[0] < b) {
1933 return PSTM_LT;
1934 } else {
1935 return PSTM_EQ;
1936 }
1937}
1938
1939/*
1940 Need invmod for ECC and also private key loading for hardware crypto
1941 in cases where dQ > dP. The values must be switched and a new qP must be
1942 calculated using this function
1943*/
Denys Vlasenko6b1b0042017-01-19 15:51:00 +01001944//bbox: pool unused
1945#define pstm_invmod_slow(pool, a, b, c) \
1946 pstm_invmod_slow( a, b, c)
Denys Vlasenko11d00962017-01-15 00:12:42 +01001947static int32 pstm_invmod_slow(psPool_t *pool, pstm_int * a, pstm_int * b,
1948 pstm_int * c)
1949{
1950 pstm_int x, y, u, v, A, B, C, D;
1951 int32 res;
1952
1953 /* b cannot be negative */
1954 if (b->sign == PSTM_NEG || pstm_iszero(b) == 1) {
1955 return PS_LIMIT_FAIL;
1956 }
1957
1958 /* init temps */
1959 if (pstm_init_size(pool, &x, b->used) != PSTM_OKAY) {
1960 return PS_MEM_FAIL;
1961 }
1962
1963 /* x = a, y = b */
1964 if ((res = pstm_mod(pool, a, b, &x)) != PSTM_OKAY) {
1965 goto LBL_X;
1966 }
1967
1968 if (pstm_init_copy(pool, &y, b, 0) != PSTM_OKAY) {
1969 goto LBL_X;
1970 }
1971
1972 /* 2. [modified] if x,y are both even then return an error! */
1973 if (pstm_iseven (&x) == 1 && pstm_iseven (&y) == 1) {
1974 res = PS_FAILURE;
1975 goto LBL_Y;
1976 }
1977
1978 /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
1979 if ((res = pstm_init_copy(pool, &u, &x, 0)) != PSTM_OKAY) {
1980 goto LBL_Y;
1981 }
1982 if ((res = pstm_init_copy(pool, &v, &y, 0)) != PSTM_OKAY) {
1983 goto LBL_U;
1984 }
1985
1986 if ((res = pstm_init_size(pool, &A, sizeof(pstm_digit))) != PSTM_OKAY) {
1987 goto LBL_V;
1988 }
1989
1990 if ((res = pstm_init_size(pool, &D, sizeof(pstm_digit))) != PSTM_OKAY) {
1991 goto LBL_A;
1992 }
1993 pstm_set (&A, 1);
1994 pstm_set (&D, 1);
1995
1996 if ((res = pstm_init(pool, &B)) != PSTM_OKAY) {
1997 goto LBL_D;
1998 }
1999 if ((res = pstm_init(pool, &C)) != PSTM_OKAY) {
2000 goto LBL_B;
2001 }
2002
2003top:
2004 /* 4. while u is even do */
2005 while (pstm_iseven (&u) == 1) {
2006 /* 4.1 u = u/2 */
2007 if ((res = pstm_div_2 (&u, &u)) != PSTM_OKAY) {
2008 goto LBL_C;
2009 }
2010
2011 /* 4.2 if A or B is odd then */
2012 if (pstm_isodd (&A) == 1 || pstm_isodd (&B) == 1) {
2013 /* A = (A+y)/2, B = (B-x)/2 */
2014 if ((res = pstm_add (&A, &y, &A)) != PSTM_OKAY) {
2015 goto LBL_C;
2016 }
2017 if ((res = pstm_sub (&B, &x, &B)) != PSTM_OKAY) {
2018 goto LBL_C;
2019 }
2020 }
2021 /* A = A/2, B = B/2 */
2022 if ((res = pstm_div_2 (&A, &A)) != PSTM_OKAY) {
2023 goto LBL_C;
2024 }
2025 if ((res = pstm_div_2 (&B, &B)) != PSTM_OKAY) {
2026 goto LBL_C;
2027 }
2028 }
2029
2030 /* 5. while v is even do */
2031 while (pstm_iseven (&v) == 1) {
2032 /* 5.1 v = v/2 */
2033 if ((res = pstm_div_2 (&v, &v)) != PSTM_OKAY) {
2034 goto LBL_C;
2035 }
2036
2037 /* 5.2 if C or D is odd then */
2038 if (pstm_isodd (&C) == 1 || pstm_isodd (&D) == 1) {
2039 /* C = (C+y)/2, D = (D-x)/2 */
2040 if ((res = pstm_add (&C, &y, &C)) != PSTM_OKAY) {
2041 goto LBL_C;
2042 }
2043 if ((res = pstm_sub (&D, &x, &D)) != PSTM_OKAY) {
2044 goto LBL_C;
2045 }
2046 }
2047 /* C = C/2, D = D/2 */
2048 if ((res = pstm_div_2 (&C, &C)) != PSTM_OKAY) {
2049 goto LBL_C;
2050 }
2051 if ((res = pstm_div_2 (&D, &D)) != PSTM_OKAY) {
2052 goto LBL_C;
2053 }
2054 }
2055
2056 /* 6. if u >= v then */
2057 if (pstm_cmp (&u, &v) != PSTM_LT) {
2058 /* u = u - v, A = A - C, B = B - D */
2059 if ((res = pstm_sub (&u, &v, &u)) != PSTM_OKAY) {
2060 goto LBL_C;
2061 }
2062 if ((res = pstm_sub (&A, &C, &A)) != PSTM_OKAY) {
2063 goto LBL_C;
2064 }
2065 if ((res = pstm_sub (&B, &D, &B)) != PSTM_OKAY) {
2066 goto LBL_C;
2067 }
2068 } else {
2069 /* v - v - u, C = C - A, D = D - B */
2070 if ((res = pstm_sub (&v, &u, &v)) != PSTM_OKAY) {
2071 goto LBL_C;
2072 }
2073 if ((res = pstm_sub (&C, &A, &C)) != PSTM_OKAY) {
2074 goto LBL_C;
2075 }
2076 if ((res = pstm_sub (&D, &B, &D)) != PSTM_OKAY) {
2077 goto LBL_C;
2078 }
2079 }
2080
2081 /* if not zero goto step 4 */
2082 if (pstm_iszero (&u) == 0)
2083 goto top;
2084
2085 /* now a = C, b = D, gcd == g*v */
2086
2087 /* if v != 1 then there is no inverse */
2088 if (pstm_cmp_d (&v, 1) != PSTM_EQ) {
2089 res = PS_FAILURE;
2090 goto LBL_C;
2091 }
2092
2093 /* if its too low */
2094 while (pstm_cmp_d(&C, 0) == PSTM_LT) {
2095 if ((res = pstm_add(&C, b, &C)) != PSTM_OKAY) {
2096 goto LBL_C;
2097 }
2098 }
2099
2100 /* too big */
2101 while (pstm_cmp_mag(&C, b) != PSTM_LT) {
2102 if ((res = pstm_sub(&C, b, &C)) != PSTM_OKAY) {
2103 goto LBL_C;
2104 }
2105 }
2106
2107 /* C is now the inverse */
2108 if ((res = pstm_copy(&C, c)) != PSTM_OKAY) {
2109 goto LBL_C;
2110 }
2111 res = PSTM_OKAY;
2112
2113LBL_C: pstm_clear(&C);
2114LBL_D: pstm_clear(&D);
2115LBL_B: pstm_clear(&B);
2116LBL_A: pstm_clear(&A);
2117LBL_V: pstm_clear(&v);
2118LBL_U: pstm_clear(&u);
2119LBL_Y: pstm_clear(&y);
2120LBL_X: pstm_clear(&x);
2121
2122 return res;
2123}
2124
2125/* c = 1/a (mod b) for odd b only */
2126int32 pstm_invmod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c)
2127{
2128 pstm_int x, y, u, v, B, D;
2129 int32 res;
Denys Vlasenko3d7ec482017-07-15 17:19:38 +02002130 int neg, sanity; //bbox: was uint16
Denys Vlasenko11d00962017-01-15 00:12:42 +01002131
2132 /* 2. [modified] b must be odd */
2133 if (pstm_iseven (b) == 1) {
2134 return pstm_invmod_slow(pool, a,b,c);
2135 }
2136
2137 /* x == modulus, y == value to invert */
2138 if ((res = pstm_init_copy(pool, &x, b, 0)) != PSTM_OKAY) {
2139 return res;
2140 }
2141
2142 if ((res = pstm_init_size(pool, &y, a->alloc)) != PSTM_OKAY) {
2143 goto LBL_X;
2144 }
2145
2146 /* we need y = |a| */
2147 pstm_abs(a, &y);
2148
2149 /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
2150 if ((res = pstm_init_copy(pool, &u, &x, 0)) != PSTM_OKAY) {
2151 goto LBL_Y;
2152 }
2153 if ((res = pstm_init_copy(pool, &v, &y, 0)) != PSTM_OKAY) {
2154 goto LBL_U;
2155 }
2156 if ((res = pstm_init(pool, &B)) != PSTM_OKAY) {
2157 goto LBL_V;
2158 }
2159 if ((res = pstm_init(pool, &D)) != PSTM_OKAY) {
2160 goto LBL_B;
2161 }
2162
2163 pstm_set (&D, 1);
2164
2165 sanity = 0;
2166top:
2167 /* 4. while u is even do */
2168 while (pstm_iseven (&u) == 1) {
2169 /* 4.1 u = u/2 */
2170 if ((res = pstm_div_2 (&u, &u)) != PSTM_OKAY) {
2171 goto LBL_D;
2172 }
2173
2174 /* 4.2 if B is odd then */
2175 if (pstm_isodd (&B) == 1) {
2176 if ((res = pstm_sub (&B, &x, &B)) != PSTM_OKAY) {
2177 goto LBL_D;
2178 }
2179 }
2180 /* B = B/2 */
2181 if ((res = pstm_div_2 (&B, &B)) != PSTM_OKAY) {
2182 goto LBL_D;
2183 }
2184 }
2185
2186 /* 5. while v is even do */
2187 while (pstm_iseven (&v) == 1) {
2188 /* 5.1 v = v/2 */
2189 if ((res = pstm_div_2 (&v, &v)) != PSTM_OKAY) {
2190 goto LBL_D;
2191 }
2192 /* 5.2 if D is odd then */
2193 if (pstm_isodd (&D) == 1) {
2194 /* D = (D-x)/2 */
2195 if ((res = pstm_sub (&D, &x, &D)) != PSTM_OKAY) {
2196 goto LBL_D;
2197 }
2198 }
2199 /* D = D/2 */
2200 if ((res = pstm_div_2 (&D, &D)) != PSTM_OKAY) {
2201 goto LBL_D;
2202 }
2203 }
2204
2205 /* 6. if u >= v then */
2206 if (pstm_cmp (&u, &v) != PSTM_LT) {
2207 /* u = u - v, B = B - D */
2208 if ((res = pstm_sub (&u, &v, &u)) != PSTM_OKAY) {
2209 goto LBL_D;
2210 }
2211 if ((res = pstm_sub (&B, &D, &B)) != PSTM_OKAY) {
2212 goto LBL_D;
2213 }
2214 } else {
2215 /* v - v - u, D = D - B */
2216 if ((res = pstm_sub (&v, &u, &v)) != PSTM_OKAY) {
2217 goto LBL_D;
2218 }
2219 if ((res = pstm_sub (&D, &B, &D)) != PSTM_OKAY) {
2220 goto LBL_D;
2221 }
2222 }
2223
2224 /* if not zero goto step 4 */
2225 if (sanity++ > 1000) {
2226 res = PS_LIMIT_FAIL;
2227 goto LBL_D;
2228 }
2229 if (pstm_iszero (&u) == 0) {
2230 goto top;
2231 }
2232
2233 /* now a = C, b = D, gcd == g*v */
2234
2235 /* if v != 1 then there is no inverse */
2236 if (pstm_cmp_d (&v, 1) != PSTM_EQ) {
2237 res = PS_FAILURE;
2238 goto LBL_D;
2239 }
2240
2241 /* b is now the inverse */
2242 neg = a->sign;
2243 while (D.sign == PSTM_NEG) {
2244 if ((res = pstm_add (&D, b, &D)) != PSTM_OKAY) {
2245 goto LBL_D;
2246 }
2247 }
2248 if ((res = pstm_copy (&D, c)) != PSTM_OKAY) {
2249 goto LBL_D;
2250 }
2251 c->sign = neg;
2252 res = PSTM_OKAY;
2253
2254LBL_D: pstm_clear(&D);
2255LBL_B: pstm_clear(&B);
2256LBL_V: pstm_clear(&v);
2257LBL_U: pstm_clear(&u);
2258LBL_Y: pstm_clear(&y);
2259LBL_X: pstm_clear(&x);
2260 return res;
2261}
2262#endif /* !DISABLE_PSTM */
2263/******************************************************************************/