]> git.pld-linux.org Git - packages/bctoolbox.git/commitdiff
- updated to 5.3.26
authorJakub Bogusz <qboosh@pld-linux.org>
Tue, 5 Mar 2024 19:17:45 +0000 (20:17 +0100)
committerJakub Bogusz <qboosh@pld-linux.org>
Tue, 5 Mar 2024 19:17:45 +0000 (20:17 +0100)
bctoolbox-decaf-shared.patch [new file with mode: 0644]
bctoolbox-mbedtlsv3.patch [deleted file]
bctoolbox-use-after-free.patch [deleted file]
bctoolbox.spec

diff --git a/bctoolbox-decaf-shared.patch b/bctoolbox-decaf-shared.patch
new file mode 100644 (file)
index 0000000..0197cab
--- /dev/null
@@ -0,0 +1,30 @@
+--- bctoolbox-5.3.26/cmake/FindDecaf.cmake.orig        2024-02-08 16:02:05.000000000 +0100
++++ bctoolbox-5.3.26/cmake/FindDecaf.cmake     2024-03-05 19:36:13.222752599 +0100
+@@ -41,10 +41,10 @@
+ if(TARGET decaf OR TARGET decaf-static)
+-      if(TARGET decaf-static)
+-              set(Decaf_TARGET decaf-static)
+-      elseif(TARGET decaf)
++      if(TARGET decaf)
+               set(Decaf_TARGET decaf)
++      elseif(TARGET decaf-static)
++              set(Decaf_TARGET decaf-static)
+       endif()
+       include(FindPackageHandleStandardArgs)
+@@ -72,10 +72,10 @@ else()
+       find_package(Decaf ${_OPTIONS})
+-      if(TARGET decaf-static)
+-              set(Decaf_TARGET decaf-static)
+-      elseif(TARGET decaf)
++      if(TARGET decaf)
+               set(Decaf_TARGET decaf)
++      elseif(TARGET decaf-static)
++              set(Decaf_TARGET decaf-static)
+       endif()
+ endif()
diff --git a/bctoolbox-mbedtlsv3.patch b/bctoolbox-mbedtlsv3.patch
deleted file mode 100644 (file)
index db1f8c0..0000000
+++ /dev/null
@@ -1,2823 +0,0 @@
-From 052d280bdf3942fe0a642187a77b1245d22269f4 Mon Sep 17 00:00:00 2001
-From: johan pascal <johan.pascal@belledonne-communications.com>
-Date: Fri, 17 Feb 2023 23:59:04 +0100
-Subject: [PATCH] Add mbedtlsv3 support - suppress TLS client auth callback
-
----
- CMakeLists.txt             |   13 +-
- cmake/FindMbedTLS.cmake    |   22 +-
- include/bctoolbox/crypto.h |    8 -
- src/CMakeLists.txt         |   11 +-
- src/crypto/mbedtls-v2.c    | 1882 ++++++++++++++++++++++++++++++++++++
- src/crypto/mbedtls.c       |  261 ++---
- src/tester.c               |    2 +-
- tester/crypto.cc           |  232 ++---
- 8 files changed, 2128 insertions(+), 303 deletions(-)
- create mode 100644 src/crypto/mbedtls-v2.c
-
-diff --git a/CMakeLists.txt b/CMakeLists.txt
-index 05a1015..467dd3c 100644
---- a/CMakeLists.txt
-+++ b/CMakeLists.txt
-@@ -81,10 +81,19 @@ if(ENABLE_MBEDTLS)
-       else()
-               message(STATUS "MBEDTLS Enabled search disabled")
-               set (MBEDTLS_FOUND On)
--              set (DTLS_SRTP_AVAILABLE On) # we using internal Mbedtls lib, we always have DTLS-SRTP
-+              set (DTLS_SRTP_AVAILABLE On) # we using internal Mbedtls lib, we always have DTLS-SRTP and use v3
-+              set (MBEDTLS_VERSION_3 On)
-       endif()
-       if(MBEDTLS_FOUND)
--              message(STATUS "Using mbedTLS")
-+              if (MBEDTLS_VERSION_3)
-+                      message(STATUS "Using mbedTLS v3")
-+              else()
-+                      if (MBEDTLS_VERSION_2)
-+                              message(STATUS "Using mbedTLS v2")
-+                      else()
-+                              message(STATUS "Mbedtls version incompatible(requires v2 or v3), build will probably fail")
-+                      endif()
-+              endif()
-               set(HAVE_MBEDTLS 1)
-               set(MBEDTLS_TARGETS
-                       mbedtls
-diff --git a/cmake/FindMbedTLS.cmake b/cmake/FindMbedTLS.cmake
-index 5dfe438..6f14c99 100644
---- a/cmake/FindMbedTLS.cmake
-+++ b/cmake/FindMbedTLS.cmake
-@@ -57,12 +57,22 @@ list(APPEND CMAKE_REQUIRED_LIBRARIES ${MBEDTLS_LIBRARY} ${MBEDX509_LIBRARY} ${MB
- # check we have a mbedTLS version 2 or above(all functions are prefixed mbedtls_)
- if(MBEDTLS_LIBRARY AND MBEDX509_LIBRARY AND MBEDCRYPTO_LIBRARY)
-       check_symbol_exists(mbedtls_ssl_init "mbedtls/ssl.h" MBEDTLS_V2)
--  if(NOT MBEDTLS_V2)
--    message ("MESSAGE: NO MBEDTLS_V2")
--    message ("MESSAGE: MBEDTLS_LIBRARY=" ${MBEDTLS_LIBRARY})
--    message ("MESSAGE: MBEDX509_LIBRARY=" ${MBEDX509_LIBRARY})
--    message ("MESSAGE: MBEDCRYPTO_LIBRARY=" ${MBEDCRYPTO_LIBRARY})
--  endif()
-+      if(NOT MBEDTLS_V2)
-+              message ("MESSAGE: NO MBEDTLS_V2")
-+              message ("MESSAGE: MBEDTLS_LIBRARY=" ${MBEDTLS_LIBRARY})
-+              message ("MESSAGE: MBEDX509_LIBRARY=" ${MBEDX509_LIBRARY})
-+              message ("MESSAGE: MBEDCRYPTO_LIBRARY=" ${MBEDCRYPTO_LIBRARY})
-+              set (MBEDTLS_VERSION_1 On)
-+      else()
-+              # Are we mbdetls 2 or 3?
-+              # from version 3 and on, version number is given in include/mbedtls/build_info.h.
-+              # This file does not exists before version 3
-+              if (EXISTS "${MBEDTLS_INCLUDE_DIRS}/mbedtls/build_info.h")
-+                      set (MBEDTLS_VERSION_3 On)
-+              else()
-+                      set (MBEDTLS_VERSION_2 On)
-+              endif()
-+      endif()
- endif()
-diff --git a/include/bctoolbox/crypto.h b/include/bctoolbox/crypto.h
-index 2067020..49b339a 100644
---- a/include/bctoolbox/crypto.h
-+++ b/include/bctoolbox/crypto.h
-@@ -501,7 +501,6 @@ BCTBX_PUBLIC int32_t bctbx_ssl_read(bctb
- BCTBX_PUBLIC int32_t bctbx_ssl_write(bctbx_ssl_context_t *ssl_ctx, const unsigned char *buf, size_t buf_length);
- BCTBX_PUBLIC int32_t bctbx_ssl_set_hostname(bctbx_ssl_context_t *ssl_ctx, const char *hostname);
- BCTBX_PUBLIC int32_t bctbx_ssl_handshake(bctbx_ssl_context_t *ssl_ctx);
--BCTBX_PUBLIC int32_t bctbx_ssl_set_hs_own_cert(bctbx_ssl_context_t *ssl_ctx, bctbx_x509_certificate_t *cert, bctbx_signing_key_t *key);
- BCTBX_PUBLIC void bctbx_ssl_set_io_callbacks(bctbx_ssl_context_t *ssl_ctx, void *callback_data,
-               int(*callback_send_function)(void *, const unsigned char *, size_t), /* callbacks args are: callback data, data buffer to be send, size of data buffer */
-               int(*callback_recv_function)(void *, unsigned char *, size_t)); /* args: callback data, data buffer to be read, size of data buffer */
-@@ -520,7 +519,6 @@ BCTBX_PUBLIC int32_t bctbx_ssl_config_se
- BCTBX_PUBLIC int32_t bctbx_ssl_config_set_authmode(bctbx_ssl_config_t *ssl_config, int authmode);
- BCTBX_PUBLIC int32_t bctbx_ssl_config_set_rng(bctbx_ssl_config_t *ssl_config, int(*rng_function)(void *, unsigned char *, size_t), void *rng_context);
- BCTBX_PUBLIC int32_t bctbx_ssl_config_set_callback_verify(bctbx_ssl_config_t *ssl_config, int(*callback_function)(void *, bctbx_x509_certificate_t *, int, uint32_t *), void *callback_data);
--BCTBX_PUBLIC int32_t bctbx_ssl_config_set_callback_cli_cert(bctbx_ssl_config_t *ssl_config, int(*callback_function)(void *, bctbx_ssl_context_t *, const bctbx_list_t *), void *callback_data);
- BCTBX_PUBLIC int32_t bctbx_ssl_config_set_ca_chain(bctbx_ssl_config_t *ssl_config, bctbx_x509_certificate_t *ca_chain);
- BCTBX_PUBLIC int32_t bctbx_ssl_config_set_own_cert(bctbx_ssl_config_t *ssl_config, bctbx_x509_certificate_t *cert, bctbx_signing_key_t *key);
- BCTBX_PUBLIC int32_t bctbx_ssl_config_set_ciphersuites(bctbx_ssl_config_t *ssl_config,const int *ciphersuites);
-diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
-index a1b3dbc..c2fae5f 100644
---- a/src/CMakeLists.txt
-+++ b/src/CMakeLists.txt
-@@ -72,20 +72,20 @@ if(WIN32)
-       list(APPEND STRICT_OPTIONS_CXX "/EHa")
-       add_definitions(-EHa)
- endif()
--if(MBEDTLS_FOUND OR POLARSSL_FOUND)
--      list(APPEND BCTOOLBOX_C_SOURCE_FILES crypto/crypto.c)
--      list(APPEND BCTOOLBOX_CXX_SOURCE_FILES crypto/ecc.cc)
--endif()
- if(MBEDTLS_FOUND)
--      list(APPEND BCTOOLBOX_C_SOURCE_FILES crypto/mbedtls.c)
-+      list(APPEND BCTOOLBOX_C_SOURCE_FILES crypto/crypto.c)
-       list(APPEND BCTOOLBOX_CXX_SOURCE_FILES
-+              crypto/ecc.cc
-               crypto/mbedtls.cc
-               vfs/vfs_encrypted.cc
-               vfs/vfs_encryption_module_dummy.cc
-               vfs/vfs_encryption_module_aes256gcm_sha256.cc)
- endif()
--if(POLARSSL_FOUND)
--      list(APPEND BCTOOLBOX_C_SOURCE_FILES crypto/polarssl.c)
-+if(MBEDTLS_VERSION_3)
-+      list(APPEND BCTOOLBOX_C_SOURCE_FILES crypto/mbedtls.c)
-+endif()
-+if(MBEDTLS_VERSION_2)
-+      list(APPEND BCTOOLBOX_C_SOURCE_FILES crypto/mbedtls-v2.c)
- endif()
- if(ENABLE_TESTS_COMPONENT)
-       set(BCTOOLBOX_C_TESTER_SOURCE_FILES tester.c)
-diff --git a/src/crypto/mbedtls-v2.c b/src/crypto/mbedtls-v2.c
-new file mode 100644
-index 0000000..ec6b53c
---- /dev/null
-+++ b/src/crypto/mbedtls-v2.c
-@@ -0,0 +1,1882 @@
-+/*
-+ * Copyright (c) 2016-2020 Belledonne Communications SARL.
-+ *
-+ * This file is part of bctoolbox.
-+ *
-+ * This program is free software: you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation, either version 3 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * 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.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
-+ */
-+#ifdef HAVE_CONFIG_H
-+#include "config.h"
-+#endif
-+
-+#include "utils.h"
-+#include <stdlib.h>
-+#include <string.h>
-+
-+#include <mbedtls/base64.h>
-+#include <mbedtls/ctr_drbg.h>
-+#include <mbedtls/entropy.h>
-+#include <mbedtls/error.h>
-+#include <mbedtls/gcm.h>
-+#include <mbedtls/md5.h>
-+#include <mbedtls/oid.h>
-+#include <mbedtls/pem.h>
-+#include <mbedtls/sha1.h>
-+#include <mbedtls/sha256.h>
-+#include <mbedtls/sha512.h>
-+#include <mbedtls/ssl.h>
-+#include <mbedtls/timing.h>
-+#include <mbedtls/version.h>
-+#include <mbedtls/x509.h>
-+
-+#if MBEDTLS_VERSION_NUMBER >= 0x02040000 // v2.4.0
-+#include <mbedtls/net_sockets.h>
-+#else
-+#include <mbedtls/net.h>
-+#endif
-+
-+#include "bctoolbox/crypto.h"
-+#include "bctoolbox/defs.h"
-+#include "bctoolbox/logging.h"
-+
-+/*** Cleaning ***/
-+/**
-+ * @brief force a buffer value to zero in a way that shall prevent the compiler from optimizing it out
-+ *
-+ * @param[in/out]     buffer  the buffer to be cleared
-+ * @param[in]         size    buffer size
-+ */
-+void bctbx_clean(void *buffer, size_t size) {
-+#if MBEDTLS_VERSION_NUMBER >= 0x020A0000 // v2.10.0
-+      mbedtls_platform_zeroize(buffer, size);
-+#else
-+      volatile uint8_t *p = buffer;
-+      while (size--)
-+              *p++ = 0;
-+#endif
-+}
-+
-+/*** Error code translation ***/
-+void bctbx_strerror(int32_t error_code, char *buffer, size_t buffer_length) {
-+      if (error_code > 0) {
-+              snprintf(buffer, buffer_length, "%s", "Invalid Error code");
-+              return;
-+      }
-+
-+      /* mbedtls error code are all negatived and bas smaller than 0x0000F000 */
-+      /* bctoolbox defined error codes are all in format -0x7XXXXXXX */
-+      if (-error_code < 0x00010000) { /* it's a mbedtls error code */
-+              mbedtls_strerror(error_code, buffer, buffer_length);
-+              return;
-+      }
-+
-+      snprintf(buffer, buffer_length, "%s [-0x%x]", "bctoolbox defined error code", -error_code);
-+      return;
-+}
-+
-+/*** base64 ***/
-+int32_t
-+bctbx_base64_encode(unsigned char *output, size_t *output_length, const unsigned char *input, size_t input_length) {
-+      size_t byte_written = 0;
-+      int ret = mbedtls_base64_encode(output, *output_length, &byte_written, input, input_length);
-+      *output_length = byte_written;
-+      if (ret == MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) {
-+              return BCTBX_ERROR_OUTPUT_BUFFER_TOO_SMALL;
-+      }
-+      return ret;
-+}
-+
-+int32_t
-+bctbx_base64_decode(unsigned char *output, size_t *output_length, const unsigned char *input, size_t input_length) {
-+      size_t byte_written = 0;
-+      int ret = mbedtls_base64_decode(output, *output_length, &byte_written, input, input_length);
-+      *output_length = byte_written;
-+      if (ret == MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) {
-+              return BCTBX_ERROR_OUTPUT_BUFFER_TOO_SMALL;
-+      }
-+      if (ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER) {
-+              return BCTBX_ERROR_INVALID_BASE64_INPUT;
-+      }
-+
-+      return ret;
-+}
-+
-+/*** signing key ***/
-+bctbx_signing_key_t *bctbx_signing_key_new(void) {
-+      mbedtls_pk_context *key = bctbx_malloc0(sizeof(mbedtls_pk_context));
-+      mbedtls_pk_init(key);
-+      return (bctbx_signing_key_t *)key;
-+}
-+
-+void bctbx_signing_key_free(bctbx_signing_key_t *key) {
-+      mbedtls_pk_free((mbedtls_pk_context *)key);
-+      bctbx_free(key);
-+}
-+
-+char *bctbx_signing_key_get_pem(bctbx_signing_key_t *key) {
-+      char *pem_key;
-+      if (key == NULL) return NULL;
-+      pem_key = (char *)bctbx_malloc0(4096);
-+      mbedtls_pk_write_key_pem((mbedtls_pk_context *)key, (unsigned char *)pem_key, 4096);
-+      return pem_key;
-+}
-+
-+int32_t bctbx_signing_key_parse(bctbx_signing_key_t *key,
-+                                const char *buffer,
-+                                size_t buffer_length,
-+                                const unsigned char *password,
-+                                size_t password_length) {
-+      int err;
-+
-+      err = mbedtls_pk_parse_key((mbedtls_pk_context *)key, (const unsigned char *)buffer, buffer_length, password,
-+                                 password_length);
-+
-+      if (err < 0) {
-+              char tmp[128];
-+              mbedtls_strerror(err, tmp, sizeof(tmp));
-+              bctbx_error("cannot parse public key because [%s]", tmp);
-+              return BCTBX_ERROR_UNABLE_TO_PARSE_KEY;
-+      }
-+      return 0;
-+}
-+
-+int32_t bctbx_signing_key_parse_file(bctbx_signing_key_t *key, const char *path, const char *password) {
-+      int err;
-+
-+      err = mbedtls_pk_parse_keyfile((mbedtls_pk_context *)key, path, password);
-+
-+      if (err < 0) {
-+              char tmp[128];
-+              mbedtls_strerror(err, tmp, sizeof(tmp));
-+              bctbx_error("cannot parse public key because [%s]", tmp);
-+              return BCTBX_ERROR_UNABLE_TO_PARSE_KEY;
-+      }
-+      return 0;
-+}
-+
-+/*** Certificate ***/
-+char *bctbx_x509_certificates_chain_get_pem(const bctbx_x509_certificate_t *cert) {
-+      char *pem_certificate = NULL;
-+      size_t olen = 0;
-+
-+      pem_certificate = (char *)bctbx_malloc0(4096);
-+      mbedtls_pem_write_buffer("-----BEGIN CERTIFICATE-----\n", "-----END CERTIFICATE-----\n",
-+                               ((mbedtls_x509_crt *)cert)->raw.p, ((mbedtls_x509_crt *)cert)->raw.len,
-+                               (unsigned char *)pem_certificate, 4096, &olen);
-+      return pem_certificate;
-+}
-+
-+bctbx_x509_certificate_t *bctbx_x509_certificate_new(void) {
-+      mbedtls_x509_crt *cert = bctbx_malloc0(sizeof(mbedtls_x509_crt));
-+      mbedtls_x509_crt_init(cert);
-+      return (bctbx_x509_certificate_t *)cert;
-+}
-+
-+void bctbx_x509_certificate_free(bctbx_x509_certificate_t *cert) {
-+      mbedtls_x509_crt_free((mbedtls_x509_crt *)cert);
-+      bctbx_free(cert);
-+}
-+
-+int32_t bctbx_x509_certificate_get_info_string(char *buf,
-+                                               size_t size,
-+                                               const char *prefix,
-+                                               const bctbx_x509_certificate_t *cert) {
-+      return mbedtls_x509_crt_info(buf, size, prefix, (mbedtls_x509_crt *)cert);
-+}
-+
-+int32_t bctbx_x509_certificate_parse_file(bctbx_x509_certificate_t *cert, const char *path) {
-+      return mbedtls_x509_crt_parse_file((mbedtls_x509_crt *)cert, path);
-+}
-+
-+int32_t bctbx_x509_certificate_parse_path(bctbx_x509_certificate_t *cert, const char *path) {
-+      return mbedtls_x509_crt_parse_path((mbedtls_x509_crt *)cert, path);
-+}
-+
-+int32_t bctbx_x509_certificate_parse(bctbx_x509_certificate_t *cert, const char *buffer, size_t buffer_length) {
-+      return mbedtls_x509_crt_parse((mbedtls_x509_crt *)cert, (const unsigned char *)buffer, buffer_length);
-+}
-+
-+int32_t bctbx_x509_certificate_get_der_length(bctbx_x509_certificate_t *cert) {
-+      if (cert != NULL) {
-+              return (int32_t)((mbedtls_x509_crt *)cert)->raw.len;
-+      }
-+      return 0;
-+}
-+
-+int32_t bctbx_x509_certificate_get_der(bctbx_x509_certificate_t *cert, unsigned char *buffer, size_t buffer_length) {
-+      if (cert == NULL) {
-+              return BCTBX_ERROR_INVALID_CERTIFICATE;
-+      }
-+      if (((mbedtls_x509_crt *)cert)->raw.len >
-+          buffer_length - 1) { /* check buffer size is ok, +1 for the NULL termination added at the end */
-+              return BCTBX_ERROR_OUTPUT_BUFFER_TOO_SMALL;
-+      }
-+      memcpy(buffer, ((mbedtls_x509_crt *)cert)->raw.p, ((mbedtls_x509_crt *)cert)->raw.len);
-+      buffer[((mbedtls_x509_crt *)cert)->raw.len] = '\0'; /* add a null termination char */
-+
-+      return 0;
-+}
-+
-+int32_t bctbx_x509_certificate_get_subject_dn(const bctbx_x509_certificate_t *cert, char *dn, size_t dn_length) {
-+      if (cert == NULL) {
-+              return BCTBX_ERROR_INVALID_CERTIFICATE;
-+      }
-+
-+      return mbedtls_x509_dn_gets(dn, dn_length, &(((mbedtls_x509_crt *)cert)->subject));
-+}
-+
-+bctbx_list_t *bctbx_x509_certificate_get_subjects(const bctbx_x509_certificate_t *cert) {
-+      bctbx_list_t *ret = NULL;
-+
-+      if (cert != NULL) {
-+              mbedtls_x509_crt *mbedtls_cert =
-+                  (mbedtls_x509_crt *)cert; // bctbx_x509_certificate_t is just a cast of mbedtls_x509_crt
-+              /* parse subjectAltName if any */
-+              if (mbedtls_cert->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) {
-+                      const mbedtls_x509_sequence *cur = &(mbedtls_cert->subject_alt_names);
-+                      while (cur != NULL) {
-+                              ret = bctbx_list_append(ret, bctbx_strndup((const char *)cur->buf.p, (int)cur->buf.len));
-+                              cur = cur->next;
-+                      }
-+              }
-+
-+              /* Add Subject CN */
-+              const mbedtls_x509_name *subject = &(mbedtls_cert->subject);
-+              while (subject != NULL) { // Certificate should hold only one CN, but be permissive and parse several if they
-+                                            // are in the certificate
-+                      if (MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &subject->oid) ==
-+                          0) { // subject holds all the distinguished name in asn1 format, get the CN only
-+                              ret = bctbx_list_append(ret, bctbx_strndup((const char *)subject->val.p, (int)subject->val.len));
-+                      }
-+                      subject = subject->next;
-+              }
-+      }
-+      return ret;
-+}
-+
-+int32_t bctbx_x509_certificate_generate_selfsigned(const char *subject,
-+                                                   bctbx_x509_certificate_t *certificate,
-+                                                   bctbx_signing_key_t *pkey,
-+                                                   char *pem,
-+                                                   size_t pem_length) {
-+      mbedtls_entropy_context entropy;
-+      mbedtls_ctr_drbg_context ctr_drbg;
-+      int ret;
-+      mbedtls_mpi serial;
-+      mbedtls_x509write_cert crt;
-+      char file_buffer[8192];
-+      size_t file_buffer_len = 0;
-+      char formatted_subject[512];
-+
-+      /* subject may be a sip URL or linphone-dtls-default-identity, add CN= before it to make a valid name */
-+      memcpy(formatted_subject, "CN=", 3);
-+      memcpy(formatted_subject + 3, subject, strlen(subject) + 1); /* +1 to get the \0 termination */
-+
-+      mbedtls_entropy_init(&entropy);
-+      mbedtls_ctr_drbg_init(&ctr_drbg);
-+      if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0)) != 0) {
-+              bctbx_error("Certificate generation can't init ctr_drbg: [-0x%x]", -ret);
-+              return BCTBX_ERROR_CERTIFICATE_GENERATION_FAIL;
-+      }
-+
-+      /* generate 3072 bits RSA public/private key */
-+      if ((ret = mbedtls_pk_setup((mbedtls_pk_context *)pkey, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA))) != 0) {
-+              bctbx_error("Certificate generation can't init pk_ctx: [-0x%x]", -ret);
-+              return BCTBX_ERROR_CERTIFICATE_GENERATION_FAIL;
-+      }
-+
-+      if ((ret = mbedtls_rsa_gen_key(mbedtls_pk_rsa(*(mbedtls_pk_context *)pkey), mbedtls_ctr_drbg_random, &ctr_drbg,
-+                                     3072, 65537)) != 0) {
-+              bctbx_error("Certificate generation can't generate rsa key: [-0x%x]", -ret);
-+              return BCTBX_ERROR_CERTIFICATE_GENERATION_FAIL;
-+      }
-+
-+      /* if there is no pem pointer, don't save the key in pem format */
-+      if (pem != NULL) {
-+              mbedtls_pk_write_key_pem((mbedtls_pk_context *)pkey, (unsigned char *)file_buffer, 4096);
-+              file_buffer_len = strlen(file_buffer);
-+      }
-+
-+      /* generate the certificate */
-+      mbedtls_x509write_crt_init(&crt);
-+      mbedtls_x509write_crt_set_md_alg(&crt, MBEDTLS_MD_SHA256);
-+
-+      mbedtls_mpi_init(&serial);
-+
-+      if ((ret = mbedtls_mpi_read_string(&serial, 10, "1")) != 0) {
-+              bctbx_error("Certificate generation can't read serial mpi: [-0x%x]", -ret);
-+              return BCTBX_ERROR_CERTIFICATE_GENERATION_FAIL;
-+      }
-+
-+      mbedtls_x509write_crt_set_subject_key(&crt, (mbedtls_pk_context *)pkey);
-+      mbedtls_x509write_crt_set_issuer_key(&crt, (mbedtls_pk_context *)pkey);
-+
-+      if ((ret = mbedtls_x509write_crt_set_subject_name(&crt, formatted_subject)) != 0) {
-+              bctbx_error("Certificate generation can't set subject name: [-0x%x]", -ret);
-+              return BCTBX_ERROR_CERTIFICATE_GENERATION_FAIL;
-+      }
-+
-+      if ((ret = mbedtls_x509write_crt_set_issuer_name(&crt, formatted_subject)) != 0) {
-+              bctbx_error("Certificate generation can't set issuer name: -%x", -ret);
-+              return BCTBX_ERROR_CERTIFICATE_GENERATION_FAIL;
-+      }
-+
-+      if ((ret = mbedtls_x509write_crt_set_serial(&crt, &serial)) != 0) {
-+              bctbx_error("Certificate generation can't set serial: -%x", -ret);
-+              return BCTBX_ERROR_CERTIFICATE_GENERATION_FAIL;
-+      }
-+      mbedtls_mpi_free(&serial);
-+
-+      if ((ret = mbedtls_x509write_crt_set_validity(&crt, "20010101000000", "20300101000000")) != 0) {
-+              bctbx_error("Certificate generation can't set validity: -%x", -ret);
-+              return BCTBX_ERROR_CERTIFICATE_GENERATION_FAIL;
-+      }
-+
-+      /* store anyway certificate in pem format in a string even if we do not have file to write as we need it to get it
-+       * in a x509_crt structure */
-+      if ((ret = mbedtls_x509write_crt_pem(&crt, (unsigned char *)file_buffer + file_buffer_len, 4096,
-+                                           mbedtls_ctr_drbg_random, &ctr_drbg)) != 0) {
-+              bctbx_error("Certificate generation can't write crt pem: -%x", -ret);
-+              return BCTBX_ERROR_CERTIFICATE_WRITE_PEM;
-+      }
-+
-+      mbedtls_x509write_crt_free(&crt);
-+      mbedtls_ctr_drbg_free(&ctr_drbg);
-+      mbedtls_entropy_free(&entropy);
-+
-+      /* copy the key+cert in pem format into the given buffer */
-+      if (pem != NULL) {
-+              if (strlen(file_buffer) + 1 > pem_length) {
-+                      bctbx_error(
-+                          "Certificate generation can't copy the certificate to pem buffer: too short [%ld] but need [%ld] bytes",
-+                          (long)pem_length, (long)strlen(file_buffer));
-+                      return BCTBX_ERROR_OUTPUT_BUFFER_TOO_SMALL;
-+              }
-+              strncpy(pem, file_buffer, pem_length);
-+      }
-+
-+      /* +1 on strlen as crt_parse in PEM format, length must include the final \0 */
-+      if ((ret = mbedtls_x509_crt_parse((mbedtls_x509_crt *)certificate, (unsigned char *)file_buffer,
-+                                        strlen(file_buffer) + 1)) != 0) {
-+              bctbx_error("Certificate generation can't parse crt pem: -%x", -ret);
-+              return BCTBX_ERROR_CERTIFICATE_PARSE_PEM;
-+      }
-+
-+      return 0;
-+}
-+
-+int32_t bctbx_x509_certificate_get_signature_hash_function(const bctbx_x509_certificate_t *certificate,
-+                                                           bctbx_md_type_t *hash_algorithm) {
-+
-+      mbedtls_x509_crt *crt;
-+      if (certificate == NULL) return BCTBX_ERROR_INVALID_CERTIFICATE;
-+
-+      crt = (mbedtls_x509_crt *)certificate;
-+
-+      switch (crt->sig_md) {
-+              case MBEDTLS_MD_SHA1:
-+                      *hash_algorithm = BCTBX_MD_SHA1;
-+                      break;
-+
-+              case MBEDTLS_MD_SHA224:
-+                      *hash_algorithm = BCTBX_MD_SHA224;
-+                      break;
-+
-+              case MBEDTLS_MD_SHA256:
-+                      *hash_algorithm = BCTBX_MD_SHA256;
-+                      break;
-+
-+              case MBEDTLS_MD_SHA384:
-+                      *hash_algorithm = BCTBX_MD_SHA384;
-+                      break;
-+
-+              case MBEDTLS_MD_SHA512:
-+                      *hash_algorithm = BCTBX_MD_SHA512;
-+                      break;
-+
-+              default:
-+                      *hash_algorithm = BCTBX_MD_UNDEFINED;
-+                      return BCTBX_ERROR_UNSUPPORTED_HASH_FUNCTION;
-+                      break;
-+      }
-+
-+      return 0;
-+}
-+
-+/* maximum length of returned buffer will be 7(SHA-512 string)+3*hash_length(64)+null char = 200 bytes */
-+int32_t bctbx_x509_certificate_get_fingerprint(const bctbx_x509_certificate_t *certificate,
-+                                               char *fingerprint,
-+                                               size_t fingerprint_length,
-+                                               bctbx_md_type_t hash_algorithm) {
-+      unsigned char buffer[64] = {0}; /* buffer is max length of returned hash, which is 64 in case we use sha-512 */
-+      size_t hash_length = 0;
-+      const char *hash_alg_string = NULL;
-+      size_t fingerprint_size = 0;
-+      mbedtls_x509_crt *crt;
-+      mbedtls_md_type_t hash_id;
-+      if (certificate == NULL) return BCTBX_ERROR_INVALID_CERTIFICATE;
-+
-+      crt = (mbedtls_x509_crt *)certificate;
-+
-+      /* if there is a specified hash algorithm, use it*/
-+      switch (hash_algorithm) {
-+              case BCTBX_MD_SHA1:
-+                      hash_id = MBEDTLS_MD_SHA1;
-+                      break;
-+              case BCTBX_MD_SHA224:
-+                      hash_id = MBEDTLS_MD_SHA224;
-+                      break;
-+              case BCTBX_MD_SHA256:
-+                      hash_id = MBEDTLS_MD_SHA256;
-+                      break;
-+              case BCTBX_MD_SHA384:
-+                      hash_id = MBEDTLS_MD_SHA384;
-+                      break;
-+              case BCTBX_MD_SHA512:
-+                      hash_id = MBEDTLS_MD_SHA512;
-+                      break;
-+              default: /* nothing specified, use the hash algo used in the certificate signature */
-+                      hash_id = crt->sig_md;
-+                      break;
-+      }
-+
-+      /* fingerprint is a hash of the DER formated certificate (found in crt->raw.p) using the same hash function used by
-+       * certificate signature */
-+      switch (hash_id) {
-+              case MBEDTLS_MD_SHA1:
-+                      mbedtls_sha1(crt->raw.p, crt->raw.len, buffer);
-+                      hash_length = 20;
-+                      hash_alg_string = "SHA-1";
-+                      break;
-+
-+              case MBEDTLS_MD_SHA224:
-+                      mbedtls_sha256(crt->raw.p, crt->raw.len, buffer,
-+                                     1); /* last argument is a boolean, indicate to output sha-224 and not sha-256 */
-+                      hash_length = 28;
-+                      hash_alg_string = "SHA-224";
-+                      break;
-+
-+              case MBEDTLS_MD_SHA256:
-+                      mbedtls_sha256(crt->raw.p, crt->raw.len, buffer, 0);
-+                      hash_length = 32;
-+                      hash_alg_string = "SHA-256";
-+                      break;
-+
-+              case MBEDTLS_MD_SHA384:
-+                      mbedtls_sha512(crt->raw.p, crt->raw.len, buffer,
-+                                     1); /* last argument is a boolean, indicate to output sha-384 and not sha-512 */
-+                      hash_length = 48;
-+                      hash_alg_string = "SHA-384";
-+                      break;
-+
-+              case MBEDTLS_MD_SHA512:
-+                      mbedtls_sha512(crt->raw.p, crt->raw.len, buffer, 0);
-+                      hash_length = 64;
-+                      hash_alg_string = "SHA-512";
-+                      break;
-+
-+              default:
-+                      return BCTBX_ERROR_UNSUPPORTED_HASH_FUNCTION;
-+                      break;
-+      }
-+
-+      if (hash_length > 0) {
-+              size_t i;
-+              size_t fingerprint_index = strlen(hash_alg_string);
-+              char prefix = ' ';
-+
-+              fingerprint_size = fingerprint_index + 3 * hash_length + 1;
-+              /* fingerprint will be : hash_alg_string+' '+HEX : separated values: length is
-+               * strlen(hash_alg_string)+3*hash_lenght + 1 for null termination */
-+              if (fingerprint_length < fingerprint_size) {
-+                      return BCTBX_ERROR_OUTPUT_BUFFER_TOO_SMALL;
-+              }
-+
-+              snprintf(fingerprint, fingerprint_size, "%s", hash_alg_string);
-+              for (i = 0; i < hash_length; i++, fingerprint_index += 3) {
-+                      snprintf((char *)fingerprint + fingerprint_index, fingerprint_size - fingerprint_index, "%c%02X", prefix,
-+                               buffer[i]);
-+                      prefix = ':';
-+              }
-+              *(fingerprint + fingerprint_index) = '\0';
-+      }
-+
-+      return (int32_t)fingerprint_size;
-+}
-+
-+#define BCTBX_MAX_CERTIFICATE_FLAGS_STRING_LENGTH 256
-+int32_t bctbx_x509_certificate_flags_to_string(char *buffer, size_t buffer_size, uint32_t flags) {
-+      size_t i = 0;
-+      char outputString[BCTBX_MAX_CERTIFICATE_FLAGS_STRING_LENGTH];
-+
-+      if (flags & MBEDTLS_X509_BADCERT_EXPIRED)
-+              i += snprintf(outputString + i, BCTBX_MAX_CERTIFICATE_FLAGS_STRING_LENGTH - i, "expired ");
-+      if (flags & MBEDTLS_X509_BADCERT_REVOKED)
-+              i += snprintf(outputString + i, BCTBX_MAX_CERTIFICATE_FLAGS_STRING_LENGTH - i, "revoked ");
-+      if (flags & MBEDTLS_X509_BADCERT_CN_MISMATCH)
-+              i += snprintf(outputString + i, BCTBX_MAX_CERTIFICATE_FLAGS_STRING_LENGTH - i, "CN-mismatch ");
-+      if (flags & MBEDTLS_X509_BADCERT_NOT_TRUSTED)
-+              i += snprintf(outputString + i, BCTBX_MAX_CERTIFICATE_FLAGS_STRING_LENGTH - i, "not-trusted ");
-+      if (flags & MBEDTLS_X509_BADCERT_MISSING)
-+              i += snprintf(outputString + i, BCTBX_MAX_CERTIFICATE_FLAGS_STRING_LENGTH - i, "missing ");
-+      if (flags & MBEDTLS_X509_BADCERT_SKIP_VERIFY)
-+              i += snprintf(outputString + i, BCTBX_MAX_CERTIFICATE_FLAGS_STRING_LENGTH - i, "skip-verify ");
-+      if (flags & MBEDTLS_X509_BADCERT_OTHER)
-+              i += snprintf(outputString + i, BCTBX_MAX_CERTIFICATE_FLAGS_STRING_LENGTH - i, "other-reason ");
-+      if (flags & MBEDTLS_X509_BADCERT_FUTURE)
-+              i += snprintf(outputString + i, BCTBX_MAX_CERTIFICATE_FLAGS_STRING_LENGTH - i, "future-validity ");
-+      if (flags & MBEDTLS_X509_BADCERT_KEY_USAGE)
-+              i += snprintf(outputString + i, BCTBX_MAX_CERTIFICATE_FLAGS_STRING_LENGTH - i, "keyUsage-mismatch");
-+      if (flags & MBEDTLS_X509_BADCERT_EXT_KEY_USAGE)
-+              i += snprintf(outputString + i, BCTBX_MAX_CERTIFICATE_FLAGS_STRING_LENGTH - i, "extendedKeyUsage-mismatch ");
-+      if (flags & MBEDTLS_X509_BADCERT_NS_CERT_TYPE)
-+              i += snprintf(outputString + i, BCTBX_MAX_CERTIFICATE_FLAGS_STRING_LENGTH - i, "nsCertType-mismatch ");
-+      if (flags & MBEDTLS_X509_BADCERT_BAD_MD)
-+              i += snprintf(outputString + i, BCTBX_MAX_CERTIFICATE_FLAGS_STRING_LENGTH - i, "unacceptable-hash ");
-+      if (flags & MBEDTLS_X509_BADCERT_BAD_PK)
-+              i += snprintf(outputString + i, BCTBX_MAX_CERTIFICATE_FLAGS_STRING_LENGTH - i, "unacceptable-PK-alg ");
-+      if (flags & MBEDTLS_X509_BADCERT_BAD_KEY)
-+              i += snprintf(outputString + i, BCTBX_MAX_CERTIFICATE_FLAGS_STRING_LENGTH - i, "unacceptable-key ");
-+
-+      if (flags & MBEDTLS_X509_BADCRL_NOT_TRUSTED)
-+              i += snprintf(outputString + i, BCTBX_MAX_CERTIFICATE_FLAGS_STRING_LENGTH - i, "crl-not-trusted ");
-+      if (flags & MBEDTLS_X509_BADCRL_EXPIRED)
-+              i += snprintf(outputString + i, BCTBX_MAX_CERTIFICATE_FLAGS_STRING_LENGTH - i, "crl-expired ");
-+
-+      if (flags & MBEDTLS_X509_BADCRL_FUTURE)
-+              i += snprintf(outputString + i, BCTBX_MAX_CERTIFICATE_FLAGS_STRING_LENGTH - i, "crl-future ");
-+      if (flags & MBEDTLS_X509_BADCRL_BAD_MD)
-+              i += snprintf(outputString + i, BCTBX_MAX_CERTIFICATE_FLAGS_STRING_LENGTH - i, "crl-unacceptable-hash ");
-+      if (flags & MBEDTLS_X509_BADCRL_BAD_PK)
-+              i += snprintf(outputString + i, BCTBX_MAX_CERTIFICATE_FLAGS_STRING_LENGTH - i, "crl-unacceptable-PK-alg ");
-+      if (flags & MBEDTLS_X509_BADCRL_BAD_KEY)
-+              i += snprintf(outputString + i, BCTBX_MAX_CERTIFICATE_FLAGS_STRING_LENGTH - i, "crl-unacceptable-key ");
-+
-+      outputString[i] = '\0'; /* null terminate the string */
-+
-+      if (i + 1 > buffer_size) {
-+              return BCTBX_ERROR_OUTPUT_BUFFER_TOO_SMALL;
-+      }
-+
-+      strncpy(buffer, outputString, buffer_size);
-+
-+      return 0;
-+}
-+
-+int32_t bctbx_x509_certificate_set_flag(uint32_t *flags, uint32_t flags_to_set) {
-+      if (flags_to_set & BCTBX_CERTIFICATE_VERIFY_BADCERT_EXPIRED) *flags |= MBEDTLS_X509_BADCERT_EXPIRED;
-+      if (flags_to_set & BCTBX_CERTIFICATE_VERIFY_BADCERT_REVOKED) *flags |= MBEDTLS_X509_BADCERT_REVOKED;
-+      if (flags_to_set & BCTBX_CERTIFICATE_VERIFY_BADCERT_CN_MISMATCH) *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
-+      if (flags_to_set & BCTBX_CERTIFICATE_VERIFY_BADCERT_NOT_TRUSTED) *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
-+      if (flags_to_set & BCTBX_CERTIFICATE_VERIFY_BADCERT_MISSING) *flags |= MBEDTLS_X509_BADCERT_MISSING;
-+      if (flags_to_set & BCTBX_CERTIFICATE_VERIFY_BADCERT_SKIP_VERIFY) *flags |= MBEDTLS_X509_BADCERT_SKIP_VERIFY;
-+      if (flags_to_set & BCTBX_CERTIFICATE_VERIFY_BADCERT_OTHER) *flags |= MBEDTLS_X509_BADCERT_OTHER;
-+      if (flags_to_set & BCTBX_CERTIFICATE_VERIFY_BADCERT_FUTURE) *flags |= MBEDTLS_X509_BADCERT_FUTURE;
-+      if (flags_to_set & BCTBX_CERTIFICATE_VERIFY_BADCERT_KEY_USAGE) *flags |= MBEDTLS_X509_BADCERT_KEY_USAGE;
-+      if (flags_to_set & BCTBX_CERTIFICATE_VERIFY_BADCERT_EXT_KEY_USAGE) *flags |= MBEDTLS_X509_BADCERT_EXT_KEY_USAGE;
-+      if (flags_to_set & BCTBX_CERTIFICATE_VERIFY_BADCERT_NS_CERT_TYPE) *flags |= MBEDTLS_X509_BADCERT_NS_CERT_TYPE;
-+      if (flags_to_set & BCTBX_CERTIFICATE_VERIFY_BADCERT_BAD_MD) *flags |= MBEDTLS_X509_BADCERT_BAD_MD;
-+      if (flags_to_set & BCTBX_CERTIFICATE_VERIFY_BADCERT_BAD_PK) *flags |= MBEDTLS_X509_BADCERT_BAD_PK;
-+      if (flags_to_set & BCTBX_CERTIFICATE_VERIFY_BADCERT_BAD_KEY) *flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
-+
-+      if (flags_to_set & BCTBX_CERTIFICATE_VERIFY_BADCRL_NOT_TRUSTED) *flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
-+      if (flags_to_set & BCTBX_CERTIFICATE_VERIFY_BADCRL_EXPIRED) *flags |= MBEDTLS_X509_BADCRL_EXPIRED;
-+      if (flags_to_set & BCTBX_CERTIFICATE_VERIFY_BADCRL_FUTURE) *flags |= MBEDTLS_X509_BADCRL_FUTURE;
-+      if (flags_to_set & BCTBX_CERTIFICATE_VERIFY_BADCRL_BAD_MD) *flags |= MBEDTLS_X509_BADCRL_BAD_MD;
-+      if (flags_to_set & BCTBX_CERTIFICATE_VERIFY_BADCRL_BAD_PK) *flags |= MBEDTLS_X509_BADCRL_BAD_PK;
-+      if (flags_to_set & BCTBX_CERTIFICATE_VERIFY_BADCRL_BAD_KEY) *flags |= MBEDTLS_X509_BADCRL_BAD_KEY;
-+
-+      return 0;
-+}
-+
-+uint32_t bctbx_x509_certificate_remap_flag(uint32_t flags) {
-+      uint32_t ret = 0;
-+      if (flags & MBEDTLS_X509_BADCERT_EXPIRED) ret |= BCTBX_CERTIFICATE_VERIFY_BADCERT_EXPIRED;
-+      if (flags & MBEDTLS_X509_BADCERT_REVOKED) ret |= BCTBX_CERTIFICATE_VERIFY_BADCERT_REVOKED;
-+      if (flags & MBEDTLS_X509_BADCERT_CN_MISMATCH) ret |= BCTBX_CERTIFICATE_VERIFY_BADCERT_CN_MISMATCH;
-+      if (flags & MBEDTLS_X509_BADCERT_NOT_TRUSTED) ret |= BCTBX_CERTIFICATE_VERIFY_BADCERT_NOT_TRUSTED;
-+      if (flags & MBEDTLS_X509_BADCERT_MISSING) ret |= BCTBX_CERTIFICATE_VERIFY_BADCERT_MISSING;
-+      if (flags & MBEDTLS_X509_BADCERT_SKIP_VERIFY) ret |= BCTBX_CERTIFICATE_VERIFY_BADCERT_SKIP_VERIFY;
-+      if (flags & MBEDTLS_X509_BADCERT_FUTURE) ret |= BCTBX_CERTIFICATE_VERIFY_BADCERT_FUTURE;
-+      if (flags & MBEDTLS_X509_BADCERT_OTHER) ret |= BCTBX_CERTIFICATE_VERIFY_BADCERT_OTHER;
-+      if (flags & MBEDTLS_X509_BADCERT_KEY_USAGE) ret |= BCTBX_CERTIFICATE_VERIFY_BADCERT_KEY_USAGE;
-+      if (flags & MBEDTLS_X509_BADCERT_EXT_KEY_USAGE) ret |= BCTBX_CERTIFICATE_VERIFY_BADCERT_EXT_KEY_USAGE;
-+      if (flags & MBEDTLS_X509_BADCERT_NS_CERT_TYPE) ret |= BCTBX_CERTIFICATE_VERIFY_BADCERT_NS_CERT_TYPE;
-+      if (flags & MBEDTLS_X509_BADCERT_BAD_MD) ret |= BCTBX_CERTIFICATE_VERIFY_BADCERT_BAD_MD;
-+      if (flags & MBEDTLS_X509_BADCERT_BAD_PK) ret |= BCTBX_CERTIFICATE_VERIFY_BADCERT_BAD_PK;
-+      if (flags & MBEDTLS_X509_BADCERT_BAD_KEY) ret |= BCTBX_CERTIFICATE_VERIFY_BADCERT_BAD_KEY;
-+
-+      if (flags & MBEDTLS_X509_BADCRL_NOT_TRUSTED) ret |= BCTBX_CERTIFICATE_VERIFY_BADCRL_NOT_TRUSTED;
-+      if (flags & MBEDTLS_X509_BADCRL_EXPIRED) ret |= BCTBX_CERTIFICATE_VERIFY_BADCRL_EXPIRED;
-+      if (flags & MBEDTLS_X509_BADCRL_FUTURE) ret |= BCTBX_CERTIFICATE_VERIFY_BADCRL_FUTURE;
-+      if (flags & MBEDTLS_X509_BADCRL_BAD_MD) ret |= BCTBX_CERTIFICATE_VERIFY_BADCRL_BAD_MD;
-+      if (flags & MBEDTLS_X509_BADCRL_BAD_PK) ret |= BCTBX_CERTIFICATE_VERIFY_BADCRL_BAD_PK;
-+      if (flags & MBEDTLS_X509_BADCRL_BAD_KEY) ret |= BCTBX_CERTIFICATE_VERIFY_BADCRL_BAD_KEY;
-+
-+      return ret;
-+}
-+
-+int32_t bctbx_x509_certificate_unset_flag(uint32_t *flags, uint32_t flags_to_unset) {
-+      if (flags_to_unset & BCTBX_CERTIFICATE_VERIFY_BADCERT_EXPIRED) *flags &= ~MBEDTLS_X509_BADCERT_EXPIRED;
-+      if (flags_to_unset & BCTBX_CERTIFICATE_VERIFY_BADCERT_REVOKED) *flags &= ~MBEDTLS_X509_BADCERT_REVOKED;
-+      if (flags_to_unset & BCTBX_CERTIFICATE_VERIFY_BADCERT_CN_MISMATCH) *flags &= ~MBEDTLS_X509_BADCERT_CN_MISMATCH;
-+      if (flags_to_unset & BCTBX_CERTIFICATE_VERIFY_BADCERT_NOT_TRUSTED) *flags &= ~MBEDTLS_X509_BADCERT_NOT_TRUSTED;
-+      if (flags_to_unset & BCTBX_CERTIFICATE_VERIFY_BADCERT_MISSING) *flags &= ~MBEDTLS_X509_BADCERT_MISSING;
-+
-+      if (flags_to_unset & BCTBX_CERTIFICATE_VERIFY_BADCERT_SKIP_VERIFY) *flags &= ~MBEDTLS_X509_BADCERT_SKIP_VERIFY;
-+      if (flags_to_unset & BCTBX_CERTIFICATE_VERIFY_BADCERT_OTHER) *flags &= ~MBEDTLS_X509_BADCERT_OTHER;
-+      if (flags_to_unset & BCTBX_CERTIFICATE_VERIFY_BADCERT_FUTURE) *flags &= ~MBEDTLS_X509_BADCERT_FUTURE;
-+      if (flags_to_unset & BCTBX_CERTIFICATE_VERIFY_BADCERT_KEY_USAGE) *flags &= ~MBEDTLS_X509_BADCERT_KEY_USAGE;
-+      if (flags_to_unset & BCTBX_CERTIFICATE_VERIFY_BADCERT_EXT_KEY_USAGE) *flags &= ~MBEDTLS_X509_BADCERT_EXT_KEY_USAGE;
-+      if (flags_to_unset & BCTBX_CERTIFICATE_VERIFY_BADCERT_NS_CERT_TYPE) *flags &= ~MBEDTLS_X509_BADCERT_NS_CERT_TYPE;
-+      if (flags_to_unset & BCTBX_CERTIFICATE_VERIFY_BADCERT_BAD_MD) *flags &= ~MBEDTLS_X509_BADCERT_BAD_MD;
-+      if (flags_to_unset & BCTBX_CERTIFICATE_VERIFY_BADCERT_BAD_PK) *flags &= ~MBEDTLS_X509_BADCERT_BAD_PK;
-+      if (flags_to_unset & BCTBX_CERTIFICATE_VERIFY_BADCERT_BAD_KEY) *flags &= ~MBEDTLS_X509_BADCERT_BAD_KEY;
-+
-+      if (flags_to_unset & BCTBX_CERTIFICATE_VERIFY_BADCRL_NOT_TRUSTED) *flags &= ~MBEDTLS_X509_BADCRL_NOT_TRUSTED;
-+      if (flags_to_unset & BCTBX_CERTIFICATE_VERIFY_BADCRL_EXPIRED) *flags &= ~MBEDTLS_X509_BADCRL_EXPIRED;
-+
-+      if (flags_to_unset & BCTBX_CERTIFICATE_VERIFY_BADCRL_FUTURE) *flags &= ~MBEDTLS_X509_BADCRL_FUTURE;
-+      if (flags_to_unset & BCTBX_CERTIFICATE_VERIFY_BADCRL_BAD_MD) *flags &= ~MBEDTLS_X509_BADCRL_BAD_MD;
-+      if (flags_to_unset & BCTBX_CERTIFICATE_VERIFY_BADCRL_BAD_PK) *flags &= ~MBEDTLS_X509_BADCRL_BAD_PK;
-+      if (flags_to_unset & BCTBX_CERTIFICATE_VERIFY_BADCRL_BAD_KEY) *flags &= ~MBEDTLS_X509_BADCRL_BAD_KEY;
-+
-+      return 0;
-+}
-+
-+/*** Diffie-Hellman-Merkle ***/
-+/* initialise de DHM context according to requested algorithm */
-+bctbx_DHMContext_t *bctbx_CreateDHMContext(uint8_t DHMAlgo, uint8_t secretLength) {
-+      mbedtls_dhm_context *mbedtlsDhmContext;
-+
-+      /* create the context */
-+      bctbx_DHMContext_t *context = (bctbx_DHMContext_t *)malloc(sizeof(bctbx_DHMContext_t));
-+      memset(context, 0, sizeof(bctbx_DHMContext_t));
-+
-+      /* create the mbedtls context for DHM */
-+      mbedtlsDhmContext = (mbedtls_dhm_context *)malloc(sizeof(mbedtls_dhm_context));
-+      memset(mbedtlsDhmContext, 0, sizeof(mbedtls_dhm_context));
-+      context->cryptoModuleData = (void *)mbedtlsDhmContext;
-+
-+      /* initialise pointer to NULL to ensure safe call to free() when destroying context */
-+      context->secret = NULL;
-+      context->self = NULL;
-+      context->key = NULL;
-+      context->peer = NULL;
-+
-+      /* set parameters in the context */
-+      context->algo = DHMAlgo;
-+      context->secretLength = secretLength;
-+      switch (DHMAlgo) {
-+              case BCTBX_DHM_2048:
-+                      /* set P and G in the mbedtls context */
-+                      if ((mbedtls_mpi_read_string(&(mbedtlsDhmContext->P), 16, MBEDTLS_DHM_RFC3526_MODP_2048_P) != 0) ||
-+                          (mbedtls_mpi_read_string(&(mbedtlsDhmContext->G), 16, MBEDTLS_DHM_RFC3526_MODP_2048_G) != 0)) {
-+                              return NULL;
-+                      }
-+                      context->primeLength = 256;
-+                      mbedtlsDhmContext->len = 256;
-+                      break;
-+              case BCTBX_DHM_3072:
-+                      /* set P and G in the mbedtls context */
-+                      if ((mbedtls_mpi_read_string(&(mbedtlsDhmContext->P), 16, MBEDTLS_DHM_RFC3526_MODP_3072_P) != 0) ||
-+                          (mbedtls_mpi_read_string(&(mbedtlsDhmContext->G), 16, MBEDTLS_DHM_RFC3526_MODP_3072_G) != 0)) {
-+                              return NULL;
-+                      }
-+                      context->primeLength = 384;
-+                      mbedtlsDhmContext->len = 384;
-+                      break;
-+              default:
-+                      free(context);
-+                      return NULL;
-+                      break;
-+      }
-+
-+      return context;
-+}
-+
-+/* generate the random secret and compute the public value */
-+void bctbx_DHMCreatePublic(bctbx_DHMContext_t *context,
-+                           int (*rngFunction)(void *, uint8_t *, size_t),
-+                           void *rngContext) {
-+      /* get the mbedtls context */
-+      mbedtls_dhm_context *mbedtlsContext = (mbedtls_dhm_context *)context->cryptoModuleData;
-+
-+      /* allocate output buffer */
-+      context->self = (uint8_t *)malloc(context->primeLength * sizeof(uint8_t));
-+
-+      mbedtls_dhm_make_public(mbedtlsContext, context->secretLength, context->self, context->primeLength,
-+                              (int (*)(void *, unsigned char *, size_t))rngFunction, rngContext);
-+}
-+
-+/* compute secret - the ->peer field of context must have been set before calling this function */
-+void bctbx_DHMComputeSecret(bctbx_DHMContext_t *context,
-+                            int (*rngFunction)(void *, uint8_t *, size_t),
-+                            void *rngContext) {
-+      size_t keyLength;
-+      uint8_t sharedSecretBuffer[384]; /* longest shared secret available in these mode */
-+
-+      /* import the peer public value G^Y mod P in the mbedtls dhm context */
-+      mbedtls_dhm_read_public((mbedtls_dhm_context *)(context->cryptoModuleData), context->peer, context->primeLength);
-+
-+      /* compute the secret key */
-+      keyLength = context->primeLength; /* undocumented but this value seems to be in/out, so we must set it to the
-+                                           expected key length */
-+      context->key = (uint8_t *)malloc(keyLength * sizeof(uint8_t)); /* allocate and reset the key buffer */
-+      memset(context->key, 0, keyLength);
-+      mbedtls_dhm_calc_secret((mbedtls_dhm_context *)(context->cryptoModuleData), sharedSecretBuffer, 384, &keyLength,
-+                              (int (*)(void *, unsigned char *, size_t))rngFunction, rngContext);
-+      /* now copy the resulting secret in the correct place in buffer(result may actually miss some front zero bytes, real
-+       * length of output is now in keyLength but we want primeLength bytes) */
-+      memcpy(context->key + (context->primeLength - keyLength), sharedSecretBuffer, keyLength);
-+      bctbx_clean(sharedSecretBuffer, 384); /* purge secret from temporary buffer */
-+}
-+
-+/* clean DHM context */
-+void bctbx_DestroyDHMContext(bctbx_DHMContext_t *context) {
-+      if (context != NULL) {
-+              /* key and secret must be erased from memory and not just freed */
-+              if (context->secret != NULL) {
-+                      bctbx_clean(context->secret, context->secretLength);
-+                      free(context->secret);
-+              }
-+              free(context->self);
-+              if (context->key != NULL) {
-+                      bctbx_clean(context->key, context->primeLength);
-+                      free(context->key);
-+              }
-+              free(context->peer);
-+
-+              mbedtls_dhm_free((mbedtls_dhm_context *)context->cryptoModuleData);
-+              free(context->cryptoModuleData);
-+
-+              free(context);
-+      }
-+}
-+
-+/*** SSL Client ***/
-+
-+static int bctbx_ssl_sendrecv_callback_return_remap(int32_t ret_code) {
-+      switch (ret_code) {
-+              case BCTBX_ERROR_NET_WANT_READ:
-+                      return MBEDTLS_ERR_SSL_WANT_READ;
-+              case BCTBX_ERROR_NET_WANT_WRITE:
-+                      return MBEDTLS_ERR_SSL_WANT_WRITE;
-+              case BCTBX_ERROR_NET_CONN_RESET:
-+                      return MBEDTLS_ERR_NET_CONN_RESET;
-+              default:
-+                      return (int)ret_code;
-+      }
-+}
-+
-+/*
-+ * Default profile used to configure ssl_context, allow 1024 bits keys(while mbedtls default is 2048)
-+ */
-+const mbedtls_x509_crt_profile bctbx_x509_crt_profile_default = {
-+    /* 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,
-+};
-+
-+/** context **/
-+struct bctbx_ssl_context_struct {
-+      mbedtls_ssl_context ssl_ctx;
-+      int (*callback_cli_cert_function)(void *,
-+                                        bctbx_ssl_context_t *,
-+                                        const bctbx_list_t *); /**< pointer to the callback called to update client
-+                    certificate during handshake callback params are user_data, ssl_context, list of server certificate
-+                    subject alt name and CN (null terminated strings) */
-+      void *callback_cli_cert_data;                            /**< data passed to the client cert callback */
-+      int (*callback_send_function)(
-+          void *,
-+          const unsigned char *,
-+          size_t); /* callbacks args are: callback data, data buffer to be send, size of data buffer */
-+      int (*callback_recv_function)(void *,
-+                                    unsigned char *,
-+                                    size_t); /* args: callback data, data buffer to be read, size of data buffer */
-+      void *callback_sendrecv_data;          /**< data passed to send/recv callbacks */
-+      mbedtls_timing_delay_context timer;    /**< a timer is requested for DTLS */
-+};
-+
-+bctbx_ssl_context_t *bctbx_ssl_context_new(void) {
-+      bctbx_ssl_context_t *ssl_ctx = bctbx_malloc0(sizeof(bctbx_ssl_context_t));
-+      mbedtls_ssl_init(&(ssl_ctx->ssl_ctx));
-+      ssl_ctx->callback_cli_cert_function = NULL;
-+      ssl_ctx->callback_cli_cert_data = NULL;
-+      ssl_ctx->callback_send_function = NULL;
-+      ssl_ctx->callback_recv_function = NULL;
-+      ssl_ctx->callback_sendrecv_data = NULL;
-+      return ssl_ctx;
-+}
-+
-+void bctbx_ssl_context_free(bctbx_ssl_context_t *ssl_ctx) {
-+      mbedtls_ssl_free(&(ssl_ctx->ssl_ctx));
-+      bctbx_free(ssl_ctx);
-+}
-+
-+int32_t bctbx_ssl_close_notify(bctbx_ssl_context_t *ssl_ctx) {
-+      return mbedtls_ssl_close_notify(&(ssl_ctx->ssl_ctx));
-+}
-+
-+int32_t bctbx_ssl_session_reset(bctbx_ssl_context_t *ssl_ctx) {
-+      return mbedtls_ssl_session_reset(&(ssl_ctx->ssl_ctx));
-+}
-+
-+int32_t bctbx_ssl_write(bctbx_ssl_context_t *ssl_ctx, const unsigned char *buf, size_t buf_length) {
-+      int ret = mbedtls_ssl_write(&(ssl_ctx->ssl_ctx), buf, buf_length);
-+      /* remap some output code */
-+      if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
-+              ret = BCTBX_ERROR_NET_WANT_WRITE;
-+      }
-+      return ret;
-+}
-+
-+int32_t bctbx_ssl_read(bctbx_ssl_context_t *ssl_ctx, unsigned char *buf, size_t buf_length) {
-+      int ret = mbedtls_ssl_read(&(ssl_ctx->ssl_ctx), buf, buf_length);
-+      /* remap some output code */
-+      if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) {
-+              ret = BCTBX_ERROR_SSL_PEER_CLOSE_NOTIFY;
-+      }
-+      if (ret == MBEDTLS_ERR_SSL_WANT_READ) {
-+              ret = BCTBX_ERROR_NET_WANT_READ;
-+      }
-+      return ret;
-+}
-+
-+int32_t bctbx_ssl_handshake(bctbx_ssl_context_t *ssl_ctx) {
-+
-+      int ret = mbedtls_ssl_handshake(&(ssl_ctx->ssl_ctx));
-+
-+      /* remap some output codes */
-+      if (ret == MBEDTLS_ERR_SSL_WANT_READ) {
-+              ret = BCTBX_ERROR_NET_WANT_READ;
-+      } else if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
-+              ret = BCTBX_ERROR_NET_WANT_WRITE;
-+      }
-+
-+      return (ret);
-+}
-+
-+int bctbx_ssl_send_callback(void *data, const unsigned char *buffer, size_t buffer_length) {
-+      int ret = 0;
-+      /* data is the ssl_context which contains the actual callback and data */
-+      bctbx_ssl_context_t *ssl_ctx = (bctbx_ssl_context_t *)data;
-+
-+      ret = ssl_ctx->callback_send_function(ssl_ctx->callback_sendrecv_data, buffer, buffer_length);
-+
-+      return bctbx_ssl_sendrecv_callback_return_remap(ret);
-+}
-+
-+int bctbx_ssl_recv_callback(void *data, unsigned char *buffer, size_t buffer_length) {
-+      int ret = 0;
-+      /* data is the ssl_context which contains the actual callback and data */
-+      bctbx_ssl_context_t *ssl_ctx = (bctbx_ssl_context_t *)data;
-+
-+      ret = ssl_ctx->callback_recv_function(ssl_ctx->callback_sendrecv_data, buffer, buffer_length);
-+
-+      return bctbx_ssl_sendrecv_callback_return_remap(ret);
-+}
-+
-+void bctbx_ssl_set_io_callbacks(
-+    bctbx_ssl_context_t *ssl_ctx,
-+    void *callback_data,
-+    int (*callback_send_function)(void *, const unsigned char *, size_t), /* callbacks args are: callback data, data
-+                                                                             buffer to be send, size of data buffer */
-+    int (*callback_recv_function)(void *,
-+                                  unsigned char *,
-+                                  size_t)) { /* args: callback data, data buffer to be read, size of data buffer */
-+
-+      if (ssl_ctx == NULL) {
-+              return;
-+      }
-+
-+      ssl_ctx->callback_send_function = callback_send_function;
-+      ssl_ctx->callback_recv_function = callback_recv_function;
-+      ssl_ctx->callback_sendrecv_data = callback_data;
-+
-+      mbedtls_ssl_set_bio(&(ssl_ctx->ssl_ctx), ssl_ctx, bctbx_ssl_send_callback, bctbx_ssl_recv_callback, NULL);
-+}
-+
-+const bctbx_x509_certificate_t *bctbx_ssl_get_peer_certificate(bctbx_ssl_context_t *ssl_ctx) {
-+      return (const bctbx_x509_certificate_t *)mbedtls_ssl_get_peer_cert(&(ssl_ctx->ssl_ctx));
-+}
-+
-+const char *bctbx_ssl_get_ciphersuite(bctbx_ssl_context_t *ssl_ctx) {
-+      return mbedtls_ssl_get_ciphersuite(&(ssl_ctx->ssl_ctx));
-+}
-+
-+int bctbx_ssl_get_ciphersuite_id(const char *ciphersuite) {
-+      return mbedtls_ssl_get_ciphersuite_id(ciphersuite);
-+}
-+
-+const char *bctbx_ssl_get_version(bctbx_ssl_context_t *ssl_ctx) {
-+      return mbedtls_ssl_get_version(&(ssl_ctx->ssl_ctx));
-+}
-+
-+int32_t bctbx_ssl_set_hostname(bctbx_ssl_context_t *ssl_ctx, const char *hostname) {
-+      return mbedtls_ssl_set_hostname(&(ssl_ctx->ssl_ctx), hostname);
-+}
-+
-+/** DTLS SRTP functions **/
-+#ifdef HAVE_DTLS_SRTP
-+uint8_t bctbx_dtls_srtp_supported(void) {
-+      return 1;
-+}
-+
-+void bctbx_ssl_set_mtu(bctbx_ssl_context_t *ssl_ctx, uint16_t mtu) {
-+      // remove all headers to the given MTU:
-+      // DTLS header (mbedtls_ssl_get_record_expansion)
-+      // UDP header: 8 bytes
-+      // IP header(up to 40 bytes when usimg IP v6)
-+      mbedtls_ssl_set_mtu(&(ssl_ctx->ssl_ctx), (mtu - mbedtls_ssl_get_record_expansion(&(ssl_ctx->ssl_ctx)) - 8 - 40));
-+}
-+
-+static bctbx_dtls_srtp_profile_t bctbx_srtp_profile_mbedtls2bctoolbox(mbedtls_ssl_srtp_profile mbedtls_profile) {
-+      switch (mbedtls_profile) {
-+              case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80:
-+                      return BCTBX_SRTP_AES128_CM_HMAC_SHA1_80;
-+              case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32:
-+                      return BCTBX_SRTP_AES128_CM_HMAC_SHA1_32;
-+              case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80:
-+                      return BCTBX_SRTP_NULL_HMAC_SHA1_80;
-+              case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32:
-+                      return BCTBX_SRTP_NULL_HMAC_SHA1_32;
-+              default:
-+                      return BCTBX_SRTP_UNDEFINED;
-+      }
-+}
-+
-+static mbedtls_ssl_srtp_profile bctbx_srtp_profile_bctoolbox2mbedtls(bctbx_dtls_srtp_profile_t bctbx_profile) {
-+      switch (bctbx_profile) {
-+              case BCTBX_SRTP_AES128_CM_HMAC_SHA1_80:
-+                      return MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80;
-+              case BCTBX_SRTP_AES128_CM_HMAC_SHA1_32:
-+                      return MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32;
-+              case BCTBX_SRTP_NULL_HMAC_SHA1_80:
-+                      return MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80;
-+              case BCTBX_SRTP_NULL_HMAC_SHA1_32:
-+                      return MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32;
-+              default:
-+                      return MBEDTLS_TLS_SRTP_UNSET;
-+      }
-+}
-+
-+bctbx_dtls_srtp_profile_t bctbx_ssl_get_dtls_srtp_protection_profile(bctbx_ssl_context_t *ssl_ctx) {
-+      if (ssl_ctx == NULL) {
-+              return BCTBX_ERROR_INVALID_SSL_CONTEXT;
-+      }
-+
-+      mbedtls_dtls_srtp_info dtls_srtp_negotiation_result;
-+      mbedtls_ssl_get_dtls_srtp_negotiation_result(&(ssl_ctx->ssl_ctx), &dtls_srtp_negotiation_result);
-+      return bctbx_srtp_profile_mbedtls2bctoolbox(dtls_srtp_negotiation_result.chosen_dtls_srtp_profile);
-+};
-+
-+#else /* HAVE_DTLS_SRTP */
-+/* dummy DTLS api when not available */
-+uint8_t bctbx_dtls_srtp_supported(void) {
-+      return 0;
-+}
-+
-+void bctbx_ssl_set_mtu(bctbx_ssl_context_t *ssl_ctx, uint16_t mtu) {
-+}
-+
-+bctbx_dtls_srtp_profile_t bctbx_ssl_get_dtls_srtp_protection_profile(bctbx_ssl_context_t *ssl_ctx) {
-+      return BCTBX_SRTP_UNDEFINED;
-+}
-+
-+#endif /* HAVE_DTLS_SRTP */
-+
-+/** DTLS SRTP functions **/
-+
-+/** config **/
-+#ifdef HAVE_DTLS_SRTP
-+typedef struct bctbx_dtls_srtp_keys {
-+      uint8_t master_secret[48];          // master secret generated during handshake
-+      uint8_t randoms[64];                // client || server randoms, 32 bytes each
-+      mbedtls_tls_prf_types tls_prf_type; // prf function identification
-+} bctbx_dtls_srtp_keys_t;
-+#endif /* HAVE_DTLS_SRTP */
-+
-+struct bctbx_ssl_config_struct {
-+      mbedtls_ssl_config *ssl_config;         /**< actual config structure */
-+      uint8_t ssl_config_externally_provided; /**< a flag, on when the ssl_config was provided by callers and not created
-+                                                 threw the new function */
-+      int (*callback_cli_cert_function)(void *,
-+                                        bctbx_ssl_context_t *,
-+                                        const bctbx_list_t *); /**< pointer to the callback called to update client
-+                    certificate during handshake callback params are user_data, ssl_context, list of server certificate
-+                    subject alt name and CN (null terminated strings) */
-+      void *callback_cli_cert_data;                            /**< data passed to the client cert callback */
-+#ifdef HAVE_DTLS_SRTP
-+      mbedtls_ssl_srtp_profile
-+          dtls_srtp_mbedtls_profiles[MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH +
-+                                     1]; /**< list of supported DTLS-SRTP profiles, mbedtls won't hold the reference, so
-+                                            we must do it for the lifetime of the config structure. (size is +1 to add the
-+                                            list termination) */
-+      bctbx_dtls_srtp_keys_t dtls_srtp_keys; /**< Key material is stored during the handshake there and used after
-+                                                completion to generate the DTLS-SRTP shared secret */
-+#endif                                     /* HAVE_DTLS_SRTP */
-+};
-+
-+bctbx_ssl_config_t *bctbx_ssl_config_new(void) {
-+      bctbx_ssl_config_t *ssl_config = bctbx_malloc0(sizeof(bctbx_ssl_config_t));
-+      /* allocate and init anyway a ssl_config, it may be then crashed by an externally provided one */
-+      ssl_config->ssl_config = bctbx_malloc0(sizeof(mbedtls_ssl_config));
-+      ssl_config->ssl_config_externally_provided = 0;
-+      mbedtls_ssl_config_init(ssl_config->ssl_config);
-+
-+      ssl_config->callback_cli_cert_function = NULL;
-+      ssl_config->callback_cli_cert_data = NULL;
-+
-+      return ssl_config;
-+}
-+
-+bctbx_type_implementation_t bctbx_ssl_get_implementation_type(void) {
-+      return BCTBX_MBEDTLS;
-+}
-+
-+int32_t bctbx_ssl_config_set_crypto_library_config(bctbx_ssl_config_t *ssl_config, void *internal_config) {
-+      if (ssl_config == NULL) {
-+              return BCTBX_ERROR_INVALID_SSL_CONFIG;
-+      }
-+
-+      /* free already existing structure */
-+      if (ssl_config->ssl_config != NULL && ssl_config->ssl_config_externally_provided == 0) {
-+              mbedtls_ssl_config_free(ssl_config->ssl_config);
-+              bctbx_free(ssl_config->ssl_config);
-+      }
-+
-+      /* set the given pointer as the ssl_config context */
-+      ssl_config->ssl_config = (mbedtls_ssl_config *)internal_config;
-+
-+      /* set the flag in order to not free the mbedtls config when freing bctbx_ssl_config */
-+      ssl_config->ssl_config_externally_provided = 1;
-+
-+      return 0;
-+}
-+
-+void bctbx_ssl_config_free(bctbx_ssl_config_t *ssl_config) {
-+      if (ssl_config == NULL) {
-+              return;
-+      }
-+
-+      /* free mbedtls_ssl_config only when created internally */
-+      if (ssl_config->ssl_config_externally_provided == 0) {
-+              mbedtls_ssl_config_free(ssl_config->ssl_config);
-+              bctbx_free(ssl_config->ssl_config);
-+      }
-+
-+#ifdef HAVE_DTLS_SRTP
-+      bctbx_clean(ssl_config->dtls_srtp_keys.master_secret, sizeof(ssl_config->dtls_srtp_keys.master_secret));
-+      bctbx_clean(ssl_config->dtls_srtp_keys.randoms, sizeof(ssl_config->dtls_srtp_keys.randoms));
-+#endif /* HAVE_DTLS_SRTP */
-+
-+      bctbx_free(ssl_config);
-+}
-+
-+int32_t bctbx_ssl_config_defaults(bctbx_ssl_config_t *ssl_config, int endpoint, int transport) {
-+      int mbedtls_endpoint, mbedtls_transport, ret;
-+
-+      if (ssl_config == NULL) {
-+              return BCTBX_ERROR_INVALID_SSL_CONFIG;
-+      }
-+
-+      /* remap input arguments */
-+      switch (endpoint) {
-+              case BCTBX_SSL_IS_CLIENT:
-+                      mbedtls_endpoint = MBEDTLS_SSL_IS_CLIENT;
-+                      break;
-+              case BCTBX_SSL_IS_SERVER:
-+                      mbedtls_endpoint = MBEDTLS_SSL_IS_SERVER;
-+                      break;
-+              default:
-+                      return BCTBX_ERROR_INVALID_INPUT_DATA;
-+      }
-+
-+      switch (transport) {
-+              case BCTBX_SSL_TRANSPORT_STREAM:
-+                      mbedtls_transport = MBEDTLS_SSL_TRANSPORT_STREAM;
-+                      break;
-+              case BCTBX_SSL_TRANSPORT_DATAGRAM:
-+                      mbedtls_transport = MBEDTLS_SSL_TRANSPORT_DATAGRAM;
-+                      break;
-+              default:
-+                      return BCTBX_ERROR_INVALID_INPUT_DATA;
-+      }
-+
-+      ret = mbedtls_ssl_config_defaults(ssl_config->ssl_config, mbedtls_endpoint, mbedtls_transport,
-+                                        MBEDTLS_SSL_PRESET_DEFAULT);
-+
-+      if (ret < 0) {
-+              return ret;
-+      }
-+      if (transport == BCTBX_SSL_TRANSPORT_DATAGRAM) {
-+              // Set agressive repetition timer for DTLS handshake
-+              mbedtls_ssl_conf_handshake_timeout(ssl_config->ssl_config, 400, 15000);
-+      }
-+
-+      /* Set the default x509 security profile used for verification of all certificate in chain */
-+      mbedtls_ssl_conf_cert_profile(ssl_config->ssl_config, &bctbx_x509_crt_profile_default);
-+
-+      return ret;
-+}
-+
-+int32_t bctbx_ssl_config_set_endpoint(bctbx_ssl_config_t *ssl_config, int endpoint) {
-+      int mbedtls_endpoint;
-+      if (ssl_config == NULL) {
-+              return BCTBX_ERROR_INVALID_SSL_CONFIG;
-+      }
-+
-+      /* remap input arguments */
-+      switch (endpoint) {
-+              case BCTBX_SSL_IS_CLIENT:
-+                      mbedtls_endpoint = MBEDTLS_SSL_IS_CLIENT;
-+                      break;
-+              case BCTBX_SSL_IS_SERVER:
-+                      mbedtls_endpoint = MBEDTLS_SSL_IS_SERVER;
-+                      break;
-+              default:
-+                      return BCTBX_ERROR_INVALID_INPUT_DATA;
-+      }
-+
-+      mbedtls_ssl_conf_endpoint(ssl_config->ssl_config, mbedtls_endpoint);
-+
-+      return 0;
-+}
-+
-+int32_t bctbx_ssl_config_set_transport(bctbx_ssl_config_t *ssl_config, int transport) {
-+      int mbedtls_transport;
-+      if (ssl_config == NULL) {
-+              return BCTBX_ERROR_INVALID_SSL_CONFIG;
-+      }
-+
-+      /* remap input arguments */
-+      switch (transport) {
-+              case BCTBX_SSL_TRANSPORT_STREAM:
-+                      mbedtls_transport = MBEDTLS_SSL_TRANSPORT_STREAM;
-+                      break;
-+              case BCTBX_SSL_TRANSPORT_DATAGRAM:
-+                      mbedtls_transport = MBEDTLS_SSL_TRANSPORT_DATAGRAM;
-+                      break;
-+              default:
-+                      return BCTBX_ERROR_INVALID_INPUT_DATA;
-+      }
-+
-+      mbedtls_ssl_conf_transport(ssl_config->ssl_config, mbedtls_transport);
-+
-+      return 0;
-+}
-+
-+int32_t bctbx_ssl_config_set_ciphersuites(bctbx_ssl_config_t *ssl_config, const int *ciphersuites) {
-+      if (ssl_config == NULL) {
-+              return BCTBX_ERROR_INVALID_SSL_CONFIG;
-+      }
-+      /* remap input arguments */
-+      if (ciphersuites == NULL) {
-+              return BCTBX_ERROR_INVALID_INPUT_DATA;
-+      }
-+
-+      mbedtls_ssl_conf_ciphersuites(ssl_config->ssl_config, ciphersuites);
-+
-+      return 0;
-+}
-+
-+void *bctbx_ssl_config_get_private_config(bctbx_ssl_config_t *ssl_config) {
-+      return (void *)ssl_config->ssl_config;
-+}
-+
-+int32_t bctbx_ssl_config_set_authmode(bctbx_ssl_config_t *ssl_config, int authmode) {
-+      int mbedtls_authmode;
-+      if (ssl_config == NULL) {
-+              return BCTBX_ERROR_INVALID_SSL_CONFIG;
-+      }
-+
-+      /* remap input arguments */
-+      switch (authmode) {
-+              case BCTBX_SSL_VERIFY_NONE:
-+                      mbedtls_authmode = MBEDTLS_SSL_VERIFY_NONE;
-+                      break;
-+              case BCTBX_SSL_VERIFY_OPTIONAL:
-+                      mbedtls_authmode = MBEDTLS_SSL_VERIFY_OPTIONAL;
-+                      break;
-+              case BCTBX_SSL_VERIFY_REQUIRED:
-+                      mbedtls_authmode = MBEDTLS_SSL_VERIFY_REQUIRED;
-+                      break;
-+              default:
-+                      return BCTBX_ERROR_INVALID_SSL_AUTHMODE;
-+                      break;
-+      }
-+
-+      mbedtls_ssl_conf_authmode(ssl_config->ssl_config, mbedtls_authmode);
-+
-+      return 0;
-+}
-+
-+int32_t bctbx_ssl_config_set_rng(bctbx_ssl_config_t *ssl_config,
-+                                 int (*rng_function)(void *, unsigned char *, size_t),
-+                                 void *rng_context) {
-+      if (ssl_config == NULL) {
-+              return BCTBX_ERROR_INVALID_SSL_CONFIG;
-+      }
-+
-+      mbedtls_ssl_conf_rng(ssl_config->ssl_config, rng_function, rng_context);
-+
-+      return 0;
-+}
-+
-+int32_t
-+bctbx_ssl_config_set_callback_verify(bctbx_ssl_config_t *ssl_config,
-+                                     int (*callback_function)(void *, bctbx_x509_certificate_t *, int, uint32_t *),
-+                                     void *callback_data) {
-+      if (ssl_config == NULL) {
-+              return BCTBX_ERROR_INVALID_SSL_CONFIG;
-+      }
-+
-+      mbedtls_ssl_conf_verify(ssl_config->ssl_config,
-+                              (int (*)(void *, mbedtls_x509_crt *, int, uint32_t *))callback_function, callback_data);
-+
-+      return 0;
-+}
-+
-+int32_t
-+bctbx_ssl_config_set_callback_cli_cert(bctbx_ssl_config_t *ssl_config,
-+                                       int (*callback_function)(void *, bctbx_ssl_context_t *, const bctbx_list_t *),
-+                                       void *callback_data) {
-+      if (ssl_config == NULL) {
-+              return BCTBX_ERROR_INVALID_SSL_CONFIG;
-+      }
-+      ssl_config->callback_cli_cert_function = callback_function;
-+      ssl_config->callback_cli_cert_data = callback_data;
-+
-+      return 0;
-+}
-+
-+int32_t bctbx_ssl_config_set_ca_chain(bctbx_ssl_config_t *ssl_config, bctbx_x509_certificate_t *ca_chain) {
-+      if (ssl_config == NULL) {
-+              return BCTBX_ERROR_INVALID_SSL_CONFIG;
-+      }
-+      /* ca_crl (arg 3) is always set to null, add the functionnality if needed */
-+      mbedtls_ssl_conf_ca_chain(ssl_config->ssl_config, (mbedtls_x509_crt *)ca_chain, NULL);
-+
-+      return 0;
-+}
-+
-+int32_t bctbx_ssl_config_set_own_cert(bctbx_ssl_config_t *ssl_config,
-+                                      bctbx_x509_certificate_t *cert,
-+                                      bctbx_signing_key_t *key) {
-+      if (ssl_config == NULL) {
-+              return BCTBX_ERROR_INVALID_SSL_CONFIG;
-+      }
-+      return mbedtls_ssl_conf_own_cert(ssl_config->ssl_config, (mbedtls_x509_crt *)cert, (mbedtls_pk_context *)key);
-+}
-+
-+/** DTLS SRTP functions **/
-+#ifdef HAVE_DTLS_SRTP
-+/* key derivation code */
-+
-+/* This callback is executed during the DTLS handshake, extract the master secret and randoms needed to generate the
-+ * DTLS-SRTP keys The generation itself is performed after the handshake */
-+static int bctbx_ssl_dtls_srtp_key_derivation(void *key_ctx,
-+                                              const unsigned char *ms,
-+                                              BCTBX_UNUSED(const unsigned char *kb),
-+                                              BCTBX_UNUSED(size_t maclen),
-+                                              BCTBX_UNUSED(size_t keylen),
-+                                              BCTBX_UNUSED(size_t ivlen), // these params are useless for our purpose
-+                                              const unsigned char client_random[32],
-+                                              const unsigned char server_random[32],
-+                                              mbedtls_tls_prf_types tls_prf_type) {
-+
-+      bctbx_dtls_srtp_keys_t *keys = (bctbx_dtls_srtp_keys_t *)key_ctx;
-+      memcpy(keys->master_secret, ms, sizeof(keys->master_secret)); // copy the master secret
-+      memcpy(keys->randoms, client_random, 32);                     // the client and server random
-+      memcpy(keys->randoms + 32, server_random, 32);
-+      keys->tls_prf_type = tls_prf_type; // the prf id
-+      return (0);
-+}
-+
-+int32_t bctbx_ssl_get_dtls_srtp_key_material(bctbx_ssl_config_t *ssl_config, uint8_t *output, size_t *output_length) {
-+      int ret = 0;
-+      if (ssl_config == NULL) {
-+              return BCTBX_ERROR_INVALID_SSL_CONTEXT;
-+      }
-+
-+      // ret = mbedtls_ssl_get_dtls_srtp_key_material(&(ssl_ctx->ssl_ctx), (unsigned char *)output, *output_length,
-+      // output_length);
-+      ret = mbedtls_ssl_tls_prf(ssl_config->dtls_srtp_keys.tls_prf_type, ssl_config->dtls_srtp_keys.master_secret,
-+                                sizeof(ssl_config->dtls_srtp_keys.master_secret), "EXTRACTOR-dtls_srtp",
-+                                ssl_config->dtls_srtp_keys.randoms, sizeof(ssl_config->dtls_srtp_keys.randoms), output,
-+                                *output_length);
-+
-+      /* remap the output error code */
-+      if (ret == MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL) {
-+              return BCTBX_ERROR_OUTPUT_BUFFER_TOO_SMALL;
-+      }
-+
-+      return 0;
-+}
-+
-+int32_t bctbx_ssl_config_set_dtls_srtp_protection_profiles(bctbx_ssl_config_t *ssl_config,
-+                                                           const bctbx_dtls_srtp_profile_t *profiles,
-+                                                           size_t profiles_number) {
-+      size_t i;
-+      if (ssl_config == NULL) {
-+              return BCTBX_ERROR_INVALID_SSL_CONFIG;
-+      }
-+
-+      /* convert the profiles array into a mbedtls profiles array */
-+      for (i = 0; i < profiles_number && i < MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH;
-+           i++) { /* MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH profiles defined max */
-+              ssl_config->dtls_srtp_mbedtls_profiles[i] = bctbx_srtp_profile_bctoolbox2mbedtls(profiles[i]);
-+      }
-+      for (; i <= MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH;
-+           i++) { /* make sure to have a MBEDTLS_TLS_SRTP_UNSET terminated list and harmless values in the rest of the
-+                         array */
-+              ssl_config->dtls_srtp_mbedtls_profiles[i] = MBEDTLS_TLS_SRTP_UNSET;
-+      }
-+
-+      /* set the callback to compute the key material */
-+      mbedtls_ssl_conf_export_keys_ext_cb(ssl_config->ssl_config, bctbx_ssl_dtls_srtp_key_derivation,
-+                                          &(ssl_config->dtls_srtp_keys));
-+
-+      return mbedtls_ssl_conf_dtls_srtp_protection_profiles(
-+          ssl_config->ssl_config, ssl_config->dtls_srtp_mbedtls_profiles); // no profile number, list is UNSET terminated
-+}
-+
-+#else  /* HAVE_DTLS_SRTP */
-+int32_t bctbx_ssl_get_dtls_srtp_key_material(bctbx_ssl_config_t *ssl_ctx, uint8_t *output, size_t *output_length) {
-+      *output_length = 0;
-+      return BCTBX_ERROR_UNAVAILABLE_FUNCTION;
-+}
-+
-+int32_t bctbx_ssl_config_set_dtls_srtp_protection_profiles(bctbx_ssl_config_t *ssl_config,
-+                                                           const bctbx_dtls_srtp_profile_t *profiles,
-+                                                           size_t profiles_number) {
-+      return BCTBX_ERROR_UNAVAILABLE_FUNCTION;
-+}
-+#endif /* HAVE_DTLS_SRTP */
-+/** DTLS SRTP functions **/
-+
-+int32_t bctbx_ssl_context_setup(bctbx_ssl_context_t *ssl_ctx, bctbx_ssl_config_t *ssl_config) {
-+      int ret;
-+      /* Check validity of context and config */
-+      if (ssl_config == NULL) {
-+              return BCTBX_ERROR_INVALID_SSL_CONFIG;
-+      }
-+
-+      if (ssl_ctx == NULL) {
-+              return BCTBX_ERROR_INVALID_SSL_CONTEXT;
-+      }
-+
-+      /* apply all valids settings to the ssl_context */
-+      if (ssl_config->callback_cli_cert_function != NULL) {
-+              ssl_ctx->callback_cli_cert_function = ssl_config->callback_cli_cert_function;
-+              ssl_ctx->callback_cli_cert_data = ssl_config->callback_cli_cert_data;
-+      }
-+
-+#ifdef HAVE_DTLS_SRTP
-+      /* We do not use DTLS SRTP cookie, so we must set to NULL the callbacks. Cookies are used to prevent DoS attack but
-+       * our server is on only when during a brief period so we do not need this */
-+      mbedtls_ssl_conf_dtls_cookies(ssl_config->ssl_config, NULL, NULL, NULL);
-+#endif /* HAVE_DTLS_SRTP */
-+
-+      ret = mbedtls_ssl_setup(&(ssl_ctx->ssl_ctx), ssl_config->ssl_config);
-+      if (ret != 0) return ret;
-+
-+      /* for DTLS handshake, we must set a timer callback */
-+      mbedtls_ssl_set_timer_cb(&(ssl_ctx->ssl_ctx), &(ssl_ctx->timer), mbedtls_timing_set_delay,
-+                               mbedtls_timing_get_delay);
-+
-+      return ret;
-+}
-+
-+/*****************************************************************************/
-+/***** Hashing                                                           *****/
-+/*****************************************************************************/
-+/*
-+ * @brief HMAC-SHA512 wrapper
-+ * @param[in]         key             HMAC secret key
-+ * @param[in]         keyLength       HMAC key length
-+ * @param[in] input           Input data buffer
-+ * @param[in]   inputLength   Input data length
-+ * @param[in] hmacLength      Length of output required in bytes, HMAC output is truncated to the hmacLength left bytes.
-+ * 64 bytes maximum
-+ * @param[out]        output          Output data buffer.
-+ *
-+ */
-+void bctbx_hmacSha512(const uint8_t *key,
-+                      size_t keyLength,
-+                      const uint8_t *input,
-+                      size_t inputLength,
-+                      uint8_t hmacLength,
-+                      uint8_t *output) {
-+      uint8_t hmacOutput[64];
-+      mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512), key, keyLength, input, inputLength, hmacOutput);
-+
-+      /* check output length, can't be>64 */
-+      if (hmacLength > 64) {
-+              memcpy(output, hmacOutput, 64);
-+      } else {
-+              memcpy(output, hmacOutput, hmacLength);
-+      }
-+}
-+
-+/*
-+ * @brief HMAC-SHA384 wrapper
-+ * @param[in]         key             HMAC secret key
-+ * @param[in]         keyLength       HMAC key length
-+ * @param[in] input           Input data buffer
-+ * @param[in]   inputLength   Input data length
-+ * @param[in] hmacLength      Length of output required in bytes, HMAC output is truncated to the hmacLength left bytes.
-+ * 48 bytes maximum
-+ * @param[out]        output          Output data buffer.
-+ *
-+ */
-+void bctbx_hmacSha384(const uint8_t *key,
-+                      size_t keyLength,
-+                      const uint8_t *input,
-+                      size_t inputLength,
-+                      uint8_t hmacLength,
-+                      uint8_t *output) {
-+      uint8_t hmacOutput[48];
-+      mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA384), key, keyLength, input, inputLength, hmacOutput);
-+
-+      /* check output length, can't be>48 */
-+      if (hmacLength > 48) {
-+              memcpy(output, hmacOutput, 48);
-+      } else {
-+              memcpy(output, hmacOutput, hmacLength);
-+      }
-+}
-+
-+/*
-+ * brief HMAC-SHA256 wrapper
-+ * @param[in]         key                     HMAC secret key
-+ * @param[in]         keyLength       HMAC key length
-+ * @param[in] input           Input data buffer
-+ * @param[in]   inputLength   Input data length
-+ * @param[in] hmacLength      Length of output required in bytes, HMAC output is truncated to the hmacLength left bytes.
-+ * 32 bytes maximum
-+ * @param[out]        output          Output data buffer.
-+ *
-+ */
-+void bctbx_hmacSha256(const uint8_t *key,
-+                      size_t keyLength,
-+                      const uint8_t *input,
-+                      size_t inputLength,
-+                      uint8_t hmacLength,
-+                      uint8_t *output) {
-+      uint8_t hmacOutput[32];
-+      mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), key, keyLength, input, inputLength, hmacOutput);
-+
-+      /* check output length, can't be>32 */
-+      if (hmacLength > 32) {
-+              memcpy(output, hmacOutput, 32);
-+      } else {
-+              memcpy(output, hmacOutput, hmacLength);
-+      }
-+}
-+
-+/*
-+ * @brief SHA512 wrapper
-+ * @param[in] input           Input data buffer
-+ * @param[in]   inputLength   Input data length in bytes
-+ * @param[in] hashLength      Length of output required in bytes, Output is truncated to the hashLength left bytes. 64
-+ * bytes maximum
-+ * @param[out]        output          Output data buffer.
-+ *
-+ */
-+void bctbx_sha512(const uint8_t *input, size_t inputLength, uint8_t hashLength, uint8_t *output) {
-+      uint8_t hashOutput[64];
-+      mbedtls_sha512(input, inputLength, hashOutput, 0);
-+
-+      /* check output length, can't be>64 */
-+      if (hashLength > 64) {
-+              memcpy(output, hashOutput, 64);
-+      } else {
-+              memcpy(output, hashOutput, hashLength);
-+      }
-+}
-+
-+/*
-+ * @brief SHA384 wrapper
-+ * @param[in] input           Input data buffer
-+ * @param[in]   inputLength   Input data length in bytes
-+ * @param[in] hashLength      Length of output required in bytes, Output is truncated to the hashLength left bytes. 48
-+ * bytes maximum
-+ * @param[out]        output          Output data buffer.
-+ *
-+ */
-+void bctbx_sha384(const uint8_t *input, size_t inputLength, uint8_t hashLength, uint8_t *output) {
-+      uint8_t hashOutput[64];
-+      mbedtls_sha512(input, inputLength, hashOutput, 1); /* last param to one to select SHA384 and not SHA512 */
-+
-+      /* check output length, can't be>48 */
-+      if (hashLength > 48) {
-+              memcpy(output, hashOutput, 48);
-+      } else {
-+              memcpy(output, hashOutput, hashLength);
-+      }
-+}
-+
-+/*
-+ * @brief SHA256 wrapper
-+ * @param[in] input           Input data buffer
-+ * @param[in]   inputLength   Input data length in bytes
-+ * @param[in] hashLength      Length of output required in bytes, Output is truncated to the hashLength left bytes. 32
-+ * bytes maximum
-+ * @param[out]        output          Output data buffer.
-+ *
-+ */
-+void bctbx_sha256(const uint8_t *input, size_t inputLength, uint8_t hashLength, uint8_t *output) {
-+      uint8_t hashOutput[32];
-+      mbedtls_sha256(input, inputLength, hashOutput, 0); /* last param to zero to select SHA256 and not SHA224 */
-+
-+      /* check output length, can't be>32 */
-+      if (hashLength > 32) {
-+              memcpy(output, hashOutput, 32);
-+      } else {
-+              memcpy(output, hashOutput, hashLength);
-+      }
-+}
-+
-+/*
-+ * @brief HMAC-SHA1 wrapper
-+ * @param[in]         key                     HMAC secret key
-+ * @param[in]         keyLength       HMAC key length
-+ * @param[in] input           Input data buffer
-+ * @param[in]   inputLength   Input data length
-+ * @param[in] hmacLength      Length of output required in bytes, HMAC output is truncated to the hmacLength left bytes.
-+ * 20 bytes maximum
-+ * @param[out]        output          Output data buffer.
-+ *
-+ */
-+void bctbx_hmacSha1(const uint8_t *key,
-+                    size_t keyLength,
-+                    const uint8_t *input,
-+                    size_t inputLength,
-+                    uint8_t hmacLength,
-+                    uint8_t *output) {
-+      uint8_t hmacOutput[20];
-+
-+      mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), key, keyLength, input, inputLength, hmacOutput);
-+
-+      /* check output length, can't be>20 */
-+      if (hmacLength > 20) {
-+              memcpy(output, hmacOutput, 20);
-+      } else {
-+              memcpy(output, hmacOutput, hmacLength);
-+      }
-+}
-+
-+/**
-+ * @brief MD5 wrapper
-+ * output = md5(input)
-+ * @param[in] input           Input data buffer
-+ * @param[in]   inputLength   Input data length in bytes
-+ * @param[out]        output          Output data buffer.
-+ *
-+ */
-+void bctbx_md5(const uint8_t *input, size_t inputLength, uint8_t output[16]) {
-+      mbedtls_md5(input, inputLength, output);
-+}
-+
-+/*****************************************************************************/
-+/***** Encryption/Decryption                                             *****/
-+/*****************************************************************************/
-+/***** GCM *****/
-+/**
-+ * @Brief AES-GCM encrypt and tag buffer
-+ *
-+ * @param[in] key                                                     Encryption key
-+ * @param[in] keyLength                                       Key buffer length, in bytes, must be 16,24 or 32
-+ * @param[in] plainText                                       Buffer to be encrypted
-+ * @param[in] plainTextLength                         Length in bytes of buffer to be encrypted
-+ * @param[in] authenticatedData                       Buffer holding additional data to be used in tag computation
-+ * @param[in] authenticatedDataLength         Additional data length in bytes
-+ * @param[in] initializationVector            Buffer holding the initialisation vector
-+ * @param[in] initializationVectorLength      Initialisation vector length in bytes
-+ * @param[out]        tag                                                     Buffer holding the generated tag
-+ * @param[in] tagLength                                       Requested length for the generated tag
-+ * @param[out]        output                                          Buffer holding the output, shall be at least the length of plainText buffer
-+ */
-+int32_t bctbx_aes_gcm_encrypt_and_tag(const uint8_t *key,
-+                                      size_t keyLength,
-+                                      const uint8_t *plainText,
-+                                      size_t plainTextLength,
-+                                      const uint8_t *authenticatedData,
-+                                      size_t authenticatedDataLength,
-+                                      const uint8_t *initializationVector,
-+                                      size_t initializationVectorLength,
-+                                      uint8_t *tag,
-+                                      size_t tagLength,
-+                                      uint8_t *output) {
-+      mbedtls_gcm_context gcmContext;
-+      int ret;
-+
-+      mbedtls_gcm_init(&gcmContext);
-+      ret = mbedtls_gcm_setkey(&gcmContext, MBEDTLS_CIPHER_ID_AES, key, (unsigned int)keyLength * 8);
-+      if (ret != 0) return ret;
-+
-+      ret = mbedtls_gcm_crypt_and_tag(&gcmContext, MBEDTLS_GCM_ENCRYPT, plainTextLength, initializationVector,
-+                                      initializationVectorLength, authenticatedData, authenticatedDataLength, plainText,
-+                                      output, tagLength, tag);
-+      mbedtls_gcm_free(&gcmContext);
-+
-+      return ret;
-+}
-+
-+/**
-+ * @Brief AES-GCM decrypt, compute authentication tag and compare it to the one provided
-+ *
-+ * @param[in] key                                                     Encryption key
-+ * @param[in] keyLength                                       Key buffer length, in bytes, must be 16,24 or 32
-+ * @param[in] cipherText                                      Buffer to be decrypted
-+ * @param[in] cipherTextLength                        Length in bytes of buffer to be decrypted
-+ * @param[in] authenticatedData                       Buffer holding additional data to be used in auth tag computation
-+ * @param[in] authenticatedDataLength         Additional data length in bytes
-+ * @param[in] initializationVector            Buffer holding the initialisation vector
-+ * @param[in] initializationVectorLength      Initialisation vector length in bytes
-+ * @param[in] tag                                                     Buffer holding the authentication tag
-+ * @param[in] tagLength                                       Length in bytes for the authentication tag
-+ * @param[out]        output                                          Buffer holding the output, shall be at least the length of cipherText buffer
-+ *
-+ * @return 0 on succes, BCTBX_ERROR_AUTHENTICATION_FAILED if tag doesn't match or mbedtls error code
-+ */
-+int32_t bctbx_aes_gcm_decrypt_and_auth(const uint8_t *key,
-+                                       size_t keyLength,
-+                                       const uint8_t *cipherText,
-+                                       size_t cipherTextLength,
-+                                       const uint8_t *authenticatedData,
-+                                       size_t authenticatedDataLength,
-+                                       const uint8_t *initializationVector,
-+                                       size_t initializationVectorLength,
-+                                       const uint8_t *tag,
-+                                       size_t tagLength,
-+                                       uint8_t *output) {
-+      mbedtls_gcm_context gcmContext;
-+      int ret;
-+
-+      mbedtls_gcm_init(&gcmContext);
-+      ret = mbedtls_gcm_setkey(&gcmContext, MBEDTLS_CIPHER_ID_AES, key, (unsigned int)keyLength * 8);
-+      if (ret != 0) return ret;
-+
-+      ret = mbedtls_gcm_auth_decrypt(&gcmContext, cipherTextLength, initializationVector, initializationVectorLength,
-+                                     authenticatedData, authenticatedDataLength, tag, tagLength, cipherText, output);
-+      mbedtls_gcm_free(&gcmContext);
-+
-+      if (ret == MBEDTLS_ERR_GCM_AUTH_FAILED) {
-+              return BCTBX_ERROR_AUTHENTICATION_FAILED;
-+      }
-+
-+      return ret;
-+}
-+
-+/**
-+ * @Brief create and initialise an AES-GCM encryption context
-+ *
-+ * @param[in] key                                                     encryption key
-+ * @param[in] keyLength                                       key buffer length, in bytes, must be 16,24 or 32
-+ * @param[in] authenticatedData                       Buffer holding additional data to be used in tag computation (can be NULL)
-+ * @param[in] authenticatedDataLength         additional data length in bytes (can be 0)
-+ * @param[in] initializationVector            Buffer holding the initialisation vector
-+ * @param[in] initializationVectorLength      Initialisation vector length in bytes
-+ * @param[in] mode                                            Operation mode : BCTBX_GCM_ENCRYPT or BCTBX_GCM_DECRYPT
-+ *
-+ * @return 0 on success, crypto library error code otherwise
-+ */
-+bctbx_aes_gcm_context_t *bctbx_aes_gcm_context_new(const uint8_t *key,
-+                                                   size_t keyLength,
-+                                                   const uint8_t *authenticatedData,
-+                                                   size_t authenticatedDataLength,
-+                                                   const uint8_t *initializationVector,
-+                                                   size_t initializationVectorLength,
-+                                                   uint8_t mode) {
-+
-+      int ret = 0;
-+      int mbedtls_mode;
-+      mbedtls_gcm_context *ctx = NULL;
-+
-+      if (mode == BCTBX_GCM_ENCRYPT) {
-+              mbedtls_mode = MBEDTLS_GCM_ENCRYPT;
-+      } else if (mode == BCTBX_GCM_DECRYPT) {
-+              mbedtls_mode = MBEDTLS_GCM_DECRYPT;
-+      } else {
-+              return NULL;
-+      }
-+
-+      ctx = bctbx_malloc0(sizeof(mbedtls_gcm_context));
-+      mbedtls_gcm_init(ctx);
-+      ret = mbedtls_gcm_setkey(ctx, MBEDTLS_CIPHER_ID_AES, key, (unsigned int)keyLength * 8);
-+      if (ret != 0) {
-+              bctbx_free(ctx);
-+              return NULL;
-+      }
-+
-+      ret = mbedtls_gcm_starts(ctx, mbedtls_mode, initializationVector, initializationVectorLength, authenticatedData,
-+                               authenticatedDataLength);
-+      if (ret != 0) {
-+              bctbx_free(ctx);
-+              return NULL;
-+      }
-+
-+      return (bctbx_aes_gcm_context_t *)ctx;
-+}
-+
-+/**
-+ * @Brief AES-GCM encrypt or decrypt a chunk of data
-+ *
-+ * @param[in/out]     context                 a context already initialized using bctbx_aes_gcm_context_new
-+ * @param[in]         input                   buffer holding the input data
-+ * @param[in]         inputLength             lenght of the input data
-+ * @param[out]                output                  buffer to store the output data (same length as input one)
-+ *
-+ * @return 0 on success, crypto library error code otherwise
-+ */
-+int32_t bctbx_aes_gcm_process_chunk(bctbx_aes_gcm_context_t *context,
-+                                    const uint8_t *input,
-+                                    size_t inputLength,
-+                                    uint8_t *output) {
-+      return mbedtls_gcm_update((mbedtls_gcm_context *)context, inputLength, input, output);
-+}
-+
-+/**
-+ * @Brief Conclude a AES-GCM encryption stream, generate tag if requested, free resources
-+ *
-+ * @param[in/out]     context                 a context already initialized using bctbx_aes_gcm_context_new
-+ * @param[out]                tag                             a buffer to hold the authentication tag. Can be NULL if tagLength is 0
-+ * @param[in]         tagLength               length of reqested authentication tag, max 16
-+ *
-+ * @return 0 on success, crypto library error code otherwise
-+ */
-+int32_t bctbx_aes_gcm_finish(bctbx_aes_gcm_context_t *context, uint8_t *tag, size_t tagLength) {
-+      int ret;
-+
-+      ret = mbedtls_gcm_finish((mbedtls_gcm_context *)context, tag, tagLength);
-+      mbedtls_gcm_free((mbedtls_gcm_context *)context);
-+
-+      bctbx_free(context);
-+
-+      return ret;
-+}
-+
-+/*
-+ * @brief Wrapper for AES-128 in CFB128 mode encryption
-+ * Both key and IV must be 16 bytes long, IV is not updated
-+ *
-+ * @param[in] key                     encryption key, 128 bits long
-+ * @param[in] IV                      Initialisation vector, 128 bits long, is not modified by this function.
-+ * @param[in] input           Input data buffer
-+ * @param[in] inputLength     Input data length
-+ * @param[out]        output          Output data buffer
-+ *
-+ */
-+void bctbx_aes128CfbEncrypt(
-+    const uint8_t *key, const uint8_t *IV, const uint8_t *input, size_t inputLength, uint8_t *output) {
-+      uint8_t IVbuffer[16];
-+      size_t iv_offset = 0; /* is not used by us but needed and updated by mbedtls */
-+      mbedtls_aes_context context;
-+      memset(&context, 0, sizeof(mbedtls_aes_context));
-+
-+      /* make a local copy of IV which is modified by the mbedtls AES-CFB function */
-+      memcpy(IVbuffer, IV, 16 * sizeof(uint8_t));
-+
-+      /* initialise the aes context and key */
-+      mbedtls_aes_setkey_enc(&context, key, 128);
-+
-+      /* encrypt */
-+      mbedtls_aes_crypt_cfb128(&context, MBEDTLS_AES_ENCRYPT, inputLength, &iv_offset, IVbuffer, input, output);
-+}
-+
-+/*
-+ * @brief Wrapper for AES-128 in CFB128 mode decryption
-+ * Both key and IV must be 16 bytes long, IV is not updated
-+ *
-+ * @param[in] key                     decryption key, 128 bits long
-+ * @param[in] IV                      Initialisation vector, 128 bits long, is not modified by this function.
-+ * @param[in] input           Input data buffer
-+ * @param[in] inputLength     Input data length
-+ * @param[out]        output          Output data buffer
-+ *
-+ */
-+void bctbx_aes128CfbDecrypt(
-+    const uint8_t *key, const uint8_t *IV, const uint8_t *input, size_t inputLength, uint8_t *output) {
-+      uint8_t IVbuffer[16];
-+      size_t iv_offset = 0; /* is not used by us but needed and updated by mbedtls */
-+      mbedtls_aes_context context;
-+      memset(&context, 0, sizeof(mbedtls_aes_context));
-+
-+      /* make a local copy of IV which is modified by the mbedtls AES-CFB function */
-+      memcpy(IVbuffer, IV, 16 * sizeof(uint8_t));
-+
-+      /* initialise the aes context and key - use the aes_setkey_enc function as requested by the documentation of
-+       * aes_crypt_cfb128 function */
-+      mbedtls_aes_setkey_enc(&context, key, 128);
-+
-+      /* encrypt */
-+      mbedtls_aes_crypt_cfb128(&context, MBEDTLS_AES_DECRYPT, inputLength, &iv_offset, IVbuffer, input, output);
-+}
-+
-+/*
-+ * @brief Wrapper for AES-256 in CFB128 mode encryption
-+ * The key must be 32 bytes long and the IV must be 16 bytes long, IV is not updated
-+ *
-+ * @param[in] key                     encryption key, 256 bits long
-+ * @param[in] IV                      Initialisation vector, 128 bits long, is not modified by this function.
-+ * @param[in] input           Input data buffer
-+ * @param[in] inputLength     Input data length
-+ * @param[out]        output          Output data buffer
-+ *
-+ */
-+void bctbx_aes256CfbEncrypt(
-+    const uint8_t *key, const uint8_t *IV, const uint8_t *input, size_t inputLength, uint8_t *output) {
-+      uint8_t IVbuffer[16];
-+      size_t iv_offset = 0;
-+      mbedtls_aes_context context;
-+
-+      memcpy(IVbuffer, IV, 16 * sizeof(uint8_t));
-+      memset(&context, 0, sizeof(mbedtls_aes_context));
-+      mbedtls_aes_setkey_enc(&context, key, 256);
-+
-+      /* encrypt */
-+      mbedtls_aes_crypt_cfb128(&context, MBEDTLS_AES_ENCRYPT, inputLength, &iv_offset, IVbuffer, input, output);
-+}
-+
-+/*
-+ * @brief Wrapper for AES-256 in CFB128 mode decryption
-+ * The key must be 32 bytes long and the IV must be 16 bytes long, IV is not updated
-+ *
-+ * @param[in] key                     decryption key, 256 bits long
-+ * @param[in] IV                      Initialisation vector, 128 bits long, is not modified by this function.
-+ * @param[in] input           Input data buffer
-+ * @param[in] inputLength     Input data length
-+ * @param[out]        output          Output data buffer
-+ *
-+ */
-+void bctbx_aes256CfbDecrypt(
-+    const uint8_t *key, const uint8_t *IV, const uint8_t *input, size_t inputLength, uint8_t *output) {
-+      uint8_t IVbuffer[16];
-+      size_t iv_offset = 0;
-+      mbedtls_aes_context context;
-+
-+      memcpy(IVbuffer, IV, 16 * sizeof(uint8_t));
-+      memset(&context, 0, sizeof(mbedtls_aes_context));
-+      mbedtls_aes_setkey_enc(&context, key, 256);
-+
-+      /* decrypt */
-+      mbedtls_aes_crypt_cfb128(&context, MBEDTLS_AES_DECRYPT, inputLength, &iv_offset, IVbuffer, input, output);
-+}
-diff --git a/src/crypto/mbedtls.c b/src/crypto/mbedtls.c
-index df68ca9..29797e4 100644
---- a/src/crypto/mbedtls.c
-+++ b/src/crypto/mbedtls.c
-@@ -110,14 +110,25 @@ int32_t bctbx_base64_decode(unsigned cha
- }
- /*** signing key ***/
-+struct bctbx_signing_key_struct {
-+      mbedtls_pk_context ctx;            /**< the actual pk context*/
-+      mbedtls_entropy_context entropy;   /**< entropy context - store it to be able to free it */
-+      mbedtls_ctr_drbg_context ctr_drbg; /**< rng context */
-+};
-+
- bctbx_signing_key_t *bctbx_signing_key_new(void) {
--      mbedtls_pk_context *key = bctbx_malloc0(sizeof(mbedtls_pk_context));
--      mbedtls_pk_init(key);
--      return (bctbx_signing_key_t *)key;
-+      bctbx_signing_key_t *key = bctbx_malloc0(sizeof(bctbx_signing_key_t));
-+      mbedtls_pk_init(&(key->ctx));
-+      mbedtls_entropy_init(&(key->entropy));
-+      mbedtls_ctr_drbg_init(&(key->ctr_drbg));
-+      mbedtls_ctr_drbg_seed(&(key->ctr_drbg), mbedtls_entropy_func, &(key->entropy), NULL, 0);
-+      return key;
- }
- void bctbx_signing_key_free(bctbx_signing_key_t *key) {
--      mbedtls_pk_free((mbedtls_pk_context *)key);
-+      mbedtls_pk_free(&(key->ctx));
-+      mbedtls_ctr_drbg_free(&(key->ctr_drbg));
-+      mbedtls_entropy_free(&(key->entropy));
-       bctbx_free(key);
- }
-@@ -125,14 +136,15 @@ char *bctbx_signing_key_get_pem(bctbx_si
-       char *pem_key;
-       if (key == NULL) return NULL;
-       pem_key = (char *)bctbx_malloc0(4096);
--      mbedtls_pk_write_key_pem( (mbedtls_pk_context *)key, (unsigned char *)pem_key, 4096);
-+      mbedtls_pk_write_key_pem(&(key->ctx), (unsigned char *)pem_key, 4096);
-       return pem_key;
- }
- int32_t bctbx_signing_key_parse(bctbx_signing_key_t *key, const char *buffer, size_t buffer_length, const unsigned char *password, size_t password_length) {
-       int err;
-       
--      err=mbedtls_pk_parse_key((mbedtls_pk_context *)key, (const unsigned char *)buffer, buffer_length, password, password_length);
-+      err = mbedtls_pk_parse_key(&(key->ctx), (const unsigned char *)buffer, buffer_length, password, password_length,
-+                                 mbedtls_ctr_drbg_random, &(key->ctr_drbg));
-       
-       if (err<0) {
-               char tmp[128];
-@@ -146,7 +158,7 @@ int32_t bctbx_signing_key_parse(bctbx_si
- int32_t bctbx_signing_key_parse_file(bctbx_signing_key_t *key, const char *path, const char *password) {
-       int err;
-       
--      err=mbedtls_pk_parse_keyfile((mbedtls_pk_context *)key, path, password);
-+      err = mbedtls_pk_parse_keyfile(&(key->ctx), path, password, mbedtls_ctr_drbg_random, &(key->ctr_drbg));
-       
-       if (err<0) {
-               char tmp[128];
-@@ -231,9 +243,9 @@ bctbx_list_t *bctbx_x509_certificate_get
-       if (cert != NULL) {
--              mbedtls_x509_crt *mbedtls_cert = (mbedtls_x509_crt *)cert; // bctbx_x509_certificate_t is just a cast of mbedtls_x509_crt
-+              mbedtls_x509_crt *mbedtls_cert = (mbedtls_x509_crt *)cert;
-               /* parse subjectAltName if any */
--              if( mbedtls_cert->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ) {
-+              if (mbedtls_x509_crt_has_ext_type(mbedtls_cert, MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) != 0) {
-                       const mbedtls_x509_sequence *cur = &(mbedtls_cert->subject_alt_names);
-                       while (cur != NULL) {
-                               ret = bctbx_list_append(ret, bctbx_strndup((const char*)cur->buf.p, (int)cur->buf.len));
-@@ -358,12 +370,13 @@ int32_t bctbx_x509_certificate_generate_
- int32_t bctbx_x509_certificate_get_signature_hash_function(const bctbx_x509_certificate_t *certificate, bctbx_md_type_t *hash_algorithm) {
--      mbedtls_x509_crt *crt;
-       if (certificate == NULL) return BCTBX_ERROR_INVALID_CERTIFICATE;
--      crt = (mbedtls_x509_crt *)certificate;
-+      mbedtls_md_type_t mdt;
-+      mbedtls_pk_type_t pk;
-+      mbedtls_oid_get_sig_alg(&(((mbedtls_x509_crt *)certificate)->sig_oid), &mdt, &pk);
--      switch (crt->sig_md) {
-+      switch (mdt) {
-               case MBEDTLS_MD_SHA1:
-                       *hash_algorithm = BCTBX_MD_SHA1;
-               break;
-@@ -424,8 +437,10 @@ int32_t bctbx_x509_certificate_get_finge
-                       hash_id = MBEDTLS_MD_SHA512;
-                       break;
-               default: /* nothing specified, use the hash algo used in the certificate signature */
--                      hash_id = crt->sig_md;
--                      break;
-+              {
-+                      mbedtls_pk_type_t pk;
-+                      mbedtls_oid_get_sig_alg(&(crt->sig_oid), &hash_id, &pk);
-+              } break;
-       }
-       /* fingerprint is a hash of the DER formated certificate (found in crt->raw.p) using the same hash function used by certificate signature */
-@@ -692,15 +707,18 @@ int32_t bctbx_x509_certificate_unset_fla
- /* initialise de DHM context according to requested algorithm */
- bctbx_DHMContext_t *bctbx_CreateDHMContext(uint8_t DHMAlgo, uint8_t secretLength)
- {
-+      if ((DHMAlgo != BCTBX_DHM_2048) && (DHMAlgo != BCTBX_DHM_3072)) {
-+              bctbx_error("bctbx_CreateDHMContext with unsupported algo: 0x%x", DHMAlgo);
-+              return NULL;
-+      }
-       mbedtls_dhm_context *mbedtlsDhmContext;
-       /* create the context */
--      bctbx_DHMContext_t *context = (bctbx_DHMContext_t *)malloc(sizeof(bctbx_DHMContext_t));
--      memset (context, 0, sizeof(bctbx_DHMContext_t));
-+      bctbx_DHMContext_t *context = (bctbx_DHMContext_t *)bctbx_malloc0(sizeof(bctbx_DHMContext_t));
-       /* create the mbedtls context for DHM */
--      mbedtlsDhmContext=(mbedtls_dhm_context *)malloc(sizeof(mbedtls_dhm_context));
--      memset(mbedtlsDhmContext, 0, sizeof(mbedtls_dhm_context));
-+      mbedtlsDhmContext = (mbedtls_dhm_context *)bctbx_malloc0(sizeof(mbedtls_dhm_context));
-+      mbedtls_dhm_init(mbedtlsDhmContext);
-       context->cryptoModuleData=(void *)mbedtlsDhmContext;
-       /* initialise pointer to NULL to ensure safe call to free() when destroying context */
-@@ -712,31 +730,55 @@ bctbx_DHMContext_t *bctbx_CreateDHMConte
-       /* set parameters in the context */
-       context->algo=DHMAlgo;
-       context->secretLength = secretLength;
-+
-+      const unsigned char dhm_p2048[] = MBEDTLS_DHM_RFC3526_MODP_2048_P_BIN;
-+      const unsigned char dhm_g2048[] = MBEDTLS_DHM_RFC3526_MODP_2048_G_BIN;
-+      const unsigned char dhm_p3072[] = MBEDTLS_DHM_RFC3526_MODP_3072_P_BIN;
-+      const unsigned char dhm_g3072[] = MBEDTLS_DHM_RFC3526_MODP_3072_G_BIN;
-+      const unsigned char *dhm_p = NULL;
-+      const unsigned char *dhm_g = NULL;
-+      size_t dhm_p_size = 0;
-+      size_t dhm_g_size = 0;
-       switch (DHMAlgo) {
--              case BCTBX_DHM_2048:
--                      /* set P and G in the mbedtls context */
--                      if ((mbedtls_mpi_read_string(&(mbedtlsDhmContext->P), 16, MBEDTLS_DHM_RFC3526_MODP_2048_P) != 0) ||
--                      (mbedtls_mpi_read_string(&(mbedtlsDhmContext->G), 16, MBEDTLS_DHM_RFC3526_MODP_2048_G) != 0)) {
--                              return NULL;
--                      }
-+              case BCTBX_DHM_2048: {
-+                      dhm_p = dhm_p2048;
-+                      dhm_p_size = sizeof(dhm_p2048);
-+                      dhm_g = dhm_g2048;
-+                      dhm_g_size = sizeof(dhm_g2048);
-                       context->primeLength=256;
--                      mbedtlsDhmContext->len=256;
--                      break;
--              case BCTBX_DHM_3072:
--                      /* set P and G in the mbedtls context */
--                      if ((mbedtls_mpi_read_string(&(mbedtlsDhmContext->P), 16, MBEDTLS_DHM_RFC3526_MODP_3072_P) != 0) ||
--                      (mbedtls_mpi_read_string(&(mbedtlsDhmContext->G), 16, MBEDTLS_DHM_RFC3526_MODP_3072_G) != 0)) {
--                              return NULL;
--                      }
--                      context->primeLength=384;
--                      mbedtlsDhmContext->len=384;
--                      break;
-+              } break;
-               default:
--                      free(context);
--                      return NULL;
--                      break;
--      }
--
-+              case BCTBX_DHM_3072: {
-+                      dhm_p = dhm_p3072;
-+                      dhm_p_size = sizeof(dhm_p3072);
-+                      dhm_g = dhm_g3072;
-+                      dhm_g_size = sizeof(dhm_g3072);
-+                      context->primeLength = 384;
-+              } break;
-+      }
-+
-+      /* set P and G in the mbedtls context */
-+      bool_t fail = FALSE;
-+      mbedtls_mpi P, G;
-+      mbedtls_mpi_init(&P);
-+      mbedtls_mpi_init(&G);
-+      if ((mbedtls_mpi_read_binary(&P, dhm_p, dhm_p_size) != 0) ||
-+          (mbedtls_mpi_read_binary(&G, dhm_g, dhm_g_size) != 0)) {
-+              fail = TRUE;
-+              bctbx_error("bctbx_CreateDHMContext cannot read DHM group parameters");
-+      } else if (mbedtls_dhm_set_group(mbedtlsDhmContext, &P, &G) != 0) {
-+              fail = TRUE;
-+              bctbx_error("bctbx_CreateDHMContext cannot set DHM group parameters");
-+      }
-+      mbedtls_mpi_free(&P);
-+      mbedtls_mpi_free(&G);
-+      if (fail == TRUE) {
-+              mbedtls_dhm_free(mbedtlsDhmContext);
-+              bctbx_free(mbedtlsDhmContext);
-+              bctbx_free(context);
-+              return NULL;
-+      }
-+ 
-       return context;
- }
-@@ -746,7 +788,7 @@ void bctbx_DHMCreatePublic(bctbx_DHMCont
-       mbedtls_dhm_context *mbedtlsContext = (mbedtls_dhm_context *)context->cryptoModuleData;
-       /* allocate output buffer */
--      context->self = (uint8_t *)malloc(context->primeLength*sizeof(uint8_t));
-+      context->self = (uint8_t *)bctbx_malloc0(context->primeLength * sizeof(uint8_t));
-       mbedtls_dhm_make_public(mbedtlsContext, context->secretLength, context->self, context->primeLength, (int (*)(void *, unsigned char *, size_t))rngFunction, rngContext);
-@@ -762,8 +804,7 @@ void bctbx_DHMComputeSecret(bctbx_DHMCon
-       /* compute the secret key */
-       keyLength = context->primeLength; /* undocumented but this value seems to be in/out, so we must set it to the expected key length */
--      context->key = (uint8_t *)malloc(keyLength*sizeof(uint8_t)); /* allocate and reset the key buffer */
--      memset(context->key,0, keyLength);
-+      context->key = (uint8_t *)bctbx_malloc0(keyLength * sizeof(uint8_t)); /* allocate and reset the key buffer */
-       mbedtls_dhm_calc_secret((mbedtls_dhm_context *)(context->cryptoModuleData), sharedSecretBuffer, 384, &keyLength, (int (*)(void *, unsigned char *, size_t))rngFunction, rngContext);
-       /* now copy the resulting secret in the correct place in buffer(result may actually miss some front zero bytes, real length of output is now in keyLength but we want primeLength bytes) */
-       memcpy(context->key+(context->primeLength-keyLength), sharedSecretBuffer, keyLength);
-@@ -776,19 +817,19 @@ void bctbx_DestroyDHMContext(bctbx_DHMCo
-               /* key and secret must be erased from memory and not just freed */
-               if (context->secret != NULL) {
-                       bctbx_clean(context->secret, context->secretLength);
--                      free(context->secret);
-+                      bctbx_free(context->secret);
-               }
--              free(context->self);
-+              bctbx_free(context->self);
-               if (context->key != NULL) {
-                       bctbx_clean(context->key, context->primeLength);
--                      free(context->key);
-+                      bctbx_free(context->key);
-               }
--              free(context->peer);
-+              bctbx_free(context->peer);
-               mbedtls_dhm_free((mbedtls_dhm_context *)context->cryptoModuleData);
--              free(context->cryptoModuleData);
-+              bctbx_free(context->cryptoModuleData);
--              free(context);
-+              bctbx_free(context);
-       }
- }
-@@ -883,35 +924,7 @@ int32_t bctbx_ssl_read(bctbx_ssl_context
- int32_t bctbx_ssl_handshake(bctbx_ssl_context_t *ssl_ctx) {
--      int ret = 0;
--      while( ssl_ctx->ssl_ctx.state != MBEDTLS_SSL_HANDSHAKE_OVER )
--      {
--              ret = mbedtls_ssl_handshake_step(&(ssl_ctx->ssl_ctx));
--              if( ret != 0 ) {
--                      break;
--              }
--
--              /* insert the callback function for client certificate request */
--              if (ssl_ctx->callback_cli_cert_function != NULL) { /* check we have a callback function */
--                      /* when in state SSL_CLIENT_CERTIFICATE - which means, next call to ssl_handshake_step will send the client certificate to server -
--                       * and the client_auth flag is set - which means the server requested a client certificate - */
--                      if (ssl_ctx->ssl_ctx.state == MBEDTLS_SSL_CLIENT_CERTIFICATE && ssl_ctx->ssl_ctx.client_auth > 0) {
--                              /* Retrieve peer certificate subject altname and cn during handshake from server certificate request
--                               * Get the peer certificate from mbedtls ssl context. No accessor to get it,
--                               * fetch it directly from session_negociate which holds the currently negotiated handshake */
--                              bctbx_list_t *names = bctbx_x509_certificate_get_subjects((const bctbx_x509_certificate_t *)ssl_ctx->ssl_ctx.session_negotiate->peer_cert);
--
--                              if (ssl_ctx->callback_cli_cert_function(ssl_ctx->callback_cli_cert_data, ssl_ctx, names)!=0) {
--                                      bctbx_list_free_with_data(names, bctbx_free);
--                                      if((ret=mbedtls_ssl_send_alert_message(&(ssl_ctx->ssl_ctx), MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE)) != 0 ) {
--                                              return( ret );
--                                      }
--                                      return BCTBX_ERROR_NO_CLIENT_CERTIFICATE;
--                              }
--                              bctbx_list_free_with_data(names, bctbx_free);
--                      }
--              }
--      }
-+      int ret = mbedtls_ssl_handshake(&(ssl_ctx->ssl_ctx));
-       /* remap some output codes */
-       if (ret == MBEDTLS_ERR_SSL_WANT_READ) {
-@@ -923,16 +936,6 @@ int32_t bctbx_ssl_handshake(bctbx_ssl_co
-       return(ret);
- }
--int32_t bctbx_ssl_set_hs_own_cert(bctbx_ssl_context_t *ssl_ctx, bctbx_x509_certificate_t *cert, bctbx_signing_key_t *key) {
--      /* WARNING Dirty-Dirty trick : in mbedtls ssl_set_hs_own_cert shall be caller on server side only for SNI, there is no real equivalent on client side yet */
--      /* If we are server call the regular function */
--      if (ssl_ctx->ssl_ctx.conf->endpoint == MBEDTLS_SSL_IS_SERVER ) {
--              return mbedtls_ssl_set_hs_own_cert(&(ssl_ctx->ssl_ctx) , (mbedtls_x509_crt *)cert , (mbedtls_pk_context *)key);
--      } else { /* if we are client, call the conf function on the function in use inside the ssl_context, dirty but it works for now */
--              return mbedtls_ssl_conf_own_cert((mbedtls_ssl_config *)ssl_ctx->ssl_ctx.conf , (mbedtls_x509_crt *)cert , (mbedtls_pk_context *)key);
--      }
--}
--
- int bctbx_ssl_send_callback(void *data, const unsigned char *buffer, size_t buffer_length) {
-       int ret = 0;
-       /* data is the ssl_context which contains the actual callback and data */
-@@ -1040,7 +1043,7 @@ bctbx_dtls_srtp_profile_t bctbx_ssl_get_
-       mbedtls_dtls_srtp_info dtls_srtp_negotiation_result;
-       mbedtls_ssl_get_dtls_srtp_negotiation_result(&(ssl_ctx->ssl_ctx), &dtls_srtp_negotiation_result);
--      return bctbx_srtp_profile_mbedtls2bctoolbox(dtls_srtp_negotiation_result.chosen_dtls_srtp_profile);
-+      return bctbx_srtp_profile_mbedtls2bctoolbox(dtls_srtp_negotiation_result.MBEDTLS_PRIVATE(chosen_dtls_srtp_profile));
- };
- #else /* HAVE_DTLS_SRTP */
-@@ -1090,6 +1093,9 @@ bctbx_ssl_config_t *bctbx_ssl_config_new
-       ssl_config->callback_cli_cert_function = NULL;
-       ssl_config->callback_cli_cert_data = NULL;
-+#ifdef HAVE_DTLS_SRTP
-+      ssl_config->dtls_srtp_mbedtls_profiles[0] = MBEDTLS_TLS_SRTP_UNSET;
-+#endif /* HAVE_DTLS_SRTP */
-       return ssl_config;
- }
-@@ -1328,17 +1334,33 @@ int32_t bctbx_ssl_config_set_own_cert(bc
- /* This callback is executed during the DTLS handshake, extract the master secret and randoms needed to generate the DTLS-SRTP keys
-  * The generation itself is performed after the handshake */
--static int bctbx_ssl_dtls_srtp_key_derivation(void *key_ctx, const unsigned char *ms,
--              BCTBX_UNUSED(const unsigned char * kb), BCTBX_UNUSED(size_t maclen), BCTBX_UNUSED(size_t keylen), BCTBX_UNUSED(size_t ivlen), // these params are useless for our purpose
--              const unsigned char client_random[32], const unsigned char server_random[32],
--              mbedtls_tls_prf_types tls_prf_type ) {
-+static void bctbx_ssl_dtls_srtp_key_derivation(
-+    void *key_ctx,
-+    mbedtls_ssl_key_export_type
-+        type, /* shall always be MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET for now, not available in TLSv1.3 */
-+    const unsigned char *secret,
-+    size_t secret_len,
-+    const unsigned char client_random[32],
-+    const unsigned char server_random[32],
-+    mbedtls_tls_prf_types tls_prf_type) {
-+
-+      /* We're only interested in the TLS 1.2 master secret */
-+      if (type != MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET) {
-+              bctbx_error("DTLS-SRTP key derivation callback given a secret not derived from TLS12: %x", (int)type);
-+              return;
-+      }
-       bctbx_dtls_srtp_keys_t *keys = (bctbx_dtls_srtp_keys_t *)key_ctx;
--      memcpy(keys->master_secret, ms, sizeof(keys->master_secret)); // copy the master secret
--      memcpy(keys->randoms, client_random, 32); // the client and server random
-+      if (secret_len != sizeof(keys->master_secret)) {
-+              bctbx_error("DTLS-SRTP key derivation callback generate a secret of size %zd but we're expecting %zd bytes",
-+                          secret_len, sizeof(keys->master_secret));
-+              return;
-+      }
-+
-+      memcpy(keys->master_secret, secret, sizeof(keys->master_secret)); // copy the master secret
-+      memcpy(keys->randoms, client_random, 32);                         // the client and server random
-       memcpy(keys->randoms + 32, server_random, 32);
-       keys->tls_prf_type = tls_prf_type; // the prf id
--      return(0);
- }
- int32_t bctbx_ssl_get_dtls_srtp_key_material(bctbx_ssl_config_t *ssl_config, uint8_t *output, size_t *output_length) {
-@@ -1372,9 +1394,6 @@ int32_t bctbx_ssl_config_set_dtls_srtp_p
-               ssl_config->dtls_srtp_mbedtls_profiles[i] = MBEDTLS_TLS_SRTP_UNSET;
-       }
--      /* set the callback to compute the key material */
--      mbedtls_ssl_conf_export_keys_ext_cb(ssl_config->ssl_config, bctbx_ssl_dtls_srtp_key_derivation, &(ssl_config->dtls_srtp_keys));
--
-       return mbedtls_ssl_conf_dtls_srtp_protection_profiles(ssl_config->ssl_config, ssl_config->dtls_srtp_mbedtls_profiles); // no profile number, list is UNSET terminated
- }
-@@ -1408,13 +1427,21 @@ int32_t bctbx_ssl_context_setup(bctbx_ss
-       }
- #ifdef HAVE_DTLS_SRTP
--      /* We do not use DTLS SRTP cookie, so we must set to NULL the callbacks. Cookies are used to prevent DoS attack but our server is on only when during a brief period so we do not need this */
-+      /* We do not use DTLS SRTP cookie, so we must set to NULL the callbacks. Cookies are used to prevent DoS attack but our server is on only during a brief period so we do not need this */
-       mbedtls_ssl_conf_dtls_cookies(ssl_config->ssl_config, NULL, NULL, NULL);
- #endif /* HAVE_DTLS_SRTP */
-       ret = mbedtls_ssl_setup(&(ssl_ctx->ssl_ctx), ssl_config->ssl_config);
-       if (ret != 0) return ret;
-+#ifdef HAVE_DTLS_SRTP
-+      /* set the callback to compute the DTLS-SRTP key material if needed */
-+      if (ssl_config->dtls_srtp_mbedtls_profiles[0] != MBEDTLS_TLS_SRTP_UNSET) {
-+              mbedtls_ssl_set_export_keys_cb(&(ssl_ctx->ssl_ctx), bctbx_ssl_dtls_srtp_key_derivation,
-+                                             &(ssl_config->dtls_srtp_keys));
-+      }
-+#endif /* HAVE_DTLS_SRTP */
-+
-       /* for DTLS handshake, we must set a timer callback */
-       mbedtls_ssl_set_timer_cb(&(ssl_ctx->ssl_ctx), &(ssl_ctx->timer), mbedtls_timing_set_delay, mbedtls_timing_get_delay);
-@@ -1741,7 +1768,15 @@ bctbx_aes_gcm_context_t *bctbx_aes_gcm_c
-               return NULL;
-       }
--      ret = mbedtls_gcm_starts(ctx, mbedtls_mode, initializationVector, initializationVectorLength, authenticatedData, authenticatedDataLength);
-+      ret = mbedtls_gcm_starts(ctx, mbedtls_mode, initializationVector, initializationVectorLength);
-+      if (ret != 0) {
-+              bctbx_free(ctx);
-+              return NULL;
-+      }
-+
-+      if (authenticatedDataLength > 0) {
-+              ret = mbedtls_gcm_update_ad(ctx, authenticatedData, authenticatedDataLength);
-+      }
-       if (ret != 0) {
-               bctbx_free(ctx);
-               return NULL;
-@@ -1763,14 +1798,21 @@ bctbx_aes_gcm_context_t *bctbx_aes_gcm_c
- int32_t bctbx_aes_gcm_process_chunk(bctbx_aes_gcm_context_t *context,
-               const uint8_t *input, size_t inputLength,
-               uint8_t *output) {
--      return mbedtls_gcm_update((mbedtls_gcm_context *)context, inputLength, input, output);
-+
-+      /* Note: Mbedtls2 is not able to bufferize a part of the input to output 16bytes blocs
-+       * So the buffering is done in liblinphone for file decryption
-+       * Mbedtls3 claim it supports the buffering but it is true only when
-+       * using alternative implementation of GCM, the main one present in mbedtls is the same : only the last call
-+       * to mbedtls_gcm_update can have a length not multiple of 16 bytes */
-+      size_t outputLength = inputLength;
-+      return mbedtls_gcm_update((mbedtls_gcm_context *)context, input, inputLength, output, inputLength, &outputLength);
- }
- /**
-  * @Brief Conclude a AES-GCM encryption stream, generate tag if requested, free resources
-  *
-  * @param[in/out]     context                 a context already initialized using bctbx_aes_gcm_context_new
-- * @param[out]                tag                             a buffer to hold the authentication tag. Can be NULL if tagLength is 0
-+ * @param[out]                tag                     a buffer to hold the authentication tag. Can be NULL if tagLength is 0
-  * @param[in]         tagLength               length of reqested authentication tag, max 16
-  *
-  * @return 0 on success, crypto library error code otherwise
-@@ -1778,8 +1820,9 @@ int32_t bctbx_aes_gcm_process_chunk(bctb
- int32_t bctbx_aes_gcm_finish(bctbx_aes_gcm_context_t *context,
-               uint8_t *tag, size_t tagLength) {
-       int ret;
-+      size_t output_len = 0;
--      ret = mbedtls_gcm_finish((mbedtls_gcm_context *)context, tag, tagLength);
-+      ret = mbedtls_gcm_finish((mbedtls_gcm_context *)context, NULL, 0, &output_len, tag, tagLength);
-       mbedtls_gcm_free((mbedtls_gcm_context *)context);
-       bctbx_free(context);
-diff --git a/src/tester.c b/src/tester.c
-index ef3eb27..ba6f3bb 100644
---- a/src/tester.c
-+++ b/src/tester.c
-@@ -143,7 +143,7 @@ void bc_tester_set_process_events_func(v
-       process_events = func;
- }
--void bc_tester_process_events(){
-+void bc_tester_process_events(void) {
-       if( process_events)
-               process_events();
- }
-diff --git a/tester/crypto.cc b/tester/crypto.cc
-index 3ac5dd0..5f8cc01 100644
---- a/tester/crypto.cc
-+++ b/tester/crypto.cc
-@@ -297,82 +297,6 @@ static void ECDH(void) {
-       bctbx_DestroyECDHContext(bob);
- }
--/* just check compatibility of ECDH exchange between mbedtls implementation and decaf one */
--/* mbedtls works with all buffer in big endian, while rfc 7748 specify little endian encoding, so all buffer in or out of mbedtls_mpi_read/write must be reversed */
--static void ECDH25519compat(void) {
--
--#ifdef HAVE_MBEDTLS
--      int i;
--      bctbx_ECDHContext_t *alice=NULL;
--      bctbx_rng_context_t *RNG;
--      mbedtls_ecdh_context *bob=NULL;
--      uint8_t tmpBuffer[32];
--      uint8_t bobPublic[32];
--      uint8_t bobShared[32];
--
--      if (!bctbx_crypto_have_ecc()) {
--              bctbx_warning("test skipped as we don't have Elliptic Curve Cryptography in bctoolbox");
--              return;
--      }
--
--
--      /* Init the RNG */
--      RNG = bctbx_rng_context_new();
--
--      /* Create Alice and Bob contexts */
--      alice = bctbx_CreateECDHContext(BCTBX_ECDH_X25519);
--
--      bob=(mbedtls_ecdh_context *)bctbx_malloc(sizeof(mbedtls_ecdh_context));
--      mbedtls_ecdh_init(bob);
--      mbedtls_ecp_group_load(&(bob->grp), MBEDTLS_ECP_DP_CURVE25519 );
--
--      /* Generate keys pairs */
--      bctbx_ECDHCreateKeyPair(alice, (int (*)(void *, uint8_t *, size_t))bctbx_rng_get, RNG);
--      mbedtls_ecdh_gen_public(&(bob->grp), &(bob->d), &(bob->Q), (int (*)(void *, unsigned char *, size_t))bctbx_rng_get, RNG);
--      mbedtls_mpi_write_binary(&(bob->Q.X), tmpBuffer, 32 );
--      /* tmpBuffer is in big endian, but we need it in little endian, reverse it */
--      for (i=0; i<32; i++) {
--              bobPublic[i]=tmpBuffer[31-i];
--      }
--
--      /* exchange public keys */
--      alice->peerPublic = (uint8_t *)malloc(alice->pointCoordinateLength*sizeof(uint8_t));
--      memcpy(alice->peerPublic, bobPublic, alice->pointCoordinateLength);
--
--      /* compute shared secrets */
--      bctbx_ECDHComputeSecret(alice, NULL, NULL);
--
--      mbedtls_mpi_lset(&(bob->Qp.Z), 1);
--      /* alice->selfPublic is in little endian, but mbedtls expect it in big, reverse it */
--      for (i=0; i<32; i++) {
--              tmpBuffer[i]=alice->selfPublic[31-i];
--      }
--
--      mbedtls_mpi_read_binary(&(bob->Qp.X), tmpBuffer, 32);
--      /* generate shared secret */
--      mbedtls_ecdh_compute_shared(&(bob->grp), &(bob->z), &(bob->Qp), &(bob->d),  (int (*)(void *, unsigned char *, size_t))bctbx_rng_get, RNG);
--      /* copy it in the output buffer */
--      mbedtls_mpi_write_binary(&(bob->z), tmpBuffer, 32);
--      /* reverse it as we need it in little endian */
--      for (i=0; i<32; i++) {
--              bobShared[i]=tmpBuffer[31-i];
--      }
--
--      /* compare the secrets */
--      BC_ASSERT_TRUE(memcmp(alice->sharedSecret, bobShared, alice->pointCoordinateLength)==0);
--
--      /* clear contexts */
--      bctbx_DestroyECDHContext(alice);
--      mbedtls_ecdh_free(bob);
--      free(bob);
--
--      /* clear contexts */
--      bctbx_rng_context_free(RNG);
--#else /* HAVE_MBEDTLS */
--      bctbx_warning("test skipped as we don't have mbedtls in bctoolbox");
--#endif /* HAVE_MBEDTLS */
--}
--
- static char const *importantMessage1 = "The most obvious mechanical phenomenon in electrical and magnetical experiments is the mutual action by which bodies in certain states set each other in motion while still at a sensible distance from each other. The first step, therefore, in reducing these phenomena into scientific form, is to ascertain the magnitude and direction of the force acting between the bodies, and when it is found that this force depends in a certain way upon the relative position of the bodies and on their electric or magnetic condition, it seems at first sight natural to explain the facts by assuming the existence of something either at rest or in motion in each body, constituting its electric or magnetic state, and capable of acting at a distance according to mathematical laws.In this way mathematical theories of statical electricity, of magnetism, of the mechanical action between conductors carrying currents, and of the induction of currents have been formed. In these theories the force acting between the two bodies is treated with reference only to the condition of the bodies and their relative position, and without any express consideration of the surrounding medium. These theories assume, more or less explicitly, the existence of substances the particles of which have the property of acting on one another at a distance by attraction or repulsion. The most complete development of a theory of this kind is that of M.W. Weber[1], who has made the same theory include electrostatic and electromagnetic phenomena. In doing so, however, he has found it necessary to assume that the force between two particles depends on their relative velocity, as well as on their distance. This theory, as developed by MM. W. Weber and C. Neumann[2], is exceedingly ingenious, and wonderfully comprehensive in its application to the phenomena of statical electricity, electromagnetic attractions, induction of current and diamagnetic phenomena; and it comes to us with the more authority, as it has served to guide the speculations of one who has made so great an advance in the practical part of electric science, both by introducing a consistent system of units in electrical measurement, and by actually determining electrical quantities with an accuracy hitherto unknown.";
- static char const *importantMessage2 = " The mechanical difficulties, however, which are involved in the assumption of particles acting at a distance with forces which depend on their velocities are such as to prevent me from considering this theory as an ultimate one though it may have been, and may yet be useful in leading to the coordination of phenomena. I have therefore preferred to seek an explanation of the fact in another direction, by supposing them to be produced by actions which go on in the surrounding medium as well as in the excited bodies, and endeavouring to explain the action between distant bodies without assuming the existence of forces capable of acting directly at sensible distances.";
-@@ -808,7 +732,50 @@ static void rng_test(void) {
- #endif //HAVE_MBEDTLS
- }
--static void AEAD(void) {
-+static int cInterfaceAESGCMTest(const std::vector<uint8_t> &key,
-+                                const std::vector<uint8_t> &AD,
-+                                const std::vector<uint8_t> &IV,
-+                                const std::vector<uint8_t> &pattern_plain,
-+                                const std::vector<uint8_t> &pattern_cipher,
-+                                const std::vector<uint8_t> &pattern_tag) {
-+      int ret = 0;
-+      uint8_t cCipher[256]; // 256 is the maximum size of patterns
-+      uint8_t cTag[16];
-+
-+      memset(cCipher, 0, 256);
-+      memset(cTag, 0, 16);
-+      bctbx_aes_gcm_context_t *ctx = bctbx_aes_gcm_context_new(key.data(), key.size(), AD.data(), AD.size(), IV.data(),
-+                                                               IV.size(), BCTBX_GCM_ENCRYPT);
-+      ret = BC_ASSERT_PTR_NOT_NULL(ctx);
-+      ret &= BC_ASSERT_TRUE(bctbx_aes_gcm_process_chunk(ctx, pattern_plain.data(), pattern_plain.size(), cCipher) == 0);
-+      ret &= BC_ASSERT_TRUE(bctbx_aes_gcm_finish(ctx, cTag, 16) == 0);
-+      ret &= BC_ASSERT_TRUE(memcmp(cCipher, pattern_cipher.data(), pattern_cipher.size()) == 0);
-+      ret &= BC_ASSERT_TRUE(memcmp(cTag, pattern_tag.data(), pattern_tag.size()) == 0);
-+
-+      return ret;
-+}
-+
-+static int AESGCMTest(const std::vector<uint8_t> &key,
-+                      const std::vector<uint8_t> &AD,
-+                      const std::vector<uint8_t> &IV,
-+                      const std::vector<uint8_t> &pattern_plain,
-+                      const std::vector<uint8_t> &pattern_cipher,
-+                      const std::vector<uint8_t> &pattern_tag) {
-+      int ret = 0;
-+      std::vector<uint8_t> cipher{};
-+      std::vector<uint8_t> tag{};
-+      std::vector<uint8_t> plain{};
-+
-+      cipher = AEADEncrypt<AES256GCM128>(key, IV, pattern_plain, AD, tag);
-+      ret = BC_ASSERT_TRUE(cipher == pattern_cipher);
-+      ret &= BC_ASSERT_TRUE(tag == pattern_tag);
-+      ret &= BC_ASSERT_TRUE(AEADDecrypt<AES256GCM128>(key, IV, pattern_cipher, AD, pattern_tag, plain));
-+      ret &= BC_ASSERT_TRUE(plain == pattern_plain);
-+
-+      return ret;
-+}
-+
-+static void AEAD(void) {
-       std::vector<uint8_t> cipher{};
-       std::vector<uint8_t> tag{};
-       std::vector<uint8_t> plain{};
-@@ -823,11 +790,8 @@ static void AEAD(void) {
-       std::vector<uint8_t> AD{};
-       AD.clear();
--      cipher = AEADEncrypt<AES256GCM128>(key, IV, pattern_plain, AD, tag);
--      BC_ASSERT_TRUE(cipher==pattern_cipher);
--      BC_ASSERT_TRUE(tag==pattern_tag);
--      BC_ASSERT_TRUE(AEADDecrypt<AES256GCM128>(key, IV, pattern_cipher, AD, pattern_tag, plain));
--      BC_ASSERT_TRUE(plain==pattern_plain);
-+      BC_ASSERT_TRUE(AESGCMTest(key, AD, IV, pattern_plain, pattern_cipher, pattern_tag) == 1);
-+      BC_ASSERT_TRUE(cInterfaceAESGCMTest(key, AD, IV, pattern_plain, pattern_cipher, pattern_tag) == 1);
-       /* Test D3.2 */
-       key = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-@@ -836,8 +800,8 @@ static void AEAD(void) {
-       pattern_plain.clear();
-       pattern_cipher.clear();
-       pattern_tag={0x2d, 0x45, 0x55, 0x2d, 0x85, 0x75, 0x92, 0x2b, 0x3c, 0xa3, 0xcc, 0x53, 0x84, 0x42, 0xfa, 0x26};
--      cipher = AEADEncrypt<AES256GCM128>(key, IV, pattern_plain, AD, tag);
--      BC_ASSERT_TRUE(tag==pattern_tag);
-+      BC_ASSERT_TRUE(AESGCMTest(key, AD, IV, pattern_plain, pattern_cipher, pattern_tag) == 1);
-+      BC_ASSERT_TRUE(cInterfaceAESGCMTest(key, AD, IV, pattern_plain, pattern_cipher, pattern_tag) == 1);
-       /* Test D3.3 */
-       key ={0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-@@ -846,14 +810,8 @@ static void AEAD(void) {
-       pattern_plain.assign({0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00});
-       pattern_cipher.assign({0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e, 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18});
-       pattern_tag={0xae, 0x9b, 0x17, 0x71, 0xdb, 0xa9, 0xcf, 0x62, 0xb3, 0x9b, 0xe0, 0x17, 0x94, 0x03, 0x30, 0xb4};
--      cipher.resize(pattern_plain.size());
--      plain.resize(pattern_plain.size());
--
--      cipher = AEADEncrypt<AES256GCM128>(key, IV, pattern_plain, AD, tag);
--      BC_ASSERT_TRUE(cipher==pattern_cipher);
--      BC_ASSERT_TRUE(tag==pattern_tag);
--      BC_ASSERT_TRUE(AEADDecrypt<AES256GCM128>(key, IV, pattern_cipher, AD, pattern_tag, plain));
--      BC_ASSERT_TRUE(plain==pattern_plain);
-+      BC_ASSERT_TRUE(AESGCMTest(key, AD, IV, pattern_plain, pattern_cipher, pattern_tag) == 1);
-+      BC_ASSERT_TRUE(cInterfaceAESGCMTest(key, AD, IV, pattern_plain, pattern_cipher, pattern_tag) == 1);
-       /* Test D3.4 */
-       key={0xfb, 0x76, 0x15, 0xb2, 0x3d, 0x80, 0x89, 0x1d, 0xd4, 0x70, 0x98, 0x0b, 0xc7, 0x95, 0x84, 0xc8, 0xb2, 0xfb, 0x64, 0xce, 0x60, 0x97, 0x8f, 0x4d, 0x17, 0xfc, 0xe4, 0x5a, 0x49, 0xe8, 0x30, 0xb7};
-@@ -862,14 +820,8 @@ static void AEAD(void) {
-       pattern_plain.assign({0xa8, 0x45, 0x34, 0x8e, 0xc8, 0xc5, 0xb5, 0xf1, 0x26, 0xf5, 0x0e, 0x76, 0xfe, 0xfd, 0x1b, 0x1e});
-       pattern_cipher.assign({0x5d, 0xf5, 0xd1, 0xfa, 0xbc, 0xbb, 0xdd, 0x05, 0x15, 0x38, 0x25, 0x24, 0x44, 0x17, 0x87, 0x04});
-       pattern_tag={0x4c, 0x43, 0xcc, 0xe5, 0xa5, 0x74, 0xd8, 0xa8, 0x8b, 0x43, 0xd4, 0x35, 0x3b, 0xd6, 0x0f, 0x9f};
--      cipher.resize(pattern_plain.size());
--      plain.resize(pattern_plain.size());
--
--      cipher = AEADEncrypt<AES256GCM128>(key, IV, pattern_plain, AD, tag);
--      BC_ASSERT_TRUE(cipher==pattern_cipher);
--      BC_ASSERT_TRUE(tag==pattern_tag);
--      BC_ASSERT_TRUE(AEADDecrypt<AES256GCM128>(key, IV, pattern_cipher, AD, pattern_tag, plain));
--      BC_ASSERT_TRUE(plain==pattern_plain);
-+      BC_ASSERT_TRUE(AESGCMTest(key, AD, IV, pattern_plain, pattern_cipher, pattern_tag) == 1);
-+      BC_ASSERT_TRUE(cInterfaceAESGCMTest(key, AD, IV, pattern_plain, pattern_cipher, pattern_tag) == 1);
-       /* Test D3.5 */
-       key={0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f};
-@@ -878,14 +830,8 @@ static void AEAD(void) {
-       pattern_plain.assign({0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37});
-       pattern_cipher.assign({0x59, 0x1b, 0x1f, 0xf2, 0x72, 0xb4, 0x32, 0x04, 0x86, 0x8f, 0xfc, 0x7b, 0xc7, 0xd5, 0x21, 0x99, 0x35, 0x26, 0xb6, 0xfa, 0x32, 0x24, 0x7c, 0x3c});
-       pattern_tag={0x7d, 0xe1, 0x2a, 0x56, 0x70, 0xe5, 0x70, 0xd8, 0xca, 0xe6, 0x24, 0xa1, 0x6d, 0xf0, 0x9c, 0x08};
--      cipher.resize(pattern_plain.size());
--      plain.resize(pattern_plain.size());
--
--      cipher = AEADEncrypt<AES256GCM128>(key, IV, pattern_plain, AD, tag);
--      BC_ASSERT_TRUE(cipher==pattern_cipher);
--      BC_ASSERT_TRUE(tag==pattern_tag);
--      BC_ASSERT_TRUE(AEADDecrypt<AES256GCM128>(key, IV, pattern_cipher, AD, pattern_tag, plain));
--      BC_ASSERT_TRUE(plain==pattern_plain);
-+      BC_ASSERT_TRUE(AESGCMTest(key, AD, IV, pattern_plain, pattern_cipher, pattern_tag) == 1);
-+      BC_ASSERT_TRUE(cInterfaceAESGCMTest(key, AD, IV, pattern_plain, pattern_cipher, pattern_tag) == 1);
-       /* Test D3.6 */
-       key={0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f};
-@@ -894,18 +840,12 @@ static void AEAD(void) {
-       pattern_plain.assign({0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f});
-       pattern_cipher.assign({0x59, 0x1b, 0x1f, 0xf2, 0x72, 0xb4, 0x32, 0x04, 0x86, 0x8f, 0xfc, 0x7b, 0xc7, 0xd5, 0x21, 0x99, 0x35, 0x26, 0xb6, 0xfa, 0x32, 0x24, 0x7c, 0x3c, 0x40, 0x57, 0xf3, 0xea, 0xe7, 0x54, 0x8c, 0xef});
-       pattern_tag={0xa1, 0xde, 0x55, 0x36, 0xe9, 0x7e, 0xdd, 0xdc, 0xcd, 0x26, 0xee, 0xb1, 0xb5, 0xff, 0x7b, 0x32};
--      cipher.resize(pattern_plain.size());
--      plain.resize(pattern_plain.size());
-       std::vector<uint8_t> repeatAD{};
-       for (auto i=0; i<256; i++) {
-               repeatAD.insert(repeatAD.end(), AD.cbegin(), AD.cend());
-       }
--
--      cipher = AEADEncrypt<AES256GCM128>(key, IV, pattern_plain, repeatAD, tag);
--      BC_ASSERT_TRUE(cipher==pattern_cipher);
--      BC_ASSERT_TRUE(tag==pattern_tag);
--      BC_ASSERT_TRUE(AEADDecrypt<AES256GCM128>(key, IV, pattern_cipher, repeatAD, pattern_tag, plain));
--      BC_ASSERT_TRUE(plain==pattern_plain);
-+      BC_ASSERT_TRUE(AESGCMTest(key, repeatAD, IV, pattern_plain, pattern_cipher, pattern_tag) == 1);
-+      BC_ASSERT_TRUE(cInterfaceAESGCMTest(key, repeatAD, IV, pattern_plain, pattern_cipher, pattern_tag) == 1);
-       /* Test D3.7 */
-       key={0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f};
-@@ -914,14 +854,8 @@ static void AEAD(void) {
-       pattern_plain.assign({0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff});
-       pattern_cipher.assign({0x79, 0x3b, 0x3f, 0xd2, 0x52, 0x94, 0x12, 0x24, 0xa6, 0xaf, 0xdc, 0x5b, 0xe7, 0xf5, 0x01, 0xb9, 0x15, 0x06, 0x96, 0xda, 0x12, 0x04, 0x5c, 0x1c, 0x60, 0x77, 0xd3, 0xca, 0xc7, 0x74, 0xac, 0xcf, 0xc3, 0xd5, 0x30, 0xd8, 0x48, 0xd6, 0x65, 0xd8, 0x1a, 0x49, 0xcb, 0xb5, 0x00, 0xb8, 0x8b, 0xbb, 0x62, 0x4a, 0xe6, 0x1d, 0x16, 0x67, 0x22, 0x9c, 0x30, 0x2d, 0xc6, 0xff, 0x0b, 0xb4, 0xd7, 0x0b, 0xdb, 0xbc, 0x85, 0x66, 0xd6, 0xf5, 0xb1, 0x58, 0xda, 0x99, 0xa2, 0xff, 0x2e, 0x01, 0xdd, 0xa6, 0x29, 0xb8, 0x9c, 0x34, 0xad, 0x1e, 0x5f, 0xeb, 0xa7, 0x0e, 0x7a, 0xae, 0x43, 0x28, 0x28, 0x9c, 0x36, 0x29, 0xb0, 0x58, 0x83, 0x50, 0x58, 0x1c, 0xa8, 0xb9, 0x7c, 0xcf, 0x12, 0x58, 0xfa, 0x3b, 0xbe, 0x2c, 0x50, 0x26, 0x04, 0x7b, 0xa7, 0x26, 0x48, 0x96, 0x9c, 0xff, 0x8b, 0xa1, 0x0a, 0xe3, 0x0e, 0x05, 0x93, 0x5d, 0xf0, 0xc6, 0x93, 0x74, 0x18, 0x92, 0xb7, 0x6f, 0xaf, 0x67, 0x13, 0x3a, 0xbd, 0x2c, 0xf2, 0x03, 0x11, 0x21, 0xbd, 0x8b, 0xb3, 0x81, 0x27, 0xa4, 0xd2, 0xee, 0xde, 0xea, 0x13, 0x27, 0x64, 0x94, 0xf4, 0x02, 0xcd, 0x7c, 0x10, 0x7f, 0xb3, 0xec, 0x3b, 0x24, 0x78, 0x48, 0x34, 0x33, 0x8e, 0x55, 0x43, 0x62, 0x87, 0x09, 0x2a, 0xc4, 0xa2, 0x6f, 0x5e, 0xa7, 0xea, 0x4a, 0xd6, 0x8d, 0x73, 0x15, 0x16, 0x39, 0xb0, 0x5b, 0x24, 0xe6, 0x8b, 0x98, 0x16, 0xd1, 0x39, 0x83, 0x76, 0xd8, 0xe4, 0x13, 0x85, 0x94, 0x75, 0x8d, 0xb9, 0xad, 0x3b, 0x40, 0x92, 0x59, 0xb2, 0x6d, 0xcf, 0xc0, 0x6e, 0x72, 0x2b, 0xe9, 0x87, 0xb3, 0x76, 0x7f, 0x70, 0xa7, 0xb8, 0x56, 0xb7, 0x74, 0xb1, 0xba, 0x26, 0x85, 0xb3, 0x68, 0x09, 0x14, 0x29, 0xfc, 0xcb, 0x8d, 0xcd, 0xde, 0x09, 0xe4});
-       pattern_tag={0x87, 0xec, 0x83, 0x7a, 0xbf, 0x53, 0x28, 0x55, 0xb2, 0xce, 0xa1, 0x69, 0xd6, 0x94, 0x3f, 0xcd};
--      cipher.resize(pattern_plain.size());
--      plain.resize(pattern_plain.size());
--
--      cipher = AEADEncrypt<AES256GCM128>(key, IV, pattern_plain, AD, tag);
--      BC_ASSERT_TRUE(cipher==pattern_cipher);
--      BC_ASSERT_TRUE(tag==pattern_tag);
--      BC_ASSERT_TRUE(AEADDecrypt<AES256GCM128>(key, IV, pattern_cipher, AD, pattern_tag, plain));
--      BC_ASSERT_TRUE(plain==pattern_plain);
-+      BC_ASSERT_TRUE(AESGCMTest(key, AD, IV, pattern_plain, pattern_cipher, pattern_tag) == 1);
-+      BC_ASSERT_TRUE(cInterfaceAESGCMTest(key, AD, IV, pattern_plain, pattern_cipher, pattern_tag) == 1);
-       /* Test D3.8 */
-       key={0xfb, 0x76, 0x15, 0xb2, 0x3d, 0x80, 0x89, 0x1d, 0xd4, 0x70, 0x98, 0x0b, 0xc7, 0x95, 0x84, 0xc8, 0xb2, 0xfb, 0x64, 0xce, 0x60, 0x97, 0x87, 0x8d, 0x17, 0xfc, 0xe4, 0x5a, 0x49, 0xe8, 0x30, 0xb7};
-@@ -930,14 +864,8 @@ static void AEAD(void) {
-       pattern_plain.assign({0xa9});
-       pattern_cipher.assign({0x0a});
-       pattern_tag={0xbe, 0x98, 0x7d, 0x00, 0x9a, 0x4b, 0x34, 0x9a, 0xa8, 0x0c, 0xb9, 0xc4, 0xeb, 0xc1, 0xe9, 0xf4};
--      cipher.resize(pattern_plain.size());
--      plain.resize(pattern_plain.size());
--
--      cipher = AEADEncrypt<AES256GCM128>(key, IV, pattern_plain, AD, tag);
--      BC_ASSERT_TRUE(cipher==pattern_cipher);
--      BC_ASSERT_TRUE(tag==pattern_tag);
--      BC_ASSERT_TRUE(AEADDecrypt<AES256GCM128>(key, IV, pattern_cipher, AD, pattern_tag, plain));
--      BC_ASSERT_TRUE(plain==pattern_plain);
-+      BC_ASSERT_TRUE(AESGCMTest(key, AD, IV, pattern_plain, pattern_cipher, pattern_tag) == 1);
-+      BC_ASSERT_TRUE(cInterfaceAESGCMTest(key, AD, IV, pattern_plain, pattern_cipher, pattern_tag) == 1);
-       /* Test D3.9 */
-       key={0xf8, 0xd4, 0x76, 0xcf, 0xd6, 0x46, 0xea, 0x6c, 0x23, 0x84, 0xcb, 0x1c, 0x27, 0xd6, 0x19, 0x5d, 0xfe, 0xf1, 0xa9, 0xf3, 0x7b, 0x9c, 0x8d, 0x21, 0xa7, 0x9c, 0x21, 0xf8, 0xcb, 0x90, 0xd2, 0x89};
-@@ -946,14 +874,8 @@ static void AEAD(void) {
-       pattern_plain.assign({0x90, 0xae, 0x61, 0xcf, 0x7b, 0xae, 0xbd, 0x4c, 0xad, 0xe4, 0x94, 0xc5, 0x4a, 0x29, 0xae, 0x70, 0x26, 0x9a, 0xec, 0x71});
-       pattern_cipher.assign({0xce, 0x20, 0x27, 0xb4, 0x7a, 0x84, 0x32, 0x52, 0x01, 0x34, 0x65, 0x83, 0x4d, 0x75, 0xfd, 0x0f, 0x07, 0x29, 0x75, 0x2e});
-       pattern_tag={0xac, 0xd8, 0x83, 0x38, 0x37, 0xab, 0x0e, 0xde, 0x84, 0xf4, 0x74, 0x8d, 0xa8, 0x89, 0x9c, 0x15};
--      cipher.resize(pattern_plain.size());
--      plain.resize(pattern_plain.size());
--
--      cipher = AEADEncrypt<AES256GCM128>(key, IV, pattern_plain, AD, tag);
--      BC_ASSERT_TRUE(cipher==pattern_cipher);
--      BC_ASSERT_TRUE(tag==pattern_tag);
--      BC_ASSERT_TRUE(AEADDecrypt<AES256GCM128>(key, IV, pattern_cipher, AD, pattern_tag, plain));
--      BC_ASSERT_TRUE(plain==pattern_plain);
-+      BC_ASSERT_TRUE(AESGCMTest(key, AD, IV, pattern_plain, pattern_cipher, pattern_tag) == 1);
-+      BC_ASSERT_TRUE(cInterfaceAESGCMTest(key, AD, IV, pattern_plain, pattern_cipher, pattern_tag) == 1);
-       /* Test D3.10 */
-       key={0xdb, 0xbc, 0x85, 0x66, 0xd6, 0xf5, 0xb1, 0x58, 0xda, 0x99, 0xa2, 0xff, 0x2e, 0x01, 0xdd, 0xa6, 0x29, 0xb8, 0x9c, 0x34, 0xad, 0x1e, 0x5f, 0xeb, 0xa7, 0x0e, 0x7a, 0xae, 0x43, 0x28, 0x28, 0x9c};
-@@ -962,14 +884,8 @@ static void AEAD(void) {
-       pattern_plain.assign({0xce, 0x20, 0x27, 0xb4, 0x7a, 0x84, 0x32, 0x52, 0x01, 0x34, 0x65, 0x83, 0x4d, 0x75, 0xfd, 0x0f});
-       pattern_cipher.assign({0xdc, 0x03, 0xe5, 0x24, 0x83, 0x0d, 0x30, 0xf8, 0x8e, 0x19, 0x7f, 0x3a, 0xca, 0xce, 0x66, 0xef});
-       pattern_tag={0x99, 0x84, 0xef, 0xf6, 0x90, 0x57, 0x55, 0xd1, 0x83, 0x6f, 0x2d, 0xb0, 0x40, 0x89, 0x63, 0x4c};
--      cipher.resize(pattern_plain.size());
--      plain.resize(pattern_plain.size());
--
--      cipher = AEADEncrypt<AES256GCM128>(key, IV, pattern_plain, AD, tag);
--      BC_ASSERT_TRUE(cipher==pattern_cipher);
--      BC_ASSERT_TRUE(tag==pattern_tag);
--      BC_ASSERT_TRUE(AEADDecrypt<AES256GCM128>(key, IV, pattern_cipher, AD, pattern_tag, plain));
--      BC_ASSERT_TRUE(plain==pattern_plain);
-+      BC_ASSERT_TRUE(AESGCMTest(key, AD, IV, pattern_plain, pattern_cipher, pattern_tag) == 1);
-+      BC_ASSERT_TRUE(cInterfaceAESGCMTest(key, AD, IV, pattern_plain, pattern_cipher, pattern_tag) == 1);
-       /* Test D3.11 */
-       key={0x0e, 0x05, 0x93, 0x5d, 0xf0, 0xc6, 0x93, 0x74, 0x18, 0x92, 0xb7, 0x6f, 0xaf, 0x67, 0x13, 0x3a, 0xbd, 0x2c, 0xf2, 0x03, 0x11, 0x21, 0xbd, 0x8b, 0xb3, 0x81, 0x27, 0xa4, 0xd2, 0xee, 0xde, 0xea};
-@@ -978,14 +894,8 @@ static void AEAD(void) {
-       pattern_plain.assign({0x90, 0xae, 0x61, 0xcf, 0x7b, 0xae, 0xbd, 0x4c, 0xad, 0xe4, 0x94, 0xc5, 0x4a, 0x29, 0xae, 0x70, 0x26, 0x9a, 0xec, 0x71});
-       pattern_cipher.assign({0x6b, 0xe6, 0x5e, 0x56, 0x06, 0x6c, 0x40, 0x56, 0x73, 0x8c, 0x03, 0xfe, 0x23, 0x20, 0x97, 0x4b, 0xa3, 0xf6, 0x5e, 0x09});
-       pattern_tag={0x61, 0x08, 0xdc, 0x41, 0x7b, 0xf3, 0x2f, 0x7f, 0xb7, 0x55, 0x4a, 0xe5, 0x2f, 0x08, 0x8f, 0x87};
--      cipher.resize(pattern_plain.size());
--      plain.resize(pattern_plain.size());
--
--      cipher = AEADEncrypt<AES256GCM128>(key, IV, pattern_plain, AD, tag);
--      BC_ASSERT_TRUE(cipher==pattern_cipher);
--      BC_ASSERT_TRUE(tag==pattern_tag);
--      BC_ASSERT_TRUE(AEADDecrypt<AES256GCM128>(key, IV, pattern_cipher, AD, pattern_tag, plain));
--      BC_ASSERT_TRUE(plain==pattern_plain);
-+      BC_ASSERT_TRUE(AESGCMTest(key, AD, IV, pattern_plain, pattern_cipher, pattern_tag) == 1);
-+      BC_ASSERT_TRUE(cInterfaceAESGCMTest(key, AD, IV, pattern_plain, pattern_cipher, pattern_tag) == 1);
-       /* Test D3.12 */
-       key={0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-@@ -994,14 +904,8 @@ static void AEAD(void) {
-       pattern_plain.assign({0xa2, 0xaa, 0xb3, 0xad, 0x8b, 0x17, 0xac, 0xdd, 0xa2, 0x88, 0x42, 0x6c, 0xd7, 0xc4, 0x29, 0xb7, 0xca, 0x86, 0xb7, 0xac, 0xa0, 0x58, 0x09, 0xc7, 0x0c, 0xe8, 0x2d, 0xb2, 0x57, 0x11, 0xcb, 0x53, 0x02, 0xeb, 0x27, 0x43, 0xb0, 0x36, 0xf3, 0xd7, 0x50, 0xd6, 0xcf, 0x0d, 0xc0, 0xac, 0xb9, 0x29, 0x50, 0xd5, 0x46, 0xdb, 0x30, 0x8f, 0x93, 0xb4, 0xff, 0x24, 0x4a, 0xfa, 0x9d, 0xc7, 0x2b, 0xcd, 0x75, 0x8d, 0x2c});
-       pattern_cipher.assign({0xee, 0x62, 0x55, 0x2a, 0xeb, 0xc0, 0xc3, 0xc7, 0xda, 0xae, 0x12, 0xbb, 0x6c, 0x32, 0xca, 0x5a, 0x00, 0x5f, 0x4a, 0x1a, 0xaa, 0xb0, 0x04, 0xed, 0x0f, 0x0b, 0x30, 0xab, 0xbf, 0x15, 0xac, 0xf4, 0xc5, 0x0c, 0x59, 0x66, 0x2d, 0x4b, 0x44, 0x68, 0x41, 0x95, 0x44, 0xe7, 0xf9, 0x81, 0x97, 0x35, 0x63, 0xce, 0x55, 0x6a, 0xe5, 0x08, 0x59, 0xee, 0x09, 0xb1, 0x4d, 0x31, 0xa0, 0x53, 0x98, 0x6f, 0x9a, 0xc8, 0x9b});
-       pattern_tag={0x9c, 0xd0, 0xdb, 0x93, 0x6e, 0x26, 0xd4, 0x4b, 0xe9, 0x74, 0xba, 0x86, 0x82, 0x85, 0xa2, 0xe1};
--      cipher.resize(pattern_plain.size());
--      plain.resize(pattern_plain.size());
--
--      cipher = AEADEncrypt<AES256GCM128>(key, IV, pattern_plain, AD, tag);
--      BC_ASSERT_TRUE(cipher==pattern_cipher);
--      BC_ASSERT_TRUE(tag==pattern_tag);
--      BC_ASSERT_TRUE(AEADDecrypt<AES256GCM128>(key, IV, pattern_cipher, AD, pattern_tag, plain));
--      BC_ASSERT_TRUE(plain==pattern_plain);
-+      BC_ASSERT_TRUE(AESGCMTest(key, AD, IV, pattern_plain, pattern_cipher, pattern_tag) == 1);
-+      BC_ASSERT_TRUE(cInterfaceAESGCMTest(key, AD, IV, pattern_plain, pattern_cipher, pattern_tag) == 1);
- }
- static void key_wrap_test(){
-@@ -1068,7 +972,6 @@ static void key_wrap_test(){
- static test_t crypto_tests[] = {
-       TEST_NO_TAG("Diffie-Hellman Key exchange", DHM),
-       TEST_NO_TAG("Elliptic Curve Diffie-Hellman Key exchange", ECDH),
--      TEST_NO_TAG("ECDH25519 decaf-mbedtls", ECDH25519compat),
-       TEST_NO_TAG("EdDSA sign and verify", EdDSA),
-       TEST_NO_TAG("Ed25519 to X25519 key conversion", ed25519_to_x25519_keyconversion),
-       TEST_NO_TAG("Sign message and exchange key using the same base secret", sign_and_key_exchange),
diff --git a/bctoolbox-use-after-free.patch b/bctoolbox-use-after-free.patch
deleted file mode 100644 (file)
index 5af587a..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-Remove two functions which return pointer to deleted object:
-bctoolbox-5.2.49/src/containers/map.cc:234:16: error: pointer 'it' used after 'void operator delete(void*)' [-Werror=use-after-free]
-bctoolbox-5.2.49/src/containers/map.cc:239:16: error: pointer 'it' used after 'void operator delete(void*)' [-Werror=use-after-free]
-
---- bctoolbox-5.2.49/src/containers/map.cc.orig        2023-04-06 12:17:19.000000000 +0200
-+++ bctoolbox-5.2.49/src/containers/map.cc     2023-04-08 12:09:02.613758031 +0200
-@@ -228,16 +228,6 @@ extern "C" bctbx_iterator_t *bctbx_itera
- extern "C" bctbx_iterator_t *bctbx_iterator_cchar_get_next(bctbx_iterator_t *it) {
-       return bctbx_iterator_get_next_type<mmap_cchar_t>(it);
- }
--extern "C" bctbx_iterator_t *bctbx_iterator_ullong_get_next_and_delete(bctbx_iterator_t *it) {
--      bctbx_iterator_t * next = bctbx_iterator_ullong_get_next(it);
--      bctbx_iterator_ullong_delete(it);
--      return next;
--}
--extern "C" bctbx_iterator_t *bctbx_iterator_cchar_get_next_and_delete(bctbx_iterator_t *it) {
--      bctbx_iterator_t * next = bctbx_iterator_cchar_get_next(it);
--      bctbx_iterator_cchar_delete(it);
--      return next;
--}
- template<typename T> bool_t bctbx_iterator_equals_type(const bctbx_iterator_t *a,const bctbx_iterator_t *b) {
-       return *(typename T::iterator*)a == *(typename T::iterator*)b;
index 982f08d4c3f3272c1ed37fcc49dad8e3ded4e9ac..102cb54582dcac6adf00771f9d1d73eb28829f2b 100644 (file)
 Summary:       Utility library for software from Belledonne Communications
 Summary(pl.UTF-8):     Biblioteka narzÄ™dziowa dla oprogramowania firmy Belledonne Communications
 Name:          bctoolbox
-Version:       5.2.49
+Version:       5.3.26
 Release:       1
 License:       GPL v3+
 Group:         Libraries
 #Source0Download: https://gitlab.linphone.org/BC/public/bctoolbox/tags
 Source0:       https://gitlab.linphone.org/BC/public/bctoolbox/-/archive/%{version}/%{name}-%{version}.tar.bz2
-# Source0-md5: bd3d6423b8fcc03035109434d74ca4c0
-Patch0:                %{name}-mbedtlsv3.patch
-Patch1:                %{name}-use-after-free.patch
+# Source0-md5: a96dfdc65b3771476abefcf50ad8469b
+Patch0:                %{name}-decaf-shared.patch
 URL:           https://linphone.org/
 BuildRequires: bcunit-devel >= 5.2.0
-BuildRequires: cmake >= 3.2
+BuildRequires: cmake >= 3.22
 BuildRequires: libdecaf-devel >= 1.0.2
-BuildRequires: libstdc++-devel >= 6:4.7
+BuildRequires: libstdc++-devel >= 6:7
 BuildRequires: mbedtls-devel >= %{mbedtls_ver}
 BuildRequires: sed >= 4.0
 Requires:      libdecaf >= 1.0.2
@@ -68,24 +67,30 @@ Statyczne biblioteki bctoolbox.
 %prep
 %setup -q
 %patch0 -p1
-%patch1 -p1
 
 %build
-install -d builddir
-cd builddir
-%cmake .. \
-       %{!?with_static_libs:-DENABLE_STATIC=OFF}
+%if %{with static_libs}
+%cmake -B builddir-static \
+       -DBUILD_SHARED_LIBS=OFF \
+       -DENABLE_UNIT_TESTS=OFF
+
+%{__make} -C builddir-static
+%endif
 
-%{__make}
+%cmake -B builddir
+
+%{__make} -C builddir
 
 %install
 rm -rf $RPM_BUILD_ROOT
 
-%{__make} -C builddir install \
+%if %{with static_libs}
+%{__make} -C builddir-static install \
        DESTDIR=$RPM_BUILD_ROOT
+%endif
 
-# disable completeness check incompatible with split packaging
-%{__sed} -i -e '/^foreach(target .*IMPORT_CHECK_TARGETS/,/^endforeach/d; /^unset(_IMPORT_CHECK_TARGETS)/d' $RPM_BUILD_ROOT%{_datadir}/bctoolbox/cmake/bctoolboxTargets.cmake
+%{__make} -C builddir install \
+       DESTDIR=$RPM_BUILD_ROOT
 
 %clean
 rm -rf $RPM_BUILD_ROOT
@@ -101,14 +106,14 @@ rm -rf $RPM_BUILD_ROOT
 
 %files devel
 %defattr(644,root,root,755)
-%attr(755,root,root) %{_bindir}/bctoolbox_tester
+%attr(755,root,root) %{_bindir}/bctoolbox-tester
 %attr(755,root,root) %{_libdir}/libbctoolbox.so
 %attr(755,root,root) %{_libdir}/libbctoolbox-tester.so
 %{_includedir}/bctoolbox
 %{_pkgconfigdir}/bctoolbox.pc
 %{_pkgconfigdir}/bctoolbox-tester.pc
-%dir %{_datadir}/bctoolbox
-%{_datadir}/bctoolbox/cmake
+%dir %{_datadir}/BCToolbox
+%{_datadir}/BCToolbox/cmake
 
 %if %{with static_libs}
 %files static
This page took 0.315028 seconds and 4 git commands to generate.