Annotation of embedaddon/ipsec-tools/src/racoon/plainrsa-gen.c, revision 1.1
1.1 ! misho 1: /* $NetBSD: plainrsa-gen.c,v 1.6 2011/02/11 10:07:19 tteras Exp $ */
! 2:
! 3: /* Id: plainrsa-gen.c,v 1.6 2005/04/21 09:08:40 monas Exp */
! 4: /*
! 5: * Copyright (C) 2004 SuSE Linux AG, Nuernberg, Germany.
! 6: * Contributed by: Michal Ludvig <mludvig@suse.cz>, SUSE Labs
! 7: * All rights reserved.
! 8: *
! 9: * Redistribution and use in source and binary forms, with or without
! 10: * modification, are permitted provided that the following conditions
! 11: * are met:
! 12: * 1. Redistributions of source code must retain the above copyright
! 13: * notice, this list of conditions and the following disclaimer.
! 14: * 2. Redistributions in binary form must reproduce the above copyright
! 15: * notice, this list of conditions and the following disclaimer in the
! 16: * documentation and/or other materials provided with the distribution.
! 17: * 3. Neither the name of the project nor the names of its contributors
! 18: * may be used to endorse or promote products derived from this software
! 19: * without specific prior written permission.
! 20: *
! 21: * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 31: * SUCH DAMAGE.
! 32: */
! 33:
! 34: /* This file contains a generator for FreeS/WAN-style ipsec.secrets RSA keys. */
! 35:
! 36: #include "config.h"
! 37:
! 38: #include <stdio.h>
! 39: #include <string.h>
! 40: #include <errno.h>
! 41:
! 42: #include <sys/types.h>
! 43: #include <sys/stat.h>
! 44: #include <sys/socket.h>
! 45: #include <unistd.h>
! 46: #include <fcntl.h>
! 47:
! 48: #include <openssl/bio.h>
! 49: #include <openssl/bn.h>
! 50: #include <openssl/err.h>
! 51: #include <openssl/objects.h>
! 52: #include <openssl/pem.h>
! 53: #include <openssl/rsa.h>
! 54: #include <openssl/evp.h>
! 55: #ifdef HAVE_OPENSSL_ENGINE_H
! 56: #include <openssl/engine.h>
! 57: #endif
! 58:
! 59: #include "misc.h"
! 60: #include "vmbuf.h"
! 61: #include "plog.h"
! 62: #include "crypto_openssl.h"
! 63:
! 64: #include "package_version.h"
! 65:
! 66: void
! 67: usage (char *argv0)
! 68: {
! 69: fprintf(stderr, "Plain RSA key generator, part of %s\n", TOP_PACKAGE_STRING);
! 70: fprintf(stderr, "By Michal Ludvig (http://www.logix.cz/michal)\n");
! 71: fprintf(stderr, "\n");
! 72: fprintf(stderr, "Usage: %s [options]\n", argv0);
! 73: fprintf(stderr, "\n");
! 74: fprintf(stderr, " -b bits Generate <bits> long RSA key (default=1024)\n");
! 75: fprintf(stderr, " -e pubexp Public exponent to use (default=0x3)\n");
! 76: fprintf(stderr, " -f filename Filename to store the key to (default=stdout)\n");
! 77: fprintf(stderr, " -i filename Input source for format conversion\n");
! 78: fprintf(stderr, " -h Help\n");
! 79: fprintf(stderr, "\n");
! 80: fprintf(stderr, "Report bugs to <ipsec-tools-devel@lists.sourceforge.net>\n");
! 81: exit(1);
! 82: }
! 83:
! 84: /*
! 85: * See RFC 2065, section 3.5 for details about the output format.
! 86: */
! 87: vchar_t *
! 88: mix_b64_pubkey(const RSA *key)
! 89: {
! 90: char *binbuf;
! 91: long binlen, ret;
! 92: vchar_t *res;
! 93:
! 94: binlen = 1 + BN_num_bytes(key->e) + BN_num_bytes(key->n);
! 95: binbuf = malloc(binlen);
! 96: memset(binbuf, 0, binlen);
! 97: binbuf[0] = BN_bn2bin(key->e, (unsigned char *) &binbuf[1]);
! 98: ret = BN_bn2bin(key->n, (unsigned char *) (&binbuf[binbuf[0] + 1]));
! 99: if (1 + binbuf[0] + ret != binlen) {
! 100: plog(LLV_ERROR, LOCATION, NULL,
! 101: "Pubkey generation failed. This is really strange...\n");
! 102: return NULL;
! 103: }
! 104:
! 105: return base64_encode(binbuf, binlen);
! 106: }
! 107:
! 108: char *
! 109: lowercase(char *input)
! 110: {
! 111: char *ptr = input;
! 112: while (*ptr) {
! 113: if (*ptr >= 'A' && *ptr <= 'F')
! 114: *ptr -= 'A' - 'a';
! 115: *ptr++;
! 116: }
! 117:
! 118: return input;
! 119: }
! 120:
! 121: int
! 122: print_rsa_key(FILE *fp, const RSA *key)
! 123: {
! 124: vchar_t *pubkey64 = NULL;
! 125:
! 126: pubkey64 = mix_b64_pubkey(key);
! 127: if (!pubkey64) {
! 128: fprintf(stderr, "mix_b64_pubkey(): %s\n", eay_strerror());
! 129: return -1;
! 130: }
! 131:
! 132: fprintf(fp, "# : PUB 0s%s\n", pubkey64->v);
! 133: fprintf(fp, ": RSA\t{\n");
! 134: fprintf(fp, "\t# RSA %d bits\n", BN_num_bits(key->n));
! 135: fprintf(fp, "\t# pubkey=0s%s\n", pubkey64->v);
! 136: fprintf(fp, "\tModulus: 0x%s\n", lowercase(BN_bn2hex(key->n)));
! 137: fprintf(fp, "\tPublicExponent: 0x%s\n", lowercase(BN_bn2hex(key->e)));
! 138: fprintf(fp, "\tPrivateExponent: 0x%s\n", lowercase(BN_bn2hex(key->d)));
! 139: fprintf(fp, "\tPrime1: 0x%s\n", lowercase(BN_bn2hex(key->p)));
! 140: fprintf(fp, "\tPrime2: 0x%s\n", lowercase(BN_bn2hex(key->q)));
! 141: fprintf(fp, "\tExponent1: 0x%s\n", lowercase(BN_bn2hex(key->dmp1)));
! 142: fprintf(fp, "\tExponent2: 0x%s\n", lowercase(BN_bn2hex(key->dmq1)));
! 143: fprintf(fp, "\tCoefficient: 0x%s\n", lowercase(BN_bn2hex(key->iqmp)));
! 144: fprintf(fp, " }\n");
! 145:
! 146: vfree(pubkey64);
! 147: return 0;
! 148: }
! 149:
! 150: int
! 151: print_public_rsa_key(FILE *fp, const RSA *key)
! 152: {
! 153: vchar_t *pubkey64 = NULL;
! 154:
! 155: pubkey64 = mix_b64_pubkey(key);
! 156: if (!pubkey64) {
! 157: fprintf(stderr, "mix_b64_pubkey(): %s\n", eay_strerror());
! 158: return -1;
! 159: }
! 160:
! 161: fprintf(fp, ": PUB 0s%s\n", pubkey64->v);
! 162:
! 163: vfree(pubkey64);
! 164: return 0;
! 165: }
! 166:
! 167: int
! 168: convert_rsa_key(FILE *fpout, FILE *fpin)
! 169: {
! 170: int ret;
! 171: RSA *key = NULL;
! 172:
! 173: key = PEM_read_RSAPrivateKey(fpin, NULL, NULL, NULL);
! 174: if (key) {
! 175: ret = print_rsa_key(fpout, key);
! 176: RSA_free(key);
! 177:
! 178: return ret;
! 179: }
! 180:
! 181: rewind(fpin);
! 182:
! 183: key = PEM_read_RSA_PUBKEY(fpin, NULL, NULL, NULL);
! 184: if (key) {
! 185: ret = print_public_rsa_key(fpout, key);
! 186: RSA_free(key);
! 187:
! 188: return ret;
! 189: }
! 190:
! 191: /* Implement parsing of input stream containing
! 192: * private or public "plainrsa" formatted text.
! 193: * Convert the result to PEM formatted output.
! 194: *
! 195: * This seemingly needs manual use of prsaparse().
! 196: * An expert ought to do this. */
! 197:
! 198: fprintf(stderr, "convert_rsa_key: %s\n", "Only conversion from PEM at this time");
! 199: return -1;
! 200: }
! 201:
! 202: int
! 203: gen_rsa_key(FILE *fp, size_t bits, unsigned long exp)
! 204: {
! 205: int ret;
! 206: RSA *key;
! 207:
! 208: key = RSA_generate_key(bits, exp, NULL, NULL);
! 209: if (!key) {
! 210: fprintf(stderr, "RSA_generate_key(): %s\n", eay_strerror());
! 211: return -1;
! 212: }
! 213:
! 214: ret = print_rsa_key(fp, key);
! 215: RSA_free(key);
! 216:
! 217: return ret;
! 218: }
! 219:
! 220: int
! 221: main (int argc, char *argv[])
! 222: {
! 223: FILE *fp = stdout, *fpin = NULL;
! 224: size_t bits = 1024;
! 225: unsigned int pubexp = 0x3;
! 226: struct stat st;
! 227: extern char *optarg;
! 228: extern int optind;
! 229: int c, fd = -1, fdin = -1;
! 230: char *fname = NULL, *finput = NULL;
! 231:
! 232: while ((c = getopt(argc, argv, "e:b:f:i:h")) != -1)
! 233: switch (c) {
! 234: case 'e':
! 235: if (strncmp(optarg, "0x", 2) == 0)
! 236: sscanf(optarg, "0x%x", &pubexp);
! 237: else
! 238: pubexp = atoi(optarg);
! 239: break;
! 240: case 'b':
! 241: bits = atoi(optarg);
! 242: break;
! 243: case 'f':
! 244: fname = optarg;
! 245: break;
! 246: case 'i':
! 247: finput = optarg;
! 248: break;
! 249: case 'h':
! 250: default:
! 251: usage(argv[0]);
! 252: }
! 253:
! 254: if (fname) {
! 255: umask(0077);
! 256: /* Restrictive access due to private key material. */
! 257: fd = open(fname, O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW, S_IRUSR | S_IWUSR);
! 258: if (fd < 0) {
! 259: if (errno == EEXIST)
! 260: fprintf(stderr, "%s: file exists! Please use a different name.\n", fname);
! 261: else
! 262: fprintf(stderr, "%s: %s\n", fname, strerror(errno));
! 263: exit(1);
! 264: }
! 265: fp = fdopen(fd, "w");
! 266: if (fp == NULL) {
! 267: fprintf(stderr, "%s: %s\n", fname, strerror(errno));
! 268: close(fd);
! 269: exit(1);
! 270: }
! 271: }
! 272:
! 273: if (finput) {
! 274: /* Restrictive access once more. Do not be fooled by a link. */
! 275: fdin = open(finput, O_RDONLY | O_NOFOLLOW);
! 276: if (fdin < 0) {
! 277: if (errno == ELOOP)
! 278: fprintf(stderr, "%s: file is a link. Discarded for security.\n", fname);
! 279: if (fp)
! 280: fclose(fp);
! 281: exit(1);
! 282: }
! 283: fpin = fdopen(fdin, "r");
! 284: if (fpin == NULL) {
! 285: fprintf(stderr, "%s: %s\n", fname, strerror(errno));
! 286: close(fdin);
! 287: if (fp)
! 288: fclose(fp);
! 289: exit(1);
! 290: }
! 291:
! 292: }
! 293:
! 294: ploginit();
! 295: eay_init();
! 296:
! 297: if (fpin)
! 298: convert_rsa_key(fp, fpin);
! 299: else
! 300: gen_rsa_key(fp, bits, pubexp);
! 301:
! 302: fclose(fp);
! 303: if (fpin)
! 304: fclose(fpin);
! 305:
! 306: return 0;
! 307: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>