tests: Use common code for all tests.
[libgcrypt.git] / tests / prime.c
1 /* prime.c - part of the Libgcrypt test suite.
2    Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
3
4    This program is free software; you can redistribute it and/or
5    modify it under the terms of the GNU General Public License as
6    published by the Free Software Foundation; either version 2 of the
7    License, or (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful, but
10    WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
17    USA.  */
18
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22 #include <assert.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26
27 #define PGM "prime"
28 #include "t-common.h"
29
30 static void
31 check_primes (void)
32 {
33   gcry_error_t err = GPG_ERR_NO_ERROR;
34   gcry_mpi_t *factors = NULL;
35   gcry_mpi_t prime = NULL;
36   gcry_mpi_t g;
37   unsigned int i = 0;
38   struct prime_spec
39   {
40     unsigned int prime_bits;
41     unsigned int factor_bits;
42     unsigned int flags;
43   } prime_specs[] =
44     {
45       { 1024, 100, GCRY_PRIME_FLAG_SPECIAL_FACTOR },
46       { 128, 0, 0 },
47       { 0 },
48     };
49
50   for (i = 0; prime_specs[i].prime_bits; i++)
51     {
52       err = gcry_prime_generate (&prime,
53                                  prime_specs[i].prime_bits,
54                                  prime_specs[i].factor_bits,
55                                  &factors,
56                                  NULL, NULL,
57                                  GCRY_WEAK_RANDOM,
58                                  prime_specs[i].flags);
59       assert (! err);
60       if (verbose)
61         {
62           fprintf (stderr, "test %d: p = ", i);
63           gcry_mpi_dump (prime);
64           putc ('\n', stderr);
65         }
66
67       err = gcry_prime_check (prime, 0);
68       assert (! err);
69
70       err = gcry_prime_group_generator (&g, prime, factors, NULL);
71       assert (!err);
72       gcry_prime_release_factors (factors); factors = NULL;
73
74       if (verbose)
75         {
76           fprintf (stderr, "     %d: g = ", i);
77           gcry_mpi_dump (g);
78           putc ('\n', stderr);
79         }
80       gcry_mpi_release (g);
81
82
83       gcry_mpi_add_ui (prime, prime, 1);
84       err = gcry_prime_check (prime, 0);
85       assert (err);
86       gcry_mpi_release (prime); prime = NULL;
87     }
88 }
89
90
91 /* Print an MPI S-expression.  */
92 static void
93 print_mpi (const char *name, gcry_mpi_t a)
94 {
95   gcry_error_t err;
96   unsigned char *buf;
97   int writerr = 0;
98
99   err = gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buf, NULL, a);
100   if (err)
101     die ("gcry_mpi_aprint failed: %s\n", gcry_strerror (err));
102
103   printf ("  (%s #%s#)\n", name, buf);
104   if (ferror (stdout))
105     writerr++;
106   if (!writerr && fflush (stdout) == EOF)
107     writerr++;
108   if (writerr)
109     die ("writing output failed\n");
110   gcry_free (buf);
111 }
112
113
114 /* Create the key for our public standard dummy CA.  */
115 static void
116 create_42prime (void)
117 {
118   gcry_error_t err;
119   char string[128*2+1];
120   int i;
121   gcry_mpi_t start = NULL;
122   gcry_mpi_t p, q, n, t1, t2, phi, f, g, e, d, u;
123
124
125   /* Our start value is a string of 0x42 values, with the exception
126      that the two high order bits are set.  This is to resemble the
127      way Lingcrypt generates RSA primes.  */
128   for (i=0; i < 128;)
129     {
130       string[i++] = '4';
131       string[i++] = '2';
132     }
133   string[i] = 0;
134   string[0] = 'C';
135
136   err = gcry_mpi_scan (&start, GCRYMPI_FMT_HEX, string, 0, NULL);
137   if (err)
138     die ("gcry_mpi_scan failed: %s\n", gcry_strerror (err));
139   fputs ("start:", stderr); gcry_mpi_dump (start); putc ('\n', stderr);
140
141   /* Generate two primes with p < q.  We take the first primes below
142      and above a start value. */
143   p = gcry_mpi_copy (start);
144   gcry_mpi_sub_ui (p, p, 1);
145   while (gcry_prime_check (p, 0))
146     gcry_mpi_sub_ui (p, p, 2);
147   fputs ("    p:", stderr); gcry_mpi_dump (p); putc ('\n', stderr);
148   q = gcry_mpi_copy (start);
149   gcry_mpi_add_ui (q, q, 1);
150   while (gcry_prime_check (q, 0))
151     gcry_mpi_add_ui (q, q, 2);
152   fputs ("    q:", stderr); gcry_mpi_dump (q); putc ('\n', stderr);
153
154   /* Compute the modulus.  */
155   n = gcry_mpi_new (1024);
156   gcry_mpi_mul (n, p, q);
157   fputs ("    n:", stderr); gcry_mpi_dump (n); putc ('\n', stderr);
158   if (gcry_mpi_get_nbits (n) != 1024)
159     die ("Oops: the size of N is not 1024 but %u\n", gcry_mpi_get_nbits (n));
160
161   /* Calculate Euler totient: phi = (p-1)(q-1) */
162   t1 = gcry_mpi_new (0);
163   t2 = gcry_mpi_new (0);
164   phi = gcry_mpi_new (0);
165   g   = gcry_mpi_new (0);
166   f   = gcry_mpi_new (0);
167   gcry_mpi_sub_ui (t1, p, 1);
168   gcry_mpi_sub_ui (t2, q, 1);
169   gcry_mpi_mul (phi, t1, t2);
170   gcry_mpi_gcd (g, t1, t2);
171   gcry_mpi_div (f, NULL, phi, g, -1);
172
173   /* Check the public exponent.  */
174   e = gcry_mpi_set_ui (NULL, 65537);
175   if (!gcry_mpi_gcd (t1, e, phi))
176     die ("Oops: E is not a generator\n");
177   fputs ("    e:", stderr); gcry_mpi_dump (e); putc ('\n', stderr);
178
179   /* Compute the secret key:  d = e^-1 mod phi */
180   d = gcry_mpi_new (0);
181   gcry_mpi_invm (d, e, f );
182   fputs ("    d:", stderr); gcry_mpi_dump (d); putc ('\n', stderr);
183
184   /* Compute the inverse of p and q. */
185   u = gcry_mpi_new (0);
186   gcry_mpi_invm (u, p, q);
187   fputs ("    u:", stderr); gcry_mpi_dump (u); putc ('\n', stderr);
188
189   /* Print the S-expression.  */
190   fputs ("(private-key\n (rsa\n", stdout);
191   print_mpi ("n", n);
192   print_mpi ("e", e);
193   print_mpi ("d", d);
194   print_mpi ("p", p);
195   print_mpi ("q", q);
196   print_mpi ("u", u);
197   fputs ("))\n", stdout);
198
199   gcry_mpi_release (p);
200   gcry_mpi_release (q);
201   gcry_mpi_release (n);
202   gcry_mpi_release (t1);
203   gcry_mpi_release (t2);
204   gcry_mpi_release (phi);
205   gcry_mpi_release (f);
206   gcry_mpi_release (g);
207   gcry_mpi_release (e);
208   gcry_mpi_release (d);
209   gcry_mpi_release (u);
210 }
211
212
213
214
215 int
216 main (int argc, char **argv)
217 {
218   int mode42 = 0;
219
220   if ((argc > 1) && (! strcmp (argv[1], "--verbose")))
221     verbose = 1;
222   else if ((argc > 1) && (! strcmp (argv[1], "--debug")))
223     verbose = debug = 1;
224   else if ((argc > 1) && (! strcmp (argv[1], "--42")))
225     verbose = debug = mode42 = 1;
226
227   gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
228   if (! gcry_check_version (GCRYPT_VERSION))
229     die ("version mismatch\n");
230
231   gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
232   if (debug)
233     gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
234
235   if (mode42)
236     create_42prime ();
237   else
238     check_primes ();
239
240   return 0;
241 }