--- rsaref/source/prime.c 2018/04/24 16:37:52 1.1 +++ rsaref/source/prime.c 2018/04/24 16:38:19 1.1.1.2 @@ -1,100 +1,74 @@ /* PRIME.C - primality-testing 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. */ #include "global.h" #include "rsaref.h" +#include "r_random.h" #include "nn.h" #include "prime.h" static unsigned int SMALL_PRIMES[] = { 3, 5, 7, 11 }; #define SMALL_PRIME_COUNT 4 -static int RSAPrime PROTO_LIST - ((NN_DIGIT *, unsigned int, NN_DIGIT *, unsigned int)); static int ProbablePrime PROTO_LIST ((NN_DIGIT *, unsigned int)); static int SmallFactor PROTO_LIST ((NN_DIGIT *, unsigned int)); static int FermatTest PROTO_LIST ((NN_DIGIT *, unsigned int)); -static int RelativelyPrime PROTO_LIST - ((NN_DIGIT *, unsigned int, NN_DIGIT *, unsigned int)); -/* Find a probable prime a between 3*2^(b-2) and 2^b-1, starting at - 3*2^(b-2) + (c mod 2^(b-2)), such that gcd (a-1, d) = 1. +/* Generates a probable prime a between b and c such that a-1 is + divisible by d. - Lengths: a[cDigits], c[cDigits], d[dDigits]. - Assumes b > 2, b < cDigits * NN_DIGIT_BITS, d is odd, - cDigits < MAX_NN_DIGITS, dDigits < MAX_NN_DIGITS, and a - probable prime can be found. - */ -void FindRSAPrime (a, b, c, cDigits, d, dDigits) -NN_DIGIT *a, *c, *d; -unsigned int b, cDigits, dDigits; + Lengths: a[digits], b[digits], c[digits], d[digits]. + Assumes b < c, digits < MAX_NN_DIGITS. + + Returns RE_NEED_RANDOM if randomStruct not seeded, RE_DATA if + unsuccessful. + */ +int GeneratePrime (a, b, c, d, digits, randomStruct) +NN_DIGIT *a, *b, *c, *d; +unsigned int digits; +R_RANDOM_STRUCT *randomStruct; { - NN_DIGIT t[MAX_NN_DIGITS], u[MAX_NN_DIGITS], v[MAX_NN_DIGITS], - w[MAX_NN_DIGITS]; - - /* Compute t = 2^(b-2), u = 3*2^(b-2). - */ - NN_Assign2Exp (t, b-2, cDigits); - NN_Assign2Exp (u, b-1, cDigits); - NN_Add (u, u, t, cDigits); - - /* Compute v = 3*2^(b-2) + (c mod 2^(b-2)); add one if even. - */ - NN_Mod (v, c, cDigits, t, cDigits); - NN_Add (v, v, u, cDigits); - if (NN_EVEN (v, cDigits)) { - NN_ASSIGN_DIGIT (w, 1, cDigits); - NN_Add (v, v, w, cDigits); - } - - /* Compute w = 2, u = 2^b - 2. - */ - NN_ASSIGN_DIGIT (w, 2, cDigits); - NN_Sub (u, u, w, cDigits); - NN_Add (u, u, t, cDigits); + int status; + unsigned char block[MAX_NN_DIGITS * NN_DIGIT_LEN]; + NN_DIGIT t[MAX_NN_DIGITS], u[MAX_NN_DIGITS]; - /* Search to 2^b-1 from starting point, then from 3*2^(b-2)+1. + /* Generate random number between b and c. */ - while (! RSAPrime (v, cDigits, d, dDigits)) { - if (NN_Cmp (v, u, cDigits) > 0) - NN_Sub (v, v, t, cDigits); - NN_Add (v, v, w, cDigits); + if (status = R_GenerateBytes (block, digits * NN_DIGIT_LEN, randomStruct)) + return (status); + NN_Decode (a, digits, block, digits * NN_DIGIT_LEN); + NN_Sub (t, c, b, digits); + NN_ASSIGN_DIGIT (u, 1, digits); + NN_Add (t, t, u, digits); + NN_Mod (a, a, digits, t, digits); + NN_Add (a, a, b, digits); + + /* Adjust so that a-1 is divisible by d. + */ + NN_Mod (t, a, digits, d, digits); + NN_Sub (a, a, t, digits); + NN_Add (a, a, u, digits); + if (NN_Cmp (a, b, digits) < 0) + NN_Add (a, a, d, digits); + if (NN_Cmp (a, c, digits) > 0) + NN_Sub (a, a, d, digits); + + /* Search to c in steps of d. + */ + NN_Assign (t, c, digits); + NN_Sub (t, t, d, digits); + + while (! ProbablePrime (a, digits)) { + if (NN_Cmp (a, t, digits) > 0) + return (RE_DATA); + NN_Add (a, a, d, digits); } - - NN_Assign (a, v, cDigits); - - /* Zeroize sensitive information. - */ - R_memset ((POINTER)v, 0, sizeof (v)); -} - -/* Returns nonzero iff a is a probable prime and GCD (a-1, b) = 1. - - Lengths: a[aDigits], b[bDigits]. - Assumes aDigits < MAX_NN_DIGITS, bDigits < MAX_NN_DIGITS. - */ -static int RSAPrime (a, aDigits, b, bDigits) -NN_DIGIT *a, *b; -unsigned int aDigits, bDigits; -{ - int status; - NN_DIGIT aMinus1[MAX_NN_DIGITS], t[MAX_NN_DIGITS]; - - NN_ASSIGN_DIGIT (t, 1, aDigits); - NN_Sub (aMinus1, a, t, aDigits); - - status = ProbablePrime (a, aDigits) && - RelativelyPrime (aMinus1, aDigits, b, bDigits); - /* Zeroize sensitive information. - */ - R_memset ((POINTER)aMinus1, 0, sizeof (aMinus1)); - - return (status); + return (0); } /* Returns nonzero iff a is a probable prime. @@ -126,6 +100,8 @@ unsigned int aDigits; for (i = 0; i < SMALL_PRIME_COUNT; i++) { NN_ASSIGN_DIGIT (t, SMALL_PRIMES[i], 1); + if ((aDigits == 1) && ! NN_Cmp (a, t, 1)) + break; NN_Mod (t, a, aDigits, t, 1); if (NN_Zero (t, 1)) { status = 1; @@ -165,29 +141,3 @@ unsigned int aDigits; return (status); } - -/* Returns nonzero iff a and b are relatively prime. - - Lengths: a[aDigits], b[bDigits]. - Assumes aDigits >= bDigits, aDigits < MAX_NN_DIGITS. - */ -static int RelativelyPrime (a, aDigits, b, bDigits) -NN_DIGIT *a, *b; -unsigned int aDigits, bDigits; -{ - int status; - NN_DIGIT t[MAX_NN_DIGITS], u[MAX_NN_DIGITS]; - - NN_AssignZero (t, aDigits); - NN_Assign (t, b, bDigits); - NN_Gcd (t, a, t, aDigits); - NN_ASSIGN_DIGIT (u, 1, aDigits); - - status = NN_EQUAL (t, u, aDigits); - - /* Zeroize sensitive information. - */ - R_memset ((POINTER)t, 0, sizeof (t)); - - return (status); -}