diff --git a/configure.in b/configure.in index b15005aca..002af39b7 100644 --- a/configure.in +++ b/configure.in @@ -673,7 +673,7 @@ AC_ARG_ENABLE( AC_ARG_ENABLE( [tools], - AS_HELP_STRING([--disable-tools],[disable additional utilities (openac and scepclient). (default is NO).]), + AS_HELP_STRING([--disable-tools],[disable additional utilities (openac, scepclient and pki). (default is NO).]), [if test x$enableval = xyes; then tools=true else @@ -1444,6 +1444,7 @@ AC_OUTPUT( src/_copyright/Makefile src/openac/Makefile src/scepclient/Makefile + src/pki/Makefile src/dumm/Makefile src/dumm/ext/extconf.rb src/libfast/Makefile diff --git a/src/Makefile.am b/src/Makefile.am index ebdaa6a63..d2ac5f655 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -25,7 +25,7 @@ if USE_UPDOWN endif if USE_TOOLS - SUBDIRS += openac scepclient + SUBDIRS += openac scepclient pki endif if USE_DUMM diff --git a/src/checksum/checksum_builder.c b/src/checksum/checksum_builder.c index a713eb526..ff20fe369 100644 --- a/src/checksum/checksum_builder.c +++ b/src/checksum/checksum_builder.c @@ -89,6 +89,10 @@ int main(int argc, char* argv[]) { name = strdup("scepclient\","); } + else if (strstr(path, "pki")) + { + name = strdup("pki\","); + } else { fprintf(stderr, "don't know how to handle '%s', ignored", path); diff --git a/src/libstrongswan/credentials/keys/key_encoding.h b/src/libstrongswan/credentials/keys/key_encoding.h index ea97a1f2d..27a120e89 100644 --- a/src/libstrongswan/credentials/keys/key_encoding.h +++ b/src/libstrongswan/credentials/keys/key_encoding.h @@ -75,6 +75,9 @@ enum key_encoding_type_t { /** PKCS#1/ASN.1 key encoding */ KEY_PUB_ASN1_DER, KEY_PRIV_ASN1_DER, + /** PEM oncoded PKCS#1 key */ + KEY_PUB_PEM, + KEY_PRIV_PEM, /** PGP key encoding */ KEY_PUB_PGP, KEY_PRIV_PGP, diff --git a/src/pki/.gitignore b/src/pki/.gitignore new file mode 100644 index 000000000..5a8ef6ad3 --- /dev/null +++ b/src/pki/.gitignore @@ -0,0 +1 @@ +pki diff --git a/src/pki/Makefile.am b/src/pki/Makefile.am new file mode 100644 index 000000000..3aa885cff --- /dev/null +++ b/src/pki/Makefile.am @@ -0,0 +1,9 @@ +ipsec_PROGRAMS = pki + +pki_SOURCES = pki.c +pki_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la +INCLUDES = -I$(top_srcdir)/src/libstrongswan +AM_CFLAGS = \ + -DPLUGINDIR=\"${plugindir}\" \ + -DPLUGINS=\""${libstrongswan_plugins}\"" \ + -DSTRONGSWAN_CONF=\"${strongswan_conf}\" diff --git a/src/pki/pki.c b/src/pki/pki.c new file mode 100644 index 000000000..0b3e8cf8d --- /dev/null +++ b/src/pki/pki.c @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2009 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * 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 . + * + * 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. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static int usage(char *error) +{ + FILE *out = stdout; + + if (error) + { + out = stderr; + fprintf(out, "%s\n\n", error); + } + fprintf(out, "strongSwan %s PKI tool\n", VERSION); + fprintf(out, "usage:\n"); + fprintf(out, "pki --help\n"); + fprintf(out, " show this usage information\n"); + fprintf(out, "pki --gen [--type rsa|ecdsa] [--size bits] [--form der|pem|pgp\n"); + fprintf(out, " generate a new private key\n"); + return !!error; +} + +/** + * Generate a private key + */ +static int gen(int argc, char *argv[]) +{ + key_encoding_type_t form = KEY_PRIV_ASN1_DER; + key_type_t type = KEY_RSA; + u_int size = 0; + private_key_t *key; + chunk_t encoding; + + struct option long_opts[] = { + { "type", required_argument, NULL, 't' }, + { "size", required_argument, NULL, 's' }, + { "form", required_argument, NULL, 'f' }, + { 0,0,0,0 } + }; + while (TRUE) + { + switch (getopt_long(argc, argv, "", long_opts, NULL)) + { + case 't': + if (streq(optarg, "rsa")) + { + type = KEY_RSA; + } + else if (streq(optarg, "ecdsa")) + { + type = KEY_ECDSA; + } + else + { + return usage("invalid key type"); + } + continue; + case 'f': + if (streq(optarg, "der")) + { + form = KEY_PRIV_ASN1_DER; + } + else if (streq(optarg, "pem")) + { + form = KEY_PRIV_PEM; + } + else if (streq(optarg, "pgp")) + { + form = KEY_PRIV_PGP; + } + else + { + return usage("invalid key format"); + } + continue; + case 's': + size = atoi(optarg); + if (!size) + { + return usage("invalid key size"); + } + continue; + case EOF: + break; + default: + return usage("invalid --gen option"); + } + break; + } + /* default key sizes */ + if (!size) + { + switch (type) + { + case KEY_RSA: + size = 2048; + break; + case KEY_ECDSA: + size = 384; + break; + default: + break; + } + } + key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type, + BUILD_KEY_SIZE, size, BUILD_END); + if (!key) + { + fprintf(stderr, "private key generation failed\n"); + return 1; + } + if (!key->get_encoding(key, form, &encoding)) + { + fprintf(stderr, "private key encoding failed\n"); + key->destroy(key); + return 1; + } + key->destroy(key); + if (fwrite(encoding.ptr, encoding.len, 1, stdout) != 1) + { + fprintf(stderr, "writing private key failed\n"); + free(encoding.ptr); + return 1; + } + free(encoding.ptr); + return 0; +} + +/** + * Library initialization and operation parsing + */ +int main(int argc, char *argv[]) +{ + struct option long_opts[] = { + { "help", no_argument, NULL, 'h' }, + { "gen", no_argument, NULL, 'g' }, + { 0,0,0,0 } + }; + + atexit(library_deinit); + if (!library_init(STRONGSWAN_CONF)) + { + exit(SS_RC_LIBSTRONGSWAN_INTEGRITY); + } + if (lib->integrity && + !lib->integrity->check_file(lib->integrity, "pki", argv[0])) + { + fprintf(stderr, "integrity check of pki failed\n"); + exit(SS_RC_DAEMON_INTEGRITY); + } + lib->plugins->load(lib->plugins, PLUGINDIR, + lib->settings->get_str(lib->settings, "pki.load", PLUGINS)); + + switch (getopt_long(argc, argv, "", long_opts, NULL)) + { + case 'h': + return usage(NULL); + case 'g': + return gen(argc, argv); + default: + return usage("invalid operation"); + } +} +