4db8d927c109368667ef15558967bdcea1bd2aaf
[platform/upstream/nettle.git] / examples / rsa-keygen.c
1 /* rsa-keygen.c
2
3    Copyright (C) 2002 Niels Möller
4
5    This file is part of GNU Nettle.
6
7    GNU Nettle is free software: you can redistribute it and/or
8    modify it under the terms of either:
9
10      * the GNU Lesser General Public License as published by the Free
11        Software Foundation; either version 3 of the License, or (at your
12        option) any later version.
13
14    or
15
16      * the GNU General Public License as published by the Free
17        Software Foundation; either version 2 of the License, or (at your
18        option) any later version.
19
20    or both in parallel, as here.
21
22    GNU Nettle is distributed in the hope that it will be useful,
23    but WITHOUT ANY WARRANTY; without even the implied warranty of
24    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25    General Public License for more details.
26
27    You should have received copies of the GNU General Public License and
28    the GNU Lesser General Public License along with this program.  If
29    not, see http://www.gnu.org/licenses/.
30 */
31
32 #if HAVE_CONFIG_H
33 # include "config.h"
34 #endif
35
36 #include <ctype.h>
37 #include <errno.h>
38 #include <stdlib.h>
39 #include <stdio.h>
40 #include <string.h>
41
42 #include "buffer.h"
43 #include "rsa.h"
44 #include "sexp.h"
45 #include "yarrow.h"
46
47 #include "io.h"
48
49 #include "getopt.h"
50
51 #define DEFAULT_KEYSIZE 2048
52 #define ESIZE 30
53
54 static void
55 progress(void *ctx, int c)
56 {
57   (void) ctx;
58   fputc(c, stderr);
59 }
60
61 static unsigned long
62 uint_arg (char c, const char *arg)
63 {
64   unsigned long val;
65   char *end;
66
67   val = strtoul(arg, &end, 0);
68   if (*arg == '\0' || *end != '\0')
69     {
70       werror ("Invalid integer argument for -%c option.\n", c);
71       exit (EXIT_FAILURE);
72     }
73
74   return val;      
75 }
76
77 int
78 main(int argc, char **argv)
79 {
80   struct yarrow256_ctx yarrow;
81   struct rsa_public_key pub;
82   struct rsa_private_key priv;
83
84   int c;
85   char *pub_name = NULL;
86   const char *priv_name = NULL;
87   const char *random_name = NULL;
88   
89   struct nettle_buffer pub_buffer;
90   struct nettle_buffer priv_buffer;
91
92   unsigned long key_size = DEFAULT_KEYSIZE;
93   unsigned long key_e = 0;
94
95   enum { OPT_HELP = 300 };
96   static const struct option options[] =
97     {
98       /* Name, args, flag, val */
99       { "help", no_argument, NULL, OPT_HELP },
100       { "random", required_argument, NULL, 'r' },
101       { NULL, 0, NULL, 0}
102     };
103   
104   while ( (c = getopt_long(argc, argv, "o:r:e:s:", options, NULL)) != -1)
105     switch (c)
106       { 
107       case 'o':
108         priv_name = optarg;
109         break;
110
111       case 'r':
112         random_name = optarg;
113         break;
114
115       case 's':
116         key_size = uint_arg ('s', optarg);
117         break;
118
119       case 'e':
120         key_e = uint_arg ('e', optarg);
121         break;
122
123       case OPT_HELP:
124         printf("FIXME: Usage information.\n");
125         return EXIT_SUCCESS;
126
127       case '?':
128         return EXIT_FAILURE;
129
130       default:
131         abort();
132       }
133
134   if (!priv_name)
135     {
136       werror("No filename provided.\n");
137       return EXIT_FAILURE;
138     }
139
140   pub_name = xalloc(strlen(priv_name) + 5);  
141   sprintf(pub_name, "%s.pub", priv_name);
142
143   /* NOTE: No sources */
144   yarrow256_init(&yarrow, 0, NULL);
145
146   /* Read some data to seed the generator */
147   if (!simple_random(&yarrow, random_name))
148     {
149       werror("Initialization of randomness generator failed.\n");
150       return EXIT_FAILURE;
151     }
152
153   rsa_public_key_init(&pub);
154   rsa_private_key_init(&priv);
155
156   if (key_e)
157     mpz_set_ui (pub.e, key_e);
158
159   if (!rsa_generate_keypair
160       (&pub, &priv,
161        (void *) &yarrow, (nettle_random_func *) yarrow256_random,
162        NULL, progress,
163        key_size, key_e == 0 ? ESIZE : 0))
164     {
165       werror("Key generation failed.\n");
166       return EXIT_FAILURE;
167     }
168
169   nettle_buffer_init(&priv_buffer);
170   nettle_buffer_init(&pub_buffer);
171   
172   if (!rsa_keypair_to_sexp(&pub_buffer, "rsa-pkcs1-sha1", &pub, NULL))
173     {
174       werror("Formatting public key failed.\n");
175       return EXIT_FAILURE;
176     }
177
178   if (!rsa_keypair_to_sexp(&priv_buffer, "rsa-pkcs1-sha1", &pub, &priv))
179     {
180       werror("Formatting private key failed.\n");
181       return EXIT_FAILURE;
182     }
183   
184   if (!write_file(pub_name, pub_buffer.size, pub_buffer.contents))
185     {
186       werror("Failed to write public key: %s\n",
187               strerror(errno));
188       return EXIT_FAILURE;
189     }
190
191   /* NOTE: This doesn't set up paranoid access restrictions on the
192    * private key file, like a serious key generation tool would do. */
193   if (!write_file(priv_name, priv_buffer.size, priv_buffer.contents))
194     {
195       werror("Failed to write private key: %s\n",
196               strerror(errno));
197       return EXIT_FAILURE;
198     }
199
200   nettle_buffer_clear(&priv_buffer);
201   nettle_buffer_clear(&pub_buffer);
202   rsa_public_key_clear(&pub);
203   rsa_private_key_clear(&priv);
204   free (pub_name);
205   
206   return EXIT_SUCCESS;
207 }