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