Return to plainrsa-gen.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / ipsec-tools / src / racoon |
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: }