plainrsa-gen.c revision f8a6a7636d53a5730c58ae041e4e09ae12e1657c
1f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh/*	$NetBSD: plainrsa-gen.c,v 1.6 2011/02/11 10:07:19 tteras Exp $	*/
20a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
30a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/* Id: plainrsa-gen.c,v 1.6 2005/04/21 09:08:40 monas Exp */
40a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/*
50a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * Copyright (C) 2004 SuSE Linux AG, Nuernberg, Germany.
60a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * Contributed by: Michal Ludvig <mludvig@suse.cz>, SUSE Labs
70a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * All rights reserved.
80a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang *
90a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * Redistribution and use in source and binary forms, with or without
100a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * modification, are permitted provided that the following conditions
110a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * are met:
120a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * 1. Redistributions of source code must retain the above copyright
130a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang *    notice, this list of conditions and the following disclaimer.
140a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * 2. Redistributions in binary form must reproduce the above copyright
150a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang *    notice, this list of conditions and the following disclaimer in the
160a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang *    documentation and/or other materials provided with the distribution.
170a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * 3. Neither the name of the project nor the names of its contributors
180a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang *    may be used to endorse or promote products derived from this software
190a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang *    without specific prior written permission.
200a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang *
210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
220a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
230a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
240a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
250a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
260a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
290a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
300a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
310a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * SUCH DAMAGE.
320a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang */
330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
340a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/* This file contains a generator for FreeS/WAN-style ipsec.secrets RSA keys. */
350a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
360a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "config.h"
370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
380a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include <stdio.h>
390a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include <string.h>
400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include <errno.h>
410a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include <sys/types.h>
430a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include <sys/stat.h>
440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include <sys/socket.h>
450a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include <unistd.h>
46f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh#include <fcntl.h>
470a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
480a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include <openssl/bio.h>
490a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include <openssl/bn.h>
500a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include <openssl/err.h>
510a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include <openssl/objects.h>
52f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh#include <openssl/pem.h>
530a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include <openssl/rsa.h>
540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include <openssl/evp.h>
550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#ifdef HAVE_OPENSSL_ENGINE_H
560a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include <openssl/engine.h>
570a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#endif
580a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
590a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "misc.h"
600a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "vmbuf.h"
610a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "plog.h"
620a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "crypto_openssl.h"
630a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "package_version.h"
650a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
660a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangvoid
670a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangusage (char *argv0)
680a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{
690a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	fprintf(stderr, "Plain RSA key generator, part of %s\n", TOP_PACKAGE_STRING);
700a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	fprintf(stderr, "By Michal Ludvig (http://www.logix.cz/michal)\n");
710a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	fprintf(stderr, "\n");
720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	fprintf(stderr, "Usage: %s [options]\n", argv0);
730a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	fprintf(stderr, "\n");
740a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	fprintf(stderr, "  -b bits       Generate <bits> long RSA key (default=1024)\n");
750a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	fprintf(stderr, "  -e pubexp     Public exponent to use (default=0x3)\n");
760a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	fprintf(stderr, "  -f filename   Filename to store the key to (default=stdout)\n");
77f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	fprintf(stderr, "  -i filename   Input source for format conversion\n");
780a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	fprintf(stderr, "  -h            Help\n");
790a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	fprintf(stderr, "\n");
800a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	fprintf(stderr, "Report bugs to <ipsec-tools-devel@lists.sourceforge.net>\n");
810a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	exit(1);
820a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang}
830a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
840a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/*
850a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * See RFC 2065, section 3.5 for details about the output format.
860a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang */
870a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangvchar_t *
88f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yehmix_b64_pubkey(const RSA *key)
890a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{
900a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	char *binbuf;
910a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	long binlen, ret;
920a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *res;
930a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
940a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	binlen = 1 + BN_num_bytes(key->e) + BN_num_bytes(key->n);
950a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	binbuf = malloc(binlen);
960a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	memset(binbuf, 0, binlen);
970a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	binbuf[0] = BN_bn2bin(key->e, (unsigned char *) &binbuf[1]);
980a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	ret = BN_bn2bin(key->n, (unsigned char *) (&binbuf[binbuf[0] + 1]));
990a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (1 + binbuf[0] + ret != binlen) {
1000a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
1010a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		     "Pubkey generation failed. This is really strange...\n");
1020a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		return NULL;
1030a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
1040a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
1050a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	return base64_encode(binbuf, binlen);
1060a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang}
1070a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
1080a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangchar *
1090a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wanglowercase(char *input)
1100a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{
1110a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	char *ptr = input;
1120a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	while (*ptr) {
1130a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		if (*ptr >= 'A' && *ptr <= 'F')
1140a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			*ptr -= 'A' - 'a';
1150a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		*ptr++;
1160a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
1170a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
1180a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	return input;
1190a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang}
1200a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
1210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangint
122f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yehprint_rsa_key(FILE *fp, const RSA *key)
1230a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{
1240a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *pubkey64 = NULL;
1250a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
1260a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	pubkey64 = mix_b64_pubkey(key);
1270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (!pubkey64) {
1280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		fprintf(stderr, "mix_b64_pubkey(): %s\n", eay_strerror());
1290a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		return -1;
1300a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
1310a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
1320a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	fprintf(fp, "# : PUB 0s%s\n", pubkey64->v);
1330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	fprintf(fp, ": RSA\t{\n");
134f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	fprintf(fp, "\t# RSA %d bits\n", BN_num_bits(key->n));
1350a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	fprintf(fp, "\t# pubkey=0s%s\n", pubkey64->v);
1360a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	fprintf(fp, "\tModulus: 0x%s\n", lowercase(BN_bn2hex(key->n)));
1370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	fprintf(fp, "\tPublicExponent: 0x%s\n", lowercase(BN_bn2hex(key->e)));
1380a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	fprintf(fp, "\tPrivateExponent: 0x%s\n", lowercase(BN_bn2hex(key->d)));
1390a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	fprintf(fp, "\tPrime1: 0x%s\n", lowercase(BN_bn2hex(key->p)));
1400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	fprintf(fp, "\tPrime2: 0x%s\n", lowercase(BN_bn2hex(key->q)));
1410a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	fprintf(fp, "\tExponent1: 0x%s\n", lowercase(BN_bn2hex(key->dmp1)));
1420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	fprintf(fp, "\tExponent2: 0x%s\n", lowercase(BN_bn2hex(key->dmq1)));
1430a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	fprintf(fp, "\tCoefficient: 0x%s\n", lowercase(BN_bn2hex(key->iqmp)));
1440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	fprintf(fp, "  }\n");
1450a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
1460a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vfree(pubkey64);
147f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	return 0;
148f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh}
149f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh
150f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yehint
151f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yehprint_public_rsa_key(FILE *fp, const RSA *key)
152f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh{
153f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	vchar_t *pubkey64 = NULL;
1540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
155f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	pubkey64 = mix_b64_pubkey(key);
156f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	if (!pubkey64) {
157f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh		fprintf(stderr, "mix_b64_pubkey(): %s\n", eay_strerror());
158f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh		return -1;
159f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	}
160f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh
161f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	fprintf(fp, ": PUB 0s%s\n", pubkey64->v);
162f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh
163f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	vfree(pubkey64);
1640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	return 0;
1650a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang}
1660a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
1670a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangint
168f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yehconvert_rsa_key(FILE *fpout, FILE *fpin)
169f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh{
170f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	int ret;
171f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	RSA *key = NULL;
172f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh
173f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	key = PEM_read_RSAPrivateKey(fpin, NULL, NULL, NULL);
174f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	if (key) {
175f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh		ret = print_rsa_key(fpout, key);
176f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh		RSA_free(key);
177f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh
178f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh		return ret;
179f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	}
180f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh
181f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	rewind(fpin);
182f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh
183f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	key = PEM_read_RSA_PUBKEY(fpin, NULL, NULL, NULL);
184f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	if (key) {
185f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh		ret = print_public_rsa_key(fpout, key);
186f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh		RSA_free(key);
187f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh
188f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh		return ret;
189f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	}
190f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh
191f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	/* Implement parsing of input stream containing
192f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	 * private or public "plainrsa" formatted text.
193f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	 * Convert the result to PEM formatted output.
194f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	 *
195f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	 * This seemingly needs manual use of prsaparse().
196f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	 * An expert ought to do this. */
197f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh
198f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	fprintf(stderr, "convert_rsa_key: %s\n", "Only conversion from PEM at this time");
199f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	return -1;
200f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh}
201f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh
202f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yehint
203f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yehgen_rsa_key(FILE *fp, size_t bits, unsigned long exp)
204f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh{
205f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	int ret;
206f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	RSA *key;
207f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh
208f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	key = RSA_generate_key(bits, exp, NULL, NULL);
209f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	if (!key) {
210f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh		fprintf(stderr, "RSA_generate_key(): %s\n", eay_strerror());
211f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh		return -1;
212f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	}
213f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh
214f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	ret = print_rsa_key(fp, key);
215f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	RSA_free(key);
216f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh
217f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	return ret;
218f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh}
219f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh
220f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yehint
2210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangmain (int argc, char *argv[])
2220a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{
223f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	FILE *fp = stdout, *fpin = NULL;
2240a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	size_t bits = 1024;
2250a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	unsigned int pubexp = 0x3;
2260a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct stat st;
2270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	extern char *optarg;
2280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	extern int optind;
229f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	int c, fd = -1, fdin = -1;
230f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	char *fname = NULL, *finput = NULL;
2310a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
232f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	while ((c = getopt(argc, argv, "e:b:f:i:h")) != -1)
2330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		switch (c) {
2340a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			case 'e':
2350a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				if (strncmp(optarg, "0x", 2) == 0)
2360a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang					sscanf(optarg, "0x%x", &pubexp);
2370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				else
2380a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang					pubexp = atoi(optarg);
2390a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				break;
2400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			case 'b':
2410a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				bits = atoi(optarg);
2420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				break;
2430a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			case 'f':
2440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				fname = optarg;
2450a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				break;
246f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh			case 'i':
247f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh				finput = optarg;
248f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh				break;
2490a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			case 'h':
2500a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			default:
2510a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				usage(argv[0]);
2520a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		}
2530a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
2540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (fname) {
255f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh		umask(0077);
256f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh		/* Restrictive access due to private key material. */
257f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh		fd = open(fname, O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW, S_IRUSR | S_IWUSR);
258f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh		if (fd < 0) {
259f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh			if (errno == EEXIST)
260f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh				fprintf(stderr, "%s: file exists! Please use a different name.\n", fname);
261f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh			else
262f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh				fprintf(stderr, "%s: %s\n", fname, strerror(errno));
2630a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			exit(1);
2640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		}
265f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh		fp = fdopen(fd, "w");
2660a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		if (fp == NULL) {
2670a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			fprintf(stderr, "%s: %s\n", fname, strerror(errno));
268f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh			close(fd);
2690a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			exit(1);
2700a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		}
2710a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
2720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
273f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	if (finput) {
274f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh		/* Restrictive access once more. Do not be fooled by a link. */
275f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh		fdin = open(finput, O_RDONLY | O_NOFOLLOW);
276f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh		if (fdin < 0) {
277f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh			if (errno == ELOOP)
278f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh				fprintf(stderr, "%s: file is a link. Discarded for security.\n", fname);
279f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh			if (fp)
280f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh				fclose(fp);
281f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh			exit(1);
282f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh		}
283f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh		fpin = fdopen(fdin, "r");
284f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh		if (fpin == NULL) {
285f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh			fprintf(stderr, "%s: %s\n", fname, strerror(errno));
286f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh			close(fdin);
287f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh			if (fp)
288f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh				fclose(fp);
289f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh			exit(1);
290f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh		}
291f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh
292f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	}
293f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh
2940a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	ploginit();
2950a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	eay_init();
2960a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
297f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	if (fpin)
298f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh		convert_rsa_key(fp, fpin);
299f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	else
300f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh		gen_rsa_key(fp, bits, pubexp);
3010a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
3020a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	fclose(fp);
303f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	if (fpin)
304f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh		fclose(fpin);
3050a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
3060a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	return 0;
3070a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang}
308