chiark / gitweb /
ec-bin (ec_binproj): Make curve setup faster.
[catacomb] / rsa-gen.c
1 /* -*-c-*-
2  *
3  * $Id$
4  *
5  * RSA parameter generation
6  *
7  * (c) 1999 Straylight/Edgeware
8  */
9
10 /*----- Licensing notice --------------------------------------------------* 
11  *
12  * This file is part of Catacomb.
13  *
14  * Catacomb is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU Library General Public License as
16  * published by the Free Software Foundation; either version 2 of the
17  * License, or (at your option) any later version.
18  * 
19  * Catacomb is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU Library General Public License for more details.
23  * 
24  * You should have received a copy of the GNU Library General Public
25  * License along with Catacomb; if not, write to the Free
26  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
27  * MA 02111-1307, USA.
28  */
29
30 /*----- Header files ------------------------------------------------------*/
31
32 #include <mLib/dstr.h>
33
34 #include "grand.h"
35 #include "mp.h"
36 #include "mpint.h"
37 #include "pgen.h"
38 #include "rsa.h"
39 #include "strongprime.h"
40
41 /*----- Main code ---------------------------------------------------------*/
42
43 /* --- @rsa_gen@ --- *
44  *
45  * Arguments:   @rsa_priv *rp@ = pointer to block to be filled in
46  *              @unsigned nbits@ = required modulus size in bits
47  *              @grand *r@ = random number source
48  *              @unsigned n@ = number of attempts to make
49  *              @pgen_proc *event@ = event handler function
50  *              @void *ectx@ = argument for the event handler
51  *
52  * Returns:     Zero if all went well, nonzero otherwise.
53  *
54  * Use:         Constructs a pair of strong RSA primes and other useful RSA
55  *              parameters.  A small encryption exponent is chosen if
56  *              possible.
57  */
58
59 int rsa_gen(rsa_priv *rp, unsigned nbits, grand *r, unsigned n,
60             pgen_proc *event, void *ectx)
61 {
62   pgen_gcdstepctx g;
63   mp *phi = MP_NEW;
64
65   /* --- Bits of initialization --- */
66
67   rp->e = mp_fromulong(MP_NEW, 0x10001);
68   rp->d = MP_NEW;
69
70   /* --- Generate strong primes %$p$% and %$q$% --- *
71    *
72    * Constrain the GCD of @q@ to ensure that overly small private exponents
73    * are impossible.  Current results suggest that if %$d < n^{0.29}$% then
74    * it can be guessed fairly easily.  This implementation is rather more
75    * conservative about that sort of thing.
76    */
77
78 again:
79   if ((rp->p = strongprime("p", MP_NEWSEC, nbits/2, r, n, event, ectx)) == 0)
80     goto fail_p;
81
82   /* --- Do painful fiddling with GCD steppers --- */
83
84   {
85     mp *q;
86     rabin rb;
87
88     if ((q = strongprime_setup("q", MP_NEWSEC, &g.jp, nbits / 2,
89                                r, n, event, ectx)) == 0)
90       goto fail_q;
91     g.r = mp_lsr(MP_NEW, rp->p, 1);
92     g.g = MP_NEW;
93     g.max = MP_256;
94     q = pgen("q", q, q, event, ectx, n, pgen_gcdstep, &g,
95                  rabin_iters(nbits/2), pgen_test, &rb);
96     pfilt_destroy(&g.jp);
97     mp_drop(g.r);
98     if (!q) {
99       mp_drop(g.g);
100       if (n)
101         goto fail_q;
102       mp_drop(rp->p);
103       goto again;
104     }
105     rp->q = q;
106   }
107
108   /* --- Ensure that %$p > q$% --- *
109    *
110    * Also ensure that %$p$% and %$q$% are sufficiently different to deter
111    * square-root-based factoring methods.
112    */
113
114   phi = mp_sub(phi, rp->p, rp->q);
115   if (MP_LEN(phi) * 4 < MP_LEN(rp->p) * 3 ||
116       MP_LEN(phi) * 4 < MP_LEN(rp->q) * 3) {
117     mp_drop(rp->p);
118     mp_drop(g.g);
119     if (n)
120       goto fail_q;
121     mp_drop(rp->q);
122     goto again;
123   }
124
125   if (MP_NEGP(phi)) {
126     mp *z = rp->p;
127     rp->p = rp->q;
128     rp->q = z;
129   }
130
131   /* --- Work out the modulus and the CRT coefficient --- */
132
133   rp->n = mp_mul(MP_NEW, rp->p, rp->q);
134   rp->q_inv = mp_modinv(MP_NEW, rp->q, rp->p);
135
136   /* --- Work out %$\varphi(n) = (p - 1)(q - 1)$% --- *
137    *
138    * Save on further multiplications by noting that %$n = pq$% is known and
139    * that %$(p - 1)(q - 1) = pq - p - q + 1$%.  To minimize the size of @d@
140    * (useful for performance reasons, although not very because an overly
141    * small @d@ will be rejected for security reasons) this is then divided by
142    * %$\gcd(p - 1, q - 1)$%.
143    */
144
145   phi = mp_sub(phi, rp->n, rp->p);
146   phi = mp_sub(phi, phi, rp->q);
147   phi = mp_add(phi, phi, MP_ONE);
148   phi = mp_lsr(phi, phi, 1);
149   mp_div(&phi, 0, phi, g.g);
150
151   /* --- Decide on a public exponent --- *
152    *
153    * Simultaneously compute the private exponent.
154    */
155
156   mp_gcd(&g.g, 0, &rp->d, phi, rp->e);
157   if (!MP_EQ(g.g, MP_ONE) && MP_LEN(rp->d) * 4 > MP_LEN(rp->n) * 3)
158     goto fail_e;
159
160   /* --- Work out exponent residues --- */
161
162   rp->dp = MP_NEW; phi = mp_sub(phi, rp->p, MP_ONE);
163   mp_div(0, &rp->dp, rp->d, phi);
164
165   rp->dq = MP_NEW; phi = mp_sub(phi, rp->q, MP_ONE);
166   mp_div(0, &rp->dq, rp->d, phi);
167
168   /* --- Done --- */
169
170   mp_drop(phi);
171   mp_drop(g.g);
172   return (0);
173
174   /* --- Tidy up when something goes wrong --- */
175
176 fail_e:
177   mp_drop(g.g);
178   mp_drop(phi);
179   mp_drop(rp->n);
180   mp_drop(rp->q_inv);
181   mp_drop(rp->q);
182 fail_q:
183   mp_drop(rp->p);
184 fail_p:
185   mp_drop(rp->e);
186   if (rp->d)
187     mp_drop(rp->d);
188   return (-1);
189 }
190
191 /*----- That's all, folks -------------------------------------------------*/