1 /* NN.C - natural numbers routines
4 /* Copyright (C) RSA Laboratories, a division of RSA Data Security,
5 Inc., created 1991. All rights reserved.
13 static NN_DIGIT NN_AddDigitMult PROTO_LIST
14 ((NN_DIGIT *, NN_DIGIT *, NN_DIGIT, NN_DIGIT *, unsigned int));
15 static NN_DIGIT NN_SubDigitMult PROTO_LIST
16 ((NN_DIGIT *, NN_DIGIT *, NN_DIGIT, NN_DIGIT *, unsigned int));
18 static unsigned int NN_DigitBits PROTO_LIST ((NN_DIGIT));
20 /* Decodes character string b into a, where character string is ordered
21 from most to least significant.
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.)
27 void NN_Decode (a, digits, b, len)
30 unsigned int digits, len;
36 for (i = 0, j = len - 1; i < digits && j >= 0; i++) {
38 for (u = 0; j >= 0 && u < NN_DIGIT_BITS; j--, u += 8)
39 t |= ((NN_DIGIT)b[j]) << u;
43 for (; i < digits; i++)
47 /* Encodes b into character string a, where character string is ordered
48 from most to least significant.
50 Lengths: a[len], b[digits].
51 Assumes NN_Bits (b, digits) <= 8 * len. (Otherwise most significant
52 digits are truncated.)
54 void NN_Encode (a, len, b, digits)
57 unsigned int digits, len;
63 for (i = 0, j = len - 1; i < digits && j >= 0; i++) {
65 for (u = 0; j >= 0 && u < NN_DIGIT_BITS; j--, u += 8)
66 a[j] = (unsigned char)(t >> u);
75 Lengths: a[digits], b[digits].
77 void NN_Assign (a, b, digits)
83 for (i = 0; i < digits; i++)
91 void NN_AssignZero (a, digits)
97 for (i = 0; i < digits; i++)
104 Requires b < digits * NN_DIGIT_BITS.
106 void NN_Assign2Exp (a, b, digits)
108 unsigned int b, digits;
110 NN_AssignZero (a, digits);
112 if (b >= digits * NN_DIGIT_BITS)
115 a[b / NN_DIGIT_BITS] = (NN_DIGIT)1 << (b % NN_DIGIT_BITS);
118 /* Computes a = b + c. Returns carry.
120 Lengths: a[digits], b[digits], c[digits].
122 NN_DIGIT NN_Add (a, b, c, digits)
131 for (i = 0; i < digits; i++) {
132 if ((ai = b[i] + carry) < carry)
134 else if ((ai += c[i]) < c[i])
144 /* Computes a = b - c. Returns borrow.
146 Lengths: a[digits], b[digits], c[digits].
148 NN_DIGIT NN_Sub (a, b, c, digits)
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]))
170 /* Computes a = b * c.
172 Lengths: a[2*digits], b[digits], c[digits].
173 Assumes digits < MAX_NN_DIGITS.
175 void NN_Mult (a, b, c, digits)
179 NN_DIGIT t[2*MAX_NN_DIGITS];
180 unsigned int bDigits, cDigits, i;
182 NN_AssignZero (t, 2 * digits);
184 bDigits = NN_Digits (b, digits);
185 cDigits = NN_Digits (c, digits);
187 for (i = 0; i < bDigits; i++)
188 t[i+cDigits] += NN_AddDigitMult (&t[i], &t[i], b[i], c, cDigits);
190 NN_Assign (a, t, 2 * digits);
192 /* Zeroize potentially sensitive information.
194 R_memset ((POINTER)t, 0, sizeof (t));
197 /* Computes a = b * 2^c (i.e., shifts left c bits), returning carry.
199 Lengths: a[digits], b[digits].
200 Requires c < NN_DIGIT_BITS.
202 NN_DIGIT NN_LShift (a, b, c, digits)
204 unsigned int c, digits;
209 if (c >= NN_DIGIT_BITS)
212 t = NN_DIGIT_BITS - c;
216 for (i = 0; i < digits; i++) {
218 a[i] = (bi << c) | carry;
219 carry = c ? (bi >> t) : 0;
225 /* Computes a = c div 2^c (i.e., shifts right c bits), returning carry.
227 Lengths: a[digits], b[digits].
228 Requires: c < NN_DIGIT_BITS.
230 NN_DIGIT NN_RShift (a, b, c, digits)
232 unsigned int c, digits;
238 if (c >= NN_DIGIT_BITS)
241 t = NN_DIGIT_BITS - c;
245 for (i = digits - 1; i >= 0; i--) {
247 a[i] = (bi >> c) | carry;
248 carry = c ? (bi << t) : 0;
254 /* Computes a = c div d and b = c mod d.
256 Lengths: a[cDigits], b[dDigits], c[cDigits], d[dDigits].
257 Assumes d > 0, cDigits < 2 * MAX_NN_DIGITS,
258 dDigits < MAX_NN_DIGITS.
260 void NN_Div (a, b, c, cDigits, d, dDigits)
261 NN_DIGIT *a, *b, *c, *d;
262 unsigned int cDigits, dDigits;
264 NN_DIGIT ai, cc[2*MAX_NN_DIGITS+1], dd[MAX_NN_DIGITS], t;
266 unsigned int ddDigits, shift;
268 ddDigits = NN_Digits (d, dDigits);
272 /* Normalize operands.
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);
280 NN_AssignZero (a, cDigits);
282 for (i = cDigits-ddDigits; i >= 0; i--) {
283 /* Underestimate quotient digit and subtract.
285 if (t == MAX_NN_DIGIT)
288 NN_DigitDiv (&ai, &cc[i+ddDigits-1], t + 1);
289 cc[i+ddDigits] -= NN_SubDigitMult (&cc[i], &cc[i], ai, dd, ddDigits);
293 while (cc[i+ddDigits] || (NN_Cmp (&cc[i], dd, ddDigits) >= 0)) {
295 cc[i+ddDigits] -= NN_Sub (&cc[i], &cc[i], dd, ddDigits);
303 NN_AssignZero (b, dDigits);
304 NN_RShift (b, cc, shift, ddDigits);
306 /* Zeroize potentially sensitive information.
308 R_memset ((POINTER)cc, 0, sizeof (cc));
309 R_memset ((POINTER)dd, 0, sizeof (dd));
312 /* Computes a = b mod c.
314 Lengths: a[cDigits], b[bDigits], c[cDigits].
315 Assumes c > 0, bDigits < 2 * MAX_NN_DIGITS, cDigits < MAX_NN_DIGITS.
317 void NN_Mod (a, b, bDigits, c, cDigits)
319 unsigned int bDigits, cDigits;
321 NN_DIGIT t[2 * MAX_NN_DIGITS];
323 NN_Div (t, a, b, bDigits, c, cDigits);
325 /* Zeroize potentially sensitive information.
327 R_memset ((POINTER)t, 0, sizeof (t));
330 /* Computes a = b * c mod d.
332 Lengths: a[digits], b[digits], c[digits], d[digits].
333 Assumes d > 0, digits < MAX_NN_DIGITS.
335 void NN_ModMult (a, b, c, d, digits)
336 NN_DIGIT *a, *b, *c, *d;
339 NN_DIGIT t[2*MAX_NN_DIGITS];
341 NN_Mult (t, b, c, digits);
342 NN_Mod (a, t, 2 * digits, d, digits);
344 /* Zeroize potentially sensitive information.
346 R_memset ((POINTER)t, 0, sizeof (t));
349 /* Computes a = b^c mod d.
351 Lengths: a[dDigits], b[dDigits], c[cDigits], d[dDigits].
352 Assumes d > 0, cDigits > 0, dDigits < MAX_NN_DIGITS.
354 void NN_ModExp (a, b, c, cDigits, d, dDigits)
355 NN_DIGIT *a, *b, *c, *d;
356 unsigned int cDigits, dDigits;
358 NN_DIGIT bPower[3][MAX_NN_DIGITS], ci, t[MAX_NN_DIGITS];
360 unsigned int ciBits, j, s;
362 /* Store b, b^2 mod d, and b^3 mod d.
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);
368 NN_ASSIGN_DIGIT (t, 1, dDigits);
370 cDigits = NN_Digits (c, cDigits);
371 for (i = cDigits - 1; i >= 0; i--) {
373 ciBits = NN_DIGIT_BITS;
375 /* Scan past leading zero bits of most significant digit.
377 if (i == (int)(cDigits - 1)) {
378 while (! DIGIT_2MSB (ci)) {
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.
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);
394 NN_Assign (a, t, dDigits);
396 /* Zeroize potentially sensitive information.
398 R_memset ((POINTER)bPower, 0, sizeof (bPower));
399 R_memset ((POINTER)t, 0, sizeof (t));
402 /* Compute a = 1/b mod c, assuming inverse exists.
404 Lengths: a[digits], b[digits], c[digits].
405 Assumes gcd (b, c) = 1, digits < MAX_NN_DIGITS.
407 void NN_ModInv (a, b, c, digits)
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];
416 /* Apply extended Euclidean algorithm, modified to avoid negative
419 NN_ASSIGN_DIGIT (u1, 1, digits);
420 NN_AssignZero (v1, digits);
421 NN_Assign (u3, b, digits);
422 NN_Assign (v3, c, digits);
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);
436 /* Negate result if sign is negative.
439 NN_Sub (a, c, u1, digits);
441 NN_Assign (a, u1, digits);
443 /* Zeroize potentially sensitive information.
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));
455 /* Computes a = gcd(b, c).
457 Lengths: a[digits], b[digits], c[digits].
458 Assumes b > c, digits < MAX_NN_DIGITS.
460 void NN_Gcd (a, b, c, digits)
464 NN_DIGIT t[MAX_NN_DIGITS], u[MAX_NN_DIGITS], v[MAX_NN_DIGITS];
466 NN_Assign (u, b, digits);
467 NN_Assign (v, c, digits);
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);
475 NN_Assign (a, u, digits);
477 /* Zeroize potentially sensitive information.
479 R_memset ((POINTER)t, 0, sizeof (t));
480 R_memset ((POINTER)u, 0, sizeof (u));
481 R_memset ((POINTER)v, 0, sizeof (v));
484 /* Returns sign of a - b.
486 Lengths: a[digits], b[digits].
488 int NN_Cmp (a, b, digits)
494 for (i = digits - 1; i >= 0; i--) {
504 /* Returns nonzero iff a is zero.
508 int NN_Zero (a, digits)
514 for (i = 0; i < digits; i++)
521 /* Returns the significant length of a in bits.
525 unsigned int NN_Bits (a, digits)
529 if ((digits = NN_Digits (a, digits)) == 0)
532 return ((digits - 1) * NN_DIGIT_BITS + NN_DigitBits (a[digits-1]));
535 /* Returns the significant length of a in digits.
539 unsigned int NN_Digits (a, digits)
545 for (i = digits - 1; i >= 0; i--)
552 /* Computes a = b + c*d, where c is a digit. Returns carry.
554 Lengths: a[digits], b[digits], d[digits].
556 static NN_DIGIT NN_AddDigitMult (a, b, c, d, digits)
557 NN_DIGIT *a, *b, c, *d;
560 NN_DIGIT carry, t[2];
567 for (i = 0; i < digits; i++) {
568 NN_DigitMult (t, c, d[i]);
569 if ((a[i] = b[i] + carry) < carry)
573 if ((a[i] += t[0]) < t[0])
581 /* Computes a = b - c*d, where c is a digit. Returns borrow.
583 Lengths: a[digits], b[digits], d[digits].
585 static NN_DIGIT NN_SubDigitMult (a, b, c, d, digits)
586 NN_DIGIT *a, *b, c, *d;
589 NN_DIGIT borrow, t[2];
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))
602 if ((a[i] -= t[0]) > (MAX_NN_DIGIT - t[0]))
610 /* Returns the significant length of a in bits, where a is a digit.
612 static unsigned int NN_DigitBits (a)
617 for (i = 0; i < NN_DIGIT_BITS; i++, a >>= 1)