53f97e1e |
/*
* OpenVPN -- An application to securely tunnel IP networks
* over a single TCP/UDP port, with support for SSL/TLS-based
* session authentication and key exchange,
* packet encryption, packet authentication, and
* packet compression.
* |
58716979 |
* Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net>
* Copyright (C) 2010-2017 Fox Crypto B.V. <openvpn@fox-it.com> |
32f07c8e |
* Copyright (C) 2006-2010, Brainspark B.V. |
53f97e1e |
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* |
caa54ac3 |
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
53f97e1e |
*/
/** |
86d8cd68 |
* @file Control Channel mbed TLS Backend |
53f97e1e |
*/
|
c110b289 |
#ifdef HAVE_CONFIG_H
#include "config.h"
#elif defined(_MSC_VER)
#include "config-msvc.h"
#endif
|
53f97e1e |
#include "syshead.h" |
31ea2ee4 |
|
86d8cd68 |
#if defined(ENABLE_CRYPTO) && defined(ENABLE_CRYPTO_MBEDTLS) |
31ea2ee4 |
|
53f97e1e |
#include "errlevel.h"
#include "ssl_backend.h" |
9048d50b |
#include "base64.h" |
53f97e1e |
#include "buffer.h"
#include "misc.h"
#include "manage.h"
#include "ssl_common.h"
|
86d8cd68 |
#include <mbedtls/havege.h> |
6efeaa2e |
|
74586c65 |
#include "ssl_verify_mbedtls.h" |
86d8cd68 |
#include <mbedtls/debug.h>
#include <mbedtls/error.h> |
c00919e8 |
#include <mbedtls/version.h>
#if MBEDTLS_VERSION_NUMBER >= 0x02040000
#include <mbedtls/net_sockets.h>
#else
#include <mbedtls/net.h>
#endif
|
86d8cd68 |
#include <mbedtls/oid.h>
#include <mbedtls/pem.h>
#include <mbedtls/sha256.h> |
53f97e1e |
|
aba75874 |
static const mbedtls_x509_crt_profile openvpn_x509_crt_profile_legacy =
{
/* Hashes from SHA-1 and above */
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) |
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_RIPEMD160 ) |
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) |
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) |
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ),
0xFFFFFFF, /* Any PK alg */
0xFFFFFFF, /* Any curve */
1024, /* RSA-1024 and larger */
};
static const mbedtls_x509_crt_profile openvpn_x509_crt_profile_preferred =
{
/* SHA-2 and above */
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) |
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) |
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ),
0xFFFFFFF, /* Any PK alg */
0xFFFFFFF, /* Any curve */
2048, /* RSA-2048 and larger */
};
#define openvpn_x509_crt_profile_suiteb mbedtls_x509_crt_profile_suiteb;
|
53f97e1e |
void |
e2a0cad4 |
tls_init_lib(void) |
53f97e1e |
{
}
void |
e2a0cad4 |
tls_free_lib(void) |
53f97e1e |
{
}
void |
e2a0cad4 |
tls_clear_error(void) |
53f97e1e |
{
}
void
tls_ctx_server_new(struct tls_root_ctx *ctx)
{ |
81d882d5 |
ASSERT(NULL != ctx);
CLEAR(*ctx); |
53f97e1e |
|
81d882d5 |
ALLOC_OBJ_CLEAR(ctx->dhm_ctx, mbedtls_dhm_context); |
53f97e1e |
|
81d882d5 |
ALLOC_OBJ_CLEAR(ctx->ca_chain, mbedtls_x509_crt); |
53f97e1e |
|
81d882d5 |
ctx->endpoint = MBEDTLS_SSL_IS_SERVER;
ctx->initialised = true; |
53f97e1e |
}
void
tls_ctx_client_new(struct tls_root_ctx *ctx)
{ |
81d882d5 |
ASSERT(NULL != ctx);
CLEAR(*ctx); |
53f97e1e |
|
81d882d5 |
ALLOC_OBJ_CLEAR(ctx->dhm_ctx, mbedtls_dhm_context);
ALLOC_OBJ_CLEAR(ctx->ca_chain, mbedtls_x509_crt); |
53f97e1e |
|
81d882d5 |
ctx->endpoint = MBEDTLS_SSL_IS_CLIENT;
ctx->initialised = true; |
53f97e1e |
}
void
tls_ctx_free(struct tls_root_ctx *ctx)
{ |
81d882d5 |
if (ctx) |
53f97e1e |
{ |
81d882d5 |
mbedtls_pk_free(ctx->priv_key);
if (ctx->priv_key)
{
free(ctx->priv_key);
}
mbedtls_x509_crt_free(ctx->ca_chain);
if (ctx->ca_chain)
{
free(ctx->ca_chain);
}
mbedtls_x509_crt_free(ctx->crt_chain);
if (ctx->crt_chain)
{
free(ctx->crt_chain);
}
mbedtls_dhm_free(ctx->dhm_ctx);
if (ctx->dhm_ctx)
{
free(ctx->dhm_ctx);
}
mbedtls_x509_crl_free(ctx->crl);
if (ctx->crl)
{
free(ctx->crl);
} |
160504a2 |
|
53f97e1e |
#if defined(ENABLE_PKCS11) |
81d882d5 |
if (ctx->priv_key_pkcs11 != NULL)
{
mbedtls_pkcs11_priv_key_free(ctx->priv_key_pkcs11);
free(ctx->priv_key_pkcs11);
} |
53f97e1e |
#endif |
38ace48c |
#if defined(MANAGMENT_EXTERNAL_KEY) |
81d882d5 |
if (ctx->external_key != NULL)
{
free(ctx->external_key);
} |
38ace48c |
#endif |
53f97e1e |
|
81d882d5 |
if (ctx->allowed_ciphers)
{
free(ctx->allowed_ciphers);
} |
53f97e1e |
|
81d882d5 |
CLEAR(*ctx); |
53f97e1e |
|
81d882d5 |
ctx->initialised = false; |
53f97e1e |
}
}
bool
tls_ctx_initialised(struct tls_root_ctx *ctx)
{ |
81d882d5 |
ASSERT(NULL != ctx);
return ctx->initialised; |
53f97e1e |
}
void |
685e486e |
key_state_export_keying_material(struct key_state_ssl *ssl,
struct tls_session *session)
{
}
void |
81d882d5 |
tls_ctx_set_options(struct tls_root_ctx *ctx, unsigned int ssl_flags) |
53f97e1e |
{
}
|
3b23b18d |
static const char * |
4cd4899e |
tls_translate_cipher_name(const char *cipher_name)
{ |
81d882d5 |
const tls_cipher_name_pair *pair = tls_get_cipher_name_pair(cipher_name, strlen(cipher_name)); |
3b23b18d |
|
81d882d5 |
if (NULL == pair) |
3b23b18d |
{ |
81d882d5 |
/* No translation found, return original */
return cipher_name; |
3b23b18d |
}
|
81d882d5 |
if (0 != strcmp(cipher_name, pair->iana_name)) |
3b23b18d |
{ |
81d882d5 |
/* Deprecated name found, notify user */
msg(M_WARN, "Deprecated cipher suite name '%s', please use IANA name '%s'", pair->openssl_name, pair->iana_name); |
3b23b18d |
}
|
81d882d5 |
return pair->iana_name; |
3b23b18d |
}
|
53f97e1e |
void
tls_ctx_restrict_ciphers(struct tls_root_ctx *ctx, const char *ciphers)
{ |
81d882d5 |
char *tmp_ciphers, *tmp_ciphers_orig, *token;
int i, cipher_count;
int ciphers_len; |
e83313a8 |
|
81d882d5 |
if (NULL == ciphers)
{
return; /* Nothing to do */ |
e83313a8 |
|
81d882d5 |
}
ciphers_len = strlen(ciphers); |
53f97e1e |
|
81d882d5 |
ASSERT(NULL != ctx);
ASSERT(0 != ciphers_len); |
53f97e1e |
|
81d882d5 |
/* Get number of ciphers */
for (i = 0, cipher_count = 1; i < ciphers_len; i++) |
4cd4899e |
{ |
81d882d5 |
if (ciphers[i] == ':')
{
cipher_count++;
} |
4cd4899e |
} |
53f97e1e |
|
81d882d5 |
/* Allocate an array for them */
ALLOC_ARRAY_CLEAR(ctx->allowed_ciphers, int, cipher_count+1) |
53f97e1e |
|
81d882d5 |
/* Parse allowed ciphers, getting IDs */
i = 0;
tmp_ciphers_orig = tmp_ciphers = string_alloc(ciphers, NULL); |
1d90851e |
|
81d882d5 |
token = strtok(tmp_ciphers, ":");
while (token) |
1d90851e |
{ |
81d882d5 |
ctx->allowed_ciphers[i] = mbedtls_ssl_get_ciphersuite_id(
tls_translate_cipher_name(token));
if (0 != ctx->allowed_ciphers[i])
{
i++;
}
token = strtok(NULL, ":"); |
1d90851e |
} |
81d882d5 |
free(tmp_ciphers_orig); |
53f97e1e |
}
void |
aba75874 |
tls_ctx_set_cert_profile(struct tls_root_ctx *ctx, const char *profile)
{
if (!profile || 0 == strcmp(profile, "legacy"))
{
ctx->cert_profile = openvpn_x509_crt_profile_legacy;
}
else if (0 == strcmp(profile, "preferred"))
{
ctx->cert_profile = openvpn_x509_crt_profile_preferred;
}
else if (0 == strcmp(profile, "suiteb"))
{
ctx->cert_profile = openvpn_x509_crt_profile_suiteb;
}
else
{
msg (M_FATAL, "ERROR: Invalid cert profile: %s", profile);
}
}
void |
81d882d5 |
tls_ctx_check_cert_time(const struct tls_root_ctx *ctx) |
091edd8e |
{ |
81d882d5 |
ASSERT(ctx);
if (ctx->crt_chain == NULL) |
868d9d01 |
{ |
81d882d5 |
return; /* Nothing to check if there is no certificate */ |
868d9d01 |
}
|
81d882d5 |
if (mbedtls_x509_time_is_future(&ctx->crt_chain->valid_from)) |
091edd8e |
{ |
81d882d5 |
msg(M_WARN, "WARNING: Your certificate is not yet valid!"); |
091edd8e |
}
|
81d882d5 |
if (mbedtls_x509_time_is_past(&ctx->crt_chain->valid_to)) |
091edd8e |
{ |
81d882d5 |
msg(M_WARN, "WARNING: Your certificate has expired!"); |
091edd8e |
}
}
void |
81d882d5 |
tls_ctx_load_dh_params(struct tls_root_ctx *ctx, const char *dh_file,
const char *dh_inline
) |
53f97e1e |
{ |
81d882d5 |
if (!strcmp(dh_file, INLINE_FILE_TAG) && dh_inline)
{
if (!mbed_ok(mbedtls_dhm_parse_dhm(ctx->dhm_ctx,
(const unsigned char *) dh_inline, strlen(dh_inline)+1)))
{
msg(M_FATAL, "Cannot read inline DH parameters");
}
}
else
{
if (!mbed_ok(mbedtls_dhm_parse_dhmfile(ctx->dhm_ctx, dh_file)))
{
msg(M_FATAL, "Cannot read DH parameters from file %s", dh_file);
}
}
msg(D_TLS_DEBUG_LOW, "Diffie-Hellman initialized with " counter_format " bit key",
(counter_type) 8 * mbedtls_mpi_size(&ctx->dhm_ctx->P)); |
53f97e1e |
}
|
609e8131 |
void |
81d882d5 |
tls_ctx_load_ecdh_params(struct tls_root_ctx *ctx, const char *curve_name
) |
609e8131 |
{
if (NULL != curve_name) |
81d882d5 |
{
msg(M_WARN, "WARNING: mbed TLS builds do not support specifying an ECDH "
"curve, using default curves.");
} |
609e8131 |
}
|
53f97e1e |
int
tls_ctx_load_pkcs12(struct tls_root_ctx *ctx, const char *pkcs12_file, |
81d882d5 |
const char *pkcs12_file_inline,
bool load_ca_file
) |
53f97e1e |
{ |
81d882d5 |
msg(M_FATAL, "PKCS #12 files not yet supported for mbed TLS.");
return 0; |
53f97e1e |
}
|
93c22ecc |
#ifdef ENABLE_CRYPTOAPI |
53f97e1e |
void
tls_ctx_load_cryptoapi(struct tls_root_ctx *ctx, const char *cryptoapi_cert)
{ |
81d882d5 |
msg(M_FATAL, "Windows CryptoAPI not yet supported for mbed TLS."); |
53f97e1e |
} |
445b192a |
#endif /* _WIN32 */ |
53f97e1e |
void |
81d882d5 |
tls_ctx_load_cert_file(struct tls_root_ctx *ctx, const char *cert_file,
const char *cert_inline
) |
53f97e1e |
{ |
81d882d5 |
ASSERT(NULL != ctx); |
53f97e1e |
|
81d882d5 |
if (!ctx->crt_chain) |
444a93ea |
{ |
81d882d5 |
ALLOC_OBJ_CLEAR(ctx->crt_chain, mbedtls_x509_crt); |
444a93ea |
}
|
81d882d5 |
if (!strcmp(cert_file, INLINE_FILE_TAG) && cert_inline) |
53f97e1e |
{ |
81d882d5 |
if (!mbed_ok(mbedtls_x509_crt_parse(ctx->crt_chain,
(const unsigned char *) cert_inline, strlen(cert_inline)+1)))
{
msg(M_FATAL, "Cannot load inline certificate file");
} |
53f97e1e |
} |
81d882d5 |
else |
53f97e1e |
{ |
81d882d5 |
if (!mbed_ok(mbedtls_x509_crt_parse_file(ctx->crt_chain, cert_file)))
{
msg(M_FATAL, "Cannot load certificate file %s", cert_file);
} |
53f97e1e |
} |
47712706 |
}
|
53f97e1e |
int |
81d882d5 |
tls_ctx_load_priv_file(struct tls_root_ctx *ctx, const char *priv_key_file,
const char *priv_key_inline
) |
53f97e1e |
{ |
81d882d5 |
int status;
ASSERT(NULL != ctx); |
53f97e1e |
|
81d882d5 |
if (!ctx->priv_key) |
444a93ea |
{ |
81d882d5 |
ALLOC_OBJ_CLEAR(ctx->priv_key, mbedtls_pk_context); |
444a93ea |
}
|
81d882d5 |
if (!strcmp(priv_key_file, INLINE_FILE_TAG) && priv_key_inline) |
53f97e1e |
{ |
81d882d5 |
status = mbedtls_pk_parse_key(ctx->priv_key,
(const unsigned char *) priv_key_inline, strlen(priv_key_inline)+1,
NULL, 0);
if (MBEDTLS_ERR_PK_PASSWORD_REQUIRED == status)
{
char passbuf[512] = {0};
pem_password_callback(passbuf, 512, 0, NULL);
status = mbedtls_pk_parse_key(ctx->priv_key,
(const unsigned char *) priv_key_inline,
strlen(priv_key_inline)+1, (unsigned char *) passbuf,
strlen(passbuf));
} |
53f97e1e |
} |
81d882d5 |
else |
53f97e1e |
{ |
81d882d5 |
status = mbedtls_pk_parse_keyfile(ctx->priv_key, priv_key_file, NULL);
if (MBEDTLS_ERR_PK_PASSWORD_REQUIRED == status)
{
char passbuf[512] = {0};
pem_password_callback(passbuf, 512, 0, NULL);
status = mbedtls_pk_parse_keyfile(ctx->priv_key, priv_key_file, passbuf);
} |
53f97e1e |
} |
81d882d5 |
if (!mbed_ok(status)) |
53f97e1e |
{
#ifdef ENABLE_MANAGEMENT |
81d882d5 |
if (management && (MBEDTLS_ERR_PK_PASSWORD_MISMATCH == status))
{
management_auth_failure(management, UP_TYPE_PRIVATE_KEY, NULL);
} |
53f97e1e |
#endif |
81d882d5 |
msg(M_WARN, "Cannot load private key file %s", priv_key_file);
return 1; |
53f97e1e |
}
|
81d882d5 |
if (!mbed_ok(mbedtls_pk_check_pair(&ctx->crt_chain->pk, ctx->priv_key))) |
5c4acf3f |
{ |
81d882d5 |
msg(M_WARN, "Private key does not match the certificate");
return 1; |
5c4acf3f |
}
|
81d882d5 |
return 0; |
53f97e1e |
}
#ifdef MANAGMENT_EXTERNAL_KEY
|
38ace48c |
struct external_context { |
81d882d5 |
size_t signature_length; |
38ace48c |
};
|
03df3a99 |
/** |
86d8cd68 |
* external_pkcs1_sign implements a mbed TLS rsa_sign_func callback, that uses |
03df3a99 |
* 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 |
86d8cd68 |
* if md_alg != MBEDTLS_MD_NONE). |
03df3a99 |
* @param hash The digest ('hash') to sign. Should have a size |
86d8cd68 |
* matching the length of md_alg (if != MBEDTLS_MD_NONE), |
03df3a99 |
* or hashlen otherwise.
* @param sig Buffer that returns the signature. Should be at least of
* size ctx->signature_length.
* |
86d8cd68 |
* @return 0 on success, non-zero mbed TLS error code on failure. |
03df3a99 |
*/ |
81d882d5 |
static inline int
external_pkcs1_sign( void *ctx_voidptr,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int mode,
mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash,
unsigned char *sig ) |
38ace48c |
{ |
81d882d5 |
struct external_context *const ctx = ctx_voidptr;
char *in_b64 = NULL;
char *out_b64 = NULL;
int rv;
unsigned char *p = sig;
size_t asn_len = 0, oid_size = 0, sig_len = 0;
const char *oid = NULL;
if (NULL == ctx) |
03df3a99 |
{ |
81d882d5 |
return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
} |
03df3a99 |
|
81d882d5 |
if (MBEDTLS_RSA_PRIVATE != mode)
{
return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; |
03df3a99 |
}
|
81d882d5 |
/*
* 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 mbed TLS pkcs11_sign(), under the GPLv2.0+.
*/
if (md_alg != MBEDTLS_MD_NONE)
{
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg );
if (md_info == NULL)
{
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
}
if (!mbed_ok(mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size )))
{
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
}
hashlen = mbedtls_md_get_size( md_info );
asn_len = 10 + oid_size;
} |
03df3a99 |
|
81d882d5 |
sig_len = ctx->signature_length;
if ( (SIZE_MAX - hashlen) < asn_len || (hashlen + asn_len) > sig_len) |
03df3a99 |
{ |
81d882d5 |
return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
} |
03df3a99 |
|
81d882d5 |
if (md_alg != MBEDTLS_MD_NONE)
{
/*
* DigestInfo ::= SEQUENCE {
* digestAlgorithm DigestAlgorithmIdentifier,
* digest Digest }
*
* DigestAlgorithmIdentifier ::= AlgorithmIdentifier
*
* Digest ::= OCTET STRING
*/
*p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED;
*p++ = (unsigned char) ( 0x08 + oid_size + hashlen );
*p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED;
*p++ = (unsigned char) ( 0x04 + oid_size );
*p++ = MBEDTLS_ASN1_OID;
*p++ = oid_size & 0xFF;
memcpy( p, oid, oid_size );
p += oid_size;
*p++ = MBEDTLS_ASN1_NULL;
*p++ = 0x00;
*p++ = MBEDTLS_ASN1_OCTET_STRING;
*p++ = hashlen;
/* Determine added ASN length */
asn_len = p - sig;
} |
32f07c8e |
|
81d882d5 |
/* Copy the hash to be signed */
memcpy( p, hash, hashlen ); |
03df3a99 |
|
81d882d5 |
/* convert 'from' to base64 */
if (openvpn_base64_encode(sig, asn_len + hashlen, &in_b64) <= 0) |
38ace48c |
{ |
81d882d5 |
rv = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
goto done; |
38ace48c |
}
|
81d882d5 |
/* call MI for signature */
if (management) |
38ace48c |
{ |
81d882d5 |
out_b64 = management_query_rsa_sig(management, in_b64);
}
if (!out_b64)
{
rv = MBEDTLS_ERR_RSA_PRIVATE_FAILED;
goto done; |
38ace48c |
}
|
81d882d5 |
/* decode base64 signature to binary and verify length */
if (openvpn_base64_decode(out_b64, sig, ctx->signature_length) !=
ctx->signature_length) |
38ace48c |
{ |
81d882d5 |
rv = MBEDTLS_ERR_RSA_PRIVATE_FAILED;
goto done; |
38ace48c |
}
|
81d882d5 |
rv = 0; |
38ace48c |
|
03df3a99 |
done: |
81d882d5 |
if (in_b64)
{
free(in_b64);
}
if (out_b64)
{
free(out_b64);
}
return rv; |
53f97e1e |
}
|
81d882d5 |
static inline size_t
external_key_len(void *vctx) |
38ace48c |
{ |
81d882d5 |
struct external_context *const ctx = vctx; |
38ace48c |
|
81d882d5 |
return ctx->signature_length; |
38ace48c |
} |
67a67e39 |
int |
81d882d5 |
tls_ctx_use_external_private_key(struct tls_root_ctx *ctx,
const char *cert_file, const char *cert_file_inline) |
67a67e39 |
{ |
81d882d5 |
ASSERT(NULL != ctx); |
67a67e39 |
|
81d882d5 |
tls_ctx_load_cert_file(ctx, cert_file, cert_file_inline); |
67a67e39 |
|
81d882d5 |
if (ctx->crt_chain == NULL)
{
return 0;
} |
67a67e39 |
|
81d882d5 |
ALLOC_OBJ_CLEAR(ctx->external_key, struct external_context);
ctx->external_key->signature_length = mbedtls_pk_get_len(&ctx->crt_chain->pk); |
67a67e39 |
|
81d882d5 |
ALLOC_OBJ_CLEAR(ctx->priv_key, mbedtls_pk_context);
if (!mbed_ok(mbedtls_pk_setup_rsa_alt(ctx->priv_key, ctx->external_key,
NULL, external_pkcs1_sign, external_key_len)))
{
return 0;
} |
67a67e39 |
|
81d882d5 |
return 1; |
67a67e39 |
} |
81d882d5 |
#endif /* ifdef MANAGMENT_EXTERNAL_KEY */ |
53f97e1e |
|
81d882d5 |
void
tls_ctx_load_ca(struct tls_root_ctx *ctx, const char *ca_file,
const char *ca_inline, const char *ca_path, bool tls_server
) |
53f97e1e |
{ |
81d882d5 |
if (ca_path)
{
msg(M_FATAL, "ERROR: mbed TLS cannot handle the capath directive");
} |
53f97e1e |
|
81d882d5 |
if (ca_file && !strcmp(ca_file, INLINE_FILE_TAG) && ca_inline) |
53f97e1e |
{ |
81d882d5 |
if (!mbed_ok(mbedtls_x509_crt_parse(ctx->ca_chain,
(const unsigned char *) ca_inline, strlen(ca_inline)+1)))
{
msg(M_FATAL, "Cannot load inline CA certificates");
} |
53f97e1e |
} |
81d882d5 |
else |
53f97e1e |
{ |
81d882d5 |
/* Load CA file for verifying peer supplied certificate */
if (!mbed_ok(mbedtls_x509_crt_parse_file(ctx->ca_chain, ca_file)))
{
msg(M_FATAL, "Cannot load CA certificate file %s", ca_file);
} |
53f97e1e |
}
}
void |
81d882d5 |
tls_ctx_load_extra_certs(struct tls_root_ctx *ctx, const char *extra_certs_file,
const char *extra_certs_inline
) |
53f97e1e |
{ |
81d882d5 |
ASSERT(NULL != ctx); |
53f97e1e |
|
81d882d5 |
if (!ctx->crt_chain) |
444a93ea |
{ |
81d882d5 |
ALLOC_OBJ_CLEAR(ctx->crt_chain, mbedtls_x509_crt); |
444a93ea |
}
|
81d882d5 |
if (!strcmp(extra_certs_file, INLINE_FILE_TAG) && extra_certs_inline) |
53f97e1e |
{ |
81d882d5 |
if (!mbed_ok(mbedtls_x509_crt_parse(ctx->crt_chain,
(const unsigned char *) extra_certs_inline,
strlen(extra_certs_inline)+1)))
{
msg(M_FATAL, "Cannot load inline extra-certs file");
} |
53f97e1e |
} |
81d882d5 |
else |
53f97e1e |
{ |
81d882d5 |
if (!mbed_ok(mbedtls_x509_crt_parse_file(ctx->crt_chain, extra_certs_file)))
{
msg(M_FATAL, "Cannot load extra-certs file: %s", extra_certs_file);
} |
53f97e1e |
}
}
/* **************************************
*
* Key-state specific functions
*
***************************************/
/*
* "Endless buffer"
*/
|
81d882d5 |
static inline void
buf_free_entry(buffer_entry *entry) |
53f97e1e |
{ |
81d882d5 |
if (NULL != entry) |
53f97e1e |
{ |
81d882d5 |
free(entry->data);
free(entry); |
53f97e1e |
}
}
|
81d882d5 |
static void
buf_free_entries(endless_buffer *buf) |
53f97e1e |
{ |
81d882d5 |
while (buf->first_block) |
53f97e1e |
{ |
81d882d5 |
buffer_entry *cur_block = buf->first_block;
buf->first_block = cur_block->next_block;
buf_free_entry(cur_block); |
53f97e1e |
} |
81d882d5 |
buf->last_block = NULL; |
53f97e1e |
}
|
81d882d5 |
static int
endless_buf_read( endless_buffer *in, unsigned char *out, size_t out_len ) |
53f97e1e |
{ |
81d882d5 |
size_t read_len = 0; |
53f97e1e |
|
81d882d5 |
if (in->first_block == NULL) |
53f97e1e |
{ |
81d882d5 |
return MBEDTLS_ERR_SSL_WANT_READ;
} |
53f97e1e |
|
81d882d5 |
while (in->first_block != NULL && read_len < out_len)
{
int block_len = in->first_block->length - in->data_start;
if (block_len <= out_len - read_len)
{
buffer_entry *cur_entry = in->first_block;
memcpy(out + read_len, cur_entry->data + in->data_start,
block_len);
read_len += block_len;
in->first_block = cur_entry->next_block;
in->data_start = 0;
if (in->first_block == NULL)
{
in->last_block = NULL;
}
buf_free_entry(cur_entry);
}
else
{
memcpy(out + read_len, in->first_block->data + in->data_start,
out_len - read_len);
in->data_start += out_len - read_len;
read_len = out_len;
} |
53f97e1e |
}
|
81d882d5 |
return read_len; |
53f97e1e |
}
|
81d882d5 |
static int
endless_buf_write( endless_buffer *out, const unsigned char *in, size_t len ) |
53f97e1e |
{ |
81d882d5 |
buffer_entry *new_block = malloc(sizeof(buffer_entry));
if (NULL == new_block)
{
return MBEDTLS_ERR_NET_SEND_FAILED;
} |
53f97e1e |
|
81d882d5 |
new_block->data = malloc(len);
if (NULL == new_block->data) |
53f97e1e |
{ |
81d882d5 |
free(new_block);
return MBEDTLS_ERR_NET_SEND_FAILED; |
53f97e1e |
}
|
81d882d5 |
new_block->length = len;
new_block->next_block = NULL; |
53f97e1e |
|
81d882d5 |
memcpy(new_block->data, in, len); |
53f97e1e |
|
81d882d5 |
if (NULL == out->first_block)
{
out->first_block = new_block;
} |
53f97e1e |
|
81d882d5 |
if (NULL != out->last_block)
{
out->last_block->next_block = new_block;
} |
53f97e1e |
|
81d882d5 |
out->last_block = new_block; |
53f97e1e |
|
81d882d5 |
return len; |
53f97e1e |
}
|
81d882d5 |
static int
ssl_bio_read( void *ctx, unsigned char *out, size_t out_len) |
86d8cd68 |
{ |
81d882d5 |
bio_ctx *my_ctx = (bio_ctx *) ctx;
return endless_buf_read(&my_ctx->in, out, out_len); |
86d8cd68 |
}
|
81d882d5 |
static int
ssl_bio_write( void *ctx, const unsigned char *in, size_t in_len) |
86d8cd68 |
{ |
81d882d5 |
bio_ctx *my_ctx = (bio_ctx *) ctx;
return endless_buf_write(&my_ctx->out, in, in_len); |
86d8cd68 |
}
|
81d882d5 |
static void
my_debug( void *ctx, int level, const char *file, int line,
const char *str ) |
53f97e1e |
{ |
81d882d5 |
int my_loglevel = (level < 3) ? D_TLS_DEBUG_MED : D_TLS_DEBUG;
msg(my_loglevel, "mbed TLS msg (%s:%d): %s", file, line, str); |
53f97e1e |
}
|
6efeaa2e |
/*
* Further personalise the RNG using a hash of the public key
*/ |
81d882d5 |
void
tls_ctx_personalise_random(struct tls_root_ctx *ctx) |
6efeaa2e |
{ |
81d882d5 |
static char old_sha256_hash[32] = {0};
unsigned char sha256_hash[32] = {0};
mbedtls_ctr_drbg_context *cd_ctx = rand_ctx_get(); |
6efeaa2e |
|
81d882d5 |
if (NULL != ctx->crt_chain) |
6efeaa2e |
{ |
81d882d5 |
mbedtls_x509_crt *cert = ctx->crt_chain;
mbedtls_sha256(cert->tbs.p, cert->tbs.len, sha256_hash, false);
if (0 != memcmp(old_sha256_hash, sha256_hash, sizeof(sha256_hash)))
{
mbedtls_ctr_drbg_update(cd_ctx, sha256_hash, 32);
memcpy(old_sha256_hash, sha256_hash, sizeof(old_sha256_hash));
} |
6efeaa2e |
}
}
|
4b67f984 |
int
tls_version_max(void)
{ |
8215b7a8 |
#if defined(MBEDTLS_SSL_MAJOR_VERSION_3) && defined(MBEDTLS_SSL_MINOR_VERSION_3) |
81d882d5 |
return TLS_VER_1_2; |
8215b7a8 |
#elif defined(MBEDTLS_SSL_MAJOR_VERSION_3) && defined(MBEDTLS_SSL_MINOR_VERSION_2) |
81d882d5 |
return TLS_VER_1_1; |
4b67f984 |
#else |
81d882d5 |
return TLS_VER_1_0; |
4b67f984 |
#endif
}
|
6cb15b90 |
/** |
86d8cd68 |
* Convert an OpenVPN tls-version variable to mbed TLS format (i.e. a major and |
6cb15b90 |
* minor ssl version number).
* |
81d882d5 |
* @param tls_ver The tls-version variable to convert.
* @param major Returns the TLS major version in mbed TLS format.
* Must be a valid pointer.
* @param minor Returns the TLS minor version in mbed TLS format.
* Must be a valid pointer. |
6cb15b90 |
*/ |
81d882d5 |
static void |
4cd4899e |
tls_version_to_major_minor(int tls_ver, int *major, int *minor)
{ |
81d882d5 |
ASSERT(major);
ASSERT(minor);
switch (tls_ver)
{
case TLS_VER_1_0:
*major = MBEDTLS_SSL_MAJOR_VERSION_3;
*minor = MBEDTLS_SSL_MINOR_VERSION_1;
break;
case TLS_VER_1_1:
*major = MBEDTLS_SSL_MAJOR_VERSION_3;
*minor = MBEDTLS_SSL_MINOR_VERSION_2;
break;
case TLS_VER_1_2:
*major = MBEDTLS_SSL_MAJOR_VERSION_3;
*minor = MBEDTLS_SSL_MINOR_VERSION_3;
break;
default:
msg(M_FATAL, "%s: invalid TLS version %d", __func__, tls_ver);
break;
} |
6cb15b90 |
}
|
160504a2 |
void |
ce91c187 |
backend_tls_ctx_reload_crl(struct tls_root_ctx *ctx, const char *crl_file, |
81d882d5 |
const char *crl_inline) |
160504a2 |
{ |
81d882d5 |
ASSERT(crl_file); |
160504a2 |
|
81d882d5 |
if (ctx->crl == NULL) |
160504a2 |
{ |
81d882d5 |
ALLOC_OBJ_CLEAR(ctx->crl, mbedtls_x509_crl); |
160504a2 |
} |
81d882d5 |
mbedtls_x509_crl_free(ctx->crl); |
160504a2 |
|
81d882d5 |
if (!strcmp(crl_file, INLINE_FILE_TAG) && crl_inline) |
160504a2 |
{ |
81d882d5 |
if (!mbed_ok(mbedtls_x509_crl_parse(ctx->crl,
(const unsigned char *)crl_inline, strlen(crl_inline)+1)))
{
msg(M_WARN, "CRL: cannot parse inline CRL");
goto err;
} |
160504a2 |
} |
81d882d5 |
else |
160504a2 |
{ |
81d882d5 |
if (!mbed_ok(mbedtls_x509_crl_parse_file(ctx->crl, crl_file)))
{
msg(M_WARN, "CRL: cannot read CRL from file %s", crl_file);
goto err;
} |
160504a2 |
} |
81d882d5 |
return; |
160504a2 |
err: |
81d882d5 |
mbedtls_x509_crl_free(ctx->crl); |
160504a2 |
}
|
81d882d5 |
void
key_state_ssl_init(struct key_state_ssl *ks_ssl,
const struct tls_root_ctx *ssl_ctx, bool is_server, struct tls_session *session) |
53f97e1e |
{ |
81d882d5 |
ASSERT(NULL != ssl_ctx);
ASSERT(ks_ssl);
CLEAR(*ks_ssl);
/* Initialise SSL config */
mbedtls_ssl_config_init(&ks_ssl->ssl_config);
mbedtls_ssl_config_defaults(&ks_ssl->ssl_config, ssl_ctx->endpoint,
MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); |
b63f9863 |
#ifdef MBEDTLS_DEBUG_C |
81d882d5 |
mbedtls_debug_set_threshold(3); |
b63f9863 |
#endif |
81d882d5 |
mbedtls_ssl_conf_dbg(&ks_ssl->ssl_config, my_debug, NULL);
mbedtls_ssl_conf_rng(&ks_ssl->ssl_config, mbedtls_ctr_drbg_random,
rand_ctx_get()); |
86d8cd68 |
|
aba75874 |
mbedtls_ssl_conf_cert_profile(&ks_ssl->ssl_config, &ssl_ctx->cert_profile);
|
81d882d5 |
if (ssl_ctx->allowed_ciphers)
{
mbedtls_ssl_conf_ciphersuites(&ks_ssl->ssl_config, ssl_ctx->allowed_ciphers);
} |
86d8cd68 |
|
81d882d5 |
/* 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. */ |
86d8cd68 |
#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) |
81d882d5 |
mbedtls_ssl_conf_cbc_record_splitting(&ks_ssl->ssl_config,
MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED); |
86d8cd68 |
#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */
|
81d882d5 |
/* Initialise authentication information */
if (is_server)
{
mbed_ok(mbedtls_ssl_conf_dh_param_ctx(&ks_ssl->ssl_config,
ssl_ctx->dhm_ctx));
} |
86d8cd68 |
|
81d882d5 |
mbed_ok(mbedtls_ssl_conf_own_cert(&ks_ssl->ssl_config, ssl_ctx->crt_chain,
ssl_ctx->priv_key)); |
86d8cd68 |
|
81d882d5 |
/* Initialise SSL verification */ |
86d8cd68 |
#if P2MP_SERVER |
81d882d5 |
if (session->opt->ssl_flags & SSLF_CLIENT_CERT_OPTIONAL) |
53f97e1e |
{ |
81d882d5 |
mbedtls_ssl_conf_authmode(&ks_ssl->ssl_config, MBEDTLS_SSL_VERIFY_OPTIONAL); |
86d8cd68 |
} |
81d882d5 |
else if (!(session->opt->ssl_flags & SSLF_CLIENT_CERT_NOT_REQUIRED)) |
86d8cd68 |
#endif |
81d882d5 |
{
mbedtls_ssl_conf_authmode(&ks_ssl->ssl_config, MBEDTLS_SSL_VERIFY_REQUIRED);
}
mbedtls_ssl_conf_verify(&ks_ssl->ssl_config, verify_callback, session);
/* TODO: mbed TLS does not currently support sending the CA chain to the client */
mbedtls_ssl_conf_ca_chain(&ks_ssl->ssl_config, ssl_ctx->ca_chain, ssl_ctx->crl);
/* Initialize minimum TLS version */
{
const int tls_version_min =
(session->opt->ssl_flags >> SSLF_TLS_VERSION_MIN_SHIFT)
&SSLF_TLS_VERSION_MIN_MASK;
/* default to TLS 1.0 */
int major = MBEDTLS_SSL_MAJOR_VERSION_3;
int minor = MBEDTLS_SSL_MINOR_VERSION_1;
if (tls_version_min > TLS_VER_UNSPEC)
{
tls_version_to_major_minor(tls_version_min, &major, &minor);
}
mbedtls_ssl_conf_min_version(&ks_ssl->ssl_config, major, minor);
}
/* Initialize maximum TLS version */
{
const int tls_version_max =
(session->opt->ssl_flags >> SSLF_TLS_VERSION_MAX_SHIFT)
&SSLF_TLS_VERSION_MAX_MASK;
if (tls_version_max > TLS_VER_UNSPEC)
{
int major, minor;
tls_version_to_major_minor(tls_version_max, &major, &minor);
mbedtls_ssl_conf_max_version(&ks_ssl->ssl_config, major, minor);
}
}
/* Initialise SSL context */
ALLOC_OBJ_CLEAR(ks_ssl->ctx, mbedtls_ssl_context);
mbedtls_ssl_init(ks_ssl->ctx);
mbedtls_ssl_setup(ks_ssl->ctx, &ks_ssl->ssl_config);
/* Initialise BIOs */
CLEAR(ks_ssl->bio_ctx);
mbedtls_ssl_set_bio(ks_ssl->ctx, &ks_ssl->bio_ctx, ssl_bio_write,
ssl_bio_read, NULL); |
53f97e1e |
}
void
key_state_ssl_free(struct key_state_ssl *ks_ssl)
{ |
81d882d5 |
if (ks_ssl)
{
if (ks_ssl->ctx)
{
mbedtls_ssl_free(ks_ssl->ctx);
free(ks_ssl->ctx);
}
mbedtls_ssl_config_free(&ks_ssl->ssl_config);
buf_free_entries(&ks_ssl->bio_ctx.in);
buf_free_entries(&ks_ssl->bio_ctx.out);
CLEAR(*ks_ssl);
} |
53f97e1e |
}
int |
81d882d5 |
key_state_write_plaintext(struct key_state_ssl *ks, struct buffer *buf) |
53f97e1e |
{ |
81d882d5 |
int retval = 0; |
53f97e1e |
|
81d882d5 |
ASSERT(buf); |
53f97e1e |
|
81d882d5 |
retval = key_state_write_plaintext_const(ks, BPTR(buf), BLEN(buf)); |
53f97e1e |
|
81d882d5 |
if (1 == retval) |
53f97e1e |
{ |
81d882d5 |
memset(BPTR(buf), 0, BLEN(buf)); /* erase data just written */
buf->len = 0; |
53f97e1e |
}
|
81d882d5 |
return retval; |
53f97e1e |
}
int |
81d882d5 |
key_state_write_plaintext_const(struct key_state_ssl *ks, const uint8_t *data, int len) |
53f97e1e |
{ |
81d882d5 |
int retval = 0;
perf_push(PERF_BIO_WRITE_PLAINTEXT); |
53f97e1e |
|
81d882d5 |
ASSERT(NULL != ks);
ASSERT(len >= 0); |
53f97e1e |
|
81d882d5 |
if (0 == len) |
53f97e1e |
{ |
81d882d5 |
perf_pop();
return 0; |
53f97e1e |
}
|
81d882d5 |
ASSERT(data); |
53f97e1e |
|
81d882d5 |
retval = mbedtls_ssl_write(ks->ctx, data, len); |
53f97e1e |
|
81d882d5 |
if (retval < 0) |
53f97e1e |
{ |
81d882d5 |
perf_pop();
if (MBEDTLS_ERR_SSL_WANT_WRITE == retval || MBEDTLS_ERR_SSL_WANT_READ == retval)
{
return 0;
}
mbed_log_err(D_TLS_ERRORS, retval,
"TLS ERROR: write tls_write_plaintext_const error");
return -1; |
53f97e1e |
}
|
81d882d5 |
if (retval != len) |
53f97e1e |
{ |
81d882d5 |
msg(D_TLS_ERRORS,
"TLS ERROR: write tls_write_plaintext_const incomplete %d/%d",
retval, len);
perf_pop();
return -1; |
53f97e1e |
}
|
81d882d5 |
/* successful write */
dmsg(D_HANDSHAKE_VERBOSE, "write tls_write_plaintext_const %d bytes", retval); |
53f97e1e |
|
81d882d5 |
perf_pop();
return 1; |
53f97e1e |
}
int |
81d882d5 |
key_state_read_ciphertext(struct key_state_ssl *ks, struct buffer *buf,
int maxlen) |
53f97e1e |
{ |
81d882d5 |
int retval = 0;
int len = 0; |
53f97e1e |
|
81d882d5 |
perf_push(PERF_BIO_READ_CIPHERTEXT); |
53f97e1e |
|
81d882d5 |
ASSERT(NULL != ks);
ASSERT(buf);
ASSERT(buf->len >= 0); |
53f97e1e |
|
81d882d5 |
if (buf->len) |
53f97e1e |
{ |
81d882d5 |
perf_pop();
return 0; |
53f97e1e |
}
|
81d882d5 |
len = buf_forward_capacity(buf);
if (maxlen < len)
{
len = maxlen;
} |
53f97e1e |
|
81d882d5 |
retval = endless_buf_read(&ks->bio_ctx.out, BPTR(buf), len); |
53f97e1e |
|
81d882d5 |
/* Error during read, check for retry error */
if (retval < 0) |
53f97e1e |
{ |
81d882d5 |
perf_pop();
if (MBEDTLS_ERR_SSL_WANT_WRITE == retval || MBEDTLS_ERR_SSL_WANT_READ == retval)
{
return 0;
}
mbed_log_err(D_TLS_ERRORS, retval, "TLS_ERROR: read tls_read_ciphertext error");
buf->len = 0;
return -1; |
53f97e1e |
} |
81d882d5 |
/* Nothing read, try again */
if (0 == retval) |
53f97e1e |
{ |
81d882d5 |
buf->len = 0;
perf_pop();
return 0; |
53f97e1e |
}
|
81d882d5 |
/* successful read */
dmsg(D_HANDSHAKE_VERBOSE, "read tls_read_ciphertext %d bytes", retval);
buf->len = retval;
perf_pop();
return 1; |
53f97e1e |
}
int |
81d882d5 |
key_state_write_ciphertext(struct key_state_ssl *ks, struct buffer *buf) |
53f97e1e |
{ |
81d882d5 |
int retval = 0;
perf_push(PERF_BIO_WRITE_CIPHERTEXT); |
53f97e1e |
|
81d882d5 |
ASSERT(NULL != ks);
ASSERT(buf);
ASSERT(buf->len >= 0); |
53f97e1e |
|
81d882d5 |
if (0 == buf->len) |
53f97e1e |
{ |
81d882d5 |
perf_pop();
return 0; |
53f97e1e |
}
|
81d882d5 |
retval = endless_buf_write(&ks->bio_ctx.in, BPTR(buf), buf->len); |
53f97e1e |
|
81d882d5 |
if (retval < 0) |
53f97e1e |
{ |
81d882d5 |
perf_pop();
if (MBEDTLS_ERR_SSL_WANT_WRITE == retval || MBEDTLS_ERR_SSL_WANT_READ == retval)
{
return 0;
}
mbed_log_err(D_TLS_ERRORS, retval,
"TLS ERROR: write tls_write_ciphertext error");
return -1; |
53f97e1e |
}
|
81d882d5 |
if (retval != buf->len) |
53f97e1e |
{ |
81d882d5 |
msg(D_TLS_ERRORS, "TLS ERROR: write tls_write_ciphertext incomplete %d/%d",
retval, buf->len);
perf_pop();
return -1; |
53f97e1e |
}
|
81d882d5 |
/* successful write */
dmsg(D_HANDSHAKE_VERBOSE, "write tls_write_ciphertext %d bytes", retval); |
53f97e1e |
|
81d882d5 |
memset(BPTR(buf), 0, BLEN(buf)); /* erase data just written */
buf->len = 0; |
53f97e1e |
|
81d882d5 |
perf_pop();
return 1; |
53f97e1e |
}
int |
81d882d5 |
key_state_read_plaintext(struct key_state_ssl *ks, struct buffer *buf,
int maxlen) |
53f97e1e |
{ |
81d882d5 |
int retval = 0;
int len = 0; |
53f97e1e |
|
81d882d5 |
perf_push(PERF_BIO_READ_PLAINTEXT); |
53f97e1e |
|
81d882d5 |
ASSERT(NULL != ks);
ASSERT(buf);
ASSERT(buf->len >= 0); |
53f97e1e |
|
81d882d5 |
if (buf->len) |
53f97e1e |
{ |
81d882d5 |
perf_pop();
return 0; |
53f97e1e |
}
|
81d882d5 |
len = buf_forward_capacity(buf);
if (maxlen < len)
{
len = maxlen;
} |
53f97e1e |
|
81d882d5 |
retval = mbedtls_ssl_read(ks->ctx, BPTR(buf), len); |
53f97e1e |
|
81d882d5 |
/* Error during read, check for retry error */
if (retval < 0) |
53f97e1e |
{ |
81d882d5 |
if (MBEDTLS_ERR_SSL_WANT_WRITE == retval || MBEDTLS_ERR_SSL_WANT_READ == retval)
{
return 0;
}
mbed_log_err(D_TLS_ERRORS, retval, "TLS_ERROR: read tls_read_plaintext error");
buf->len = 0;
perf_pop();
return -1; |
53f97e1e |
} |
81d882d5 |
/* Nothing read, try again */
if (0 == retval) |
53f97e1e |
{ |
81d882d5 |
buf->len = 0;
perf_pop();
return 0; |
53f97e1e |
}
|
81d882d5 |
/* successful read */
dmsg(D_HANDSHAKE_VERBOSE, "read tls_read_plaintext %d bytes", retval);
buf->len = retval; |
53f97e1e |
|
81d882d5 |
perf_pop();
return 1; |
53f97e1e |
}
/* **************************************
*
* Information functions
*
* Print information for the end user.
*
***************************************/
void |
81d882d5 |
print_details(struct key_state_ssl *ks_ssl, const char *prefix) |
53f97e1e |
{ |
81d882d5 |
const mbedtls_x509_crt *cert;
char s1[256];
char s2[256];
s1[0] = s2[0] = 0;
openvpn_snprintf(s1, sizeof(s1), "%s %s, cipher %s",
prefix,
mbedtls_ssl_get_version(ks_ssl->ctx),
mbedtls_ssl_get_ciphersuite(ks_ssl->ctx));
cert = mbedtls_ssl_get_peer_cert(ks_ssl->ctx);
if (cert != NULL) |
53f97e1e |
{ |
81d882d5 |
openvpn_snprintf(s2, sizeof(s2), ", %u bit key",
(unsigned int) mbedtls_pk_get_bitlen(&cert->pk)); |
53f97e1e |
}
|
81d882d5 |
msg(D_HANDSHAKE, "%s%s", s1, s2); |
53f97e1e |
}
void |
aba75874 |
show_available_tls_ciphers(const char *cipher_list,
const char *tls_cert_profile) |
53f97e1e |
{ |
81d882d5 |
struct tls_root_ctx tls_ctx;
const int *ciphers = mbedtls_ssl_list_ciphersuites(); |
53f97e1e |
|
81d882d5 |
tls_ctx_server_new(&tls_ctx); |
aba75874 |
tls_ctx_set_cert_profile(&tls_ctx, tls_cert_profile); |
81d882d5 |
tls_ctx_restrict_ciphers(&tls_ctx, cipher_list); |
e83313a8 |
|
81d882d5 |
if (tls_ctx.allowed_ciphers)
{
ciphers = tls_ctx.allowed_ciphers;
} |
cb03dca8 |
|
53f97e1e |
#ifndef ENABLE_SMALL |
81d882d5 |
printf("Available TLS Ciphers,\n");
printf("listed in order of preference:\n\n"); |
53f97e1e |
#endif
|
81d882d5 |
while (*ciphers != 0) |
53f97e1e |
{ |
81d882d5 |
printf("%s\n", mbedtls_ssl_get_ciphersuite_name(*ciphers));
ciphers++; |
53f97e1e |
} |
81d882d5 |
printf("\n" SHOW_TLS_CIPHER_LIST_WARNING); |
e83313a8 |
|
81d882d5 |
tls_ctx_free(&tls_ctx); |
53f97e1e |
}
void |
81d882d5 |
show_available_curves(void) |
609e8131 |
{ |
81d882d5 |
const mbedtls_ecp_curve_info *pcurve = mbedtls_ecp_curve_list(); |
609e8131 |
|
81d882d5 |
if (NULL == pcurve)
{
msg(M_FATAL, "Cannot retrieve curve list from mbed TLS");
} |
609e8131 |
|
81d882d5 |
/* Print curve list */
printf("Available Elliptic curves, listed in order of preference:\n\n");
while (MBEDTLS_ECP_DP_NONE != pcurve->grp_id) |
609e8131 |
{ |
81d882d5 |
printf("%s\n", pcurve->name);
pcurve++; |
609e8131 |
}
}
void |
81d882d5 |
get_highest_preference_tls_cipher(char *buf, int size) |
53f97e1e |
{ |
81d882d5 |
const char *cipher_name;
const int *ciphers = mbedtls_ssl_list_ciphersuites();
if (*ciphers == 0)
{
msg(M_FATAL, "Cannot retrieve list of supported SSL ciphers.");
} |
53f97e1e |
|
81d882d5 |
cipher_name = mbedtls_ssl_get_ciphersuite_name(*ciphers);
strncpynt(buf, cipher_name, size); |
53f97e1e |
} |
31ea2ee4 |
|
5b17803e |
const char * |
1ec984b1 |
get_ssl_library_version(void)
{ |
86d8cd68 |
static char mbedtls_version[30];
unsigned int pv = mbedtls_version_get_number();
sprintf( mbedtls_version, "mbed TLS %d.%d.%d", |
81d882d5 |
(pv>>24)&0xff, (pv>>16)&0xff, (pv>>8)&0xff ); |
86d8cd68 |
return mbedtls_version; |
1ec984b1 |
}
|
86d8cd68 |
#endif /* defined(ENABLE_CRYPTO) && defined(ENABLE_CRYPTO_MBEDTLS) */ |