diff options
author | Yves-Alexis Perez <corsac@debian.org> | 2013-02-07 13:27:27 +0100 |
---|---|---|
committer | Yves-Alexis Perez <corsac@debian.org> | 2013-02-07 13:27:27 +0100 |
commit | 7585facf05d927eb6df3929ce09ed5e60d905437 (patch) | |
tree | e4d14b4dc180db20356b6b01ce0112f3a2d7897e /src/pki/commands | |
parent | c1343b3278cdf99533b7902744d15969f9d6fdc1 (diff) | |
download | vyos-strongswan-7585facf05d927eb6df3929ce09ed5e60d905437.tar.gz vyos-strongswan-7585facf05d927eb6df3929ce09ed5e60d905437.zip |
Imported Upstream version 5.0.2
Diffstat (limited to 'src/pki/commands')
-rw-r--r-- | src/pki/commands/gen.c | 57 | ||||
-rw-r--r-- | src/pki/commands/issue.c | 4 | ||||
-rw-r--r-- | src/pki/commands/pkcs7.c | 462 | ||||
-rw-r--r-- | src/pki/commands/req.c | 2 | ||||
-rw-r--r-- | src/pki/commands/self.c | 2 | ||||
-rw-r--r-- | src/pki/commands/signcrl.c | 4 |
6 files changed, 517 insertions, 14 deletions
diff --git a/src/pki/commands/gen.c b/src/pki/commands/gen.c index 33d9cf35d..e3602f0c3 100644 --- a/src/pki/commands/gen.c +++ b/src/pki/commands/gen.c @@ -22,9 +22,10 @@ static int gen() { cred_encoding_type_t form = PRIVKEY_ASN1_DER; key_type_t type = KEY_RSA; - u_int size = 0; + u_int size = 0, shares = 0, threshold = 1; private_key_t *key; chunk_t encoding; + bool safe_primes = FALSE; char *arg; while (TRUE) @@ -60,6 +61,23 @@ static int gen() return command_usage("invalid key size"); } continue; + case 'p': + safe_primes = TRUE; + continue; + case 'n': + shares = atoi(arg); + if (shares < 2) + { + return command_usage("invalid number of key shares"); + } + continue; + case 'l': + threshold = atoi(arg); + if (threshold < 1) + { + return command_usage("invalid key share threshold"); + } + continue; case EOF: break; default: @@ -82,8 +100,27 @@ static int gen() break; } } - key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type, - BUILD_KEY_SIZE, size, BUILD_END); + if (type == KEY_RSA && shares) + { + if (threshold > shares) + { + return command_usage("threshold is larger than number of shares"); + } + key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type, + BUILD_KEY_SIZE, size, BUILD_SAFE_PRIMES, + BUILD_SHARES, shares, BUILD_THRESHOLD, threshold, + BUILD_END); + } + else if (type == KEY_RSA && safe_primes) + { + key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type, + BUILD_KEY_SIZE, size, BUILD_SAFE_PRIMES, BUILD_END); + } + else + { + 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"); @@ -113,12 +150,16 @@ static void __attribute__ ((constructor))reg() { command_register((command_t) { gen, 'g', "gen", "generate a new private key", - {"[--type rsa|ecdsa] [--size bits] [--outform der|pem|pgp]"}, + {" [--type rsa|ecdsa] [--size bits] [--safe-primes]", + "[--shares n] [--threshold l] [--outform der|pem|pgp]"}, { - {"help", 'h', 0, "show usage information"}, - {"type", 't', 1, "type of key, default: rsa"}, - {"size", 's', 1, "keylength in bits, default: rsa 2048, ecdsa 384"}, - {"outform", 'f', 1, "encoding of generated private key"}, + {"help", 'h', 0, "show usage information"}, + {"type", 't', 1, "type of key, default: rsa"}, + {"size", 's', 1, "keylength in bits, default: rsa 2048, ecdsa 384"}, + {"safe-primes", 'p', 0, "generate rsa safe primes"}, + {"shares", 'n', 1, "number of private rsa key shares"}, + {"threshold", 'l', 1, "minimum number of participating rsa key shares"}, + {"outform", 'f', 1, "encoding of generated private key"}, } }); } diff --git a/src/pki/commands/issue.c b/src/pki/commands/issue.c index 47e668b6c..5f098ba41 100644 --- a/src/pki/commands/issue.c +++ b/src/pki/commands/issue.c @@ -17,9 +17,9 @@ #include "pki.h" -#include <debug.h> +#include <utils/debug.h> #include <asn1/asn1.h> -#include <utils/linked_list.h> +#include <collections/linked_list.h> #include <credentials/certificates/certificate.h> #include <credentials/certificates/x509.h> #include <credentials/certificates/pkcs10.h> diff --git a/src/pki/commands/pkcs7.c b/src/pki/commands/pkcs7.c new file mode 100644 index 000000000..790656c62 --- /dev/null +++ b/src/pki/commands/pkcs7.c @@ -0,0 +1,462 @@ +/* + * Copyright (C) 2012 Martin Willi + * Copyright (C) 2012 revosec AG + * + * 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. + */ + +#include "pki.h" + +#include <asn1/oid.h> +#include <asn1/asn1.h> +#include <credentials/containers/pkcs7.h> +#include <credentials/sets/mem_cred.h> + +/** + * Read input data as chunk + */ +static chunk_t read_from_stream(FILE *stream) +{ + char buf[8096]; + size_t len, total = 0; + + while (TRUE) + { + len = fread(buf + total, 1, sizeof(buf) - total, stream); + if (len < (sizeof(buf) - total)) + { + if (ferror(stream)) + { + return chunk_empty; + } + if (feof(stream)) + { + return chunk_clone(chunk_create(buf, total + len)); + } + } + total += len; + if (total == sizeof(buf)) + { + fprintf(stderr, "buffer too small to read input!\n"); + return chunk_empty; + } + } +} + +/** + * Write output data from chunk to stream + */ +static bool write_to_stream(FILE *stream, chunk_t data) +{ + size_t len, total = 0; + + while (total < data.len) + { + len = fwrite(data.ptr + total, 1, data.len - total, stream); + if (len <= 0) + { + return FALSE; + } + total += len; + } + return TRUE; +} + +/** + * Verify PKCS#7 signed-data + */ +static int verify(chunk_t chunk) +{ + container_t *container; + pkcs7_t *pkcs7; + enumerator_t *enumerator; + certificate_t *cert; + auth_cfg_t *auth; + chunk_t data; + time_t t; + bool verified = FALSE; + + container = lib->creds->create(lib->creds, CRED_CONTAINER, CONTAINER_PKCS7, + BUILD_BLOB_ASN1_DER, chunk, BUILD_END); + if (!container) + { + return 1; + } + + if (container->get_type(container) != CONTAINER_PKCS7_SIGNED_DATA) + { + fprintf(stderr, "verification failed, container is %N\n", + container_type_names, container->get_type(container)); + container->destroy(container); + return 1; + } + + pkcs7 = (pkcs7_t*)container; + enumerator = container->create_signature_enumerator(container); + while (enumerator->enumerate(enumerator, &auth)) + { + verified = TRUE; + cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT); + if (cert) + { + fprintf(stderr, "signed by '%Y'", cert->get_subject(cert)); + + if (pkcs7->get_attribute(pkcs7, OID_PKCS9_SIGNING_TIME, + enumerator, &data)) + { + t = asn1_to_time(&data, ASN1_UTCTIME); + if (t != UNDEFINED_TIME) + { + fprintf(stderr, " at %T", &t, FALSE); + } + free(data.ptr); + } + fprintf(stderr, "\n"); + } + } + enumerator->destroy(enumerator); + + if (!verified) + { + fprintf(stderr, "no trusted signature found\n"); + } + + if (verified) + { + if (container->get_data(container, &data)) + { + write_to_stream(stdout, data); + free(data.ptr); + } + else + { + verified = FALSE; + } + } + container->destroy(container); + + return verified ? 0 : 1; +} + +/** + * Sign data into PKCS#7 signed-data + */ +static int sign(chunk_t chunk, certificate_t *cert, private_key_t *key) +{ + container_t *container; + chunk_t encoding; + int res = 1; + + container = lib->creds->create(lib->creds, + CRED_CONTAINER, CONTAINER_PKCS7_SIGNED_DATA, + BUILD_BLOB, chunk, + BUILD_SIGNING_CERT, cert, + BUILD_SIGNING_KEY, key, + BUILD_END); + if (container) + { + if (container->get_encoding(container, &encoding)) + { + write_to_stream(stdout, encoding); + free(encoding.ptr); + } + container->destroy(container); + } + return res; +} + +/** + * Encrypt data to a PKCS#7 enveloped-data + */ +static int encrypt(chunk_t chunk, certificate_t *cert) +{ + container_t *container; + chunk_t encoding; + int res = 1; + + container = lib->creds->create(lib->creds, + CRED_CONTAINER, CONTAINER_PKCS7_ENVELOPED_DATA, + BUILD_BLOB, chunk, BUILD_CERT, cert, + BUILD_END); + if (container) + { + if (container->get_encoding(container, &encoding)) + { + write_to_stream(stdout, encoding); + free(encoding.ptr); + } + container->destroy(container); + } + return res; +} + +/** + * Decrypt PKCS#7 enveloped-data + */ +static int decrypt(chunk_t chunk) +{ + container_t *container; + chunk_t data; + + container = lib->creds->create(lib->creds, CRED_CONTAINER, CONTAINER_PKCS7, + BUILD_BLOB_ASN1_DER, chunk, BUILD_END); + if (!container) + { + return 1; + } + if (container->get_type(container) != CONTAINER_PKCS7_ENVELOPED_DATA) + { + fprintf(stderr, "decryption failed, container is %N\n", + container_type_names, container->get_type(container)); + container->destroy(container); + return 1; + } + if (!container->get_data(container, &data)) + { + fprintf(stderr, "PKCS#7 decryption failed\n"); + container->destroy(container); + return 1; + } + container->destroy(container); + + write_to_stream(stdout, data); + free(data.ptr); + + return 0; +} + +/** + * Show info about PKCS#7 container + */ +static int show(chunk_t chunk) +{ + container_t *container; + pkcs7_t *pkcs7; + enumerator_t *enumerator; + certificate_t *cert; + chunk_t data; + + container = lib->creds->create(lib->creds, CRED_CONTAINER, CONTAINER_PKCS7, + BUILD_BLOB_ASN1_DER, chunk, BUILD_END); + if (!container) + { + return 1; + } + fprintf(stderr, "%N\n", container_type_names, container->get_type(container)); + + if (container->get_type(container) == CONTAINER_PKCS7_SIGNED_DATA) + { + pkcs7 = (pkcs7_t*)container; + enumerator = pkcs7->create_cert_enumerator(pkcs7); + while (enumerator->enumerate(enumerator, &cert)) + { + if (cert->get_encoding(cert, CERT_PEM, &data)) + { + printf("%.*s", (int)data.len, data.ptr); + free(data.ptr); + } + } + enumerator->destroy(enumerator); + } + container->destroy(container); + return 0; +} + +/** + * Wrap/Unwrap PKCs#7 containers + */ +static int pkcs7() +{ + char *arg, *file = NULL; + private_key_t *key = NULL; + certificate_t *cert = NULL; + chunk_t data = chunk_empty; + mem_cred_t *creds; + int res = 1; + FILE *in; + enum { + OP_NONE, + OP_SIGN, + OP_VERIFY, + OP_ENCRYPT, + OP_DECRYPT, + OP_SHOW, + } op = OP_NONE; + + creds = mem_cred_create(); + + while (TRUE) + { + switch (command_getopt(&arg)) + { + case 'h': + creds->destroy(creds); + return command_usage(NULL); + case 'i': + file = arg; + continue; + case 's': + if (op != OP_NONE) + { + goto invalid; + } + op = OP_SIGN; + continue; + case 'u': + if (op != OP_NONE) + { + goto invalid; + } + op = OP_VERIFY; + continue; + case 'e': + if (op != OP_NONE) + { + goto invalid; + } + op = OP_ENCRYPT; + continue; + case 'd': + if (op != OP_NONE) + { + goto invalid; + } + op = OP_DECRYPT; + continue; + case 'p': + if (op != OP_NONE) + { + goto invalid; + } + op = OP_SHOW; + continue; + case 'k': + key = lib->creds->create(lib->creds, + CRED_PRIVATE_KEY, KEY_RSA, + BUILD_FROM_FILE, arg, BUILD_END); + if (!key) + { + fprintf(stderr, "parsing private key failed\n"); + goto end; + } + creds->add_key(creds, key); + continue; + case 'c': + cert = lib->creds->create(lib->creds, + CRED_CERTIFICATE, CERT_X509, + BUILD_FROM_FILE, arg, BUILD_END); + if (!cert) + { + fprintf(stderr, "parsing certificate failed\n"); + goto end; + } + creds->add_cert(creds, TRUE, cert); + continue; + case EOF: + break; + default: + invalid: + creds->destroy(creds); + return command_usage("invalid --pkcs7 option"); + } + break; + } + + if (file) + { + in = fopen(file, "r"); + if (in) + { + data = read_from_stream(in); + fclose(in); + } + } + else + { + data = read_from_stream(stdin); + } + + if (!data.len) + { + fprintf(stderr, "reading input failed!\n"); + goto end; + } + if (op != OP_SHOW && !cert) + { + fprintf(stderr, "requiring a certificate!\n"); + goto end; + } + + lib->credmgr->add_local_set(lib->credmgr, &creds->set, FALSE); + + switch (op) + { + case OP_SIGN: + if (!key) + { + fprintf(stderr, "signing requires a private key\n"); + res = 1; + break; + } + res = sign(data, cert, key); + break; + case OP_VERIFY: + res = verify(data); + break; + case OP_ENCRYPT: + res = encrypt(data, cert); + break; + case OP_DECRYPT: + if (!key) + { + fprintf(stderr, "decryption requires a private key\n"); + res = 1; + break; + } + res = decrypt(data); + break; + case OP_SHOW: + res = show(data); + break; + default: + res = 1; + break; + } + lib->credmgr->remove_local_set(lib->credmgr, &creds->set); + +end: + creds->destroy(creds); + free(data.ptr); + return res; +} + +/** + * Register the command. + */ +static void __attribute__ ((constructor))reg() +{ + command_register((command_t) { + pkcs7, '7', "pkcs7", "PKCS#7 wrap/unwrap functions", + {"--sign | --verify | --encrypt | --decrypt", + "--certificate+ [--key]"}, + { + {"help", 'h', 0, "show usage information"}, + {"sign", 's', 0, "create PKCS#7 signed-data"}, + {"verify", 'u', 0, "verify PKCS#7 signed-data"}, + {"encrypt", 'e', 0, "create PKCS#7 enveloped-data"}, + {"decrypt", 'd', 0, "decrypt PKCS#7 enveloped-data"}, + {"show", 'p', 0, "show info about PKCS#7, print certificates"}, + {"in", 'i', 1, "input file, default: stdin"}, + {"key", 'k', 1, "path to private key for sign/decryp"}, + {"cert", 'c', 1, "path to certificate for sign/verify/encryp"}, + } + }); +} diff --git a/src/pki/commands/req.c b/src/pki/commands/req.c index d050c7032..d90ddc251 100644 --- a/src/pki/commands/req.c +++ b/src/pki/commands/req.c @@ -19,7 +19,7 @@ #include "pki.h" -#include <utils/linked_list.h> +#include <collections/linked_list.h> #include <credentials/certificates/certificate.h> /** diff --git a/src/pki/commands/self.c b/src/pki/commands/self.c index 4a50aa463..448360821 100644 --- a/src/pki/commands/self.c +++ b/src/pki/commands/self.c @@ -17,7 +17,7 @@ #include "pki.h" -#include <utils/linked_list.h> +#include <collections/linked_list.h> #include <credentials/certificates/certificate.h> #include <credentials/certificates/x509.h> #include <asn1/asn1.h> diff --git a/src/pki/commands/signcrl.c b/src/pki/commands/signcrl.c index 4ada120ed..f9746cca7 100644 --- a/src/pki/commands/signcrl.c +++ b/src/pki/commands/signcrl.c @@ -17,8 +17,8 @@ #include "pki.h" -#include <debug.h> -#include <utils/linked_list.h> +#include <utils/debug.h> +#include <collections/linked_list.h> #include <credentials/certificates/certificate.h> #include <credentials/certificates/x509.h> #include <credentials/certificates/crl.h> |