1 /* NN.C - natural numbers routines
4 /* Copyright (C) RSA Laboratories, a division of RSA Data Security,
5 Inc., created 1991. All rights reserved.
8 /* CHANGES MADE TO THIS FILE UNDER RSAREF 2.0 license clause 1(c):
10 For the MIT PGP 2.5 distribution, this file was modified to permit
11 replacement of the NN_ModExp routine by an equivalent routine contained
12 in the PGP 2.5 sources. To enable this change, an #ifdef was added to this
13 file (search for #ifndef USEMPILIB below). RSAREF *must* be compiled with
14 USEMPILIB defined for this change to occur.
16 Change made May 8, 1994. */
23 static NN_DIGIT NN_AddDigitMult PROTO_LIST
24 ((NN_DIGIT *, NN_DIGIT *, NN_DIGIT, NN_DIGIT *, unsigned int));
25 static NN_DIGIT NN_SubDigitMult PROTO_LIST
26 ((NN_DIGIT *, NN_DIGIT *, NN_DIGIT, NN_DIGIT *, unsigned int));
28 static unsigned int NN_DigitBits PROTO_LIST ((NN_DIGIT));
30 /* Decodes character string b into a, where character string is ordered
31 from most to least significant.
33 Lengths: a[digits], b[len].
34 Assumes b[i] = 0 for i < len - digits * NN_DIGIT_LEN. (Otherwise most
35 significant bytes are truncated.)
37 void NN_Decode (a, digits, b, len)
40 unsigned int digits, len;
46 for (i = 0, j = len - 1; i < digits && j >= 0; i++) {
48 for (u = 0; j >= 0 && u < NN_DIGIT_BITS; j--, u += 8)
49 t |= ((NN_DIGIT)b[j]) << u;
53 for (; i < digits; i++)
57 /* Encodes b into character string a, where character string is ordered
58 from most to least significant.
60 Lengths: a[len], b[digits].
61 Assumes NN_Bits (b, digits) <= 8 * len. (Otherwise most significant
62 digits are truncated.)
64 void NN_Encode (a, len, b, digits)
67 unsigned int digits, len;
73 for (i = 0, j = len - 1; i < digits && j >= 0; i++) {
75 for (u = 0; j >= 0 && u < NN_DIGIT_BITS; j--, u += 8)
76 a[j] = (unsigned char)(t >> u);
85 Lengths: a[digits], b[digits].
87 void NN_Assign (a, b, digits)
93 for (i = 0; i < digits; i++)
101 void NN_AssignZero (a, digits)
107 for (i = 0; i < digits; i++)
114 Requires b < digits * NN_DIGIT_BITS.
116 void NN_Assign2Exp (a, b, digits)
118 unsigned int b, digits;
120 NN_AssignZero (a, digits);
122 if (b >= digits * NN_DIGIT_BITS)
125 a[b / NN_DIGIT_BITS] = (NN_DIGIT)1 << (b % NN_DIGIT_BITS);
128 /* Computes a = b + c. Returns carry.
130 Lengths: a[digits], b[digits], c[digits].
132 NN_DIGIT NN_Add (a, b, c, digits)
141 for (i = 0; i < digits; i++) {
142 if ((ai = b[i] + carry) < carry)
144 else if ((ai += c[i]) < c[i])
154 /* Computes a = b - c. Returns borrow.
156 Lengths: a[digits], b[digits], c[digits].
158 NN_DIGIT NN_Sub (a, b, c, digits)
167 for (i = 0; i < digits; i++) {
168 if ((ai = b[i] - borrow) > (MAX_NN_DIGIT - borrow))
169 ai = MAX_NN_DIGIT - c[i];
170 else if ((ai -= c[i]) > (MAX_NN_DIGIT - c[i]))
180 /* Computes a = b * c.
182 Lengths: a[2*digits], b[digits], c[digits].
183 Assumes digits < MAX_NN_DIGITS.
185 void NN_Mult (a, b, c, digits)
189 NN_DIGIT t[2*MAX_NN_DIGITS];
190 unsigned int bDigits, cDigits, i;
192 NN_AssignZero (t, 2 * digits);
194 bDigits = NN_Digits (b, digits);
195 cDigits = NN_Digits (c, digits);
197 for (i = 0; i < bDigits; i++)
198 t[i+cDigits] += NN_AddDigitMult (&t[i], &t[i], b[i], c, cDigits);
200 NN_Assign (a, t, 2 * digits);
202 /* Zeroize potentially sensitive information.
204 R_memset ((POINTER)t, 0, sizeof (t));
207 /* Computes a = b * 2^c (i.e., shifts left c bits), returning carry.
209 Lengths: a[digits], b[digits].
210 Requires c < NN_DIGIT_BITS.
212 NN_DIGIT NN_LShift (a, b, c, digits)
214 unsigned int c, digits;
219 if (c >= NN_DIGIT_BITS)
222 t = NN_DIGIT_BITS - c;
226 for (i = 0; i < digits; i++) {
228 a[i] = (bi << c) | carry;
229 carry = c ? (bi >> t) : 0;
235 /* Computes a = c div 2^c (i.e., shifts right c bits), returning carry.
237 Lengths: a[digits], b[digits].
238 Requires: c < NN_DIGIT_BITS.
240 NN_DIGIT NN_RShift (a, b, c, digits)
242 unsigned int c, digits;
248 if (c >= NN_DIGIT_BITS)
251 t = NN_DIGIT_BITS - c;
255 for (i = digits - 1; i >= 0; i--) {
257 a[i] = (bi >> c) | carry;
258 carry = c ? (bi << t) : 0;
264 /* Computes a = c div d and b = c mod d.
266 Lengths: a[cDigits], b[dDigits], c[cDigits], d[dDigits].
267 Assumes d > 0, cDigits < 2 * MAX_NN_DIGITS,
268 dDigits < MAX_NN_DIGITS.
270 void NN_Div (a, b, c, cDigits, d, dDigits)
271 NN_DIGIT *a, *b, *c, *d;
272 unsigned int cDigits, dDigits;
274 NN_DIGIT ai, cc[2*MAX_NN_DIGITS+1], dd[MAX_NN_DIGITS], t;
276 unsigned int ddDigits, shift;
278 ddDigits = NN_Digits (d, dDigits);
282 /* Normalize operands.
284 shift = NN_DIGIT_BITS - NN_DigitBits (d[ddDigits-1]);
285 NN_AssignZero (cc, ddDigits);
286 cc[cDigits] = NN_LShift (cc, c, shift, cDigits);
287 NN_LShift (dd, d, shift, ddDigits);
290 NN_AssignZero (a, cDigits);
292 for (i = cDigits-ddDigits; i >= 0; i--) {
293 /* Underestimate quotient digit and subtract.
295 if (t == MAX_NN_DIGIT)
298 NN_DigitDiv (&ai, &cc[i+ddDigits-1], t + 1);
299 cc[i+ddDigits] -= NN_SubDigitMult (&cc[i], &cc[i], ai, dd, ddDigits);
303 while (cc[i+ddDigits] || (NN_Cmp (&cc[i], dd, ddDigits) >= 0)) {
305 cc[i+ddDigits] -= NN_Sub (&cc[i], &cc[i], dd, ddDigits);
313 NN_AssignZero (b, dDigits);
314 NN_RShift (b, cc, shift, ddDigits);
316 /* Zeroize potentially sensitive information.
318 R_memset ((POINTER)cc, 0, sizeof (cc));
319 R_memset ((POINTER)dd, 0, sizeof (dd));
322 /* Computes a = b mod c.
324 Lengths: a[cDigits], b[bDigits], c[cDigits].
325 Assumes c > 0, bDigits < 2 * MAX_NN_DIGITS, cDigits < MAX_NN_DIGITS.
327 void NN_Mod (a, b, bDigits, c, cDigits)
329 unsigned int bDigits, cDigits;
331 NN_DIGIT t[2 * MAX_NN_DIGITS];
333 NN_Div (t, a, b, bDigits, c, cDigits);
335 /* Zeroize potentially sensitive information.
337 R_memset ((POINTER)t, 0, sizeof (t));
340 /* Computes a = b * c mod d.
342 Lengths: a[digits], b[digits], c[digits], d[digits].
343 Assumes d > 0, digits < MAX_NN_DIGITS.
345 void NN_ModMult (a, b, c, d, digits)
346 NN_DIGIT *a, *b, *c, *d;
349 NN_DIGIT t[2*MAX_NN_DIGITS];
351 NN_Mult (t, b, c, digits);
352 NN_Mod (a, t, 2 * digits, d, digits);
354 /* Zeroize potentially sensitive information.
356 R_memset ((POINTER)t, 0, sizeof (t));
359 /* Computes a = b^c mod d.
361 Lengths: a[dDigits], b[dDigits], c[cDigits], d[dDigits].
362 Assumes d > 0, cDigits > 0, dDigits < MAX_NN_DIGITS.
365 /* PGP 2.5's mpilib contains a faster modular exponentiation routine, mp_modexp.
366 If USEMPILIB is defined, NN_ModExp is replaced in the PGP 2.5 sources with a
367 stub call to mp_modexp. If USEMPILIB is not defined, we'll get a pure (albeit
368 slower) RSAREF implementation.
370 The RSAREF 2.0 license, clause 1(c), permits "...modify[ing] the Program in any
371 manner for porting or performance improvement purposes..." */
374 void NN_ModExp (a, b, c, cDigits, d, dDigits)
375 NN_DIGIT *a, *b, *c, *d;
376 unsigned int cDigits, dDigits;
378 NN_DIGIT bPower[3][MAX_NN_DIGITS], ci, t[MAX_NN_DIGITS];
380 unsigned int ciBits, j, s;
382 /* Store b, b^2 mod d, and b^3 mod d.
384 NN_Assign (bPower[0], b, dDigits);
385 NN_ModMult (bPower[1], bPower[0], b, d, dDigits);
386 NN_ModMult (bPower[2], bPower[1], b, d, dDigits);
388 NN_ASSIGN_DIGIT (t, 1, dDigits);
390 cDigits = NN_Digits (c, cDigits);
391 for (i = cDigits - 1; i >= 0; i--) {
393 ciBits = NN_DIGIT_BITS;
395 /* Scan past leading zero bits of most significant digit.
397 if (i == (int)(cDigits - 1)) {
398 while (! DIGIT_2MSB (ci)) {
404 for (j = 0; j < ciBits; j += 2, ci <<= 2) {
405 /* Compute t = t^4 * b^s mod d, where s = two MSB's of ci.
407 NN_ModMult (t, t, t, d, dDigits);
408 NN_ModMult (t, t, t, d, dDigits);
409 if ((s = DIGIT_2MSB (ci)) != 0)
410 NN_ModMult (t, t, bPower[s-1], d, dDigits);
414 NN_Assign (a, t, dDigits);
416 /* Zeroize potentially sensitive information.
418 R_memset ((POINTER)bPower, 0, sizeof (bPower));
419 R_memset ((POINTER)t, 0, sizeof (t));
423 /* Compute a = 1/b mod c, assuming inverse exists.
425 Lengths: a[digits], b[digits], c[digits].
426 Assumes gcd (b, c) = 1, digits < MAX_NN_DIGITS.
428 void NN_ModInv (a, b, c, digits)
432 NN_DIGIT q[MAX_NN_DIGITS], t1[MAX_NN_DIGITS], t3[MAX_NN_DIGITS],
433 u1[MAX_NN_DIGITS], u3[MAX_NN_DIGITS], v1[MAX_NN_DIGITS],
434 v3[MAX_NN_DIGITS], w[2*MAX_NN_DIGITS];
437 /* Apply extended Euclidean algorithm, modified to avoid negative
440 NN_ASSIGN_DIGIT (u1, 1, digits);
441 NN_AssignZero (v1, digits);
442 NN_Assign (u3, b, digits);
443 NN_Assign (v3, c, digits);
446 while (! NN_Zero (v3, digits)) {
447 NN_Div (q, t3, u3, digits, v3, digits);
448 NN_Mult (w, q, v1, digits);
449 NN_Add (t1, u1, w, digits);
450 NN_Assign (u1, v1, digits);
451 NN_Assign (v1, t1, digits);
452 NN_Assign (u3, v3, digits);
453 NN_Assign (v3, t3, digits);
457 /* Negate result if sign is negative.
460 NN_Sub (a, c, u1, digits);
462 NN_Assign (a, u1, digits);
464 /* Zeroize potentially sensitive information.
466 R_memset ((POINTER)q, 0, sizeof (q));
467 R_memset ((POINTER)t1, 0, sizeof (t1));
468 R_memset ((POINTER)t3, 0, sizeof (t3));
469 R_memset ((POINTER)u1, 0, sizeof (u1));
470 R_memset ((POINTER)u3, 0, sizeof (u3));
471 R_memset ((POINTER)v1, 0, sizeof (v1));
472 R_memset ((POINTER)v3, 0, sizeof (v3));
473 R_memset ((POINTER)w, 0, sizeof (w));
476 /* Computes a = gcd(b, c).
478 Lengths: a[digits], b[digits], c[digits].
479 Assumes b > c, digits < MAX_NN_DIGITS.
481 void NN_Gcd (a, b, c, digits)
485 NN_DIGIT t[MAX_NN_DIGITS], u[MAX_NN_DIGITS], v[MAX_NN_DIGITS];
487 NN_Assign (u, b, digits);
488 NN_Assign (v, c, digits);
490 while (! NN_Zero (v, digits)) {
491 NN_Mod (t, u, digits, v, digits);
492 NN_Assign (u, v, digits);
493 NN_Assign (v, t, digits);
496 NN_Assign (a, u, digits);
498 /* Zeroize potentially sensitive information.
500 R_memset ((POINTER)t, 0, sizeof (t));
501 R_memset ((POINTER)u, 0, sizeof (u));
502 R_memset ((POINTER)v, 0, sizeof (v));
505 /* Returns sign of a - b.
507 Lengths: a[digits], b[digits].
509 int NN_Cmp (a, b, digits)
515 for (i = digits - 1; i >= 0; i--) {
525 /* Returns nonzero iff a is zero.
529 int NN_Zero (a, digits)
535 for (i = 0; i < digits; i++)
542 /* Returns the significant length of a in bits.
546 unsigned int NN_Bits (a, digits)
550 if ((digits = NN_Digits (a, digits)) == 0)
553 return ((digits - 1) * NN_DIGIT_BITS + NN_DigitBits (a[digits-1]));
556 /* Returns the significant length of a in digits.
560 unsigned int NN_Digits (a, digits)
566 for (i = digits - 1; i >= 0; i--)
573 /* Computes a = b + c*d, where c is a digit. Returns carry.
575 Lengths: a[digits], b[digits], d[digits].
577 static NN_DIGIT NN_AddDigitMult (a, b, c, d, digits)
578 NN_DIGIT *a, *b, c, *d;
581 NN_DIGIT carry, t[2];
588 for (i = 0; i < digits; i++) {
589 NN_DigitMult (t, c, d[i]);
590 if ((a[i] = b[i] + carry) < carry)
594 if ((a[i] += t[0]) < t[0])
602 /* Computes a = b - c*d, where c is a digit. Returns borrow.
604 Lengths: a[digits], b[digits], d[digits].
606 static NN_DIGIT NN_SubDigitMult (a, b, c, d, digits)
607 NN_DIGIT *a, *b, c, *d;
610 NN_DIGIT borrow, t[2];
617 for (i = 0; i < digits; i++) {
618 NN_DigitMult (t, c, d[i]);
619 if ((a[i] = b[i] - borrow) > (MAX_NN_DIGIT - borrow))
623 if ((a[i] -= t[0]) > (MAX_NN_DIGIT - t[0]))
631 /* Returns the significant length of a in bits, where a is a digit.
633 static unsigned int NN_DigitBits (a)
638 for (i = 0; i < NN_DIGIT_BITS; i++, a >>= 1)