aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib/ndpi_main.c3
-rw-r--r--src/lib/protocols/quic.c7
-rw-r--r--src/lib/third_party/include/gcrypt/aes.h271
-rw-r--r--src/lib/third_party/include/gcrypt/aesni.h130
-rw-r--r--src/lib/third_party/include/gcrypt/cipher.h934
-rw-r--r--src/lib/third_party/include/gcrypt/cipher_wrap.h92
-rw-r--r--src/lib/third_party/include/gcrypt/common.h368
-rw-r--r--src/lib/third_party/include/gcrypt/digest.h26
-rw-r--r--src/lib/third_party/include/gcrypt/error.h201
-rw-r--r--src/lib/third_party/include/gcrypt/gcm.h364
-rw-r--r--src/lib/third_party/include/gcrypt_light.h89
-rw-r--r--src/lib/third_party/src/gcrypt/aes.c508
-rw-r--r--src/lib/third_party/src/gcrypt/aesni.c461
-rw-r--r--src/lib/third_party/src/gcrypt/cipher.c591
-rw-r--r--src/lib/third_party/src/gcrypt/cipher_wrap.c252
-rw-r--r--src/lib/third_party/src/gcrypt/digest.c321
-rw-r--r--src/lib/third_party/src/gcrypt/gcm.c667
-rw-r--r--src/lib/third_party/src/gcrypt_light.c375
18 files changed, 5658 insertions, 2 deletions
diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c
index 2740ec8bb..82f24f4aa 100644
--- a/src/lib/ndpi_main.c
+++ b/src/lib/ndpi_main.c
@@ -34,6 +34,9 @@
#ifdef HAVE_LIBGCRYPT
#include <gcrypt.h>
+#else
+#include <gcrypt_light.h>
+#define HAVE_LIBGCRYPT 1
#endif
#include <time.h>
diff --git a/src/lib/protocols/quic.c b/src/lib/protocols/quic.c
index 9ba2eade5..a25fa75df 100644
--- a/src/lib/protocols/quic.c
+++ b/src/lib/protocols/quic.c
@@ -28,6 +28,9 @@
#ifdef HAVE_LIBGCRYPT
#include <gcrypt.h>
+#else
+#define HAVE_LIBGCRYPT 1
+#include <gcrypt_light.h>
#endif
// #define DEBUG_CRYPT
@@ -243,12 +246,12 @@ static uint16_t gquic_get_u16(const uint8_t *buf, uint32_t version)
}
-#ifdef HAVE_LIBGCRYPT
+#if defined(HAVE_LIBGCRYPT)
#ifdef DEBUG_CRYPT
char *__gcry_err(gpg_error_t err, char *buf, size_t buflen)
{
-#ifdef HAVE_LIBGPG_ERROR
+#if defined(HAVE_LIBGPG_ERROR) || defined(LIBGCRYPT_INTERNAL)
gpg_strerror_r(err, buf, buflen);
/* I am not sure if the string will be always null-terminated...
Better safe than sorry */
diff --git a/src/lib/third_party/include/gcrypt/aes.h b/src/lib/third_party/include/gcrypt/aes.h
new file mode 100644
index 000000000..edfee5a7b
--- /dev/null
+++ b/src/lib/third_party/include/gcrypt/aes.h
@@ -0,0 +1,271 @@
+/**
+ * \file aes.h
+ *
+ * \brief This file contains AES definitions and functions.
+ *
+ * The Advanced Encryption Standard (AES) specifies a FIPS-approved
+ * cryptographic algorithm that can be used to protect electronic
+ * data.
+ *
+ * The AES algorithm is a symmetric block cipher that can
+ * encrypt and decrypt information. For more information, see
+ * <em>FIPS Publication 197: Advanced Encryption Standard</em> and
+ * <em>ISO/IEC 18033-2:2006: Information technology -- Security
+ * techniques -- Encryption algorithms -- Part 2: Asymmetric
+ * ciphers</em>.
+ *
+ * The AES-XTS block mode is standardized by NIST SP 800-38E
+ * <https://nvlpubs.nist.gov/nistpubs/legacy/sp/nistspecialpublication800-38e.pdf>
+ * and described in detail by IEEE P1619
+ * <https://ieeexplore.ieee.org/servlet/opac?punumber=4375278>.
+ */
+
+/*
+ * Copyright The Mbed TLS Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MBEDTLS_AES_H
+#define MBEDTLS_AES_H
+
+
+
+/* padlock.c and aesni.c rely on these values! */
+#define MBEDTLS_AES_ENCRYPT 1 /**< AES encryption. */
+#define MBEDTLS_AES_DECRYPT 0 /**< AES decryption. */
+
+/* Error codes in range 0x0020-0x0022 */
+/** Invalid key length. */
+#define MBEDTLS_ERR_AES_INVALID_KEY_LENGTH -0x0020
+/** Invalid data input length. */
+#define MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH -0x0022
+
+/* Error codes in range 0x0021-0x0025 */
+/** Invalid input data. */
+#define MBEDTLS_ERR_AES_BAD_INPUT_DATA -0x0021
+
+#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
+ !defined(inline) && !defined(__cplusplus)
+#define inline __inline
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Regular implementation
+//
+
+/**
+ * \brief The AES context-type definition.
+ */
+typedef struct mbedtls_aes_context
+{
+ int nr; /*!< The number of rounds. */
+ uint32_t *rk; /*!< AES round keys. */
+ uint32_t buf[68]; /*!< Unaligned data buffer. This buffer can
+ hold 32 extra Bytes, which can be used for
+ one of the following purposes:
+ <ul><li>Alignment if VIA padlock is
+ used.</li>
+ <li>Simplifying key expansion in the 256-bit
+ case by generating an extra round key.
+ </li></ul> */
+}
+mbedtls_aes_context;
+
+
+
+/**
+ * \brief This function initializes the specified AES context.
+ *
+ * It must be the first API called before using
+ * the context.
+ *
+ * \param ctx The AES context to initialize. This must not be \c NULL.
+ */
+void mbedtls_aes_init( mbedtls_aes_context *ctx );
+
+/**
+ * \brief This function releases and clears the specified AES context.
+ *
+ * \param ctx The AES context to clear.
+ * If this is \c NULL, this function does nothing.
+ * Otherwise, the context must have been at least initialized.
+ */
+void mbedtls_aes_free( mbedtls_aes_context *ctx );
+
+
+/**
+ * \brief This function sets the encryption key.
+ *
+ * \param ctx The AES context to which the key should be bound.
+ * It must be initialized.
+ * \param key The encryption key.
+ * This must be a readable buffer of size \p keybits bits.
+ * \param keybits The size of data passed in bits. Valid options are:
+ * <ul><li>128 bits</li>
+ * <li>192 bits</li>
+ * <li>256 bits</li></ul>
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
+ */
+MBEDTLS_CHECK_RETURN_TYPICAL
+int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
+ unsigned int keybits );
+
+/**
+ * \brief This function sets the decryption key.
+ *
+ * \param ctx The AES context to which the key should be bound.
+ * It must be initialized.
+ * \param key The decryption key.
+ * This must be a readable buffer of size \p keybits bits.
+ * \param keybits The size of data passed. Valid options are:
+ * <ul><li>128 bits</li>
+ * <li>192 bits</li>
+ * <li>256 bits</li></ul>
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
+ */
+MBEDTLS_CHECK_RETURN_TYPICAL
+int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key,
+ unsigned int keybits );
+
+
+/**
+ * \brief This function performs an AES single-block encryption or
+ * decryption operation.
+ *
+ * It performs the operation defined in the \p mode parameter
+ * (encrypt or decrypt), on the input data buffer defined in
+ * the \p input parameter.
+ *
+ * mbedtls_aes_init(), and either mbedtls_aes_setkey_enc() or
+ * mbedtls_aes_setkey_dec() must be called before the first
+ * call to this API with the same context.
+ *
+ * \param ctx The AES context to use for encryption or decryption.
+ * It must be initialized and bound to a key.
+ * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or
+ * #MBEDTLS_AES_DECRYPT.
+ * \param input The buffer holding the input data.
+ * It must be readable and at least \c 16 Bytes long.
+ * \param output The buffer where the output data will be written.
+ * It must be writeable and at least \c 16 Bytes long.
+
+ * \return \c 0 on success.
+ */
+MBEDTLS_CHECK_RETURN_TYPICAL
+int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
+ int mode,
+ const unsigned char input[16],
+ unsigned char output[16] );
+
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+/**
+ * \brief This function performs an AES-CBC encryption or decryption operation
+ * on full blocks.
+ *
+ * It performs the operation defined in the \p mode
+ * parameter (encrypt/decrypt), on the input data buffer defined in
+ * the \p input parameter.
+ *
+ * It can be called as many times as needed, until all the input
+ * data is processed. mbedtls_aes_init(), and either
+ * mbedtls_aes_setkey_enc() or mbedtls_aes_setkey_dec() must be called
+ * before the first call to this API with the same context.
+ *
+ * \note This function operates on full blocks, that is, the input size
+ * must be a multiple of the AES block size of \c 16 Bytes.
+ *
+ * \note Upon exit, the content of the IV is updated so that you can
+ * call the same function again on the next
+ * block(s) of data and get the same result as if it was
+ * encrypted in one call. This allows a "streaming" usage.
+ * If you need to retain the contents of the IV, you should
+ * either save it manually or use the cipher module instead.
+ *
+ *
+ * \param ctx The AES context to use for encryption or decryption.
+ * It must be initialized and bound to a key.
+ * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or
+ * #MBEDTLS_AES_DECRYPT.
+ * \param length The length of the input data in Bytes. This must be a
+ * multiple of the block size (\c 16 Bytes).
+ * \param iv Initialization vector (updated after use).
+ * It must be a readable and writeable buffer of \c 16 Bytes.
+ * \param input The buffer holding the input data.
+ * It must be readable and of size \p length Bytes.
+ * \param output The buffer holding the output data.
+ * It must be writeable and of size \p length Bytes.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH
+ * on failure.
+ */
+MBEDTLS_CHECK_RETURN_TYPICAL
+int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output );
+#endif /* MBEDTLS_CIPHER_MODE_CBC */
+
+
+
+
+
+/**
+ * \brief Internal AES block encryption function. This is only
+ * exposed to allow overriding it using
+ * \c MBEDTLS_AES_ENCRYPT_ALT.
+ *
+ * \param ctx The AES context to use for encryption.
+ * \param input The plaintext block.
+ * \param output The output (ciphertext) block.
+ *
+ * \return \c 0 on success.
+ */
+MBEDTLS_CHECK_RETURN_TYPICAL
+int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx,
+ const unsigned char input[16],
+ unsigned char output[16] );
+
+/**
+ * \brief Internal AES block decryption function. This is only
+ * exposed to allow overriding it using see
+ * \c MBEDTLS_AES_DECRYPT_ALT.
+ *
+ * \param ctx The AES context to use for decryption.
+ * \param input The ciphertext block.
+ * \param output The output (plaintext) block.
+ *
+ * \return \c 0 on success.
+ */
+MBEDTLS_CHECK_RETURN_TYPICAL
+int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx,
+ const unsigned char input[16],
+ unsigned char output[16] );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* aes.h */
diff --git a/src/lib/third_party/include/gcrypt/aesni.h b/src/lib/third_party/include/gcrypt/aesni.h
new file mode 100644
index 000000000..ca614475d
--- /dev/null
+++ b/src/lib/third_party/include/gcrypt/aesni.h
@@ -0,0 +1,130 @@
+/**
+ * \file aesni.h
+ *
+ * \brief AES-NI for hardware AES acceleration on some Intel processors
+ *
+ * \warning These functions are only for internal use by other library
+ * functions; you must not call them directly.
+ */
+/*
+ * Copyright The Mbed TLS Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef MBEDTLS_AESNI_H
+#define MBEDTLS_AESNI_H
+
+
+
+#define MBEDTLS_AESNI_AES 0x02000000u
+#define MBEDTLS_AESNI_CLMUL 0x00000002u
+
+#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && \
+ ( defined(__amd64__) || defined(__x86_64__) ) && \
+ ! defined(MBEDTLS_HAVE_X86_64)
+#define MBEDTLS_HAVE_X86_64
+#endif
+
+#if defined(MBEDTLS_HAVE_X86_64)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Internal function to detect the AES-NI feature in CPUs.
+ *
+ * \note This function is only for internal use by other library
+ * functions; you must not call it directly.
+ *
+ * \param what The feature to detect
+ * (MBEDTLS_AESNI_AES or MBEDTLS_AESNI_CLMUL)
+ *
+ * \return 1 if CPU has support for the feature, 0 otherwise
+ */
+int mbedtls_aesni_has_support( unsigned int what );
+
+/**
+ * \brief Internal AES-NI AES-ECB block encryption and decryption
+ *
+ * \note This function is only for internal use by other library
+ * functions; you must not call it directly.
+ *
+ * \param ctx AES context
+ * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
+ * \param input 16-byte input block
+ * \param output 16-byte output block
+ *
+ * \return 0 on success (cannot fail)
+ */
+int mbedtls_aesni_crypt_ecb( mbedtls_aes_context *ctx,
+ int mode,
+ const unsigned char input[16],
+ unsigned char output[16] );
+
+/**
+ * \brief Internal GCM multiplication: c = a * b in GF(2^128)
+ *
+ * \note This function is only for internal use by other library
+ * functions; you must not call it directly.
+ *
+ * \param c Result
+ * \param a First operand
+ * \param b Second operand
+ *
+ * \note Both operands and result are bit strings interpreted as
+ * elements of GF(2^128) as per the GCM spec.
+ */
+void mbedtls_aesni_gcm_mult( unsigned char c[16],
+ const unsigned char a[16],
+ const unsigned char b[16] );
+
+/**
+ * \brief Internal round key inversion. This function computes
+ * decryption round keys from the encryption round keys.
+ *
+ * \note This function is only for internal use by other library
+ * functions; you must not call it directly.
+ *
+ * \param invkey Round keys for the equivalent inverse cipher
+ * \param fwdkey Original round keys (for encryption)
+ * \param nr Number of rounds (that is, number of round keys minus one)
+ */
+void mbedtls_aesni_inverse_key( unsigned char *invkey,
+ const unsigned char *fwdkey,
+ int nr );
+
+/**
+ * \brief Internal key expansion for encryption
+ *
+ * \note This function is only for internal use by other library
+ * functions; you must not call it directly.
+ *
+ * \param rk Destination buffer where the round keys are written
+ * \param key Encryption key
+ * \param bits Key size in bits (must be 128, 192 or 256)
+ *
+ * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH
+ */
+int mbedtls_aesni_setkey_enc( unsigned char *rk,
+ const unsigned char *key,
+ size_t bits );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDTLS_HAVE_X86_64 */
+
+#endif /* MBEDTLS_AESNI_H */
diff --git a/src/lib/third_party/include/gcrypt/cipher.h b/src/lib/third_party/include/gcrypt/cipher.h
new file mode 100644
index 000000000..3d67e5f59
--- /dev/null
+++ b/src/lib/third_party/include/gcrypt/cipher.h
@@ -0,0 +1,934 @@
+/**
+ * \file cipher.h
+ *
+ * \brief This file contains an abstraction interface for use with the cipher
+ * primitives provided by the library. It provides a common interface to all of
+ * the available cipher operations.
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ */
+/*
+ * Copyright The Mbed TLS Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MBEDTLS_CIPHER_H
+#define MBEDTLS_CIPHER_H
+
+
+
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
+#define MBEDTLS_CIPHER_MODE_AEAD
+#endif
+
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+#define MBEDTLS_CIPHER_MODE_WITH_PADDING
+#endif
+
+#if defined(MBEDTLS_CIPHER_NULL_CIPHER) || \
+ defined(MBEDTLS_CHACHA20_C)
+#define MBEDTLS_CIPHER_MODE_STREAM
+#endif
+
+#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
+ !defined(inline) && !defined(__cplusplus)
+#define inline __inline
+#endif
+
+/** The selected feature is not available. */
+#define MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE -0x6080
+/** Bad input parameters. */
+#define MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA -0x6100
+/** Failed to allocate memory. */
+#define MBEDTLS_ERR_CIPHER_ALLOC_FAILED -0x6180
+/** Input data contains invalid padding and is rejected. */
+#define MBEDTLS_ERR_CIPHER_INVALID_PADDING -0x6200
+/** Decryption of block requires a full block. */
+#define MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED -0x6280
+/** Authentication failed (for AEAD modes). */
+#define MBEDTLS_ERR_CIPHER_AUTH_FAILED -0x6300
+/** The context is invalid. For example, because it was freed. */
+#define MBEDTLS_ERR_CIPHER_INVALID_CONTEXT -0x6380
+
+#define MBEDTLS_CIPHER_VARIABLE_IV_LEN 0x01 /**< Cipher accepts IVs of variable length. */
+#define MBEDTLS_CIPHER_VARIABLE_KEY_LEN 0x02 /**< Cipher accepts keys of variable length. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Supported cipher types.
+ *
+ * \warning DES is considered weak cipher and its use
+ * constitutes a security risk. Arm recommends considering stronger
+ * ciphers instead.
+ */
+typedef enum {
+ MBEDTLS_CIPHER_ID_NONE = 0, /**< Placeholder to mark the end of cipher ID lists. */
+ MBEDTLS_CIPHER_ID_NULL, /**< The identity cipher, treated as a stream cipher. */
+ MBEDTLS_CIPHER_ID_AES, /**< The AES cipher. */
+ MBEDTLS_CIPHER_ID_DES, /**< The DES cipher. */
+ MBEDTLS_CIPHER_ID_3DES, /**< The Triple DES cipher. */
+ MBEDTLS_CIPHER_ID_CAMELLIA, /**< The Camellia cipher. */
+ MBEDTLS_CIPHER_ID_ARIA, /**< The Aria cipher. */
+ MBEDTLS_CIPHER_ID_CHACHA20, /**< The ChaCha20 cipher. */
+} mbedtls_cipher_id_t;
+
+/**
+ * \brief Supported {cipher type, cipher mode} pairs.
+ *
+ * \warning DES is considered weak cipher and its use
+ * constitutes a security risk. Arm recommends considering stronger
+ * ciphers instead.
+ */
+typedef enum {
+ MBEDTLS_CIPHER_NONE = 0, /**< Placeholder to mark the end of cipher-pair lists. */
+ MBEDTLS_CIPHER_NULL, /**< The identity stream cipher. */
+ MBEDTLS_CIPHER_AES_128_ECB, /**< AES cipher with 128-bit ECB mode. */
+ MBEDTLS_CIPHER_AES_192_ECB, /**< AES cipher with 192-bit ECB mode. */
+ MBEDTLS_CIPHER_AES_256_ECB, /**< AES cipher with 256-bit ECB mode. */
+ MBEDTLS_CIPHER_AES_128_CBC, /**< AES cipher with 128-bit CBC mode. */
+ MBEDTLS_CIPHER_AES_192_CBC, /**< AES cipher with 192-bit CBC mode. */
+ MBEDTLS_CIPHER_AES_256_CBC, /**< AES cipher with 256-bit CBC mode. */
+ MBEDTLS_CIPHER_AES_128_CFB128, /**< AES cipher with 128-bit CFB128 mode. */
+ MBEDTLS_CIPHER_AES_192_CFB128, /**< AES cipher with 192-bit CFB128 mode. */
+ MBEDTLS_CIPHER_AES_256_CFB128, /**< AES cipher with 256-bit CFB128 mode. */
+ MBEDTLS_CIPHER_AES_128_CTR, /**< AES cipher with 128-bit CTR mode. */
+ MBEDTLS_CIPHER_AES_192_CTR, /**< AES cipher with 192-bit CTR mode. */
+ MBEDTLS_CIPHER_AES_256_CTR, /**< AES cipher with 256-bit CTR mode. */
+ MBEDTLS_CIPHER_AES_128_GCM, /**< AES cipher with 128-bit GCM mode. */
+ MBEDTLS_CIPHER_AES_192_GCM, /**< AES cipher with 192-bit GCM mode. */
+ MBEDTLS_CIPHER_AES_256_GCM, /**< AES cipher with 256-bit GCM mode. */
+ MBEDTLS_CIPHER_CAMELLIA_128_ECB, /**< Camellia cipher with 128-bit ECB mode. */
+ MBEDTLS_CIPHER_CAMELLIA_192_ECB, /**< Camellia cipher with 192-bit ECB mode. */
+ MBEDTLS_CIPHER_CAMELLIA_256_ECB, /**< Camellia cipher with 256-bit ECB mode. */
+ MBEDTLS_CIPHER_CAMELLIA_128_CBC, /**< Camellia cipher with 128-bit CBC mode. */
+ MBEDTLS_CIPHER_CAMELLIA_192_CBC, /**< Camellia cipher with 192-bit CBC mode. */
+ MBEDTLS_CIPHER_CAMELLIA_256_CBC, /**< Camellia cipher with 256-bit CBC mode. */
+ MBEDTLS_CIPHER_CAMELLIA_128_CFB128, /**< Camellia cipher with 128-bit CFB128 mode. */
+ MBEDTLS_CIPHER_CAMELLIA_192_CFB128, /**< Camellia cipher with 192-bit CFB128 mode. */
+ MBEDTLS_CIPHER_CAMELLIA_256_CFB128, /**< Camellia cipher with 256-bit CFB128 mode. */
+ MBEDTLS_CIPHER_CAMELLIA_128_CTR, /**< Camellia cipher with 128-bit CTR mode. */
+ MBEDTLS_CIPHER_CAMELLIA_192_CTR, /**< Camellia cipher with 192-bit CTR mode. */
+ MBEDTLS_CIPHER_CAMELLIA_256_CTR, /**< Camellia cipher with 256-bit CTR mode. */
+ MBEDTLS_CIPHER_CAMELLIA_128_GCM, /**< Camellia cipher with 128-bit GCM mode. */
+ MBEDTLS_CIPHER_CAMELLIA_192_GCM, /**< Camellia cipher with 192-bit GCM mode. */
+ MBEDTLS_CIPHER_CAMELLIA_256_GCM, /**< Camellia cipher with 256-bit GCM mode. */
+ MBEDTLS_CIPHER_DES_ECB, /**< DES cipher with ECB mode. */
+ MBEDTLS_CIPHER_DES_CBC, /**< DES cipher with CBC mode. */
+ MBEDTLS_CIPHER_DES_EDE_ECB, /**< DES cipher with EDE ECB mode. */
+ MBEDTLS_CIPHER_DES_EDE_CBC, /**< DES cipher with EDE CBC mode. */
+ MBEDTLS_CIPHER_DES_EDE3_ECB, /**< DES cipher with EDE3 ECB mode. */
+ MBEDTLS_CIPHER_DES_EDE3_CBC, /**< DES cipher with EDE3 CBC mode. */
+ MBEDTLS_CIPHER_AES_128_CCM, /**< AES cipher with 128-bit CCM mode. */
+ MBEDTLS_CIPHER_AES_192_CCM, /**< AES cipher with 192-bit CCM mode. */
+ MBEDTLS_CIPHER_AES_256_CCM, /**< AES cipher with 256-bit CCM mode. */
+ MBEDTLS_CIPHER_AES_128_CCM_STAR_NO_TAG, /**< AES cipher with 128-bit CCM_STAR_NO_TAG mode. */
+ MBEDTLS_CIPHER_AES_192_CCM_STAR_NO_TAG, /**< AES cipher with 192-bit CCM_STAR_NO_TAG mode. */
+ MBEDTLS_CIPHER_AES_256_CCM_STAR_NO_TAG, /**< AES cipher with 256-bit CCM_STAR_NO_TAG mode. */
+ MBEDTLS_CIPHER_CAMELLIA_128_CCM, /**< Camellia cipher with 128-bit CCM mode. */
+ MBEDTLS_CIPHER_CAMELLIA_192_CCM, /**< Camellia cipher with 192-bit CCM mode. */
+ MBEDTLS_CIPHER_CAMELLIA_256_CCM, /**< Camellia cipher with 256-bit CCM mode. */
+ MBEDTLS_CIPHER_CAMELLIA_128_CCM_STAR_NO_TAG, /**< Camellia cipher with 128-bit CCM_STAR_NO_TAG mode. */
+ MBEDTLS_CIPHER_CAMELLIA_192_CCM_STAR_NO_TAG, /**< Camellia cipher with 192-bit CCM_STAR_NO_TAG mode. */
+ MBEDTLS_CIPHER_CAMELLIA_256_CCM_STAR_NO_TAG, /**< Camellia cipher with 256-bit CCM_STAR_NO_TAG mode. */
+ MBEDTLS_CIPHER_ARIA_128_ECB, /**< Aria cipher with 128-bit key and ECB mode. */
+ MBEDTLS_CIPHER_ARIA_192_ECB, /**< Aria cipher with 192-bit key and ECB mode. */
+ MBEDTLS_CIPHER_ARIA_256_ECB, /**< Aria cipher with 256-bit key and ECB mode. */
+ MBEDTLS_CIPHER_ARIA_128_CBC, /**< Aria cipher with 128-bit key and CBC mode. */
+ MBEDTLS_CIPHER_ARIA_192_CBC, /**< Aria cipher with 192-bit key and CBC mode. */
+ MBEDTLS_CIPHER_ARIA_256_CBC, /**< Aria cipher with 256-bit key and CBC mode. */
+ MBEDTLS_CIPHER_ARIA_128_CFB128, /**< Aria cipher with 128-bit key and CFB-128 mode. */
+ MBEDTLS_CIPHER_ARIA_192_CFB128, /**< Aria cipher with 192-bit key and CFB-128 mode. */
+ MBEDTLS_CIPHER_ARIA_256_CFB128, /**< Aria cipher with 256-bit key and CFB-128 mode. */
+ MBEDTLS_CIPHER_ARIA_128_CTR, /**< Aria cipher with 128-bit key and CTR mode. */
+ MBEDTLS_CIPHER_ARIA_192_CTR, /**< Aria cipher with 192-bit key and CTR mode. */
+ MBEDTLS_CIPHER_ARIA_256_CTR, /**< Aria cipher with 256-bit key and CTR mode. */
+ MBEDTLS_CIPHER_ARIA_128_GCM, /**< Aria cipher with 128-bit key and GCM mode. */
+ MBEDTLS_CIPHER_ARIA_192_GCM, /**< Aria cipher with 192-bit key and GCM mode. */
+ MBEDTLS_CIPHER_ARIA_256_GCM, /**< Aria cipher with 256-bit key and GCM mode. */
+ MBEDTLS_CIPHER_ARIA_128_CCM, /**< Aria cipher with 128-bit key and CCM mode. */
+ MBEDTLS_CIPHER_ARIA_192_CCM, /**< Aria cipher with 192-bit key and CCM mode. */
+ MBEDTLS_CIPHER_ARIA_256_CCM, /**< Aria cipher with 256-bit key and CCM mode. */
+ MBEDTLS_CIPHER_ARIA_128_CCM_STAR_NO_TAG, /**< Aria cipher with 128-bit key and CCM_STAR_NO_TAG mode. */
+ MBEDTLS_CIPHER_ARIA_192_CCM_STAR_NO_TAG, /**< Aria cipher with 192-bit key and CCM_STAR_NO_TAG mode. */
+ MBEDTLS_CIPHER_ARIA_256_CCM_STAR_NO_TAG, /**< Aria cipher with 256-bit key and CCM_STAR_NO_TAG mode. */
+ MBEDTLS_CIPHER_AES_128_OFB, /**< AES 128-bit cipher in OFB mode. */
+ MBEDTLS_CIPHER_AES_192_OFB, /**< AES 192-bit cipher in OFB mode. */
+ MBEDTLS_CIPHER_AES_256_OFB, /**< AES 256-bit cipher in OFB mode. */
+ MBEDTLS_CIPHER_AES_128_XTS, /**< AES 128-bit cipher in XTS block mode. */
+ MBEDTLS_CIPHER_AES_256_XTS, /**< AES 256-bit cipher in XTS block mode. */
+ MBEDTLS_CIPHER_CHACHA20, /**< ChaCha20 stream cipher. */
+ MBEDTLS_CIPHER_CHACHA20_POLY1305, /**< ChaCha20-Poly1305 AEAD cipher. */
+ MBEDTLS_CIPHER_AES_128_KW, /**< AES cipher with 128-bit NIST KW mode. */
+ MBEDTLS_CIPHER_AES_192_KW, /**< AES cipher with 192-bit NIST KW mode. */
+ MBEDTLS_CIPHER_AES_256_KW, /**< AES cipher with 256-bit NIST KW mode. */
+ MBEDTLS_CIPHER_AES_128_KWP, /**< AES cipher with 128-bit NIST KWP mode. */
+ MBEDTLS_CIPHER_AES_192_KWP, /**< AES cipher with 192-bit NIST KWP mode. */
+ MBEDTLS_CIPHER_AES_256_KWP, /**< AES cipher with 256-bit NIST KWP mode. */
+} mbedtls_cipher_type_t;
+
+/** Supported cipher modes. */
+typedef enum {
+ MBEDTLS_MODE_NONE = 0, /**< None. */
+ MBEDTLS_MODE_ECB, /**< The ECB cipher mode. */
+ MBEDTLS_MODE_CBC, /**< The CBC cipher mode. */
+ MBEDTLS_MODE_CFB, /**< The CFB cipher mode. */
+ MBEDTLS_MODE_OFB, /**< The OFB cipher mode. */
+ MBEDTLS_MODE_CTR, /**< The CTR cipher mode. */
+ MBEDTLS_MODE_GCM, /**< The GCM cipher mode. */
+ MBEDTLS_MODE_STREAM, /**< The stream cipher mode. */
+ MBEDTLS_MODE_CCM, /**< The CCM cipher mode. */
+ MBEDTLS_MODE_CCM_STAR_NO_TAG, /**< The CCM*-no-tag cipher mode. */
+ MBEDTLS_MODE_XTS, /**< The XTS cipher mode. */
+ MBEDTLS_MODE_CHACHAPOLY, /**< The ChaCha-Poly cipher mode. */
+ MBEDTLS_MODE_KW, /**< The SP800-38F KW mode */
+ MBEDTLS_MODE_KWP, /**< The SP800-38F KWP mode */
+} mbedtls_cipher_mode_t;
+
+/** Supported cipher padding types. */
+typedef enum {
+ MBEDTLS_PADDING_PKCS7 = 0, /**< PKCS7 padding (default). */
+ MBEDTLS_PADDING_ONE_AND_ZEROS, /**< ISO/IEC 7816-4 padding. */
+ MBEDTLS_PADDING_ZEROS_AND_LEN, /**< ANSI X.923 padding. */
+ MBEDTLS_PADDING_ZEROS, /**< Zero padding (not reversible). */
+ MBEDTLS_PADDING_NONE, /**< Never pad (full blocks only). */
+} mbedtls_cipher_padding_t;
+
+/** Type of operation. */
+typedef enum {
+ MBEDTLS_OPERATION_NONE = -1,
+ MBEDTLS_DECRYPT = 0,
+ MBEDTLS_ENCRYPT,
+} mbedtls_operation_t;
+
+enum {
+ /** Undefined key length. */
+ MBEDTLS_KEY_LENGTH_NONE = 0,
+ /** Key length, in bits (including parity), for DES keys. */
+ MBEDTLS_KEY_LENGTH_DES = 64,
+ /** Key length in bits, including parity, for DES in two-key EDE. */
+ MBEDTLS_KEY_LENGTH_DES_EDE = 128,
+ /** Key length in bits, including parity, for DES in three-key EDE. */
+ MBEDTLS_KEY_LENGTH_DES_EDE3 = 192,
+};
+
+/** Maximum length of any IV, in Bytes. */
+/* This should ideally be derived automatically from list of ciphers.
+ * This should be kept in sync with MBEDTLS_SSL_MAX_IV_LENGTH defined
+ * in library/ssl_misc.h. */
+#define MBEDTLS_MAX_IV_LENGTH 16
+
+/** Maximum block size of any cipher, in Bytes. */
+/* This should ideally be derived automatically from list of ciphers.
+ * This should be kept in sync with MBEDTLS_SSL_MAX_BLOCK_LENGTH defined
+ * in library/ssl_misc.h. */
+#define MBEDTLS_MAX_BLOCK_LENGTH 16
+
+/** Maximum key length, in Bytes. */
+/* This should ideally be derived automatically from list of ciphers.
+ * For now, only check whether XTS is enabled which uses 64 Byte keys,
+ * and use 32 Bytes as an upper bound for the maximum key length otherwise.
+ * This should be kept in sync with MBEDTLS_SSL_MAX_BLOCK_LENGTH defined
+ * in library/ssl_misc.h, which however deliberately ignores the case of XTS
+ * since the latter isn't used in SSL/TLS. */
+#define MBEDTLS_MAX_KEY_LENGTH 32
+
+/**
+ * Base cipher information (opaque struct).
+ */
+typedef struct mbedtls_cipher_base_t mbedtls_cipher_base_t;
+
+/**
+ * CMAC context (opaque struct).
+ */
+typedef struct mbedtls_cmac_context_t mbedtls_cmac_context_t;
+
+/**
+ * Cipher information. Allows calling cipher functions
+ * in a generic way.
+ *
+ * \note The library does not support custom cipher info structures,
+ * only built-in structures returned by the functions
+ * mbedtls_cipher_info_from_string(),
+ * mbedtls_cipher_info_from_type(),
+ * mbedtls_cipher_info_from_values(),
+ * mbedtls_cipher_info_from_psa().
+ */
+typedef struct mbedtls_cipher_info_t
+{
+ /** Full cipher identifier. For example,
+ * MBEDTLS_CIPHER_AES_256_CBC.
+ */
+ mbedtls_cipher_type_t type;
+
+ /** The cipher mode. For example, MBEDTLS_MODE_CBC. */
+ mbedtls_cipher_mode_t mode;
+
+ /** The cipher key length, in bits. This is the
+ * default length for variable sized ciphers.
+ * Includes parity bits for ciphers like DES.
+ */
+ unsigned int key_bitlen;
+
+ /** Name of the cipher. */
+ const char * name;
+
+ /** IV or nonce size, in Bytes.
+ * For ciphers that accept variable IV sizes,
+ * this is the recommended size.
+ */
+ unsigned int iv_size;
+
+ /** Bitflag comprised of MBEDTLS_CIPHER_VARIABLE_IV_LEN and
+ * MBEDTLS_CIPHER_VARIABLE_KEY_LEN indicating whether the
+ * cipher supports variable IV or variable key sizes, respectively.
+ */
+ int flags;
+
+ /** The block size, in Bytes. */
+ unsigned int block_size;
+
+ /** Struct for base cipher information and functions. */
+ const mbedtls_cipher_base_t *base;
+
+} mbedtls_cipher_info_t;
+
+/**
+ * Generic cipher context.
+ */
+typedef struct mbedtls_cipher_context_t
+{
+ /** Information about the associated cipher. */
+ const mbedtls_cipher_info_t *cipher_info;
+
+ /** Key length to use. */
+ int key_bitlen;
+
+ /** Operation that the key of the context has been
+ * initialized for.
+ */
+ mbedtls_operation_t operation;
+
+
+ /** Buffer for input that has not been processed yet. */
+ unsigned char unprocessed_data[MBEDTLS_MAX_BLOCK_LENGTH];
+
+ /** Number of Bytes that have not been processed yet. */
+ size_t unprocessed_len;
+
+ /** Current IV or NONCE_COUNTER for CTR-mode, data unit (or sector) number
+ * for XTS-mode. */
+ unsigned char iv[MBEDTLS_MAX_IV_LENGTH];
+
+ /** IV size in Bytes, for ciphers with variable-length IVs. */
+ size_t iv_size;
+
+ /** The cipher-specific context. */
+ void *cipher_ctx;
+
+
+
+} mbedtls_cipher_context_t;
+
+/**
+ * \brief This function retrieves the list of ciphers supported
+ * by the generic cipher module.
+ *
+ * For any cipher identifier in the returned list, you can
+ * obtain the corresponding generic cipher information structure
+ * via mbedtls_cipher_info_from_type(), which can then be used
+ * to prepare a cipher context via mbedtls_cipher_setup().
+ *
+ *
+ * \return A statically-allocated array of cipher identifiers
+ * of type cipher_type_t. The last entry is zero.
+ */
+const int *mbedtls_cipher_list( void );
+
+/**
+ * \brief This function retrieves the cipher-information
+ * structure associated with the given cipher name.
+ *
+ * \param cipher_name Name of the cipher to search for. This must not be
+ * \c NULL.
+ *
+ * \return The cipher information structure associated with the
+ * given \p cipher_name.
+ * \return \c NULL if the associated cipher information is not found.
+ */
+const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name );
+
+/**
+ * \brief This function retrieves the cipher-information
+ * structure associated with the given cipher type.
+ *
+ * \param cipher_type Type of the cipher to search for.
+ *
+ * \return The cipher information structure associated with the
+ * given \p cipher_type.
+ * \return \c NULL if the associated cipher information is not found.
+ */
+const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type );
+
+/**
+ * \brief This function retrieves the cipher-information
+ * structure associated with the given cipher ID,
+ * key size and mode.
+ *
+ * \param cipher_id The ID of the cipher to search for. For example,
+ * #MBEDTLS_CIPHER_ID_AES.
+ * \param key_bitlen The length of the key in bits.
+ * \param mode The cipher mode. For example, #MBEDTLS_MODE_CBC.
+ *
+ * \return The cipher information structure associated with the
+ * given \p cipher_id.
+ * \return \c NULL if the associated cipher information is not found.
+ */
+const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id,
+ int key_bitlen,
+ const mbedtls_cipher_mode_t mode );
+
+/**
+ * \brief Retrieve the identifier for a cipher info structure.
+ *
+ * \param[in] info The cipher info structure to query.
+ * This may be \c NULL.
+ *
+ * \return The full cipher identifier (\c MBEDTLS_CIPHER_xxx).
+ * \return #MBEDTLS_CIPHER_NONE if \p info is \c NULL.
+ */
+static inline mbedtls_cipher_type_t mbedtls_cipher_info_get_type(
+ const mbedtls_cipher_info_t *info )
+{
+ if( info == NULL )
+ return( MBEDTLS_CIPHER_NONE );
+ else
+ return( info->type );
+}
+
+/**
+ * \brief Retrieve the operation mode for a cipher info structure.
+ *
+ * \param[in] info The cipher info structure to query.
+ * This may be \c NULL.
+ *
+ * \return The cipher mode (\c MBEDTLS_MODE_xxx).
+ * \return #MBEDTLS_MODE_NONE if \p info is \c NULL.
+ */
+static inline mbedtls_cipher_mode_t mbedtls_cipher_info_get_mode(
+ const mbedtls_cipher_info_t *info )
+{
+ if( info == NULL )
+ return( MBEDTLS_MODE_NONE );
+ else
+ return( info->mode );
+}
+
+/**
+ * \brief Retrieve the key size for a cipher info structure.
+ *
+ * \param[in] info The cipher info structure to query.
+ * This may be \c NULL.
+ *
+ * \return The key length in bits.
+ * For variable-sized ciphers, this is the default length.
+ * For DES, this includes the parity bits.
+ * \return \c 0 if \p info is \c NULL.
+ */
+static inline size_t mbedtls_cipher_info_get_key_bitlen(
+ const mbedtls_cipher_info_t *info )
+{
+ if( info == NULL )
+ return( 0 );
+ else
+ return( info->key_bitlen );
+}
+
+/**
+ * \brief Retrieve the human-readable name for a
+ * cipher info structure.
+ *
+ * \param[in] info The cipher info structure to query.
+ * This may be \c NULL.
+ *
+ * \return The cipher name, which is a human readable string,
+ * with static storage duration.
+ * \return \c NULL if \c info is \p NULL.
+ */
+static inline const char *mbedtls_cipher_info_get_name(
+ const mbedtls_cipher_info_t *info )
+{
+ if( info == NULL )
+ return( NULL );
+ else
+ return( info->name );
+}
+
+/**
+ * \brief This function returns the size of the IV or nonce
+ * for the cipher info structure, in bytes.
+ *
+ * \param info The cipher info structure. This may be \c NULL.
+ *
+ * \return The recommended IV size.
+ * \return \c 0 for ciphers not using an IV or a nonce.
+ * \return \c 0 if \p info is \c NULL.
+ */
+static inline size_t mbedtls_cipher_info_get_iv_size(
+ const mbedtls_cipher_info_t *info )
+{
+ if( info == NULL )
+ return( 0 );
+
+ return( (size_t) info->iv_size );
+}
+
+/**
+ * \brief This function returns the block size of the given
+ * cipher info structure in bytes.
+ *
+ * \param info The cipher info structure. This may be \c NULL.
+ *
+ * \return The block size of the cipher.
+ * \return \c 1 if the cipher is a stream cipher.
+ * \return \c 0 if \p info is \c NULL.
+ */
+static inline size_t mbedtls_cipher_info_get_block_size(
+ const mbedtls_cipher_info_t *info )
+{
+ if( info == NULL )
+ return( 0 );
+
+ return( (size_t) info->block_size );
+}
+
+/**
+ * \brief This function returns a non-zero value if the key length for
+ * the given cipher is variable.
+ *
+ * \param info The cipher info structure. This may be \c NULL.
+ *
+ * \return Non-zero if the key length is variable, \c 0 otherwise.
+ * \return \c 0 if the given pointer is \c NULL.
+ */
+static inline int mbedtls_cipher_info_has_variable_key_bitlen(
+ const mbedtls_cipher_info_t *info )
+{
+ if( info == NULL )
+ return( 0 );
+
+ return( info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN );
+}
+
+/**
+ * \brief This function returns a non-zero value if the IV size for
+ * the given cipher is variable.
+ *
+ * \param info The cipher info structure. This may be \c NULL.
+ *
+ * \return Non-zero if the IV size is variable, \c 0 otherwise.
+ * \return \c 0 if the given pointer is \c NULL.
+ */
+static inline int mbedtls_cipher_info_has_variable_iv_size(
+ const mbedtls_cipher_info_t *info )
+{
+ if( info == NULL )
+ return( 0 );
+
+ return( info->flags & MBEDTLS_CIPHER_VARIABLE_IV_LEN );
+}
+
+/**
+ * \brief This function initializes a \p cipher_context as NONE.
+ *
+ * \param ctx The context to be initialized. This must not be \c NULL.
+ */
+void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx );
+
+/**
+ * \brief This function returns the block size of the given cipher
+ * in bytes.
+ *
+ * \param ctx The context of the cipher.
+ *
+ * \return The block size of the underlying cipher.
+ * \return \c 1 if the cipher is a stream cipher.
+ * \return \c 0 if \p ctx has not been initialized.
+ */
+static inline unsigned int mbedtls_cipher_get_block_size(
+ const mbedtls_cipher_context_t *ctx )
+{
+ MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, 0 );
+ if( ctx->cipher_info == NULL )
+ return 0;
+
+ return ctx->cipher_info->block_size;
+}
+
+/**
+ * \brief This function returns the mode of operation for
+ * the cipher. For example, MBEDTLS_MODE_CBC.
+ *
+ * \param ctx The context of the cipher. This must be initialized.
+ *
+ * \return The mode of operation.
+ * \return #MBEDTLS_MODE_NONE if \p ctx has not been initialized.
+ */
+static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode(
+ const mbedtls_cipher_context_t *ctx )
+{
+ MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, MBEDTLS_MODE_NONE );
+ if( ctx->cipher_info == NULL )
+ return MBEDTLS_MODE_NONE;
+
+ return ctx->cipher_info->mode;
+}
+
+/**
+ * \brief This function returns the size of the IV or nonce
+ * of the cipher, in Bytes.
+ *
+ * \param ctx The context of the cipher. This must be initialized.
+ *
+ * \return The recommended IV size if no IV has been set.
+ * \return \c 0 for ciphers not using an IV or a nonce.
+ * \return The actual size if an IV has been set.
+ */
+static inline int mbedtls_cipher_get_iv_size(
+ const mbedtls_cipher_context_t *ctx )
+{
+ MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, 0 );
+ if( ctx->cipher_info == NULL )
+ return 0;
+
+ if( ctx->iv_size != 0 )
+ return (int) ctx->iv_size;
+
+ return (int) ctx->cipher_info->iv_size;
+}
+
+/**
+ * \brief This function returns the type of the given cipher.
+ *
+ * \param ctx The context of the cipher. This must be initialized.
+ *
+ * \return The type of the cipher.
+ * \return #MBEDTLS_CIPHER_NONE if \p ctx has not been initialized.
+ */
+static inline mbedtls_cipher_type_t mbedtls_cipher_get_type(
+ const mbedtls_cipher_context_t *ctx )
+{
+ MBEDTLS_INTERNAL_VALIDATE_RET(
+ ctx != NULL, MBEDTLS_CIPHER_NONE );
+ if( ctx->cipher_info == NULL )
+ return MBEDTLS_CIPHER_NONE;
+
+ return ctx->cipher_info->type;
+}
+
+/**
+ * \brief This function returns the name of the given cipher
+ * as a string.
+ *
+ * \param ctx The context of the cipher. This must be initialized.
+ *
+ * \return The name of the cipher.
+ * \return NULL if \p ctx has not been not initialized.
+ */
+static inline const char *mbedtls_cipher_get_name(
+ const mbedtls_cipher_context_t *ctx )
+{
+ MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, 0 );
+ if( ctx->cipher_info == NULL )
+ return 0;
+
+ return ctx->cipher_info->name;
+}
+
+/**
+ * \brief This function returns the key length of the cipher.
+ *
+ * \param ctx The context of the cipher. This must be initialized.
+ *
+ * \return The key length of the cipher in bits.
+ * \return #MBEDTLS_KEY_LENGTH_NONE if ctx \p has not been
+ * initialized.
+ */
+static inline int mbedtls_cipher_get_key_bitlen(
+ const mbedtls_cipher_context_t *ctx )
+{
+ MBEDTLS_INTERNAL_VALIDATE_RET(
+ ctx != NULL, MBEDTLS_KEY_LENGTH_NONE );
+ if( ctx->cipher_info == NULL )
+ return MBEDTLS_KEY_LENGTH_NONE;
+
+ return (int) ctx->cipher_info->key_bitlen;
+}
+
+/**
+ * \brief This function returns the operation of the given cipher.
+ *
+ * \param ctx The context of the cipher. This must be initialized.
+ *
+ * \return The type of operation: #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT.
+ * \return #MBEDTLS_OPERATION_NONE if \p ctx has not been initialized.
+ */
+static inline mbedtls_operation_t mbedtls_cipher_get_operation(
+ const mbedtls_cipher_context_t *ctx )
+{
+ MBEDTLS_INTERNAL_VALIDATE_RET(
+ ctx != NULL, MBEDTLS_OPERATION_NONE );
+ if( ctx->cipher_info == NULL )
+ return MBEDTLS_OPERATION_NONE;
+
+ return ctx->operation;
+}
+
+/**
+ * \brief This function sets the key to use with the given context.
+ *
+ * \param ctx The generic cipher context. This must be initialized and
+ * bound to a cipher information structure.
+ * \param key The key to use. This must be a readable buffer of at
+ * least \p key_bitlen Bits.
+ * \param key_bitlen The key length to use, in Bits.
+ * \param operation The operation that the key will be used for:
+ * #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on
+ * parameter-verification failure.
+ * \return A cipher-specific error code on failure.
+ */
+int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx,
+ const unsigned char *key,
+ int key_bitlen,
+ const mbedtls_operation_t operation );
+
+
+/**
+ * \brief This function sets the initialization vector (IV)
+ * or nonce.
+ *
+ * \note Some ciphers do not use IVs nor nonce. For these
+ * ciphers, this function has no effect.
+ *
+ * \param ctx The generic cipher context. This must be initialized and
+ * bound to a cipher information structure.
+ * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. This
+ * must be a readable buffer of at least \p iv_len Bytes.
+ * \param iv_len The IV length for ciphers with variable-size IV.
+ * This parameter is discarded by ciphers with fixed-size IV.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on
+ * parameter-verification failure.
+ */
+int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx,
+ const unsigned char *iv,
+ size_t iv_len );
+
+/**
+ * \brief This function resets the cipher state.
+ *
+ * \note With non-AEAD ciphers, the order of calls for each message
+ * is as follows:
+ * 1. mbedtls_cipher_set_iv() if the mode uses an IV/nonce.
+ * 2. mbedtls_cipher_reset()
+ * 3. mbedtls_cipher_update() one or more times
+ * 4. mbedtls_cipher_finish()
+ * .
+ * This sequence can be repeated to encrypt or decrypt multiple
+ * messages with the same key.
+ *
+ * \note With AEAD ciphers, the order of calls for each message
+ * is as follows:
+ * 1. mbedtls_cipher_set_iv() if the mode uses an IV/nonce.
+ * 2. mbedtls_cipher_reset()
+ * 3. mbedtls_cipher_update_ad()
+ * 4. mbedtls_cipher_update() one or more times
+ * 5. mbedtls_cipher_finish()
+ * 6. mbedtls_cipher_check_tag() (for decryption) or
+ * mbedtls_cipher_write_tag() (for encryption).
+ * .
+ * This sequence can be repeated to encrypt or decrypt multiple
+ * messages with the same key.
+ *
+ * \param ctx The generic cipher context. This must be bound to a key.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on
+ * parameter-verification failure.
+ */
+int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx );
+
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
+/**
+ * \brief This function adds additional data for AEAD ciphers.
+ * Currently supported with GCM and ChaCha20+Poly1305.
+ *
+ * \param ctx The generic cipher context. This must be initialized.
+ * \param ad The additional data to use. This must be a readable
+ * buffer of at least \p ad_len Bytes.
+ * \param ad_len The length of \p ad in Bytes.
+ *
+ * \return \c 0 on success.
+ * \return A specific error code on failure.
+ */
+int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx,
+ const unsigned char *ad, size_t ad_len );
+#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
+
+/**
+ * \brief The generic cipher update function. It encrypts or
+ * decrypts using the given cipher context. Writes as
+ * many block-sized blocks of data as possible to output.
+ * Any data that cannot be written immediately is either
+ * added to the next block, or flushed when
+ * mbedtls_cipher_finish() is called.
+ * Exception: For MBEDTLS_MODE_ECB, expects a single block
+ * in size. For example, 16 Bytes for AES.
+ *
+ * \param ctx The generic cipher context. This must be initialized and
+ * bound to a key.
+ * \param input The buffer holding the input data. This must be a
+ * readable buffer of at least \p ilen Bytes.
+ * \param ilen The length of the input data.
+ * \param output The buffer for the output data. This must be able to
+ * hold at least `ilen + block_size`. This must not be the
+ * same buffer as \p input.
+ * \param olen The length of the output data, to be updated with the
+ * actual number of Bytes written. This must not be
+ * \c NULL.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on
+ * parameter-verification failure.
+ * \return #MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE on an
+ * unsupported mode for a cipher.
+ * \return A cipher-specific error code on failure.
+ */
+int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx,
+ const unsigned char *input,
+ size_t ilen, unsigned char *output,
+ size_t *olen );
+
+/**
+ * \brief The generic cipher finalization function. If data still
+ * needs to be flushed from an incomplete block, the data
+ * contained in it is padded to the size of
+ * the last block, and written to the \p output buffer.
+ *
+ * \param ctx The generic cipher context. This must be initialized and
+ * bound to a key.
+ * \param output The buffer to write data to. This needs to be a writable
+ * buffer of at least \p block_size Bytes.
+ * \param olen The length of the data written to the \p output buffer.
+ * This may not be \c NULL.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on
+ * parameter-verification failure.
+ * \return #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED on decryption
+ * expecting a full block but not receiving one.
+ * \return #MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding
+ * while decrypting.
+ * \return A cipher-specific error code on failure.
+ */
+int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx,
+ unsigned char *output, size_t *olen );
+
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
+/**
+ * \brief This function writes a tag for AEAD ciphers.
+ * Currently supported with GCM and ChaCha20+Poly1305.
+ * This must be called after mbedtls_cipher_finish().
+ *
+ * \param ctx The generic cipher context. This must be initialized,
+ * bound to a key, and have just completed a cipher
+ * operation through mbedtls_cipher_finish() the tag for
+ * which should be written.
+ * \param tag The buffer to write the tag to. This must be a writable
+ * buffer of at least \p tag_len Bytes.
+ * \param tag_len The length of the tag to write.
+ *
+ * \return \c 0 on success.
+ * \return A specific error code on failure.
+ */
+int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
+ unsigned char *tag, size_t tag_len );
+
+/**
+ * \brief This function checks the tag for AEAD ciphers.
+ * Currently supported with GCM and ChaCha20+Poly1305.
+ * This must be called after mbedtls_cipher_finish().
+ *
+ * \param ctx The generic cipher context. This must be initialized.
+ * \param tag The buffer holding the tag. This must be a readable
+ * buffer of at least \p tag_len Bytes.
+ * \param tag_len The length of the tag to check.
+ *
+ * \return \c 0 on success.
+ * \return A specific error code on failure.
+ */
+int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx,
+ const unsigned char *tag, size_t tag_len );
+#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
+
+/**
+ * \brief The generic all-in-one encryption/decryption function,
+ * for all ciphers except AEAD constructs.
+ *
+ * \param ctx The generic cipher context. This must be initialized.
+ * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers.
+ * This must be a readable buffer of at least \p iv_len
+ * Bytes.
+ * \param iv_len The IV length for ciphers with variable-size IV.
+ * This parameter is discarded by ciphers with fixed-size
+ * IV.
+ * \param input The buffer holding the input data. This must be a
+ * readable buffer of at least \p ilen Bytes.
+ * \param ilen The length of the input data in Bytes.
+ * \param output The buffer for the output data. This must be able to
+ * hold at least `ilen + block_size`. This must not be the
+ * same buffer as \p input.
+ * \param olen The length of the output data, to be updated with the
+ * actual number of Bytes written. This must not be
+ * \c NULL.
+ *
+ * \note Some ciphers do not use IVs nor nonce. For these
+ * ciphers, use \p iv = NULL and \p iv_len = 0.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on
+ * parameter-verification failure.
+ * \return #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED on decryption
+ * expecting a full block but not receiving one.
+ * \return #MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding
+ * while decrypting.
+ * \return A cipher-specific error code on failure.
+ */
+int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx,
+ const unsigned char *iv, size_t iv_len,
+ const unsigned char *input, size_t ilen,
+ unsigned char *output, size_t *olen );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDTLS_CIPHER_H */
diff --git a/src/lib/third_party/include/gcrypt/cipher_wrap.h b/src/lib/third_party/include/gcrypt/cipher_wrap.h
new file mode 100644
index 000000000..a75d04c91
--- /dev/null
+++ b/src/lib/third_party/include/gcrypt/cipher_wrap.h
@@ -0,0 +1,92 @@
+/**
+ * \file cipher_wrap.h
+ *
+ * \brief Cipher wrappers.
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ */
+/*
+ * Copyright The Mbed TLS Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef MBEDTLS_CIPHER_WRAP_H
+#define MBEDTLS_CIPHER_WRAP_H
+
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Base cipher information. The non-mode specific functions and values.
+ */
+struct mbedtls_cipher_base_t
+{
+ /** Base Cipher type (e.g. MBEDTLS_CIPHER_ID_AES) */
+ mbedtls_cipher_id_t cipher;
+
+ /** Encrypt using ECB */
+ int (*ecb_func)( void *ctx, mbedtls_operation_t mode,
+ const unsigned char *input, unsigned char *output );
+
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+ /** Encrypt using CBC */
+ int (*cbc_func)( void *ctx, mbedtls_operation_t mode, size_t length,
+ unsigned char *iv, const unsigned char *input,
+ unsigned char *output );
+#endif
+
+
+
+
+
+
+ /** Set key for encryption purposes */
+ int (*setkey_enc_func)( void *ctx, const unsigned char *key,
+ unsigned int key_bitlen );
+
+ /** Set key for decryption purposes */
+ int (*setkey_dec_func)( void *ctx, const unsigned char *key,
+ unsigned int key_bitlen);
+
+ /** Allocate a new context */
+ void * (*ctx_alloc_func)( void );
+
+ /** Free the given context */
+ void (*ctx_free_func)( void *ctx );
+
+ /** Zero the given context */
+ void (*ctx_zero_func)( void *ctx );
+
+};
+
+typedef struct
+{
+ mbedtls_cipher_type_t type;
+ const mbedtls_cipher_info_t *info;
+} mbedtls_cipher_definition_t;
+
+
+extern const mbedtls_cipher_definition_t mbedtls_cipher_definitions[];
+
+extern int mbedtls_cipher_supported[];
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDTLS_CIPHER_WRAP_H */
diff --git a/src/lib/third_party/include/gcrypt/common.h b/src/lib/third_party/include/gcrypt/common.h
new file mode 100644
index 000000000..d25031bb5
--- /dev/null
+++ b/src/lib/third_party/include/gcrypt/common.h
@@ -0,0 +1,368 @@
+/**
+ * \file common.h
+ *
+ * \brief Utility macros for internal use in the library
+ */
+/*
+ * Copyright The Mbed TLS Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MBEDTLS_LIBRARY_COMMON_H
+#define MBEDTLS_LIBRARY_COMMON_H
+
+#ifdef _MSC_VER
+
+ #include <stdlib.h>
+ #define bswap_64(x) _byteswap_uint64(x)
+
+#elif defined(__APPLE__)
+
+ // Mac OS X / Darwin features
+ #include <libkern/OSByteOrder.h>
+ #define bswap_64(x) OSSwapInt64(x)
+
+#elif defined(__sun) || defined(sun)
+
+ #include <sys/byteorder.h>
+ #define bswap_64(x) BSWAP_64(x)
+
+#elif defined(__FreeBSD__)
+
+ #include <sys/endian.h>
+ #define bswap_64(x) bswap64(x)
+
+#elif defined(__OpenBSD__)
+
+ #include <sys/types.h>
+ #define bswap_64(x) swap64(x)
+
+#elif defined(__NetBSD__)
+
+ #include <sys/types.h>
+ #include <machine/bswap.h>
+ #if defined(__BSWAP_RENAME) && !defined(__bswap_32)
+ #define bswap_64(x) bswap64(x)
+ #endif
+#elif defined(__MINGW32__) || defined(__MINGW64__)
+ #define bswap_64(x) __builtin_bswap64(x)
+#else
+ #include <byteswap.h>
+#endif
+
+
+/** Helper to define a function as static except when building invasive tests.
+ *
+ * If a function is only used inside its own source file and should be
+ * declared `static` to allow the compiler to optimize for code size,
+ * but that function has unit tests, define it with
+ * ```
+ * MBEDTLS_STATIC_TESTABLE int mbedtls_foo(...) { ... }
+ * ```
+ * and declare it in a header in the `library/` directory with
+ * ```
+ * #if defined(MBEDTLS_TEST_HOOKS)
+ * int mbedtls_foo(...);
+ * #endif
+ * ```
+ */
+
+/** Byte Reading Macros
+ *
+ * Given a multi-byte integer \p x, MBEDTLS_BYTE_n retrieves the n-th
+ * byte from x, where byte 0 is the least significant byte.
+ */
+
+#if defined(__LITTLE_ENDIAN__) || defined(_LITTLE_ENDIAN)
+
+#define MBEDTLS_GET_UINT32_LE(b,i) (*(uint32_t *) (&(b)[(i)]))
+#define MBEDTLS_GET_UINT32_BE(b,i) htonl(*(uint32_t *) (&(b)[(i)]))
+#define MBEDTLS_PUT_UINT32_LE(n,b,i) *(uint32_t *) (&(b)[(i)]) = (n);
+#define MBEDTLS_PUT_UINT64_BE(n,b,i) *(uint64_t *) (&(b)[(i)]) = bswap_64(n);
+
+#elif defined(__BIG_ENDIAN__) || defined(__BIG_ENDIAN)
+
+#define MBEDTLS_GET_UINT32_LE(b,i) htonl(*(uint32_t *) (&(b)[(i)]))
+#define MBEDTLS_GET_UINT32_BE(b,i) (*(uint32_t *) (&(b)[(i)]))
+#define MBEDTLS_PUT_UINT32_LE(n,b,i) *(uint32_t *) (&(b)[(i)]) = htonl(n);
+#define MBEDTLS_PUT_UINT64_BE(n,b,i) *(uint64_t *) (&(b)[(i)]) = (n);
+
+#else
+#warning "__BYTE_ORDER MUST BE DEFINED !"
+#endif
+
+
+#define MBEDTLS_BYTE_0( x ) ( (uint8_t) ( ( x ) & 0xff ) )
+#define MBEDTLS_BYTE_1( x ) ( (uint8_t) ( ( ( x ) >> 8 ) & 0xff ) )
+#define MBEDTLS_BYTE_2( x ) ( (uint8_t) ( ( ( x ) >> 16 ) & 0xff ) )
+#define MBEDTLS_BYTE_3( x ) ( (uint8_t) ( ( ( x ) >> 24 ) & 0xff ) )
+
+/**
+ * Get the unsigned 32 bits integer corresponding to four bytes in
+ * big-endian order (MSB first).
+ *
+ * \param data Base address of the memory to get the four bytes from.
+ * \param offset Offset from \p data of the first and most significant
+ * byte of the four bytes to build the 32 bits unsigned
+ * integer from.
+ */
+#ifndef MBEDTLS_GET_UINT32_BE
+#define MBEDTLS_GET_UINT32_BE( data , offset ) \
+ ( \
+ ( (uint32_t) ( data )[( offset ) ] << 24 ) \
+ | ( (uint32_t) ( data )[( offset ) + 1] << 16 ) \
+ | ( (uint32_t) ( data )[( offset ) + 2] << 8 ) \
+ | ( (uint32_t) ( data )[( offset ) + 3] ) \
+ )
+#endif
+
+/**
+ * Put in memory a 32 bits unsigned integer in big-endian order.
+ *
+ * \param n 32 bits unsigned integer to put in memory.
+ * \param data Base address of the memory where to put the 32
+ * bits unsigned integer in.
+ * \param offset Offset from \p data where to put the most significant
+ * byte of the 32 bits unsigned integer \p n.
+ */
+#ifndef MBEDTLS_PUT_UINT32_BE
+#define MBEDTLS_PUT_UINT32_BE( n, data, offset ) \
+{ \
+ ( data )[( offset ) ] = MBEDTLS_BYTE_3( n ); \
+ ( data )[( offset ) + 1] = MBEDTLS_BYTE_2( n ); \
+ ( data )[( offset ) + 2] = MBEDTLS_BYTE_1( n ); \
+ ( data )[( offset ) + 3] = MBEDTLS_BYTE_0( n ); \
+}
+#endif
+
+/**
+ * Get the unsigned 32 bits integer corresponding to four bytes in
+ * little-endian order (LSB first).
+ *
+ * \param data Base address of the memory to get the four bytes from.
+ * \param offset Offset from \p data of the first and least significant
+ * byte of the four bytes to build the 32 bits unsigned
+ * integer from.
+ */
+#ifndef MBEDTLS_GET_UINT32_LE
+#define MBEDTLS_GET_UINT32_LE( data, offset ) \
+ ( \
+ ( (uint32_t) ( data )[( offset ) ] ) \
+ | ( (uint32_t) ( data )[( offset ) + 1] << 8 ) \
+ | ( (uint32_t) ( data )[( offset ) + 2] << 16 ) \
+ | ( (uint32_t) ( data )[( offset ) + 3] << 24 ) \
+ )
+#endif
+
+/**
+ * Put in memory a 32 bits unsigned integer in little-endian order.
+ *
+ * \param n 32 bits unsigned integer to put in memory.
+ * \param data Base address of the memory where to put the 32
+ * bits unsigned integer in.
+ * \param offset Offset from \p data where to put the least significant
+ * byte of the 32 bits unsigned integer \p n.
+ */
+#ifndef MBEDTLS_PUT_UINT32_LE
+#define MBEDTLS_PUT_UINT32_LE( n, data, offset ) \
+{ \
+ ( data )[( offset ) ] = MBEDTLS_BYTE_0( n ); \
+ ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n ); \
+ ( data )[( offset ) + 2] = MBEDTLS_BYTE_2( n ); \
+ ( data )[( offset ) + 3] = MBEDTLS_BYTE_3( n ); \
+}
+#endif
+
+/**
+ * Get the unsigned 16 bits integer corresponding to two bytes in
+ * little-endian order (LSB first).
+ *
+ * \param data Base address of the memory to get the two bytes from.
+ * \param offset Offset from \p data of the first and least significant
+ * byte of the two bytes to build the 16 bits unsigned
+ * integer from.
+ */
+#ifndef MBEDTLS_GET_UINT16_LE
+#define MBEDTLS_GET_UINT16_LE( data, offset ) \
+ ( \
+ ( (uint16_t) ( data )[( offset ) ] ) \
+ | ( (uint16_t) ( data )[( offset ) + 1] << 8 ) \
+ )
+#endif
+
+/**
+ * Put in memory a 16 bits unsigned integer in little-endian order.
+ *
+ * \param n 16 bits unsigned integer to put in memory.
+ * \param data Base address of the memory where to put the 16
+ * bits unsigned integer in.
+ * \param offset Offset from \p data where to put the least significant
+ * byte of the 16 bits unsigned integer \p n.
+ */
+#ifndef MBEDTLS_PUT_UINT16_LE
+#define MBEDTLS_PUT_UINT16_LE( n, data, offset ) \
+{ \
+ ( data )[( offset ) ] = MBEDTLS_BYTE_0( n ); \
+ ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n ); \
+}
+#endif
+
+/**
+ * Get the unsigned 16 bits integer corresponding to two bytes in
+ * big-endian order (MSB first).
+ *
+ * \param data Base address of the memory to get the two bytes from.
+ * \param offset Offset from \p data of the first and most significant
+ * byte of the two bytes to build the 16 bits unsigned
+ * integer from.
+ */
+#ifndef MBEDTLS_GET_UINT16_BE
+#define MBEDTLS_GET_UINT16_BE( data, offset ) \
+ ( \
+ ( (uint16_t) ( data )[( offset ) ] << 8 ) \
+ | ( (uint16_t) ( data )[( offset ) + 1] ) \
+ )
+#endif
+
+/**
+ * Put in memory a 16 bits unsigned integer in big-endian order.
+ *
+ * \param n 16 bits unsigned integer to put in memory.
+ * \param data Base address of the memory where to put the 16
+ * bits unsigned integer in.
+ * \param offset Offset from \p data where to put the most significant
+ * byte of the 16 bits unsigned integer \p n.
+ */
+#ifndef MBEDTLS_PUT_UINT16_BE
+#define MBEDTLS_PUT_UINT16_BE( n, data, offset ) \
+{ \
+ ( data )[( offset ) ] = MBEDTLS_BYTE_1( n ); \
+ ( data )[( offset ) + 1] = MBEDTLS_BYTE_0( n ); \
+}
+#endif
+
+/**
+ * Get the unsigned 64 bits integer corresponding to eight bytes in
+ * big-endian order (MSB first).
+ *
+ * \param data Base address of the memory to get the eight bytes from.
+ * \param offset Offset from \p data of the first and most significant
+ * byte of the eight bytes to build the 64 bits unsigned
+ * integer from.
+ */
+#ifndef MBEDTLS_GET_UINT64_BE
+#define MBEDTLS_GET_UINT64_BE( data, offset ) \
+ ( \
+ ( (uint64_t) ( data )[( offset ) ] << 56 ) \
+ | ( (uint64_t) ( data )[( offset ) + 1] << 48 ) \
+ | ( (uint64_t) ( data )[( offset ) + 2] << 40 ) \
+ | ( (uint64_t) ( data )[( offset ) + 3] << 32 ) \
+ | ( (uint64_t) ( data )[( offset ) + 4] << 24 ) \
+ | ( (uint64_t) ( data )[( offset ) + 5] << 16 ) \
+ | ( (uint64_t) ( data )[( offset ) + 6] << 8 ) \
+ | ( (uint64_t) ( data )[( offset ) + 7] ) \
+ )
+#endif
+
+/**
+ * Put in memory a 64 bits unsigned integer in big-endian order.
+ *
+ * \param n 64 bits unsigned integer to put in memory.
+ * \param data Base address of the memory where to put the 64
+ * bits unsigned integer in.
+ * \param offset Offset from \p data where to put the most significant
+ * byte of the 64 bits unsigned integer \p n.
+ */
+#ifndef MBEDTLS_PUT_UINT64_BE
+#define MBEDTLS_PUT_UINT64_BE( n, data, offset ) \
+{ \
+ ( data )[( offset ) ] = MBEDTLS_BYTE_7( n ); \
+ ( data )[( offset ) + 1] = MBEDTLS_BYTE_6( n ); \
+ ( data )[( offset ) + 2] = MBEDTLS_BYTE_5( n ); \
+ ( data )[( offset ) + 3] = MBEDTLS_BYTE_4( n ); \
+ ( data )[( offset ) + 4] = MBEDTLS_BYTE_3( n ); \
+ ( data )[( offset ) + 5] = MBEDTLS_BYTE_2( n ); \
+ ( data )[( offset ) + 6] = MBEDTLS_BYTE_1( n ); \
+ ( data )[( offset ) + 7] = MBEDTLS_BYTE_0( n ); \
+}
+#endif
+
+/**
+ * Get the unsigned 64 bits integer corresponding to eight bytes in
+ * little-endian order (LSB first).
+ *
+ * \param data Base address of the memory to get the eight bytes from.
+ * \param offset Offset from \p data of the first and least significant
+ * byte of the eight bytes to build the 64 bits unsigned
+ * integer from.
+ */
+#ifndef MBEDTLS_GET_UINT64_LE
+#define MBEDTLS_GET_UINT64_LE( data, offset ) \
+ ( \
+ ( (uint64_t) ( data )[( offset ) + 7] << 56 ) \
+ | ( (uint64_t) ( data )[( offset ) + 6] << 48 ) \
+ | ( (uint64_t) ( data )[( offset ) + 5] << 40 ) \
+ | ( (uint64_t) ( data )[( offset ) + 4] << 32 ) \
+ | ( (uint64_t) ( data )[( offset ) + 3] << 24 ) \
+ | ( (uint64_t) ( data )[( offset ) + 2] << 16 ) \
+ | ( (uint64_t) ( data )[( offset ) + 1] << 8 ) \
+ | ( (uint64_t) ( data )[( offset ) ] ) \
+ )
+#endif
+
+/**
+ * Put in memory a 64 bits unsigned integer in little-endian order.
+ *
+ * \param n 64 bits unsigned integer to put in memory.
+ * \param data Base address of the memory where to put the 64
+ * bits unsigned integer in.
+ * \param offset Offset from \p data where to put the least significant
+ * byte of the 64 bits unsigned integer \p n.
+ */
+#ifndef MBEDTLS_PUT_UINT64_LE
+#define MBEDTLS_PUT_UINT64_LE( n, data, offset ) \
+{ \
+ ( data )[( offset ) ] = MBEDTLS_BYTE_0( n ); \
+ ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n ); \
+ ( data )[( offset ) + 2] = MBEDTLS_BYTE_2( n ); \
+ ( data )[( offset ) + 3] = MBEDTLS_BYTE_3( n ); \
+ ( data )[( offset ) + 4] = MBEDTLS_BYTE_4( n ); \
+ ( data )[( offset ) + 5] = MBEDTLS_BYTE_5( n ); \
+ ( data )[( offset ) + 6] = MBEDTLS_BYTE_6( n ); \
+ ( data )[( offset ) + 7] = MBEDTLS_BYTE_7( n ); \
+}
+#endif
+
+/* Fix MSVC C99 compatible issue
+ * MSVC support __func__ from visual studio 2015( 1900 )
+ * Use MSVC predefine macro to avoid name check fail.
+ */
+#if (defined(_MSC_VER) && ( _MSC_VER <= 1900 ))
+#define /*no-check-names*/ __func__ __FUNCTION__
+#endif
+
+#define ROTL8(x) ( (uint32_t)( ( x ) << 8 ) + (uint32_t)( ( x ) >> 24 ) )
+#define ROTL16(x) ( (uint32_t)( ( x ) << 16 ) + (uint32_t)( ( x ) >> 16 ) )
+#define ROTL24(x) ( (uint32_t)( ( x ) << 24 ) + (uint32_t)( ( x ) >> 8 ) )
+
+#ifndef mbedtls_calloc
+#define mbedtls_calloc calloc
+#endif
+#ifndef mbedtls_free
+#define mbedtls_free free
+#endif
+
+
+#endif /* MBEDTLS_LIBRARY_COMMON_H */
diff --git a/src/lib/third_party/include/gcrypt/digest.h b/src/lib/third_party/include/gcrypt/digest.h
new file mode 100644
index 000000000..a57a901e5
--- /dev/null
+++ b/src/lib/third_party/include/gcrypt/digest.h
@@ -0,0 +1,26 @@
+/*
+ * hmac-sha256.c
+ * Copyright (C) 2017 Adrian Perez <aperez@igalia.com>
+ *
+ * Distributed under terms of the MIT license.
+ */
+
+#ifndef DIGEST_CRYPT_H
+#define DIGEST_CRYPT_H
+
+#define HMAC_SHA256_DIGEST_SIZE 32 /* Same as SHA-256's output size. */
+#define SHA256_DIGEST_SIZE 32
+
+typedef struct sha256_t
+{
+ uint32_t state[8];
+ uint64_t count;
+ unsigned char buffer[64];
+} sha256_t;
+
+void
+hmac_sha256 (uint8_t out[HMAC_SHA256_DIGEST_SIZE],
+ const uint8_t *data, size_t data_len,
+ const uint8_t *key, size_t key_len);
+
+#endif
diff --git a/src/lib/third_party/include/gcrypt/error.h b/src/lib/third_party/include/gcrypt/error.h
new file mode 100644
index 000000000..3fc9b03d9
--- /dev/null
+++ b/src/lib/third_party/include/gcrypt/error.h
@@ -0,0 +1,201 @@
+/**
+ * \file error.h
+ *
+ * \brief Error to string translation
+ */
+/*
+ * Copyright The Mbed TLS Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef MBEDTLS_ERROR_H
+#define MBEDTLS_ERROR_H
+
+
+
+#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
+ !defined(inline) && !defined(__cplusplus)
+#define inline __inline
+#endif
+
+/**
+ * Error code layout.
+ *
+ * Currently we try to keep all error codes within the negative space of 16
+ * bits signed integers to support all platforms (-0x0001 - -0x7FFF). In
+ * addition we'd like to give two layers of information on the error if
+ * possible.
+ *
+ * For that purpose the error codes are segmented in the following manner:
+ *
+ * 16 bit error code bit-segmentation
+ *
+ * 1 bit - Unused (sign bit)
+ * 3 bits - High level module ID
+ * 5 bits - Module-dependent error code
+ * 7 bits - Low level module errors
+ *
+ * For historical reasons, low-level error codes are divided in even and odd,
+ * even codes were assigned first, and -1 is reserved for other errors.
+ *
+ * Low-level module errors (0x0002-0x007E, 0x0001-0x007F)
+ *
+ * Module Nr Codes assigned
+ * ERROR 2 0x006E 0x0001
+ * MPI 7 0x0002-0x0010
+ * GCM 3 0x0012-0x0016 0x0013-0x0013
+ * THREADING 3 0x001A-0x001E
+ * AES 5 0x0020-0x0022 0x0021-0x0025
+ * CAMELLIA 3 0x0024-0x0026 0x0027-0x0027
+ * BASE64 2 0x002A-0x002C
+ * OID 1 0x002E-0x002E 0x000B-0x000B
+ * PADLOCK 1 0x0030-0x0030
+ * DES 2 0x0032-0x0032 0x0033-0x0033
+ * CTR_DBRG 4 0x0034-0x003A
+ * ENTROPY 3 0x003C-0x0040 0x003D-0x003F
+ * NET 13 0x0042-0x0052 0x0043-0x0049
+ * ARIA 4 0x0058-0x005E
+ * ASN1 7 0x0060-0x006C
+ * CMAC 1 0x007A-0x007A
+ * PBKDF2 1 0x007C-0x007C
+ * HMAC_DRBG 4 0x0003-0x0009
+ * CCM 3 0x000D-0x0011
+ * MD5 1 0x002F-0x002F
+ * RIPEMD160 1 0x0031-0x0031
+ * SHA1 1 0x0035-0x0035 0x0073-0x0073
+ * SHA256 1 0x0037-0x0037 0x0074-0x0074
+ * SHA512 1 0x0039-0x0039 0x0075-0x0075
+ * CHACHA20 3 0x0051-0x0055
+ * POLY1305 3 0x0057-0x005B
+ * CHACHAPOLY 2 0x0054-0x0056
+ * PLATFORM 2 0x0070-0x0072
+ *
+ * High-level module nr (3 bits - 0x0...-0x7...)
+ * Name ID Nr of Errors
+ * PEM 1 9
+ * PKCS#12 1 4 (Started from top)
+ * X509 2 20
+ * PKCS5 2 4 (Started from top)
+ * DHM 3 11
+ * PK 3 15 (Started from top)
+ * RSA 4 11
+ * ECP 4 10 (Started from top)
+ * MD 5 5
+ * HKDF 5 1 (Started from top)
+ * SSL 5 2 (Started from 0x5F00)
+ * CIPHER 6 8 (Started from 0x6080)
+ * SSL 6 22 (Started from top, plus 0x6000)
+ * SSL 7 20 (Started from 0x7000, gaps at
+ * 0x7380, 0x7900-0x7980, 0x7A80-0x7E80)
+ *
+ * Module dependent error code (5 bits 0x.00.-0x.F8.)
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Generic error */
+#define MBEDTLS_ERR_ERROR_GENERIC_ERROR -0x0001
+/** This is a bug in the library */
+#define MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED -0x006E
+
+/** Hardware accelerator failed */
+#define MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED -0x0070
+/** The requested feature is not supported by the platform */
+#define MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED -0x0072
+
+/**
+ * \brief Combines a high-level and low-level error code together.
+ *
+ * Wrapper macro for mbedtls_error_add(). See that function for
+ * more details.
+ */
+#define MBEDTLS_ERROR_ADD( high, low ) \
+ mbedtls_error_add( high, low, __FILE__, __LINE__ )
+
+
+/**
+ * \brief Combines a high-level and low-level error code together.
+ *
+ * This function can be called directly however it is usually
+ * called via the #MBEDTLS_ERROR_ADD macro.
+ *
+ * While a value of zero is not a negative error code, it is still an
+ * error code (that denotes success) and can be combined with both a
+ * negative error code or another value of zero.
+ *
+ * \note When invasive testing is enabled via #MBEDTLS_TEST_HOOKS, also try to
+ * call \link mbedtls_test_hook_error_add \endlink.
+ *
+ * \param high high-level error code. See error.h for more details.
+ * \param low low-level error code. See error.h for more details.
+ * \param file file where this error code addition occurred.
+ * \param line line where this error code addition occurred.
+ */
+static inline int mbedtls_error_add( int high, int low,
+ const char *file, int line )
+{
+ (void)file;
+ (void)line;
+
+ return( high + low );
+}
+
+/**
+ * \brief Translate a mbed TLS error code into a string representation,
+ * Result is truncated if necessary and always includes a terminating
+ * null byte.
+ *
+ * \param errnum error code
+ * \param buffer buffer to place representation in
+ * \param buflen length of the buffer
+ */
+void mbedtls_strerror( int errnum, char *buffer, size_t buflen );
+
+/**
+ * \brief Translate the high-level part of an Mbed TLS error code into a string
+ * representation.
+ *
+ * This function returns a const pointer to an un-modifiable string. The caller
+ * must not try to modify the string. It is intended to be used mostly for
+ * logging purposes.
+ *
+ * \param error_code error code
+ *
+ * \return The string representation of the error code, or \c NULL if the error
+ * code is unknown.
+ */
+const char * mbedtls_high_level_strerr( int error_code );
+
+/**
+ * \brief Translate the low-level part of an Mbed TLS error code into a string
+ * representation.
+ *
+ * This function returns a const pointer to an un-modifiable string. The caller
+ * must not try to modify the string. It is intended to be used mostly for
+ * logging purposes.
+ *
+ * \param error_code error code
+ *
+ * \return The string representation of the error code, or \c NULL if the error
+ * code is unknown.
+ */
+const char * mbedtls_low_level_strerr( int error_code );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* error.h */
diff --git a/src/lib/third_party/include/gcrypt/gcm.h b/src/lib/third_party/include/gcrypt/gcm.h
new file mode 100644
index 000000000..19f07111b
--- /dev/null
+++ b/src/lib/third_party/include/gcrypt/gcm.h
@@ -0,0 +1,364 @@
+/**
+ * \file gcm.h
+ *
+ * \brief This file contains GCM definitions and functions.
+ *
+ * The Galois/Counter Mode (GCM) for 128-bit block ciphers is defined
+ * in <em>D. McGrew, J. Viega, The Galois/Counter Mode of Operation
+ * (GCM), Natl. Inst. Stand. Technol.</em>
+ *
+ * For more information on GCM, see <em>NIST SP 800-38D: Recommendation for
+ * Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC</em>.
+ *
+ */
+/*
+ * Copyright The Mbed TLS Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MBEDTLS_GCM_H
+#define MBEDTLS_GCM_H
+
+
+
+
+#define MBEDTLS_GCM_ENCRYPT 1
+#define MBEDTLS_GCM_DECRYPT 0
+
+/** Authenticated decryption failed. */
+#define MBEDTLS_ERR_GCM_AUTH_FAILED -0x0012
+/** Bad input parameters to function. */
+#define MBEDTLS_ERR_GCM_BAD_INPUT -0x0014
+/** An output buffer is too small. */
+#define MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL -0x0016
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * \brief The GCM context structure.
+ */
+typedef struct mbedtls_gcm_context
+{
+ mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */
+ uint64_t HL[16]; /*!< Precalculated HTable low. */
+ uint64_t HH[16]; /*!< Precalculated HTable high. */
+ uint64_t len; /*!< The total length of the encrypted data. */
+ uint64_t add_len; /*!< The total length of the additional data. */
+ unsigned char base_ectr[16]; /*!< The first ECTR for tag. */
+ unsigned char y[16]; /*!< The Y working value. */
+ unsigned char buf[16]; /*!< The buf working value. */
+ int mode; /*!< The operation to perform:
+ #MBEDTLS_GCM_ENCRYPT or
+ #MBEDTLS_GCM_DECRYPT. */
+}
+mbedtls_gcm_context;
+
+
+/**
+ * \brief This function initializes the specified GCM context,
+ * to make references valid, and prepares the context
+ * for mbedtls_gcm_setkey() or mbedtls_gcm_free().
+ *
+ * The function does not bind the GCM context to a particular
+ * cipher, nor set the key. For this purpose, use
+ * mbedtls_gcm_setkey().
+ *
+ * \param ctx The GCM context to initialize. This must not be \c NULL.
+ */
+void mbedtls_gcm_init( mbedtls_gcm_context *ctx, void *aes_ctx );
+
+/**
+ * \brief This function associates a GCM context with a
+ * cipher algorithm and a key.
+ *
+ * \param ctx The GCM context. This must be initialized.
+ * \param cipher The 128-bit block cipher to use.
+ * \param key The encryption key. This must be a readable buffer of at
+ * least \p keybits bits.
+ * \param keybits The key size in bits. Valid options are:
+ * <ul><li>128 bits</li>
+ * <li>192 bits</li>
+ * <li>256 bits</li></ul>
+ *
+ * \return \c 0 on success.
+ * \return A cipher-specific error code on failure.
+ */
+int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx,
+ mbedtls_cipher_id_t cipher,
+ const unsigned char *key,
+ unsigned int keybits );
+
+/**
+ * \brief This function performs GCM encryption or decryption of a buffer.
+ *
+ * \note For encryption, the output buffer can be the same as the
+ * input buffer. For decryption, the output buffer cannot be
+ * the same as input buffer. If the buffers overlap, the output
+ * buffer must trail at least 8 Bytes behind the input buffer.
+ *
+ * \warning When this function performs a decryption, it outputs the
+ * authentication tag and does not verify that the data is
+ * authentic. You should use this function to perform encryption
+ * only. For decryption, use mbedtls_gcm_auth_decrypt() instead.
+ *
+ * \param ctx The GCM context to use for encryption or decryption. This
+ * must be initialized.
+ * \param mode The operation to perform:
+ * - #MBEDTLS_GCM_ENCRYPT to perform authenticated encryption.
+ * The ciphertext is written to \p output and the
+ * authentication tag is written to \p tag.
+ * - #MBEDTLS_GCM_DECRYPT to perform decryption.
+ * The plaintext is written to \p output and the
+ * authentication tag is written to \p tag.
+ * Note that this mode is not recommended, because it does
+ * not verify the authenticity of the data. For this reason,
+ * you should use mbedtls_gcm_auth_decrypt() instead of
+ * calling this function in decryption mode.
+ * \param length The length of the input data, which is equal to the length
+ * of the output data.
+ * \param iv The initialization vector. This must be a readable buffer of
+ * at least \p iv_len Bytes.
+ * \param iv_len The length of the IV.
+ * \param add The buffer holding the additional data. This must be of at
+ * least that size in Bytes.
+ * \param add_len The length of the additional data.
+ * \param input The buffer holding the input data. If \p length is greater
+ * than zero, this must be a readable buffer of at least that
+ * size in Bytes.
+ * \param output The buffer for holding the output data. If \p length is greater
+ * than zero, this must be a writable buffer of at least that
+ * size in Bytes.
+ * \param tag_len The length of the tag to generate.
+ * \param tag The buffer for holding the tag. This must be a writable
+ * buffer of at least \p tag_len Bytes.
+ *
+ * \return \c 0 if the encryption or decryption was performed
+ * successfully. Note that in #MBEDTLS_GCM_DECRYPT mode,
+ * this does not indicate that the data is authentic.
+ * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths or pointers are
+ * not valid or a cipher-specific error code if the encryption
+ * or decryption failed.
+ */
+int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx,
+ int mode,
+ size_t length,
+ const unsigned char *iv,
+ size_t iv_len,
+ const unsigned char *add,
+ size_t add_len,
+ const unsigned char *input,
+ unsigned char *output,
+ size_t tag_len,
+ unsigned char *tag );
+
+/**
+ * \brief This function performs a GCM authenticated decryption of a
+ * buffer.
+ *
+ * \note For decryption, the output buffer cannot be the same as
+ * input buffer. If the buffers overlap, the output buffer
+ * must trail at least 8 Bytes behind the input buffer.
+ *
+ * \param ctx The GCM context. This must be initialized.
+ * \param length The length of the ciphertext to decrypt, which is also
+ * the length of the decrypted plaintext.
+ * \param iv The initialization vector. This must be a readable buffer
+ * of at least \p iv_len Bytes.
+ * \param iv_len The length of the IV.
+ * \param add The buffer holding the additional data. This must be of at
+ * least that size in Bytes.
+ * \param add_len The length of the additional data.
+ * \param tag The buffer holding the tag to verify. This must be a
+ * readable buffer of at least \p tag_len Bytes.
+ * \param tag_len The length of the tag to verify.
+ * \param input The buffer holding the ciphertext. If \p length is greater
+ * than zero, this must be a readable buffer of at least that
+ * size.
+ * \param output The buffer for holding the decrypted plaintext. If \p length
+ * is greater than zero, this must be a writable buffer of at
+ * least that size.
+ *
+ * \return \c 0 if successful and authenticated.
+ * \return #MBEDTLS_ERR_GCM_AUTH_FAILED if the tag does not match.
+ * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths or pointers are
+ * not valid or a cipher-specific error code if the decryption
+ * failed.
+ */
+int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx,
+ size_t length,
+ const unsigned char *iv,
+ size_t iv_len,
+ const unsigned char *add,
+ size_t add_len,
+ const unsigned char *tag,
+ size_t tag_len,
+ const unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief This function starts a GCM encryption or decryption
+ * operation.
+ *
+ * \param ctx The GCM context. This must be initialized.
+ * \param mode The operation to perform: #MBEDTLS_GCM_ENCRYPT or
+ * #MBEDTLS_GCM_DECRYPT.
+ * \param iv The initialization vector. This must be a readable buffer of
+ * at least \p iv_len Bytes.
+ * \param iv_len The length of the IV.
+ *
+ * \return \c 0 on success.
+ */
+int mbedtls_gcm_starts( mbedtls_gcm_context *ctx,
+ int mode,
+ const unsigned char *iv,
+ size_t iv_len );
+
+/**
+ * \brief This function feeds an input buffer as associated data
+ * (authenticated but not encrypted data) in a GCM
+ * encryption or decryption operation.
+ *
+ * Call this function after mbedtls_gcm_starts() to pass
+ * the associated data. If the associated data is empty,
+ * you do not need to call this function. You may not
+ * call this function after calling mbedtls_cipher_update().
+ *
+ * \param ctx The GCM context. This must have been started with
+ * mbedtls_gcm_starts() and must not have yet received
+ * any input with mbedtls_gcm_update().
+ * \param add The buffer holding the additional data, or \c NULL
+ * if \p add_len is \c 0.
+ * \param add_len The length of the additional data. If \c 0,
+ * \p add may be \c NULL.
+ *
+ * \return \c 0 on success.
+ */
+int mbedtls_gcm_update_ad( mbedtls_gcm_context *ctx,
+ const unsigned char *add,
+ size_t add_len );
+
+/**
+ * \brief This function feeds an input buffer into an ongoing GCM
+ * encryption or decryption operation.
+ *
+ * You may call this function zero, one or more times
+ * to pass successive parts of the input: the plaintext to
+ * encrypt, or the ciphertext (not including the tag) to
+ * decrypt. After the last part of the input, call
+ * mbedtls_gcm_finish().
+ *
+ * This function may produce output in one of the following
+ * ways:
+ * - Immediate output: the output length is always equal
+ * to the input length.
+ * - Buffered output: the output consists of a whole number
+ * of 16-byte blocks. If the total input length so far
+ * (not including associated data) is 16 \* *B* + *A*
+ * with *A* < 16 then the total output length is 16 \* *B*.
+ *
+ * In particular:
+ * - It is always correct to call this function with
+ * \p output_size >= \p input_length + 15.
+ * - If \p input_length is a multiple of 16 for all the calls
+ * to this function during an operation, then it is
+ * correct to use \p output_size = \p input_length.
+ *
+ * \note For decryption, the output buffer cannot be the same as
+ * input buffer. If the buffers overlap, the output buffer
+ * must trail at least 8 Bytes behind the input buffer.
+ *
+ * \param ctx The GCM context. This must be initialized.
+ * \param input The buffer holding the input data. If \p input_length
+ * is greater than zero, this must be a readable buffer
+ * of at least \p input_length bytes.
+ * \param input_length The length of the input data in bytes.
+ * \param output The buffer for the output data. If \p output_size
+ * is greater than zero, this must be a writable buffer of
+ * of at least \p output_size bytes.
+ * \param output_size The size of the output buffer in bytes.
+ * See the function description regarding the output size.
+ * \param output_length On success, \p *output_length contains the actual
+ * length of the output written in \p output.
+ * On failure, the content of \p *output_length is
+ * unspecified.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure:
+ * total input length too long,
+ * unsupported input/output buffer overlap detected,
+ * or \p output_size too small.
+ */
+int mbedtls_gcm_update( mbedtls_gcm_context *ctx,
+ const unsigned char *input, size_t input_length,
+ unsigned char *output, size_t output_size,
+ size_t *output_length );
+
+/**
+ * \brief This function finishes the GCM operation and generates
+ * the authentication tag.
+ *
+ * It wraps up the GCM stream, and generates the
+ * tag. The tag can have a maximum length of 16 Bytes.
+ *
+ * \param ctx The GCM context. This must be initialized.
+ * \param tag The buffer for holding the tag. This must be a writable
+ * buffer of at least \p tag_len Bytes.
+ * \param tag_len The length of the tag to generate. This must be at least
+ * four.
+ * \param output The buffer for the final output.
+ * If \p output_size is nonzero, this must be a writable
+ * buffer of at least \p output_size bytes.
+ * \param output_size The size of the \p output buffer in bytes.
+ * This must be large enough for the output that
+ * mbedtls_gcm_update() has not produced. In particular:
+ * - If mbedtls_gcm_update() produces immediate output,
+ * or if the total input size is a multiple of \c 16,
+ * then mbedtls_gcm_finish() never produces any output,
+ * so \p output_size can be \c 0.
+ * - \p output_size never needs to be more than \c 15.
+ * \param output_length On success, \p *output_length contains the actual
+ * length of the output written in \p output.
+ * On failure, the content of \p *output_length is
+ * unspecified.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure:
+ * invalid value of \p tag_len,
+ * or \p output_size too small.
+ */
+int mbedtls_gcm_finish( mbedtls_gcm_context *ctx,
+ unsigned char *output, size_t output_size,
+ size_t *output_length,
+ unsigned char *tag, size_t tag_len );
+
+/**
+ * \brief This function clears a GCM context and the underlying
+ * cipher sub-context.
+ *
+ * \param ctx The GCM context to clear. If this is \c NULL, the call has
+ * no effect. Otherwise, this must be initialized.
+ */
+void mbedtls_gcm_free( mbedtls_gcm_context *ctx );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* gcm.h */
diff --git a/src/lib/third_party/include/gcrypt_light.h b/src/lib/third_party/include/gcrypt_light.h
new file mode 100644
index 000000000..de77c8e38
--- /dev/null
+++ b/src/lib/third_party/include/gcrypt_light.h
@@ -0,0 +1,89 @@
+
+#ifndef GCRY_LIGHT_H
+#define GCRY_LIGHT_H
+
+#define LIBGCRYPT_INTERNAL
+
+#define HMAC_SHA256_DIGEST_SIZE 32 /* Same as SHA-256's output size. */
+#define SHA256_DIGEST_SIZE 32
+#define GCRY_MD_BUFF_SIZE 256
+
+#define GCRY_CIPHER_AES128 7
+#define GCRY_CIPHER_AES256 8
+#define GCRY_CIPHER_MODE_ECB 1
+#define GCRY_CIPHER_MODE_GCM 8
+
+#define GCRY_MD_SHA256 8
+#define GCRY_MD_FLAG_HMAC 2
+#define GPG_ERR_NO_ERROR 0
+#define GPG_ERR_KEY -1
+#define GPG_ERR_ANY -2
+#define GPG_ERR_INV_ARG -3
+#define GCRYCTL_INITIALIZATION_FINISHED_P 1,0
+#define GCRYCTL_INITIALIZATION_FINISHED 2
+#define GCRYCTL_RESET 3
+
+#define GCRY_AES_KEY_SIZE 32
+#define GCRY_AES_AUTH_SIZE 128
+#define GCRY_AES_TAG_SIZE 32
+#define GCRY_AES_IV_SIZE 12
+
+typedef int gcry_error_t;
+typedef gcry_error_t gpg_error_t;
+
+struct gcry_md_hd {
+ uint8_t key[64],out[HMAC_SHA256_DIGEST_SIZE];
+ uint8_t data_buf[GCRY_MD_BUFF_SIZE];
+ uint32_t key_len;
+ uint32_t data_len;
+};
+typedef struct gcry_md_hd * gcry_md_hd_t;
+
+struct gcry_cipher_hd {
+ int algo,mode;
+ size_t keylen,authlen,taglen,ivlen;
+ uint8_t s_key:1,s_auth:1,s_iv:1,s_crypt_ok:1;
+ uint8_t auth[GCRY_AES_AUTH_SIZE];
+ uint8_t tag[GCRY_AES_TAG_SIZE];
+ uint8_t iv[GCRY_AES_IV_SIZE];
+ union {
+ struct mbedtls_aes_context *ecb;
+ struct mbedtls_gcm_context *gcm;
+ } ctx;
+};
+
+typedef struct gcry_cipher_hd * gcry_cipher_hd_t;
+
+int gcry_control (int, int);
+const char *gcry_check_version(void *);
+char *gpg_strerror_r(gcry_error_t, char *, size_t);
+
+gcry_error_t gcry_md_open (gcry_md_hd_t *h, int algo, int flags);
+void gcry_md_close (gcry_md_hd_t h);
+void gcry_md_reset (gcry_md_hd_t h);
+
+gcry_error_t gcry_md_setkey (gcry_md_hd_t h, const uint8_t *key, size_t key_len);
+gcry_error_t gcry_md_write (gcry_md_hd_t h, const uint8_t *data, size_t data_len);
+uint8_t *gcry_md_read (gcry_md_hd_t h, int flag);
+
+size_t gcry_md_get_algo_dlen (int algo);
+int gcry_md_get_algo (gcry_md_hd_t h);
+
+gcry_error_t gcry_cipher_open (gcry_cipher_hd_t *handle, int algo, int mode, unsigned int flags);
+void gcry_cipher_close (gcry_cipher_hd_t h);
+gcry_error_t gcry_cipher_ctl (gcry_cipher_hd_t h, int cmd, void *data, size_t len);
+gcry_error_t gcry_cipher_reset (gcry_cipher_hd_t h);
+gcry_error_t gcry_cipher_setiv (gcry_cipher_hd_t h, const void *iv, size_t ivlen);
+gcry_error_t gcry_cipher_setkey (gcry_cipher_hd_t h, const void *key, size_t keylen);
+gcry_error_t gcry_cipher_checktag (gcry_cipher_hd_t h, const void *intag, size_t taglen);
+gcry_error_t gcry_cipher_authenticate (gcry_cipher_hd_t h, const void *abuf, size_t abuflen);
+gcry_error_t gcry_cipher_encrypt (gcry_cipher_hd_t h, void *out, size_t outsize,
+ const void *in, size_t inlen);
+gcry_error_t gcry_cipher_decrypt (gcry_cipher_hd_t h, void *out, size_t outsize,
+ const void *in, size_t inlen);
+
+size_t gcry_cipher_get_algo_keylen (int algo);
+
+#endif /* GCRY_LIGHT_H */
+
+/* vim: set ts=4 sw=4 et foldmethod=marker foldmarker={{{{,}}}}: */
diff --git a/src/lib/third_party/src/gcrypt/aes.c b/src/lib/third_party/src/gcrypt/aes.c
new file mode 100644
index 000000000..61dc2137a
--- /dev/null
+++ b/src/lib/third_party/src/gcrypt/aes.c
@@ -0,0 +1,508 @@
+/*
+ * FIPS-197 compliant AES implementation
+ *
+ * Copyright The Mbed TLS Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * The AES block cipher was designed by Vincent Rijmen and Joan Daemen.
+ *
+ * http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf
+ * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
+ */
+
+
+/* Parameter validation macros based on platform_util.h */
+#define AES_VALIDATE_RET( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_AES_BAD_INPUT_DATA )
+#define AES_VALIDATE( cond ) MBEDTLS_INTERNAL_VALIDATE( cond )
+
+/*
+ * Forward S-box & tables
+ */
+static unsigned char FSb[256];
+static uint32_t FT0[256];
+static uint32_t FT1[256];
+static uint32_t FT2[256];
+static uint32_t FT3[256];
+
+/*
+ * Reverse S-box & tables
+ */
+static unsigned char RSb[256];
+static uint32_t RT0[256];
+static uint32_t RT1[256];
+static uint32_t RT2[256];
+static uint32_t RT3[256];
+
+/*
+ * Round constants
+ */
+static uint32_t RCON[10];
+
+/*
+ * Tables generation code
+ */
+#define XTIME(x) ( ( (x) << 1 ) ^ ( ( (x) & 0x80 ) ? 0x1B : 0x00 ) )
+#define MUL(x,y) ( ( (x) && (y) ) ? pow[(log[(x)]+log[(y)]) % 255] : 0 )
+
+static int aes_init_done = 0;
+int aes_aesni_has_support = 0;
+
+static void aes_gen_tables( void )
+{
+ int i, x, y, z;
+ int pow[256];
+ int log[256];
+
+#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
+ if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) )
+ aes_aesni_has_support = 1;
+#endif
+
+ /*
+ * compute pow and log tables over GF(2^8)
+ */
+ for( i = 0, x = 1; i < 256; i++ )
+ {
+ pow[i] = x;
+ log[x] = i;
+ x = MBEDTLS_BYTE_0( x ^ XTIME( x ) );
+ }
+
+ /*
+ * calculate the round constants
+ */
+ for( i = 0, x = 1; i < 10; i++ )
+ {
+ RCON[i] = (uint32_t) x;
+ x = MBEDTLS_BYTE_0( XTIME( x ) );
+ }
+
+ /*
+ * generate the forward and reverse S-boxes
+ */
+ FSb[0x00] = 0x63;
+ RSb[0x63] = 0x00;
+
+ for( i = 1; i < 256; i++ )
+ {
+ x = pow[255 - log[i]];
+
+ y = x; y = MBEDTLS_BYTE_0( ( y << 1 ) | ( y >> 7 ) );
+ x ^= y; y = MBEDTLS_BYTE_0( ( y << 1 ) | ( y >> 7 ) );
+ x ^= y; y = MBEDTLS_BYTE_0( ( y << 1 ) | ( y >> 7 ) );
+ x ^= y; y = MBEDTLS_BYTE_0( ( y << 1 ) | ( y >> 7 ) );
+ x ^= y ^ 0x63;
+
+ FSb[i] = (unsigned char) x;
+ RSb[x] = (unsigned char) i;
+ }
+
+ /*
+ * generate the forward and reverse tables
+ */
+ for( i = 0; i < 256; i++ )
+ {
+ x = FSb[i];
+ y = MBEDTLS_BYTE_0( XTIME( x ) );
+ z = MBEDTLS_BYTE_0( y ^ x );
+
+ FT0[i] = ( (uint32_t) y ) ^
+ ( (uint32_t) x << 8 ) ^
+ ( (uint32_t) x << 16 ) ^
+ ( (uint32_t) z << 24 );
+
+ FT1[i] = ROTL8( FT0[i] );
+ FT2[i] = ROTL8( FT1[i] );
+ FT3[i] = ROTL8( FT2[i] );
+
+ x = RSb[i];
+
+ RT0[i] = ( (uint32_t) MUL( 0x0E, x ) ) ^
+ ( (uint32_t) MUL( 0x09, x ) << 8 ) ^
+ ( (uint32_t) MUL( 0x0D, x ) << 16 ) ^
+ ( (uint32_t) MUL( 0x0B, x ) << 24 );
+
+ RT1[i] = ROTL8( RT0[i] );
+ RT2[i] = ROTL8( RT1[i] );
+ RT3[i] = ROTL8( RT2[i] );
+ }
+}
+
+#define AES_RT0(idx) RT0[idx]
+#define AES_RT1(idx) RT1[idx]
+#define AES_RT2(idx) RT2[idx]
+#define AES_RT3(idx) RT3[idx]
+
+#define AES_FT0(idx) FT0[idx]
+#define AES_FT1(idx) FT1[idx]
+#define AES_FT2(idx) FT2[idx]
+#define AES_FT3(idx) FT3[idx]
+
+void mbedtls_aes_init( mbedtls_aes_context *ctx )
+{
+ AES_VALIDATE( ctx != NULL );
+
+ memset( ctx, 0, sizeof( mbedtls_aes_context ) );
+}
+
+void mbedtls_aes_free( mbedtls_aes_context *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+ // mbedtls_platform_zeroize( ctx, sizeof( mbedtls_aes_context ) );
+}
+
+
+/*
+ * AES key schedule (encryption)
+ */
+int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
+ unsigned int keybits )
+{
+ unsigned int i;
+ uint32_t *RK;
+
+ AES_VALIDATE_RET( ctx != NULL );
+ AES_VALIDATE_RET( key != NULL );
+
+ switch( keybits )
+ {
+ case 128: ctx->nr = 10; break;
+ case 192: ctx->nr = 12; break;
+ case 256: ctx->nr = 14; break;
+ default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
+ }
+
+ if( aes_init_done == 0 )
+ {
+ aes_gen_tables();
+ aes_init_done = 1;
+ }
+
+ ctx->rk = RK = ctx->buf;
+
+#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
+ if( aes_aesni_has_support )
+ return( mbedtls_aesni_setkey_enc( (unsigned char *) ctx->rk, key, keybits ) );
+#endif
+
+ for( i = 0; i < ( keybits >> 5 ); i++ )
+ {
+ RK[i] = MBEDTLS_GET_UINT32_LE( key, i << 2 );
+ }
+
+ switch( ctx->nr )
+ {
+ case 10:
+
+ for( i = 0; i < 10; i++, RK += 4 )
+ {
+ RK[4] = RK[0] ^ RCON[i] ^
+ ( (uint32_t) FSb[ MBEDTLS_BYTE_1( RK[3] ) ] ) ^
+ ( (uint32_t) FSb[ MBEDTLS_BYTE_2( RK[3] ) ] << 8 ) ^
+ ( (uint32_t) FSb[ MBEDTLS_BYTE_3( RK[3] ) ] << 16 ) ^
+ ( (uint32_t) FSb[ MBEDTLS_BYTE_0( RK[3] ) ] << 24 );
+
+ RK[5] = RK[1] ^ RK[4];
+ RK[6] = RK[2] ^ RK[5];
+ RK[7] = RK[3] ^ RK[6];
+ }
+ break;
+
+ case 12:
+
+ for( i = 0; i < 8; i++, RK += 6 )
+ {
+ RK[6] = RK[0] ^ RCON[i] ^
+ ( (uint32_t) FSb[ MBEDTLS_BYTE_1( RK[5] ) ] ) ^
+ ( (uint32_t) FSb[ MBEDTLS_BYTE_2( RK[5] ) ] << 8 ) ^
+ ( (uint32_t) FSb[ MBEDTLS_BYTE_3( RK[5] ) ] << 16 ) ^
+ ( (uint32_t) FSb[ MBEDTLS_BYTE_0( RK[5] ) ] << 24 );
+
+ RK[7] = RK[1] ^ RK[6];
+ RK[8] = RK[2] ^ RK[7];
+ RK[9] = RK[3] ^ RK[8];
+ RK[10] = RK[4] ^ RK[9];
+ RK[11] = RK[5] ^ RK[10];
+ }
+ break;
+
+ case 14:
+
+ for( i = 0; i < 7; i++, RK += 8 )
+ {
+ RK[8] = RK[0] ^ RCON[i] ^
+ ( (uint32_t) FSb[ MBEDTLS_BYTE_1( RK[7] ) ] ) ^
+ ( (uint32_t) FSb[ MBEDTLS_BYTE_2( RK[7] ) ] << 8 ) ^
+ ( (uint32_t) FSb[ MBEDTLS_BYTE_3( RK[7] ) ] << 16 ) ^
+ ( (uint32_t) FSb[ MBEDTLS_BYTE_0( RK[7] ) ] << 24 );
+
+ RK[9] = RK[1] ^ RK[8];
+ RK[10] = RK[2] ^ RK[9];
+ RK[11] = RK[3] ^ RK[10];
+
+ RK[12] = RK[4] ^
+ ( (uint32_t) FSb[ MBEDTLS_BYTE_0( RK[11] ) ] ) ^
+ ( (uint32_t) FSb[ MBEDTLS_BYTE_1( RK[11] ) ] << 8 ) ^
+ ( (uint32_t) FSb[ MBEDTLS_BYTE_2( RK[11] ) ] << 16 ) ^
+ ( (uint32_t) FSb[ MBEDTLS_BYTE_3( RK[11] ) ] << 24 );
+
+ RK[13] = RK[5] ^ RK[12];
+ RK[14] = RK[6] ^ RK[13];
+ RK[15] = RK[7] ^ RK[14];
+ }
+ break;
+ }
+
+ return( 0 );
+}
+
+/*
+ * AES key schedule (decryption)
+ */
+int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key,
+ unsigned int keybits )
+{
+ int i, j, ret;
+ mbedtls_aes_context cty;
+ uint32_t *RK;
+ uint32_t *SK;
+
+ AES_VALIDATE_RET( ctx != NULL );
+ AES_VALIDATE_RET( key != NULL );
+
+ mbedtls_aes_init( &cty );
+
+ ctx->rk = RK = ctx->buf;
+
+ /* Also checks keybits */
+ if( ( ret = mbedtls_aes_setkey_enc( &cty, key, keybits ) ) != 0 )
+ goto exit;
+
+ ctx->nr = cty.nr;
+
+#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
+ if( aes_aesni_has_support ) {
+ mbedtls_aesni_inverse_key( (unsigned char *) ctx->rk,
+ (const unsigned char *) cty.rk, ctx->nr );
+ goto exit;
+ }
+#endif
+
+ SK = cty.rk + cty.nr * 4;
+
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+
+ for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 )
+ {
+ for( j = 0; j < 4; j++, SK++ )
+ {
+ *RK++ = AES_RT0( FSb[ MBEDTLS_BYTE_0( *SK ) ] ) ^
+ AES_RT1( FSb[ MBEDTLS_BYTE_1( *SK ) ] ) ^
+ AES_RT2( FSb[ MBEDTLS_BYTE_2( *SK ) ] ) ^
+ AES_RT3( FSb[ MBEDTLS_BYTE_3( *SK ) ] );
+ }
+ }
+
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+
+exit:
+ mbedtls_aes_free( &cty );
+
+ return( ret );
+}
+
+#define AES_FROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3) \
+ { uint32_t T; \
+ X0 = *RK++; X1 = *RK++; X2 = *RK++; X3 = *RK++; \
+ T=Y0; \
+ X0 ^= FT0[ ( T ) & 0xFF ]; T >>= 8; \
+ X3 ^= FT1[ ( T ) & 0xFF ]; T >>= 8; \
+ X2 ^= FT2[ ( T ) & 0xFF ]; T >>= 8; \
+ X1 ^= FT3[ ( T ) & 0xFF ]; \
+ T=Y1; \
+ X1 ^= FT0[ ( T ) & 0xFF ]; T >>= 8; \
+ X0 ^= FT1[ ( T ) & 0xFF ]; T >>= 8; \
+ X3 ^= FT2[ ( T ) & 0xFF ]; T >>= 8; \
+ X2 ^= FT3[ ( T ) & 0xFF ]; \
+ T=Y2; \
+ X2 ^= FT0[ ( T ) & 0xFF ]; T >>= 8; \
+ X1 ^= FT1[ ( T ) & 0xFF ]; T >>= 8; \
+ X0 ^= FT2[ ( T ) & 0xFF ]; T >>= 8; \
+ X3 ^= FT3[ ( T ) & 0xFF ]; \
+ T=Y3; \
+ X3 ^= FT0[ ( T ) & 0xFF ]; T >>= 8; \
+ X2 ^= FT1[ ( T ) & 0xFF ]; T >>= 8; \
+ X1 ^= FT2[ ( T ) & 0xFF ]; T >>= 8; \
+ X0 ^= FT3[ ( T ) & 0xFF ]; \
+ }
+
+#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
+{ uint32_t T; \
+ X0 = *RK++; X1 = *RK++; X2 = *RK++; X3 = *RK++; \
+ T=Y0; \
+ X0 ^= RT0[ ( T ) & 0xFF ]; T >>= 8; \
+ X1 ^= RT1[ ( T ) & 0xFF ]; T >>= 8; \
+ X2 ^= RT2[ ( T ) & 0xFF ]; T >>= 8; \
+ X3 ^= RT3[ ( T ) & 0xFF ]; \
+ T=Y1; \
+ X1 ^= RT0[ ( T ) & 0xFF ]; T >>= 8; \
+ X2 ^= RT1[ ( T ) & 0xFF ]; T >>= 8; \
+ X3 ^= RT2[ ( T ) & 0xFF ]; T >>= 8; \
+ X0 ^= RT3[ ( T ) & 0xFF ]; \
+ T=Y2; \
+ X2 ^= RT0[ ( T ) & 0xFF ]; T >>= 8; \
+ X3 ^= RT1[ ( T ) & 0xFF ]; T >>= 8; \
+ X0 ^= RT2[ ( T ) & 0xFF ]; T >>= 8; \
+ X2 ^= RT3[ ( T ) & 0xFF ]; \
+ T=Y3; \
+ X3 ^= RT0[ ( T ) & 0xFF ]; T >>= 8; \
+ X0 ^= RT1[ ( T ) & 0xFF ]; T >>= 8; \
+ X1 ^= RT2[ ( T ) & 0xFF ]; T >>= 8; \
+ X2 ^= RT3[ ( T ) & 0xFF ]; \
+}
+
+/*
+ * AES-ECB block encryption
+ */
+int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx,
+ const unsigned char input[16],
+ unsigned char output[16] )
+{
+ int i;
+ uint32_t T0,*RK = ctx->rk;
+ struct
+ {
+ uint32_t X[4];
+ uint32_t Y[4];
+ } t;
+
+ t.X[0] = MBEDTLS_GET_UINT32_LE( input, 0 ); t.X[0] ^= *RK++;
+ t.X[1] = MBEDTLS_GET_UINT32_LE( input, 4 ); t.X[1] ^= *RK++;
+ t.X[2] = MBEDTLS_GET_UINT32_LE( input, 8 ); t.X[2] ^= *RK++;
+ t.X[3] = MBEDTLS_GET_UINT32_LE( input, 12 ); t.X[3] ^= *RK++;
+
+ for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- )
+ {
+ AES_FROUND( t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3] );
+ AES_FROUND( t.X[0], t.X[1], t.X[2], t.X[3], t.Y[0], t.Y[1], t.Y[2], t.Y[3] );
+ }
+
+ AES_FROUND( t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3] );
+#define AES_XROUND(X,Y0,Y1,Y2,Y3) \
+ T0 = FSb[ ( Y3 >> 24 ) & 0xFF ]; T0 <<= 8; \
+ T0 |= FSb[ ( Y2 >> 16 ) & 0xFF ]; T0 <<= 8; \
+ T0 |= FSb[ ( Y1 >> 8 ) & 0xFF ]; T0 <<= 8;\
+ T0 |= FSb[ ( Y0 ) & 0xFF ]; \
+ X = *RK++ ^ T0
+
+ AES_XROUND(t.X[0],t.Y[0],t.Y[1],t.Y[2],t.Y[3]);
+ AES_XROUND(t.X[1],t.Y[1],t.Y[2],t.Y[3],t.Y[0]);
+ AES_XROUND(t.X[2],t.Y[2],t.Y[3],t.Y[0],t.Y[1]);
+ AES_XROUND(t.X[3],t.Y[3],t.Y[0],t.Y[1],t.Y[2]);
+#undef AES_XROUND
+
+ MBEDTLS_PUT_UINT32_LE( t.X[0], output, 0 );
+ MBEDTLS_PUT_UINT32_LE( t.X[1], output, 4 );
+ MBEDTLS_PUT_UINT32_LE( t.X[2], output, 8 );
+ MBEDTLS_PUT_UINT32_LE( t.X[3], output, 12 );
+
+ return( 0 );
+}
+
+/*
+ * AES-ECB block decryption
+ */
+int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx,
+ const unsigned char input[16],
+ unsigned char output[16] )
+{
+ int i;
+ uint32_t T0,*RK = ctx->rk;
+ struct
+ {
+ uint32_t X[4];
+ uint32_t Y[4];
+ } t;
+
+ t.X[0] = MBEDTLS_GET_UINT32_LE( input, 0 ); t.X[0] ^= *RK++;
+ t.X[1] = MBEDTLS_GET_UINT32_LE( input, 4 ); t.X[1] ^= *RK++;
+ t.X[2] = MBEDTLS_GET_UINT32_LE( input, 8 ); t.X[2] ^= *RK++;
+ t.X[3] = MBEDTLS_GET_UINT32_LE( input, 12 ); t.X[3] ^= *RK++;
+
+ for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- )
+ {
+ AES_RROUND( t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3] );
+ AES_RROUND( t.X[0], t.X[1], t.X[2], t.X[3], t.Y[0], t.Y[1], t.Y[2], t.Y[3] );
+ }
+
+ AES_RROUND( t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3] );
+#define AES_XROUNDD(X,Y0,Y1,Y2,Y3) \
+ T0 = RSb[ ( Y3 >> 24 ) & 0xFF ]; T0 <<= 8; \
+ T0 |= RSb[ ( Y2 >> 16 ) & 0xFF ]; T0 <<= 8; \
+ T0 |= RSb[ ( Y1 >> 8 ) & 0xFF ]; T0 <<= 8;\
+ T0 |= RSb[ ( Y0 ) & 0xFF ]; \
+ X = *RK++ ^ T0
+
+ AES_XROUNDD(t.X[0],t.Y[0],t.Y[3],t.Y[2],t.Y[1]);
+ AES_XROUNDD(t.X[1],t.Y[1],t.Y[0],t.Y[3],t.Y[2]);
+ AES_XROUNDD(t.X[2],t.Y[2],t.Y[1],t.Y[0],t.Y[3]);
+ AES_XROUNDD(t.X[3],t.Y[3],t.Y[2],t.Y[1],t.Y[0]);
+
+#undef AES_XROUNDD
+
+ MBEDTLS_PUT_UINT32_LE( t.X[0], output, 0 );
+ MBEDTLS_PUT_UINT32_LE( t.X[1], output, 4 );
+ MBEDTLS_PUT_UINT32_LE( t.X[2], output, 8 );
+ MBEDTLS_PUT_UINT32_LE( t.X[3], output, 12 );
+
+ return( 0 );
+}
+
+/*
+ * AES-ECB block encryption/decryption
+ */
+int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
+ int mode,
+ const unsigned char input[16],
+ unsigned char output[16] )
+{
+ AES_VALIDATE_RET( ctx != NULL );
+ AES_VALIDATE_RET( input != NULL );
+ AES_VALIDATE_RET( output != NULL );
+ AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT ||
+ mode == MBEDTLS_AES_DECRYPT );
+
+#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
+ if( aes_aesni_has_support )
+ return( mbedtls_aesni_crypt_ecb( ctx, mode, input, output ) );
+#endif
+
+
+ if( mode == MBEDTLS_AES_ENCRYPT )
+ return( mbedtls_internal_aes_encrypt( ctx, input, output ) );
+ else
+ return( mbedtls_internal_aes_decrypt( ctx, input, output ) );
+}
+
diff --git a/src/lib/third_party/src/gcrypt/aesni.c b/src/lib/third_party/src/gcrypt/aesni.c
new file mode 100644
index 000000000..76edeea4e
--- /dev/null
+++ b/src/lib/third_party/src/gcrypt/aesni.c
@@ -0,0 +1,461 @@
+/*
+ * AES-NI support functions
+ *
+ * Copyright The Mbed TLS Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * [AES-WP] http://software.intel.com/en-us/articles/intel-advanced-encryption-standard-aes-instructions-set
+ * [CLMUL-WP] http://software.intel.com/en-us/articles/intel-carry-less-multiplication-instruction-and-its-usage-for-computing-the-gcm-mode/
+ */
+
+
+#if defined(__has_feature)
+#if __has_feature(memory_sanitizer)
+#warning "MBEDTLS_AESNI_C is known to cause spurious error reports with some memory sanitizers as they do not understand the assembly code."
+#endif
+#endif
+
+#ifndef asm
+#define asm __asm
+#endif
+
+#if defined(MBEDTLS_HAVE_X86_64)
+
+/*
+ * AES-NI support detection routine
+ */
+int mbedtls_aesni_has_support( unsigned int what )
+{
+ static int done = 0;
+ static unsigned int c = 0;
+
+#if defined(__has_feature)
+# if __has_feature(memory_sanitizer)
+ return 0;
+# endif
+#endif
+
+ if( ! done )
+ {
+ asm( "movl $1, %%eax \n\t"
+ "cpuid \n\t"
+ : "=c" (c)
+ :
+ : "eax", "ebx", "edx" );
+ done = 1;
+ }
+
+ return( ( (volatile unsigned int)c & what ) != 0 );
+}
+
+/*
+ * Binutils needs to be at least 2.19 to support AES-NI instructions.
+ * Unfortunately, a lot of users have a lower version now (2014-04).
+ * Emit bytecode directly in order to support "old" version of gas.
+ *
+ * Opcodes from the Intel architecture reference manual, vol. 3.
+ * We always use registers, so we don't need prefixes for memory operands.
+ * Operand macros are in gas order (src, dst) as opposed to Intel order
+ * (dst, src) in order to blend better into the surrounding assembly code.
+ */
+#define AESDEC ".byte 0x66,0x0F,0x38,0xDE,"
+#define AESDECLAST ".byte 0x66,0x0F,0x38,0xDF,"
+#define AESENC ".byte 0x66,0x0F,0x38,0xDC,"
+#define AESENCLAST ".byte 0x66,0x0F,0x38,0xDD,"
+#define AESIMC ".byte 0x66,0x0F,0x38,0xDB,"
+#define AESKEYGENA ".byte 0x66,0x0F,0x3A,0xDF,"
+#define PCLMULQDQ ".byte 0x66,0x0F,0x3A,0x44,"
+
+#define xmm0_xmm0 "0xC0"
+#define xmm0_xmm1 "0xC8"
+#define xmm0_xmm2 "0xD0"
+#define xmm0_xmm3 "0xD8"
+#define xmm0_xmm4 "0xE0"
+#define xmm1_xmm0 "0xC1"
+#define xmm1_xmm2 "0xD1"
+
+/*
+ * AES-NI AES-ECB block en(de)cryption
+ */
+int mbedtls_aesni_crypt_ecb( mbedtls_aes_context *ctx,
+ int mode,
+ const unsigned char input[16],
+ unsigned char output[16] )
+{
+ asm( "movdqu (%3), %%xmm0 \n\t" // load input
+ "movdqu (%1), %%xmm1 \n\t" // load round key 0
+ "pxor %%xmm1, %%xmm0 \n\t" // round 0
+ "add $16, %1 \n\t" // point to next round key
+ "subl $1, %0 \n\t" // normal rounds = nr - 1
+ "test %2, %2 \n\t" // mode?
+ "jz 2f \n\t" // 0 = decrypt
+
+ "1: \n\t" // encryption loop
+ "movdqu (%1), %%xmm1 \n\t" // load round key
+ AESENC xmm1_xmm0 "\n\t" // do round
+ "add $16, %1 \n\t" // point to next round key
+ "subl $1, %0 \n\t" // loop
+ "jnz 1b \n\t"
+ "movdqu (%1), %%xmm1 \n\t" // load round key
+ AESENCLAST xmm1_xmm0 "\n\t" // last round
+ "jmp 3f \n\t"
+
+ "2: \n\t" // decryption loop
+ "movdqu (%1), %%xmm1 \n\t"
+ AESDEC xmm1_xmm0 "\n\t" // do round
+ "add $16, %1 \n\t"
+ "subl $1, %0 \n\t"
+ "jnz 2b \n\t"
+ "movdqu (%1), %%xmm1 \n\t" // load round key
+ AESDECLAST xmm1_xmm0 "\n\t" // last round
+
+ "3: \n\t"
+ "movdqu %%xmm0, (%4) \n\t" // export output
+ :
+ : "r" (ctx->nr), "r" (ctx->rk), "r" (mode), "r" (input), "r" (output)
+ : "memory", "cc", "xmm0", "xmm1" );
+
+
+ return( 0 );
+}
+
+/*
+ * GCM multiplication: c = a times b in GF(2^128)
+ * Based on [CLMUL-WP] algorithms 1 (with equation 27) and 5.
+ */
+void mbedtls_aesni_gcm_mult( unsigned char c[16],
+ const unsigned char a[16],
+ const unsigned char b[16] )
+{
+ unsigned char aa[16], bb[16], cc[16];
+ size_t i;
+
+ /* The inputs are in big-endian order, so byte-reverse them */
+ for( i = 0; i < 16; i++ )
+ {
+ aa[i] = a[15 - i];
+ bb[i] = b[15 - i];
+ }
+
+ asm( "movdqu (%0), %%xmm0 \n\t" // a1:a0
+ "movdqu (%1), %%xmm1 \n\t" // b1:b0
+
+ /*
+ * Caryless multiplication xmm2:xmm1 = xmm0 * xmm1
+ * using [CLMUL-WP] algorithm 1 (p. 13).
+ */
+ "movdqa %%xmm1, %%xmm2 \n\t" // copy of b1:b0
+ "movdqa %%xmm1, %%xmm3 \n\t" // same
+ "movdqa %%xmm1, %%xmm4 \n\t" // same
+ PCLMULQDQ xmm0_xmm1 ",0x00 \n\t" // a0*b0 = c1:c0
+ PCLMULQDQ xmm0_xmm2 ",0x11 \n\t" // a1*b1 = d1:d0
+ PCLMULQDQ xmm0_xmm3 ",0x10 \n\t" // a0*b1 = e1:e0
+ PCLMULQDQ xmm0_xmm4 ",0x01 \n\t" // a1*b0 = f1:f0
+ "pxor %%xmm3, %%xmm4 \n\t" // e1+f1:e0+f0
+ "movdqa %%xmm4, %%xmm3 \n\t" // same
+ "psrldq $8, %%xmm4 \n\t" // 0:e1+f1
+ "pslldq $8, %%xmm3 \n\t" // e0+f0:0
+ "pxor %%xmm4, %%xmm2 \n\t" // d1:d0+e1+f1
+ "pxor %%xmm3, %%xmm1 \n\t" // c1+e0+f1:c0
+
+ /*
+ * Now shift the result one bit to the left,
+ * taking advantage of [CLMUL-WP] eq 27 (p. 20)
+ */
+ "movdqa %%xmm1, %%xmm3 \n\t" // r1:r0
+ "movdqa %%xmm2, %%xmm4 \n\t" // r3:r2
+ "psllq $1, %%xmm1 \n\t" // r1<<1:r0<<1
+ "psllq $1, %%xmm2 \n\t" // r3<<1:r2<<1
+ "psrlq $63, %%xmm3 \n\t" // r1>>63:r0>>63
+ "psrlq $63, %%xmm4 \n\t" // r3>>63:r2>>63
+ "movdqa %%xmm3, %%xmm5 \n\t" // r1>>63:r0>>63
+ "pslldq $8, %%xmm3 \n\t" // r0>>63:0
+ "pslldq $8, %%xmm4 \n\t" // r2>>63:0
+ "psrldq $8, %%xmm5 \n\t" // 0:r1>>63
+ "por %%xmm3, %%xmm1 \n\t" // r1<<1|r0>>63:r0<<1
+ "por %%xmm4, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1
+ "por %%xmm5, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1|r1>>63
+
+ /*
+ * Now reduce modulo the GCM polynomial x^128 + x^7 + x^2 + x + 1
+ * using [CLMUL-WP] algorithm 5 (p. 20).
+ * Currently xmm2:xmm1 holds x3:x2:x1:x0 (already shifted).
+ */
+ /* Step 2 (1) */
+ "movdqa %%xmm1, %%xmm3 \n\t" // x1:x0
+ "movdqa %%xmm1, %%xmm4 \n\t" // same
+ "movdqa %%xmm1, %%xmm5 \n\t" // same
+ "psllq $63, %%xmm3 \n\t" // x1<<63:x0<<63 = stuff:a
+ "psllq $62, %%xmm4 \n\t" // x1<<62:x0<<62 = stuff:b
+ "psllq $57, %%xmm5 \n\t" // x1<<57:x0<<57 = stuff:c
+
+ /* Step 2 (2) */
+ "pxor %%xmm4, %%xmm3 \n\t" // stuff:a+b
+ "pxor %%xmm5, %%xmm3 \n\t" // stuff:a+b+c
+ "pslldq $8, %%xmm3 \n\t" // a+b+c:0
+ "pxor %%xmm3, %%xmm1 \n\t" // x1+a+b+c:x0 = d:x0
+
+ /* Steps 3 and 4 */
+ "movdqa %%xmm1,%%xmm0 \n\t" // d:x0
+ "movdqa %%xmm1,%%xmm4 \n\t" // same
+ "movdqa %%xmm1,%%xmm5 \n\t" // same
+ "psrlq $1, %%xmm0 \n\t" // e1:x0>>1 = e1:e0'
+ "psrlq $2, %%xmm4 \n\t" // f1:x0>>2 = f1:f0'
+ "psrlq $7, %%xmm5 \n\t" // g1:x0>>7 = g1:g0'
+ "pxor %%xmm4, %%xmm0 \n\t" // e1+f1:e0'+f0'
+ "pxor %%xmm5, %%xmm0 \n\t" // e1+f1+g1:e0'+f0'+g0'
+ // e0'+f0'+g0' is almost e0+f0+g0, ex\tcept for some missing
+ // bits carried from d. Now get those\t bits back in.
+ "movdqa %%xmm1,%%xmm3 \n\t" // d:x0
+ "movdqa %%xmm1,%%xmm4 \n\t" // same
+ "movdqa %%xmm1,%%xmm5 \n\t" // same
+ "psllq $63, %%xmm3 \n\t" // d<<63:stuff
+ "psllq $62, %%xmm4 \n\t" // d<<62:stuff
+ "psllq $57, %%xmm5 \n\t" // d<<57:stuff
+ "pxor %%xmm4, %%xmm3 \n\t" // d<<63+d<<62:stuff
+ "pxor %%xmm5, %%xmm3 \n\t" // missing bits of d:stuff
+ "psrldq $8, %%xmm3 \n\t" // 0:missing bits of d
+ "pxor %%xmm3, %%xmm0 \n\t" // e1+f1+g1:e0+f0+g0
+ "pxor %%xmm1, %%xmm0 \n\t" // h1:h0
+ "pxor %%xmm2, %%xmm0 \n\t" // x3+h1:x2+h0
+
+ "movdqu %%xmm0, (%2) \n\t" // done
+ :
+ : "r" (aa), "r" (bb), "r" (cc)
+ : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" );
+
+ /* Now byte-reverse the outputs */
+ for( i = 0; i < 16; i++ )
+ c[i] = cc[15 - i];
+
+ return;
+}
+
+/*
+ * Compute decryption round keys from encryption round keys
+ */
+void mbedtls_aesni_inverse_key( unsigned char *invkey,
+ const unsigned char *fwdkey, int nr )
+{
+ unsigned char *ik = invkey;
+ const unsigned char *fk = fwdkey + 16 * nr;
+
+ memcpy( ik, fk, 16 );
+
+ for( fk -= 16, ik += 16; fk > fwdkey; fk -= 16, ik += 16 )
+ asm( "movdqu (%0), %%xmm0 \n\t"
+ AESIMC xmm0_xmm0 "\n\t"
+ "movdqu %%xmm0, (%1) \n\t"
+ :
+ : "r" (fk), "r" (ik)
+ : "memory", "xmm0" );
+
+ memcpy( ik, fk, 16 );
+}
+
+/*
+ * Key expansion, 128-bit case
+ */
+static void aesni_setkey_enc_128( unsigned char *rk,
+ const unsigned char *key )
+{
+ asm( "movdqu (%1), %%xmm0 \n\t" // copy the original key
+ "movdqu %%xmm0, (%0) \n\t" // as round key 0
+ "jmp 2f \n\t" // skip auxiliary routine
+
+ /*
+ * Finish generating the next round key.
+ *
+ * On entry xmm0 is r3:r2:r1:r0 and xmm1 is X:stuff:stuff:stuff
+ * with X = rot( sub( r3 ) ) ^ RCON.
+ *
+ * On exit, xmm0 is r7:r6:r5:r4
+ * with r4 = X + r0, r5 = r4 + r1, r6 = r5 + r2, r7 = r6 + r3
+ * and those are written to the round key buffer.
+ */
+ "1: \n\t"
+ "pshufd $0xff, %%xmm1, %%xmm1 \n\t" // X:X:X:X
+ "pxor %%xmm0, %%xmm1 \n\t" // X+r3:X+r2:X+r1:r4
+ "pslldq $4, %%xmm0 \n\t" // r2:r1:r0:0
+ "pxor %%xmm0, %%xmm1 \n\t" // X+r3+r2:X+r2+r1:r5:r4
+ "pslldq $4, %%xmm0 \n\t" // etc
+ "pxor %%xmm0, %%xmm1 \n\t"
+ "pslldq $4, %%xmm0 \n\t"
+ "pxor %%xmm1, %%xmm0 \n\t" // update xmm0 for next time!
+ "add $16, %0 \n\t" // point to next round key
+ "movdqu %%xmm0, (%0) \n\t" // write it
+ "ret \n\t"
+
+ /* Main "loop" */
+ "2: \n\t"
+ AESKEYGENA xmm0_xmm1 ",0x01 \n\tcall 1b \n\t"
+ AESKEYGENA xmm0_xmm1 ",0x02 \n\tcall 1b \n\t"
+ AESKEYGENA xmm0_xmm1 ",0x04 \n\tcall 1b \n\t"
+ AESKEYGENA xmm0_xmm1 ",0x08 \n\tcall 1b \n\t"
+ AESKEYGENA xmm0_xmm1 ",0x10 \n\tcall 1b \n\t"
+ AESKEYGENA xmm0_xmm1 ",0x20 \n\tcall 1b \n\t"
+ AESKEYGENA xmm0_xmm1 ",0x40 \n\tcall 1b \n\t"
+ AESKEYGENA xmm0_xmm1 ",0x80 \n\tcall 1b \n\t"
+ AESKEYGENA xmm0_xmm1 ",0x1B \n\tcall 1b \n\t"
+ AESKEYGENA xmm0_xmm1 ",0x36 \n\tcall 1b \n\t"
+ :
+ : "r" (rk), "r" (key)
+ : "memory", "cc", "0" );
+}
+
+/*
+ * Key expansion, 192-bit case
+ */
+static void aesni_setkey_enc_192( unsigned char *rk,
+ const unsigned char *key )
+{
+ asm( "movdqu (%1), %%xmm0 \n\t" // copy original round key
+ "movdqu %%xmm0, (%0) \n\t"
+ "add $16, %0 \n\t"
+ "movq 16(%1), %%xmm1 \n\t"
+ "movq %%xmm1, (%0) \n\t"
+ "add $8, %0 \n\t"
+ "jmp 2f \n\t" // skip auxiliary routine
+
+ /*
+ * Finish generating the next 6 quarter-keys.
+ *
+ * On entry xmm0 is r3:r2:r1:r0, xmm1 is stuff:stuff:r5:r4
+ * and xmm2 is stuff:stuff:X:stuff with X = rot( sub( r3 ) ) ^ RCON.
+ *
+ * On exit, xmm0 is r9:r8:r7:r6 and xmm1 is stuff:stuff:r11:r10
+ * and those are written to the round key buffer.
+ */
+ "1: \n\t"
+ "pshufd $0x55, %%xmm2, %%xmm2 \n\t" // X:X:X:X
+ "pxor %%xmm0, %%xmm2 \n\t" // X+r3:X+r2:X+r1:r4
+ "pslldq $4, %%xmm0 \n\t" // etc
+ "pxor %%xmm0, %%xmm2 \n\t"
+ "pslldq $4, %%xmm0 \n\t"
+ "pxor %%xmm0, %%xmm2 \n\t"
+ "pslldq $4, %%xmm0 \n\t"
+ "pxor %%xmm2, %%xmm0 \n\t" // update xmm0 = r9:r8:r7:r6
+ "movdqu %%xmm0, (%0) \n\t"
+ "add $16, %0 \n\t"
+ "pshufd $0xff, %%xmm0, %%xmm2 \n\t" // r9:r9:r9:r9
+ "pxor %%xmm1, %%xmm2 \n\t" // stuff:stuff:r9+r5:r10
+ "pslldq $4, %%xmm1 \n\t" // r2:r1:r0:0
+ "pxor %%xmm2, %%xmm1 \n\t" // xmm1 = stuff:stuff:r11:r10
+ "movq %%xmm1, (%0) \n\t"
+ "add $8, %0 \n\t"
+ "ret \n\t"
+
+ "2: \n\t"
+ AESKEYGENA xmm1_xmm2 ",0x01 \n\tcall 1b \n\t"
+ AESKEYGENA xmm1_xmm2 ",0x02 \n\tcall 1b \n\t"
+ AESKEYGENA xmm1_xmm2 ",0x04 \n\tcall 1b \n\t"
+ AESKEYGENA xmm1_xmm2 ",0x08 \n\tcall 1b \n\t"
+ AESKEYGENA xmm1_xmm2 ",0x10 \n\tcall 1b \n\t"
+ AESKEYGENA xmm1_xmm2 ",0x20 \n\tcall 1b \n\t"
+ AESKEYGENA xmm1_xmm2 ",0x40 \n\tcall 1b \n\t"
+ AESKEYGENA xmm1_xmm2 ",0x80 \n\tcall 1b \n\t"
+
+ :
+ : "r" (rk), "r" (key)
+ : "memory", "cc", "0" );
+}
+
+/*
+ * Key expansion, 256-bit case
+ */
+static void aesni_setkey_enc_256( unsigned char *rk,
+ const unsigned char *key )
+{
+ asm( "movdqu (%1), %%xmm0 \n\t"
+ "movdqu %%xmm0, (%0) \n\t"
+ "add $16, %0 \n\t"
+ "movdqu 16(%1), %%xmm1 \n\t"
+ "movdqu %%xmm1, (%0) \n\t"
+ "jmp 2f \n\t" // skip auxiliary routine
+
+ /*
+ * Finish generating the next two round keys.
+ *
+ * On entry xmm0 is r3:r2:r1:r0, xmm1 is r7:r6:r5:r4 and
+ * xmm2 is X:stuff:stuff:stuff with X = rot( sub( r7 )) ^ RCON
+ *
+ * On exit, xmm0 is r11:r10:r9:r8 and xmm1 is r15:r14:r13:r12
+ * and those have been written to the output buffer.
+ */
+ "1: \n\t"
+ "pshufd $0xff, %%xmm2, %%xmm2 \n\t"
+ "pxor %%xmm0, %%xmm2 \n\t"
+ "pslldq $4, %%xmm0 \n\t"
+ "pxor %%xmm0, %%xmm2 \n\t"
+ "pslldq $4, %%xmm0 \n\t"
+ "pxor %%xmm0, %%xmm2 \n\t"
+ "pslldq $4, %%xmm0 \n\t"
+ "pxor %%xmm2, %%xmm0 \n\t"
+ "add $16, %0 \n\t"
+ "movdqu %%xmm0, (%0) \n\t"
+
+ /* Set xmm2 to stuff:Y:stuff:stuff with Y = subword( r11 )
+ * and proceed to generate next round key from there */
+ AESKEYGENA xmm0_xmm2 ",0x00 \n\t"
+ "pshufd $0xaa, %%xmm2, %%xmm2 \n\t"
+ "pxor %%xmm1, %%xmm2 \n\t"
+ "pslldq $4, %%xmm1 \n\t"
+ "pxor %%xmm1, %%xmm2 \n\t"
+ "pslldq $4, %%xmm1 \n\t"
+ "pxor %%xmm1, %%xmm2 \n\t"
+ "pslldq $4, %%xmm1 \n\t"
+ "pxor %%xmm2, %%xmm1 \n\t"
+ "add $16, %0 \n\t"
+ "movdqu %%xmm1, (%0) \n\t"
+ "ret \n\t"
+
+ /*
+ * Main "loop" - Generating one more key than necessary,
+ * see definition of mbedtls_aes_context.buf
+ */
+ "2: \n\t"
+ AESKEYGENA xmm1_xmm2 ",0x01 \n\tcall 1b \n\t"
+ AESKEYGENA xmm1_xmm2 ",0x02 \n\tcall 1b \n\t"
+ AESKEYGENA xmm1_xmm2 ",0x04 \n\tcall 1b \n\t"
+ AESKEYGENA xmm1_xmm2 ",0x08 \n\tcall 1b \n\t"
+ AESKEYGENA xmm1_xmm2 ",0x10 \n\tcall 1b \n\t"
+ AESKEYGENA xmm1_xmm2 ",0x20 \n\tcall 1b \n\t"
+ AESKEYGENA xmm1_xmm2 ",0x40 \n\tcall 1b \n\t"
+ :
+ : "r" (rk), "r" (key)
+ : "memory", "cc", "0" );
+}
+
+/*
+ * Key expansion, wrapper
+ */
+int mbedtls_aesni_setkey_enc( unsigned char *rk,
+ const unsigned char *key,
+ size_t bits )
+{
+ switch( bits )
+ {
+ case 128: aesni_setkey_enc_128( rk, key ); break;
+ case 192: aesni_setkey_enc_192( rk, key ); break;
+ case 256: aesni_setkey_enc_256( rk, key ); break;
+ default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
+ }
+
+ return( 0 );
+}
+
+#endif /* MBEDTLS_HAVE_X86_64 */
diff --git a/src/lib/third_party/src/gcrypt/cipher.c b/src/lib/third_party/src/gcrypt/cipher.c
new file mode 100644
index 000000000..2231db9f6
--- /dev/null
+++ b/src/lib/third_party/src/gcrypt/cipher.c
@@ -0,0 +1,591 @@
+/**
+ * \file cipher.c
+ *
+ * \brief Generic cipher wrapper for mbed TLS
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ * Copyright The Mbed TLS Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#define CIPHER_VALIDATE_RET( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA )
+#define CIPHER_VALIDATE( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE( cond )
+
+static int supported_init = 0;
+
+const int *mbedtls_cipher_list( void )
+{
+ const mbedtls_cipher_definition_t *def;
+ int *type;
+
+ if( ! supported_init )
+ {
+ def = mbedtls_cipher_definitions;
+ type = mbedtls_cipher_supported;
+
+ while( def->type != 0 )
+ *type++ = (*def++).type;
+
+ *type = 0;
+
+ supported_init = 1;
+ }
+
+ return( mbedtls_cipher_supported );
+}
+
+const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type(
+ const mbedtls_cipher_type_t cipher_type )
+{
+ const mbedtls_cipher_definition_t *def;
+
+ for( def = mbedtls_cipher_definitions; def->info != NULL; def++ )
+ if( def->type == cipher_type )
+ return( def->info );
+
+ return( NULL );
+}
+
+const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string(
+ const char *cipher_name )
+{
+ const mbedtls_cipher_definition_t *def;
+
+ if( NULL == cipher_name )
+ return( NULL );
+
+ for( def = mbedtls_cipher_definitions; def->info != NULL; def++ )
+ if( ! strcmp( def->info->name, cipher_name ) )
+ return( def->info );
+
+ return( NULL );
+}
+
+const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values(
+ const mbedtls_cipher_id_t cipher_id,
+ int key_bitlen,
+ const mbedtls_cipher_mode_t mode )
+{
+ const mbedtls_cipher_definition_t *def;
+
+ for( def = mbedtls_cipher_definitions; def->info != NULL; def++ )
+ if( def->info->base->cipher == cipher_id &&
+ def->info->key_bitlen == (unsigned) key_bitlen &&
+ def->info->mode == mode )
+ return( def->info );
+
+ return( NULL );
+}
+
+void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx )
+{
+ CIPHER_VALIDATE( ctx != NULL );
+ memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) );
+}
+
+int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx,
+ const unsigned char *key,
+ int key_bitlen,
+ const mbedtls_operation_t operation )
+{
+ CIPHER_VALIDATE_RET( ctx != NULL );
+ CIPHER_VALIDATE_RET( key != NULL );
+ CIPHER_VALIDATE_RET( operation == MBEDTLS_ENCRYPT ||
+ operation == MBEDTLS_DECRYPT );
+ if( ctx->cipher_info == NULL )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+
+ if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN ) == 0 &&
+ (int) ctx->cipher_info->key_bitlen != key_bitlen )
+ {
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+ }
+
+ ctx->key_bitlen = key_bitlen;
+ ctx->operation = operation;
+
+ /*
+ * For OFB, CFB and CTR mode always use the encryption key schedule
+ */
+ if( MBEDTLS_ENCRYPT == operation ||
+ MBEDTLS_MODE_CFB == ctx->cipher_info->mode ||
+ MBEDTLS_MODE_OFB == ctx->cipher_info->mode ||
+ MBEDTLS_MODE_CTR == ctx->cipher_info->mode )
+ {
+ return( ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key,
+ ctx->key_bitlen ) );
+ }
+
+ if( MBEDTLS_DECRYPT == operation )
+ return( ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key,
+ ctx->key_bitlen ) );
+
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+}
+
+int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx,
+ const unsigned char *iv,
+ size_t iv_len )
+{
+ size_t actual_iv_size;
+
+ CIPHER_VALIDATE_RET( ctx != NULL );
+ CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL );
+ if( ctx->cipher_info == NULL )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+ /* avoid buffer overflow in ctx->iv */
+ if( iv_len > MBEDTLS_MAX_IV_LENGTH )
+ return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+
+ if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_IV_LEN ) != 0 )
+ actual_iv_size = iv_len;
+ else
+ {
+ actual_iv_size = ctx->cipher_info->iv_size;
+
+ /* avoid reading past the end of input buffer */
+ if( actual_iv_size > iv_len )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+ }
+
+
+#if defined(MBEDTLS_GCM_C)
+ if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
+ {
+ return( mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx,
+ ctx->operation,
+ iv, iv_len ) );
+ }
+#endif
+
+
+ if ( actual_iv_size != 0 )
+ {
+ memcpy( ctx->iv, iv, actual_iv_size );
+ ctx->iv_size = actual_iv_size;
+ }
+
+ return( 0 );
+}
+
+int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx )
+{
+ CIPHER_VALIDATE_RET( ctx != NULL );
+ if( ctx->cipher_info == NULL )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+
+ ctx->unprocessed_len = 0;
+
+ return( 0 );
+}
+
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
+int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx,
+ const unsigned char *ad, size_t ad_len )
+{
+ CIPHER_VALIDATE_RET( ctx != NULL );
+ CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL );
+ if( ctx->cipher_info == NULL )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+
+#if defined(MBEDTLS_GCM_C)
+ if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
+ {
+ return( mbedtls_gcm_update_ad( (mbedtls_gcm_context *) ctx->cipher_ctx,
+ ad, ad_len ) );
+ }
+#endif
+
+
+ return( 0 );
+}
+#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
+
+int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input,
+ size_t ilen, unsigned char *output, size_t *olen )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t block_size;
+
+ CIPHER_VALIDATE_RET( ctx != NULL );
+ CIPHER_VALIDATE_RET( ilen == 0 || input != NULL );
+ CIPHER_VALIDATE_RET( output != NULL );
+ CIPHER_VALIDATE_RET( olen != NULL );
+ if( ctx->cipher_info == NULL )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+
+ *olen = 0;
+ block_size = mbedtls_cipher_get_block_size( ctx );
+ if ( 0 == block_size )
+ {
+ return( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT );
+ }
+
+ if( ctx->cipher_info->mode == MBEDTLS_MODE_ECB )
+ {
+ if( ilen != block_size )
+ return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED );
+
+ *olen = ilen;
+
+ if( 0 != ( ret = ctx->cipher_info->base->ecb_func( ctx->cipher_ctx,
+ ctx->operation, input, output ) ) )
+ {
+ return( ret );
+ }
+
+ return( 0 );
+ }
+
+#if defined(MBEDTLS_GCM_C)
+ if( ctx->cipher_info->mode == MBEDTLS_MODE_GCM )
+ {
+ return( mbedtls_gcm_update( (mbedtls_gcm_context *) ctx->cipher_ctx,
+ input, ilen,
+ output, ilen, olen ) );
+ }
+#endif
+
+
+
+ if( input == output &&
+ ( ctx->unprocessed_len != 0 || ilen % block_size ) )
+ {
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+ }
+
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+ if( ctx->cipher_info->mode == MBEDTLS_MODE_CBC )
+ {
+ size_t copy_len = 0;
+
+ /*
+ * If there is not enough data for a full block, cache it.
+ */
+ if( ( ctx->operation == MBEDTLS_DECRYPT && NULL != ctx->add_padding &&
+ ilen <= block_size - ctx->unprocessed_len ) ||
+ ( ctx->operation == MBEDTLS_DECRYPT && NULL == ctx->add_padding &&
+ ilen < block_size - ctx->unprocessed_len ) ||
+ ( ctx->operation == MBEDTLS_ENCRYPT &&
+ ilen < block_size - ctx->unprocessed_len ) )
+ {
+ memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input,
+ ilen );
+
+ ctx->unprocessed_len += ilen;
+ return( 0 );
+ }
+
+ /*
+ * Process cached data first
+ */
+ if( 0 != ctx->unprocessed_len )
+ {
+ copy_len = block_size - ctx->unprocessed_len;
+
+ memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input,
+ copy_len );
+
+ if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
+ ctx->operation, block_size, ctx->iv,
+ ctx->unprocessed_data, output ) ) )
+ {
+ return( ret );
+ }
+
+ *olen += block_size;
+ output += block_size;
+ ctx->unprocessed_len = 0;
+
+ input += copy_len;
+ ilen -= copy_len;
+ }
+
+ /*
+ * Cache final, incomplete block
+ */
+ if( 0 != ilen )
+ {
+ /* Encryption: only cache partial blocks
+ * Decryption w/ padding: always keep at least one whole block
+ * Decryption w/o padding: only cache partial blocks
+ */
+ copy_len = ilen % block_size;
+ if( copy_len == 0 &&
+ ctx->operation == MBEDTLS_DECRYPT &&
+ NULL != ctx->add_padding)
+ {
+ copy_len = block_size;
+ }
+
+ memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ),
+ copy_len );
+
+ ctx->unprocessed_len += copy_len;
+ ilen -= copy_len;
+ }
+
+ /*
+ * Process remaining full blocks
+ */
+ if( ilen )
+ {
+ if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
+ ctx->operation, ilen, ctx->iv, input, output ) ) )
+ {
+ return( ret );
+ }
+
+ *olen += ilen;
+ }
+
+ return( 0 );
+ }
+#endif /* MBEDTLS_CIPHER_MODE_CBC */
+
+
+
+
+
+
+ return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+}
+
+
+int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx,
+ unsigned char *output, size_t *olen )
+{
+ CIPHER_VALIDATE_RET( ctx != NULL );
+ CIPHER_VALIDATE_RET( output != NULL );
+ CIPHER_VALIDATE_RET( olen != NULL );
+ if( ctx->cipher_info == NULL )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+
+ *olen = 0;
+
+ if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode ||
+ MBEDTLS_MODE_OFB == ctx->cipher_info->mode ||
+ MBEDTLS_MODE_CTR == ctx->cipher_info->mode ||
+ MBEDTLS_MODE_GCM == ctx->cipher_info->mode ||
+ MBEDTLS_MODE_CCM_STAR_NO_TAG == ctx->cipher_info->mode ||
+ MBEDTLS_MODE_XTS == ctx->cipher_info->mode ||
+ MBEDTLS_MODE_STREAM == ctx->cipher_info->mode )
+ {
+ return( 0 );
+ }
+
+ if ( ( MBEDTLS_CIPHER_CHACHA20 == ctx->cipher_info->type ) ||
+ ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) )
+ {
+ return( 0 );
+ }
+
+ if( MBEDTLS_MODE_ECB == ctx->cipher_info->mode )
+ {
+ if( ctx->unprocessed_len != 0 )
+ return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED );
+
+ return( 0 );
+ }
+
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+ if( MBEDTLS_MODE_CBC == ctx->cipher_info->mode )
+ {
+ int ret = 0;
+
+ if( MBEDTLS_ENCRYPT == ctx->operation )
+ {
+ /* check for 'no padding' mode */
+ if( NULL == ctx->add_padding )
+ {
+ if( 0 != ctx->unprocessed_len )
+ return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED );
+
+ return( 0 );
+ }
+
+ ctx->add_padding( ctx->unprocessed_data, mbedtls_cipher_get_iv_size( ctx ),
+ ctx->unprocessed_len );
+ }
+ else if( mbedtls_cipher_get_block_size( ctx ) != ctx->unprocessed_len )
+ {
+ /*
+ * For decrypt operations, expect a full block,
+ * or an empty block if no padding
+ */
+ if( NULL == ctx->add_padding && 0 == ctx->unprocessed_len )
+ return( 0 );
+
+ return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED );
+ }
+
+ /* cipher block */
+ if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
+ ctx->operation, mbedtls_cipher_get_block_size( ctx ), ctx->iv,
+ ctx->unprocessed_data, output ) ) )
+ {
+ return( ret );
+ }
+
+ /* Set output size for decryption */
+ if( MBEDTLS_DECRYPT == ctx->operation )
+ return( ctx->get_padding( output, mbedtls_cipher_get_block_size( ctx ),
+ olen ) );
+
+ /* Set output size for encryption */
+ *olen = mbedtls_cipher_get_block_size( ctx );
+ return( 0 );
+ }
+#else
+ ((void) output);
+#endif /* MBEDTLS_CIPHER_MODE_CBC */
+
+ return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+}
+
+
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
+int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
+ unsigned char *tag, size_t tag_len )
+{
+ CIPHER_VALIDATE_RET( ctx != NULL );
+ CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL );
+ if( ctx->cipher_info == NULL )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+ if( MBEDTLS_ENCRYPT != ctx->operation )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+
+#if defined(MBEDTLS_GCM_C)
+ if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
+ {
+ size_t output_length;
+ /* The code here doesn't yet support alternative implementations
+ * that can delay up to a block of output. */
+ return( mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx,
+ NULL, 0, &output_length,
+ tag, tag_len ) );
+ }
+#endif
+
+
+ return( 0 );
+}
+
+int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx,
+ const unsigned char *tag, size_t tag_len )
+{
+ unsigned char check_tag[16];
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+ CIPHER_VALIDATE_RET( ctx != NULL );
+ CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL );
+ if( ctx->cipher_info == NULL )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+ if( MBEDTLS_DECRYPT != ctx->operation )
+ {
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+ }
+
+
+ /* Status to return on a non-authenticated algorithm. It would make sense
+ * to return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT or perhaps
+ * MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, but at the time I write this our
+ * unit tests assume 0. */
+ ret = 0;
+
+#if defined(MBEDTLS_GCM_C)
+ if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
+ {
+ size_t output_length;
+ /* The code here doesn't yet support alternative implementations
+ * that can delay up to a block of output. */
+
+ if( tag_len > sizeof( check_tag ) )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+ if( 0 != ( ret = mbedtls_gcm_finish(
+ (mbedtls_gcm_context *) ctx->cipher_ctx,
+ NULL, 0, &output_length,
+ check_tag, tag_len ) ) )
+ {
+ return( ret );
+ }
+
+ /* Check the tag in "constant-time" */
+ if( mbedtls_ct_memcmp( tag, check_tag, tag_len ) != 0 )
+ {
+ ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
+ goto exit;
+ }
+ }
+#endif /* MBEDTLS_GCM_C */
+
+
+exit:
+ mbedtls_platform_zeroize( check_tag, tag_len );
+ return( ret );
+}
+#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
+
+/*
+ * Packet-oriented wrapper for non-AEAD modes
+ */
+int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx,
+ const unsigned char *iv, size_t iv_len,
+ const unsigned char *input, size_t ilen,
+ unsigned char *output, size_t *olen )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t finish_olen;
+
+ CIPHER_VALIDATE_RET( ctx != NULL );
+ CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL );
+ CIPHER_VALIDATE_RET( ilen == 0 || input != NULL );
+ CIPHER_VALIDATE_RET( output != NULL );
+ CIPHER_VALIDATE_RET( olen != NULL );
+
+
+ if( ( ret = mbedtls_cipher_set_iv( ctx, iv, iv_len ) ) != 0 )
+ return( ret );
+
+ if( ( ret = mbedtls_cipher_reset( ctx ) ) != 0 )
+ return( ret );
+
+ if( ( ret = mbedtls_cipher_update( ctx, input, ilen,
+ output, olen ) ) != 0 )
+ return( ret );
+
+ if( ( ret = mbedtls_cipher_finish( ctx, output + *olen,
+ &finish_olen ) ) != 0 )
+ return( ret );
+
+ *olen += finish_olen;
+
+ return( 0 );
+}
+
diff --git a/src/lib/third_party/src/gcrypt/cipher_wrap.c b/src/lib/third_party/src/gcrypt/cipher_wrap.c
new file mode 100644
index 000000000..6db209cba
--- /dev/null
+++ b/src/lib/third_party/src/gcrypt/cipher_wrap.c
@@ -0,0 +1,252 @@
+/**
+ * \file cipher_wrap.c
+ *
+ * \brief Generic cipher wrapper for mbed TLS
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ * Copyright The Mbed TLS Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined(MBEDTLS_AES_C)
+
+static int aes_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation,
+ const unsigned char *input, unsigned char *output )
+{
+ return mbedtls_aes_crypt_ecb( (mbedtls_aes_context *) ctx, operation, input, output );
+}
+
+
+static int aes_setkey_dec_wrap( void *ctx, const unsigned char *key,
+ unsigned int key_bitlen )
+{
+ return mbedtls_aes_setkey_dec( (mbedtls_aes_context *) ctx, key, key_bitlen );
+}
+
+static int aes_setkey_enc_wrap( void *ctx, const unsigned char *key,
+ unsigned int key_bitlen )
+{
+ return mbedtls_aes_setkey_enc( (mbedtls_aes_context *) ctx, key, key_bitlen );
+}
+
+static void * aes_ctx_alloc( void )
+{
+ mbedtls_aes_context *aes = mbedtls_calloc( 1, sizeof( mbedtls_aes_context ) );
+
+ if( aes == NULL )
+ return( NULL );
+
+ mbedtls_aes_init( aes );
+
+ return( aes );
+}
+
+static void aes_ctx_free( void *ctx )
+{
+ mbedtls_aes_free( (mbedtls_aes_context *) ctx );
+ mbedtls_free( ctx );
+}
+
+static void aes_ctx_zero( void *ctx )
+{
+ mbedtls_aes_init( (mbedtls_aes_context *) ctx );
+}
+
+static const mbedtls_cipher_base_t aes_info = {
+ MBEDTLS_CIPHER_ID_AES,
+ aes_crypt_ecb_wrap,
+ aes_setkey_enc_wrap,
+ aes_setkey_dec_wrap,
+ NULL, // aes_ctx_alloc
+ NULL, // aes_ctx_free
+ aes_ctx_zero
+};
+
+static const mbedtls_cipher_info_t aes_128_ecb_info = {
+ MBEDTLS_CIPHER_AES_128_ECB,
+ MBEDTLS_MODE_ECB,
+ 128,
+ "AES-128-ECB",
+ 0,
+ 0,
+ 16,
+ &aes_info
+};
+
+static const mbedtls_cipher_info_t aes_192_ecb_info = {
+ MBEDTLS_CIPHER_AES_192_ECB,
+ MBEDTLS_MODE_ECB,
+ 192,
+ "AES-192-ECB",
+ 0,
+ 0,
+ 16,
+ &aes_info
+};
+
+static const mbedtls_cipher_info_t aes_256_ecb_info = {
+ MBEDTLS_CIPHER_AES_256_ECB,
+ MBEDTLS_MODE_ECB,
+ 256,
+ "AES-256-ECB",
+ 0,
+ 0,
+ 16,
+ &aes_info
+};
+
+#if defined(MBEDTLS_GCM_C)
+static int gcm_aes_setkey_wrap( void *ctx, const unsigned char *key,
+ unsigned int key_bitlen )
+{
+ return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_AES,
+ key, key_bitlen );
+}
+
+static const mbedtls_cipher_base_t gcm_aes_info = {
+ MBEDTLS_CIPHER_ID_AES,
+ NULL,
+ gcm_aes_setkey_wrap,
+ gcm_aes_setkey_wrap,
+ NULL, // gcm_ctx_alloc
+ NULL, // gcm_ctx_free
+ NULL
+};
+
+static const mbedtls_cipher_info_t aes_128_gcm_info = {
+ MBEDTLS_CIPHER_AES_128_GCM,
+ MBEDTLS_MODE_GCM,
+ 128,
+ "AES-128-GCM",
+ 12,
+ MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+ 16,
+ &gcm_aes_info
+};
+
+static const mbedtls_cipher_info_t aes_192_gcm_info = {
+ MBEDTLS_CIPHER_AES_192_GCM,
+ MBEDTLS_MODE_GCM,
+ 192,
+ "AES-192-GCM",
+ 12,
+ MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+ 16,
+ &gcm_aes_info
+};
+
+static const mbedtls_cipher_info_t aes_256_gcm_info = {
+ MBEDTLS_CIPHER_AES_256_GCM,
+ MBEDTLS_MODE_GCM,
+ 256,
+ "AES-256-GCM",
+ 12,
+ MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+ 16,
+ &gcm_aes_info
+};
+#endif /* MBEDTLS_GCM_C */
+
+
+#endif /* MBEDTLS_AES_C */
+
+
+
+
+
+
+#if defined(MBEDTLS_CIPHER_NULL_CIPHER)
+static int null_crypt_stream( void *ctx, size_t length,
+ const unsigned char *input,
+ unsigned char *output )
+{
+ ((void) ctx);
+ memmove( output, input, length );
+ return( 0 );
+}
+
+static int null_setkey( void *ctx, const unsigned char *key,
+ unsigned int key_bitlen )
+{
+ ((void) ctx);
+ ((void) key);
+ ((void) key_bitlen);
+
+ return( 0 );
+}
+
+static void * null_ctx_alloc( void )
+{
+ return( (void *) 1 );
+}
+
+static void null_ctx_free( void *ctx )
+{
+ ((void) ctx);
+}
+
+static const mbedtls_cipher_base_t null_base_info = {
+ MBEDTLS_CIPHER_ID_NULL,
+ NULL,
+ null_setkey,
+ null_setkey,
+ null_ctx_alloc,
+ null_ctx_free
+};
+
+static const mbedtls_cipher_info_t null_cipher_info = {
+ MBEDTLS_CIPHER_NULL,
+ MBEDTLS_MODE_STREAM,
+ 0,
+ "NULL",
+ 0,
+ 0,
+ 1,
+ &null_base_info
+};
+#endif /* defined(MBEDTLS_CIPHER_NULL_CIPHER) */
+
+
+const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] =
+{
+#if defined(MBEDTLS_AES_C)
+ { MBEDTLS_CIPHER_AES_128_ECB, &aes_128_ecb_info },
+ { MBEDTLS_CIPHER_AES_192_ECB, &aes_192_ecb_info },
+ { MBEDTLS_CIPHER_AES_256_ECB, &aes_256_ecb_info },
+#if defined(MBEDTLS_GCM_C)
+ { MBEDTLS_CIPHER_AES_128_GCM, &aes_128_gcm_info },
+ { MBEDTLS_CIPHER_AES_192_GCM, &aes_192_gcm_info },
+ { MBEDTLS_CIPHER_AES_256_GCM, &aes_256_gcm_info },
+#endif
+#endif /* MBEDTLS_AES_C */
+
+
+
+
+
+
+
+#if defined(MBEDTLS_CIPHER_NULL_CIPHER)
+ { MBEDTLS_CIPHER_NULL, &null_cipher_info },
+#endif /* MBEDTLS_CIPHER_NULL_CIPHER */
+
+ { MBEDTLS_CIPHER_NONE, NULL }
+};
+
+#define NUM_CIPHERS ( sizeof(mbedtls_cipher_definitions) / \
+ sizeof(mbedtls_cipher_definitions[0]) )
+int mbedtls_cipher_supported[NUM_CIPHERS];
+
diff --git a/src/lib/third_party/src/gcrypt/digest.c b/src/lib/third_party/src/gcrypt/digest.c
new file mode 100644
index 000000000..3cdd1f1f8
--- /dev/null
+++ b/src/lib/third_party/src/gcrypt/digest.c
@@ -0,0 +1,321 @@
+/*
+ * hmac-sha256.c
+ * Copyright (C) 2017 Adrian Perez <aperez@igalia.com>
+ *
+ * Distributed under terms of the MIT license.
+ */
+
+//#include <stdint.h>
+//#include <unistd.h>
+//#include <string.h>
+//#include <stdlib.h>
+
+//#include "gcrypt/digest.h"
+
+/* define it for speed optimization */
+#define _SHA256_UNROLL
+#define _SHA256_UNROLL2
+
+/*
+ * Crypto/Sha256.c -- SHA-256 Hash
+ * 2010-06-11 : Igor Pavlov : Public domain
+ * This code is based on public domain code from Wei Dai's Crypto++ library.
+ */
+
+#define U8V(v) ((uint8_t)(v) & 0xFFU)
+#define U16V(v) ((uint16_t)(v) & 0xFFFFU)
+#define U32V(v) ((uint32_t)(v) & 0xFFFFFFFFU)
+#define U64V(v) ((uint64_t)(v) & 0xFFFFFFFFFFFFFFFFU)
+
+#define ROTL32(v, n) (U32V((uint32_t)(v) << (n)) | ((uint32_t)(v) >> (32 - (n))))
+
+// tests fail if we don't have this cast...
+#define ROTL64(v, n) (U64V((uint64_t)(v) << (n)) | ((uint64_t)(v) >> (64 - (n))))
+
+#define ROTR32(v, n) ROTL32(v, 32 - (n))
+#define ROTR64(v, n) ROTL64(v, 64 - (n))
+
+#ifndef ROTL8
+#define ROTL8(v, n) (U8V((uint8_t)(v) << (n)) | ((uint8_t)(v) >> (8 - (n))))
+#endif
+#ifndef ROTL16
+#define ROTL16(v, n) (U16V((uint16_t)(v) << (n)) | ((uint16_t)(v) >> (16 - (n))))
+#endif
+
+#define ROTR8(v, n) ROTL8(v, 8 - (n))
+#define ROTR16(v, n) ROTL16(v, 16 - (n))
+
+#define S0(x) (ROTR32(x, 2) ^ ROTR32(x,13) ^ ROTR32(x, 22))
+#define S1(x) (ROTR32(x, 6) ^ ROTR32(x,11) ^ ROTR32(x, 25))
+#define s0(x) (ROTR32(x, 7) ^ ROTR32(x,18) ^ (x >> 3))
+#define s1(x) (ROTR32(x,17) ^ ROTR32(x,19) ^ (x >> 10))
+
+#define blk0(i) (W[i] = data[i])
+#define blk2(i) (W[i&15] += s1(W[(i-2)&15]) + W[(i-7)&15] + s0(W[(i-15)&15]))
+
+#define Ch(x,y,z) (z^(x&(y^z)))
+#define Maj(x,y,z) ((x&y)|(z&(x|y)))
+
+#define a(i) T[(0-(i))&7]
+#define b(i) T[(1-(i))&7]
+#define c(i) T[(2-(i))&7]
+#define d(i) T[(3-(i))&7]
+#define e(i) T[(4-(i))&7]
+#define f(i) T[(5-(i))&7]
+#define g(i) T[(6-(i))&7]
+#define h(i) T[(7-(i))&7]
+
+
+#ifdef _SHA256_UNROLL2
+
+#define R(a,b,c,d,e,f,g,h, i) h += S1(e) + Ch(e,f,g) + K[i+j] + (j?blk2(i):blk0(i));\
+ d += h; h += S0(a) + Maj(a, b, c)
+
+#define RX_8(i) \
+ R(a,b,c,d,e,f,g,h, i); \
+ R(h,a,b,c,d,e,f,g, (i+1)); \
+ R(g,h,a,b,c,d,e,f, (i+2)); \
+ R(f,g,h,a,b,c,d,e, (i+3)); \
+ R(e,f,g,h,a,b,c,d, (i+4)); \
+ R(d,e,f,g,h,a,b,c, (i+5)); \
+ R(c,d,e,f,g,h,a,b, (i+6)); \
+ R(b,c,d,e,f,g,h,a, (i+7))
+
+#else
+
+#define R(i) h(i) += S1(e(i)) + Ch(e(i),f(i),g(i)) + K[i+j] + (j?blk2(i):blk0(i));\
+ d(i) += h(i); h(i) += S0(a(i)) + Maj(a(i), b(i), c(i))
+
+#ifdef _SHA256_UNROLL
+
+#define RX_8(i) R(i+0); R(i+1); R(i+2); R(i+3); R(i+4); R(i+5); R(i+6); R(i+7);
+
+#endif
+
+#endif
+
+static const uint32_t K[64] = {
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+ 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+ 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+ 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+ 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+ 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+};
+
+static void
+sha256_init(sha256_t *p)
+{
+ p->state[0] = 0x6a09e667;
+ p->state[1] = 0xbb67ae85;
+ p->state[2] = 0x3c6ef372;
+ p->state[3] = 0xa54ff53a;
+ p->state[4] = 0x510e527f;
+ p->state[5] = 0x9b05688c;
+ p->state[6] = 0x1f83d9ab;
+ p->state[7] = 0x5be0cd19;
+ p->count = 0;
+}
+
+static void
+sha256_transform(uint32_t *state, const uint32_t *data)
+{
+ uint32_t W[16];
+ unsigned j;
+ #ifdef _SHA256_UNROLL2
+ uint32_t a,b,c,d,e,f,g,h;
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+ e = state[4];
+ f = state[5];
+ g = state[6];
+ h = state[7];
+ #else
+ uint32_t T[8];
+ for (j = 0; j < 8; j++)
+ T[j] = state[j];
+ #endif
+
+ for (j = 0; j < 64; j += 16)
+ {
+ #if defined(_SHA256_UNROLL) || defined(_SHA256_UNROLL2)
+ RX_8(0); RX_8(8);
+ #else
+ unsigned i;
+ for (i = 0; i < 16; i++) { R(i); }
+ #endif
+ }
+
+ #ifdef _SHA256_UNROLL2
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+ state[4] += e;
+ state[5] += f;
+ state[6] += g;
+ state[7] += h;
+ #else
+ for (j = 0; j < 8; j++)
+ state[j] += T[j];
+ #endif
+
+ /* Wipe variables */
+ /* memset(W, 0, sizeof(W)); */
+ /* memset(T, 0, sizeof(T)); */
+}
+
+#undef S0
+#undef S1
+#undef s0
+#undef s1
+
+static void
+sha256_write_byte_block(sha256_t *p)
+{
+ uint32_t data32[16];
+ unsigned i;
+ for (i = 0; i < 16; i++)
+ data32[i] =
+ ((uint32_t)(p->buffer[i * 4 ]) << 24) +
+ ((uint32_t)(p->buffer[i * 4 + 1]) << 16) +
+ ((uint32_t)(p->buffer[i * 4 + 2]) << 8) +
+ ((uint32_t)(p->buffer[i * 4 + 3]));
+ sha256_transform(p->state, data32);
+}
+
+static void
+sha256_update(sha256_t *p, const unsigned char *data, size_t size)
+{
+ uint32_t curBufferPos = (uint32_t)p->count & 0x3F;
+ while (size > 0)
+ {
+ p->buffer[curBufferPos++] = *data++;
+ p->count++;
+ size--;
+ if (curBufferPos == 64)
+ {
+ curBufferPos = 0;
+ sha256_write_byte_block(p);
+ }
+ }
+}
+
+
+void
+sha256_final(sha256_t *p, unsigned char *digest)
+{
+ uint64_t lenInBits = (p->count << 3);
+ uint32_t curBufferPos = (uint32_t)p->count & 0x3F;
+ unsigned i;
+ p->buffer[curBufferPos++] = 0x80;
+ while (curBufferPos != (64 - 8))
+ {
+ curBufferPos &= 0x3F;
+ if (curBufferPos == 0)
+ sha256_write_byte_block(p);
+ p->buffer[curBufferPos++] = 0;
+ }
+ for (i = 0; i < 8; i++)
+ {
+ p->buffer[curBufferPos++] = (unsigned char)(lenInBits >> 56);
+ lenInBits <<= 8;
+ }
+ sha256_write_byte_block(p);
+
+ for (i = 0; i < 8; i++)
+ {
+ *digest++ = (unsigned char)(p->state[i] >> 24);
+ *digest++ = (unsigned char)(p->state[i] >> 16);
+ *digest++ = (unsigned char)(p->state[i] >> 8);
+ *digest++ = (unsigned char)(p->state[i]);
+ }
+ sha256_init(p);
+}
+
+/*
+ * HMAC(H, K) == H(K ^ opad, H(K ^ ipad, text))
+ *
+ * H: Hash function (sha256)
+ * K: Secret key
+ * B: Block byte length
+ * L: Byte length of hash function output
+ *
+ * https://tools.ietf.org/html/rfc2104
+ */
+
+#define B 64
+#define L (SHA256_DIGEST_SIZE)
+#define K (SHA256_DIGEST_SIZE * 2)
+
+#define I_PAD 0x36
+#define O_PAD 0x5C
+
+void
+hmac_sha256 (uint8_t out[HMAC_SHA256_DIGEST_SIZE],
+ const uint8_t *data, size_t data_len,
+ const uint8_t *key, size_t key_len)
+{
+ sha256_t ss;
+ uint8_t kx[B];
+ size_t i;
+
+ if(!out) return;
+ if(!data) return;
+ if(!key) return;
+ if(key_len > B) return;
+
+ /*
+ * (1) append zeros to the end of K to create a B byte string
+ * (e.g., if K is of length 20 bytes and B=64, then K will be
+ * appended with 44 zero bytes 0x00)
+ * (2) XOR (bitwise exclusive-OR) the B byte string computed in step
+ * (1) with ipad
+ */
+ for (i = 0; i < key_len; i++) kx[i] = I_PAD ^ key[i];
+ for (i = key_len; i < B; i++) kx[i] = I_PAD ^ 0;
+
+ /*
+ * (3) append the stream of data 'text' to the B byte string resulting
+ * from step (2)
+ * (4) apply H to the stream generated in step (3)
+ */
+ sha256_init (&ss);
+ sha256_update (&ss, kx, B);
+ sha256_update (&ss, data, data_len);
+ sha256_final (&ss, out);
+
+ /*
+ * (5) XOR (bitwise exclusive-OR) the B byte string computed in
+ * step (1) with opad
+ *
+ * NOTE: The "kx" variable is reused.
+ */
+ for (i = 0; i < key_len; i++) kx[i] = O_PAD ^ key[i];
+ for (i = key_len; i < B; i++) kx[i] = O_PAD ^ 0;
+
+ /*
+ * (6) append the H result from step (4) to the B byte string
+ * resulting from step (5)
+ * (7) apply H to the stream generated in step (6) and output
+ * the result
+ */
+ sha256_init (&ss);
+ sha256_update (&ss, kx, B);
+ sha256_update (&ss, out, SHA256_DIGEST_SIZE);
+ sha256_final (&ss, out);
+}
+
+
diff --git a/src/lib/third_party/src/gcrypt/gcm.c b/src/lib/third_party/src/gcrypt/gcm.c
new file mode 100644
index 000000000..824c92bc9
--- /dev/null
+++ b/src/lib/third_party/src/gcrypt/gcm.c
@@ -0,0 +1,667 @@
+/*
+ * NIST SP800-38D compliant GCM implementation
+ *
+ * Copyright The Mbed TLS Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
+ *
+ * See also:
+ * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
+ *
+ * We use the algorithm described as Shoup's method with 4-bit tables in
+ * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory.
+ */
+
+
+/* Parameter validation macros */
+#define GCM_VALIDATE_RET( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_GCM_BAD_INPUT )
+#define GCM_VALIDATE( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE( cond )
+
+#define LBLOCKSIZE __SIZEOF_LONG__
+
+static void xorbytes( unsigned char *dst, const unsigned char *src, int n) {
+ while(n > LBLOCKSIZE) {
+ *(unsigned long int *)dst ^= *(const unsigned long int *)src;
+ dst += LBLOCKSIZE;
+ src += LBLOCKSIZE;
+ n -= LBLOCKSIZE;
+ }
+ while(n) {
+ *dst++ ^= *src++;
+ n--;
+ }
+}
+
+static void xorbytes3d( unsigned char *output, unsigned char *buf,
+ const unsigned char *ectr, const unsigned char *input, int n) {
+ while(n > LBLOCKSIZE) {
+ *(unsigned long int *)buf ^= *(const unsigned long int *)input;
+ *(unsigned long int *)output = *(const unsigned long int *)input ^ *(const unsigned long int *)ectr;
+ buf += LBLOCKSIZE;
+ output += LBLOCKSIZE;
+ ectr += LBLOCKSIZE;
+ input += LBLOCKSIZE;
+ n -= LBLOCKSIZE;
+ }
+ while(n) {
+ *buf++ ^= *input;
+ *output++ = *input++ ^ *ectr++;
+ n--;
+ }
+}
+
+static void xorbytes3e( unsigned char *output, unsigned char *buf,
+ const unsigned char *ectr, const unsigned char *input, int n) {
+ while(n > LBLOCKSIZE) {
+ unsigned long int t = *(const unsigned long int *)input ^ *(const unsigned long int *)ectr;
+ *(unsigned long int *)output = t;
+ *(unsigned long int *)buf ^= t;
+ buf += LBLOCKSIZE;
+ output += LBLOCKSIZE;
+ ectr += LBLOCKSIZE;
+ input += LBLOCKSIZE;
+ n -= LBLOCKSIZE;
+ }
+ while(n) {
+ *output++ = *input++ ^ *ectr++;
+ *buf++ ^= *output++;
+ n--;
+ }
+}
+
+
+
+/*
+ * Initialize a context
+ */
+void mbedtls_gcm_init( mbedtls_gcm_context *ctx, void *aes_ctx )
+{
+ GCM_VALIDATE( ctx != NULL );
+ memset( ctx, 0, sizeof( mbedtls_gcm_context ) );
+ ctx->cipher_ctx.cipher_ctx = aes_ctx;
+}
+
+/*
+ * Precompute small multiples of H, that is set
+ * HH[i] || HL[i] = H times i,
+ * where i is seen as a field element as in [MGV], ie high-order bits
+ * correspond to low powers of P. The result is stored in the same way, that
+ * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
+ * corresponds to P^127.
+ */
+static int gcm_gen_table( mbedtls_gcm_context *ctx )
+{
+ int ret, i, j;
+ uint64_t hi, lo;
+ uint64_t vl, vh;
+ unsigned char h[16];
+ size_t olen = 0;
+
+ memset( h, 0, 16 );
+ if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 )
+ return( ret );
+
+ /* pack h as two 64-bits ints, big-endian */
+ hi = MBEDTLS_GET_UINT32_BE( h, 0 );
+ lo = MBEDTLS_GET_UINT32_BE( h, 4 );
+ vh = (uint64_t) hi << 32 | lo;
+
+ hi = MBEDTLS_GET_UINT32_BE( h, 8 );
+ lo = MBEDTLS_GET_UINT32_BE( h, 12 );
+ vl = (uint64_t) hi << 32 | lo;
+
+ /* 8 = 1000 corresponds to 1 in GF(2^128) */
+ ctx->HL[8] = vl;
+ ctx->HH[8] = vh;
+
+#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
+ /* With CLMUL support, we need only h, not the rest of the table */
+ if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) {
+ aes_aesni_has_support = 1;
+ return( 0 );
+ }
+#endif
+
+ /* 0 corresponds to 0 in GF(2^128) */
+ ctx->HH[0] = 0;
+ ctx->HL[0] = 0;
+
+ for( i = 4; i > 0; i >>= 1 )
+ {
+ uint32_t T = ( vl & 1 ) * 0xe1000000U;
+ vl = ( vh << 63 ) | ( vl >> 1 );
+ vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32);
+
+ ctx->HL[i] = vl;
+ ctx->HH[i] = vh;
+ }
+
+ for( i = 2; i <= 8; i *= 2 )
+ {
+ uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
+ vh = *HiH;
+ vl = *HiL;
+ for( j = 1; j < i; j++ )
+ {
+ HiH[j] = vh ^ ctx->HH[j];
+ HiL[j] = vl ^ ctx->HL[j];
+ }
+ }
+
+ return( 0 );
+}
+
+int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx,
+ mbedtls_cipher_id_t cipher,
+ const unsigned char *key,
+ unsigned int keybits )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ const mbedtls_cipher_info_t *cipher_info;
+
+ GCM_VALIDATE_RET( ctx != NULL );
+ GCM_VALIDATE_RET( key != NULL );
+ GCM_VALIDATE_RET( keybits == 128 || keybits == 192 || keybits == 256 );
+
+ cipher_info = mbedtls_cipher_info_from_values( cipher, keybits,
+ MBEDTLS_MODE_ECB );
+ if( cipher_info == NULL )
+ return( MBEDTLS_ERR_GCM_BAD_INPUT );
+
+ if( cipher_info->block_size != 16 )
+ return( MBEDTLS_ERR_GCM_BAD_INPUT );
+
+ if(ctx->cipher_ctx.cipher_ctx == NULL) return MBEDTLS_ERR_GCM_BAD_INPUT;
+ if(!cipher_info->base->ctx_zero_func) return MBEDTLS_ERR_GCM_BAD_INPUT;
+ (*cipher_info->base->ctx_zero_func)(ctx->cipher_ctx.cipher_ctx);
+ ctx->cipher_ctx.cipher_info = cipher_info;
+
+ if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits,
+ MBEDTLS_ENCRYPT ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ if( ( ret = gcm_gen_table( ctx ) ) != 0 )
+ return( ret );
+
+ return( 0 );
+}
+
+/*
+ * Shoup's method for multiplication use this table with
+ * last4[x] = x times P^128
+ * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
+ */
+static const uint64_t last4[16] =
+{
+ 0x0000UL << 48, 0x1c20UL << 48, 0x3840UL << 48, 0x2460UL << 48,
+ 0x7080UL << 48, 0x6ca0UL << 48, 0x48c0UL << 48, 0x54e0UL << 48,
+ 0xe100UL << 48, 0xfd20UL << 48, 0xd940UL << 48, 0xc560UL << 48,
+ 0x9180UL << 48, 0x8da0UL << 48, 0xa9c0UL << 48, 0xb5e0UL << 48
+};
+
+/*
+ * Sets output to x times H using the precomputed tables.
+ * x and output are seen as elements of GF(2^128) as in [MGV].
+ */
+static void gcm_mult( mbedtls_gcm_context *ctx, const unsigned char x[16],
+ unsigned char output[16] )
+{
+ int i = 0;
+ unsigned char lo, hi, rem;
+ uint64_t zh, zl;
+
+#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
+ if( aes_aesni_has_support) {
+ unsigned char h[16];
+
+ MBEDTLS_PUT_UINT64_BE( ctx->HH[8], h, 0 );
+ MBEDTLS_PUT_UINT64_BE( ctx->HL[8], h, 8 );
+
+ mbedtls_aesni_gcm_mult( output, x, h );
+ return;
+ }
+#endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */
+
+ lo = x[15] & 0xf;
+
+ zh = ctx->HH[lo];
+ zl = ctx->HL[lo];
+
+ for( i = 15; i >= 0; i-- )
+ {
+ lo = x[i] & 0xf;
+ hi = ( x[i] >> 4 ) & 0xf;
+
+ if( i != 15 )
+ {
+ rem = (unsigned char) zl & 0xf;
+ zl = ( zh << 60 ) | ( zl >> 4 );
+ zh = ( zh >> 4 );
+ zh ^= (uint64_t) last4[rem];
+ zh ^= ctx->HH[lo];
+ zl ^= ctx->HL[lo];
+
+ }
+
+ rem = (unsigned char) zl & 0xf;
+ zl = ( zh << 60 ) | ( zl >> 4 );
+ zh = ( zh >> 4 );
+ zh ^= (uint64_t) last4[rem];
+ zh ^= ctx->HH[hi];
+ zl ^= ctx->HL[hi];
+ }
+ MBEDTLS_PUT_UINT64_BE( zh, output, 0 );
+ MBEDTLS_PUT_UINT64_BE( zl, output, 8 );
+}
+
+int mbedtls_gcm_starts( mbedtls_gcm_context *ctx,
+ int mode,
+ const unsigned char *iv, size_t iv_len )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ unsigned char work_buf[16];
+ const unsigned char *p;
+ size_t use_len, olen = 0;
+ uint64_t iv_bits;
+
+ GCM_VALIDATE_RET( ctx != NULL );
+ GCM_VALIDATE_RET( iv != NULL );
+
+ /* IV is limited to 2^64 bits, so 2^61 bytes */
+ /* IV is not allowed to be zero length */
+ if( iv_len == 0)
+ return( MBEDTLS_ERR_GCM_BAD_INPUT );
+#if __SIZE_WIDTH__ == 64
+ if( iv_len >= (1UL << 32 ))
+ return( MBEDTLS_ERR_GCM_BAD_INPUT );
+#endif
+
+ memset( ctx->y, 0x00, sizeof(ctx->y) );
+ memset( ctx->buf, 0x00, sizeof(ctx->buf) );
+
+ ctx->mode = mode;
+ ctx->len = 0;
+ ctx->add_len = 0;
+
+ if( iv_len == 12 )
+ {
+ memcpy( ctx->y, iv, iv_len );
+ ctx->y[15] = 1;
+ }
+ else
+ {
+ memset( work_buf, 0x00, 16 );
+ iv_bits = (uint64_t)iv_len * 8;
+ MBEDTLS_PUT_UINT64_BE( iv_bits, work_buf, 8 );
+
+ p = iv;
+ while( iv_len > 0 )
+ {
+ use_len = ( iv_len < 16 ) ? iv_len : 16;
+
+ xorbytes(ctx->y,p,use_len);
+
+ gcm_mult( ctx, ctx->y, ctx->y );
+
+ iv_len -= use_len;
+ p += use_len;
+ }
+
+ xorbytes(ctx->y,work_buf,16);
+
+ gcm_mult( ctx, ctx->y, ctx->y );
+ }
+
+ if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16,
+ ctx->base_ectr, &olen ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ return( 0 );
+}
+
+/**
+ * mbedtls_gcm_context::buf contains the partial state of the computation of
+ * the authentication tag.
+ * mbedtls_gcm_context::add_len and mbedtls_gcm_context::len indicate
+ * different stages of the computation:
+ * * len == 0 && add_len == 0: initial state
+ * * len == 0 && add_len % 16 != 0: the first `add_len % 16` bytes have
+ * a partial block of AD that has been
+ * xored in but not yet multiplied in.
+ * * len == 0 && add_len % 16 == 0: the authentication tag is correct if
+ * the data ends now.
+ * * len % 16 != 0: the first `len % 16` bytes have
+ * a partial block of ciphertext that has
+ * been xored in but not yet multiplied in.
+ * * len > 0 && len % 16 == 0: the authentication tag is correct if
+ * the data ends now.
+ */
+int mbedtls_gcm_update_ad( mbedtls_gcm_context *ctx,
+ const unsigned char *add, size_t add_len )
+{
+ const unsigned char *p;
+ size_t use_len, offset;
+
+ GCM_VALIDATE_RET( add_len == 0 || add != NULL );
+
+ /* IV is limited to 2^64 bits, so 2^61 bytes */
+ if( (uint64_t) add_len >> 61 != 0 )
+ return( MBEDTLS_ERR_GCM_BAD_INPUT );
+
+ offset = ctx->add_len % 16;
+ p = add;
+
+ if( offset != 0 )
+ {
+ use_len = 16 - offset;
+ if( use_len > add_len )
+ use_len = add_len;
+
+ xorbytes(ctx->buf,p,use_len);
+
+ if( offset + use_len == 16 )
+ gcm_mult( ctx, ctx->buf, ctx->buf );
+
+ ctx->add_len += use_len;
+ add_len -= use_len;
+ p += use_len;
+ }
+
+ ctx->add_len += add_len;
+
+ while( add_len >= 16 )
+ {
+ xorbytes(ctx->buf,p,16);
+
+ gcm_mult( ctx, ctx->buf, ctx->buf );
+
+ add_len -= 16;
+ p += 16;
+ }
+
+ if( add_len > 0 )
+ xorbytes(ctx->buf,p,add_len);
+
+ return( 0 );
+}
+
+/* Increment the counter. */
+static void gcm_incr( unsigned char y[16] )
+{
+ size_t i;
+ for( i = 16; i > 12; i-- )
+ if( ++y[i - 1] != 0 )
+ break;
+}
+
+/* Calculate and apply the encryption mask. Process use_len bytes of data,
+ * starting at position offset in the mask block. */
+static int gcm_mask( mbedtls_gcm_context *ctx,
+ unsigned char ectr[16],
+ size_t offset, size_t use_len,
+ const unsigned char *input,
+ unsigned char *output )
+{
+ size_t olen = 0;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+ if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr,
+ &olen ) ) != 0 )
+ {
+ mbedtls_platform_zeroize( ectr, 16 );
+ return( ret );
+ }
+
+ if(ctx->mode == MBEDTLS_GCM_DECRYPT )
+ xorbytes3d(output,&ctx->buf[offset],&ectr[offset],input,use_len);
+ else
+ xorbytes3e(output,&ctx->buf[offset],&ectr[offset],input,use_len);
+
+ return( 0 );
+}
+
+int mbedtls_gcm_update( mbedtls_gcm_context *ctx,
+ const unsigned char *input, size_t input_length,
+ unsigned char *output, size_t output_size,
+ size_t *output_length )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ const unsigned char *p = input;
+ unsigned char *out_p = output;
+ size_t offset;
+ unsigned char ectr[16];
+
+ if( output_size < input_length )
+ return( MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL );
+ GCM_VALIDATE_RET( output_length != NULL );
+ *output_length = input_length;
+
+ /* Exit early if input_length==0 so that we don't do any pointer arithmetic
+ * on a potentially null pointer.
+ * Returning early also means that the last partial block of AD remains
+ * untouched for mbedtls_gcm_finish */
+ if( input_length == 0 )
+ return( 0 );
+
+ GCM_VALIDATE_RET( ctx != NULL );
+ GCM_VALIDATE_RET( input != NULL );
+ GCM_VALIDATE_RET( output != NULL );
+
+ if( output > input && (size_t) ( output - input ) < input_length )
+ return( MBEDTLS_ERR_GCM_BAD_INPUT );
+
+ /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
+ * Also check for possible overflow */
+ if( ctx->len + input_length < ctx->len ||
+ (uint64_t) ctx->len + input_length > 0xFFFFFFFE0ull )
+ {
+ return( MBEDTLS_ERR_GCM_BAD_INPUT );
+ }
+
+ if( ctx->len == 0 && ctx->add_len % 16 != 0 )
+ {
+ gcm_mult( ctx, ctx->buf, ctx->buf );
+ }
+
+ offset = ctx->len % 16;
+ if( offset != 0 )
+ {
+ size_t use_len = 16 - offset;
+ if( use_len > input_length )
+ use_len = input_length;
+
+ if( ( ret = gcm_mask( ctx, ectr, offset, use_len, p, out_p ) ) != 0 )
+ return( ret );
+
+ if( offset + use_len == 16 )
+ gcm_mult( ctx, ctx->buf, ctx->buf );
+
+ ctx->len += use_len;
+ input_length -= use_len;
+ p += use_len;
+ out_p += use_len;
+ }
+
+ ctx->len += input_length;
+
+ while( input_length >= 16 )
+ {
+ gcm_incr( ctx->y );
+ if( ( ret = gcm_mask( ctx, ectr, 0, 16, p, out_p ) ) != 0 )
+ return( ret );
+
+ gcm_mult( ctx, ctx->buf, ctx->buf );
+
+ input_length -= 16;
+ p += 16;
+ out_p += 16;
+ }
+
+ if( input_length > 0 )
+ {
+ gcm_incr( ctx->y );
+ if( ( ret = gcm_mask( ctx, ectr, 0, input_length, p, out_p ) ) != 0 )
+ return( ret );
+ }
+
+ return( 0 );
+}
+
+int mbedtls_gcm_finish( mbedtls_gcm_context *ctx,
+ unsigned char *output, size_t output_size,
+ size_t *output_length,
+ unsigned char *tag, size_t tag_len )
+{
+ unsigned char work_buf[16];
+ uint64_t orig_len;
+ uint64_t orig_add_len;
+
+ GCM_VALIDATE_RET( ctx != NULL );
+ GCM_VALIDATE_RET( tag != NULL );
+
+ /* We never pass any output in finish(). The output parameter exists only
+ * for the sake of alternative implementations. */
+ (void) output;
+ (void) output_size;
+ *output_length = 0;
+
+ orig_len = ctx->len * 8;
+ orig_add_len = ctx->add_len * 8;
+
+ if( ctx->len == 0 && ctx->add_len % 16 != 0 )
+ {
+ gcm_mult( ctx, ctx->buf, ctx->buf );
+ }
+
+ if( tag_len > 16 || tag_len < 4 )
+ return( MBEDTLS_ERR_GCM_BAD_INPUT );
+
+ if( ctx->len % 16 != 0 )
+ gcm_mult( ctx, ctx->buf, ctx->buf );
+
+ memcpy( tag, ctx->base_ectr, tag_len );
+
+ if( orig_len || orig_add_len )
+ {
+ MBEDTLS_PUT_UINT64_BE( ( orig_add_len ), work_buf, 0 );
+ MBEDTLS_PUT_UINT64_BE( ( orig_len ), work_buf, 8 );
+
+ xorbytes(ctx->buf,work_buf,16);
+
+ gcm_mult( ctx, ctx->buf, ctx->buf );
+
+ xorbytes(tag,ctx->buf,tag_len);
+ }
+
+ return( 0 );
+}
+
+int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx,
+ int mode,
+ size_t length,
+ const unsigned char *iv,
+ size_t iv_len,
+ const unsigned char *add,
+ size_t add_len,
+ const unsigned char *input,
+ unsigned char *output,
+ size_t tag_len,
+ unsigned char *tag )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t olen;
+
+ GCM_VALIDATE_RET( ctx != NULL );
+ GCM_VALIDATE_RET( iv != NULL );
+ GCM_VALIDATE_RET( add_len == 0 || add != NULL );
+ GCM_VALIDATE_RET( length == 0 || input != NULL );
+ GCM_VALIDATE_RET( length == 0 || output != NULL );
+ GCM_VALIDATE_RET( tag != NULL );
+
+ if( ( ret = mbedtls_gcm_starts( ctx, mode, iv, iv_len ) ) != 0 )
+ return( ret );
+
+ if( ( ret = mbedtls_gcm_update_ad( ctx, add, add_len ) ) != 0 )
+ return( ret );
+
+ if( ( ret = mbedtls_gcm_update( ctx, input, length,
+ output, length, &olen ) ) != 0 )
+ return( ret );
+
+ if( ( ret = mbedtls_gcm_finish( ctx, NULL, 0, &olen, tag, tag_len ) ) != 0 )
+ return( ret );
+
+ return( 0 );
+}
+
+int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx,
+ size_t length,
+ const unsigned char *iv,
+ size_t iv_len,
+ const unsigned char *add,
+ size_t add_len,
+ const unsigned char *tag,
+ size_t tag_len,
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ unsigned char check_tag[16];
+ size_t i;
+ int diff;
+
+ GCM_VALIDATE_RET( ctx != NULL );
+ GCM_VALIDATE_RET( iv != NULL );
+ GCM_VALIDATE_RET( add_len == 0 || add != NULL );
+ GCM_VALIDATE_RET( tag != NULL );
+ GCM_VALIDATE_RET( length == 0 || input != NULL );
+ GCM_VALIDATE_RET( length == 0 || output != NULL );
+
+ if( ( ret = mbedtls_gcm_crypt_and_tag( ctx, MBEDTLS_GCM_DECRYPT, length,
+ iv, iv_len, add, add_len,
+ input, output, tag_len, check_tag ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ /* Check tag in "constant-time" */
+ for( diff = 0, i = 0; i < tag_len; i++ )
+ diff |= tag[i] ^ check_tag[i];
+
+ if( diff != 0 )
+ {
+ mbedtls_platform_zeroize( output, length );
+ return( MBEDTLS_ERR_GCM_AUTH_FAILED );
+ }
+
+ return( 0 );
+}
+
+void mbedtls_gcm_free( mbedtls_gcm_context *ctx )
+{
+ if( ctx == NULL )
+ return;
+ // mbedtls_cipher_free( &ctx->cipher_ctx );
+}
+
diff --git a/src/lib/third_party/src/gcrypt_light.c b/src/lib/third_party/src/gcrypt_light.c
new file mode 100644
index 000000000..9c8a9e3f3
--- /dev/null
+++ b/src/lib/third_party/src/gcrypt_light.c
@@ -0,0 +1,375 @@
+
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "ndpi_api.h"
+
+#if !defined(HAVE_LIBGCRYPT)
+
+#if defined(__GNUC__) && \
+ ( defined(__amd64__) || defined(__x86_64__) ) && \
+ ! defined(MBEDTLS_HAVE_X86_64)
+#define MBEDTLS_HAVE_X86_64
+#define MBEDTLS_AESNI_C
+#endif
+
+/****************************/
+#define MBEDTLS_GCM_C
+#define MBEDTLS_CIPHER_C
+#define MBEDTLS_AES_C
+/****************************/
+
+#define mbedtls_calloc ndpi_calloc
+#define mbedtls_free ndpi_free
+
+#include "gcrypt_light.h"
+
+#define MBEDTLS_CHECK_RETURN_TYPICAL
+#define MBEDTLS_INTERNAL_VALIDATE_RET( cond, ret ) do { } while( 0 )
+#define MBEDTLS_INTERNAL_VALIDATE( cond ) do { } while( 0 )
+
+#define mbedtls_platform_zeroize(a,b) memset(a,0,b)
+#define mbedtls_ct_memcmp(s1,s2,n) memcmp(s1,s2,n)
+
+#include "gcrypt/common.h"
+#include "gcrypt/error.h"
+#include "gcrypt/aes.h"
+#if defined(MBEDTLS_AESNI_C)
+#include "gcrypt/aesni.h"
+#endif
+#include "gcrypt/cipher.h"
+#include "gcrypt/gcm.h"
+#include "gcrypt/digest.h"
+#include "gcrypt/cipher_wrap.h"
+
+
+#include "gcrypt/aes.c"
+#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
+#include "gcrypt/aesni.c"
+#endif
+
+#include "gcrypt/gcm.c"
+
+#include "gcrypt/cipher.c"
+#include "gcrypt/cipher_wrap.c"
+#include "gcrypt/digest.c"
+
+#define MBEDTLS_ERR_MD_ALLOC_FAILED 0x50f0
+#define MBEDTLS_ERR_MD_NOT_SUPPORT 0x50f1
+#define MBEDTLS_ERR_MD_REKEY 0x50f2
+#define MBEDTLS_ERR_MD_DATA_TOO_BIG 0x50f3
+#define MBEDTLS_ERR_CIPHER_BAD_KEY 0x50f4
+#define MBEDTLS_ERR_GCM_ALLOC_FAILED 0x50f5
+#define MBEDTLS_ERR_GCM_NOT_SUPPORT 0x50f6
+#define MBEDTLS_ERR_GCM_MISSING_KEY 0x50f7
+#define MBEDTLS_ERR_AES_MISSING_KEY 0x50f8
+#define MBEDTLS_ERR_NOT_SUPPORT 0x50f9
+
+const char *gcry_errstr(gcry_error_t err) {
+ switch(err) {
+ case MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED: return "Corruption detected";
+ case MBEDTLS_ERR_MD_ALLOC_FAILED: return "MD:Alloc failed";
+ case MBEDTLS_ERR_MD_NOT_SUPPORT: return "MD:Not supported";
+ case MBEDTLS_ERR_MD_REKEY: return "MD:Key already set";
+ case MBEDTLS_ERR_MD_DATA_TOO_BIG: return "MD:Data is too long";
+ case MBEDTLS_ERR_AES_BAD_INPUT_DATA: return "AES:Bad input data";
+ case MBEDTLS_ERR_AES_MISSING_KEY: return "AES:No key";
+ case MBEDTLS_ERR_AES_INVALID_KEY_LENGTH: return "AES:Invalid key length";
+ case MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH: return "AES:Invalid input length";
+ case MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA: return "CIPHER:Bad input data";
+ case MBEDTLS_ERR_CIPHER_ALLOC_FAILED: return "CIPHER:Alloc failed";
+ case MBEDTLS_ERR_CIPHER_BAD_KEY: return "CIPHER:Wrong key/iv";
+ case MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE: return "CIPHER:Feature unavailable";
+ case MBEDTLS_ERR_CIPHER_INVALID_CONTEXT: return "CIPHER:Invalid context";
+ case MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED: return "CIPHER:Full block expected";
+ case MBEDTLS_ERR_CIPHER_AUTH_FAILED: return "CIPHER:Auth failed";
+ case MBEDTLS_ERR_GCM_AUTH_FAILED: return "GCM:Auth failed";
+ case MBEDTLS_ERR_GCM_BAD_INPUT: return "GCM:Bad input";
+ case MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL: return "GCM:Buffer too small";
+ case MBEDTLS_ERR_GCM_ALLOC_FAILED: return "GCM:Alloc failed";
+ case MBEDTLS_ERR_GCM_NOT_SUPPORT: return "GCM:Not supported";
+ case MBEDTLS_ERR_GCM_MISSING_KEY: return "GCM:No key/siv/auth";
+ case MBEDTLS_ERR_NOT_SUPPORT: return "Not supported";
+ }
+ return "Unknown error code";
+}
+
+char *gpg_strerror_r(gcry_error_t err,char *buf, size_t buflen) {
+ const char *err_txt = gcry_errstr(err);
+ strncpy(buf,err_txt,buflen-1);
+ return buf;
+}
+
+int gcry_control (int ctl,int val) {
+ if(ctl == GCRYCTL_INITIALIZATION_FINISHED) return GPG_ERR_NO_ERROR;
+ return MBEDTLS_ERR_NOT_SUPPORT;
+}
+
+const char *gcry_check_version(void *unused) {
+ return "1.8.6internal";
+}
+
+gcry_error_t gcry_md_open(gcry_md_hd_t *h,int algo,int flags) {
+ gcry_md_hd_t ctx;
+ if(!(algo == GCRY_MD_SHA256 && flags == GCRY_MD_FLAG_HMAC)) return MBEDTLS_ERR_MD_NOT_SUPPORT;
+ ctx = ndpi_calloc(1,sizeof(struct gcry_md_hd));
+ if(!ctx) return MBEDTLS_ERR_MD_ALLOC_FAILED;
+ *h = ctx;
+ return GPG_ERR_NO_ERROR;
+}
+
+void gcry_md_close(gcry_md_hd_t h) {
+ if(h) ndpi_free(h);
+}
+
+void gcry_md_reset(gcry_md_hd_t h) {
+ memset((char *)h, 0, sizeof(*h));
+}
+
+gcry_error_t gcry_md_setkey(gcry_md_hd_t h,const uint8_t *key,size_t key_len) {
+ if(h->key_len) return MBEDTLS_ERR_MD_REKEY;
+ h->key_len = key_len <= sizeof(h->key) ? key_len : sizeof(h->key);
+ memcpy(h->key,key,h->key_len);
+ return GPG_ERR_NO_ERROR;
+}
+
+gcry_error_t gcry_md_write(gcry_md_hd_t h,const uint8_t *data,size_t data_len) {
+ if(h->data_len + data_len > GCRY_MD_BUFF_SIZE) return MBEDTLS_ERR_MD_DATA_TOO_BIG;
+ memcpy(&h->data_buf[h->data_len],data,data_len);
+ h->data_len += data_len;
+ return GPG_ERR_NO_ERROR;
+}
+
+size_t gcry_md_get_algo_dlen(int algo) {
+ return algo == GCRY_MD_SHA256 ? HMAC_SHA256_DIGEST_SIZE:0;
+}
+
+int gcry_md_get_algo(gcry_md_hd_t h) {
+ return GCRY_MD_SHA256;
+}
+
+uint8_t *gcry_md_read(gcry_md_hd_t h, int flag) {
+ hmac_sha256(h->out,h->data_buf,h->data_len,h->key,h->key_len);
+ return h->out;
+}
+
+/**********************************************************/
+
+static int check_valid_algo_mode(gcry_cipher_hd_t h) {
+ if(!h) return 1;
+ if(h->algo == GCRY_CIPHER_AES128 &&
+ (h->mode == GCRY_CIPHER_MODE_ECB || h->mode == GCRY_CIPHER_MODE_GCM)) return 0;
+ return 1;
+}
+
+#define ROUND_SIZE8(a) (((a)+7UL) & ~7UL)
+
+gcry_error_t gcry_cipher_open (gcry_cipher_hd_t *handle,
+ int algo, int mode, unsigned int flags) {
+
+struct gcry_cipher_hd *r = 0;
+size_t s_len = ROUND_SIZE8(sizeof(struct gcry_cipher_hd));;
+
+ if(flags || algo != GCRY_CIPHER_AES128 || !( mode == GCRY_CIPHER_MODE_ECB || mode == GCRY_CIPHER_MODE_GCM)) return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
+
+ switch(mode) {
+ case GCRY_CIPHER_MODE_ECB:
+ r = ndpi_calloc(1,s_len + sizeof(mbedtls_aes_context));
+ if(!r) return MBEDTLS_ERR_CIPHER_ALLOC_FAILED;
+ r->ctx.ecb = (mbedtls_aes_context *)(r+1);
+ mbedtls_aes_init(r->ctx.ecb);
+ break;
+ case GCRY_CIPHER_MODE_GCM:
+ {
+ size_t aes_ctx_size = ROUND_SIZE8(sizeof( mbedtls_aes_context ));
+ size_t gcm_ctx_size = ROUND_SIZE8(sizeof( mbedtls_gcm_context ));
+
+ r = ndpi_calloc(1,s_len + gcm_ctx_size + aes_ctx_size);
+ if(!r) return MBEDTLS_ERR_CIPHER_ALLOC_FAILED;
+ r->ctx.gcm = (mbedtls_gcm_context *)(r+1);
+ mbedtls_gcm_init(r->ctx.gcm,(void *)(((char *)(r+1)) + gcm_ctx_size));
+ }
+ break;
+ default:
+ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
+ }
+ r->algo = algo;
+ r->mode = mode;
+ *handle = r;
+ return GPG_ERR_NO_ERROR;
+}
+
+void gcry_cipher_close (gcry_cipher_hd_t h) {
+ if(h && !check_valid_algo_mode(h)) {
+ switch(h->mode) {
+ case GCRY_CIPHER_MODE_ECB:
+ mbedtls_aes_free(h->ctx.ecb);
+ break;
+ case GCRY_CIPHER_MODE_GCM:
+ mbedtls_gcm_free(h->ctx.gcm);
+ break;
+ }
+ ndpi_free(h);
+ }
+}
+
+gcry_error_t gcry_cipher_ctl (gcry_cipher_hd_t h, int cmd, void *data, size_t len) {
+ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
+}
+
+gcry_error_t gcry_cipher_reset (gcry_cipher_hd_t h) {
+
+ gcry_error_t err = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
+ if(check_valid_algo_mode(h)) return err;
+ h->authlen = 0; h->taglen = 0; h->ivlen = 0;
+ h->s_auth = 0; h->s_iv = 0; h->s_crypt_ok = 0;
+ memset((char *)h->iv,0,sizeof(h->iv));
+ memset((char *)h->auth,0,sizeof(h->auth));
+ memset((char *)h->tag,0,sizeof(h->tag));
+ switch(h->mode) {
+ case GCRY_CIPHER_MODE_ECB:
+ break;
+ case GCRY_CIPHER_MODE_GCM:
+ mbedtls_cipher_reset(&h->ctx.gcm->cipher_ctx);
+ break;
+ default:
+ return err;
+ }
+ return 0;
+}
+
+
+gcry_error_t gcry_cipher_setkey (gcry_cipher_hd_t h, const void *key, size_t keylen) {
+ gcry_error_t r = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+ if(check_valid_algo_mode(h)) return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
+ if( h->s_key ) return MBEDTLS_ERR_CIPHER_BAD_KEY;
+ if( keylen != gcry_cipher_get_algo_keylen(h->algo)) return MBEDTLS_ERR_CIPHER_BAD_KEY;
+ switch(h->mode) {
+ case GCRY_CIPHER_MODE_ECB:
+ r = mbedtls_aes_setkey_enc( h->ctx.ecb, key, keylen*8 );
+ break;
+ case GCRY_CIPHER_MODE_GCM:
+ r = mbedtls_gcm_setkey( h->ctx.gcm, MBEDTLS_CIPHER_ID_AES, key, keylen*8 );
+ break;
+ }
+ if(!r) {
+ h->s_key = 1;
+ h->keylen = keylen;
+ }
+ return r;
+}
+
+gcry_error_t gcry_cipher_setiv (gcry_cipher_hd_t h, const void *iv, size_t ivlen) {
+ if(check_valid_algo_mode(h)) return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
+ if(h->s_iv) return MBEDTLS_ERR_CIPHER_BAD_KEY;
+ switch(h->mode) {
+ case GCRY_CIPHER_MODE_GCM:
+ if(ivlen != 12) return MBEDTLS_ERR_CIPHER_BAD_KEY;
+ h->s_iv = 1;
+ h->ivlen = ivlen;
+ memcpy( h->iv, iv, ivlen );
+ return 0;
+ }
+ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
+}
+
+gcry_error_t gcry_cipher_authenticate (gcry_cipher_hd_t h, const void *abuf, size_t abuflen) {
+ if(check_valid_algo_mode(h)) return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
+ if(h->s_auth) return MBEDTLS_ERR_CIPHER_BAD_KEY;
+ switch(h->mode) {
+ case GCRY_CIPHER_MODE_GCM:
+ if(abuflen > sizeof(h->auth)) return MBEDTLS_ERR_CIPHER_BAD_KEY;
+ h->s_auth = 1;
+ h->authlen = abuflen;
+ memcpy(h->auth,abuf,abuflen);
+ return 0;
+ }
+ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
+}
+
+gcry_error_t gcry_cipher_checktag (gcry_cipher_hd_t h, const void *intag, size_t taglen) {
+ if(check_valid_algo_mode(h)) return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
+ switch(h->mode) {
+ case GCRY_CIPHER_MODE_GCM:
+ if(h->s_crypt_ok && h->taglen == taglen) {
+ size_t i;
+ int diff;
+ const uint8_t *ctag = intag;
+ for( diff = 0, i = 0; i < taglen; i++ )
+ diff |= ctag[i] ^ h->tag[i];
+ if(!diff) return 0;
+ }
+ return MBEDTLS_ERR_GCM_AUTH_FAILED;
+ }
+ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
+}
+
+size_t gcry_cipher_get_algo_keylen (int algo) {
+ switch(algo) {
+ case GCRY_CIPHER_AES128: return 16;
+ default: return 0;
+ }
+ return 0;
+}
+
+static gcry_error_t _gcry_cipher_crypt (gcry_cipher_hd_t h,
+ void *out, size_t outsize,
+ const void *in, size_t inlen,int encrypt) {
+ uint8_t *src = NULL;
+ size_t srclen = 0;
+ gcry_error_t rv = MBEDTLS_ERR_GCM_BAD_INPUT;
+
+ if(check_valid_algo_mode(h)) return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
+ if(!inlen && !outsize) return MBEDTLS_ERR_GCM_BAD_INPUT;
+ if(!in && !inlen) {
+ src = ndpi_malloc(outsize);
+ if(!src) return MBEDTLS_ERR_GCM_ALLOC_FAILED;
+ srclen = outsize;
+ memcpy(src,out,outsize);
+ } else {
+ if(inlen != outsize) return MBEDTLS_ERR_GCM_BAD_INPUT;
+ }
+ switch(h->mode) {
+ case GCRY_CIPHER_MODE_ECB:
+ if(!encrypt) return MBEDTLS_ERR_GCM_NOT_SUPPORT;
+ if(!( h->s_key && !h->s_crypt_ok)) return MBEDTLS_ERR_AES_MISSING_KEY;
+ rv = mbedtls_aes_crypt_ecb(h->ctx.ecb, MBEDTLS_AES_ENCRYPT,
+ src ? src:in, out);
+ break;
+ case GCRY_CIPHER_MODE_GCM:
+ if(encrypt) return MBEDTLS_ERR_GCM_NOT_SUPPORT;
+ if(!( h->s_key && h->s_auth && h->s_iv && !h->s_crypt_ok)) return MBEDTLS_ERR_GCM_MISSING_KEY;
+ h->taglen = 16;
+ rv = mbedtls_gcm_crypt_and_tag(h->ctx.gcm,
+ MBEDTLS_GCM_DECRYPT,
+ src ? srclen:outsize,
+ h->iv,h->ivlen,
+ h->auth,h->authlen,
+ src ? src:in,out,
+ h->taglen, h->tag);
+ break;
+ }
+ if(!rv) h->s_crypt_ok = 1;
+
+ if(src) ndpi_free(src);
+ return rv;
+}
+
+
+gcry_error_t gcry_cipher_encrypt (gcry_cipher_hd_t h,
+ void *out, size_t outsize,
+ const void *in, size_t inlen) {
+ return _gcry_cipher_crypt(h,out,outsize,in,inlen,1);
+}
+
+gcry_error_t gcry_cipher_decrypt (gcry_cipher_hd_t h,
+ void *out, size_t outsize,
+ const void *in, size_t inlen) {
+ return _gcry_cipher_crypt(h,out,outsize,in,inlen,0);
+}
+
+#endif /* HAVE_LIBGCRYPT */
+
+/* vim: set ts=4 sw=4 et: */