prime generation: Deploy the new Baillie--PSW testers.
[catacomb] / pub / rsa-gen.c
CommitLineData
01898d8e 1/* -*-c-*-
2 *
01898d8e 3 * RSA parameter generation
4 *
5 * (c) 1999 Straylight/Edgeware
6 */
7
45c0fd36 8/*----- Licensing notice --------------------------------------------------*
01898d8e 9 *
10 * This file is part of Catacomb.
11 *
12 * Catacomb is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Library General Public License as
14 * published by the Free Software Foundation; either version 2 of the
15 * License, or (at your option) any later version.
45c0fd36 16 *
01898d8e 17 * Catacomb is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Library General Public License for more details.
45c0fd36 21 *
01898d8e 22 * You should have received a copy of the GNU Library General Public
23 * License along with Catacomb; if not, write to the Free
24 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25 * MA 02111-1307, USA.
26 */
27
01898d8e 28/*----- Header files ------------------------------------------------------*/
29
30#include <mLib/dstr.h>
31
32#include "grand.h"
33#include "mp.h"
bb2e2fd8 34#include "mpint.h"
01898d8e 35#include "pgen.h"
36#include "rsa.h"
37#include "strongprime.h"
38
39/*----- Main code ---------------------------------------------------------*/
40
8de0fc89 41/* --- @rsa_gen@, @rsa_gen_e --- *
01898d8e 42 *
b82ec4e8 43 * Arguments: @rsa_priv *rp@ = pointer to block to be filled in
01898d8e 44 * @unsigned nbits@ = required modulus size in bits
8de0fc89 45 * @mp *e@ = public exponent
01898d8e 46 * @grand *r@ = random number source
47 * @unsigned n@ = number of attempts to make
48 * @pgen_proc *event@ = event handler function
49 * @void *ectx@ = argument for the event handler
50 *
51 * Returns: Zero if all went well, nonzero otherwise.
52 *
53 * Use: Constructs a pair of strong RSA primes and other useful RSA
54 * parameters. A small encryption exponent is chosen if
55 * possible.
56 */
57
8de0fc89
MW
58static int genprime(mp **pp, mp **dd, const char *name,
59 unsigned nbits, mp *e,
60 grand *r, unsigned nsteps, pgen_proc *event, void *ectx)
01898d8e 61{
8de0fc89
MW
62 pgen_jumpctx jctx; pfilt j;
63 mp *p = MP_NEWSEC, *t = MP_NEW, *u = MP_NEW;
8de0fc89
MW
64 mpw p3, j3, a;
65 int rc = -1;
66
67 j.m = MP_NEW;
68
69 /* Find a start position for the search. */
70 p = strongprime_setup(name, p, &j, nbits, r, nsteps, event, ectx);
71 if (!p) goto end;
72
73 /* Special handling for e = 3. */
74 if (MP_EQ(e, MP_THREE)) {
75 /* We must have p == 2 (mod 3): if p == 0 (mod 3) then p is not prime; if
76 * p == 1 (mod 3) then e|(p - 1). So fiddle the start position and jump
77 * context to allow for this.
78 */
79
80 /* Figure out the residues of the start position and jump. */
81 mp_div(0, &t, p, MP_THREE); p3 = t->v[0];
82 mp_div(0, &u, j.m, MP_THREE); j3 = u->v[0];
83
84 /* If the jump is a multiple of three already, then we're stuffed unless
85 * the start position is 2 (mod 3). This shouldn't happen, since the
86 * jump should be twice a multiple of two large primes, which will be
87 * nonzero (mod 3).
88 *
89 * Set a = (2 - p) j mod 3. Then p' = p + a j == p (mod j), and p' ==
90 * p + (2 - p) j^2 == 2 (mod 3).
91 */
92 assert(j3 != 0);
93 a = ((2 - p3)*j3)%3;
94 if (a == 1) p = mp_add(p, p, j.m);
95 else if (a == 2) { t = mp_lsl(t, j.m, 1); p = mp_add(p, p, t); }
96
97 /* Finally, multiply j by three to make sure it preserves this
98 * congruence.
99 */
100 pfilt_muladd(&j, &j, 3, 0);
bb2e2fd8 101 }
102
8de0fc89
MW
103 /* Set the search going. */
104 jctx.j = &j;
105 p = pgen(name, p, p, event, ectx,
106 nsteps, pgen_jump, &jctx,
fbfcb6c0 107 PGEN_BAILLIEPSWNTESTS, pgen_bailliepswtest, 0);
8de0fc89
MW
108
109 if (!p) goto end;
110
111 /* Check the GCD constraint. */
112 t = mp_sub(t, p, MP_ONE);
113 mp_gcd(&t, &u, 0, e, t);
114 if (!MP_EQ(t, MP_ONE)) goto end;
115
116 /* All is good. */
117 mp_drop(*pp); *pp = p; p = 0;
118 mp_drop(*dd); *dd = u; u = 0;
119 rc = 0;
120end:
121 mp_drop(p); mp_drop(t); mp_drop(u);
122 mp_drop(j.m);
123 return (rc);
124}
bb2e2fd8 125
8de0fc89
MW
126int rsa_gen_e(rsa_priv *rp, unsigned nbits, mp *e,
127 grand *r, unsigned nsteps, pgen_proc *event, void *ectx)
128{
129 mp *p = MP_NEWSEC, *q = MP_NEWSEC, *n = MP_NEW;
130 mp *dp = MP_NEWSEC, *dq = MP_NEWSEC;
131 mp *t = MP_NEW, *u = MP_NEW, *v = MP_NEW;
132 mp *tt;
133 int rc = -1;
134
135#define RETRY(what) \
136 do { if (nsteps) goto fail; else goto retry_##what; } while (0)
137
138 /* Find the first prime. */
139retry_all:
140retry_p:
141 if (genprime(&p, &dp, "p", nbits/2, e, r, nsteps, event, ectx))
142 RETRY(p);
143
144 /* Find the second prime. */
145retry_q:
146 if (genprime(&q, &dq, "q", nbits/2, e, r, nsteps, event, ectx))
147 RETRY(q);
148
149 /* Check that gcd(p - 1, q - 1) is sufficiently large. */
150 u = mp_sub(u, p, MP_ONE);
151 v = mp_sub(v, q, MP_ONE);
152 mp_gcd(&t, 0, 0, u, v);
153 if (mp_bits(t) >= 8) RETRY(all);
154
155 /* Arrange for p > q. */
156 if (MP_CMP(p, <, q)) {
157 tt = p; p = q; q = tt;
158 tt = dp; dp = dq; dq = tt;
bb2e2fd8 159 }
01898d8e 160
8de0fc89
MW
161 /* Check that the modulus is the right size. */
162 n = mp_mul(n, p, q);
163 if (mp_bits(n) != nbits) RETRY(all);
01898d8e 164
8de0fc89
MW
165 /* Now we want to calculate d. The unit-group exponent is λ = lcm(p - 1,
166 * q - 1), so d == e^-1 (mod λ).
01898d8e 167 */
8de0fc89
MW
168 u = mp_mul(u, u, v);
169 mp_div(&t, 0, u, t);
170 rp->d = mp_modinv(MP_NEW, e, t);
171
172 /* All done. */
173 rp->e = MP_COPY(e);
174 rp->q_inv = mp_modinv(MP_NEW, q, p);
175 rp->p = p; p = 0; rp->dp = dp; dp = 0;
176 rp->q = q; q = 0; rp->dq = dq; dq = 0;
177 rp->n = n; n = 0;
178 rc = 0;
179
180fail:
181 mp_drop(p); mp_drop(dp);
182 mp_drop(q); mp_drop(dq);
183 mp_drop(n);
184 mp_drop(t); mp_drop(u); mp_drop(v);
185 return (rc);
186}
01898d8e 187
8de0fc89
MW
188int rsa_gen(rsa_priv *rp, unsigned nbits,
189 grand *r, unsigned nsteps, pgen_proc *event, void *ectx)
190{
191 mp *f4 = mp_fromulong(MP_NEW, 65537);
192 int rc = rsa_gen_e(rp, nbits, f4, r, nsteps, event, ectx);
193 mp_drop(f4); return (rc);
01898d8e 194}
195
196/*----- That's all, folks -------------------------------------------------*/