summaryrefslogtreecommitdiff
path: root/src/openvpn/ssl_polarssl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvpn/ssl_polarssl.c')
-rw-r--r--src/openvpn/ssl_polarssl.c242
1 files changed, 221 insertions, 21 deletions
diff --git a/src/openvpn/ssl_polarssl.c b/src/openvpn/ssl_polarssl.c
index 2b5b37b..551c352 100644
--- a/src/openvpn/ssl_polarssl.c
+++ b/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,
@@ -501,8 +636,20 @@ void tls_ctx_personalise_random(struct tls_root_ctx *ctx)
}
}
+int
+tls_version_max(void)
+{
+#if defined(SSL_MAJOR_VERSION_3) && defined(SSL_MINOR_VERSION_3)
+ return TLS_VER_1_2;
+#elif defined(SSL_MAJOR_VERSION_3) && defined(SSL_MINOR_VERSION_2)
+ return TLS_VER_1_1;
+#else
+ return TLS_VER_1_0;
+#endif
+}
+
void key_state_ssl_init(struct key_state_ssl *ks_ssl,
- const struct tls_root_ctx *ssl_ctx, bool is_server, void *session)
+ const struct tls_root_ctx *ssl_ctx, bool is_server, struct tls_session *session)
{
ASSERT(NULL != ssl_ctx);
ASSERT(ks_ssl);
@@ -530,14 +677,61 @@ 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 */
- ssl_set_authmode (ks_ssl->ctx, SSL_VERIFY_REQUIRED);
- ssl_set_verify (ks_ssl->ctx, verify_callback, session);
+#if P2MP_SERVER
+ if (session->opt->ssl_flags & SSLF_CLIENT_CERT_NOT_REQUIRED)
+ {
+ msg (M_WARN, "WARNING: POTENTIALLY DANGEROUS OPTION "
+ "--client-cert-not-required may accept clients which do not present "
+ "a certificate");
+ }
+ else
+#endif
+ {
+ ssl_set_authmode (ks_ssl->ctx, SSL_VERIFY_REQUIRED);
+ ssl_set_verify (ks_ssl->ctx, verify_callback, session);
+ }
+
/* TODO: PolarSSL does not currently support sending the CA chain to the client */
ssl_set_ca_chain (ks_ssl->ctx, ssl_ctx->ca_chain, NULL, NULL );
+ /* Initialize minimum TLS version */
+ {
+ const int tls_version_min = (session->opt->ssl_flags >> SSLF_TLS_VERSION_SHIFT) & SSLF_TLS_VERSION_MASK;
+ int polar_major;
+ int polar_minor;
+ switch (tls_version_min)
+ {
+ case TLS_VER_1_0:
+ default:
+ polar_major = SSL_MAJOR_VERSION_3;
+ polar_minor = SSL_MINOR_VERSION_1;
+ break;
+#if defined(SSL_MAJOR_VERSION_3) && defined(SSL_MINOR_VERSION_2)
+ case TLS_VER_1_1:
+ polar_major = SSL_MAJOR_VERSION_3;
+ polar_minor = SSL_MINOR_VERSION_2;
+ break;
+#endif
+#if defined(SSL_MAJOR_VERSION_3) && defined(SSL_MINOR_VERSION_3)
+ case TLS_VER_1_2:
+ polar_major = SSL_MAJOR_VERSION_3;
+ polar_minor = SSL_MINOR_VERSION_3;
+ break;
+#endif
+ }
+ ssl_set_min_version(ks_ssl->ctx, polar_major, polar_minor);
+ }
+
/* Initialise BIOs */
ALLOC_OBJ_CLEAR (ks_ssl->ct_in, endless_buffer);
ALLOC_OBJ_CLEAR (ks_ssl->ct_out, endless_buffer);
@@ -839,10 +1033,16 @@ print_details (struct key_state_ssl * ks_ssl, const char *prefix)
}
void
-show_available_tls_ciphers ()
+show_available_tls_ciphers (const char *cipher_list)
{
+ struct tls_root_ctx tls_ctx;
const int *ciphers = ssl_list_ciphersuites();
+ if (cipher_list) {
+ tls_ctx_restrict_ciphers(&tls_ctx, cipher_list);
+ ciphers = tls_ctx.allowed_ciphers;
+ }
+
#ifndef ENABLE_SMALL
printf ("Available TLS Ciphers,\n");
printf ("listed in order of preference:\n\n");