summaryrefslogtreecommitdiff
path: root/programs/rsasigkey/rsasigkey.c
diff options
context:
space:
mode:
authorRene Mayrhofer <rene@mayrhofer.eu.org>2007-04-12 20:30:08 +0000
committerRene Mayrhofer <rene@mayrhofer.eu.org>2007-04-12 20:30:08 +0000
commitb0d8ed94fe9e74afb49fdf5f11e4add29879c65c (patch)
treeb20167235628771046e940a82a906a6d0991ee4a /programs/rsasigkey/rsasigkey.c
parentea939d07c84d2a8e51215458063fc05e9c399290 (diff)
downloadvyos-strongswan-b0d8ed94fe9e74afb49fdf5f11e4add29879c65c.tar.gz
vyos-strongswan-b0d8ed94fe9e74afb49fdf5f11e4add29879c65c.zip
[svn-upgrade] Integrating new upstream version, strongswan (4.1.1)
Diffstat (limited to 'programs/rsasigkey/rsasigkey.c')
-rw-r--r--programs/rsasigkey/rsasigkey.c573
1 files changed, 0 insertions, 573 deletions
diff --git a/programs/rsasigkey/rsasigkey.c b/programs/rsasigkey/rsasigkey.c
deleted file mode 100644
index b55dbb889..000000000
--- a/programs/rsasigkey/rsasigkey.c
+++ /dev/null
@@ -1,573 +0,0 @@
-/*
- * RSA signature key generation
- * Copyright (C) 1999, 2000, 2001 Henry Spencer.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * RCSID $Id: rsasigkey.c,v 1.2 2005/08/11 10:35:58 as Exp $
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <time.h>
-#include <limits.h>
-#include <errno.h>
-#include <string.h>
-#include <assert.h>
-#include <getopt.h>
-#include <freeswan.h>
-#include "gmp.h"
-
-#ifndef DEVICE
-#define DEVICE "/dev/random"
-#endif
-#ifndef MAXBITS
-#define MAXBITS 20000
-#endif
-
-/* the code in getoldkey() knows about this */
-#define E 3 /* standard public exponent */
-
-char usage[] = "rsasigkey [--verbose] [--random device] nbits";
-char usage2[] = "rsasigkey [--verbose] --oldkey filename";
-struct option opts[] = {
- {"verbose", 0, NULL, 'v',},
- {"random", 1, NULL, 'r',},
- {"rounds", 1, NULL, 'p',},
- {"oldkey", 1, NULL, 'o',},
- {"hostname", 1, NULL, 'H',},
- {"noopt", 0, NULL, 'n',},
- {"help", 0, NULL, 'h',},
- {"version", 0, NULL, 'V',},
- {0, 0, NULL, 0,}
-};
-int verbose = 0; /* narrate the action? */
-char *device = DEVICE; /* where to get randomness */
-int nrounds = 30; /* rounds of prime checking; 25 is good */
-mpz_t prime1; /* old key's prime1 */
-mpz_t prime2; /* old key's prime2 */
-char outputhostname[1024]; /* hostname for output */
-int do_lcm = 1; /* use lcm(p-1, q-1), not (p-1)*(q-1) */
-
-char me[] = "ipsec rsasigkey"; /* for messages */
-
-/* forwards */
-int getoldkey(char *filename);
-void rsasigkey(int nbits, int useoldkey);
-void initprime(mpz_t var, int nbits, int eval);
-void initrandom(mpz_t var, int nbits);
-void getrandom(size_t nbytes, char *buf);
-char *bundle(int e, mpz_t n, size_t *sizep);
-char *conv(char *bits, size_t nbytes, int format);
-char *hexout(mpz_t var);
-void report(char *msg);
-
-/*
- - main - mostly argument parsing
- */
-int main(int argc, char *argv[])
-{
- int opt;
- extern int optind;
- extern char *optarg;
- int errflg = 0;
- int i;
- int nbits;
- char *oldkeyfile = NULL;
-
- while ((opt = getopt_long(argc, argv, "", opts, NULL)) != EOF)
- switch (opt) {
- case 'v': /* verbose description */
- verbose = 1;
- break;
- case 'r': /* nonstandard /dev/random */
- device = optarg;
- break;
- case 'p': /* number of prime-check rounds */
- nrounds = atoi(optarg);
- if (nrounds <= 0) {
- fprintf(stderr, "%s: rounds must be > 0\n", me);
- exit(2);
- }
- break;
- case 'o': /* reformat old key */
- oldkeyfile = optarg;
- break;
- case 'H': /* set hostname for output */
- strcpy(outputhostname, optarg);
- break;
- case 'n': /* don't optimize the private key */
- do_lcm = 0;
- break;
- case 'h': /* help */
- printf("Usage:\t%s\n", usage);
- printf("\tor\n");
- printf("\t%s\n", usage2);
- exit(0);
- break;
- case 'V': /* version */
- printf("%s %s\n", me, ipsec_version_code());
- exit(0);
- break;
- case '?':
- default:
- errflg = 1;
- break;
- }
- if (errflg || optind != ((oldkeyfile != NULL) ? argc : argc-1)) {
- printf("Usage:\t%s\n", usage);
- printf("\tor\n");
- printf("\t%s\n", usage2);
- exit(2);
- }
-
- if (outputhostname[0] == '\0') {
- i = gethostname(outputhostname, sizeof(outputhostname));
- if (i < 0) {
- fprintf(stderr, "%s: gethostname failed (%s)\n",
- me,
- strerror(errno));
- exit(1);
- }
- }
-
- if (oldkeyfile == NULL) {
- assert(argv[optind] != NULL);
- nbits = atoi(argv[optind]);
- } else
- nbits = getoldkey(oldkeyfile);
-
- if (nbits <= 0) {
- fprintf(stderr, "%s: invalid bit count (%d)\n", me, nbits);
- exit(1);
- } else if (nbits > MAXBITS) {
- fprintf(stderr, "%s: overlarge bit count (max %d)\n", me,
- MAXBITS);
- exit(1);
- } else if (nbits % (CHAR_BIT*2) != 0) { /* *2 for nbits/2-bit primes */
- fprintf(stderr, "%s: bit count (%d) not multiple of %d\n", me,
- nbits, (int)CHAR_BIT*2);
- exit(1);
- }
-
- rsasigkey(nbits, (oldkeyfile == NULL) ? 0 : 1);
- exit(0);
-}
-
-/*
- - getoldkey - fetch an old key's primes
- */
-int /* nbits */
-getoldkey(filename)
-char *filename;
-{
- FILE *f;
- char line[MAXBITS/2];
- char *p;
- char *value;
- static char pube[] = "PublicExponent:";
- static char pubevalue[] = "0x03";
- static char pr1[] = "Prime1:";
- static char pr2[] = "Prime2:";
-# define STREQ(a, b) (strcmp(a, b) == 0)
- int sawpube = 0;
- int sawpr1 = 0;
- int sawpr2 = 0;
- int nbits;
-
- nbits = 0;
-
- if (STREQ(filename, "-"))
- f = stdin;
- else
- f = fopen(filename, "r");
- if (f == NULL) {
- fprintf(stderr, "%s: unable to open file `%s' (%s)\n", me,
- filename, strerror(errno));
- exit(1);
- }
- if (verbose)
- fprintf(stderr, "getting old key from %s...\n", filename);
-
- while (fgets(line, sizeof(line), f) != NULL) {
- p = line + strlen(line) - 1;
- if (*p != '\n') {
- fprintf(stderr, "%s: over-long line in file `%s'\n",
- me, filename);
- exit(1);
- }
- *p = '\0';
-
- p = line + strspn(line, " \t"); /* p -> first word */
- value = strpbrk(p, " \t"); /* value -> after it */
- if (value != NULL) {
- *value++ = '\0';
- value += strspn(value, " \t");
- /* value -> second word if any */
- }
-
- if (value == NULL || *value == '\0') {
- /* wrong format */
- } else if (STREQ(p, pube)) {
- sawpube = 1;
- if (!STREQ(value, pubevalue)) {
- fprintf(stderr, "%s: wrong public exponent (`%s') in old key\n",
- me, value);
- exit(1);
- }
- } else if (STREQ(p, pr1)) {
- if (sawpr1) {
- fprintf(stderr, "%s: duplicate `%s' lines in `%s'\n",
- me, pr1, filename);
- exit(1);
- }
- sawpr1 = 1;
- nbits = (strlen(value) - 2) * 4 * 2;
- if (mpz_init_set_str(prime1, value, 0) < 0) {
- fprintf(stderr, "%s: conversion error in reading old prime1\n",
- me);
- exit(1);
- }
- } else if (STREQ(p, pr2)) {
- if (sawpr2) {
- fprintf(stderr, "%s: duplicate `%s' lines in `%s'\n",
- me, pr2, filename);
- exit(1);
- }
- sawpr2 = 1;
- if (mpz_init_set_str(prime2, value, 0) < 0) {
- fprintf(stderr, "%s: conversion error in reading old prime2\n",
- me);
- exit(1);
- }
- }
- }
-
- if (f != stdin)
- fclose(f);
-
- if (!sawpube || !sawpr1 || !sawpr2) {
- fprintf(stderr, "%s: old key missing or incomplete\n", me);
- exit(1);
- }
-
- assert(sawpr1); /* and thus nbits is known */
- return(nbits);
-}
-
-/*
- - rsasigkey - generate an RSA signature key
- * e is fixed at 3, without discussion. That would not be wise if these
- * keys were to be used for encryption, but for signatures there are some
- * real speed advantages.
- */
-void
-rsasigkey(nbits, useoldkey)
-int nbits;
-int useoldkey; /* take primes from old key? */
-{
- mpz_t p;
- mpz_t q;
- mpz_t n;
- mpz_t e;
- mpz_t d;
- mpz_t q1; /* temporary */
- mpz_t m; /* internal modulus, (p-1)*(q-1) */
- mpz_t t; /* temporary */
- mpz_t exp1;
- mpz_t exp2;
- mpz_t coeff;
- char *bundp;
- size_t bs;
- int success;
- time_t now = time((time_t *)NULL);
-
- /* the easy stuff */
- if (useoldkey) {
- mpz_init_set(p, prime1);
- mpz_init_set(q, prime2);
- } else {
- initprime(p, nbits/2, E);
- initprime(q, nbits/2, E);
- }
- mpz_init(t);
- if (mpz_cmp(p, q) < 0) {
- report("swapping primes so p is the larger...");
- mpz_set(t, p);
- mpz_set(p, q);
- mpz_set(q, t);
- }
- report("computing modulus...");
- mpz_init(n);
- mpz_mul(n, p, q); /* n = p*q */
- mpz_init_set_ui(e, E);
-
- /* internal modulus */
- report("computing lcm(p-1, q-1)...");
- mpz_init_set(m, p);
- mpz_sub_ui(m, m, 1);
- mpz_init_set(q1, q);
- mpz_sub_ui(q1, q1, 1);
- mpz_gcd(t, m, q1); /* t = gcd(p-1, q-1) */
- mpz_mul(m, m, q1); /* m = (p-1)*(q-1) */
- if (do_lcm)
- mpz_divexact(m, m, t); /* m = lcm(p-1, q-1) */
- mpz_gcd(t, m, e);
- assert(mpz_cmp_ui(t, 1) == 0); /* m and e relatively prime */
-
- /* decryption key */
- report("computing d...");
- mpz_init(d);
- success = mpz_invert(d, e, m);
- assert(success); /* e has an inverse mod m */
- if (mpz_cmp_ui(d, 0) < 0)
- mpz_add(d, d, m);
- assert(mpz_cmp(d, m) < 0);
-
- /* the speedup hacks */
- report("computing exp1, exp1, coeff...");
- mpz_init(exp1);
- mpz_sub_ui(t, p, 1);
- mpz_mod(exp1, d, t); /* exp1 = d mod p-1 */
- mpz_init(exp2);
- mpz_sub_ui(t, q, 1);
- mpz_mod(exp2, d, t); /* exp2 = d mod q-1 */
- mpz_init(coeff);
- mpz_invert(coeff, q, p); /* coeff = q^-1 mod p */
- if (mpz_cmp_ui(coeff, 0) < 0)
- mpz_add(coeff, coeff, p);
- assert(mpz_cmp(coeff, p) < 0);
-
- /* and the output */
- /* note, getoldkey() knows about some of this */
- report("output...\n"); /* deliberate extra newline */
- printf("\t# RSA %d bits %s %s", nbits, outputhostname, ctime(&now));
- /* ctime provides \n */
- printf("\t# for signatures only, UNSAFE FOR ENCRYPTION\n");
- bundp = bundle(E, n, &bs);
- printf("\t#pubkey=%s\n", conv(bundp, bs, 's')); /* RFC2537ish format */
- printf("\tModulus: %s\n", hexout(n));
- printf("\tPublicExponent: %s\n", hexout(e));
- printf("\t# everything after this point is secret\n");
- printf("\tPrivateExponent: %s\n", hexout(d));
- printf("\tPrime1: %s\n", hexout(p));
- printf("\tPrime2: %s\n", hexout(q));
- printf("\tExponent1: %s\n", hexout(exp1));
- printf("\tExponent2: %s\n", hexout(exp2));
- printf("\tCoefficient: %s\n", hexout(coeff));
-}
-
-/*
- - initprime - initialize an mpz_t to a random prime of specified size
- * Efficiency tweak: we reject candidates that are 1 higher than a multiple
- * of e, since they will make the internal modulus not relatively prime to e.
- */
-void
-initprime(var, nbits, eval)
-mpz_t var;
-int nbits; /* known to be a multiple of CHAR_BIT */
-int eval; /* value of e; 0 means don't bother w. tweak */
-{
- unsigned long tries;
- size_t len;
-# define OKAY(p) (eval == 0 || mpz_fdiv_ui(p, eval) != 1)
-
- initrandom(var, nbits);
- assert(mpz_fdiv_ui(var, 2) == 1); /* odd number */
-
- report("looking for a prime starting there (can take a while)...");
- tries = 1;
- while (!( OKAY(var) && mpz_probab_prime_p(var, nrounds) )) {
- mpz_add_ui(var, var, 2);
- tries++;
- }
-
- len = mpz_sizeinbase(var, 2);
- assert(len == (size_t)nbits || len == (size_t)(nbits+1));
- if (len == (size_t)(nbits+1)) {
- report("carry out occurred (!), retrying...");
- mpz_clear(var);
- initprime(var, nbits, eval);
- return;
- }
- if (verbose)
- fprintf(stderr, "found it after %lu tries.\n", tries);
-}
-
-/*
- - initrandom - initialize an mpz_t to a random number, specified bit count
- * Converting via hex is a bit weird, but it's the best route GMP gives us.
- * Note that highmost and lowmost bits are forced on -- highmost to give a
- * number of exactly the specified length, lowmost so it is an odd number.
- */
-void
-initrandom(var, nbits)
-mpz_t var;
-int nbits; /* known to be a multiple of CHAR_BIT */
-{
- size_t nbytes = (size_t)(nbits / CHAR_BIT);
- static char bitbuf[MAXBITS/CHAR_BIT];
- static char hexbuf[2 + MAXBITS/4 + 1];
- size_t hsize = sizeof(hexbuf);
-
- assert(nbytes <= sizeof(bitbuf));
- getrandom(nbytes, bitbuf);
- bitbuf[0] |= 01 << (CHAR_BIT-1); /* force high bit on */
- bitbuf[nbytes-1] |= 01; /* force low bit on */
- if (datatot(bitbuf, nbytes, 'x', hexbuf, hsize) > hsize) {
- fprintf(stderr, "%s: can't-happen buffer overflow\n", me);
- exit(1);
- }
- if (mpz_init_set_str(var, hexbuf, 0) < 0) {
- fprintf(stderr, "%s: can't-happen hex conversion error\n", me);
- exit(1);
- }
-}
-
-/*
- - getrandom - get some random bytes from /dev/random (or wherever)
- */
-void
-getrandom(nbytes, buf)
-size_t nbytes;
-char *buf; /* known to be big enough */
-{
- size_t ndone;
- int dev;
- size_t got;
-
- dev = open(device, 0);
- if (dev < 0) {
- fprintf(stderr, "%s: could not open %s (%s)\n", me,
- device, strerror(errno));
- exit(1);
- }
-
- ndone = 0;
- if (verbose)
- fprintf(stderr, "getting %d random bytes from %s...\n", (int) nbytes,
- device);
- while (ndone < nbytes) {
- got = read(dev, buf + ndone, nbytes - ndone);
- if (got < 0) {
- fprintf(stderr, "%s: read error on %s (%s)\n", me,
- device, strerror(errno));
- exit(1);
- }
- if (got == 0) {
- fprintf(stderr, "%s: eof on %s!?!\n", me, device);
- exit(1);
- }
- ndone += got;
- }
-
- close(dev);
-}
-
-/*
- - hexout - prepare hex output, guaranteeing even number of digits
- * (The current FreeS/WAN conversion routines want an even digit count,
- * but mpz_get_str doesn't promise one.)
- */
-char * /* pointer to static buffer (ick) */
-hexout(var)
-mpz_t var;
-{
- static char hexbuf[3 + MAXBITS/4 + 1];
- char *hexp;
-
- mpz_get_str(hexbuf+3, 16, var);
- if (strlen(hexbuf+3)%2 == 0) /* even number of hex digits */
- hexp = hexbuf+1;
- else { /* odd, must pad */
- hexp = hexbuf;
- hexp[2] = '0';
- }
- hexp[0] = '0';
- hexp[1] = 'x';
-
- return hexp;
-}
-
-/*
- - bundle - bundle e and n into an RFC2537-format lump
- * Note, calls hexout.
- */
-char * /* pointer to static buffer (ick) */
-bundle(e, n, sizep)
-int e;
-mpz_t n;
-size_t *sizep;
-{
- char *hexp = hexout(n);
- static char bundbuf[2 + MAXBITS/8];
- const char *er;
- size_t size;
-
- assert(e <= 255);
- bundbuf[0] = 1;
- bundbuf[1] = e;
- er = ttodata(hexp, 0, 0, bundbuf+2, sizeof(bundbuf)-2, &size);
- if (er != NULL) {
- fprintf(stderr, "%s: can't-happen bundle convert error `%s'\n",
- me, er);
- exit(1);
- }
- if (size > sizeof(bundbuf)-2) {
- fprintf(stderr, "%s: can't-happen bundle overflow (need %d)\n",
- me, (int) size);
- exit(1);
- }
- if (sizep != NULL)
- *sizep = size + 2;
- return bundbuf;
-}
-
-/*
- - conv - convert bits to output in specified format
- */
-char * /* pointer to static buffer (ick) */
-conv(bits, nbytes, format)
-char *bits;
-size_t nbytes;
-int format; /* datatot() code */
-{
- static char convbuf[MAXBITS/4 + 50]; /* enough for hex */
- size_t n;
-
- n = datatot(bits, nbytes, format, convbuf, sizeof(convbuf));
- if (n == 0) {
- fprintf(stderr, "%s: can't-happen convert error\n", me);
- exit(1);
- }
- if (n > sizeof(convbuf)) {
- fprintf(stderr, "%s: can't-happen convert overflow (need %d)\n",
- me, (int) n);
- exit(1);
- }
- return convbuf;
-}
-
-/*
- - report - report progress, if indicated
- */
-void
-report(msg)
-char *msg;
-{
- if (!verbose)
- return;
- fprintf(stderr, "%s\n", msg);
-}