36#if defined(ENABLE_CRYPTO_MBEDTLS)
37#include <mbedtls/version.h>
39#if MBEDTLS_VERSION_NUMBER >= 0x04000000
51#include <psa/crypto.h>
52#include <psa/crypto_config.h>
53#include <mbedtls/constant_time.h>
54#include <mbedtls/error.h>
55#include <mbedtls/pem.h>
66 msg(
M_WARN,
"Note: mbed TLS hardware crypto engine functionality is not "
75 msg(
M_WARN,
"Note: mbed TLS provider functionality is not available");
91#if PSA_WANT_KEY_TYPE_AES
93 {
"AES-128-GCM", PSA_KEY_TYPE_AES, PSA_ALG_GCM, 128 / 8, 96 / 8, 128 / 8 },
94 {
"AES-192-GCM", PSA_KEY_TYPE_AES, PSA_ALG_GCM, 192 / 8, 96 / 8, 128 / 8 },
95 {
"AES-256-GCM", PSA_KEY_TYPE_AES, PSA_ALG_GCM, 256 / 8, 96 / 8, 128 / 8 },
97#if PSA_WANT_ALG_CBC_PKCS7
98 {
"AES-128-CBC", PSA_KEY_TYPE_AES, PSA_ALG_CBC_PKCS7, 128 / 8, 128 / 8, 128 / 8 },
99 {
"AES-192-CBC", PSA_KEY_TYPE_AES, PSA_ALG_CBC_PKCS7, 192 / 8, 128 / 8, 128 / 8 },
100 {
"AES-256-CBC", PSA_KEY_TYPE_AES, PSA_ALG_CBC_PKCS7, 256 / 8, 128 / 8, 128 / 8 },
103 {
"AES-128-CTR", PSA_KEY_TYPE_AES, PSA_ALG_CTR, 128 / 8, 128 / 8, 128 / 8 },
104 {
"AES-192-CTR", PSA_KEY_TYPE_AES, PSA_ALG_CTR, 192 / 8, 128 / 8, 128 / 8 },
105 {
"AES-256-CTR", PSA_KEY_TYPE_AES, PSA_ALG_CTR, 256 / 8, 128 / 8, 128 / 8 },
110#if PSA_WANT_KEY_TYPE_CHACHA20 && PSA_WANT_ALG_CHACHA20_POLY1305
111 {
"CHACHA20-POLY1305", PSA_KEY_TYPE_CHACHA20, PSA_ALG_CHACHA20_POLY1305, 256 / 8, 96 / 8, 1 },
114static const size_t cipher_info_table_entries =
sizeof(cipher_info_table) /
sizeof(
cipher_info_t);
119 for (
size_t i = 0; i < cipher_info_table_entries; i++)
121 if (strcmp(ciphername, cipher_info_table[i].name) == 0)
123 return &cipher_info_table[i];
142 psa_status_t result = psa_generate_random(output, (
size_t)len);
143 return result == PSA_SUCCESS;
155 msg(
D_LOW,
"Cipher algorithm '%s' not found", ciphername);
156 *reason =
"disabled because unknown";
163 "Cipher algorithm '%s' uses a default key size (%d bytes) "
164 "which is larger than " PACKAGE_NAME "'s current maximum key size "
167 *reason =
"disabled due to key size too large";
181 return "[null-cipher]";
297 ASSERT(psa_destroy_key(ctx->
key) == PSA_SUCCESS);
305 ASSERT(ciphername != NULL && ctx != NULL);
382 return mode == (int)PSA_ALG_GCM || mode == (
int)PSA_ALG_CHACHA20_POLY1305;
388 psa_key_usage_t key_usage = psa_get_key_usage_flags(&ctx->
key_attributes);
389 if (key_usage & PSA_KEY_USAGE_ENCRYPT)
393 else if (key_usage & PSA_KEY_USAGE_DECRYPT)
428 if (
status != PSA_SUCCESS)
434 if (
status != PSA_SUCCESS)
459 if (
status != PSA_SUCCESS)
465 if (
status != PSA_SUCCESS)
483 if (mode == PSA_ALG_CTR || mode == PSA_ALG_GCM || mode == PSA_ALG_CHACHA20_POLY1305)
487 return (
size_t)src_len;
494 size_t max_blocks = 1 + (size_t)src_len / block_size;
495 return max_blocks * block_size;
507 if (psa_aead_update_ad(&ctx->
operation.
aead, src, (
size_t)src_len) != PSA_SUCCESS)
522 size_t dst_size = needed_dst_size(ctx, src_len);
523 size_t psa_output_len = 0;
528 status = psa_aead_update(&ctx->
operation.
aead, src, (
size_t)src_len, dst, dst_size, &psa_output_len);
532 status = psa_cipher_update(&ctx->
operation.
cipher, src, (
size_t)src_len, dst, dst_size, &psa_output_len);
535 if (
status != PSA_SUCCESS)
540 if (psa_output_len > INT_MAX)
544 *dst_len = (int)psa_output_len;
552 size_t dst_size = needed_dst_size(ctx, 0);
553 size_t psa_output_len = 0;
558 size_t actual_tag_size = 0;
575 if (
status != PSA_SUCCESS || psa_output_len > (
size_t)INT_MAX)
581 *dst_len = (int)psa_output_len;
594 size_t psa_output_len = 0;
598 if (
status != PSA_SUCCESS || psa_output_len > (
size_t)INT_MAX)
602 *dst_len = (int)psa_output_len;
607static const md_info_t md_info_table[] = {
609 {
"MD5", PSA_ALG_MD5 },
610 {
"SHA1", PSA_ALG_SHA_1 },
611 {
"SHA256", PSA_ALG_SHA_256 },
613const size_t md_info_table_entries =
sizeof(md_info_table) /
sizeof(
md_info_t);
616md_get(
const char *digest_name)
618 for (
size_t i = 0; i < md_info_table_entries; i++)
620 if (strcmp(digest_name, md_info_table[i].name) == 0)
622 return &md_info_table[i];
638 if (strcmp(
"none", mdname) == 0)
640 return "[null-digest]";
653 if (strcmp(
"none", mdname) == 0)
674md_full(
const char *mdname,
const uint8_t *src,
int src_len, uint8_t *dst)
677 if (md == NULL || src_len < 0)
684 size_t dst_size = PSA_HASH_LENGTH(md->
psa_alg);
685 size_t hash_length = 0;
687 psa_status_t
status = psa_hash_compute(md->
psa_alg, src, (
size_t)src_len, dst, dst_size, &hash_length);
688 if (
status != PSA_SUCCESS || hash_length != dst_size)
739 size_t hash_length = 0;
741 ASSERT(psa_hash_finish(&ctx->
operation, dst, dst_size, &hash_length) == PSA_SUCCESS);
742 ASSERT(hash_length == dst_size);
765 psa_set_key_usage_flags(&ctx->
key_attributes, PSA_KEY_USAGE_SIGN_MESSAGE);
788 ASSERT(psa_destroy_key(ctx->
key) == PSA_SUCCESS);
808 ASSERT(psa_mac_update(&ctx->
operation, src, (
size_t)src_len) == PSA_SUCCESS);
817 size_t hmac_length = 0;
819 ASSERT(psa_mac_sign_finish(&ctx->
operation, dst, dst_size, &hmac_length) == PSA_SUCCESS);
820 ASSERT(hmac_length == dst_size);
835tls1_P_hash(
const md_info_t *
md_info,
const uint8_t *sec,
size_t sec_len,
const uint8_t *seed,
836 int seed_len, uint8_t *out,
size_t olen)
844 const size_t olen_orig = olen;
845 const uint8_t *out_orig = out;
854 unsigned int chunk = (
unsigned int)PSA_HASH_LENGTH(
md_info->
psa_alg);
855 unsigned int A1_len = (
unsigned int)PSA_HASH_LENGTH(
md_info->
psa_alg);
859 hmac_ctx_init_with_arbitrary_key_length(ctx, sec, sec_len,
md_info);
860 hmac_ctx_init_with_arbitrary_key_length(ctx_tmp, sec, sec_len,
md_info);
883 memcpy(out, A1, olen);
917ssl_tls1_PRF(
const uint8_t *label,
size_t label_len,
const uint8_t *sec,
size_t slen, uint8_t *out1,
923 if (label_len > (
size_t)INT_MAX)
930 uint8_t *out2 = (uint8_t *)
gc_malloc(olen,
false, &
gc);
932 size_t len = slen / 2;
933 const uint8_t *S1 = sec;
934 const uint8_t *S2 = &(sec[len]);
937 tls1_P_hash(md5, S1, len, label, (
int)label_len, out1, olen);
938 tls1_P_hash(sha1, S2, len, label, (
int)label_len, out2, olen);
940 for (
size_t i = 0; i < olen; i++)
969mbed_log_err(
unsigned int flags,
int errval,
const char *prefix)
974 mbedtls_strerror(errval, errstr,
sizeof(errstr));
978 prefix =
"mbed TLS error";
980 msg(flags,
"%s: %s", prefix, errstr);
991 if (snprintf(prefix,
sizeof(prefix),
"%s:%d", func, line) >=
sizeof(prefix))
1002 return mbedtls_ct_memcmp(a, b, size);
1012 printf(
"The following ciphers and cipher modes are available for use\n"
1013 "with " PACKAGE_NAME ". Each cipher shown below may be used as a\n"
1014 "parameter to the --data-ciphers (or --cipher) option. Using a\n"
1015 "GCM or CBC mode is recommended. In static key mode only CBC\n"
1016 "mode is allowed.\n\n");
1019 for (
size_t i = 0; i < cipher_info_table_entries; i++)
1022 const char *name = info->
name;
1029 printf(
"\nThe following ciphers have a block size of less than 128 bits, \n"
1030 "and are therefore deprecated. Do not use unless you have to.\n\n");
1031 for (
size_t i = 0; i < cipher_info_table_entries; i++)
1034 const char *name = info->
name;
1050 printf(
"The following message digests are available for use with\n" PACKAGE_NAME
1051 ". A message digest is used in conjunction with\n"
1052 "the HMAC function, to authenticate received packets.\n"
1053 "You can specify a message digest as parameter to\n"
1054 "the --auth option.\n\n");
1057 for (
size_t i = 0; i < md_info_table_entries; i++)
1059 const md_info_t *info = &md_info_table[i];
1060 printf(
"%s %d bit default key\n", info->
name,
1061 (
unsigned char)PSA_HASH_LENGTH(info->
psa_alg) * 8);
1069 printf(
"Sorry, mbed TLS hardware crypto engine functionality is not "
1078 char header[1000 + 1] = { 0 };
1079 char footer[1000 + 1] = { 0 };
1081 if (snprintf(header,
sizeof(header),
"-----BEGIN %s-----\n", name) >=
sizeof(header))
1085 if (snprintf(footer,
sizeof(footer),
"-----END %s-----\n", name) >=
sizeof(footer))
1091 if (MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL
1092 != mbedtls_pem_write_buffer(header, footer,
BPTR(src),
BLEN(src), NULL, 0, &out_len))
1101 BCAP(dst), &out_len))
1102 || !(out_len < INT_MAX && out_len > 1)
1116 char header[1000 + 1] = { 0 };
1117 char footer[1000 + 1] = { 0 };
1119 if (snprintf(header,
sizeof(header),
"-----BEGIN %s-----", name) >=
sizeof(header))
1123 if (snprintf(footer,
sizeof(footer),
"-----END %s-----", name) >=
sizeof(footer))
1144 msg(
M_WARN,
"PEM decode error: destination buffer too small");
void buf_null_terminate(struct buffer *buf)
void * gc_malloc(size_t size, bool clear, struct gc_arena *a)
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
static bool buf_copy(struct buffer *dest, const struct buffer *src)
static bool buf_inc_len(struct buffer *buf, int inc)
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)
static char * format_hex(const uint8_t *data, size_t size, size_t maxoutput, struct gc_arena *gc)
static void gc_free(struct gc_arena *a)
#define ALLOC_OBJ_CLEAR(dptr, type)
static struct gc_arena gc_new(void)
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.
int cipher_ctx_update(cipher_ctx_t *ctx, uint8_t *dst, int *dst_len, uint8_t *src, int src_len)
Updates the given cipher context, encrypting data in the source buffer, and placing any complete bloc...
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)
int md_full(const char *mdname, const uint8_t *src, int src_len, uint8_t *dst)
Calculates the message digest for the given buffer.
void hmac_ctx_reset(hmac_ctx_t *ctx)
int cipher_ctx_block_size(const cipher_ctx_t *ctx)
Returns the block size of the cipher, in bytes.
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)
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)
int cipher_kt_block_size(const char *ciphername)
Returns the block size of the cipher, in bytes.
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)
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.
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
#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_kt_key_size(const char *ciphername)
Returns the size of keys used by the cipher, in bytes.
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)
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.
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.
Data Channel Cryptography backend interface using the TF-PSA-Crypto library part of Mbed TLS 4.
#define OPENVPN_OP_DECRYPT
Cipher should decrypt.
#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_OP_ENCRYPT
Cipher should encrypt.
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.
static evp_cipher_type * cipher_get(const char *ciphername)
static evp_md_type * md_get(const char *digest)
#define D_SHOW_KEY_SOURCE
static SERVICE_STATUS status
Wrapper structure for dynamically allocated memory.
int len
Length in bytes of the actual content within the allocated memory.
cipher_operation_t operation
psa_key_attributes_t key_attributes
const cipher_info_t * cipher_info
psa_key_type_t psa_key_type
Struct used in cipher name translation table.
Garbage collection arena used to keep track of dynamically allocated memory.
const md_info_t * md_info
psa_mac_operation_t operation
psa_key_attributes_t key_attributes
Container for unidirectional cipher and HMAC key material.
const md_info_t * md_info
psa_hash_operation_t operation
psa_aead_operation_t aead
psa_cipher_operation_t cipher