]> andersk Git - moira.git/blame - util/rsaref/nn.c
Set creation time and creator information for new users.
[moira.git] / util / rsaref / nn.c
CommitLineData
bd940221 1/* NN.C - natural numbers routines
2 */
3
4/* Copyright (C) RSA Laboratories, a division of RSA Data Security,
5 Inc., created 1991. All rights reserved.
6 */
7
8#include "global.h"
9#include "rsaref.h"
10#include "nn.h"
11#include "digit.h"
12
13static NN_DIGIT NN_AddDigitMult PROTO_LIST
14 ((NN_DIGIT *, NN_DIGIT *, NN_DIGIT, NN_DIGIT *, unsigned int));
15static NN_DIGIT NN_SubDigitMult PROTO_LIST
16 ((NN_DIGIT *, NN_DIGIT *, NN_DIGIT, NN_DIGIT *, unsigned int));
17
18static unsigned int NN_DigitBits PROTO_LIST ((NN_DIGIT));
19
20/* Decodes character string b into a, where character string is ordered
21 from most to least significant.
22
23 Lengths: a[digits], b[len].
24 Assumes b[i] = 0 for i < len - digits * NN_DIGIT_LEN. (Otherwise most
25 significant bytes are truncated.)
26 */
27void NN_Decode (a, digits, b, len)
28NN_DIGIT *a;
29unsigned char *b;
30unsigned int digits, len;
31{
32 NN_DIGIT t;
33 int j;
34 unsigned int i, u;
35
36 for (i = 0, j = len - 1; i < digits && j >= 0; i++) {
37 t = 0;
38 for (u = 0; j >= 0 && u < NN_DIGIT_BITS; j--, u += 8)
39 t |= ((NN_DIGIT)b[j]) << u;
40 a[i] = t;
41 }
42
43 for (; i < digits; i++)
44 a[i] = 0;
45}
46
47/* Encodes b into character string a, where character string is ordered
48 from most to least significant.
49
50 Lengths: a[len], b[digits].
51 Assumes NN_Bits (b, digits) <= 8 * len. (Otherwise most significant
52 digits are truncated.)
53 */
54void NN_Encode (a, len, b, digits)
55NN_DIGIT *b;
56unsigned char *a;
57unsigned int digits, len;
58{
59 NN_DIGIT t;
60 int j;
61 unsigned int i, u;
62
63 for (i = 0, j = len - 1; i < digits && j >= 0; i++) {
64 t = b[i];
65 for (u = 0; j >= 0 && u < NN_DIGIT_BITS; j--, u += 8)
66 a[j] = (unsigned char)(t >> u);
67 }
68
69 for (; j >= 0; j--)
70 a[j] = 0;
71}
72
73/* Assigns a = b.
74
75 Lengths: a[digits], b[digits].
76 */
77void NN_Assign (a, b, digits)
78NN_DIGIT *a, *b;
79unsigned int digits;
80{
81 unsigned int i;
82
83 for (i = 0; i < digits; i++)
84 a[i] = b[i];
85}
86
87/* Assigns a = 0.
88
89 Lengths: a[digits].
90 */
91void NN_AssignZero (a, digits)
92NN_DIGIT *a;
93unsigned int digits;
94{
95 unsigned int i;
96
97 for (i = 0; i < digits; i++)
98 a[i] = 0;
99}
100
101/* Assigns a = 2^b.
102
103 Lengths: a[digits].
104 Requires b < digits * NN_DIGIT_BITS.
105 */
106void NN_Assign2Exp (a, b, digits)
107NN_DIGIT *a;
108unsigned int b, digits;
109{
110 NN_AssignZero (a, digits);
111
112 if (b >= digits * NN_DIGIT_BITS)
113 return;
114
115 a[b / NN_DIGIT_BITS] = (NN_DIGIT)1 << (b % NN_DIGIT_BITS);
116}
117
118/* Computes a = b + c. Returns carry.
119
120 Lengths: a[digits], b[digits], c[digits].
121 */
122NN_DIGIT NN_Add (a, b, c, digits)
123NN_DIGIT *a, *b, *c;
124unsigned int digits;
125{
126 NN_DIGIT ai, carry;
127 unsigned int i;
128
129 carry = 0;
130
131 for (i = 0; i < digits; i++) {
132 if ((ai = b[i] + carry) < carry)
133 ai = c[i];
134 else if ((ai += c[i]) < c[i])
135 carry = 1;
136 else
137 carry = 0;
138 a[i] = ai;
139 }
140
141 return (carry);
142}
143
144/* Computes a = b - c. Returns borrow.
145
146 Lengths: a[digits], b[digits], c[digits].
147 */
148NN_DIGIT NN_Sub (a, b, c, digits)
149NN_DIGIT *a, *b, *c;
150unsigned int digits;
151{
152 NN_DIGIT ai, borrow;
153 unsigned int i;
154
155 borrow = 0;
156
157 for (i = 0; i < digits; i++) {
158 if ((ai = b[i] - borrow) > (MAX_NN_DIGIT - borrow))
159 ai = MAX_NN_DIGIT - c[i];
160 else if ((ai -= c[i]) > (MAX_NN_DIGIT - c[i]))
161 borrow = 1;
162 else
163 borrow = 0;
164 a[i] = ai;
165 }
166
167 return (borrow);
168}
169
170/* Computes a = b * c.
171
172 Lengths: a[2*digits], b[digits], c[digits].
173 Assumes digits < MAX_NN_DIGITS.
174 */
175void NN_Mult (a, b, c, digits)
176NN_DIGIT *a, *b, *c;
177unsigned int digits;
178{
179 NN_DIGIT t[2*MAX_NN_DIGITS];
180 unsigned int bDigits, cDigits, i;
181
182 NN_AssignZero (t, 2 * digits);
183
184 bDigits = NN_Digits (b, digits);
185 cDigits = NN_Digits (c, digits);
186
187 for (i = 0; i < bDigits; i++)
188 t[i+cDigits] += NN_AddDigitMult (&t[i], &t[i], b[i], c, cDigits);
189
190 NN_Assign (a, t, 2 * digits);
191
192 /* Zeroize potentially sensitive information.
193 */
194 R_memset ((POINTER)t, 0, sizeof (t));
195}
196
197/* Computes a = b * 2^c (i.e., shifts left c bits), returning carry.
198
199 Lengths: a[digits], b[digits].
200 Requires c < NN_DIGIT_BITS.
201 */
202NN_DIGIT NN_LShift (a, b, c, digits)
203NN_DIGIT *a, *b;
204unsigned int c, digits;
205{
206 NN_DIGIT bi, carry;
207 unsigned int i, t;
208
209 if (c >= NN_DIGIT_BITS)
210 return (0);
211
212 t = NN_DIGIT_BITS - c;
213
214 carry = 0;
215
216 for (i = 0; i < digits; i++) {
217 bi = b[i];
218 a[i] = (bi << c) | carry;
219 carry = c ? (bi >> t) : 0;
220 }
221
222 return (carry);
223}
224
225/* Computes a = c div 2^c (i.e., shifts right c bits), returning carry.
226
227 Lengths: a[digits], b[digits].
228 Requires: c < NN_DIGIT_BITS.
229 */
230NN_DIGIT NN_RShift (a, b, c, digits)
231NN_DIGIT *a, *b;
232unsigned int c, digits;
233{
234 NN_DIGIT bi, carry;
235 int i;
236 unsigned int t;
237
238 if (c >= NN_DIGIT_BITS)
239 return (0);
240
241 t = NN_DIGIT_BITS - c;
242
243 carry = 0;
244
245 for (i = digits - 1; i >= 0; i--) {
246 bi = b[i];
247 a[i] = (bi >> c) | carry;
248 carry = c ? (bi << t) : 0;
249 }
250
251 return (carry);
252}
253
254/* Computes a = c div d and b = c mod d.
255
256 Lengths: a[cDigits], b[dDigits], c[cDigits], d[dDigits].
257 Assumes d > 0, cDigits < 2 * MAX_NN_DIGITS,
258 dDigits < MAX_NN_DIGITS.
259 */
260void NN_Div (a, b, c, cDigits, d, dDigits)
261NN_DIGIT *a, *b, *c, *d;
262unsigned int cDigits, dDigits;
263{
264 NN_DIGIT ai, cc[2*MAX_NN_DIGITS+1], dd[MAX_NN_DIGITS], t;
265 int i;
266 unsigned int ddDigits, shift;
267
268 ddDigits = NN_Digits (d, dDigits);
269 if (ddDigits == 0)
270 return;
271
272 /* Normalize operands.
273 */
274 shift = NN_DIGIT_BITS - NN_DigitBits (d[ddDigits-1]);
275 NN_AssignZero (cc, ddDigits);
276 cc[cDigits] = NN_LShift (cc, c, shift, cDigits);
277 NN_LShift (dd, d, shift, ddDigits);
278 t = dd[ddDigits-1];
279
280 NN_AssignZero (a, cDigits);
281
282 for (i = cDigits-ddDigits; i >= 0; i--) {
283 /* Underestimate quotient digit and subtract.
284 */
285 if (t == MAX_NN_DIGIT)
286 ai = cc[i+ddDigits];
287 else
288 NN_DigitDiv (&ai, &cc[i+ddDigits-1], t + 1);
289 cc[i+ddDigits] -= NN_SubDigitMult (&cc[i], &cc[i], ai, dd, ddDigits);
290
291 /* Correct estimate.
292 */
293 while (cc[i+ddDigits] || (NN_Cmp (&cc[i], dd, ddDigits) >= 0)) {
294 ai++;
295 cc[i+ddDigits] -= NN_Sub (&cc[i], &cc[i], dd, ddDigits);
296 }
297
298 a[i] = ai;
299 }
300
301 /* Restore result.
302 */
303 NN_AssignZero (b, dDigits);
304 NN_RShift (b, cc, shift, ddDigits);
305
306 /* Zeroize potentially sensitive information.
307 */
308 R_memset ((POINTER)cc, 0, sizeof (cc));
309 R_memset ((POINTER)dd, 0, sizeof (dd));
310}
311
312/* Computes a = b mod c.
313
314 Lengths: a[cDigits], b[bDigits], c[cDigits].
315 Assumes c > 0, bDigits < 2 * MAX_NN_DIGITS, cDigits < MAX_NN_DIGITS.
316 */
317void NN_Mod (a, b, bDigits, c, cDigits)
318NN_DIGIT *a, *b, *c;
319unsigned int bDigits, cDigits;
320{
321 NN_DIGIT t[2 * MAX_NN_DIGITS];
322
323 NN_Div (t, a, b, bDigits, c, cDigits);
324
325 /* Zeroize potentially sensitive information.
326 */
327 R_memset ((POINTER)t, 0, sizeof (t));
328}
329
330/* Computes a = b * c mod d.
331
332 Lengths: a[digits], b[digits], c[digits], d[digits].
333 Assumes d > 0, digits < MAX_NN_DIGITS.
334 */
335void NN_ModMult (a, b, c, d, digits)
336NN_DIGIT *a, *b, *c, *d;
337unsigned int digits;
338{
339 NN_DIGIT t[2*MAX_NN_DIGITS];
340
341 NN_Mult (t, b, c, digits);
342 NN_Mod (a, t, 2 * digits, d, digits);
343
344 /* Zeroize potentially sensitive information.
345 */
346 R_memset ((POINTER)t, 0, sizeof (t));
347}
348
349/* Computes a = b^c mod d.
350
351 Lengths: a[dDigits], b[dDigits], c[cDigits], d[dDigits].
352 Assumes d > 0, cDigits > 0, dDigits < MAX_NN_DIGITS.
353 */
354void NN_ModExp (a, b, c, cDigits, d, dDigits)
355NN_DIGIT *a, *b, *c, *d;
356unsigned int cDigits, dDigits;
357{
358 NN_DIGIT bPower[3][MAX_NN_DIGITS], ci, t[MAX_NN_DIGITS];
359 int i;
360 unsigned int ciBits, j, s;
361
362 /* Store b, b^2 mod d, and b^3 mod d.
363 */
364 NN_Assign (bPower[0], b, dDigits);
365 NN_ModMult (bPower[1], bPower[0], b, d, dDigits);
366 NN_ModMult (bPower[2], bPower[1], b, d, dDigits);
367
368 NN_ASSIGN_DIGIT (t, 1, dDigits);
369
370 cDigits = NN_Digits (c, cDigits);
371 for (i = cDigits - 1; i >= 0; i--) {
372 ci = c[i];
373 ciBits = NN_DIGIT_BITS;
374
375 /* Scan past leading zero bits of most significant digit.
376 */
377 if (i == (int)(cDigits - 1)) {
378 while (! DIGIT_2MSB (ci)) {
379 ci <<= 2;
380 ciBits -= 2;
381 }
382 }
383
384 for (j = 0; j < ciBits; j += 2, ci <<= 2) {
385 /* Compute t = t^4 * b^s mod d, where s = two MSB's of ci.
386 */
387 NN_ModMult (t, t, t, d, dDigits);
388 NN_ModMult (t, t, t, d, dDigits);
389 if ((s = DIGIT_2MSB (ci)) != 0)
390 NN_ModMult (t, t, bPower[s-1], d, dDigits);
391 }
392 }
393
394 NN_Assign (a, t, dDigits);
395
396 /* Zeroize potentially sensitive information.
397 */
398 R_memset ((POINTER)bPower, 0, sizeof (bPower));
399 R_memset ((POINTER)t, 0, sizeof (t));
400}
401
402/* Compute a = 1/b mod c, assuming inverse exists.
403
404 Lengths: a[digits], b[digits], c[digits].
405 Assumes gcd (b, c) = 1, digits < MAX_NN_DIGITS.
406 */
407void NN_ModInv (a, b, c, digits)
408NN_DIGIT *a, *b, *c;
409unsigned int digits;
410{
411 NN_DIGIT q[MAX_NN_DIGITS], t1[MAX_NN_DIGITS], t3[MAX_NN_DIGITS],
412 u1[MAX_NN_DIGITS], u3[MAX_NN_DIGITS], v1[MAX_NN_DIGITS],
413 v3[MAX_NN_DIGITS], w[2*MAX_NN_DIGITS];
414 int u1Sign;
415
416 /* Apply extended Euclidean algorithm, modified to avoid negative
417 numbers.
418 */
419 NN_ASSIGN_DIGIT (u1, 1, digits);
420 NN_AssignZero (v1, digits);
421 NN_Assign (u3, b, digits);
422 NN_Assign (v3, c, digits);
423 u1Sign = 1;
424
425 while (! NN_Zero (v3, digits)) {
426 NN_Div (q, t3, u3, digits, v3, digits);
427 NN_Mult (w, q, v1, digits);
428 NN_Add (t1, u1, w, digits);
429 NN_Assign (u1, v1, digits);
430 NN_Assign (v1, t1, digits);
431 NN_Assign (u3, v3, digits);
432 NN_Assign (v3, t3, digits);
433 u1Sign = -u1Sign;
434 }
435
436 /* Negate result if sign is negative.
437 */
438 if (u1Sign < 0)
439 NN_Sub (a, c, u1, digits);
440 else
441 NN_Assign (a, u1, digits);
442
443 /* Zeroize potentially sensitive information.
444 */
445 R_memset ((POINTER)q, 0, sizeof (q));
446 R_memset ((POINTER)t1, 0, sizeof (t1));
447 R_memset ((POINTER)t3, 0, sizeof (t3));
448 R_memset ((POINTER)u1, 0, sizeof (u1));
449 R_memset ((POINTER)u3, 0, sizeof (u3));
450 R_memset ((POINTER)v1, 0, sizeof (v1));
451 R_memset ((POINTER)v3, 0, sizeof (v3));
452 R_memset ((POINTER)w, 0, sizeof (w));
453}
454
455/* Computes a = gcd(b, c).
456
457 Lengths: a[digits], b[digits], c[digits].
458 Assumes b > c, digits < MAX_NN_DIGITS.
459 */
460void NN_Gcd (a, b, c, digits)
461NN_DIGIT *a, *b, *c;
462unsigned int digits;
463{
464 NN_DIGIT t[MAX_NN_DIGITS], u[MAX_NN_DIGITS], v[MAX_NN_DIGITS];
465
466 NN_Assign (u, b, digits);
467 NN_Assign (v, c, digits);
468
469 while (! NN_Zero (v, digits)) {
470 NN_Mod (t, u, digits, v, digits);
471 NN_Assign (u, v, digits);
472 NN_Assign (v, t, digits);
473 }
474
475 NN_Assign (a, u, digits);
476
477 /* Zeroize potentially sensitive information.
478 */
479 R_memset ((POINTER)t, 0, sizeof (t));
480 R_memset ((POINTER)u, 0, sizeof (u));
481 R_memset ((POINTER)v, 0, sizeof (v));
482}
483
484/* Returns sign of a - b.
485
486 Lengths: a[digits], b[digits].
487 */
488int NN_Cmp (a, b, digits)
489NN_DIGIT *a, *b;
490unsigned int digits;
491{
492 int i;
493
494 for (i = digits - 1; i >= 0; i--) {
495 if (a[i] > b[i])
496 return (1);
497 if (a[i] < b[i])
498 return (-1);
499 }
500
501 return (0);
502}
503
504/* Returns nonzero iff a is zero.
505
506 Lengths: a[digits].
507 */
508int NN_Zero (a, digits)
509NN_DIGIT *a;
510unsigned int digits;
511{
512 unsigned int i;
513
514 for (i = 0; i < digits; i++)
515 if (a[i])
516 return (0);
517
518 return (1);
519}
520
521/* Returns the significant length of a in bits.
522
523 Lengths: a[digits].
524 */
525unsigned int NN_Bits (a, digits)
526NN_DIGIT *a;
527unsigned int digits;
528{
529 if ((digits = NN_Digits (a, digits)) == 0)
530 return (0);
531
532 return ((digits - 1) * NN_DIGIT_BITS + NN_DigitBits (a[digits-1]));
533}
534
535/* Returns the significant length of a in digits.
536
537 Lengths: a[digits].
538 */
539unsigned int NN_Digits (a, digits)
540NN_DIGIT *a;
541unsigned int digits;
542{
543 int i;
544
545 for (i = digits - 1; i >= 0; i--)
546 if (a[i])
547 break;
548
549 return (i + 1);
550}
551
552/* Computes a = b + c*d, where c is a digit. Returns carry.
553
554 Lengths: a[digits], b[digits], d[digits].
555 */
556static NN_DIGIT NN_AddDigitMult (a, b, c, d, digits)
557NN_DIGIT *a, *b, c, *d;
558unsigned int digits;
559{
560 NN_DIGIT carry, t[2];
561 unsigned int i;
562
563 if (c == 0)
564 return (0);
565
566 carry = 0;
567 for (i = 0; i < digits; i++) {
568 NN_DigitMult (t, c, d[i]);
569 if ((a[i] = b[i] + carry) < carry)
570 carry = 1;
571 else
572 carry = 0;
573 if ((a[i] += t[0]) < t[0])
574 carry++;
575 carry += t[1];
576 }
577
578 return (carry);
579}
580
581/* Computes a = b - c*d, where c is a digit. Returns borrow.
582
583 Lengths: a[digits], b[digits], d[digits].
584 */
585static NN_DIGIT NN_SubDigitMult (a, b, c, d, digits)
586NN_DIGIT *a, *b, c, *d;
587unsigned int digits;
588{
589 NN_DIGIT borrow, t[2];
590 unsigned int i;
591
592 if (c == 0)
593 return (0);
594
595 borrow = 0;
596 for (i = 0; i < digits; i++) {
597 NN_DigitMult (t, c, d[i]);
598 if ((a[i] = b[i] - borrow) > (MAX_NN_DIGIT - borrow))
599 borrow = 1;
600 else
601 borrow = 0;
602 if ((a[i] -= t[0]) > (MAX_NN_DIGIT - t[0]))
603 borrow++;
604 borrow += t[1];
605 }
606
607 return (borrow);
608}
609
610/* Returns the significant length of a in bits, where a is a digit.
611 */
612static unsigned int NN_DigitBits (a)
613NN_DIGIT a;
614{
615 unsigned int i;
616
617 for (i = 0; i < NN_DIGIT_BITS; i++, a >>= 1)
618 if (a == 0)
619 break;
620
621 return (i);
622}
This page took 0.139331 seconds and 5 git commands to generate.