chiark / gitweb /
base/asm-common.h: Factor out `deposit fake literal pool' macro.
[catacomb] / pub / rsa-gen.c
CommitLineData
01898d8e 1/* -*-c-*-
01898d8e 2 *
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
41/* --- @rsa_gen@ --- *
42 *
b82ec4e8 43 * Arguments: @rsa_priv *rp@ = pointer to block to be filled in
01898d8e 44 * @unsigned nbits@ = required modulus size in bits
45 * @grand *r@ = random number source
46 * @unsigned n@ = number of attempts to make
47 * @pgen_proc *event@ = event handler function
48 * @void *ectx@ = argument for the event handler
49 *
50 * Returns: Zero if all went well, nonzero otherwise.
51 *
52 * Use: Constructs a pair of strong RSA primes and other useful RSA
53 * parameters. A small encryption exponent is chosen if
54 * possible.
55 */
56
b82ec4e8 57int rsa_gen(rsa_priv *rp, unsigned nbits, grand *r, unsigned n,
01898d8e 58 pgen_proc *event, void *ectx)
59{
bb2e2fd8 60 pgen_gcdstepctx g;
61 mp *phi = MP_NEW;
01898d8e 62
bb2e2fd8 63 /* --- Bits of initialization --- */
64
65 rp->e = mp_fromulong(MP_NEW, 0x10001);
66 rp->d = MP_NEW;
67
68 /* --- Generate strong primes %$p$% and %$q$% --- *
69 *
70 * Constrain the GCD of @q@ to ensure that overly small private exponents
71 * are impossible. Current results suggest that if %$d < n^{0.29}$% then
72 * it can be guessed fairly easily. This implementation is rather more
73 * conservative about that sort of thing.
74 */
01898d8e 75
bb2e2fd8 76 if ((rp->p = strongprime("p", MP_NEWSEC, nbits/2, r, n, event, ectx)) == 0)
01898d8e 77 goto fail_p;
bb2e2fd8 78
0b09aab8
MW
79 /* --- Do painful fiddling with GCD steppers --- *
80 *
81 * Also, arrange that %$q \ge \lceil 2^{N-1}/p \rceil$%, so that %$p q$%
82 * has the right length.
83 */
bb2e2fd8 84
85 {
86 mp *q;
0b09aab8 87 mp *t = MP_NEW, *u = MP_NEW;
bb2e2fd8 88 rabin rb;
89
90 if ((q = strongprime_setup("q", MP_NEWSEC, &g.jp, nbits / 2,
91 r, n, event, ectx)) == 0)
92 goto fail_q;
0b09aab8
MW
93 t = mp_lsl(t, MP_ONE, nbits - 1);
94 mp_div(&t, &u, t, rp->p);
95 if (!MP_ZEROP(u)) t = mp_add(t, t, MP_ONE);
96 if (MP_CMP(q, <, t)) q = mp_leastcongruent(q, t, q, g.jp.m);
1f86efe6 97 mp_drop(t);
0b09aab8 98
bb2e2fd8 99 g.r = mp_lsr(MP_NEW, rp->p, 1);
100 g.g = MP_NEW;
101 g.max = MP_256;
102 q = pgen("q", q, q, event, ectx, n, pgen_gcdstep, &g,
6687eff5 103 rabin_iters(nbits/2), pgen_test, &rb);
bb2e2fd8 104 pfilt_destroy(&g.jp);
105 mp_drop(g.r);
106 if (!q) {
107 mp_drop(g.g);
285bf989 108 goto fail_q;
bb2e2fd8 109 }
110 rp->q = q;
111 }
112
113 /* --- Ensure that %$p > q$% --- *
114 *
115 * Also ensure that %$p$% and %$q$% are sufficiently different to deter
116 * square-root-based factoring methods.
117 */
118
119 phi = mp_sub(phi, rp->p, rp->q);
120 if (MP_LEN(phi) * 4 < MP_LEN(rp->p) * 3 ||
121 MP_LEN(phi) * 4 < MP_LEN(rp->q) * 3) {
122 mp_drop(rp->p);
123 mp_drop(g.g);
285bf989 124 goto fail_q;
bb2e2fd8 125 }
126
a69a3efd 127 if (MP_NEGP(phi)) {
bb2e2fd8 128 mp *z = rp->p;
129 rp->p = rp->q;
130 rp->q = z;
131 }
01898d8e 132
133 /* --- Work out the modulus and the CRT coefficient --- */
134
135 rp->n = mp_mul(MP_NEW, rp->p, rp->q);
b817bfc6 136 rp->q_inv = mp_modinv(MP_NEW, rp->q, rp->p);
01898d8e 137
138 /* --- Work out %$\varphi(n) = (p - 1)(q - 1)$% --- *
139 *
140 * Save on further multiplications by noting that %$n = pq$% is known and
bb2e2fd8 141 * that %$(p - 1)(q - 1) = pq - p - q + 1$%. To minimize the size of @d@
142 * (useful for performance reasons, although not very because an overly
143 * small @d@ will be rejected for security reasons) this is then divided by
144 * %$\gcd(p - 1, q - 1)$%.
01898d8e 145 */
146
bb2e2fd8 147 phi = mp_sub(phi, rp->n, rp->p);
01898d8e 148 phi = mp_sub(phi, phi, rp->q);
149 phi = mp_add(phi, phi, MP_ONE);
bb2e2fd8 150 phi = mp_lsr(phi, phi, 1);
151 mp_div(&phi, 0, phi, g.g);
01898d8e 152
153 /* --- Decide on a public exponent --- *
154 *
155 * Simultaneously compute the private exponent.
156 */
157
bb2e2fd8 158 mp_gcd(&g.g, 0, &rp->d, phi, rp->e);
22bab86c 159 if (!MP_EQ(g.g, MP_ONE) && MP_LEN(rp->d) * 4 > MP_LEN(rp->n) * 3)
bb2e2fd8 160 goto fail_e;
998e6c3d
MW
161 if (mp_bits(rp->n) != nbits)
162 goto fail_e;
01898d8e 163
164 /* --- Work out exponent residues --- */
165
01898d8e 166 rp->dp = MP_NEW; phi = mp_sub(phi, rp->p, MP_ONE);
167 mp_div(0, &rp->dp, rp->d, phi);
168
169 rp->dq = MP_NEW; phi = mp_sub(phi, rp->q, MP_ONE);
170 mp_div(0, &rp->dq, rp->d, phi);
171
172 /* --- Done --- */
173
174 mp_drop(phi);
bb2e2fd8 175 mp_drop(g.g);
01898d8e 176 return (0);
177
178 /* --- Tidy up when something goes wrong --- */
179
180fail_e:
bb2e2fd8 181 mp_drop(g.g);
01898d8e 182 mp_drop(phi);
183 mp_drop(rp->n);
184 mp_drop(rp->q_inv);
185 mp_drop(rp->q);
186fail_q:
187 mp_drop(rp->p);
188fail_p:
bb2e2fd8 189 mp_drop(rp->e);
190 if (rp->d)
191 mp_drop(rp->d);
01898d8e 192 return (-1);
193}
194
195/*----- That's all, folks -------------------------------------------------*/