/ tools / skey.c
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  typedef struct {
 35  	int print_text;
 36  	int print_C;
 37  	const char *rawder;
 38  	const char *rawpem;
 39  	const char *pk8der;
 40  	const char *pk8pem;
 41  } outspec;
 42  
 43  static void
 44  print_int_text(const char *name, const unsigned char *buf, size_t len)
 45  {
 46  	size_t u;
 47  
 48  	printf("%s = ", name);
 49  	for (u = 0; u < len; u ++) {
 50  		printf("%02X", buf[u]);
 51  	}
 52  	printf("\n");
 53  }
 54  
 55  static void
 56  print_int_C(const char *name, const unsigned char *buf, size_t len)
 57  {
 58  	size_t u;
 59  
 60  	printf("\nstatic const unsigned char %s[] = {", name);
 61  	for (u = 0; u < len; u ++) {
 62  		if (u != 0) {
 63  			printf(",");
 64  		}
 65  		if (u % 12 == 0) {
 66  			printf("\n\t");
 67  		} else {
 68  			printf(" ");
 69  		}
 70  		printf("0x%02X", buf[u]);
 71  	}
 72  	printf("\n};\n");
 73  }
 74  
 75  static int
 76  write_to_file(const char *name, const void *data, size_t len)
 77  {
 78  	FILE *f;
 79  
 80  	f = fopen(name, "wb");
 81  	if (f == NULL) {
 82  		fprintf(stderr,
 83  			"ERROR: cannot open file '%s' for writing\n",
 84  			name);
 85  		return 0;
 86  	}
 87  	if (fwrite(data, 1, len, f) != len) {
 88  		fclose(f);
 89  		fprintf(stderr,
 90  			"ERROR: cannot write to file '%s'\n",
 91  			name);
 92  		return 0;
 93  	}
 94  	fclose(f);
 95  	return 1;
 96  }
 97  
 98  static int
 99  write_to_pem_file(const char *name,
100  	const void *data, size_t len, const char *banner)
101  {
102  	void *pem;
103  	size_t pemlen;
104  	int r;
105  
106  	pemlen = br_pem_encode(NULL, NULL, len, banner, 0);
107  	pem = xmalloc(pemlen + 1);
108  	br_pem_encode(pem, data, len, banner, 0);
109  	r = write_to_file(name, pem, pemlen);
110  	xfree(pem);
111  	return r;
112  }
113  
114  static int
115  print_rsa(const br_rsa_private_key *sk, outspec *os)
116  {
117  	int ret;
118  	unsigned char *n, *d, *buf;
119  	uint32_t e;
120  	size_t nlen, dlen, len;
121  	br_rsa_compute_modulus cm;
122  	br_rsa_compute_pubexp ce;
123  	br_rsa_compute_privexp cd;
124  	br_rsa_public_key pk;
125  	unsigned char ebuf[4];
126  
127  	n = NULL;
128  	d = NULL;
129  	buf = NULL;
130  	ret = 1;
131  	if (os->print_text) {
132  		print_int_text("p ", sk->p, sk->plen);
133  		print_int_text("q ", sk->q, sk->qlen);
134  		print_int_text("dp", sk->dp, sk->dplen);
135  		print_int_text("dq", sk->dq, sk->dqlen);
136  		print_int_text("iq", sk->iq, sk->iqlen);
137  	}
138  	if (os->print_C) {
139  		print_int_C("RSA_P", sk->p, sk->plen);
140  		print_int_C("RSA_Q", sk->q, sk->qlen);
141  		print_int_C("RSA_DP", sk->dp, sk->dplen);
142  		print_int_C("RSA_DQ", sk->dq, sk->dqlen);
143  		print_int_C("RSA_IQ", sk->iq, sk->iqlen);
144  		printf("\nstatic const br_rsa_private_key RSA = {\n");
145  		printf("\t%lu,\n", (unsigned long)sk->n_bitlen);
146  		printf("\t(unsigned char *)RSA_P, sizeof RSA_P,\n");
147  		printf("\t(unsigned char *)RSA_Q, sizeof RSA_Q,\n");
148  		printf("\t(unsigned char *)RSA_DP, sizeof RSA_DP,\n");
149  		printf("\t(unsigned char *)RSA_DQ, sizeof RSA_DQ,\n");
150  		printf("\t(unsigned char *)RSA_IQ, sizeof RSA_IQ\n");
151  		printf("};\n");
152  	}
153  
154  	if (os->rawder == NULL && os->rawpem == NULL
155  		&& os->pk8der == NULL && os->pk8pem == NULL)
156  	{
157  		return ret;
158  	}
159  
160  	cm = br_rsa_compute_modulus_get_default();
161  	ce = br_rsa_compute_pubexp_get_default();
162  	cd = br_rsa_compute_privexp_get_default();
163  	nlen = cm(NULL, sk);
164  	if (nlen == 0) {
165  		goto print_RSA_error;
166  	}
167  	n = xmalloc(nlen);
168  	if (cm(n, sk) != nlen) {
169  		goto print_RSA_error;
170  	}
171  	e = ce(sk);
172  	if (e == 0) {
173  		goto print_RSA_error;
174  	}
175  	dlen = cd(NULL, sk, e);
176  	if (dlen == 0) {
177  		goto print_RSA_error;
178  	}
179  	d = xmalloc(dlen);
180  	if (cd(d, sk, e) != dlen) {
181  		goto print_RSA_error;
182  	}
183  	ebuf[0] = e >> 24;
184  	ebuf[1] = e >> 16;
185  	ebuf[2] = e >> 8;
186  	ebuf[3] = e;
187  	pk.n = n;
188  	pk.nlen = nlen;
189  	pk.e = ebuf;
190  	pk.elen = sizeof ebuf;
191  
192  	if (os->rawder != NULL || os->rawpem != NULL) {
193  		len = br_encode_rsa_raw_der(NULL, sk, &pk, d, dlen);
194  		if (len == 0) {
195  			goto print_RSA_error;
196  		}
197  		buf = xmalloc(len);
198  		if (br_encode_rsa_raw_der(buf, sk, &pk, d, dlen) != len) {
199  			goto print_RSA_error;
200  		}
201  		if (os->rawder != NULL) {
202  			ret &= write_to_file(os->rawder, buf, len);
203  		}
204  		if (os->rawpem != NULL) {
205  			ret &= write_to_pem_file(os->rawpem,
206  				buf, len, "RSA PRIVATE KEY");
207  		}
208  		xfree(buf);
209  		buf = NULL;
210  	}
211  
212  	if (os->pk8der != NULL || os->pk8pem != NULL) {
213  		len = br_encode_rsa_pkcs8_der(NULL, sk, &pk, d, dlen);
214  		if (len == 0) {
215  			goto print_RSA_error;
216  		}
217  		buf = xmalloc(len);
218  		if (br_encode_rsa_pkcs8_der(buf, sk, &pk, d, dlen) != len) {
219  			goto print_RSA_error;
220  		}
221  		if (os->pk8der != NULL) {
222  			ret &= write_to_file(os->pk8der, buf, len);
223  		}
224  		if (os->pk8pem != NULL) {
225  			ret &= write_to_pem_file(os->pk8pem,
226  				buf, len, "PRIVATE KEY");
227  		}
228  		xfree(buf);
229  		buf = NULL;
230  	}
231  
232  print_RSA_exit:
233  	xfree(n);
234  	xfree(d);
235  	xfree(buf);
236  	return ret;
237  
238  print_RSA_error:
239  	fprintf(stderr, "ERROR: cannot encode RSA key\n");
240  	ret = 0;
241  	goto print_RSA_exit;
242  }
243  
244  static int
245  print_ec(const br_ec_private_key *sk, outspec *os)
246  {
247  	br_ec_public_key pk;
248  	unsigned kbuf[BR_EC_KBUF_PUB_MAX_SIZE];
249  	unsigned char *buf;
250  	size_t len;
251  	int r;
252  
253  	if (os->print_text) {
254  		print_int_text("x", sk->x, sk->xlen);
255  	}
256  	if (os->print_C) {
257  		print_int_C("EC_X", sk->x, sk->xlen);
258  		printf("\nstatic const br_ec_private_key EC = {\n");
259  		printf("\t%d,\n", sk->curve);
260  		printf("\t(unsigned char *)EC_X, sizeof EC_X\n");
261  		printf("};\n");
262  	}
263  
264  	if (os->rawder == NULL && os->rawpem == NULL
265  		&& os->pk8der == NULL && os->pk8pem == NULL)
266  	{
267  		return 1;
268  	}
269  	if (br_ec_compute_pub(br_ec_get_default(), &pk, kbuf, sk) == 0) {
270  		fprintf(stderr,
271  			"ERROR: cannot re-encode (unsupported curve)\n");
272  		return 0;
273  	}
274  
275  	r = 1;
276  	if (os->rawder != NULL || os->rawpem != NULL) {
277  		len = br_encode_ec_raw_der(NULL, sk, &pk);
278  		if (len == 0) {
279  			fprintf(stderr, "ERROR: cannot re-encode"
280  				" (unsupported curve)\n");
281  			return 0;
282  		}
283  		buf = xmalloc(len);
284  		if (br_encode_ec_raw_der(buf, sk, &pk) != len) {
285  			fprintf(stderr, "ERROR: re-encode failure\n");
286  			xfree(buf);
287  			return 0;
288  		}
289  		if (os->rawder != NULL) {
290  			r &= write_to_file(os->rawder, buf, len);
291  		}
292  		if (os->rawpem != NULL) {
293  			r &= write_to_pem_file(os->rawpem,
294  				buf, len, "EC PRIVATE KEY");
295  		}
296  		xfree(buf);
297  	}
298  	if (os->pk8der != NULL || os->pk8pem != NULL) {
299  		len = br_encode_ec_pkcs8_der(NULL, sk, &pk);
300  		if (len == 0) {
301  			fprintf(stderr, "ERROR: cannot re-encode"
302  				" (unsupported curve)\n");
303  			return 0;
304  		}
305  		buf = xmalloc(len);
306  		if (br_encode_ec_pkcs8_der(buf, sk, &pk) != len) {
307  			fprintf(stderr, "ERROR: re-encode failure\n");
308  			xfree(buf);
309  			return 0;
310  		}
311  		if (os->pk8der != NULL) {
312  			r &= write_to_file(os->pk8der, buf, len);
313  		}
314  		if (os->pk8pem != NULL) {
315  			r &= write_to_pem_file(os->pk8pem,
316  				buf, len, "PRIVATE KEY");
317  		}
318  		xfree(buf);
319  	}
320  	return r;
321  }
322  
323  static int
324  parse_rsa_spec(const char *kgen_spec, unsigned *size, uint32_t *pubexp)
325  {
326  	const char *p;
327  	char *end;
328  	unsigned long ul;
329  
330  	p = kgen_spec;
331  	if (*p != 'r' && *p != 'R') {
332  		return 0;
333  	}
334  	p ++;
335  	if (*p != 's' && *p != 'S') {
336  		return 0;
337  	}
338  	p ++;
339  	if (*p != 'a' && *p != 'A') {
340  		return 0;
341  	}
342  	p ++;
343  	if (*p == 0) {
344  		*size = 2048;
345  		*pubexp = 3;
346  		return 1;
347  	} else if (*p != ':') {
348  		return 0;
349  	}
350  	p ++;
351  	ul = strtoul(p, &end, 10);
352  	if (ul < 512 || ul > 32768) {
353  		return 0;
354  	}
355  	*size = ul;
356  	p = end;
357  	if (*p == 0) {
358  		*pubexp = 3;
359  		return 1;
360  	} else if (*p != ':') {
361  		return 0;
362  	}
363  	p ++;
364  	ul = strtoul(p, &end, 10);
365  	if ((ul & 1) == 0 || ul == 1 || ((ul >> 30) >> 2) != 0) {
366  		return 0;
367  	}
368  	*pubexp = ul;
369  	if (*end != 0) {
370  		return 0;
371  	}
372  	return 1;
373  }
374  
375  static int
376  keygen_rsa(unsigned size, uint32_t pubexp, outspec *os)
377  {
378  	br_hmac_drbg_context rng;
379  	br_prng_seeder seeder;
380  	br_rsa_keygen kg;
381  	br_rsa_private_key sk;
382  	unsigned char *kbuf_priv;
383  	uint32_t r;
384  
385  	seeder = br_prng_seeder_system(NULL);
386  	if (seeder == 0) {
387  		fprintf(stderr, "ERROR: no system source of randomness\n");
388  		return 0;
389  	}
390  	br_hmac_drbg_init(&rng, &br_sha256_vtable, NULL, 0);
391  	if (!seeder(&rng.vtable)) {
392  		fprintf(stderr, "ERROR: system source of randomness failed\n");
393  		return 0;
394  	}
395  	kbuf_priv = xmalloc(BR_RSA_KBUF_PRIV_SIZE(size));
396  	kg = br_rsa_keygen_get_default();
397  	r = kg(&rng.vtable, &sk, kbuf_priv, NULL, NULL, size, pubexp);
398  	if (!r) {
399  		fprintf(stderr, "ERROR: RSA key pair generation failed\n");
400  	} else {
401  		r = print_rsa(&sk, os);
402  	}
403  	xfree(kbuf_priv);
404  	return r;
405  }
406  
407  static int
408  parse_ec_spec(const char *kgen_spec, int *curve)
409  {
410  	const char *p;
411  
412  	*curve = 0;
413  	p = kgen_spec;
414  	if (*p != 'e' && *p != 'E') {
415  		return 0;
416  	}
417  	p ++;
418  	if (*p != 'c' && *p != 'C') {
419  		return 0;
420  	}
421  	p ++;
422  	if (*p == 0) {
423  		*curve = BR_EC_secp256r1;
424  		return 1;
425  	}
426  	if (*p != ':') {
427  		return 0;
428  	}
429  	*curve = get_curve_by_name(p);
430  	return *curve > 0;
431  }
432  
433  static int
434  keygen_ec(int curve, outspec *os)
435  {
436  	br_hmac_drbg_context rng;
437  	br_prng_seeder seeder;
438  	const br_ec_impl *impl;
439  	br_ec_private_key sk;
440  	unsigned char kbuf_priv[BR_EC_KBUF_PRIV_MAX_SIZE];
441  	size_t len;
442  
443  	seeder = br_prng_seeder_system(NULL);
444  	if (seeder == 0) {
445  		fprintf(stderr, "ERROR: no system source of randomness\n");
446  		return 0;
447  	}
448  	br_hmac_drbg_init(&rng, &br_sha256_vtable, NULL, 0);
449  	if (!seeder(&rng.vtable)) {
450  		fprintf(stderr, "ERROR: system source of randomness failed\n");
451  		return 0;
452  	}
453  	impl = br_ec_get_default();
454  	len = br_ec_keygen(&rng.vtable, impl, &sk, kbuf_priv, curve);
455  	if (len == 0) {
456  		fprintf(stderr, "ERROR: curve is not supported\n");
457  		return 0;
458  	}
459  	return print_ec(&sk, os);
460  }
461  
462  static int
463  decode_key(const unsigned char *buf, size_t len, outspec *os)
464  {
465  	br_skey_decoder_context dc;
466  	int err, ret;
467  
468  	br_skey_decoder_init(&dc);
469  	br_skey_decoder_push(&dc, buf, len);
470  	err = br_skey_decoder_last_error(&dc);
471  	if (err != 0) {
472  		const char *errname, *errmsg;
473  
474  		fprintf(stderr, "ERROR (decoding): err=%d\n", err);
475  		errname = find_error_name(err, &errmsg);
476  		if (errname != NULL) {
477  			fprintf(stderr, "  %s: %s\n", errname, errmsg);
478  		} else {
479  			fprintf(stderr, "  (unknown)\n");
480  		}
481  		return 0;
482  	}
483  	ret = 1;
484  	switch (br_skey_decoder_key_type(&dc)) {
485  		const br_rsa_private_key *rk;
486  		const br_ec_private_key *ek;
487  
488  	case BR_KEYTYPE_RSA:
489  		rk = br_skey_decoder_get_rsa(&dc);
490  		printf("RSA key (%lu bits)\n", (unsigned long)rk->n_bitlen);
491  		ret = print_rsa(rk, os);
492  		break;
493  
494  	case BR_KEYTYPE_EC:
495  		ek = br_skey_decoder_get_ec(&dc);
496  		printf("EC key (curve = %d: %s)\n",
497  			ek->curve, ec_curve_name(ek->curve));
498  		ret = print_ec(ek, os);
499  		break;
500  
501  	default:
502  		fprintf(stderr, "Unknown key type: %d\n",
503  			br_skey_decoder_key_type(&dc));
504  		ret = 0;
505  		break;
506  	}
507  
508  	return ret;
509  }
510  
511  static void
512  usage_skey(void)
513  {
514  	fprintf(stderr,
515  "usage: brssl skey [ options ] file...\n");
516  	fprintf(stderr,
517  "options:\n");
518  	fprintf(stderr,
519  "   -q             suppress verbose messages\n");
520  	fprintf(stderr,
521  "   -text          print private key details (human-readable)\n");
522  	fprintf(stderr,
523  "   -C             print private key details (C code)\n");
524  	fprintf(stderr,
525  "   -rawder file   save private key in 'file' (raw format, DER)\n");
526  	fprintf(stderr,
527  "   -rawpem file   save private key in 'file' (raw format, PEM)\n");
528  	fprintf(stderr,
529  "   -pk8der file   save private key in 'file' (PKCS#8 format, DER)\n");
530  	fprintf(stderr,
531  "   -pk8pem file   save private key in 'file' (PKCS#8 format, PEM)\n");
532  	fprintf(stderr,
533  "   -gen spec      generate a new key using the provided key specification\n");
534  	fprintf(stderr,
535  "   -list          list known elliptic curve names\n");
536  	fprintf(stderr,
537  "Key specification begins with a key type, followed by optional parameters\n");
538  	fprintf(stderr,
539  "that depend on the key type, separated by colon characters:\n");
540  	fprintf(stderr,
541  "   rsa[:size[:pubexep]]   RSA key (defaults: size = 2048, pubexp = 3)\n");
542  	fprintf(stderr,
543  "   ec[:curvename]         EC key (default curve: secp256r1)\n");
544  }
545  
546  /* see brssl.h */
547  int
548  do_skey(int argc, char *argv[])
549  {
550  	int retcode;
551  	int verbose;
552  	int i, num_files;
553  	outspec os;
554  	unsigned char *buf;
555  	size_t len;
556  	pem_object *pos;
557  	const char *kgen_spec;
558  
559  	retcode = 0;
560  	verbose = 1;
561  	os.print_text = 0;
562  	os.print_C = 0;
563  	os.rawder = NULL;
564  	os.rawpem = NULL;
565  	os.pk8der = NULL;
566  	os.pk8pem = NULL;
567  	num_files = 0;
568  	buf = NULL;
569  	pos = NULL;
570  	kgen_spec = NULL;
571  	for (i = 0; i < argc; i ++) {
572  		const char *arg;
573  
574  		arg = argv[i];
575  		if (arg[0] != '-') {
576  			num_files ++;
577  			continue;
578  		}
579  		argv[i] = NULL;
580  		if (eqstr(arg, "-v") || eqstr(arg, "-verbose")) {
581  			verbose = 1;
582  		} else if (eqstr(arg, "-q") || eqstr(arg, "-quiet")) {
583  			verbose = 0;
584  		} else if (eqstr(arg, "-text")) {
585  			os.print_text = 1;
586  		} else if (eqstr(arg, "-C")) {
587  			os.print_C = 1;
588  		} else if (eqstr(arg, "-rawder")) {
589  			if (++ i >= argc) {
590  				fprintf(stderr,
591  					"ERROR: no argument for '-rawder'\n");
592  				usage_skey();
593  				goto skey_exit_error;
594  			}
595  			if (os.rawder != NULL) {
596  				fprintf(stderr,
597  					"ERROR: multiple '-rawder' options\n");
598  				usage_skey();
599  				goto skey_exit_error;
600  			}
601  			os.rawder = argv[i];
602  			argv[i] = NULL;
603  		} else if (eqstr(arg, "-rawpem")) {
604  			if (++ i >= argc) {
605  				fprintf(stderr,
606  					"ERROR: no argument for '-rawpem'\n");
607  				usage_skey();
608  				goto skey_exit_error;
609  			}
610  			if (os.rawpem != NULL) {
611  				fprintf(stderr,
612  					"ERROR: multiple '-rawpem' options\n");
613  				usage_skey();
614  				goto skey_exit_error;
615  			}
616  			os.rawpem = argv[i];
617  			argv[i] = NULL;
618  		} else if (eqstr(arg, "-pk8der")) {
619  			if (++ i >= argc) {
620  				fprintf(stderr,
621  					"ERROR: no argument for '-pk8der'\n");
622  				usage_skey();
623  				goto skey_exit_error;
624  			}
625  			if (os.pk8der != NULL) {
626  				fprintf(stderr,
627  					"ERROR: multiple '-pk8der' options\n");
628  				usage_skey();
629  				goto skey_exit_error;
630  			}
631  			os.pk8der = argv[i];
632  			argv[i] = NULL;
633  		} else if (eqstr(arg, "-pk8pem")) {
634  			if (++ i >= argc) {
635  				fprintf(stderr,
636  					"ERROR: no argument for '-pk8pem'\n");
637  				usage_skey();
638  				goto skey_exit_error;
639  			}
640  			if (os.pk8pem != NULL) {
641  				fprintf(stderr,
642  					"ERROR: multiple '-pk8pem' options\n");
643  				usage_skey();
644  				goto skey_exit_error;
645  			}
646  			os.pk8pem = argv[i];
647  			argv[i] = NULL;
648  		} else if (eqstr(arg, "-gen")) {
649  			if (++ i >= argc) {
650  				fprintf(stderr,
651  					"ERROR: no argument for '-gen'\n");
652  				usage_skey();
653  				goto skey_exit_error;
654  			}
655  			if (kgen_spec != NULL) {
656  				fprintf(stderr,
657  					"ERROR: multiple '-gen' options\n");
658  				usage_skey();
659  				goto skey_exit_error;
660  			}
661  			kgen_spec = argv[i];
662  			argv[i] = NULL;
663  		} else if (eqstr(arg, "-list")) {
664  			list_curves();
665  			goto skey_exit;
666  		} else {
667  			fprintf(stderr, "ERROR: unknown option: '%s'\n", arg);
668  			usage_skey();
669  			goto skey_exit_error;
670  		}
671  	}
672  	if (kgen_spec != NULL) {
673  		unsigned rsa_size;
674  		uint32_t rsa_pubexp;
675  		int curve;
676  
677  		if (num_files != 0) {
678  			fprintf(stderr,
679  				"ERROR: key files provided while generating\n");
680  			usage_skey();
681  			goto skey_exit_error;
682  		}
683  
684  		if (parse_rsa_spec(kgen_spec, &rsa_size, &rsa_pubexp)) {
685  			if (!keygen_rsa(rsa_size, rsa_pubexp, &os)) {
686  				goto skey_exit_error;
687  			}
688  		} else if (parse_ec_spec(kgen_spec, &curve)) {
689  			if (!keygen_ec(curve, &os)) {
690  				goto skey_exit_error;
691  			}
692  		} else {
693  			fprintf(stderr,
694  				"ERROR: unknown key specification: '%s'\n",
695  				kgen_spec);
696  			usage_skey();
697  			goto skey_exit_error;
698  		}
699  	} else if (num_files == 0) {
700  		fprintf(stderr, "ERROR: no private key provided\n");
701  		usage_skey();
702  		goto skey_exit_error;
703  	}
704  
705  	for (i = 0; i < argc; i ++) {
706  		const char *fname;
707  
708  		fname = argv[i];
709  		if (fname == NULL) {
710  			continue;
711  		}
712  		buf = read_file(fname, &len);
713  		if (buf == NULL) {
714  			goto skey_exit_error;
715  		}
716  		if (looks_like_DER(buf, len)) {
717  			if (verbose) {
718  				fprintf(stderr, "File '%s': ASN.1/DER object\n",
719  					fname);
720  			}
721  			if (!decode_key(buf, len, &os)) {
722  				goto skey_exit_error;
723  			}
724  		} else {
725  			size_t u, num;
726  
727  			if (verbose) {
728  				fprintf(stderr, "File '%s': decoding as PEM\n",
729  					fname);
730  			}
731  			pos = decode_pem(buf, len, &num);
732  			if (pos == NULL) {
733  				goto skey_exit_error;
734  			}
735  			for (u = 0; pos[u].name; u ++) {
736  				const char *name;
737  
738  				name = pos[u].name;
739  				if (eqstr(name, "RSA PRIVATE KEY")
740  					|| eqstr(name, "EC PRIVATE KEY")
741  					|| eqstr(name, "PRIVATE KEY"))
742  				{
743  					if (!decode_key(pos[u].data,
744  						pos[u].data_len, &os))
745  					{
746  						goto skey_exit_error;
747  					}
748  				} else {
749  					if (verbose) {
750  						fprintf(stderr,
751  							"(skipping '%s')\n",
752  							name);
753  					}
754  				}
755  			}
756  			for (u = 0; pos[u].name; u ++) {
757  				free_pem_object_contents(&pos[u]);
758  			}
759  			xfree(pos);
760  			pos = NULL;
761  		}
762  		xfree(buf);
763  		buf = NULL;
764  	}
765  
766  	/*
767  	 * Release allocated structures.
768  	 */
769  skey_exit:
770  	xfree(buf);
771  	if (pos != NULL) {
772  		size_t u;
773  
774  		for (u = 0; pos[u].name; u ++) {
775  			free_pem_object_contents(&pos[u]);
776  		}
777  		xfree(pos);
778  	}
779  	return retcode;
780  
781  skey_exit_error:
782  	retcode = -1;
783  	goto skey_exit;
784  }