PolarSSL 1.2 is going end-of-support by 31-12-2015, so we have to move on. Newer versions of polarssl/mbedtls are already released (2.0-2.2), but as previously agreed upon, we will just move release/2.3 to polar 1.3, where master has been for a while now.
This commit removes support for PolarSSL 1.2. The mimimum required version of PolarSSL is now 1.3.8. This commit is a combination of a number of commits related to upgrading or fixing polarssl 1.3 support from the master branch, adjusted to apply to the release/2.3 branch: 03df3a99 Upgrade to PolarSSL 1.3 cc1cee74 Update openvpn-plugin.h for PolarSSL 1.3. 4b9eaa1e Fix regression with password protected private keys (polarssl) d0f26fb5 polarssl: disable 1/n-1 record splitting 444a93ea polarssl: fix --client-cert-not-required 9571010a polarssl: also allocate PKCS#11 certificate object on demand 67a67e39 polarssl: don't use deprecated functions anymore 9d3b7cec polarssl: require >= 1.3.8 This commit was tested using: * Regular private key file * Password-protected private key file * PKCS#11 * --management-external-key * CRL file (with and w/o revoked cert) * With and w/o tls-auth * RSA and ECDSA key/certs Signed-off-by: Steffan Karger <stef...@karger.me> --- README.polarssl | 2 +- configure.ac | 4 +- include/openvpn-plugin.h | 4 +- src/openvpn/crypto_polarssl.c | 13 +- src/openvpn/pkcs11_polarssl.c | 26 ++-- src/openvpn/ssl_polarssl.c | 299 ++++++++++++++++++++------------------ src/openvpn/ssl_polarssl.h | 7 +- src/openvpn/ssl_verify.c | 2 +- src/openvpn/ssl_verify_backend.h | 2 +- src/openvpn/ssl_verify_openssl.c | 2 +- src/openvpn/ssl_verify_polarssl.c | 116 +++++---------- src/openvpn/ssl_verify_polarssl.h | 6 +- 12 files changed, 234 insertions(+), 249 deletions(-) diff --git a/README.polarssl b/README.polarssl index 06f30bf..d34d44a 100644 --- a/README.polarssl +++ b/README.polarssl @@ -7,7 +7,7 @@ To Build and Install, make make install -This version depends on PolarSSL 1.2 (and requires at least 1.2.10). +This version depends on PolarSSL 1.3 (and requires at least 1.3.8). ************************************************************************* diff --git a/configure.ac b/configure.ac index a2f458d..7644c55 100644 --- a/configure.ac +++ b/configure.ac @@ -835,13 +835,13 @@ if test "${with_crypto_library}" = "polarssl" ; then #include <polarssl/version.h> ]], [[ -#if POLARSSL_VERSION_NUMBER < 0x01020A00 || POLARSSL_VERSION_NUMBER >= 0x01030000 +#if POLARSSL_VERSION_NUMBER < 0x01030800 || POLARSSL_VERSION_NUMBER >= 0x01040000 #error invalid version #endif ]] )], [AC_MSG_RESULT([ok])], - [AC_MSG_ERROR([PolarSSL 1.2.x required and must be 1.2.10 or later])] + [AC_MSG_ERROR([PolarSSL 1.3.x required and must be 1.3.8 or later])] ) polarssl_with_pkcs11="no" diff --git a/include/openvpn-plugin.h b/include/openvpn-plugin.h index 03da92a..5f2d407 100644 --- a/include/openvpn-plugin.h +++ b/include/openvpn-plugin.h @@ -29,10 +29,10 @@ #ifdef ENABLE_SSL #ifdef ENABLE_CRYPTO_POLARSSL -#include <polarssl/x509.h> +#include <polarssl/x509_crt.h> #ifndef __OPENVPN_X509_CERT_T_DECLARED #define __OPENVPN_X509_CERT_T_DECLARED -typedef x509_cert openvpn_x509_cert_t; +typedef x509_crt openvpn_x509_cert_t; #endif #else #include <openssl/x509.h> diff --git a/src/openvpn/crypto_polarssl.c b/src/openvpn/crypto_polarssl.c index af79029..24712ed 100644 --- a/src/openvpn/crypto_polarssl.c +++ b/src/openvpn/crypto_polarssl.c @@ -457,7 +457,7 @@ cipher_ctx_init (cipher_context_t *ctx, uint8_t *key, int key_len, void cipher_ctx_cleanup (cipher_context_t *ctx) { - cipher_free_ctx(ctx); + cipher_free(ctx); } int cipher_ctx_iv_length (const cipher_context_t *ctx) @@ -487,7 +487,12 @@ cipher_ctx_get_cipher_kt (const cipher_ctx_t *ctx) int cipher_ctx_reset (cipher_context_t *ctx, uint8_t *iv_buf) { - return 0 == cipher_reset(ctx, iv_buf); + int retval = cipher_reset(ctx); + + if (0 == retval) + retval = cipher_set_iv(ctx, iv_buf, ctx->cipher_info->iv_size); + + return 0 == retval; } int cipher_ctx_update (cipher_context_t *ctx, uint8_t *dst, int *dst_len, @@ -614,7 +619,7 @@ void md_ctx_final (md_context_t *ctx, uint8_t *dst) { ASSERT(0 == md_finish(ctx, dst)); - ASSERT(0 == md_free_ctx(ctx)); + md_free(ctx); } @@ -645,7 +650,7 @@ hmac_ctx_init (md_context_t *ctx, const uint8_t *key, int key_len, const md_info void hmac_ctx_cleanup(md_context_t *ctx) { - ASSERT(0 == md_free_ctx(ctx)); + md_free(ctx); } int diff --git a/src/openvpn/pkcs11_polarssl.c b/src/openvpn/pkcs11_polarssl.c index 03b2bab..a58beef 100644 --- a/src/openvpn/pkcs11_polarssl.c +++ b/src/openvpn/pkcs11_polarssl.c @@ -40,6 +40,7 @@ #include "errlevel.h" #include "pkcs11_backend.h" #include <polarssl/pkcs11.h> +#include <polarssl/x509.h> int pkcs11_init_tls_session(pkcs11h_certificate_t certificate, @@ -49,20 +50,21 @@ pkcs11_init_tls_session(pkcs11h_certificate_t certificate, ASSERT (NULL != ssl_ctx); + ALLOC_OBJ_CLEAR (ssl_ctx->crt_chain, x509_crt); if (pkcs11_x509_cert_init(ssl_ctx->crt_chain, certificate)) { msg (M_FATAL, "PKCS#11: Cannot retrieve PolarSSL certificate object"); goto cleanup; } - ssl_ctx->priv_key_pkcs11 = malloc(sizeof(pkcs11_context)); - - if (ssl_ctx->priv_key_pkcs11 == NULL) { - msg (M_FATAL, "PKCS#11: Cannot allocate PolarSSL private key object"); + ALLOC_OBJ_CLEAR (ssl_ctx->priv_key_pkcs11, pkcs11_context); + if (pkcs11_priv_key_init(ssl_ctx->priv_key_pkcs11, certificate)) { + msg (M_FATAL, "PKCS#11: Cannot initialize PolarSSL private key object"); goto cleanup; } - if (pkcs11_priv_key_init(ssl_ctx->priv_key_pkcs11, certificate)) { - msg (M_FATAL, "PKCS#11: Cannot initialize PolarSSL private key object"); + ALLOC_OBJ_CLEAR (ssl_ctx->priv_key, pk_context); + if (0 != pk_init_ctx_rsa_alt(ssl_ctx->priv_key, ssl_ctx->priv_key_pkcs11, + ssl_pkcs11_decrypt, ssl_pkcs11_sign, ssl_pkcs11_key_len)) { goto cleanup; } @@ -78,14 +80,14 @@ pkcs11_certificate_dn (pkcs11h_certificate_t cert, struct gc_arena *gc) char *ret = NULL; char dn[1024] = {0}; - x509_cert polar_cert = {0}; + x509_crt polar_cert = {0}; if (pkcs11_x509_cert_init(&polar_cert, cert)) { msg (M_FATAL, "PKCS#11: Cannot retrieve PolarSSL certificate object"); goto cleanup; } - if (-1 == x509parse_dn_gets (dn, sizeof(dn), &polar_cert.subject)) { + if (-1 == x509_dn_gets (dn, sizeof(dn), &polar_cert.subject)) { msg (M_FATAL, "PKCS#11: PolarSSL cannot parse subject"); goto cleanup; } @@ -93,7 +95,7 @@ pkcs11_certificate_dn (pkcs11h_certificate_t cert, struct gc_arena *gc) ret = string_alloc(dn, gc); cleanup: - x509_free(&polar_cert); + x509_crt_free(&polar_cert); return ret; } @@ -104,14 +106,14 @@ pkcs11_certificate_serial (pkcs11h_certificate_t cert, char *serial, { int ret = 1; - x509_cert polar_cert = {0}; + x509_crt polar_cert = {0}; if (pkcs11_x509_cert_init(&polar_cert, cert)) { msg (M_FATAL, "PKCS#11: Cannot retrieve PolarSSL certificate object"); goto cleanup; } - if (-1 == x509parse_serial_gets (serial, serial_len, &polar_cert.serial)) { + if (-1 == x509_serial_gets (serial, serial_len, &polar_cert.serial)) { msg (M_FATAL, "PKCS#11: PolarSSL cannot parse serial"); goto cleanup; } @@ -119,7 +121,7 @@ pkcs11_certificate_serial (pkcs11h_certificate_t cert, char *serial, ret = 0; cleanup: - x509_free(&polar_cert); + x509_crt_free(&polar_cert); return ret; } diff --git a/src/openvpn/ssl_polarssl.c b/src/openvpn/ssl_polarssl.c index 32566e4..8d9d219 100644 --- a/src/openvpn/ssl_polarssl.c +++ b/src/openvpn/ssl_polarssl.c @@ -46,12 +46,13 @@ #include "manage.h" #include "ssl_common.h" -#include <polarssl/sha2.h> #include <polarssl/havege.h> #include "ssl_verify_polarssl.h" #include <polarssl/error.h> +#include <polarssl/oid.h> #include <polarssl/pem.h> +#include <polarssl/sha256.h> #include <polarssl/version.h> void @@ -76,11 +77,8 @@ tls_ctx_server_new(struct tls_root_ctx *ctx, unsigned int ssl_flags) CLEAR(*ctx); ALLOC_OBJ_CLEAR(ctx->dhm_ctx, dhm_context); - ALLOC_OBJ_CLEAR(ctx->priv_key, rsa_context); - - ALLOC_OBJ_CLEAR(ctx->ca_chain, x509_cert); - ALLOC_OBJ_CLEAR(ctx->crt_chain, x509_cert); + ALLOC_OBJ_CLEAR(ctx->ca_chain, x509_crt); ctx->endpoint = SSL_IS_SERVER; ctx->initialised = true; @@ -93,10 +91,7 @@ tls_ctx_client_new(struct tls_root_ctx *ctx, unsigned int ssl_flags) CLEAR(*ctx); ALLOC_OBJ_CLEAR(ctx->dhm_ctx, dhm_context); - ALLOC_OBJ_CLEAR(ctx->priv_key, rsa_context); - - ALLOC_OBJ_CLEAR(ctx->ca_chain, x509_cert); - ALLOC_OBJ_CLEAR(ctx->crt_chain, x509_cert); + ALLOC_OBJ_CLEAR(ctx->ca_chain, x509_crt); ctx->endpoint = SSL_IS_CLIENT; ctx->initialised = true; @@ -107,17 +102,21 @@ tls_ctx_free(struct tls_root_ctx *ctx) { if (ctx) { - rsa_free(ctx->priv_key); - free(ctx->priv_key); + pk_free(ctx->priv_key); + if (ctx->priv_key) + free(ctx->priv_key); - x509_free(ctx->ca_chain); - free(ctx->ca_chain); + x509_crt_free(ctx->ca_chain); + if (ctx->ca_chain) + free(ctx->ca_chain); - x509_free(ctx->crt_chain); - free(ctx->crt_chain); + x509_crt_free(ctx->crt_chain); + if (ctx->crt_chain) + free(ctx->crt_chain); dhm_free(ctx->dhm_ctx); - free(ctx->dhm_ctx); + if (ctx->dhm_ctx) + free(ctx->dhm_ctx); #if defined(ENABLE_PKCS11) if (ctx->priv_key_pkcs11 != NULL) { @@ -212,13 +211,13 @@ tls_ctx_load_dh_params (struct tls_root_ctx *ctx, const char *dh_file, { if (!strcmp (dh_file, INLINE_FILE_TAG) && dh_inline) { - if (0 != x509parse_dhm(ctx->dhm_ctx, (const unsigned char *) dh_inline, + if (0 != dhm_parse_dhm(ctx->dhm_ctx, (const unsigned char *) dh_inline, strlen(dh_inline))) msg (M_FATAL, "Cannot read inline DH parameters"); } else { - if (0 != x509parse_dhmfile(ctx->dhm_ctx, dh_file)) + if (0 != dhm_parse_dhmfile(ctx->dhm_ctx, dh_file)) msg (M_FATAL, "Cannot read DH parameters from file %s", dh_file); } @@ -251,15 +250,20 @@ tls_ctx_load_cert_file (struct tls_root_ctx *ctx, const char *cert_file, { ASSERT(NULL != ctx); + if (!ctx->crt_chain) + { + ALLOC_OBJ_CLEAR(ctx->crt_chain, x509_crt); + } + if (!strcmp (cert_file, INLINE_FILE_TAG) && cert_inline) { - if (0 != x509parse_crt(ctx->crt_chain, + if (0 != x509_crt_parse(ctx->crt_chain, (const unsigned char *) cert_inline, strlen(cert_inline))) msg (M_FATAL, "Cannot load inline certificate file"); } else { - if (0 != x509parse_crtfile(ctx->crt_chain, cert_file)) + if (0 != x509_crt_parse_file(ctx->crt_chain, cert_file)) msg (M_FATAL, "Cannot load certificate file %s", cert_file); } } @@ -272,34 +276,40 @@ tls_ctx_load_priv_file (struct tls_root_ctx *ctx, const char *priv_key_file, int status; ASSERT(NULL != ctx); + if (!ctx->priv_key) + { + ALLOC_OBJ_CLEAR(ctx->priv_key, pk_context); + } + if (!strcmp (priv_key_file, INLINE_FILE_TAG) && priv_key_inline) { - status = x509parse_key(ctx->priv_key, + status = pk_parse_key(ctx->priv_key, (const unsigned char *) priv_key_inline, strlen(priv_key_inline), NULL, 0); - if (POLARSSL_ERR_X509_PASSWORD_REQUIRED == status) + + if (POLARSSL_ERR_PK_PASSWORD_REQUIRED == status) { char passbuf[512] = {0}; pem_password_callback(passbuf, 512, 0, NULL); - status = x509parse_key(ctx->priv_key, + status = pk_parse_key(ctx->priv_key, (const unsigned char *) priv_key_inline, strlen(priv_key_inline), - (const unsigned char *) passbuf, strlen(passbuf)); + (unsigned char *) passbuf, strlen(passbuf)); } } else { - status = x509parse_keyfile(ctx->priv_key, priv_key_file, NULL); - if (POLARSSL_ERR_X509_PASSWORD_REQUIRED == status) + status = pk_parse_keyfile(ctx->priv_key, priv_key_file, NULL); + if (POLARSSL_ERR_PK_PASSWORD_REQUIRED == status) { char passbuf[512] = {0}; pem_password_callback(passbuf, 512, 0, NULL); - status = x509parse_keyfile(ctx->priv_key, priv_key_file, passbuf); + status = pk_parse_keyfile(ctx->priv_key, priv_key_file, passbuf); } } if (0 != status) { #ifdef ENABLE_MANAGEMENT - if (management && (POLARSSL_ERR_X509_PASSWORD_MISMATCH == status)) + if (management && (POLARSSL_ERR_PK_PASSWORD_MISMATCH == status)) management_auth_failure (management, UP_TYPE_PRIVATE_KEY, NULL); #endif msg (M_WARN, "Cannot load private key file %s", priv_key_file); @@ -323,43 +333,43 @@ struct external_context { size_t signature_length; }; -int -tls_ctx_use_external_private_key (struct tls_root_ctx *ctx, - const char *cert_file, const char *cert_file_inline) -{ - 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; -} - +/** + * external_pkcs1_sign implements a PolarSSL rsa_sign_func callback, that uses + * the management interface to request an RSA signature for the supplied hash. + * + * @param ctx_voidptr Management external key context. + * @param f_rng (Unused) + * @param p_rng (Unused) + * @param mode RSA mode (should be RSA_PRIVATE). + * @param md_alg Message digest ('hash') algorithm type. + * @param hashlen Length of hash (overridden by length specified by md_alg + * if md_alg != POLARSSL_MD_NONE). + * @param hash The digest ('hash') to sign. Should have a size + * matching the length of md_alg (if != POLARSSL_MD_NONE), + * or hashlen otherwise. + * @param sig Buffer that returns the signature. Should be at least of + * size ctx->signature_length. + * + * @return 0 on success, non-zero polarssl error code on failure. + */ 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, + md_type_t md_alg, 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; + unsigned char *p = sig; + size_t asn_len = 0, oid_size = 0, sig_len = 0; + const char *oid = NULL; - ASSERT(NULL != ctx); + if( NULL == ctx ) + return POLARSSL_ERR_RSA_BAD_INPUT_DATA; - if (RSA_PRIVATE != mode) - { - rv = POLARSSL_ERR_RSA_BAD_INPUT_DATA; - goto done; - } + if( RSA_PRIVATE != mode ) + return POLARSSL_ERR_RSA_BAD_INPUT_DATA; /* * Support a wide range of hashes. TLSv1.1 and before only need SIG_RSA_RAW, @@ -367,67 +377,54 @@ static inline int external_pkcs1_sign( void *ctx_voidptr, * * 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; + if( md_alg != POLARSSL_MD_NONE ) + { + const md_info_t *md_info = md_info_from_type( md_alg ); + if( md_info == NULL ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + if( oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = md_get_size( md_info ); + asn_len = 10 + oid_size; + } + + sig_len = ctx->signature_length; + if ( (SIZE_MAX - hashlen) < asn_len || (hashlen + asn_len) > sig_len ) + return POLARSSL_ERR_RSA_BAD_INPUT_DATA; + + if( md_alg != POLARSSL_MD_NONE ) + { + /* + * DigestInfo ::= SEQUENCE { + * digestAlgorithm DigestAlgorithmIdentifier, + * digest Digest } + * + * DigestAlgorithmIdentifier ::= AlgorithmIdentifier + * + * Digest ::= OCTET STRING + */ + *p++ = ASN1_SEQUENCE | ASN1_CONSTRUCTED; + *p++ = (unsigned char) ( 0x08 + oid_size + hashlen ); + *p++ = ASN1_SEQUENCE | ASN1_CONSTRUCTED; + *p++ = (unsigned char) ( 0x04 + oid_size ); + *p++ = ASN1_OID; + *p++ = oid_size & 0xFF; + memcpy( p, oid, oid_size ); + p += oid_size; + *p++ = ASN1_NULL; + *p++ = 0x00; + *p++ = ASN1_OCTET_STRING; + *p++ = hashlen; + + /* Determine added ASN length */ + asn_len = p - sig; } + /* Copy the hash to be signed */ + memcpy( p, hash, hashlen ); + /* convert 'from' to base64 */ if (openvpn_base64_encode (sig, asn_len + hashlen, &in_b64) <= 0) { @@ -454,7 +451,7 @@ static inline int external_pkcs1_sign( void *ctx_voidptr, rv = 0; - done: +done: if (in_b64) free (in_b64); if (out_b64) @@ -468,6 +465,28 @@ static inline size_t external_key_len(void *vctx) return ctx->signature_length; } + +int +tls_ctx_use_external_private_key (struct tls_root_ctx *ctx, + const char *cert_file, const char *cert_file_inline) +{ + ASSERT(NULL != ctx); + + tls_ctx_load_cert_file(ctx, cert_file, cert_file_inline); + + if (ctx->crt_chain == NULL) + return 0; + + ALLOC_OBJ_CLEAR (ctx->external_key, struct external_context); + ctx->external_key->signature_length = pk_get_len(&ctx->crt_chain->pk); + + ALLOC_OBJ_CLEAR (ctx->priv_key, pk_context); + if (0 != pk_init_ctx_rsa_alt(ctx->priv_key, ctx->external_key, + NULL, external_pkcs1_sign, external_key_len)) + return 0; + + return 1; +} #endif void tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file, @@ -480,14 +499,14 @@ void tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file, if (ca_file && !strcmp (ca_file, INLINE_FILE_TAG) && ca_inline) { - if (0 != x509parse_crt(ctx->ca_chain, (const unsigned char *) ca_inline, + if (0 != x509_crt_parse(ctx->ca_chain, (unsigned char *) ca_inline, strlen(ca_inline))) msg (M_FATAL, "Cannot load inline CA certificates"); } else { /* Load CA file for verifying peer supplied certificate */ - if (0 != x509parse_crtfile(ctx->ca_chain, ca_file)) + if (0 != x509_crt_parse_file(ctx->ca_chain, ca_file)) msg (M_FATAL, "Cannot load CA certificate file %s", ca_file); } } @@ -499,16 +518,21 @@ tls_ctx_load_extra_certs (struct tls_root_ctx *ctx, const char *extra_certs_file { ASSERT(NULL != ctx); + if (!ctx->crt_chain) + { + ALLOC_OBJ_CLEAR (ctx->crt_chain, x509_crt); + } + if (!strcmp (extra_certs_file, INLINE_FILE_TAG) && extra_certs_inline) { - if (0 != x509parse_crt(ctx->crt_chain, - (const unsigned char *) extra_certs_inline, + if (0 != x509_crt_parse(ctx->crt_chain, + (const unsigned char *) extra_certs_inline, strlen(extra_certs_inline))) msg (M_FATAL, "Cannot load inline extra-certs file"); } else { - if (0 != x509parse_crtfile(ctx->crt_chain, extra_certs_file)) + if (0 != x509_crt_parse_file(ctx->crt_chain, extra_certs_file)) msg (M_FATAL, "Cannot load extra-certs file: %s", extra_certs_file); } } @@ -631,9 +655,9 @@ void tls_ctx_personalise_random(struct tls_root_ctx *ctx) if (NULL != ctx->crt_chain) { - x509_cert *cert = ctx->crt_chain; + x509_crt *cert = ctx->crt_chain; - sha2(cert->tbs.p, cert->tbs.len, sha256_hash, false); + sha256(cert->tbs.p, cert->tbs.len, sha256_hash, false); if ( 0 != memcmp(old_sha256_hash, sha256_hash, sizeof(sha256_hash))) { ctr_drbg_update(cd_ctx, sha256_hash, 32); @@ -707,24 +731,19 @@ void key_state_ssl_init(struct key_state_ssl *ks_ssl, if (ssl_ctx->allowed_ciphers) ssl_set_ciphersuites (ks_ssl->ctx, ssl_ctx->allowed_ciphers); + /* Disable record splitting (for now). OpenVPN assumes records are sent + * unfragmented, and changing that will require thorough review and + * testing. Since OpenVPN is not susceptible to BEAST, we can just + * disable record splitting as a quick fix. */ +#if defined(POLARSSL_SSL_CBC_RECORD_SPLITTING) + ssl_set_cbc_record_splitting (ks_ssl->ctx, SSL_CBC_RECORD_SPLITTING_DISABLED); +#endif /* POLARSSL_SSL_CBC_RECORD_SPLITTING */ + /* Initialise authentication information */ if (is_server) - ssl_set_dh_param_ctx (ks_ssl->ctx, ssl_ctx->dhm_ctx ); -#if defined(ENABLE_PKCS11) - if (ssl_ctx->priv_key_pkcs11 != NULL) - ssl_set_own_cert_alt( ks_ssl->ctx, ssl_ctx->crt_chain, - ssl_ctx->priv_key_pkcs11, ssl_pkcs11_decrypt, ssl_pkcs11_sign, - 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 ); + ssl_set_dh_param_ctx (ks_ssl->ctx, ssl_ctx->dhm_ctx); + + ssl_set_own_cert (ks_ssl->ctx, ssl_ctx->crt_chain, ssl_ctx->priv_key); /* Initialise SSL verification */ #if P2MP_SERVER @@ -1055,7 +1074,7 @@ key_state_read_plaintext (struct key_state_ssl *ks, struct buffer *buf, void print_details (struct key_state_ssl * ks_ssl, const char *prefix) { - const x509_cert *cert; + const x509_crt *cert; char s1[256]; char s2[256]; @@ -1068,7 +1087,7 @@ print_details (struct key_state_ssl * ks_ssl, const char *prefix) cert = ssl_get_peer_cert(ks_ssl->ctx); if (cert != NULL) { - openvpn_snprintf (s2, sizeof (s2), ", " counter_format " bit RSA", (counter_type) cert->rsa.len * 8); + openvpn_snprintf (s2, sizeof (s2), ", %zu bit key", pk_get_size(&cert->pk)); } msg (D_HANDSHAKE, "%s%s", s1, s2); diff --git a/src/openvpn/ssl_polarssl.h b/src/openvpn/ssl_polarssl.h index fc9aa78..b80a509 100644 --- a/src/openvpn/ssl_polarssl.h +++ b/src/openvpn/ssl_polarssl.h @@ -33,6 +33,7 @@ #include "syshead.h" #include <polarssl/ssl.h> +#include <polarssl/x509_crt.h> #if defined(ENABLE_PKCS11) #include <polarssl/pkcs11.h> @@ -64,9 +65,9 @@ struct tls_root_ctx { int endpoint; /**< Whether or not this is a server or a client */ dhm_context *dhm_ctx; /**< Diffie-Helmann-Merkle context */ - x509_cert *crt_chain; /**< Local Certificate chain */ - x509_cert *ca_chain; /**< CA chain for remote verification */ - rsa_context *priv_key; /**< Local private key */ + x509_crt *crt_chain; /**< Local Certificate chain */ + x509_crt *ca_chain; /**< CA chain for remote verification */ + pk_context *priv_key; /**< Local private key */ #if defined(ENABLE_PKCS11) pkcs11_context *priv_key_pkcs11; /**< PKCS11 private key */ #endif diff --git a/src/openvpn/ssl_verify.c b/src/openvpn/ssl_verify.c index 9693b81..ca69b41 100644 --- a/src/openvpn/ssl_verify.c +++ b/src/openvpn/ssl_verify.c @@ -619,7 +619,7 @@ verify_cert(struct tls_session *session, openvpn_x509_cert_t *cert, int cert_dep string_replace_leading (subject, '-', '_'); /* extract the username (default is CN) */ - if (SUCCESS != x509_get_username (common_name, sizeof(common_name), + if (SUCCESS != backend_x509_get_username (common_name, sizeof(common_name), opt->x509_username_field, cert)) { if (!cert_depth) diff --git a/src/openvpn/ssl_verify_backend.h b/src/openvpn/ssl_verify_backend.h index 6f118c9..01e453e 100644 --- a/src/openvpn/ssl_verify_backend.h +++ b/src/openvpn/ssl_verify_backend.h @@ -109,7 +109,7 @@ unsigned char *x509_get_sha1_hash (openvpn_x509_cert_t *cert, struct gc_arena *g * * @return \c FAILURE, \c or SUCCESS */ -result_t x509_get_username (char *common_name, int cn_len, +result_t backend_x509_get_username (char *common_name, int cn_len, char * x509_username_field, openvpn_x509_cert_t *peer_cert); /* diff --git a/src/openvpn/ssl_verify_openssl.c b/src/openvpn/ssl_verify_openssl.c index 309e832..4750f02 100644 --- a/src/openvpn/ssl_verify_openssl.c +++ b/src/openvpn/ssl_verify_openssl.c @@ -200,7 +200,7 @@ extract_x509_field_ssl (X509_NAME *x509, const char *field_name, char *out, } result_t -x509_get_username (char *common_name, int cn_len, +backend_x509_get_username (char *common_name, int cn_len, char * x509_username_field, X509 *peer_cert) { #ifdef ENABLE_X509ALTUSERNAME diff --git a/src/openvpn/ssl_verify_polarssl.c b/src/openvpn/ssl_verify_polarssl.c index c39fc7c..ac252a3 100644 --- a/src/openvpn/ssl_verify_polarssl.c +++ b/src/openvpn/ssl_verify_polarssl.c @@ -38,14 +38,15 @@ #if defined(ENABLE_SSL) && defined(ENABLE_CRYPTO_POLARSSL) #include "ssl_verify.h" -#include <polarssl/error.h> #include <polarssl/bignum.h> +#include <polarssl/error.h> +#include <polarssl/oid.h> #include <polarssl/sha1.h> #define MAX_SUBJECT_LENGTH 256 int -verify_callback (void *session_obj, x509_cert *cert, int cert_depth, +verify_callback (void *session_obj, x509_crt *cert, int cert_depth, int *flags) { struct tls_session *session = (struct tls_session *) session_obj; @@ -90,8 +91,8 @@ verify_callback (void *session_obj, x509_cert *cert, int cert_depth, #endif result_t -x509_get_username (char *cn, int cn_len, - char *x509_username_field, x509_cert *cert) +backend_x509_get_username (char *cn, int cn_len, + char *x509_username_field, x509_crt *cert) { x509_name *name; @@ -102,7 +103,7 @@ x509_get_username (char *cn, int cn_len, /* Find common name */ while( name != NULL ) { - if( memcmp( name->oid.p, OID_CN, OID_SIZE(OID_CN) ) == 0) + if( memcmp( name->oid.p, OID_AT_CN, OID_SIZE(OID_AT_CN) ) == 0) break; name = name->next; @@ -170,14 +171,14 @@ backend_x509_get_serial_hex (openvpn_x509_cert_t *cert, struct gc_arena *gc) buf = gc_malloc(len, true, gc); - if(x509parse_serial_gets(buf, len-1, &cert->serial) < 0) + if(x509_serial_gets(buf, len-1, &cert->serial) < 0) buf = NULL; return buf; } unsigned char * -x509_get_sha1_hash (x509_cert *cert, struct gc_arena *gc) +x509_get_sha1_hash (x509_crt *cert, struct gc_arena *gc) { unsigned char *sha1_hash = gc_malloc(SHA_DIGEST_LENGTH, false, gc); sha1(cert->tbs.p, cert->tbs.len, sha1_hash); @@ -185,14 +186,14 @@ x509_get_sha1_hash (x509_cert *cert, struct gc_arena *gc) } char * -x509_get_subject(x509_cert *cert, struct gc_arena *gc) +x509_get_subject(x509_crt *cert, struct gc_arena *gc) { char tmp_subject[MAX_SUBJECT_LENGTH] = {0}; char *subject = NULL; int ret = 0; - ret = x509parse_dn_gets( tmp_subject, MAX_SUBJECT_LENGTH-1, &cert->subject ); + ret = x509_dn_gets( tmp_subject, MAX_SUBJECT_LENGTH-1, &cert->subject ); if (ret > 0) { /* Allocate the required space for the subject */ @@ -222,70 +223,28 @@ x509_setenv (struct env_set *es, int cert_depth, openvpn_x509_cert_t *cert) while( name != NULL ) { char name_expand[64+8]; + const char *shortname; - if( name->oid.len == 2 && memcmp( name->oid.p, OID_X520, 2 ) == 0 ) + if( 0 == oid_get_attr_short_name(&name->oid, &shortname) ) { - switch( name->oid.p[2] ) - { - case X520_COMMON_NAME: - openvpn_snprintf (name_expand, sizeof(name_expand), "X509_%d_CN", - cert_depth); break; - - case X520_COUNTRY: - openvpn_snprintf (name_expand, sizeof(name_expand), "X509_%d_C", - cert_depth); break; - - case X520_LOCALITY: - openvpn_snprintf (name_expand, sizeof(name_expand), "X509_%d_L", - cert_depth); break; - - case X520_STATE: - openvpn_snprintf (name_expand, sizeof(name_expand), "X509_%d_ST", - cert_depth); break; - - case X520_ORGANIZATION: - openvpn_snprintf (name_expand, sizeof(name_expand), "X509_%d_O", - cert_depth); break; - - case X520_ORG_UNIT: - openvpn_snprintf (name_expand, sizeof(name_expand), "X509_%d_OU", - cert_depth); break; - - default: - openvpn_snprintf (name_expand, sizeof(name_expand), - "X509_%d_0x%02X", cert_depth, name->oid.p[2]); - break; - } + openvpn_snprintf (name_expand, sizeof(name_expand), "X509_%d_%s", + cert_depth, shortname); } - else if( name->oid.len == 8 && memcmp( name->oid.p, OID_PKCS9, 8 ) == 0 ) - { - switch( name->oid.p[8] ) - { - case PKCS9_EMAIL: - openvpn_snprintf (name_expand, sizeof(name_expand), - "X509_%d_emailAddress", cert_depth); break; - - default: - openvpn_snprintf (name_expand, sizeof(name_expand), - "X509_%d_0x%02X", cert_depth, name->oid.p[8]); - break; - } - } - else - { - openvpn_snprintf (name_expand, sizeof(name_expand), "X509_%d_\?\?", - cert_depth); - } - - for( i = 0; i < name->val.len; i++ ) + else + { + openvpn_snprintf (name_expand, sizeof(name_expand), "X509_%d_\?\?", + cert_depth); + } + + for( i = 0; i < name->val.len; i++ ) { - if( i >= (int) sizeof( s ) - 1 ) - break; + if( i >= (int) sizeof( s ) - 1 ) + break; - c = name->val.p[i]; - if( c < 32 || c == 127 || ( c > 128 && c < 160 ) ) - s[i] = '?'; - else s[i] = c; + c = name->val.p[i]; + if( c < 32 || c == 127 || ( c > 128 && c < 160 ) ) + s[i] = '?'; + else s[i] = c; } s[i] = '\0'; @@ -299,7 +258,7 @@ x509_setenv (struct env_set *es, int cert_depth, openvpn_x509_cert_t *cert) } result_t -x509_verify_ns_cert_type(const x509_cert *cert, const int usage) +x509_verify_ns_cert_type(const x509_crt *cert, const int usage) { if (usage == NS_CERT_CHECK_NONE) return SUCCESS; @@ -314,7 +273,7 @@ x509_verify_ns_cert_type(const x509_cert *cert, const int usage) } result_t -x509_verify_cert_ku (x509_cert *cert, const unsigned * const expected_ku, +x509_verify_cert_ku (x509_crt *cert, const unsigned * const expected_ku, int expected_len) { result_t fFound = FAILURE; @@ -347,7 +306,7 @@ x509_verify_cert_ku (x509_cert *cert, const unsigned * const expected_ku, } result_t -x509_verify_cert_eku (x509_cert *cert, const char * const expected_oid) +x509_verify_cert_eku (x509_crt *cert, const char * const expected_oid) { result_t fFound = FAILURE; @@ -366,8 +325,7 @@ x509_verify_cert_eku (x509_cert *cert, const char * const expected_oid) char oid_num_str[1024]; const char *oid_str; - oid_str = x509_oid_get_description(oid); - if (oid_str != NULL) + if (0 == oid_get_extended_key_usage( oid, &oid_str )) { msg (D_HANDSHAKE, "++ Certificate has EKU (str) %s, expects %s", oid_str, expected_oid); @@ -378,7 +336,7 @@ x509_verify_cert_eku (x509_cert *cert, const char * const expected_oid) } } - if (0 < x509_oid_get_numeric_string( oid_num_str, + if (0 < oid_get_numeric_string( oid_num_str, sizeof (oid_num_str), oid)) { msg (D_HANDSHAKE, "++ Certificate has EKU (oid) %s, expects %s", @@ -397,7 +355,7 @@ x509_verify_cert_eku (x509_cert *cert, const char * const expected_oid) } result_t -x509_write_pem(FILE *peercert_file, x509_cert *peercert) +x509_write_pem(FILE *peercert_file, x509_crt *peercert) { msg (M_WARN, "PolarSSL does not support writing peer certificate in PEM format"); return FAILURE; @@ -407,18 +365,18 @@ x509_write_pem(FILE *peercert_file, x509_cert *peercert) * check peer cert against CRL */ result_t -x509_verify_crl(const char *crl_file, x509_cert *cert, const char *subject) +x509_verify_crl(const char *crl_file, x509_crt *cert, const char *subject) { result_t retval = FAILURE; x509_crl crl = {0}; struct gc_arena gc = gc_new(); char *serial; - int polar_retval = x509parse_crlfile(&crl, crl_file); + int polar_retval = x509_crl_parse_file(&crl, crl_file); if (polar_retval != 0) { char errstr[128]; - error_strerror(polar_retval, errstr, sizeof(errstr)); + polarssl_strerror(polar_retval, errstr, sizeof(errstr)); msg (M_WARN, "CRL: cannot read CRL from file %s (%s)", crl_file, errstr); goto end; } @@ -432,7 +390,7 @@ x509_verify_crl(const char *crl_file, x509_cert *cert, const char *subject) goto end; } - if (0 != x509parse_revoked(cert, &crl)) + if (0 != x509_crt_revoked(cert, &crl)) { serial = backend_x509_get_serial_hex(cert, &gc); msg (D_HANDSHAKE, "CRL CHECK FAILED: %s (serial %s) is REVOKED", subject, (serial ? serial : "NOT AVAILABLE")); diff --git a/src/openvpn/ssl_verify_polarssl.h b/src/openvpn/ssl_verify_polarssl.h index b259081..b5157ed 100644 --- a/src/openvpn/ssl_verify_polarssl.h +++ b/src/openvpn/ssl_verify_polarssl.h @@ -33,11 +33,11 @@ #include "syshead.h" #include "misc.h" #include "manage.h" -#include <polarssl/x509.h> +#include <polarssl/x509_crt.h> #ifndef __OPENVPN_X509_CERT_T_DECLARED #define __OPENVPN_X509_CERT_T_DECLARED -typedef x509_cert openvpn_x509_cert_t; +typedef x509_crt openvpn_x509_cert_t; #endif /** @name Function for authenticating a new connection from a remote OpenVPN peer @@ -72,7 +72,7 @@ typedef x509_cert openvpn_x509_cert_t; * * @return The return value is 0 unless a fatal error occurred. */ -int verify_callback (void *session_obj, x509_cert *cert, int cert_depth, +int verify_callback (void *session_obj, x509_crt *cert, int cert_depth, int *flags); /** @} name Function for authenticating a new connection from a remote OpenVPN peer */ -- 2.5.0