summaryrefslogtreecommitdiff
path: root/openvpn/src
diff options
context:
space:
mode:
Diffstat (limited to 'openvpn/src')
-rw-r--r--openvpn/src/openvpn/error.c6
-rw-r--r--openvpn/src/openvpn/options.c2
-rw-r--r--openvpn/src/openvpn/ssl.c10
-rw-r--r--openvpn/src/openvpn/ssl_backend.h26
-rw-r--r--openvpn/src/openvpn/ssl_openssl.c23
-rw-r--r--openvpn/src/openvpn/ssl_polarssl.c176
-rw-r--r--openvpn/src/openvpn/ssl_polarssl.h5
-rw-r--r--openvpn/src/openvpn/syshead.h2
8 files changed, 198 insertions, 52 deletions
diff --git a/openvpn/src/openvpn/error.c b/openvpn/src/openvpn/error.c
index 9fdd78b2..af865f32 100644
--- a/openvpn/src/openvpn/error.c
+++ b/openvpn/src/openvpn/error.c
@@ -88,7 +88,7 @@ static bool use_syslog; /* GLOBAL */
/* Should stdout/stderr be be parsable and always be prefixed with time
* and message flags */
-static bool parsable_output; /* GLOBAL */
+static bool machine_readable_output; /* GLOBAL */
/* Should timestamps be included on messages to stdout/stderr? */
static bool suppress_timestamps; /* GLOBAL */
@@ -350,14 +350,14 @@ void x_msg_va (const unsigned int flags, const char *format, va_list arglist)
struct timeval tv;
gettimeofday (&tv, NULL);
- fprintf (fp, "%ld.%06d %x %s%s%s%s",
+ fprintf (fp, "%lu.%06lu %x %s%s%s%s",
tv.tv_sec,
tv.tv_usec,
flags,
prefix,
prefix_sep,
m1,
- (flags&M_NOLF) ? "" : "\n");
+ "\n");
}
else if ((flags & M_NOPREFIX) || suppress_timestamps)
diff --git a/openvpn/src/openvpn/options.c b/openvpn/src/openvpn/options.c
index 77ccf107..6e9377ac 100644
--- a/openvpn/src/openvpn/options.c
+++ b/openvpn/src/openvpn/options.c
@@ -1512,7 +1512,7 @@ show_settings (const struct options *o)
SHOW_INT (inetd);
SHOW_BOOL (log);
SHOW_BOOL (suppress_timestamps);
- SHOW_BOOL (parsable_output);
+ SHOW_BOOL (machine_readable_output);
SHOW_INT (nice);
SHOW_INT (verbosity);
SHOW_INT (mute);
diff --git a/openvpn/src/openvpn/ssl.c b/openvpn/src/openvpn/ssl.c
index 4203fc5c..bd19d754 100644
--- a/openvpn/src/openvpn/ssl.c
+++ b/openvpn/src/openvpn/ssl.c
@@ -509,12 +509,8 @@ init_ssl (const struct options *options, struct tls_root_ctx *new_ctx)
#ifdef MANAGMENT_EXTERNAL_KEY
else if ((options->management_flags & MF_EXTERNAL_KEY) && options->cert_file)
{
- openvpn_x509_cert_t *my_cert = NULL;
- tls_ctx_load_cert_file(new_ctx, options->cert_file, options->cert_file_inline,
- &my_cert);
- tls_ctx_use_external_private_key(new_ctx, my_cert);
-
- tls_ctx_free_cert_file(my_cert);
+ tls_ctx_use_external_private_key(new_ctx, options->cert_file,
+ options->cert_file_inline);
}
#endif
else
@@ -522,7 +518,7 @@ init_ssl (const struct options *options, struct tls_root_ctx *new_ctx)
/* Load Certificate */
if (options->cert_file)
{
- tls_ctx_load_cert_file(new_ctx, options->cert_file, options->cert_file_inline, NULL);
+ tls_ctx_load_cert_file(new_ctx, options->cert_file, options->cert_file_inline);
}
/* Load Private Key */
diff --git a/openvpn/src/openvpn/ssl_backend.h b/openvpn/src/openvpn/ssl_backend.h
index 4d2958c7..07cb9abc 100644
--- a/openvpn/src/openvpn/ssl_backend.h
+++ b/openvpn/src/openvpn/ssl_backend.h
@@ -215,27 +215,13 @@ void tls_ctx_load_cryptoapi(struct tls_root_ctx *ctx, const char *cryptoapi_cert
* Load certificate file into the given TLS context. If the given certificate
* file contains a certificate chain, load the whole chain.
*
- * If the x509 parameter is not NULL, the certificate will be returned in it.
- *
* @param ctx TLS context to use
* @param cert_file The file name to load the certificate from, or
* "[[INLINE]]" in the case of inline files.
* @param cert_file_inline A string containing the certificate
- * @param x509 An optional certificate, if x509 is NULL,
- * do nothing, if x509 is not NULL, *x509 will be
- * allocated and filled with the loaded certificate.
- * *x509 must be NULL.
*/
void tls_ctx_load_cert_file (struct tls_root_ctx *ctx, const char *cert_file,
- const char *cert_file_inline, openvpn_x509_cert_t **x509
- );
-
-/**
- * Free the given certificate
- *
- * @param x509 certificate to free
- */
-void tls_ctx_free_cert_file (openvpn_x509_cert_t *x509);
+ const char *cert_file_inline);
/**
* Load private key file into the given TLS context.
@@ -255,17 +241,19 @@ int tls_ctx_load_priv_file (struct tls_root_ctx *ctx, const char *priv_key_file,
#ifdef MANAGMENT_EXTERNAL_KEY
/**
- * Tell the management interface to load the external private key matching
- * the given certificate.
+ * Tell the management interface to load the given certificate and the external
+ * private key matching the given certificate.
*
* @param ctx TLS context to use
- * @param cert The certificate file to load the private key for
+ * @param cert_file The file name to load the certificate from, or
* "[[INLINE]]" in the case of inline files.
+ * @param cert_file_inline A string containing the certificate
*
* @return 1 if an error occurred, 0 if parsing was
* successful.
*/
-int tls_ctx_use_external_private_key (struct tls_root_ctx *ctx, openvpn_x509_cert_t *cert);
+int tls_ctx_use_external_private_key (struct tls_root_ctx *ctx,
+ const char *cert_file, const char *cert_file_inline);
#endif
diff --git a/openvpn/src/openvpn/ssl_openssl.c b/openvpn/src/openvpn/ssl_openssl.c
index e3926914..120aa666 100644
--- a/openvpn/src/openvpn/ssl_openssl.c
+++ b/openvpn/src/openvpn/ssl_openssl.c
@@ -473,9 +473,10 @@ tls_ctx_add_extra_certs (struct tls_root_ctx *ctx, BIO *bio)
}
}
-void
-tls_ctx_load_cert_file (struct tls_root_ctx *ctx, const char *cert_file,
- const char *cert_file_inline, X509 **x509
+/* Like tls_ctx_load_cert, but returns a copy of the certificate in **X509 */
+static void
+tls_ctx_load_cert_file_and_copy (struct tls_root_ctx *ctx,
+ const char *cert_file, const char *cert_file_inline, X509 **x509
)
{
BIO *in = NULL;
@@ -530,6 +531,13 @@ end:
}
void
+tls_ctx_load_cert_file (struct tls_root_ctx *ctx, const char *cert_file,
+ const char *cert_file_inline)
+{
+ tls_ctx_load_cert_file_and_copy (ctx, cert_file, cert_file_inline, NULL);
+}
+
+void
tls_ctx_free_cert_file (X509 *x509)
{
X509_free(x509);
@@ -665,15 +673,19 @@ rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, i
}
int
-tls_ctx_use_external_private_key (struct tls_root_ctx *ctx, X509 *cert)
+tls_ctx_use_external_private_key (struct tls_root_ctx *ctx,
+ const char *cert_file, const char *cert_file_inline)
{
RSA *rsa = NULL;
RSA *pub_rsa;
RSA_METHOD *rsa_meth;
+ X509 *cert = NULL;
ASSERT (NULL != ctx);
ASSERT (NULL != cert);
+ tls_ctx_load_cert_file_and_copy (ctx, cert_file, cert_file_inline, &cert);
+
/* allocate custom RSA method object */
ALLOC_OBJ_CLEAR (rsa_meth, RSA_METHOD);
rsa_meth->name = "OpenVPN external private key RSA Method";
@@ -708,10 +720,13 @@ tls_ctx_use_external_private_key (struct tls_root_ctx *ctx, X509 *cert)
if (!SSL_CTX_use_RSAPrivateKey(ctx->ctx, rsa))
goto err;
+ X509_free(cert);
RSA_free(rsa); /* doesn't necessarily free, just decrements refcount */
return 1;
err:
+ if (cert)
+ X509_free(cert);
if (rsa)
RSA_free(rsa);
else
diff --git a/openvpn/src/openvpn/ssl_polarssl.c b/openvpn/src/openvpn/ssl_polarssl.c
index fb732254..cdd91890 100644
--- a/openvpn/src/openvpn/ssl_polarssl.c
+++ b/openvpn/src/openvpn/ssl_polarssl.c
@@ -7,6 +7,7 @@
*
* Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
* Copyright (C) 2010 Fox Crypto B.V. <openvpn@fox-it.com>
+ * Copyright (C) 2006-2010, Brainspark B.V.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
@@ -121,6 +122,10 @@ tls_ctx_free(struct tls_root_ctx *ctx)
free(ctx->priv_key_pkcs11);
}
#endif
+#if defined(MANAGMENT_EXTERNAL_KEY)
+ if (ctx->external_key != NULL)
+ free(ctx->external_key);
+#endif
if (ctx->allowed_ciphers)
free(ctx->allowed_ciphers);
@@ -237,13 +242,10 @@ tls_ctx_load_cryptoapi(struct tls_root_ctx *ctx, const char *cryptoapi_cert)
void
tls_ctx_load_cert_file (struct tls_root_ctx *ctx, const char *cert_file,
- const char *cert_file_inline,
- openvpn_x509_cert_t **x509
+ const char *cert_file_inline
)
{
ASSERT(NULL != ctx);
- if (NULL != x509)
- ASSERT(NULL == *x509);
if (!strcmp (cert_file, INLINE_FILE_TAG) && cert_file_inline)
{
@@ -256,16 +258,6 @@ tls_ctx_load_cert_file (struct tls_root_ctx *ctx, const char *cert_file,
if (0 != x509parse_crtfile(ctx->crt_chain, cert_file))
msg (M_FATAL, "Cannot load certificate file %s", cert_file);
}
- if (x509)
- {
- *x509 = ctx->crt_chain;
- }
-}
-
-void
-tls_ctx_free_cert_file (openvpn_x509_cert_t *x509)
-{
- x509_free(x509);
}
int
@@ -322,13 +314,156 @@ tls_ctx_load_priv_file (struct tls_root_ctx *ctx, const char *priv_key_file,
#ifdef MANAGMENT_EXTERNAL_KEY
+
+struct external_context {
+ size_t signature_length;
+};
+
int
-tls_ctx_use_external_private_key (struct tls_root_ctx *ctx, openvpn_x509_cert_t *cert)
+tls_ctx_use_external_private_key (struct tls_root_ctx *ctx,
+ const char *cert_file, const char *cert_file_inline)
{
- msg(M_FATAL, "Use of management external keys not yet supported for PolarSSL.");
- return false;
+ ASSERT(NULL != ctx);
+
+ tls_ctx_load_cert_file(ctx, cert_file, cert_file_inline);
+
+ if (ctx->crt_chain == NULL)
+ return 0;
+
+ /* Most of the initialization happens in key_state_ssl_init() */
+ ALLOC_OBJ_CLEAR (ctx->external_key, struct external_context);
+ ctx->external_key->signature_length = ctx->crt_chain->rsa.len;
+
+ return 1;
+}
+
+static inline int external_pkcs1_sign( void *ctx_voidptr,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int mode,
+ int hash_id, unsigned int hashlen, const unsigned char *hash,
+ unsigned char *sig )
+{
+ struct external_context * const ctx = ctx_voidptr;
+ char *in_b64 = NULL;
+ char *out_b64 = NULL;
+ int rv;
+ unsigned char * const p = sig;
+ size_t asn_len;
+
+ ASSERT(NULL != ctx);
+
+ if (RSA_PRIVATE != mode)
+ {
+ rv = POLARSSL_ERR_RSA_BAD_INPUT_DATA;
+ goto done;
+ }
+
+ /*
+ * Support a wide range of hashes. TLSv1.1 and before only need SIG_RSA_RAW,
+ * but TLSv1.2 needs the full suite of hashes.
+ *
+ * This code has been taken from PolarSSL pkcs11_sign(), under the GPLv2.0+.
+ */
+ switch( hash_id )
+ {
+ case SIG_RSA_RAW:
+ asn_len = 0;
+ memcpy( p, hash, hashlen );
+ break;
+
+ case SIG_RSA_MD2:
+ asn_len = OID_SIZE(ASN1_HASH_MDX);
+ memcpy( p, ASN1_HASH_MDX, asn_len );
+ memcpy( p + asn_len, hash, hashlen );
+ p[13] = 2; break;
+
+ case SIG_RSA_MD4:
+ asn_len = OID_SIZE(ASN1_HASH_MDX);
+ memcpy( p, ASN1_HASH_MDX, asn_len );
+ memcpy( p + asn_len, hash, hashlen );
+ p[13] = 4; break;
+
+ case SIG_RSA_MD5:
+ asn_len = OID_SIZE(ASN1_HASH_MDX);
+ memcpy( p, ASN1_HASH_MDX, asn_len );
+ memcpy( p + asn_len, hash, hashlen );
+ p[13] = 5; break;
+
+ case SIG_RSA_SHA1:
+ asn_len = OID_SIZE(ASN1_HASH_SHA1);
+ memcpy( p, ASN1_HASH_SHA1, asn_len );
+ memcpy( p + 15, hash, hashlen );
+ break;
+
+ case SIG_RSA_SHA224:
+ asn_len = OID_SIZE(ASN1_HASH_SHA2X);
+ memcpy( p, ASN1_HASH_SHA2X, asn_len );
+ memcpy( p + asn_len, hash, hashlen );
+ p[1] += hashlen; p[14] = 4; p[18] += hashlen; break;
+
+ case SIG_RSA_SHA256:
+ asn_len = OID_SIZE(ASN1_HASH_SHA2X);
+ memcpy( p, ASN1_HASH_SHA2X, asn_len );
+ memcpy( p + asn_len, hash, hashlen );
+ p[1] += hashlen; p[14] = 1; p[18] += hashlen; break;
+
+ case SIG_RSA_SHA384:
+ asn_len = OID_SIZE(ASN1_HASH_SHA2X);
+ memcpy( p, ASN1_HASH_SHA2X, asn_len );
+ memcpy( p + asn_len, hash, hashlen );
+ p[1] += hashlen; p[14] = 2; p[18] += hashlen; break;
+
+ case SIG_RSA_SHA512:
+ asn_len = OID_SIZE(ASN1_HASH_SHA2X);
+ memcpy( p, ASN1_HASH_SHA2X, asn_len );
+ memcpy( p + asn_len, hash, hashlen );
+ p[1] += hashlen; p[14] = 3; p[18] += hashlen; break;
+
+ /* End of copy */
+ default:
+ rv = POLARSSL_ERR_RSA_BAD_INPUT_DATA;
+ goto done;
+ }
+
+ /* convert 'from' to base64 */
+ if (openvpn_base64_encode (sig, asn_len + hashlen, &in_b64) <= 0)
+ {
+ rv = POLARSSL_ERR_RSA_BAD_INPUT_DATA;
+ goto done;
+ }
+
+ /* call MI for signature */
+ if (management)
+ out_b64 = management_query_rsa_sig (management, in_b64);
+ if (!out_b64)
+ {
+ rv = POLARSSL_ERR_RSA_PRIVATE_FAILED;
+ goto done;
+ }
+
+ /* decode base64 signature to binary and verify length */
+ if ( openvpn_base64_decode (out_b64, sig, ctx->signature_length) !=
+ ctx->signature_length )
+ {
+ rv = POLARSSL_ERR_RSA_PRIVATE_FAILED;
+ goto done;
+ }
+
+ rv = 0;
+
+ done:
+ if (in_b64)
+ free (in_b64);
+ if (out_b64)
+ free (out_b64);
+ return rv;
}
+static inline size_t external_key_len(void *vctx)
+{
+ struct external_context * const ctx = vctx;
+
+ return ctx->signature_length;
+}
#endif
void tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file,
@@ -542,6 +677,13 @@ void key_state_ssl_init(struct key_state_ssl *ks_ssl,
ssl_pkcs11_key_len );
else
#endif
+#if defined(MANAGMENT_EXTERNAL_KEY)
+ if (ssl_ctx->external_key != NULL)
+ ssl_set_own_cert_alt( ks_ssl->ctx, ssl_ctx->crt_chain,
+ ssl_ctx->external_key, NULL, external_pkcs1_sign,
+ external_key_len );
+ else
+#endif
ssl_set_own_cert( ks_ssl->ctx, ssl_ctx->crt_chain, ssl_ctx->priv_key );
/* Initialise SSL verification */
diff --git a/openvpn/src/openvpn/ssl_polarssl.h b/openvpn/src/openvpn/ssl_polarssl.h
index da936998..fc9aa784 100644
--- a/openvpn/src/openvpn/ssl_polarssl.h
+++ b/openvpn/src/openvpn/ssl_polarssl.h
@@ -30,6 +30,8 @@
#ifndef SSL_POLARSSL_H_
#define SSL_POLARSSL_H_
+#include "syshead.h"
+
#include <polarssl/ssl.h>
#if defined(ENABLE_PKCS11)
@@ -68,6 +70,9 @@ struct tls_root_ctx {
#if defined(ENABLE_PKCS11)
pkcs11_context *priv_key_pkcs11; /**< PKCS11 private key */
#endif
+#ifdef MANAGMENT_EXTERNAL_KEY
+ struct external_context *external_key; /**< Management external key */
+#endif
int * allowed_ciphers; /**< List of allowed ciphers for this connection */
};
diff --git a/openvpn/src/openvpn/syshead.h b/openvpn/src/openvpn/syshead.h
index df6927de..51b24028 100644
--- a/openvpn/src/openvpn/syshead.h
+++ b/openvpn/src/openvpn/syshead.h
@@ -539,7 +539,7 @@ socket_defined (const socket_descriptor_t sd)
/*
* Enable external private key
*/
-#if defined(ENABLE_MANAGEMENT) && defined(ENABLE_SSL) && !defined(ENABLE_CRYPTO_POLARSSL)
+#if defined(ENABLE_MANAGEMENT) && defined(ENABLE_SSL)
#define MANAGMENT_EXTERNAL_KEY
#endif