3 * $Id: rsa-gen.c,v 1.2 2000/06/17 12:05:15 mdw Exp $
5 * RSA parameter generation
7 * (c) 1999 Straylight/Edgeware
10 /*----- Licensing notice --------------------------------------------------*
12 * This file is part of Catacomb.
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.
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.
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,
30 /*----- Revision history --------------------------------------------------*
33 * Revision 1.2 2000/06/17 12:05:15 mdw
36 * * Apply limits on %$\gcd(p - 1, q - 1)$% to reduce the space of
37 * equivalent decryption exponents.
39 * * Force %$e = F_4 = 2^{16} + 1$% to avoid small-encryption-exponent
42 * * Ensure that %$p > q$% and that %$p - q$% is large to deter
43 * square-root-based factoring methods.
45 * * Use %$e d \equiv 1 \pmod{\lambda(n)}$%, where %$\lambda(n)$% is
46 * %$\lcm(p - 1, q - 1)$%, as recommended in PKCS#1, rather than the
47 * more usual %$\varphi(n) = (p - 1)(q - 1)$%.
49 * * Handle aborts from pgen_jump.
51 * Revision 1.1 1999/12/22 15:50:45 mdw
52 * Initial RSA support.
56 /*----- Header files ------------------------------------------------------*/
58 #include <mLib/dstr.h>
65 #include "strongprime.h"
67 /*----- Main code ---------------------------------------------------------*/
69 /* --- @rsa_gen@ --- *
71 * Arguments: @rsa_param *rp@ = pointer to block to be filled in
72 * @unsigned nbits@ = required modulus size in bits
73 * @grand *r@ = random number source
74 * @unsigned n@ = number of attempts to make
75 * @pgen_proc *event@ = event handler function
76 * @void *ectx@ = argument for the event handler
78 * Returns: Zero if all went well, nonzero otherwise.
80 * Use: Constructs a pair of strong RSA primes and other useful RSA
81 * parameters. A small encryption exponent is chosen if
85 int rsa_gen(rsa_param *rp, unsigned nbits, grand *r, unsigned n,
86 pgen_proc *event, void *ectx)
91 /* --- Bits of initialization --- */
93 rp->e = mp_fromulong(MP_NEW, 0x10001);
96 /* --- Generate strong primes %$p$% and %$q$% --- *
98 * Constrain the GCD of @q@ to ensure that overly small private exponents
99 * are impossible. Current results suggest that if %$d < n^{0.29}$% then
100 * it can be guessed fairly easily. This implementation is rather more
101 * conservative about that sort of thing.
105 if ((rp->p = strongprime("p", MP_NEWSEC, nbits/2, r, n, event, ectx)) == 0)
108 /* --- Do painful fiddling with GCD steppers --- */
114 if ((q = strongprime_setup("q", MP_NEWSEC, &g.jp, nbits / 2,
115 r, n, event, ectx)) == 0)
117 g.r = mp_lsr(MP_NEW, rp->p, 1);
120 q = pgen("q", q, q, event, ectx, n, pgen_gcdstep, &g,
121 rabin_iters(nbits/2), pgen_test, &rb);
122 pfilt_destroy(&g.jp);
134 /* --- Ensure that %$p > q$% --- *
136 * Also ensure that %$p$% and %$q$% are sufficiently different to deter
137 * square-root-based factoring methods.
140 phi = mp_sub(phi, rp->p, rp->q);
141 if (MP_LEN(phi) * 4 < MP_LEN(rp->p) * 3 ||
142 MP_LEN(phi) * 4 < MP_LEN(rp->q) * 3) {
151 if (phi->f & MP_NEG) {
157 /* --- Work out the modulus and the CRT coefficient --- */
159 rp->n = mp_mul(MP_NEW, rp->p, rp->q);
160 rp->q_inv = MP_NEW; mp_gcd(0, 0, &rp->q_inv, rp->p, rp->q);
162 /* --- Work out %$\varphi(n) = (p - 1)(q - 1)$% --- *
164 * Save on further multiplications by noting that %$n = pq$% is known and
165 * that %$(p - 1)(q - 1) = pq - p - q + 1$%. To minimize the size of @d@
166 * (useful for performance reasons, although not very because an overly
167 * small @d@ will be rejected for security reasons) this is then divided by
168 * %$\gcd(p - 1, q - 1)$%.
171 phi = mp_sub(phi, rp->n, rp->p);
172 phi = mp_sub(phi, phi, rp->q);
173 phi = mp_add(phi, phi, MP_ONE);
174 phi = mp_lsr(phi, phi, 1);
175 mp_div(&phi, 0, phi, g.g);
177 /* --- Decide on a public exponent --- *
179 * Simultaneously compute the private exponent.
182 mp_gcd(&g.g, 0, &rp->d, phi, rp->e);
183 if (MP_CMP(g.g, !=, MP_ONE) && MP_LEN(rp->d) * 4 > MP_LEN(rp->n) * 3)
186 /* --- Work out exponent residues --- */
188 rp->dp = MP_NEW; phi = mp_sub(phi, rp->p, MP_ONE);
189 mp_div(0, &rp->dp, rp->d, phi);
191 rp->dq = MP_NEW; phi = mp_sub(phi, rp->q, MP_ONE);
192 mp_div(0, &rp->dq, rp->d, phi);
200 /* --- Tidy up when something goes wrong --- */
217 /*----- That's all, folks -------------------------------------------------*/