|
|
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.