--- rsaref/source/nn.c 2018/04/24 16:37:52 1.1.1.1 +++ rsaref/source/nn.c 2018/04/24 16:38:54 1.1.1.3 @@ -1,36 +1,15 @@ /* NN.C - natural numbers routines */ -/* Copyright (C) 1991-2 RSA Laboratories, a division of RSA Data - Security, Inc. All rights reserved. +/* Copyright (C) RSA Laboratories, a division of RSA Data Security, + Inc., created 1991. All rights reserved. */ -/* - * CHANGES MADE TO THIS FILE UNDER RSAREF license clause 1(c): - * - * For the MIT PGP 2.6 distribution, this file was modified to permit - * replacement of the NN_ModExp routine by an equivalent routine - * contained in the PGP 2.6 sources. To enable this change, an #ifdef - * was added to this file (search for #ifndef USEMPILIB - * below). RSAREF *must* be compiled with USEMPILIB defined for this - * change to occur. - * - * Change made May 21, 1994. - */ - #include "global.h" #include "rsaref.h" #include "nn.h" #include "digit.h" -static NN_DIGIT NN_LShift PROTO_LIST - ((NN_DIGIT *, NN_DIGIT *, unsigned int, unsigned int)); -static NN_DIGIT NN_RShift PROTO_LIST - ((NN_DIGIT *, NN_DIGIT *, unsigned int, unsigned int)); -static void NN_Div PROTO_LIST - ((NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int, NN_DIGIT *, - unsigned int)); - static NN_DIGIT NN_AddDigitMult PROTO_LIST ((NN_DIGIT *, NN_DIGIT *, NN_DIGIT, NN_DIGIT *, unsigned int)); static NN_DIGIT NN_SubDigitMult PROTO_LIST @@ -41,7 +20,7 @@ static unsigned int NN_DigitBits PROTO_L /* Decodes character string b into a, where character string is ordered from most to least significant. - Length: a[digits], b[len]. + Lengths: a[digits], b[len]. Assumes b[i] = 0 for i < len - digits * NN_DIGIT_LEN. (Otherwise most significant bytes are truncated.) */ @@ -54,7 +33,7 @@ unsigned int digits, len; int j; unsigned int i, u; - for (i = 0, j = len - 1; j >= 0; i++) { + for (i = 0, j = len - 1; i < digits && j >= 0; i++) { t = 0; for (u = 0; j >= 0 && u < NN_DIGIT_BITS; j--, u += 8) t |= ((NN_DIGIT)b[j]) << u; @@ -81,7 +60,7 @@ unsigned int digits, len; int j; unsigned int i, u; - for (i = 0, j = len - 1; i < digits; i++) { + for (i = 0, j = len - 1; i < digits && j >= 0; i++) { t = b[i]; for (u = 0; j >= 0 && u < NN_DIGIT_BITS; j--, u += 8) a[j] = (unsigned char)(t >> u); @@ -91,7 +70,7 @@ unsigned int digits, len; a[j] = 0; } -/* Assigns a = 0. +/* Assigns a = b. Lengths: a[digits], b[digits]. */ @@ -215,6 +194,121 @@ unsigned int digits; R_memset ((POINTER)t, 0, sizeof (t)); } +/* Computes a = b * 2^c (i.e., shifts left c bits), returning carry. + + Lengths: a[digits], b[digits]. + Requires c < NN_DIGIT_BITS. + */ +NN_DIGIT NN_LShift (a, b, c, digits) +NN_DIGIT *a, *b; +unsigned int c, digits; +{ + NN_DIGIT bi, carry; + unsigned int i, t; + + if (c >= NN_DIGIT_BITS) + return (0); + + t = NN_DIGIT_BITS - c; + + carry = 0; + + for (i = 0; i < digits; i++) { + bi = b[i]; + a[i] = (bi << c) | carry; + carry = c ? (bi >> t) : 0; + } + + return (carry); +} + +/* Computes a = c div 2^c (i.e., shifts right c bits), returning carry. + + Lengths: a[digits], b[digits]. + Requires: c < NN_DIGIT_BITS. + */ +NN_DIGIT NN_RShift (a, b, c, digits) +NN_DIGIT *a, *b; +unsigned int c, digits; +{ + NN_DIGIT bi, carry; + int i; + unsigned int t; + + if (c >= NN_DIGIT_BITS) + return (0); + + t = NN_DIGIT_BITS - c; + + carry = 0; + + for (i = digits - 1; i >= 0; i--) { + bi = b[i]; + a[i] = (bi >> c) | carry; + carry = c ? (bi << t) : 0; + } + + return (carry); +} + +/* Computes a = c div d and b = c mod d. + + Lengths: a[cDigits], b[dDigits], c[cDigits], d[dDigits]. + Assumes d > 0, cDigits < 2 * MAX_NN_DIGITS, + dDigits < MAX_NN_DIGITS. + */ +void NN_Div (a, b, c, cDigits, d, dDigits) +NN_DIGIT *a, *b, *c, *d; +unsigned int cDigits, dDigits; +{ + NN_DIGIT ai, cc[2*MAX_NN_DIGITS+1], dd[MAX_NN_DIGITS], t; + int i; + unsigned int ddDigits, shift; + + ddDigits = NN_Digits (d, dDigits); + if (ddDigits == 0) + return; + + /* Normalize operands. + */ + shift = NN_DIGIT_BITS - NN_DigitBits (d[ddDigits-1]); + NN_AssignZero (cc, ddDigits); + cc[cDigits] = NN_LShift (cc, c, shift, cDigits); + NN_LShift (dd, d, shift, ddDigits); + t = dd[ddDigits-1]; + + NN_AssignZero (a, cDigits); + + for (i = cDigits-ddDigits; i >= 0; i--) { + /* Underestimate quotient digit and subtract. + */ + if (t == MAX_NN_DIGIT) + ai = cc[i+ddDigits]; + else + NN_DigitDiv (&ai, &cc[i+ddDigits-1], t + 1); + cc[i+ddDigits] -= NN_SubDigitMult (&cc[i], &cc[i], ai, dd, ddDigits); + + /* Correct estimate. + */ + while (cc[i+ddDigits] || (NN_Cmp (&cc[i], dd, ddDigits) >= 0)) { + ai++; + cc[i+ddDigits] -= NN_Sub (&cc[i], &cc[i], dd, ddDigits); + } + + a[i] = ai; + } + + /* Restore result. + */ + NN_AssignZero (b, dDigits); + NN_RShift (b, cc, shift, ddDigits); + + /* Zeroize potentially sensitive information. + */ + R_memset ((POINTER)cc, 0, sizeof (cc)); + R_memset ((POINTER)dd, 0, sizeof (dd)); +} + /* Computes a = b mod c. Lengths: a[cDigits], b[bDigits], c[cDigits]. @@ -252,24 +346,10 @@ unsigned int digits; R_memset ((POINTER)t, 0, sizeof (t)); } - -/* - * PGP 2.6's mpilib contains a faster modular exponentiation routine, - * mp_modexp. If USEMPILIB is defined, NN_ModExp is replaced in the - * PGP 2.6 sources with a stub call to mp_modexp. If USEMPILIB is - * not defined, we'll get a pure (albeit slower) RSAREF - * implementation. - * - * The RSAREF license, clause 1(c), permits "...modify[ing] the - * Program in any manner for porting or performance improvement - * purposes..." - */ -#ifndef USEMPILIB /* Computes a = b^c mod d. Lengths: a[dDigits], b[dDigits], c[cDigits], d[dDigits]. - Assumes b < d, d > 0, cDigits > 0, dDigits > 0, - dDigits < MAX_NN_DIGITS. + Assumes d > 0, cDigits > 0, dDigits < MAX_NN_DIGITS. */ void NN_ModExp (a, b, c, cDigits, d, dDigits) NN_DIGIT *a, *b, *c, *d; @@ -302,11 +382,11 @@ unsigned int cDigits, dDigits; } for (j = 0; j < ciBits; j += 2, ci <<= 2) { - /* Compute t = t^4 * b^s mod d, where s = two MSB's of d. + /* Compute t = t^4 * b^s mod d, where s = two MSB's of ci. */ NN_ModMult (t, t, t, d, dDigits); NN_ModMult (t, t, t, d, dDigits); - if (s = DIGIT_2MSB (ci)) + if ((s = DIGIT_2MSB (ci)) != 0) NN_ModMult (t, t, bPower[s-1], d, dDigits); } } @@ -318,7 +398,6 @@ unsigned int cDigits, dDigits; R_memset ((POINTER)bPower, 0, sizeof (bPower)); R_memset ((POINTER)t, 0, sizeof (t)); } -#endif /* Compute a = 1/b mod c, assuming inverse exists. @@ -470,121 +549,6 @@ unsigned int digits; return (i + 1); } -/* Computes a = b * 2^c (i.e., shifts left c bits), returning carry. - - Lengths: a[digits], b[digits]. - Requires c < NN_DIGIT_BITS. - */ -static NN_DIGIT NN_LShift (a, b, c, digits) -NN_DIGIT *a, *b; -unsigned int c, digits; -{ - NN_DIGIT bi, carry; - unsigned int i, t; - - if (c >= NN_DIGIT_BITS) - return (0); - - t = NN_DIGIT_BITS - c; - - carry = 0; - - for (i = 0; i < digits; i++) { - bi = b[i]; - a[i] = (bi << c) | carry; - carry = c ? (bi >> t) : 0; - } - - return (carry); -} - -/* Computes a = c div 2^c (i.e., shifts right c bits), returning carry. - - Lengths: a[digits], b[digits]. - Requires: c < NN_DIGIT_BITS. - */ -static NN_DIGIT NN_RShift (a, b, c, digits) -NN_DIGIT *a, *b; -unsigned int c, digits; -{ - NN_DIGIT bi, carry; - int i; - unsigned int t; - - if (c >= NN_DIGIT_BITS) - return (0); - - t = NN_DIGIT_BITS - c; - - carry = 0; - - for (i = digits - 1; i >= 0; i--) { - bi = b[i]; - a[i] = (bi >> c) | carry; - carry = c ? (bi << t) : 0; - } - - return (carry); -} - -/* Computes a = c div d and b = c mod d. - - Lengths: a[cDigits], b[dDigits], c[cDigits], d[dDigits]. - Assumes d > 0, cDigits < 2 * MAX_NN_DIGITS, - dDigits < MAX_NN_DIGITS. - */ -static void NN_Div (a, b, c, cDigits, d, dDigits) -NN_DIGIT *a, *b, *c, *d; -unsigned int cDigits, dDigits; -{ - NN_DIGIT ai, cc[2*MAX_NN_DIGITS+1], dd[MAX_NN_DIGITS], t; - int i; - unsigned int ddDigits, shift; - - ddDigits = NN_Digits (d, dDigits); - if (ddDigits == 0) - return; - - /* Normalize operands. - */ - shift = NN_DIGIT_BITS - NN_DigitBits (d[ddDigits-1]); - NN_AssignZero (cc, ddDigits); - cc[cDigits] = NN_LShift (cc, c, shift, cDigits); - NN_LShift (dd, d, shift, ddDigits); - t = dd[ddDigits-1]; - - NN_AssignZero (a, cDigits); - - for (i = cDigits-ddDigits; i >= 0; i--) { - /* Underestimate quotient digit and subtract. - */ - if (t == MAX_NN_DIGIT) - ai = cc[i+dDigits]; - else - NN_DigitDiv (&ai, &cc[i+ddDigits-1], t + 1); - cc[i+ddDigits] -= NN_SubDigitMult (&cc[i], &cc[i], ai, dd, ddDigits); - - /* Correct estimate. - */ - while (cc[i+ddDigits] || (NN_Cmp (&cc[i], dd, ddDigits) >= 0)) { - ai++; - cc[i+ddDigits] -= NN_Sub (&cc[i], &cc[i], dd, ddDigits); - } - - a[i] = ai; - } - - /* Restore result. - */ - NN_AssignZero (b, dDigits); - NN_RShift (b, cc, shift, ddDigits); - - /* Zeroize potentially sensitive information. - */ - R_memset ((POINTER)cc, 0, sizeof (cc)); - R_memset ((POINTER)dd, 0, sizeof (dd)); -} - /* Computes a = b + c*d, where c is a digit. Returns carry. Lengths: a[digits], b[digits], d[digits].