36#if defined(ENABLE_CRYPTO_MBEDTLS)
37#include <mbedtls/version.h>
39#if MBEDTLS_VERSION_NUMBER < 0x04000000
50#include <mbedtls/base64.h>
51#include <mbedtls/des.h>
52#include <mbedtls/error.h>
53#include <mbedtls/md5.h>
54#include <mbedtls/cipher.h>
55#include <mbedtls/pem.h>
57#include <mbedtls/entropy.h>
58#include <mbedtls/ssl.h>
70 msg(
M_WARN,
"Note: mbed TLS hardware crypto engine functionality is not "
79 msg(
M_WARN,
"Note: mbed TLS provider functionality is not available");
111mbed_log_err(
unsigned int flags,
int errval,
const char *prefix)
116 mbedtls_strerror(errval, errstr,
sizeof(errstr));
120 prefix =
"mbed TLS error";
122 msg(flags,
"%s: %s", prefix, errstr);
143 {
"BF-CBC",
"BLOWFISH-CBC" },
144 {
"BF-CFB",
"BLOWFISH-CFB64" },
145 {
"CAMELLIA-128-CFB",
"CAMELLIA-128-CFB128" },
146 {
"CAMELLIA-192-CFB",
"CAMELLIA-192-CFB128" },
147 {
"CAMELLIA-256-CFB",
"CAMELLIA-256-CFB128" }
155 const int *ciphers = mbedtls_cipher_list();
158 printf(
"The following ciphers and cipher modes are available for use\n"
159 "with " PACKAGE_NAME
". Each cipher shown below may be used as a\n"
160 "parameter to the --data-ciphers (or --cipher) option. Using a\n"
161 "GCM or CBC mode is recommended. In static key mode only CBC\n"
162 "mode is allowed.\n\n");
165 while (*ciphers != 0)
167 const mbedtls_cipher_info_t *info = mbedtls_cipher_info_from_type(*ciphers);
168 const char *name = mbedtls_cipher_info_get_name(info);
177 printf(
"\nThe following ciphers have a block size of less than 128 bits, \n"
178 "and are therefore deprecated. Do not use unless you have to.\n\n");
179 ciphers = mbedtls_cipher_list();
180 while (*ciphers != 0)
182 const mbedtls_cipher_info_t *info = mbedtls_cipher_info_from_type(*ciphers);
183 const char *name = mbedtls_cipher_info_get_name(info);
197 const int *digests = mbedtls_md_list();
200 printf(
"The following message digests are available for use with\n" PACKAGE_NAME
201 ". A message digest is used in conjunction with\n"
202 "the HMAC function, to authenticate received packets.\n"
203 "You can specify a message digest as parameter to\n"
204 "the --auth option.\n\n");
207 while (*digests != 0)
209 const mbedtls_md_info_t *info = mbedtls_md_info_from_type(*digests);
213 printf(
"%s %d bit default key\n", mbedtls_md_get_name(info),
214 mbedtls_md_get_size(info) * 8);
224 printf(
"Sorry, mbed TLS hardware crypto engine functionality is not "
228#if defined(__GNUC__) || defined(__clang__)
229#pragma GCC diagnostic push
230#pragma GCC diagnostic ignored "-Wconversion"
238 char header[1000 + 1] = { 0 };
239 char footer[1000 + 1] = { 0 };
241 if (!
checked_snprintf(header,
sizeof(header),
"-----BEGIN %s-----\n", name))
251 if (MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL
252 != mbedtls_pem_write_buffer(header, footer,
CBPTR(src),
BLEN(src), NULL, 0, &out_len))
261 BCAP(dst), &out_len))
275 char header[1000 + 1] = { 0 };
276 char footer[1000 + 1] = { 0 };
303 msg(
M_WARN,
"PEM decode error: destination buffer too small");
351 msg(
M_FATAL,
"Failed to initialize random generator");
407 msg(
D_LOW,
"Cipher algorithm '%s' not found", ciphername);
408 *
reason =
"disabled because unknown";
416 "Cipher algorithm '%s' uses a default key size (%zu bytes) "
417 "which is larger than " PACKAGE_NAME "'s current maximum key size "
420 *
reason =
"disabled due to key size too large";
434 return "[null-cipher]";
496#ifdef MBEDTLS_CHACHAPOLY_C
531#ifdef MBEDTLS_CHACHAPOLY_C
572 msg(
M_FATAL,
"mbed TLS cipher context init #1");
584 msg(
M_FATAL,
"mbed TLS cipher set padding mode");
648#ifdef MBEDTLS_CHACHAPOLY_C
753#if defined(__GNUC__) || defined(__clang__)
754#pragma GCC diagnostic pop
773 msg(
M_FATAL,
"Message hash algorithm '%s' not found", digest);
778 "Message hash algorithm '%s' uses a default hash size (%d bytes) which is larger than " PACKAGE_NAME
779 "'s current maximum hash size (%d bytes)",
797 return "[null-digest]";
956 volatile const unsigned char *
A = (
volatile const unsigned char *)
a;
957 volatile const unsigned char *
B = (
volatile const unsigned char *)
b;
958 volatile unsigned char diff = 0;
960 for (
size_t i = 0;
i < size;
i++)
962 unsigned char x =
A[
i],
y =
B[
i];
969#if defined(__GNUC__) || defined(__clang__)
970#pragma GCC diagnostic push
971#pragma GCC diagnostic ignored "-Wconversion"
995 const size_t olen_orig = olen;
996 const uint8_t *out_orig = out;
1005 unsigned int chunk = mbedtls_md_get_size(md_kt);
1006 unsigned int A1_len = mbedtls_md_get_size(md_kt);
1010 mbedtls_md_init(ctx);
1011 ASSERT(0 == mbedtls_md_setup(ctx, md_kt, 1));
1012 ASSERT(0 == mbedtls_md_hmac_starts(ctx, sec, sec_len));
1014 mbedtls_md_init(ctx_tmp);
1015 ASSERT(0 == mbedtls_md_setup(ctx_tmp, md_kt, 1));
1016 ASSERT(0 == mbedtls_md_hmac_starts(ctx_tmp, sec, sec_len));
1039 memcpy(out, A1, olen);
1073ssl_tls1_PRF(
const uint8_t *label,
size_t label_len,
const uint8_t *sec,
size_t slen, uint8_t *out1,
1080 uint8_t *out2 = (uint8_t *)
gc_malloc(olen,
false, &
gc);
1082 size_t len = slen / 2;
1083 const uint8_t *S1 = sec;
1084 const uint8_t *S2 = &(sec[len]);
1087 tls1_P_hash(md5, S1, len, label, label_len, out1, olen);
1088 tls1_P_hash(sha1, S2, len, label, label_len, out2, olen);
1090 for (
size_t i = 0; i < olen; i++)
1103#if defined(__GNUC__) || defined(__clang__)
1104#pragma GCC diagnostic pop
bool buf_printf(struct buffer *buf, const char *format,...)
printf-style append to a buffer with overflow check.
void buf_null_terminate(struct buffer *buf)
Force a null terminator at the end of the buffer content.
void * gc_malloc(size_t size, bool clear, struct gc_arena *a)
Allocate memory and, optionally, zero it.
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Allocate a buffer of the given size under garbage collection.
bool checked_snprintf(char *str, size_t size, const char *format,...)
Like snprintf() but returns an boolean.
Buffer management functions and garbage collection.
#define ALLOC_OBJ(dptr, type)
Allocate memory for a single object of the given type.
static bool buf_copy(struct buffer *dest, const struct buffer *src)
Copy the content of one buffer to the end of another.
#define BPTR(buf)
Return a pointer to the start of the buffer content.
static bool buf_inc_len(struct buffer *buf, int inc)
Increase or decrease the length of a buffer.
#define CBPTR(buf)
Return a const pointer to the start of the buffer content.
static void secure_memzero(void *data, size_t len)
Securely zeroise memory.
static bool buf_write(struct buffer *dest, const void *src, size_t size)
Append data to a buffer.
#define BLEN(buf)
Return the length of the buffer content in bytes.
static char * format_hex(const uint8_t *data, size_t size, size_t maxoutput, struct gc_arena *gc)
Format a binary buffer as a hex string with spaces every 4 bytes.
#define BCAP(buf)
Return the number of bytes available for appending to the buffer.
static void gc_free(struct gc_arena *a)
Free all allocations in a garbage collection arena.
#define ALLOC_OBJ_CLEAR(dptr, type)
Allocate and zero-initialise memory for a single object of the given type.
static struct gc_arena gc_new(void)
Allocate and return a new, empty garbage collection arena.
const char * translate_cipher_name_from_openvpn(const char *cipher_name)
Translate an OpenVPN cipher name to a crypto library cipher name.
const char * translate_cipher_name_to_openvpn(const char *cipher_name)
Translate a crypto library cipher name to an OpenVPN cipher name.
void print_cipher(const char *ciphername)
Print a cipher list entry.
Data Channel Cryptography Module.
int memcmp_constant_time(const void *a, const void *b, size_t size)
As memcmp(), but constant-time.
Data Channel Cryptography SSL library-specific backend interface.
bool ssl_tls1_PRF(const uint8_t *seed, size_t seed_len, const uint8_t *secret, size_t secret_len, uint8_t *output, size_t output_len)
Calculates the TLS 1.0-1.1 PRF function.
void hmac_ctx_update(hmac_ctx_t *ctx, const uint8_t *src, int src_len)
hmac_ctx_t * hmac_ctx_new(void)
void hmac_ctx_reset(hmac_ctx_t *ctx)
bool cipher_kt_mode_cbc(const char *ciphername)
Check if the supplied cipher is a supported CBC mode cipher.
void show_available_engines(void)
void hmac_ctx_init(hmac_ctx_t *ctx, const uint8_t *key, const char *mdname)
md_ctx_t * md_ctx_new(void)
void hmac_ctx_final(hmac_ctx_t *ctx, uint8_t *dst)
void md_ctx_update(md_ctx_t *ctx, const uint8_t *src, size_t src_len)
unsigned int cipher_kt_iv_size(const char *ciphername)
Returns the size of the IV used by the cipher, in bytes, or 0 if no IV is used.
unsigned int cipher_ctx_iv_length(const cipher_ctx_t *ctx)
Returns the size of the IV used by the cipher, in bytes, or 0 if no IV is used.
void crypto_unload_provider(const char *provname, provider_t *provider)
Unloads the given (OpenSSL) provider.
void crypto_uninit_lib(void)
bool cipher_kt_mode_aead(const char *ciphername)
Check if the supplied cipher is a supported AEAD mode cipher.
int md_ctx_size(const md_ctx_t *ctx)
void show_available_ciphers(void)
bool md_valid(const char *digest)
Return if a message digest parameters is valid given the name of the digest.
bool cipher_ctx_mode_cbc(const cipher_ctx_t *ctx)
Check if the supplied cipher is a supported CBC mode cipher.
void crypto_init_lib(void)
cipher_ctx_t * cipher_ctx_new(void)
Generic cipher functions.
bool cipher_kt_mode_ofb_cfb(const char *ciphername)
Check if the supplied cipher is a supported OFB or CFB mode cipher.
const char * md_kt_name(const char *mdname)
Retrieve a string describing the digest digest (e.g.
int hmac_ctx_size(hmac_ctx_t *ctx)
bool cipher_kt_insecure(const char *ciphername)
Returns true if we consider this cipher to be insecure.
#define MAX_CIPHER_KEY_LENGTH
void crypto_clear_error(void)
bool crypto_pem_decode(const char *name, struct buffer *dst, const struct buffer *src)
Decode a PEM buffer to binary data.
provider_t * crypto_load_provider(const char *provider)
Load the given (OpenSSL) providers.
void cipher_ctx_free(cipher_ctx_t *ctx)
Cleanup and free a cipher context.
int cipher_ctx_mode(const cipher_ctx_t *ctx)
Returns the mode that the cipher runs in.
bool cipher_ctx_mode_ofb_cfb(const cipher_ctx_t *ctx)
Check if the supplied cipher is a supported OFB or CFB mode cipher.
bool cipher_ctx_mode_aead(const cipher_ctx_t *ctx)
Check if the supplied cipher is a supported AEAD mode cipher.
void hmac_ctx_free(hmac_ctx_t *ctx)
unsigned int cipher_kt_tag_size(const char *ciphername)
Returns the MAC tag size of the cipher, in bytes.
int cipher_ctx_update_ad(cipher_ctx_t *ctx, const uint8_t *src, int src_len)
Updates the given cipher context, providing additional data (AD) for authenticated encryption with ad...
int rand_bytes(uint8_t *output, int len)
Wrapper for secure random number generator.
const size_t cipher_name_translation_table_count
const char * cipher_kt_name(const char *ciphername)
Retrieve a normalised string describing the cipher (e.g.
#define MAX_HMAC_KEY_LENGTH
unsigned int cipher_kt_key_size(const char *ciphername)
Returns the size of keys used by the cipher, in bytes.
#define OPENVPN_AEAD_TAG_LENGTH
void cipher_ctx_init(cipher_ctx_t *ctx, const uint8_t *key, const char *ciphername, crypto_operation_t enc)
Initialise a cipher context, based on the given key and key type.
int cipher_ctx_get_tag(cipher_ctx_t *ctx, uint8_t *tag, int tag_len)
Gets the computed message authenticated code (MAC) tag for this cipher.
int cipher_ctx_update(cipher_ctx_t *ctx, uint8_t *dst, int *dst_len, const uint8_t *src, int src_len)
Updates the given cipher context, encrypting data in the source buffer, and placing any complete bloc...
void crypto_init_lib_engine(const char *engine_name)
void hmac_ctx_cleanup(hmac_ctx_t *ctx)
int cipher_ctx_reset(cipher_ctx_t *ctx, const uint8_t *iv_buf)
Resets the given cipher context, setting the IV to the specified value.
const cipher_name_pair cipher_name_translation_table[]
Cipher name translation table.
void md_ctx_cleanup(md_ctx_t *ctx)
unsigned int cipher_ctx_block_size(const cipher_ctx_t *ctx)
Returns the block size of the cipher, in bytes.
int cipher_ctx_final(cipher_ctx_t *ctx, uint8_t *dst, int *dst_len)
Pads the final cipher block using PKCS padding, and output to the destination buffer.
unsigned int cipher_kt_block_size(const char *ciphername)
Returns the block size of the cipher, in bytes.
void md_ctx_final(md_ctx_t *ctx, uint8_t *dst)
unsigned char md_kt_size(const char *mdname)
Returns the size of the message digest, in bytes.
void show_available_digests(void)
bool cipher_valid_reason(const char *ciphername, const char **reason)
Returns if the cipher is valid, based on the given cipher name and provides a reason if invalid.
int cipher_ctx_final_check_tag(cipher_ctx_t *ctx, uint8_t *dst, int *dst_len, uint8_t *tag, size_t tag_len)
Like cipher_ctx_final, but check the computed authentication tag against the supplied (expected) tag.
void md_ctx_init(md_ctx_t *ctx, const char *mdname)
Initialises the given message digest context.
void md_ctx_free(md_ctx_t *ctx)
bool crypto_pem_encode(const char *name, struct buffer *dst, const struct buffer *src, struct gc_arena *gc)
Encode binary data as PEM.
#define OPENVPN_MODE_OFB
Cipher is in OFB mode.
#define mbed_ok(errval)
Check errval and log on error.
bool mbed_log_err(unsigned int flags, int errval, const char *prefix)
Log the supplied mbed TLS error, prefixed by supplied prefix.
#define OPENVPN_MODE_CFB
Cipher is in CFB mode.
#define OPENVPN_MODE_CBC
Cipher is in CBC mode.
#define OPENVPN_MODE_GCM
Cipher is in GCM mode.
bool mbed_log_func_line(unsigned int flags, int errval, const char *func, int line)
Log the supplied mbed TLS error, prefixed by function name and line number.
mbedtls_ctr_drbg_context * rand_ctx_get(void)
Returns a singleton instance of the mbed TLS random number generator.
mbedtls_md_info_t md_kt_t
Generic message digest key type context.
const mbedtls_md_info_t * md_get(const char *digest)
int cipher_kt_mode(const EVP_CIPHER *cipher_kt)
static evp_cipher_type * cipher_get(const char *ciphername)
#define D_SHOW_KEY_SOURCE
static int min_int(int x, int y)
const char * time_string(time_t t, tv_usec_t usec, bool show_usec, struct gc_arena *gc)
Wrapper structure for dynamically allocated memory.
int len
Length in bytes of the actual content within the allocated memory.
Struct used in cipher name translation table.
Garbage collection arena used to keep track of dynamically allocated memory.
Container for unidirectional cipher and HMAC key material.