|
|
1.1 ! root 1: /* PRIME.C - primality-testing routines ! 2: */ ! 3: ! 4: /* Copyright (C) 1991-2 RSA Laboratories, a division of RSA Data ! 5: Security, Inc. All rights reserved. ! 6: */ ! 7: ! 8: #include "global.h" ! 9: #include "rsaref.h" ! 10: #include "nn.h" ! 11: #include "prime.h" ! 12: ! 13: static unsigned int SMALL_PRIMES[] = { 3, 5, 7, 11 }; ! 14: #define SMALL_PRIME_COUNT 4 ! 15: ! 16: static int RSAPrime PROTO_LIST ! 17: ((NN_DIGIT *, unsigned int, NN_DIGIT *, unsigned int)); ! 18: static int ProbablePrime PROTO_LIST ((NN_DIGIT *, unsigned int)); ! 19: static int SmallFactor PROTO_LIST ((NN_DIGIT *, unsigned int)); ! 20: static int FermatTest PROTO_LIST ((NN_DIGIT *, unsigned int)); ! 21: static int RelativelyPrime PROTO_LIST ! 22: ((NN_DIGIT *, unsigned int, NN_DIGIT *, unsigned int)); ! 23: ! 24: /* Find a probable prime a between 3*2^(b-2) and 2^b-1, starting at ! 25: 3*2^(b-2) + (c mod 2^(b-2)), such that gcd (a-1, d) = 1. ! 26: ! 27: Lengths: a[cDigits], c[cDigits], d[dDigits]. ! 28: Assumes b > 2, b < cDigits * NN_DIGIT_BITS, d is odd, ! 29: cDigits < MAX_NN_DIGITS, dDigits < MAX_NN_DIGITS, and a ! 30: probable prime can be found. ! 31: */ ! 32: void FindRSAPrime (a, b, c, cDigits, d, dDigits) ! 33: NN_DIGIT *a, *c, *d; ! 34: unsigned int b, cDigits, dDigits; ! 35: { ! 36: NN_DIGIT t[MAX_NN_DIGITS], u[MAX_NN_DIGITS], v[MAX_NN_DIGITS], ! 37: w[MAX_NN_DIGITS]; ! 38: ! 39: /* Compute t = 2^(b-2), u = 3*2^(b-2). ! 40: */ ! 41: NN_Assign2Exp (t, b-2, cDigits); ! 42: NN_Assign2Exp (u, b-1, cDigits); ! 43: NN_Add (u, u, t, cDigits); ! 44: ! 45: /* Compute v = 3*2^(b-2) + (c mod 2^(b-2)); add one if even. ! 46: */ ! 47: NN_Mod (v, c, cDigits, t, cDigits); ! 48: NN_Add (v, v, u, cDigits); ! 49: if (NN_EVEN (v, cDigits)) { ! 50: NN_ASSIGN_DIGIT (w, 1, cDigits); ! 51: NN_Add (v, v, w, cDigits); ! 52: } ! 53: ! 54: /* Compute w = 2, u = 2^b - 2. ! 55: */ ! 56: NN_ASSIGN_DIGIT (w, 2, cDigits); ! 57: NN_Sub (u, u, w, cDigits); ! 58: NN_Add (u, u, t, cDigits); ! 59: ! 60: /* Search to 2^b-1 from starting point, then from 3*2^(b-2)+1. ! 61: */ ! 62: while (! RSAPrime (v, cDigits, d, dDigits)) { ! 63: if (NN_Cmp (v, u, cDigits) > 0) ! 64: NN_Sub (v, v, t, cDigits); ! 65: NN_Add (v, v, w, cDigits); ! 66: } ! 67: ! 68: NN_Assign (a, v, cDigits); ! 69: ! 70: /* Zeroize sensitive information. ! 71: */ ! 72: R_memset ((POINTER)v, 0, sizeof (v)); ! 73: } ! 74: ! 75: /* Returns nonzero iff a is a probable prime and GCD (a-1, b) = 1. ! 76: ! 77: Lengths: a[aDigits], b[bDigits]. ! 78: Assumes aDigits < MAX_NN_DIGITS, bDigits < MAX_NN_DIGITS. ! 79: */ ! 80: static int RSAPrime (a, aDigits, b, bDigits) ! 81: NN_DIGIT *a, *b; ! 82: unsigned int aDigits, bDigits; ! 83: { ! 84: int status; ! 85: NN_DIGIT aMinus1[MAX_NN_DIGITS], t[MAX_NN_DIGITS]; ! 86: ! 87: NN_ASSIGN_DIGIT (t, 1, aDigits); ! 88: NN_Sub (aMinus1, a, t, aDigits); ! 89: ! 90: status = ProbablePrime (a, aDigits) && ! 91: RelativelyPrime (aMinus1, aDigits, b, bDigits); ! 92: ! 93: /* Zeroize sensitive information. ! 94: */ ! 95: R_memset ((POINTER)aMinus1, 0, sizeof (aMinus1)); ! 96: ! 97: return (status); ! 98: } ! 99: ! 100: /* Returns nonzero iff a is a probable prime. ! 101: ! 102: Lengths: a[aDigits]. ! 103: Assumes aDigits < MAX_NN_DIGITS. ! 104: */ ! 105: static int ProbablePrime (a, aDigits) ! 106: NN_DIGIT *a; ! 107: unsigned int aDigits; ! 108: { ! 109: return (! SmallFactor (a, aDigits) && FermatTest (a, aDigits)); ! 110: } ! 111: ! 112: /* Returns nonzero iff a has a prime factor in SMALL_PRIMES. ! 113: ! 114: Lengths: a[aDigits]. ! 115: Assumes aDigits < MAX_NN_DIGITS. ! 116: */ ! 117: static int SmallFactor (a, aDigits) ! 118: NN_DIGIT *a; ! 119: unsigned int aDigits; ! 120: { ! 121: int status; ! 122: NN_DIGIT t[1]; ! 123: unsigned int i; ! 124: ! 125: status = 0; ! 126: ! 127: for (i = 0; i < SMALL_PRIME_COUNT; i++) { ! 128: NN_ASSIGN_DIGIT (t, SMALL_PRIMES[i], 1); ! 129: NN_Mod (t, a, aDigits, t, 1); ! 130: if (NN_Zero (t, 1)) { ! 131: status = 1; ! 132: break; ! 133: } ! 134: } ! 135: ! 136: /* Zeroize sensitive information. ! 137: */ ! 138: i = 0; ! 139: R_memset ((POINTER)t, 0, sizeof (t)); ! 140: ! 141: return (status); ! 142: } ! 143: ! 144: /* Returns nonzero iff a passes Fermat's test for witness 2. ! 145: (All primes pass the test, and nearly all composites fail.) ! 146: ! 147: Lengths: a[aDigits]. ! 148: Assumes aDigits < MAX_NN_DIGITS. ! 149: */ ! 150: static int FermatTest (a, aDigits) ! 151: NN_DIGIT *a; ! 152: unsigned int aDigits; ! 153: { ! 154: int status; ! 155: NN_DIGIT t[MAX_NN_DIGITS], u[MAX_NN_DIGITS]; ! 156: ! 157: NN_ASSIGN_DIGIT (t, 2, aDigits); ! 158: NN_ModExp (u, t, a, aDigits, a, aDigits); ! 159: ! 160: status = NN_EQUAL (t, u, aDigits); ! 161: ! 162: /* Zeroize sensitive information. ! 163: */ ! 164: R_memset ((POINTER)u, 0, sizeof (u)); ! 165: ! 166: return (status); ! 167: } ! 168: ! 169: /* Returns nonzero iff a and b are relatively prime. ! 170: ! 171: Lengths: a[aDigits], b[bDigits]. ! 172: Assumes aDigits >= bDigits, aDigits < MAX_NN_DIGITS. ! 173: */ ! 174: static int RelativelyPrime (a, aDigits, b, bDigits) ! 175: NN_DIGIT *a, *b; ! 176: unsigned int aDigits, bDigits; ! 177: { ! 178: int status; ! 179: NN_DIGIT t[MAX_NN_DIGITS], u[MAX_NN_DIGITS]; ! 180: ! 181: NN_AssignZero (t, aDigits); ! 182: NN_Assign (t, b, bDigits); ! 183: NN_Gcd (t, a, t, aDigits); ! 184: NN_ASSIGN_DIGIT (u, 1, aDigits); ! 185: ! 186: status = NN_EQUAL (t, u, aDigits); ! 187: ! 188: /* Zeroize sensitive information. ! 189: */ ! 190: R_memset ((POINTER)t, 0, sizeof (t)); ! 191: ! 192: return (status); ! 193: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.