diff options
| author | Arne Schwabe <arne@rfc2549.org> | 2013-11-23 14:08:51 +0100 | 
|---|---|---|
| committer | Arne Schwabe <arne@rfc2549.org> | 2013-11-23 14:08:51 +0100 | 
| commit | d6e51630dcae4b9982a84fcd68b92b5c709d4c52 (patch) | |
| tree | 7214d5d347e8dd2cea6ab69bf6c45e775e7c3b94 /openvpn | |
| parent | c1571bb90a4449cf3d359392b6093079ab705721 (diff) | |
Update OpenVPN source code (closes issue #209)
--HG--
extra : rebase_source : 26d053a6a25472491471f00c12f93965f20e6068
Diffstat (limited to 'openvpn')
| -rw-r--r-- | openvpn/src/openvpn/error.c | 6 | ||||
| -rw-r--r-- | openvpn/src/openvpn/options.c | 2 | ||||
| -rw-r--r-- | openvpn/src/openvpn/ssl.c | 10 | ||||
| -rw-r--r-- | openvpn/src/openvpn/ssl_backend.h | 26 | ||||
| -rw-r--r-- | openvpn/src/openvpn/ssl_openssl.c | 23 | ||||
| -rw-r--r-- | openvpn/src/openvpn/ssl_polarssl.c | 176 | ||||
| -rw-r--r-- | openvpn/src/openvpn/ssl_polarssl.h | 5 | ||||
| -rw-r--r-- | openvpn/src/openvpn/syshead.h | 2 | 
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 | 
