cbddb70d01f44e152df648997042f17a2e454e23
3 * $Id: dsa-gen.c,v 1.2 1999/11/20 22:23:48 mdw Exp $
5 * Generate DSA shared parameters
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 1999/11/20 22:23:48 mdw
34 * Allow event handler to abort the search process.
36 * Revision 1.1 1999/11/19 19:28:00 mdw
37 * Implementation of the Digital Signature Algorithm.
41 /*----- Header files ------------------------------------------------------*/
53 /*----- Main code ---------------------------------------------------------*/
55 /* --- @dsa_seed@ --- *
57 * Arguments: @dsa_param *dp@ = where to store parameters
58 * @unsigned l@ = bitlength of @p@ in bits
59 * @const void *k@ = pointer to key material
60 * @int (*proc)(int ev, mp *m, void *p)@ = event procedure
61 * @size_t sz@ = size of key material
63 * Returns: Zero if all went well, nonzero if key material was
64 * unsuitable (one of the @DSAEV@ codes).
66 * Use: Generates the DSA shared parameters from a given seed value.
67 * This can take quite a long time. The size of @p@ in bits is
68 * %$l = 512 + 64l'$%. The DSA standard, FIPS 186, only allows
69 * %$0 \le l' \le 8$%. This implementation has no such limit,
70 * although @l@ must be a multiple of 8.
72 * The event procedure is informed of various happenings during
73 * generation. It is passed an event code describing what
74 * happened, and a multiprecision number which pertains to the
75 * event code. It may abort the search at any time by returning
76 * a nonzero value, which is returned as the result of the
80 int dsa_seed(dsa_param
*dp
, unsigned l
, const void *k
, size_t sz
,
81 int (*proc
)(int /*ev*/, mp */
*m*/
, void */
*p*/
), void *arg
)
84 mp
*s
= mp_loadb(MP_NEW
, k
, sz
);
85 octet
*sbuf
= xmalloc(sz
);
90 rc4_init(&rc4
, k
, sz
);
92 /* --- Generate @q@ --- */
95 octet xbuf
[SHA_HASHSZ
], ybuf
[SHA_HASHSZ
];
103 mpx_uaddn(s
->v
, s
->vl
, 1);
104 mp_storeb(s
, sbuf
, sz
);
106 sha_hash(&c
, sbuf
, sz
);
109 for (i
= 0; i
< sizeof(xbuf
); i
++)
112 xbuf
[SHA_HASHSZ
- 1] |= 0x01;
113 q
= mp_loadb(MP_NEW
, xbuf
, sizeof(xbuf
));
116 /* --- Quick primality check --- */
120 int rc
= pgen_create(&pg
, q
);
122 if (rc
== PGEN_COMPOSITE
) {
124 fail
= proc(DSAEV_FAILQ
, q
, arg
);
131 /* --- Ensure that @q@ is prime --- *
133 * This requires 18 iterations, because the DSA spec is paranoid.
134 * Fortunately, it doesn't actually take very long.
141 octet gbuf
[SHA_HASHSZ
];
144 for (i
= 0; i
< 18; i
++) {
145 rc4_encrypt(&rc4
, 0, gbuf
, sizeof(gbuf
));
146 g
= mp_loadb(g
, gbuf
, sizeof(gbuf
));
147 if (rabin_test(&r
, g
) == PGEN_COMPOSITE
)
149 if (proc
&& (fail
= proc(DSAEV_PASSQ
, q
, arg
)) != 0)
158 fail
= proc(DSAEV_FAILQ
, q
, arg
);
163 if (proc
&& (fail
= proc(DSAEV_GOODQ
, q
, arg
)) != 0)
167 /* --- Now generate @p@ --- *
169 * This is, unfortunately, rather more messy and complicated.
173 mp
*q2
= mp_lsl(MP_NEW
, q
, 1);
174 mp
*ll
= mp_lsl(MP_NEW
, MP_ONE
, l
* 8 - 1);
175 unsigned n
= l
/ SHA_HASHSZ
, b
= l
% SHA_HASHSZ
;
176 size_t psz
= SHA_HASHSZ
* (n
+ 1);
177 octet
*pbuf
= xmalloc(psz
);
181 /* --- Fiddle with the leftover bytes count --- */
185 /* --- Go round 4096 times trying different @p@ values --- */
188 for (j
= 0; j
< 4096; j
++) {
190 /* --- Build a prospective value of @p@ --- */
193 octet
*pp
= pbuf
+ SHA_HASHSZ
* n
;
195 for (i
= 0; i
<= n
; i
++) {
196 mpx_uaddn(s
->v
, s
->vl
, 1);
197 mp_storeb(s
, sbuf
, sz
);
199 sha_hash(&c
, sbuf
, sz
);
205 p
= mp_loadb(p
, pbuf
+ b
, psz
- b
);
206 p
= mp_add(p
, p
, ll
);
209 /* --- Adjust @p@ so that %$p \bmod 2q = 1$% --- */
213 mp_div(0, &c
, p
, q2
);
214 c
= mp_sub(c
, c
, MP_ONE
);
219 /* --- Check that @p@ is large enough --- */
221 if (MP_CMP(p
, <, ll
))
224 /* --- Run a simple primality test --- */
228 int rc
= pgen_create(&pg
, p
);
230 if (rc
== PGEN_COMPOSITE
)
234 /* --- Run the Rabin-Miller test --- */
241 if (proc
&& (fail
= proc(DSAEV_TRYP
, p
, arg
)) != 0)
243 for (i
= 0; i
< 5; i
++) {
244 rc4_encrypt(&rc4
, 0, pbuf
, psz
- b
);
245 g
= mp_loadb(g
, pbuf
, psz
- b
);
246 if (rabin_test(&r
, g
) == PGEN_COMPOSITE
)
248 if (proc
&& (fail
= proc(DSAEV_PASSP
, p
, arg
)) != 0)
256 if (proc
&& (fail
= proc(DSAEV_FAILP
, p
, arg
)) != 0)
262 /* --- It worked! --- */
265 fail
= proc(DSAEV_GOODP
, p
, arg
);
272 if (j
>= 4096 || fail
)
276 /* --- Choose a generator of an order-%$q$% subgroup of %$Z^*_p$% --- */
285 /* --- Calculate %$p' = (p - 1)/q$% --- */
288 mp
*p1
= mp_sub(MP_NEW
, p
, MP_ONE
);
289 mp_div(&pp
, 0, p1
, q
);
293 /* --- Now find %$h$% where %$g = h^{p'} \bmod p \ne 1$% --- */
295 mp_build(&h
, &hw
, &hw
+ 1);
296 mpmont_create(&mm
, p
);
297 for (i
= 0; i
< NPRIME
; i
++) {
299 if (proc
&& (fail
= proc(DSAEV_TRYH
, &h
, arg
)) != 0)
301 g
= mpmont_exp(&mm
, &h
, pp
);
302 if (MP_CMP(g
, !=, MP_ONE
))
305 if (proc
&& (fail
= proc(DSAEV_FAILH
, &h
, arg
)) != 0)
316 if (proc
&& (fail
= proc(DSAEV_GOODG
, g
, arg
) != 0))
319 /* --- Return the important information that I succeeded --- */
328 /* --- Tidy up after failure --- */
341 /*----- Test rig ----------------------------------------------------------*/
345 static char baton
[] = "/-\\|";
346 static char *b
= baton
;
348 static int event(int ev
, mp
*m
, void *p
)
350 if (ev
== DSAEV_TRYP
|| ev
== DSAEV_PASSP
) {
360 static int verify(dstr
*v
)
362 mp
*q
= *(mp
**)v
[2].buf
;
363 mp
*p
= *(mp
**)v
[3].buf
;
364 mp
*g
= *(mp
**)v
[4].buf
;
366 unsigned l
= *(unsigned *)v
[1].buf
;
370 rc
= dsa_seed(&dp
, l
, v
[0].buf
, v
[0].len
, event
, 0);
371 if (rc
|| MP_CMP(q
, !=, dp
.q
) ||
372 MP_CMP(p
, !=, dp
.p
) || MP_CMP(g
, !=, dp
.g
)) {
373 fputs("\n*** gen failed", stderr
);
374 fputs("\nseed = ", stderr
); type_hex
.dump(&v
[0], stderr
);
375 fprintf(stderr
, "\nl = %u", l
);
376 fputs("\n q = ", stderr
); mp_writefile(q
, stderr
, 16);
377 fputs("\n p = ", stderr
); mp_writefile(q
, stderr
, 16);
378 fputs("\n g = ", stderr
); mp_writefile(g
, stderr
, 16);
380 fputs("\ndp.q = ", stderr
); mp_writefile(dp
.q
, stderr
, 16);
381 fputs("\ndp.p = ", stderr
); mp_writefile(dp
.p
, stderr
, 16);
382 fputs("\ndp.g = ", stderr
); mp_writefile(dp
.g
, stderr
, 16);
388 mp_drop(q
); mp_drop(p
); mp_drop(g
);
390 mp_drop(dp
.q
); mp_drop(dp
.p
); mp_drop(dp
.g
);
395 static test_chunk tests
[] = {
397 { &type_hex
, &type_int
, &type_mp
, &type_mp
, &type_mp
, 0 } },
401 int main(int argc
, char *argv
[])
404 test_run(argc
, argv
, tests
, SRCDIR
"/tests/dsa");
410 /*----- That's all, folks -------------------------------------------------*/