Remove bad type name `rsa_param'.
[u/mdw/catacomb] / rsa-gen.c
CommitLineData
01898d8e 1/* -*-c-*-
2 *
b82ec4e8 3 * $Id: rsa-gen.c,v 1.3 2000/07/01 11:22:22 mdw Exp $
01898d8e 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/*----- Revision history --------------------------------------------------*
31 *
32 * $Log: rsa-gen.c,v $
b82ec4e8 33 * Revision 1.3 2000/07/01 11:22:22 mdw
34 * Remove bad type name `rsa_param'.
35 *
bb2e2fd8 36 * Revision 1.2 2000/06/17 12:05:15 mdw
37 * Lots of changes:
38 *
39 * * Apply limits on %$\gcd(p - 1, q - 1)$% to reduce the space of
40 * equivalent decryption exponents.
41 *
42 * * Force %$e = F_4 = 2^{16} + 1$% to avoid small-encryption-exponent
43 * attacks.
44 *
45 * * Ensure that %$p > q$% and that %$p - q$% is large to deter
46 * square-root-based factoring methods.
47 *
48 * * Use %$e d \equiv 1 \pmod{\lambda(n)}$%, where %$\lambda(n)$% is
49 * %$\lcm(p - 1, q - 1)$%, as recommended in PKCS#1, rather than the
50 * more usual %$\varphi(n) = (p - 1)(q - 1)$%.
51 *
52 * * Handle aborts from pgen_jump.
53 *
01898d8e 54 * Revision 1.1 1999/12/22 15:50:45 mdw
55 * Initial RSA support.
56 *
57 */
58
59/*----- Header files ------------------------------------------------------*/
60
61#include <mLib/dstr.h>
62
63#include "grand.h"
64#include "mp.h"
bb2e2fd8 65#include "mpint.h"
01898d8e 66#include "pgen.h"
67#include "rsa.h"
68#include "strongprime.h"
69
70/*----- Main code ---------------------------------------------------------*/
71
72/* --- @rsa_gen@ --- *
73 *
b82ec4e8 74 * Arguments: @rsa_priv *rp@ = pointer to block to be filled in
01898d8e 75 * @unsigned nbits@ = required modulus size in bits
76 * @grand *r@ = random number source
77 * @unsigned n@ = number of attempts to make
78 * @pgen_proc *event@ = event handler function
79 * @void *ectx@ = argument for the event handler
80 *
81 * Returns: Zero if all went well, nonzero otherwise.
82 *
83 * Use: Constructs a pair of strong RSA primes and other useful RSA
84 * parameters. A small encryption exponent is chosen if
85 * possible.
86 */
87
b82ec4e8 88int rsa_gen(rsa_priv *rp, unsigned nbits, grand *r, unsigned n,
01898d8e 89 pgen_proc *event, void *ectx)
90{
bb2e2fd8 91 pgen_gcdstepctx g;
92 mp *phi = MP_NEW;
01898d8e 93
bb2e2fd8 94 /* --- Bits of initialization --- */
95
96 rp->e = mp_fromulong(MP_NEW, 0x10001);
97 rp->d = MP_NEW;
98
99 /* --- Generate strong primes %$p$% and %$q$% --- *
100 *
101 * Constrain the GCD of @q@ to ensure that overly small private exponents
102 * are impossible. Current results suggest that if %$d < n^{0.29}$% then
103 * it can be guessed fairly easily. This implementation is rather more
104 * conservative about that sort of thing.
105 */
01898d8e 106
bb2e2fd8 107again:
108 if ((rp->p = strongprime("p", MP_NEWSEC, nbits/2, r, n, event, ectx)) == 0)
01898d8e 109 goto fail_p;
bb2e2fd8 110
111 /* --- Do painful fiddling with GCD steppers --- */
112
113 {
114 mp *q;
115 rabin rb;
116
117 if ((q = strongprime_setup("q", MP_NEWSEC, &g.jp, nbits / 2,
118 r, n, event, ectx)) == 0)
119 goto fail_q;
120 g.r = mp_lsr(MP_NEW, rp->p, 1);
121 g.g = MP_NEW;
122 g.max = MP_256;
123 q = pgen("q", q, q, event, ectx, n, pgen_gcdstep, &g,
124 rabin_iters(nbits/2), pgen_test, &rb);
125 pfilt_destroy(&g.jp);
126 mp_drop(g.r);
127 if (!q) {
128 mp_drop(g.g);
129 if (n)
130 goto fail_q;
131 mp_drop(rp->p);
132 goto again;
133 }
134 rp->q = q;
135 }
136
137 /* --- Ensure that %$p > q$% --- *
138 *
139 * Also ensure that %$p$% and %$q$% are sufficiently different to deter
140 * square-root-based factoring methods.
141 */
142
143 phi = mp_sub(phi, rp->p, rp->q);
144 if (MP_LEN(phi) * 4 < MP_LEN(rp->p) * 3 ||
145 MP_LEN(phi) * 4 < MP_LEN(rp->q) * 3) {
146 mp_drop(rp->p);
147 mp_drop(g.g);
148 if (n)
149 goto fail_q;
150 mp_drop(rp->q);
151 goto again;
152 }
153
154 if (phi->f & MP_NEG) {
155 mp *z = rp->p;
156 rp->p = rp->q;
157 rp->q = z;
158 }
01898d8e 159
160 /* --- Work out the modulus and the CRT coefficient --- */
161
162 rp->n = mp_mul(MP_NEW, rp->p, rp->q);
163 rp->q_inv = MP_NEW; mp_gcd(0, 0, &rp->q_inv, rp->p, rp->q);
164
165 /* --- Work out %$\varphi(n) = (p - 1)(q - 1)$% --- *
166 *
167 * Save on further multiplications by noting that %$n = pq$% is known and
bb2e2fd8 168 * that %$(p - 1)(q - 1) = pq - p - q + 1$%. To minimize the size of @d@
169 * (useful for performance reasons, although not very because an overly
170 * small @d@ will be rejected for security reasons) this is then divided by
171 * %$\gcd(p - 1, q - 1)$%.
01898d8e 172 */
173
bb2e2fd8 174 phi = mp_sub(phi, rp->n, rp->p);
01898d8e 175 phi = mp_sub(phi, phi, rp->q);
176 phi = mp_add(phi, phi, MP_ONE);
bb2e2fd8 177 phi = mp_lsr(phi, phi, 1);
178 mp_div(&phi, 0, phi, g.g);
01898d8e 179
180 /* --- Decide on a public exponent --- *
181 *
182 * Simultaneously compute the private exponent.
183 */
184
bb2e2fd8 185 mp_gcd(&g.g, 0, &rp->d, phi, rp->e);
186 if (MP_CMP(g.g, !=, MP_ONE) && MP_LEN(rp->d) * 4 > MP_LEN(rp->n) * 3)
187 goto fail_e;
01898d8e 188
189 /* --- Work out exponent residues --- */
190
01898d8e 191 rp->dp = MP_NEW; phi = mp_sub(phi, rp->p, MP_ONE);
192 mp_div(0, &rp->dp, rp->d, phi);
193
194 rp->dq = MP_NEW; phi = mp_sub(phi, rp->q, MP_ONE);
195 mp_div(0, &rp->dq, rp->d, phi);
196
197 /* --- Done --- */
198
199 mp_drop(phi);
bb2e2fd8 200 mp_drop(g.g);
01898d8e 201 return (0);
202
203 /* --- Tidy up when something goes wrong --- */
204
205fail_e:
bb2e2fd8 206 mp_drop(g.g);
01898d8e 207 mp_drop(phi);
208 mp_drop(rp->n);
209 mp_drop(rp->q_inv);
210 mp_drop(rp->q);
211fail_q:
212 mp_drop(rp->p);
213fail_p:
bb2e2fd8 214 mp_drop(rp->e);
215 if (rp->d)
216 mp_drop(rp->d);
01898d8e 217 return (-1);
218}
219
220/*----- That's all, folks -------------------------------------------------*/