Added RSA key generation code (i15, i31, i62).
[BearSSL] / tools / skey.c
1 /*
2 * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <stdint.h>
29 #include <errno.h>
30
31 #include "brssl.h"
32 #include "bearssl.h"
33
34 static void
35 print_int_text(const char *name, const unsigned char *buf, size_t len)
36 {
37 size_t u;
38
39 printf("%s = ", name);
40 for (u = 0; u < len; u ++) {
41 printf("%02X", buf[u]);
42 }
43 printf("\n");
44 }
45
46 static void
47 print_int_C(const char *name, const unsigned char *buf, size_t len)
48 {
49 size_t u;
50
51 printf("\nstatic const unsigned char %s[] = {", name);
52 for (u = 0; u < len; u ++) {
53 if (u != 0) {
54 printf(",");
55 }
56 if (u % 12 == 0) {
57 printf("\n\t");
58 } else {
59 printf(" ");
60 }
61 printf("0x%02X", buf[u]);
62 }
63 printf("\n};\n");
64 }
65
66 static void
67 print_rsa(const br_rsa_private_key *sk, int print_text, int print_C)
68 {
69 if (print_text) {
70 print_int_text("p ", sk->p, sk->plen);
71 print_int_text("q ", sk->q, sk->qlen);
72 print_int_text("dp", sk->dp, sk->dplen);
73 print_int_text("dq", sk->dq, sk->dqlen);
74 print_int_text("iq", sk->iq, sk->iqlen);
75 }
76 if (print_C) {
77 print_int_C("RSA_P", sk->p, sk->plen);
78 print_int_C("RSA_Q", sk->q, sk->qlen);
79 print_int_C("RSA_DP", sk->dp, sk->dplen);
80 print_int_C("RSA_DQ", sk->dq, sk->dqlen);
81 print_int_C("RSA_IQ", sk->iq, sk->iqlen);
82 printf("\nstatic const br_rsa_private_key RSA = {\n");
83 printf("\t%lu,\n", (unsigned long)sk->n_bitlen);
84 printf("\t(unsigned char *)RSA_P, sizeof RSA_P,\n");
85 printf("\t(unsigned char *)RSA_Q, sizeof RSA_Q,\n");
86 printf("\t(unsigned char *)RSA_DP, sizeof RSA_DP,\n");
87 printf("\t(unsigned char *)RSA_DQ, sizeof RSA_DQ,\n");
88 printf("\t(unsigned char *)RSA_IQ, sizeof RSA_IQ\n");
89 printf("};\n");
90 }
91 }
92
93 static void
94 print_ec(const br_ec_private_key *sk, int print_text, int print_C)
95 {
96 if (print_text) {
97 print_int_text("x", sk->x, sk->xlen);
98 }
99 if (print_C) {
100 print_int_C("EC_X", sk->x, sk->xlen);
101 printf("\nstatic const br_ec_private_key EC = {\n");
102 printf("\t%d,\n", sk->curve);
103 printf("\t(unsigned char *)EC_X, sizeof EC_X\n");
104 printf("};\n");
105 }
106 }
107
108 static int
109 parse_rsa_spec(const char *kgen_spec, unsigned *size, uint32_t *pubexp)
110 {
111 const char *p;
112 char *end;
113 unsigned long ul;
114
115 p = kgen_spec;
116 if (*p != 'r' && *p != 'R') {
117 return 0;
118 }
119 p ++;
120 if (*p != 's' && *p != 'S') {
121 return 0;
122 }
123 p ++;
124 if (*p != 'a' && *p != 'A') {
125 return 0;
126 }
127 p ++;
128 if (*p == 0) {
129 *size = 2048;
130 *pubexp = 3;
131 return 1;
132 } else if (*p != ':') {
133 return 0;
134 }
135 p ++;
136 ul = strtoul(p, &end, 10);
137 if (ul < 512 || ul > 32768) {
138 return 0;
139 }
140 *size = ul;
141 p = end;
142 if (*p == 0) {
143 *pubexp = 3;
144 return 1;
145 } else if (*p != ':') {
146 return 0;
147 }
148 p ++;
149 ul = strtoul(p, &end, 10);
150 if ((ul & 1) == 0 || ul == 1 || ((ul >> 30) >> 2) != 0) {
151 return 0;
152 }
153 *pubexp = ul;
154 if (*end != 0) {
155 return 0;
156 }
157 return 1;
158 }
159
160 static int
161 keygen_rsa(unsigned size, uint32_t pubexp, int print_text, int print_C)
162 {
163 br_hmac_drbg_context rng;
164 br_prng_seeder seeder;
165 br_rsa_keygen kg;
166 br_rsa_private_key sk;
167 unsigned char *kbuf_priv;
168 uint32_t r;
169
170 seeder = br_prng_seeder_system(NULL);
171 if (seeder == 0) {
172 fprintf(stderr, "ERROR: no system source of randomness\n");
173 return 0;
174 }
175 br_hmac_drbg_init(&rng, &br_sha256_vtable, NULL, 0);
176 if (!seeder(&rng.vtable)) {
177 fprintf(stderr, "ERROR: system source of randomness failed\n");
178 return 0;
179 }
180 kbuf_priv = xmalloc(BR_RSA_KBUF_PRIV_SIZE(size));
181 kg = br_rsa_keygen_get_default();
182 r = kg(&rng.vtable, &sk, kbuf_priv, NULL, NULL, size, pubexp);
183 if (!r) {
184 fprintf(stderr, "ERROR: RSA key pair generation failed\n");
185 } else {
186 print_rsa(&sk, print_text, print_C);
187 }
188 xfree(kbuf_priv);
189 return r;
190 }
191
192 static int
193 decode_key(const unsigned char *buf, size_t len, int print_text, int print_C)
194 {
195 br_skey_decoder_context dc;
196 int err;
197
198 br_skey_decoder_init(&dc);
199 br_skey_decoder_push(&dc, buf, len);
200 err = br_skey_decoder_last_error(&dc);
201 if (err != 0) {
202 const char *errname, *errmsg;
203
204 fprintf(stderr, "ERROR (decoding): err=%d\n", err);
205 errname = find_error_name(err, &errmsg);
206 if (errname != NULL) {
207 fprintf(stderr, " %s: %s\n", errname, errmsg);
208 } else {
209 fprintf(stderr, " (unknown)\n");
210 }
211 return -1;
212 }
213 switch (br_skey_decoder_key_type(&dc)) {
214 const br_rsa_private_key *rk;
215 const br_ec_private_key *ek;
216
217 case BR_KEYTYPE_RSA:
218 rk = br_skey_decoder_get_rsa(&dc);
219 printf("RSA key (%lu bits)\n", (unsigned long)rk->n_bitlen);
220 print_rsa(rk, print_text, print_C);
221 break;
222
223 case BR_KEYTYPE_EC:
224 ek = br_skey_decoder_get_ec(&dc);
225 printf("EC key (curve = %d: %s)\n",
226 ek->curve, ec_curve_name(ek->curve));
227 print_ec(ek, print_text, print_C);
228 break;
229
230 default:
231 fprintf(stderr, "Unknown key type: %d\n",
232 br_skey_decoder_key_type(&dc));
233 return -1;
234 }
235
236 return 0;
237 }
238
239 static void
240 usage_skey(void)
241 {
242 fprintf(stderr,
243 "usage: brssl skey [ options ] file...\n");
244 fprintf(stderr,
245 "options:\n");
246 fprintf(stderr,
247 " -q suppress verbose messages\n");
248 fprintf(stderr,
249 " -text print public key details (human-readable)\n");
250 fprintf(stderr,
251 " -C print public key details (C code)\n");
252 fprintf(stderr,
253 " -gen spec generate a new key using the provided key specification\n");
254 fprintf(stderr,
255 "Key specification begins with a key type, followed by optional parameters\n");
256 fprintf(stderr,
257 "that depend on the key type, separated by colon characters:\n");
258 fprintf(stderr,
259 " rsa[:size[:pubexep]] RSA key (defaults: size = 2048, pubexp = 3)\n");
260 }
261
262 /* see brssl.h */
263 int
264 do_skey(int argc, char *argv[])
265 {
266 int retcode;
267 int verbose;
268 int i, num_files;
269 int print_text, print_C;
270 unsigned char *buf;
271 size_t len;
272 pem_object *pos;
273 const char *kgen_spec;
274
275 retcode = 0;
276 verbose = 1;
277 print_text = 0;
278 print_C = 0;
279 num_files = 0;
280 buf = NULL;
281 pos = NULL;
282 kgen_spec = NULL;
283 for (i = 0; i < argc; i ++) {
284 const char *arg;
285
286 arg = argv[i];
287 if (arg[0] != '-') {
288 num_files ++;
289 continue;
290 }
291 argv[i] = NULL;
292 if (eqstr(arg, "-v") || eqstr(arg, "-verbose")) {
293 verbose = 1;
294 } else if (eqstr(arg, "-q") || eqstr(arg, "-quiet")) {
295 verbose = 0;
296 } else if (eqstr(arg, "-text")) {
297 print_text = 1;
298 } else if (eqstr(arg, "-C")) {
299 print_C = 1;
300 } else if (eqstr(arg, "-gen")) {
301 if (++ i >= argc) {
302 fprintf(stderr,
303 "ERROR: no argument for '-gen'\n");
304 usage_skey();
305 goto skey_exit_error;
306 }
307 if (kgen_spec != NULL) {
308 fprintf(stderr,
309 "ERROR: multiple '-gen' options\n");
310 usage_skey();
311 goto skey_exit_error;
312 }
313 kgen_spec = argv[i];
314 argv[i] = NULL;
315 } else {
316 fprintf(stderr, "ERROR: unknown option: '%s'\n", arg);
317 usage_skey();
318 goto skey_exit_error;
319 }
320 }
321 if (kgen_spec != NULL) {
322 unsigned rsa_size;
323 uint32_t rsa_pubexp;
324
325 if (num_files != 0) {
326 fprintf(stderr,
327 "ERROR: key files provided while generating\n");
328 usage_skey();
329 goto skey_exit_error;
330 }
331
332 if (parse_rsa_spec(kgen_spec, &rsa_size, &rsa_pubexp)) {
333 keygen_rsa(rsa_size, rsa_pubexp, print_text, print_C);
334 } else {
335 fprintf(stderr,
336 "ERROR: unknown key specification: '%s'\n",
337 kgen_spec);
338 usage_skey();
339 goto skey_exit_error;
340 }
341 } else if (num_files == 0) {
342 fprintf(stderr, "ERROR: no private key provided\n");
343 usage_skey();
344 goto skey_exit_error;
345 }
346
347 for (i = 0; i < argc; i ++) {
348 const char *fname;
349
350 fname = argv[i];
351 if (fname == NULL) {
352 continue;
353 }
354 buf = read_file(fname, &len);
355 if (buf == NULL) {
356 goto skey_exit_error;
357 }
358 if (looks_like_DER(buf, len)) {
359 if (verbose) {
360 fprintf(stderr, "File '%s': ASN.1/DER object\n",
361 fname);
362 }
363 if (decode_key(buf, len, print_text, print_C) < 0) {
364 goto skey_exit_error;
365 }
366 } else {
367 size_t u, num;
368
369 if (verbose) {
370 fprintf(stderr, "File '%s': decoding as PEM\n",
371 fname);
372 }
373 pos = decode_pem(buf, len, &num);
374 if (pos == NULL) {
375 goto skey_exit_error;
376 }
377 for (u = 0; pos[u].name; u ++) {
378 const char *name;
379
380 name = pos[u].name;
381 if (eqstr(name, "RSA PRIVATE KEY")
382 || eqstr(name, "EC PRIVATE KEY")
383 || eqstr(name, "PRIVATE KEY"))
384 {
385 if (decode_key(pos[u].data,
386 pos[u].data_len,
387 print_text, print_C) < 0)
388 {
389 goto skey_exit_error;
390 }
391 } else {
392 if (verbose) {
393 fprintf(stderr,
394 "(skipping '%s')\n",
395 name);
396 }
397 }
398 }
399 for (u = 0; pos[u].name; u ++) {
400 free_pem_object_contents(&pos[u]);
401 }
402 xfree(pos);
403 pos = NULL;
404 }
405 xfree(buf);
406 buf = NULL;
407 }
408
409 /*
410 * Release allocated structures.
411 */
412 skey_exit:
413 xfree(buf);
414 if (pos != NULL) {
415 size_t u;
416
417 for (u = 0; pos[u].name; u ++) {
418 free_pem_object_contents(&pos[u]);
419 }
420 xfree(pos);
421 }
422 return retcode;
423
424 skey_exit_error:
425 retcode = -1;
426 goto skey_exit;
427 }