3 * $Id: rsa-gen.c,v 1.4 2000/10/08 12:11:22 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.4 2000/10/08 12:11:22 mdw
34 * Use @MP_EQ@ instead of @MP_CMP@.
36 * Revision 1.3 2000/07/01 11:22:22 mdw
37 * Remove bad type name `rsa_param'.
39 * Revision 1.2 2000/06/17 12:05:15 mdw
42 * * Apply limits on %$\gcd(p - 1, q - 1)$% to reduce the space of
43 * equivalent decryption exponents.
45 * * Force %$e = F_4 = 2^{16} + 1$% to avoid small-encryption-exponent
48 * * Ensure that %$p > q$% and that %$p - q$% is large to deter
49 * square-root-based factoring methods.
51 * * Use %$e d \equiv 1 \pmod{\lambda(n)}$%, where %$\lambda(n)$% is
52 * %$\lcm(p - 1, q - 1)$%, as recommended in PKCS#1, rather than the
53 * more usual %$\varphi(n) = (p - 1)(q - 1)$%.
55 * * Handle aborts from pgen_jump.
57 * Revision 1.1 1999/12/22 15:50:45 mdw
58 * Initial RSA support.
62 /*----- Header files ------------------------------------------------------*/
64 #include <mLib/dstr.h>
71 #include "strongprime.h"
73 /*----- Main code ---------------------------------------------------------*/
75 /* --- @rsa_gen@ --- *
77 * Arguments: @rsa_priv *rp@ = pointer to block to be filled in
78 * @unsigned nbits@ = required modulus size in bits
79 * @grand *r@ = random number source
80 * @unsigned n@ = number of attempts to make
81 * @pgen_proc *event@ = event handler function
82 * @void *ectx@ = argument for the event handler
84 * Returns: Zero if all went well, nonzero otherwise.
86 * Use: Constructs a pair of strong RSA primes and other useful RSA
87 * parameters. A small encryption exponent is chosen if
91 int rsa_gen(rsa_priv
*rp
, unsigned nbits
, grand
*r
, unsigned n
,
92 pgen_proc
*event
, void *ectx
)
97 /* --- Bits of initialization --- */
99 rp
->e
= mp_fromulong(MP_NEW
, 0x10001);
102 /* --- Generate strong primes %$p$% and %$q$% --- *
104 * Constrain the GCD of @q@ to ensure that overly small private exponents
105 * are impossible. Current results suggest that if %$d < n^{0.29}$% then
106 * it can be guessed fairly easily. This implementation is rather more
107 * conservative about that sort of thing.
111 if ((rp
->p
= strongprime("p", MP_NEWSEC
, nbits
/2, r
, n
, event
, ectx
)) == 0)
114 /* --- Do painful fiddling with GCD steppers --- */
120 if ((q
= strongprime_setup("q", MP_NEWSEC
, &g
.jp
, nbits
/ 2,
121 r
, n
, event
, ectx
)) == 0)
123 g
.r
= mp_lsr(MP_NEW
, rp
->p
, 1);
126 q
= pgen("q", q
, q
, event
, ectx
, n
, pgen_gcdstep
, &g
,
127 rabin_iters(nbits
/2), pgen_test
, &rb
);
128 pfilt_destroy(&g
.jp
);
140 /* --- Ensure that %$p > q$% --- *
142 * Also ensure that %$p$% and %$q$% are sufficiently different to deter
143 * square-root-based factoring methods.
146 phi
= mp_sub(phi
, rp
->p
, rp
->q
);
147 if (MP_LEN(phi
) * 4 < MP_LEN(rp
->p
) * 3 ||
148 MP_LEN(phi
) * 4 < MP_LEN(rp
->q
) * 3) {
157 if (phi
->f
& MP_NEG
) {
163 /* --- Work out the modulus and the CRT coefficient --- */
165 rp
->n
= mp_mul(MP_NEW
, rp
->p
, rp
->q
);
166 rp
->q_inv
= MP_NEW
; mp_gcd(0, 0, &rp
->q_inv
, rp
->p
, rp
->q
);
168 /* --- Work out %$\varphi(n) = (p - 1)(q - 1)$% --- *
170 * Save on further multiplications by noting that %$n = pq$% is known and
171 * that %$(p - 1)(q - 1) = pq - p - q + 1$%. To minimize the size of @d@
172 * (useful for performance reasons, although not very because an overly
173 * small @d@ will be rejected for security reasons) this is then divided by
174 * %$\gcd(p - 1, q - 1)$%.
177 phi
= mp_sub(phi
, rp
->n
, rp
->p
);
178 phi
= mp_sub(phi
, phi
, rp
->q
);
179 phi
= mp_add(phi
, phi
, MP_ONE
);
180 phi
= mp_lsr(phi
, phi
, 1);
181 mp_div(&phi
, 0, phi
, g
.g
);
183 /* --- Decide on a public exponent --- *
185 * Simultaneously compute the private exponent.
188 mp_gcd(&g
.g
, 0, &rp
->d
, phi
, rp
->e
);
189 if (!MP_EQ(g
.g
, MP_ONE
) && MP_LEN(rp
->d
) * 4 > MP_LEN(rp
->n
) * 3)
192 /* --- Work out exponent residues --- */
194 rp
->dp
= MP_NEW
; phi
= mp_sub(phi
, rp
->p
, MP_ONE
);
195 mp_div(0, &rp
->dp
, rp
->d
, phi
);
197 rp
->dq
= MP_NEW
; phi
= mp_sub(phi
, rp
->q
, MP_ONE
);
198 mp_div(0, &rp
->dq
, rp
->d
, phi
);
206 /* --- Tidy up when something goes wrong --- */
223 /*----- That's all, folks -------------------------------------------------*/