summaryrefslogtreecommitdiff
path: root/utils/open-isns/pki.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/open-isns/pki.c')
-rw-r--r--utils/open-isns/pki.c536
1 files changed, 0 insertions, 536 deletions
diff --git a/utils/open-isns/pki.c b/utils/open-isns/pki.c
deleted file mode 100644
index f3af922..0000000
--- a/utils/open-isns/pki.c
+++ /dev/null
@@ -1,536 +0,0 @@
-/*
- * PKI related functions
- *
- * Copyright (C) 2007 Olaf Kirch <olaf.kirch@oracle.com>
- */
-
-#include <sys/stat.h>
-#include <string.h>
-#include <unistd.h>
-#include <limits.h>
-#include <openssl/pem.h>
-#include <openssl/err.h>
-#include <fcntl.h>
-#include "isns.h"
-#include "security.h"
-#include "util.h"
-#include "config.h"
-
-#ifdef WITH_SECURITY
-
-/* versions prior to 9.6.8 didn't seem to have these */
-#if OPADDRCONFIGENSSL_VERSION_NUMBER < 0x00906080L
-# define EVP_MD_CTX_init(c) do { } while (0)
-# define EVP_MD_CTX_cleanup(c) do { } while (0)
-#endif
-#if OPADDRCONFIGENSSL_VERSION_NUMBER < 0x00906070L
-# define i2d_DSA_PUBKEY i2d_DSA_PUBKEY_backwards
-
-static int i2d_DSA_PUBKEY_backwards(DSA *, unsigned char **);
-#endif
-
-static int isns_openssl_init = 0;
-
-static int isns_dsasig_verify(isns_security_t *ctx,
- isns_principal_t *peer,
- buf_t *pdu,
- const struct isns_authblk *);
-static int isns_dsasig_sign(isns_security_t *ctx,
- isns_principal_t *peer,
- buf_t *pdu,
- struct isns_authblk *);
-static EVP_PKEY *isns_dsasig_load_private_pem(isns_security_t *ctx,
- const char *filename);
-static EVP_PKEY *isns_dsasig_load_public_pem(isns_security_t *ctx,
- const char *filename);
-static DSA * isns_dsa_load_params(const char *);
-
-
-/*
- * Create a DSA security context
- */
-isns_security_t *
-isns_create_dsa_context(void)
-{
- isns_security_t *ctx;
-
- if (!isns_openssl_init) {
- ERR_load_crypto_strings();
- OpenSSL_add_all_algorithms();
- OpenSSL_add_all_ciphers();
- OpenSSL_add_all_digests();
- isns_openssl_init = 1;
- }
-
- ctx = isns_calloc(1, sizeof(*ctx));
-
- ctx->is_name = "DSA";
- ctx->is_type = ISNS_AUTH_TYPE_SHA1_DSA;
- ctx->is_replay_window = isns_config.ic_auth.replay_window;
- ctx->is_timestamp_jitter = isns_config.ic_auth.timestamp_jitter;
-
- ctx->is_verify = isns_dsasig_verify;
- ctx->is_sign = isns_dsasig_sign;
- ctx->is_load_private = isns_dsasig_load_private_pem;
- ctx->is_load_public = isns_dsasig_load_public_pem;
-
- isns_debug_auth("Created DSA authentication context\n");
- return ctx;
-}
-
-/*
- * DSA signature generation and verification
- */
-static void
-isns_message_digest(EVP_MD_CTX *md, const buf_t *pdu,
- const struct isns_authblk *blk)
-{
- uint64_t stamp;
-
- EVP_DigestUpdate(md, buf_head(pdu), buf_avail(pdu));
-
- /* The RFC doesn't say which pieces of the
- * message should be hashed.
- * We make an educated guess.
- */
- stamp = htonll(blk->iab_timestamp);
- EVP_DigestUpdate(md, &stamp, sizeof(stamp));
-}
-
-static void
-isns_dsasig_report_errors(const char *msg, isns_print_fn_t *fn)
-{
- unsigned long code;
-
- fn("%s - OpenSSL errors follow:\n", msg);
- while ((code = ERR_get_error()) != 0)
- fn("> %s: %s\n",
- ERR_func_error_string(code),
- ERR_reason_error_string(code));
-}
-
-int
-isns_dsasig_sign(isns_security_t *ctx,
- isns_principal_t *peer,
- buf_t *pdu,
- struct isns_authblk *blk)
-{
- static unsigned char signature[1024];
- unsigned int sig_len = sizeof(signature);
- EVP_MD_CTX md_ctx;
- EVP_PKEY *pkey;
- int err;
-
- if ((pkey = peer->is_key) == NULL)
- return 0;
-
- if (pkey->type != EVP_PKEY_DSA) {
- isns_debug_message(
- "Incompatible public key (spi=%s)\n",
- peer->is_name);
- return 0;
- }
- if (EVP_PKEY_size(pkey) > sizeof(signature)) {
- isns_error("isns_dsasig_sign: signature buffer too small\n");
- return 0;
- }
- if (pkey->pkey.dsa->priv_key == NULL) {
- isns_error("isns_dsasig_sign: oops, seems to be a public key\n");
- return 0;
- }
-
- isns_debug_auth("Signing messages with spi=%s, DSA/%u\n",
- peer->is_name, EVP_PKEY_bits(pkey));
-
- EVP_MD_CTX_init(&md_ctx);
- EVP_SignInit(&md_ctx, EVP_dss1());
- isns_message_digest(&md_ctx, pdu, blk);
- err = EVP_SignFinal(&md_ctx,
- signature, &sig_len,
- pkey);
- EVP_MD_CTX_cleanup(&md_ctx);
-
- if (err == 0) {
- isns_dsasig_report_errors("EVP_SignFinal failed", isns_error);
- return 0;
- }
-
- blk->iab_sig = signature;
- blk->iab_sig_len = sig_len;
- return 1;
-}
-
-int
-isns_dsasig_verify(isns_security_t *ctx,
- isns_principal_t *peer,
- buf_t *pdu,
- const struct isns_authblk *blk)
-{
- EVP_MD_CTX md_ctx;
- EVP_PKEY *pkey;
- int err;
-
- if ((pkey = peer->is_key) == NULL)
- return 0;
-
- if (pkey->type != EVP_PKEY_DSA) {
- isns_debug_message(
- "Incompatible public key (spi=%s)\n",
- peer->is_name);
- return 0;
- }
-
- EVP_MD_CTX_init(&md_ctx);
- EVP_VerifyInit(&md_ctx, EVP_dss1());
- isns_message_digest(&md_ctx, pdu, blk);
- err = EVP_VerifyFinal(&md_ctx,
- blk->iab_sig, blk->iab_sig_len,
- pkey);
- EVP_MD_CTX_cleanup(&md_ctx);
-
- if (err == 0) {
- isns_debug_auth("*** Incorrect signature ***\n");
- return 0;
- }
- if (err < 0) {
- isns_dsasig_report_errors("EVP_VerifyFinal failed", isns_error);
- return 0;
- }
-
- isns_debug_message("Good signature from %s\n",
- peer->is_name?: "<server>");
- return 1;
-}
-
-EVP_PKEY *
-isns_dsasig_load_private_pem(isns_security_t *ctx, const char *filename)
-{
- EVP_PKEY *pkey;
- FILE *fp;
-
- if (!(fp = fopen(filename, "r"))) {
- isns_error("Unable to open DSA keyfile %s: %m\n",
- filename);
- return 0;
- }
-
- pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL);
- fclose(fp);
- return pkey;
-}
-
-EVP_PKEY *
-isns_dsasig_load_public_pem(isns_security_t *ctx, const char *filename)
-{
- EVP_PKEY *pkey;
- FILE *fp;
-
- if (!(fp = fopen(filename, "r"))) {
- isns_error("Unable to open DSA keyfile %s: %m\n",
- filename);
- return 0;
- }
-
- pkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL);
- if (pkey == NULL) {
- isns_dsasig_report_errors("Error loading DSA public key",
- isns_error);
- }
-
- fclose(fp);
- return pkey;
-}
-
-EVP_PKEY *
-isns_dsa_decode_public(const void *ptr, size_t len)
-{
- const unsigned char *der = ptr;
- EVP_PKEY *evp;
- DSA *dsa;
-
- /* Assigning ptr to a temporary variable avoids a silly
- * compiled warning about type-punning. */
- dsa = d2i_DSA_PUBKEY(NULL, &der, len);
- if (dsa == NULL)
- return NULL;
-
- evp = EVP_PKEY_new();
- EVP_PKEY_assign_DSA(evp, dsa);
- return evp;
-}
-
-int
-isns_dsa_encode_public(EVP_PKEY *pkey, void **ptr, size_t *len)
-{
- int bytes;
-
- *ptr = NULL;
- bytes = i2d_DSA_PUBKEY(pkey->pkey.dsa, (unsigned char **) ptr);
- if (bytes < 0)
- return 0;
-
- *len = bytes;
- return 1;
-}
-
-EVP_PKEY *
-isns_dsa_load_public(const char *name)
-{
- return isns_dsasig_load_public_pem(NULL, name);
-}
-
-int
-isns_dsa_store_private(const char *name, EVP_PKEY *key)
-{
- FILE *fp;
- int rv, fd;
-
- if ((fd = open(name, O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0) {
- isns_error("Cannot save DSA key to %s: %m\n", name);
- return 0;
- }
-
- if (!(fp = fdopen(fd, "w"))) {
- isns_error("fdopen(%s): %m\n", name);
- close(fd);
- return 0;
- }
-
- rv = PEM_write_PrivateKey(fp, key, NULL, NULL, 0, 0, NULL);
- fclose(fp);
-
- if (rv == 0)
- isns_dsasig_report_errors("Failed to store private key",
- isns_error);
-
- return rv;
-}
-
-int
-isns_dsa_store_public(const char *name, EVP_PKEY *key)
-{
- FILE *fp;
- int rv;
-
- if (!(fp = fopen(name, "w"))) {
- isns_error("Unable to open %s: %m\n", name);
- return 0;
- }
-
- rv = PEM_write_PUBKEY(fp, key);
- fclose(fp);
-
- if (rv == 0)
- isns_dsasig_report_errors("Failed to store public key",
- isns_error);
-
- return rv;
-}
-
-
-/*
- * DSA key generation
- */
-EVP_PKEY *
-isns_dsa_generate_key(void)
-{
- EVP_PKEY *pkey;
- DSA *dsa = NULL;
-
- if (!(dsa = isns_dsa_load_params(isns_config.ic_dsa.param_file)))
- goto failed;
-
- if (!DSA_generate_key(dsa)) {
- isns_dsasig_report_errors("Failed to generate DSA key",
- isns_error);
- goto failed;
- }
-
- pkey = EVP_PKEY_new();
- EVP_PKEY_assign_DSA(pkey, dsa);
- return pkey;
-
-failed:
- if (dsa)
- DSA_free(dsa);
- return NULL;
-}
-
-DSA *
-isns_dsa_load_params(const char *filename)
-{
- FILE *fp;
- DSA *dsa;
-
- if (!filename) {
- isns_error("Cannot generate key - no DSA parameter file\n");
- return NULL;
- }
- if (!(fp = fopen(filename, "r"))) {
- isns_error("Unable to open %s: %m\n", filename);
- return NULL;
- }
-
- dsa = PEM_read_DSAparams(fp, NULL, NULL, NULL);
- fclose(fp);
-
- if (dsa == NULL) {
- isns_dsasig_report_errors("Error loading DSA parameters",
- isns_error);
- }
-
- return dsa;
-}
-
-static void
-isns_dsa_param_gen_callback(int stage, int index, void *dummy)
-{
- if (stage == 0)
- write(1, "+", 1);
- else if (stage == 1)
- write(1, ".", 1);
- else if (stage == 2)
- write(1, "/", 1);
-}
-
-int
-isns_dsa_init_params(const char *filename)
-{
- FILE *fp;
- DSA *dsa;
-
- if (access(filename, R_OK) == 0)
- return 1;
-
- isns_mkdir_recursive(isns_dirname(filename));
- if (!(fp = fopen(filename, "w"))) {
- isns_error("Unable to open %s: %m\n", filename);
- return 0;
- }
-
- isns_notice("Generating DSA parameters; this may take a while\n");
- dsa = DSA_generate_parameters(1024, NULL, 0,
- NULL, NULL, isns_dsa_param_gen_callback, NULL);
- write(1, "\n", 1);
-
- if (dsa == NULL) {
- isns_dsasig_report_errors("Error generating DSA parameters",
- isns_error);
- fclose(fp);
- return 0;
- }
-
- if (!PEM_write_DSAparams(fp, dsa)) {
- isns_dsasig_report_errors("Error writing DSA parameters",
- isns_error);
- DSA_free(dsa);
- fclose(fp);
- return 0;
- }
- DSA_free(dsa);
- fclose(fp);
- return 1;
-}
-
-/*
- * Make sure the authentication key is present.
- */
-int
-isns_dsa_init_key(const char *filename)
-{
- char pubkey_path[1024];
- EVP_PKEY *pkey;
-
- isns_mkdir_recursive(isns_dirname(filename));
- snprintf(pubkey_path, sizeof(pubkey_path),
- "%s.pub", filename);
- if (access(filename, R_OK) == 0
- && access(pubkey_path, R_OK) == 0)
- return 1;
-
- if (!(pkey = isns_dsa_generate_key())) {
- isns_error("Failed to generate AuthKey\n");
- return 0;
- }
-
- if (!isns_dsa_store_private(filename, pkey)) {
- isns_error("Unable to write private key to %s\n", filename);
- return 0;
- }
- isns_notice("Stored private key in %s\n", filename);
-
- if (!isns_dsa_store_public(pubkey_path, pkey)) {
- isns_error("Unable to write public key to %s\n", pubkey_path);
- return 0;
- }
- isns_notice("Stored private key in %s\n", pubkey_path);
-
- return 1;
-}
-
-/*
- * Simple keystore - this is a flat directory, with
- * public key files using the SPI as their name.
- */
-typedef struct isns_simple_keystore isns_simple_keystore_t;
-struct isns_simple_keystore {
- isns_keystore_t sc_base;
- char * sc_dirpath;
-};
-
-/*
- * Load a DSA key from the cert store
- * In fact, this will load RSA keys as well.
- */
-static EVP_PKEY *
-__isns_simple_keystore_find(isns_keystore_t *store_base,
- const char *name, size_t namelen)
-{
- isns_simple_keystore_t *store = (isns_simple_keystore_t *) store_base;
- char pathname[PATH_MAX];
-
- /* Refuse to open key files with names
- * that refer to parent directories */
- if (memchr(name, '/', namelen) || name[0] == '.')
- return NULL;
-
- snprintf(pathname, sizeof(pathname),
- "%s/%.*s", store->sc_dirpath,
- (int) namelen, name);
- if (access(pathname, R_OK) < 0)
- return NULL;
- return isns_dsasig_load_public_pem(NULL, pathname);
-}
-
-isns_keystore_t *
-isns_create_simple_keystore(const char *dirname)
-{
- isns_simple_keystore_t *store;
-
- store = isns_calloc(1, sizeof(*store));
- store->sc_base.ic_name = "simple key store";
- store->sc_base.ic_find = __isns_simple_keystore_find;
- store->sc_dirpath = isns_strdup(dirname);
-
- return (isns_keystore_t *) store;
-}
-
-#if OPADDRCONFIGENSSL_VERSION_NUMBER < 0x00906070L
-#undef i2d_DSA_PUBKEY
-
-int
-i2d_DSA_PUBKEY_backwards(DSA *dsa, unsigned char **ptr)
-{
- unsigned char *buf;
- int len;
-
- len = i2d_DSA_PUBKEY(dsa, NULL);
- if (len < 0)
- return 0;
-
- *ptr = buf = OPENSSL_malloc(len);
- return i2d_DSA_PUBKEY(dsa, &buf);
-}
-#endif
-
-#endif /* WITH_SECURITY */