ct.c, ct.h: New constant-time operations.
[u/mdw/catacomb] / rsa-gen.c
CommitLineData
01898d8e 1/* -*-c-*-
2 *
a69a3efd 3 * $Id$
01898d8e 4 *
5 * RSA parameter generation
6 *
7 * (c) 1999 Straylight/Edgeware
8 */
9
45c0fd36 10/*----- Licensing notice --------------------------------------------------*
01898d8e 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.
45c0fd36 18 *
01898d8e 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.
45c0fd36 23 *
01898d8e 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
01898d8e 30/*----- Header files ------------------------------------------------------*/
31
32#include <mLib/dstr.h>
33
34#include "grand.h"
35#include "mp.h"
bb2e2fd8 36#include "mpint.h"
01898d8e 37#include "pgen.h"
38#include "rsa.h"
39#include "strongprime.h"
40
41/*----- Main code ---------------------------------------------------------*/
42
43/* --- @rsa_gen@ --- *
44 *
b82ec4e8 45 * Arguments: @rsa_priv *rp@ = pointer to block to be filled in
01898d8e 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
b82ec4e8 59int rsa_gen(rsa_priv *rp, unsigned nbits, grand *r, unsigned n,
01898d8e 60 pgen_proc *event, void *ectx)
61{
bb2e2fd8 62 pgen_gcdstepctx g;
63 mp *phi = MP_NEW;
01898d8e 64
bb2e2fd8 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 */
01898d8e 77
bb2e2fd8 78again:
79 if ((rp->p = strongprime("p", MP_NEWSEC, nbits/2, r, n, event, ectx)) == 0)
01898d8e 80 goto fail_p;
bb2e2fd8 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
a69a3efd 125 if (MP_NEGP(phi)) {
bb2e2fd8 126 mp *z = rp->p;
127 rp->p = rp->q;
128 rp->q = z;
129 }
01898d8e 130
131 /* --- Work out the modulus and the CRT coefficient --- */
132
133 rp->n = mp_mul(MP_NEW, rp->p, rp->q);
b817bfc6 134 rp->q_inv = mp_modinv(MP_NEW, rp->q, rp->p);
01898d8e 135
136 /* --- Work out %$\varphi(n) = (p - 1)(q - 1)$% --- *
137 *
138 * Save on further multiplications by noting that %$n = pq$% is known and
bb2e2fd8 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)$%.
01898d8e 143 */
144
bb2e2fd8 145 phi = mp_sub(phi, rp->n, rp->p);
01898d8e 146 phi = mp_sub(phi, phi, rp->q);
147 phi = mp_add(phi, phi, MP_ONE);
bb2e2fd8 148 phi = mp_lsr(phi, phi, 1);
149 mp_div(&phi, 0, phi, g.g);
01898d8e 150
151 /* --- Decide on a public exponent --- *
152 *
153 * Simultaneously compute the private exponent.
154 */
155
bb2e2fd8 156 mp_gcd(&g.g, 0, &rp->d, phi, rp->e);
22bab86c 157 if (!MP_EQ(g.g, MP_ONE) && MP_LEN(rp->d) * 4 > MP_LEN(rp->n) * 3)
bb2e2fd8 158 goto fail_e;
01898d8e 159
160 /* --- Work out exponent residues --- */
161
01898d8e 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);
bb2e2fd8 171 mp_drop(g.g);
01898d8e 172 return (0);
173
174 /* --- Tidy up when something goes wrong --- */
175
176fail_e:
bb2e2fd8 177 mp_drop(g.g);
01898d8e 178 mp_drop(phi);
179 mp_drop(rp->n);
180 mp_drop(rp->q_inv);
181 mp_drop(rp->q);
182fail_q:
183 mp_drop(rp->p);
184fail_p:
bb2e2fd8 185 mp_drop(rp->e);
186 if (rp->d)
187 mp_drop(rp->d);
01898d8e 188 return (-1);
189}
190
191/*----- That's all, folks -------------------------------------------------*/