Release Mbed Crypto 0.1.0a
diff --git a/include/mbedcrypto/aes.h b/include/mbedcrypto/aes.h
new file mode 100644
index 0000000..eecf76c
--- /dev/null
+++ b/include/mbedcrypto/aes.h
@@ -0,0 +1,415 @@
+/**
+ * \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>.
+ */
+
+/*  Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved.
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#ifndef MBEDCRYPTO_AES_H
+#define MBEDCRYPTO_AES_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+/* padlock.c and aesni.c rely on these values! */
+#define MBEDCRYPTO_AES_ENCRYPT     1 /**< AES encryption. */
+#define MBEDCRYPTO_AES_DECRYPT     0 /**< AES decryption. */
+
+/* Error codes in range 0x0020-0x0022 */
+#define MBEDCRYPTO_ERR_AES_INVALID_KEY_LENGTH                -0x0020  /**< Invalid key length. */
+#define MBEDCRYPTO_ERR_AES_INVALID_INPUT_LENGTH              -0x0022  /**< Invalid data input length. */
+
+/* Error codes in range 0x0023-0x0025 */
+#define MBEDCRYPTO_ERR_AES_FEATURE_UNAVAILABLE               -0x0023  /**< Feature not available. For example, an unsupported AES key size. */
+#define MBEDCRYPTO_ERR_AES_HW_ACCEL_FAILED                   -0x0025  /**< AES hardware accelerator failed. */
+
+#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
+    !defined(inline) && !defined(__cplusplus)
+#define inline __inline
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDCRYPTO_AES_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief The AES context-type definition.
+ */
+typedef struct
+{
+    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> */
+}
+mbedcrypto_aes_context;
+
+#else  /* MBEDCRYPTO_AES_ALT */
+#include "aes_alt.h"
+#endif /* MBEDCRYPTO_AES_ALT */
+
+/**
+ * \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.
+ */
+void mbedcrypto_aes_init( mbedcrypto_aes_context *ctx );
+
+/**
+ * \brief          This function releases and clears the specified AES context.
+ *
+ * \param ctx      The AES context to clear.
+ */
+void mbedcrypto_aes_free( mbedcrypto_aes_context *ctx );
+
+/**
+ * \brief          This function sets the encryption key.
+ *
+ * \param ctx      The AES context to which the key should be bound.
+ * \param key      The encryption key.
+ * \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         #MBEDCRYPTO_ERR_AES_INVALID_KEY_LENGTH on failure.
+ */
+int mbedcrypto_aes_setkey_enc( mbedcrypto_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.
+ * \param key      The decryption key.
+ * \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         #MBEDCRYPTO_ERR_AES_INVALID_KEY_LENGTH on failure.
+ */
+int mbedcrypto_aes_setkey_dec( mbedcrypto_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.
+ *
+ *                 mbedcrypto_aes_init(), and either mbedcrypto_aes_setkey_enc() or
+ *                 mbedcrypto_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.
+ * \param mode     The AES operation: #MBEDCRYPTO_AES_ENCRYPT or
+ *                 #MBEDCRYPTO_AES_DECRYPT.
+ * \param input    The 16-Byte buffer holding the input data.
+ * \param output   The 16-Byte buffer holding the output data.
+
+ * \return         \c 0 on success.
+ */
+int mbedcrypto_aes_crypt_ecb( mbedcrypto_aes_context *ctx,
+                    int mode,
+                    const unsigned char input[16],
+                    unsigned char output[16] );
+
+#if defined(MBEDCRYPTO_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. mbedcrypto_aes_init(), and either
+ *         mbedcrypto_aes_setkey_enc() or mbedcrypto_aes_setkey_dec() must be called
+ *         before the first call to this API with the same context.
+ *
+ * \note   This function operates on aligned blocks, that is, the input size
+ *         must be a multiple of the AES block size of 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.
+ * \param mode     The AES operation: #MBEDCRYPTO_AES_ENCRYPT or
+ *                 #MBEDCRYPTO_AES_DECRYPT.
+ * \param length   The length of the input data in Bytes. This must be a
+ *                 multiple of the block size (16 Bytes).
+ * \param iv       Initialization vector (updated after use).
+ * \param input    The buffer holding the input data.
+ * \param output   The buffer holding the output data.
+ *
+ * \return         \c 0 on success.
+ * \return         #MBEDCRYPTO_ERR_AES_INVALID_INPUT_LENGTH
+ *                 on failure.
+ */
+int mbedcrypto_aes_crypt_cbc( mbedcrypto_aes_context *ctx,
+                    int mode,
+                    size_t length,
+                    unsigned char iv[16],
+                    const unsigned char *input,
+                    unsigned char *output );
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+/**
+ * \brief This function performs an AES-CFB128 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.
+ *
+ *        For CFB, you must set up the context with mbedcrypto_aes_setkey_enc(),
+ *        regardless of whether you are performing an encryption or decryption
+ *        operation, that is, regardless of the \p mode parameter. This is
+ *        because CFB mode uses the same key schedule for encryption and
+ *        decryption.
+ *
+ * \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 must either save it manually or use the cipher
+ *        module instead.
+ *
+ *
+ * \param ctx      The AES context to use for encryption or decryption.
+ * \param mode     The AES operation: #MBEDCRYPTO_AES_ENCRYPT or
+ *                 #MBEDCRYPTO_AES_DECRYPT.
+ * \param length   The length of the input data.
+ * \param iv_off   The offset in IV (updated after use).
+ * \param iv       The initialization vector (updated after use).
+ * \param input    The buffer holding the input data.
+ * \param output   The buffer holding the output data.
+ *
+ * \return         \c 0 on success.
+ */
+int mbedcrypto_aes_crypt_cfb128( mbedcrypto_aes_context *ctx,
+                       int mode,
+                       size_t length,
+                       size_t *iv_off,
+                       unsigned char iv[16],
+                       const unsigned char *input,
+                       unsigned char *output );
+
+/**
+ * \brief This function performs an AES-CFB8 encryption or decryption
+ *        operation.
+ *
+ *        It performs the operation defined in the \p mode
+ *        parameter (encrypt/decrypt), on the input data buffer defined
+ *        in the \p input parameter.
+ *
+ *        Due to the nature of CFB, you must use the same key schedule for
+ *        both encryption and decryption operations. Therefore, you must
+ *        use the context initialized with mbedcrypto_aes_setkey_enc() for
+ *        both #MBEDCRYPTO_AES_ENCRYPT and #MBEDCRYPTO_AES_DECRYPT.
+ *
+ * \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.
+ * \param mode     The AES operation: #MBEDCRYPTO_AES_ENCRYPT or
+ *                 #MBEDCRYPTO_AES_DECRYPT
+ * \param length   The length of the input data.
+ * \param iv       The initialization vector (updated after use).
+ * \param input    The buffer holding the input data.
+ * \param output   The buffer holding the output data.
+ *
+ * \return         \c 0 on success.
+ */
+int mbedcrypto_aes_crypt_cfb8( mbedcrypto_aes_context *ctx,
+                    int mode,
+                    size_t length,
+                    unsigned char iv[16],
+                    const unsigned char *input,
+                    unsigned char *output );
+#endif /*MBEDCRYPTO_CIPHER_MODE_CFB */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+/**
+ * \brief      This function performs an AES-CTR encryption or decryption
+ *             operation.
+ *
+ *             This function performs the operation defined in the \p mode
+ *             parameter (encrypt/decrypt), on the input data buffer
+ *             defined in the \p input parameter.
+ *
+ *             Due to the nature of CTR, you must use the same key schedule
+ *             for both encryption and decryption operations. Therefore, you
+ *             must use the context initialized with mbedcrypto_aes_setkey_enc()
+ *             for both #MBEDCRYPTO_AES_ENCRYPT and #MBEDCRYPTO_AES_DECRYPT.
+ *
+ * \warning    You must keep the maximum use of your counter in mind.
+ *
+ * \param ctx              The AES context to use for encryption or decryption.
+ * \param length           The length of the input data.
+ * \param nc_off           The offset in the current \p stream_block, for
+ *                         resuming within the current cipher stream. The
+ *                         offset pointer should be 0 at the start of a stream.
+ * \param nonce_counter    The 128-bit nonce and counter.
+ * \param stream_block     The saved stream block for resuming. This is
+ *                         overwritten by the function.
+ * \param input            The buffer holding the input data.
+ * \param output           The buffer holding the output data.
+ *
+ * \return                 \c 0 on success.
+ */
+int mbedcrypto_aes_crypt_ctr( mbedcrypto_aes_context *ctx,
+                       size_t length,
+                       size_t *nc_off,
+                       unsigned char nonce_counter[16],
+                       unsigned char stream_block[16],
+                       const unsigned char *input,
+                       unsigned char *output );
+#endif /* MBEDCRYPTO_CIPHER_MODE_CTR */
+
+/**
+ * \brief           Internal AES block encryption function. This is only
+ *                  exposed to allow overriding it using
+ *                  \c MBEDCRYPTO_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.
+ */
+int mbedcrypto_internal_aes_encrypt( mbedcrypto_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 MBEDCRYPTO_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.
+ */
+int mbedcrypto_internal_aes_decrypt( mbedcrypto_aes_context *ctx,
+                                  const unsigned char input[16],
+                                  unsigned char output[16] );
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING)
+#define MBEDCRYPTO_DEPRECATED      __attribute__((deprecated))
+#else
+#define MBEDCRYPTO_DEPRECATED
+#endif
+/**
+ * \brief           Deprecated internal AES block encryption function
+ *                  without return value.
+ *
+ * \deprecated      Superseded by mbedcrypto_aes_encrypt_ext() in 2.5.0.
+ *
+ * \param ctx       The AES context to use for encryption.
+ * \param input     Plaintext block.
+ * \param output    Output (ciphertext) block.
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_aes_encrypt( mbedcrypto_aes_context *ctx,
+                                             const unsigned char input[16],
+                                             unsigned char output[16] );
+
+/**
+ * \brief           Deprecated internal AES block decryption function
+ *                  without return value.
+ *
+ * \deprecated      Superseded by mbedcrypto_aes_decrypt_ext() in 2.5.0.
+ *
+ * \param ctx       The AES context to use for decryption.
+ * \param input     Ciphertext block.
+ * \param output    Output (plaintext) block.
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_aes_decrypt( mbedcrypto_aes_context *ctx,
+                                             const unsigned char input[16],
+                                             unsigned char output[16] );
+
+#undef MBEDCRYPTO_DEPRECATED
+#endif /* !MBEDCRYPTO_DEPRECATED_REMOVED */
+
+/**
+ * \brief          Checkup routine.
+ *
+ * \return         \c 0 on success.
+ * \return         \c 1 on failure.
+ */
+int mbedcrypto_aes_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* aes.h */
diff --git a/include/mbedcrypto/aesni.h b/include/mbedcrypto/aesni.h
new file mode 100644
index 0000000..c68e360
--- /dev/null
+++ b/include/mbedcrypto/aesni.h
@@ -0,0 +1,112 @@
+/**
+ * \file aesni.h
+ *
+ * \brief AES-NI for hardware AES acceleration on some Intel processors
+ */
+/*
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_AESNI_H
+#define MBEDCRYPTO_AESNI_H
+
+#include "aes.h"
+
+#define MBEDCRYPTO_AESNI_AES      0x02000000u
+#define MBEDCRYPTO_AESNI_CLMUL    0x00000002u
+
+#if defined(MBEDCRYPTO_HAVE_ASM) && defined(__GNUC__) &&  \
+    ( defined(__amd64__) || defined(__x86_64__) )   &&  \
+    ! defined(MBEDCRYPTO_HAVE_X86_64)
+#define MBEDCRYPTO_HAVE_X86_64
+#endif
+
+#if defined(MBEDCRYPTO_HAVE_X86_64)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          AES-NI features detection routine
+ *
+ * \param what     The feature to detect
+ *                 (MBEDCRYPTO_AESNI_AES or MBEDCRYPTO_AESNI_CLMUL)
+ *
+ * \return         1 if CPU has support for the feature, 0 otherwise
+ */
+int mbedcrypto_aesni_has_support( unsigned int what );
+
+/**
+ * \brief          AES-NI AES-ECB block en(de)cryption
+ *
+ * \param ctx      AES context
+ * \param mode     MBEDCRYPTO_AES_ENCRYPT or MBEDCRYPTO_AES_DECRYPT
+ * \param input    16-byte input block
+ * \param output   16-byte output block
+ *
+ * \return         0 on success (cannot fail)
+ */
+int mbedcrypto_aesni_crypt_ecb( mbedcrypto_aes_context *ctx,
+                     int mode,
+                     const unsigned char input[16],
+                     unsigned char output[16] );
+
+/**
+ * \brief          GCM multiplication: c = a * b in GF(2^128)
+ *
+ * \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 mbedcrypto_aesni_gcm_mult( unsigned char c[16],
+                     const unsigned char a[16],
+                     const unsigned char b[16] );
+
+/**
+ * \brief           Compute decryption round keys from encryption round keys
+ *
+ * \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 mbedcrypto_aesni_inverse_key( unsigned char *invkey,
+                        const unsigned char *fwdkey, int nr );
+
+/**
+ * \brief           Perform key expansion (for encryption)
+ *
+ * \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 MBEDCRYPTO_ERR_AES_INVALID_KEY_LENGTH
+ */
+int mbedcrypto_aesni_setkey_enc( unsigned char *rk,
+                      const unsigned char *key,
+                      size_t bits );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDCRYPTO_HAVE_X86_64 */
+
+#endif /* MBEDCRYPTO_AESNI_H */
diff --git a/include/mbedcrypto/arc4.h b/include/mbedcrypto/arc4.h
new file mode 100644
index 0000000..32c3abb
--- /dev/null
+++ b/include/mbedcrypto/arc4.h
@@ -0,0 +1,141 @@
+/**
+ * \file arc4.h
+ *
+ * \brief The ARCFOUR stream cipher
+ *
+ * \warning   ARC4 is considered a weak cipher and its use constitutes a
+ *            security risk. We recommend considering stronger ciphers instead.
+ */
+/*
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ *
+ */
+#ifndef MBEDCRYPTO_ARC4_H
+#define MBEDCRYPTO_ARC4_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+
+#define MBEDCRYPTO_ERR_ARC4_HW_ACCEL_FAILED                  -0x0019  /**< ARC4 hardware accelerator failed. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDCRYPTO_ARC4_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief     ARC4 context structure
+ *
+ * \warning   ARC4 is considered a weak cipher and its use constitutes a
+ *            security risk. We recommend considering stronger ciphers instead.
+ *
+ */
+typedef struct
+{
+    int x;                      /*!< permutation index */
+    int y;                      /*!< permutation index */
+    unsigned char m[256];       /*!< permutation table */
+}
+mbedcrypto_arc4_context;
+
+#else  /* MBEDCRYPTO_ARC4_ALT */
+#include "arc4_alt.h"
+#endif /* MBEDCRYPTO_ARC4_ALT */
+
+/**
+ * \brief          Initialize ARC4 context
+ *
+ * \param ctx      ARC4 context to be initialized
+ *
+ * \warning        ARC4 is considered a weak cipher and its use constitutes a
+ *                 security risk. We recommend considering stronger ciphers
+ *                 instead.
+ *
+ */
+void mbedcrypto_arc4_init( mbedcrypto_arc4_context *ctx );
+
+/**
+ * \brief          Clear ARC4 context
+ *
+ * \param ctx      ARC4 context to be cleared
+ *
+ * \warning        ARC4 is considered a weak cipher and its use constitutes a
+ *                 security risk. We recommend considering stronger ciphers
+ *                 instead.
+ *
+ */
+void mbedcrypto_arc4_free( mbedcrypto_arc4_context *ctx );
+
+/**
+ * \brief          ARC4 key schedule
+ *
+ * \param ctx      ARC4 context to be setup
+ * \param key      the secret key
+ * \param keylen   length of the key, in bytes
+ *
+ * \warning        ARC4 is considered a weak cipher and its use constitutes a
+ *                 security risk. We recommend considering stronger ciphers
+ *                 instead.
+ *
+ */
+void mbedcrypto_arc4_setup( mbedcrypto_arc4_context *ctx, const unsigned char *key,
+                 unsigned int keylen );
+
+/**
+ * \brief          ARC4 cipher function
+ *
+ * \param ctx      ARC4 context
+ * \param length   length of the input data
+ * \param input    buffer holding the input data
+ * \param output   buffer for the output data
+ *
+ * \return         0 if successful
+ *
+ * \warning        ARC4 is considered a weak cipher and its use constitutes a
+ *                 security risk. We recommend considering stronger ciphers
+ *                 instead.
+ *
+ */
+int mbedcrypto_arc4_crypt( mbedcrypto_arc4_context *ctx, size_t length, const unsigned char *input,
+                unsigned char *output );
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ *
+ * \warning        ARC4 is considered a weak cipher and its use constitutes a
+ *                 security risk. We recommend considering stronger ciphers
+ *                 instead.
+ *
+ */
+int mbedcrypto_arc4_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* arc4.h */
diff --git a/include/mbedcrypto/asn1.h b/include/mbedcrypto/asn1.h
new file mode 100644
index 0000000..d815c4d
--- /dev/null
+++ b/include/mbedcrypto/asn1.h
@@ -0,0 +1,358 @@
+/**
+ * \file asn1.h
+ *
+ * \brief Generic ASN.1 parsing
+ */
+/*
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_ASN1_H
+#define MBEDCRYPTO_ASN1_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+
+#if defined(MBEDCRYPTO_BIGNUM_C)
+#include "bignum.h"
+#endif
+
+/**
+ * \addtogroup asn1_module
+ * \{
+ */
+
+/**
+ * \name ASN1 Error codes
+ * These error codes are OR'ed to X509 error codes for
+ * higher error granularity.
+ * ASN1 is a standard to specify data structures.
+ * \{
+ */
+#define MBEDCRYPTO_ERR_ASN1_OUT_OF_DATA                      -0x0060  /**< Out of data when parsing an ASN1 data structure. */
+#define MBEDCRYPTO_ERR_ASN1_UNEXPECTED_TAG                   -0x0062  /**< ASN1 tag was of an unexpected value. */
+#define MBEDCRYPTO_ERR_ASN1_INVALID_LENGTH                   -0x0064  /**< Error when trying to determine the length or invalid length. */
+#define MBEDCRYPTO_ERR_ASN1_LENGTH_MISMATCH                  -0x0066  /**< Actual length differs from expected length. */
+#define MBEDCRYPTO_ERR_ASN1_INVALID_DATA                     -0x0068  /**< Data is invalid. (not used) */
+#define MBEDCRYPTO_ERR_ASN1_ALLOC_FAILED                     -0x006A  /**< Memory allocation failed */
+#define MBEDCRYPTO_ERR_ASN1_BUF_TOO_SMALL                    -0x006C  /**< Buffer too small when writing ASN.1 data structure. */
+
+/* \} name */
+
+/**
+ * \name DER constants
+ * These constants comply with the DER encoded ASN.1 type tags.
+ * DER encoding uses hexadecimal representation.
+ * An example DER sequence is:\n
+ * - 0x02 -- tag indicating INTEGER
+ * - 0x01 -- length in octets
+ * - 0x05 -- value
+ * Such sequences are typically read into \c ::mbedcrypto_x509_buf.
+ * \{
+ */
+#define MBEDCRYPTO_ASN1_BOOLEAN                 0x01
+#define MBEDCRYPTO_ASN1_INTEGER                 0x02
+#define MBEDCRYPTO_ASN1_BIT_STRING              0x03
+#define MBEDCRYPTO_ASN1_OCTET_STRING            0x04
+#define MBEDCRYPTO_ASN1_NULL                    0x05
+#define MBEDCRYPTO_ASN1_OID                     0x06
+#define MBEDCRYPTO_ASN1_UTF8_STRING             0x0C
+#define MBEDCRYPTO_ASN1_SEQUENCE                0x10
+#define MBEDCRYPTO_ASN1_SET                     0x11
+#define MBEDCRYPTO_ASN1_PRINTABLE_STRING        0x13
+#define MBEDCRYPTO_ASN1_T61_STRING              0x14
+#define MBEDCRYPTO_ASN1_IA5_STRING              0x16
+#define MBEDCRYPTO_ASN1_UTC_TIME                0x17
+#define MBEDCRYPTO_ASN1_GENERALIZED_TIME        0x18
+#define MBEDCRYPTO_ASN1_UNIVERSAL_STRING        0x1C
+#define MBEDCRYPTO_ASN1_BMP_STRING              0x1E
+#define MBEDCRYPTO_ASN1_PRIMITIVE               0x00
+#define MBEDCRYPTO_ASN1_CONSTRUCTED             0x20
+#define MBEDCRYPTO_ASN1_CONTEXT_SPECIFIC        0x80
+
+/*
+ * Bit masks for each of the components of an ASN.1 tag as specified in
+ * ITU X.690 (08/2015), section 8.1 "General rules for encoding",
+ * paragraph 8.1.2.2:
+ *
+ * Bit  8     7   6   5          1
+ *     +-------+-----+------------+
+ *     | Class | P/C | Tag number |
+ *     +-------+-----+------------+
+ */
+#define MBEDCRYPTO_ASN1_TAG_CLASS_MASK          0xC0
+#define MBEDCRYPTO_ASN1_TAG_PC_MASK             0x20
+#define MBEDCRYPTO_ASN1_TAG_VALUE_MASK          0x1F
+
+/* \} name */
+/* \} addtogroup asn1_module */
+
+/** Returns the size of the binary string, without the trailing \\0 */
+#define MBEDCRYPTO_OID_SIZE(x) (sizeof(x) - 1)
+
+/**
+ * Compares an mbedcrypto_asn1_buf structure to a reference OID.
+ *
+ * Only works for 'defined' oid_str values (MBEDCRYPTO_OID_HMAC_SHA1), you cannot use a
+ * 'unsigned char *oid' here!
+ */
+#define MBEDCRYPTO_OID_CMP(oid_str, oid_buf)                                   \
+        ( ( MBEDCRYPTO_OID_SIZE(oid_str) != (oid_buf)->len ) ||                \
+          memcmp( (oid_str), (oid_buf)->p, (oid_buf)->len) != 0 )
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \name Functions to parse ASN.1 data structures
+ * \{
+ */
+
+/**
+ * Type-length-value structure that allows for ASN1 using DER.
+ */
+typedef struct mbedcrypto_asn1_buf
+{
+    int tag;                /**< ASN1 type, e.g. MBEDCRYPTO_ASN1_UTF8_STRING. */
+    size_t len;             /**< ASN1 length, in octets. */
+    unsigned char *p;       /**< ASN1 data, e.g. in ASCII. */
+}
+mbedcrypto_asn1_buf;
+
+/**
+ * Container for ASN1 bit strings.
+ */
+typedef struct mbedcrypto_asn1_bitstring
+{
+    size_t len;                 /**< ASN1 length, in octets. */
+    unsigned char unused_bits;  /**< Number of unused bits at the end of the string */
+    unsigned char *p;           /**< Raw ASN1 data for the bit string */
+}
+mbedcrypto_asn1_bitstring;
+
+/**
+ * Container for a sequence of ASN.1 items
+ */
+typedef struct mbedcrypto_asn1_sequence
+{
+    mbedcrypto_asn1_buf buf;                   /**< Buffer containing the given ASN.1 item. */
+    struct mbedcrypto_asn1_sequence *next;    /**< The next entry in the sequence. */
+}
+mbedcrypto_asn1_sequence;
+
+/**
+ * Container for a sequence or list of 'named' ASN.1 data items
+ */
+typedef struct mbedcrypto_asn1_named_data
+{
+    mbedcrypto_asn1_buf oid;                   /**< The object identifier. */
+    mbedcrypto_asn1_buf val;                   /**< The named value. */
+    struct mbedcrypto_asn1_named_data *next;  /**< The next entry in the sequence. */
+    unsigned char next_merged;      /**< Merge next item into the current one? */
+}
+mbedcrypto_asn1_named_data;
+
+/**
+ * \brief       Get the length of an ASN.1 element.
+ *              Updates the pointer to immediately behind the length.
+ *
+ * \param p     The position in the ASN.1 data
+ * \param end   End of data
+ * \param len   The variable that will receive the value
+ *
+ * \return      0 if successful, MBEDCRYPTO_ERR_ASN1_OUT_OF_DATA on reaching
+ *              end of data, MBEDCRYPTO_ERR_ASN1_INVALID_LENGTH if length is
+ *              unparseable.
+ */
+int mbedcrypto_asn1_get_len( unsigned char **p,
+                  const unsigned char *end,
+                  size_t *len );
+
+/**
+ * \brief       Get the tag and length of the tag. Check for the requested tag.
+ *              Updates the pointer to immediately behind the tag and length.
+ *
+ * \param p     The position in the ASN.1 data
+ * \param end   End of data
+ * \param len   The variable that will receive the length
+ * \param tag   The expected tag
+ *
+ * \return      0 if successful, MBEDCRYPTO_ERR_ASN1_UNEXPECTED_TAG if tag did
+ *              not match requested tag, or another specific ASN.1 error code.
+ */
+int mbedcrypto_asn1_get_tag( unsigned char **p,
+                  const unsigned char *end,
+                  size_t *len, int tag );
+
+/**
+ * \brief       Retrieve a boolean ASN.1 tag and its value.
+ *              Updates the pointer to immediately behind the full tag.
+ *
+ * \param p     The position in the ASN.1 data
+ * \param end   End of data
+ * \param val   The variable that will receive the value
+ *
+ * \return      0 if successful or a specific ASN.1 error code.
+ */
+int mbedcrypto_asn1_get_bool( unsigned char **p,
+                   const unsigned char *end,
+                   int *val );
+
+/**
+ * \brief       Retrieve an integer ASN.1 tag and its value.
+ *              Updates the pointer to immediately behind the full tag.
+ *
+ * \param p     The position in the ASN.1 data
+ * \param end   End of data
+ * \param val   The variable that will receive the value
+ *
+ * \return      0 if successful or a specific ASN.1 error code.
+ */
+int mbedcrypto_asn1_get_int( unsigned char **p,
+                  const unsigned char *end,
+                  int *val );
+
+/**
+ * \brief       Retrieve a bitstring ASN.1 tag and its value.
+ *              Updates the pointer to immediately behind the full tag.
+ *
+ * \param p     The position in the ASN.1 data
+ * \param end   End of data
+ * \param bs    The variable that will receive the value
+ *
+ * \return      0 if successful or a specific ASN.1 error code.
+ */
+int mbedcrypto_asn1_get_bitstring( unsigned char **p, const unsigned char *end,
+                        mbedcrypto_asn1_bitstring *bs);
+
+/**
+ * \brief       Retrieve a bitstring ASN.1 tag without unused bits and its
+ *              value.
+ *              Updates the pointer to the beginning of the bit/octet string.
+ *
+ * \param p     The position in the ASN.1 data
+ * \param end   End of data
+ * \param len   Length of the actual bit/octect string in bytes
+ *
+ * \return      0 if successful or a specific ASN.1 error code.
+ */
+int mbedcrypto_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end,
+                             size_t *len );
+
+/**
+ * \brief       Parses and splits an ASN.1 "SEQUENCE OF <tag>"
+ *              Updated the pointer to immediately behind the full sequence tag.
+ *
+ * \param p     The position in the ASN.1 data
+ * \param end   End of data
+ * \param cur   First variable in the chain to fill
+ * \param tag   Type of sequence
+ *
+ * \return      0 if successful or a specific ASN.1 error code.
+ */
+int mbedcrypto_asn1_get_sequence_of( unsigned char **p,
+                          const unsigned char *end,
+                          mbedcrypto_asn1_sequence *cur,
+                          int tag);
+
+#if defined(MBEDCRYPTO_BIGNUM_C)
+/**
+ * \brief       Retrieve a MPI value from an integer ASN.1 tag.
+ *              Updates the pointer to immediately behind the full tag.
+ *
+ * \param p     The position in the ASN.1 data
+ * \param end   End of data
+ * \param X     The MPI that will receive the value
+ *
+ * \return      0 if successful or a specific ASN.1 or MPI error code.
+ */
+int mbedcrypto_asn1_get_mpi( unsigned char **p,
+                  const unsigned char *end,
+                  mbedcrypto_mpi *X );
+#endif /* MBEDCRYPTO_BIGNUM_C */
+
+/**
+ * \brief       Retrieve an AlgorithmIdentifier ASN.1 sequence.
+ *              Updates the pointer to immediately behind the full
+ *              AlgorithmIdentifier.
+ *
+ * \param p     The position in the ASN.1 data
+ * \param end   End of data
+ * \param alg   The buffer to receive the OID
+ * \param params The buffer to receive the params (if any)
+ *
+ * \return      0 if successful or a specific ASN.1 or MPI error code.
+ */
+int mbedcrypto_asn1_get_alg( unsigned char **p,
+                  const unsigned char *end,
+                  mbedcrypto_asn1_buf *alg, mbedcrypto_asn1_buf *params );
+
+/**
+ * \brief       Retrieve an AlgorithmIdentifier ASN.1 sequence with NULL or no
+ *              params.
+ *              Updates the pointer to immediately behind the full
+ *              AlgorithmIdentifier.
+ *
+ * \param p     The position in the ASN.1 data
+ * \param end   End of data
+ * \param alg   The buffer to receive the OID
+ *
+ * \return      0 if successful or a specific ASN.1 or MPI error code.
+ */
+int mbedcrypto_asn1_get_alg_null( unsigned char **p,
+                       const unsigned char *end,
+                       mbedcrypto_asn1_buf *alg );
+
+/**
+ * \brief       Find a specific named_data entry in a sequence or list based on
+ *              the OID.
+ *
+ * \param list  The list to seek through
+ * \param oid   The OID to look for
+ * \param len   Size of the OID
+ *
+ * \return      NULL if not found, or a pointer to the existing entry.
+ */
+mbedcrypto_asn1_named_data *mbedcrypto_asn1_find_named_data( mbedcrypto_asn1_named_data *list,
+                                       const char *oid, size_t len );
+
+/**
+ * \brief       Free a mbedcrypto_asn1_named_data entry
+ *
+ * \param entry The named data entry to free
+ */
+void mbedcrypto_asn1_free_named_data( mbedcrypto_asn1_named_data *entry );
+
+/**
+ * \brief       Free all entries in a mbedcrypto_asn1_named_data list
+ *              Head will be set to NULL
+ *
+ * \param head  Pointer to the head of the list of named data entries to free
+ */
+void mbedcrypto_asn1_free_named_data_list( mbedcrypto_asn1_named_data **head );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* asn1.h */
diff --git a/include/mbedcrypto/asn1write.h b/include/mbedcrypto/asn1write.h
new file mode 100644
index 0000000..cc134ce
--- /dev/null
+++ b/include/mbedcrypto/asn1write.h
@@ -0,0 +1,240 @@
+/**
+ * \file asn1write.h
+ *
+ * \brief ASN.1 buffer writing functionality
+ */
+/*
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_ASN1_WRITE_H
+#define MBEDCRYPTO_ASN1_WRITE_H
+
+#include "asn1.h"
+
+#define MBEDCRYPTO_ASN1_CHK_ADD(g, f) do { if( ( ret = f ) < 0 ) return( ret ); else   \
+                                g += ret; } while( 0 )
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief           Write a length field in ASN.1 format
+ *                  Note: function works backwards in data buffer
+ *
+ * \param p         reference to current position pointer
+ * \param start     start of the buffer (for bounds-checking)
+ * \param len       the length to write
+ *
+ * \return          the length written or a negative error code
+ */
+int mbedcrypto_asn1_write_len( unsigned char **p, unsigned char *start, size_t len );
+
+/**
+ * \brief           Write a ASN.1 tag in ASN.1 format
+ *                  Note: function works backwards in data buffer
+ *
+ * \param p         reference to current position pointer
+ * \param start     start of the buffer (for bounds-checking)
+ * \param tag       the tag to write
+ *
+ * \return          the length written or a negative error code
+ */
+int mbedcrypto_asn1_write_tag( unsigned char **p, unsigned char *start,
+                    unsigned char tag );
+
+/**
+ * \brief           Write raw buffer data
+ *                  Note: function works backwards in data buffer
+ *
+ * \param p         reference to current position pointer
+ * \param start     start of the buffer (for bounds-checking)
+ * \param buf       data buffer to write
+ * \param size      length of the data buffer
+ *
+ * \return          the length written or a negative error code
+ */
+int mbedcrypto_asn1_write_raw_buffer( unsigned char **p, unsigned char *start,
+                           const unsigned char *buf, size_t size );
+
+#if defined(MBEDCRYPTO_BIGNUM_C)
+/**
+ * \brief           Write a big number (MBEDCRYPTO_ASN1_INTEGER) in ASN.1 format
+ *                  Note: function works backwards in data buffer
+ *
+ * \param p         reference to current position pointer
+ * \param start     start of the buffer (for bounds-checking)
+ * \param X         the MPI to write
+ *
+ * \return          the length written or a negative error code
+ */
+int mbedcrypto_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedcrypto_mpi *X );
+#endif /* MBEDCRYPTO_BIGNUM_C */
+
+/**
+ * \brief           Write a NULL tag (MBEDCRYPTO_ASN1_NULL) with zero data in ASN.1 format
+ *                  Note: function works backwards in data buffer
+ *
+ * \param p         reference to current position pointer
+ * \param start     start of the buffer (for bounds-checking)
+ *
+ * \return          the length written or a negative error code
+ */
+int mbedcrypto_asn1_write_null( unsigned char **p, unsigned char *start );
+
+/**
+ * \brief           Write an OID tag (MBEDCRYPTO_ASN1_OID) and data in ASN.1 format
+ *                  Note: function works backwards in data buffer
+ *
+ * \param p         reference to current position pointer
+ * \param start     start of the buffer (for bounds-checking)
+ * \param oid       the OID to write
+ * \param oid_len   length of the OID
+ *
+ * \return          the length written or a negative error code
+ */
+int mbedcrypto_asn1_write_oid( unsigned char **p, unsigned char *start,
+                    const char *oid, size_t oid_len );
+
+/**
+ * \brief           Write an AlgorithmIdentifier sequence in ASN.1 format
+ *                  Note: function works backwards in data buffer
+ *
+ * \param p         reference to current position pointer
+ * \param start     start of the buffer (for bounds-checking)
+ * \param oid       the OID of the algorithm
+ * \param oid_len   length of the OID
+ * \param par_len   length of parameters, which must be already written.
+ *                  If 0, NULL parameters are added
+ *
+ * \return          the length written or a negative error code
+ */
+int mbedcrypto_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start,
+                                     const char *oid, size_t oid_len,
+                                     size_t par_len );
+
+/**
+ * \brief           Write a boolean tag (MBEDCRYPTO_ASN1_BOOLEAN) and value in ASN.1 format
+ *                  Note: function works backwards in data buffer
+ *
+ * \param p         reference to current position pointer
+ * \param start     start of the buffer (for bounds-checking)
+ * \param boolean   0 or 1
+ *
+ * \return          the length written or a negative error code
+ */
+int mbedcrypto_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean );
+
+/**
+ * \brief           Write an int tag (MBEDCRYPTO_ASN1_INTEGER) and value in ASN.1 format
+ *                  Note: function works backwards in data buffer
+ *
+ * \param p         reference to current position pointer
+ * \param start     start of the buffer (for bounds-checking)
+ * \param val       the integer value
+ *
+ * \return          the length written or a negative error code
+ */
+int mbedcrypto_asn1_write_int( unsigned char **p, unsigned char *start, int val );
+
+/**
+ * \brief           Write a printable string tag (MBEDCRYPTO_ASN1_PRINTABLE_STRING) and
+ *                  value in ASN.1 format
+ *                  Note: function works backwards in data buffer
+ *
+ * \param p         reference to current position pointer
+ * \param start     start of the buffer (for bounds-checking)
+ * \param text      the text to write
+ * \param text_len  length of the text
+ *
+ * \return          the length written or a negative error code
+ */
+int mbedcrypto_asn1_write_printable_string( unsigned char **p, unsigned char *start,
+                                 const char *text, size_t text_len );
+
+/**
+ * \brief           Write an IA5 string tag (MBEDCRYPTO_ASN1_IA5_STRING) and
+ *                  value in ASN.1 format
+ *                  Note: function works backwards in data buffer
+ *
+ * \param p         reference to current position pointer
+ * \param start     start of the buffer (for bounds-checking)
+ * \param text      the text to write
+ * \param text_len  length of the text
+ *
+ * \return          the length written or a negative error code
+ */
+int mbedcrypto_asn1_write_ia5_string( unsigned char **p, unsigned char *start,
+                           const char *text, size_t text_len );
+
+/**
+ * \brief           Write a bitstring tag (MBEDCRYPTO_ASN1_BIT_STRING) and
+ *                  value in ASN.1 format
+ *                  Note: function works backwards in data buffer
+ *
+ * \param p         reference to current position pointer
+ * \param start     start of the buffer (for bounds-checking)
+ * \param buf       the bitstring
+ * \param bits      the total number of bits in the bitstring
+ *
+ * \return          the length written or a negative error code
+ */
+int mbedcrypto_asn1_write_bitstring( unsigned char **p, unsigned char *start,
+                          const unsigned char *buf, size_t bits );
+
+/**
+ * \brief           Write an octet string tag (MBEDCRYPTO_ASN1_OCTET_STRING) and
+ *                  value in ASN.1 format
+ *                  Note: function works backwards in data buffer
+ *
+ * \param p         reference to current position pointer
+ * \param start     start of the buffer (for bounds-checking)
+ * \param buf       data buffer to write
+ * \param size      length of the data buffer
+ *
+ * \return          the length written or a negative error code
+ */
+int mbedcrypto_asn1_write_octet_string( unsigned char **p, unsigned char *start,
+                             const unsigned char *buf, size_t size );
+
+/**
+ * \brief           Create or find a specific named_data entry for writing in a
+ *                  sequence or list based on the OID. If not already in there,
+ *                  a new entry is added to the head of the list.
+ *                  Warning: Destructive behaviour for the val data!
+ *
+ * \param list      Pointer to the location of the head of the list to seek
+ *                  through (will be updated in case of a new entry)
+ * \param oid       The OID to look for
+ * \param oid_len   Size of the OID
+ * \param val       Data to store (can be NULL if you want to fill it by hand)
+ * \param val_len   Minimum length of the data buffer needed
+ *
+ * \return      NULL if if there was a memory allocation error, or a pointer
+ *              to the new / existing entry.
+ */
+mbedcrypto_asn1_named_data *mbedcrypto_asn1_store_named_data( mbedcrypto_asn1_named_data **list,
+                                        const char *oid, size_t oid_len,
+                                        const unsigned char *val,
+                                        size_t val_len );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDCRYPTO_ASN1_WRITE_H */
diff --git a/include/mbedcrypto/base64.h b/include/mbedcrypto/base64.h
new file mode 100644
index 0000000..21b4622
--- /dev/null
+++ b/include/mbedcrypto/base64.h
@@ -0,0 +1,89 @@
+/**
+ * \file base64.h
+ *
+ * \brief RFC 1521 base64 encoding/decoding
+ */
+/*
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_BASE64_H
+#define MBEDCRYPTO_BASE64_H
+
+#include <stddef.h>
+
+#define MBEDCRYPTO_ERR_BASE64_BUFFER_TOO_SMALL               -0x002A  /**< Output buffer too small. */
+#define MBEDCRYPTO_ERR_BASE64_INVALID_CHARACTER              -0x002C  /**< Invalid character in input. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          Encode a buffer into base64 format
+ *
+ * \param dst      destination buffer
+ * \param dlen     size of the destination buffer
+ * \param olen     number of bytes written
+ * \param src      source buffer
+ * \param slen     amount of data to be encoded
+ *
+ * \return         0 if successful, or MBEDCRYPTO_ERR_BASE64_BUFFER_TOO_SMALL.
+ *                 *olen is always updated to reflect the amount
+ *                 of data that has (or would have) been written.
+ *                 If that length cannot be represented, then no data is
+ *                 written to the buffer and *olen is set to the maximum
+ *                 length representable as a size_t.
+ *
+ * \note           Call this function with dlen = 0 to obtain the
+ *                 required buffer size in *olen
+ */
+int mbedcrypto_base64_encode( unsigned char *dst, size_t dlen, size_t *olen,
+                   const unsigned char *src, size_t slen );
+
+/**
+ * \brief          Decode a base64-formatted buffer
+ *
+ * \param dst      destination buffer (can be NULL for checking size)
+ * \param dlen     size of the destination buffer
+ * \param olen     number of bytes written
+ * \param src      source buffer
+ * \param slen     amount of data to be decoded
+ *
+ * \return         0 if successful, MBEDCRYPTO_ERR_BASE64_BUFFER_TOO_SMALL, or
+ *                 MBEDCRYPTO_ERR_BASE64_INVALID_CHARACTER if the input data is
+ *                 not correct. *olen is always updated to reflect the amount
+ *                 of data that has (or would have) been written.
+ *
+ * \note           Call this function with *dst = NULL or dlen = 0 to obtain
+ *                 the required buffer size in *olen
+ */
+int mbedcrypto_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
+                   const unsigned char *src, size_t slen );
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int mbedcrypto_base64_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* base64.h */
diff --git a/include/mbedcrypto/bignum.h b/include/mbedcrypto/bignum.h
new file mode 100644
index 0000000..ad989bb
--- /dev/null
+++ b/include/mbedcrypto/bignum.h
@@ -0,0 +1,772 @@
+/**
+ * \file bignum.h
+ *
+ * \brief Multi-precision integer library
+ */
+/*
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_BIGNUM_H
+#define MBEDCRYPTO_BIGNUM_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+#if defined(MBEDCRYPTO_FS_IO)
+#include <stdio.h>
+#endif
+
+#define MBEDCRYPTO_ERR_MPI_FILE_IO_ERROR                     -0x0002  /**< An error occurred while reading from or writing to a file. */
+#define MBEDCRYPTO_ERR_MPI_BAD_INPUT_DATA                    -0x0004  /**< Bad input parameters to function. */
+#define MBEDCRYPTO_ERR_MPI_INVALID_CHARACTER                 -0x0006  /**< There is an invalid character in the digit string. */
+#define MBEDCRYPTO_ERR_MPI_BUFFER_TOO_SMALL                  -0x0008  /**< The buffer is too small to write to. */
+#define MBEDCRYPTO_ERR_MPI_NEGATIVE_VALUE                    -0x000A  /**< The input arguments are negative or result in illegal output. */
+#define MBEDCRYPTO_ERR_MPI_DIVISION_BY_ZERO                  -0x000C  /**< The input argument for division is zero, which is not allowed. */
+#define MBEDCRYPTO_ERR_MPI_NOT_ACCEPTABLE                    -0x000E  /**< The input arguments are not acceptable. */
+#define MBEDCRYPTO_ERR_MPI_ALLOC_FAILED                      -0x0010  /**< Memory allocation failed. */
+
+#define MBEDCRYPTO_MPI_CHK(f) do { if( ( ret = f ) != 0 ) goto cleanup; } while( 0 )
+
+/*
+ * Maximum size MPIs are allowed to grow to in number of limbs.
+ */
+#define MBEDCRYPTO_MPI_MAX_LIMBS                             10000
+
+#if !defined(MBEDCRYPTO_MPI_WINDOW_SIZE)
+/*
+ * Maximum window size used for modular exponentiation. Default: 6
+ * Minimum value: 1. Maximum value: 6.
+ *
+ * Result is an array of ( 2 << MBEDCRYPTO_MPI_WINDOW_SIZE ) MPIs used
+ * for the sliding window calculation. (So 64 by default)
+ *
+ * Reduction in size, reduces speed.
+ */
+#define MBEDCRYPTO_MPI_WINDOW_SIZE                           6        /**< Maximum windows size used. */
+#endif /* !MBEDCRYPTO_MPI_WINDOW_SIZE */
+
+#if !defined(MBEDCRYPTO_MPI_MAX_SIZE)
+/*
+ * Maximum size of MPIs allowed in bits and bytes for user-MPIs.
+ * ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits )
+ *
+ * Note: Calculations can temporarily result in larger MPIs. So the number
+ * of limbs required (MBEDCRYPTO_MPI_MAX_LIMBS) is higher.
+ */
+#define MBEDCRYPTO_MPI_MAX_SIZE                              1024     /**< Maximum number of bytes for usable MPIs. */
+#endif /* !MBEDCRYPTO_MPI_MAX_SIZE */
+
+#define MBEDCRYPTO_MPI_MAX_BITS                              ( 8 * MBEDCRYPTO_MPI_MAX_SIZE )    /**< Maximum number of bits for usable MPIs. */
+
+/*
+ * When reading from files with mbedcrypto_mpi_read_file() and writing to files with
+ * mbedcrypto_mpi_write_file() the buffer should have space
+ * for a (short) label, the MPI (in the provided radix), the newline
+ * characters and the '\0'.
+ *
+ * By default we assume at least a 10 char label, a minimum radix of 10
+ * (decimal) and a maximum of 4096 bit numbers (1234 decimal chars).
+ * Autosized at compile time for at least a 10 char label, a minimum radix
+ * of 10 (decimal) for a number of MBEDCRYPTO_MPI_MAX_BITS size.
+ *
+ * This used to be statically sized to 1250 for a maximum of 4096 bit
+ * numbers (1234 decimal chars).
+ *
+ * Calculate using the formula:
+ *  MBEDCRYPTO_MPI_RW_BUFFER_SIZE = ceil(MBEDCRYPTO_MPI_MAX_BITS / ln(10) * ln(2)) +
+ *                                LabelSize + 6
+ */
+#define MBEDCRYPTO_MPI_MAX_BITS_SCALE100          ( 100 * MBEDCRYPTO_MPI_MAX_BITS )
+#define MBEDCRYPTO_LN_2_DIV_LN_10_SCALE100                 332
+#define MBEDCRYPTO_MPI_RW_BUFFER_SIZE             ( ((MBEDCRYPTO_MPI_MAX_BITS_SCALE100 + MBEDCRYPTO_LN_2_DIV_LN_10_SCALE100 - 1) / MBEDCRYPTO_LN_2_DIV_LN_10_SCALE100) + 10 + 6 )
+
+/*
+ * Define the base integer type, architecture-wise.
+ *
+ * 32 or 64-bit integer types can be forced regardless of the underlying
+ * architecture by defining MBEDCRYPTO_HAVE_INT32 or MBEDCRYPTO_HAVE_INT64
+ * respectively and undefining MBEDCRYPTO_HAVE_ASM.
+ *
+ * Double-width integers (e.g. 128-bit in 64-bit architectures) can be
+ * disabled by defining MBEDCRYPTO_NO_UDBL_DIVISION.
+ */
+#if !defined(MBEDCRYPTO_HAVE_INT32)
+    #if defined(_MSC_VER) && defined(_M_AMD64)
+        /* Always choose 64-bit when using MSC */
+        #if !defined(MBEDCRYPTO_HAVE_INT64)
+            #define MBEDCRYPTO_HAVE_INT64
+        #endif /* !MBEDCRYPTO_HAVE_INT64 */
+        typedef  int64_t mbedcrypto_mpi_sint;
+        typedef uint64_t mbedcrypto_mpi_uint;
+    #elif defined(__GNUC__) && (                         \
+        defined(__amd64__) || defined(__x86_64__)     || \
+        defined(__ppc64__) || defined(__powerpc64__)  || \
+        defined(__ia64__)  || defined(__alpha__)      || \
+        ( defined(__sparc__) && defined(__arch64__) ) || \
+        defined(__s390x__) || defined(__mips64) )
+        #if !defined(MBEDCRYPTO_HAVE_INT64)
+            #define MBEDCRYPTO_HAVE_INT64
+        #endif /* MBEDCRYPTO_HAVE_INT64 */
+        typedef  int64_t mbedcrypto_mpi_sint;
+        typedef uint64_t mbedcrypto_mpi_uint;
+        #if !defined(MBEDCRYPTO_NO_UDBL_DIVISION)
+            /* mbedcrypto_t_udbl defined as 128-bit unsigned int */
+            typedef unsigned int mbedcrypto_t_udbl __attribute__((mode(TI)));
+            #define MBEDCRYPTO_HAVE_UDBL
+        #endif /* !MBEDCRYPTO_NO_UDBL_DIVISION */
+    #elif defined(__ARMCC_VERSION) && defined(__aarch64__)
+        /*
+         * __ARMCC_VERSION is defined for both armcc and armclang and
+         * __aarch64__ is only defined by armclang when compiling 64-bit code
+         */
+        #if !defined(MBEDCRYPTO_HAVE_INT64)
+            #define MBEDCRYPTO_HAVE_INT64
+        #endif /* !MBEDCRYPTO_HAVE_INT64 */
+        typedef  int64_t mbedcrypto_mpi_sint;
+        typedef uint64_t mbedcrypto_mpi_uint;
+        #if !defined(MBEDCRYPTO_NO_UDBL_DIVISION)
+            /* mbedcrypto_t_udbl defined as 128-bit unsigned int */
+            typedef __uint128_t mbedcrypto_t_udbl;
+            #define MBEDCRYPTO_HAVE_UDBL
+        #endif /* !MBEDCRYPTO_NO_UDBL_DIVISION */
+    #elif defined(MBEDCRYPTO_HAVE_INT64)
+        /* Force 64-bit integers with unknown compiler */
+        typedef  int64_t mbedcrypto_mpi_sint;
+        typedef uint64_t mbedcrypto_mpi_uint;
+    #endif
+#endif /* !MBEDCRYPTO_HAVE_INT32 */
+
+#if !defined(MBEDCRYPTO_HAVE_INT64)
+    /* Default to 32-bit compilation */
+    #if !defined(MBEDCRYPTO_HAVE_INT32)
+        #define MBEDCRYPTO_HAVE_INT32
+    #endif /* !MBEDCRYPTO_HAVE_INT32 */
+    typedef  int32_t mbedcrypto_mpi_sint;
+    typedef uint32_t mbedcrypto_mpi_uint;
+    #if !defined(MBEDCRYPTO_NO_UDBL_DIVISION)
+        typedef uint64_t mbedcrypto_t_udbl;
+        #define MBEDCRYPTO_HAVE_UDBL
+    #endif /* !MBEDCRYPTO_NO_UDBL_DIVISION */
+#endif /* !MBEDCRYPTO_HAVE_INT64 */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          MPI structure
+ */
+typedef struct
+{
+    int s;              /*!<  integer sign      */
+    size_t n;           /*!<  total # of limbs  */
+    mbedcrypto_mpi_uint *p;          /*!<  pointer to limbs  */
+}
+mbedcrypto_mpi;
+
+/**
+ * \brief           Initialize one MPI (make internal references valid)
+ *                  This just makes it ready to be set or freed,
+ *                  but does not define a value for the MPI.
+ *
+ * \param X         One MPI to initialize.
+ */
+void mbedcrypto_mpi_init( mbedcrypto_mpi *X );
+
+/**
+ * \brief          Unallocate one MPI
+ *
+ * \param X        One MPI to unallocate.
+ */
+void mbedcrypto_mpi_free( mbedcrypto_mpi *X );
+
+/**
+ * \brief          Enlarge to the specified number of limbs
+ *
+ *                 This function does nothing if the MPI is already large enough.
+ *
+ * \param X        MPI to grow
+ * \param nblimbs  The target number of limbs
+ *
+ * \return         0 if successful,
+ *                 MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedcrypto_mpi_grow( mbedcrypto_mpi *X, size_t nblimbs );
+
+/**
+ * \brief          Resize down, keeping at least the specified number of limbs
+ *
+ *                 If \c X is smaller than \c nblimbs, it is resized up
+ *                 instead.
+ *
+ * \param X        MPI to shrink
+ * \param nblimbs  The minimum number of limbs to keep
+ *
+ * \return         0 if successful,
+ *                 MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ *                 (this can only happen when resizing up).
+ */
+int mbedcrypto_mpi_shrink( mbedcrypto_mpi *X, size_t nblimbs );
+
+/**
+ * \brief          Copy the contents of Y into X
+ *
+ * \param X        Destination MPI. It is enlarged if necessary.
+ * \param Y        Source MPI.
+ *
+ * \return         0 if successful,
+ *                 MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedcrypto_mpi_copy( mbedcrypto_mpi *X, const mbedcrypto_mpi *Y );
+
+/**
+ * \brief          Swap the contents of X and Y
+ *
+ * \param X        First MPI value
+ * \param Y        Second MPI value
+ */
+void mbedcrypto_mpi_swap( mbedcrypto_mpi *X, mbedcrypto_mpi *Y );
+
+/**
+ * \brief          Safe conditional assignement X = Y if assign is 1
+ *
+ * \param X        MPI to conditionally assign to
+ * \param Y        Value to be assigned
+ * \param assign   1: perform the assignment, 0: keep X's original value
+ *
+ * \return         0 if successful,
+ *                 MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed,
+ *
+ * \note           This function is equivalent to
+ *                      if( assign ) mbedcrypto_mpi_copy( X, Y );
+ *                 except that it avoids leaking any information about whether
+ *                 the assignment was done or not (the above code may leak
+ *                 information through branch prediction and/or memory access
+ *                 patterns analysis).
+ */
+int mbedcrypto_mpi_safe_cond_assign( mbedcrypto_mpi *X, const mbedcrypto_mpi *Y, unsigned char assign );
+
+/**
+ * \brief          Safe conditional swap X <-> Y if swap is 1
+ *
+ * \param X        First mbedcrypto_mpi value
+ * \param Y        Second mbedcrypto_mpi value
+ * \param assign   1: perform the swap, 0: keep X and Y's original values
+ *
+ * \return         0 if successful,
+ *                 MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed,
+ *
+ * \note           This function is equivalent to
+ *                      if( assign ) mbedcrypto_mpi_swap( X, Y );
+ *                 except that it avoids leaking any information about whether
+ *                 the assignment was done or not (the above code may leak
+ *                 information through branch prediction and/or memory access
+ *                 patterns analysis).
+ */
+int mbedcrypto_mpi_safe_cond_swap( mbedcrypto_mpi *X, mbedcrypto_mpi *Y, unsigned char assign );
+
+/**
+ * \brief          Set value from integer
+ *
+ * \param X        MPI to set
+ * \param z        Value to use
+ *
+ * \return         0 if successful,
+ *                 MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedcrypto_mpi_lset( mbedcrypto_mpi *X, mbedcrypto_mpi_sint z );
+
+/**
+ * \brief          Get a specific bit from X
+ *
+ * \param X        MPI to use
+ * \param pos      Zero-based index of the bit in X
+ *
+ * \return         Either a 0 or a 1
+ */
+int mbedcrypto_mpi_get_bit( const mbedcrypto_mpi *X, size_t pos );
+
+/**
+ * \brief          Set a bit of X to a specific value of 0 or 1
+ *
+ * \note           Will grow X if necessary to set a bit to 1 in a not yet
+ *                 existing limb. Will not grow if bit should be set to 0
+ *
+ * \param X        MPI to use
+ * \param pos      Zero-based index of the bit in X
+ * \param val      The value to set the bit to (0 or 1)
+ *
+ * \return         0 if successful,
+ *                 MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed,
+ *                 MBEDCRYPTO_ERR_MPI_BAD_INPUT_DATA if val is not 0 or 1
+ */
+int mbedcrypto_mpi_set_bit( mbedcrypto_mpi *X, size_t pos, unsigned char val );
+
+/**
+ * \brief          Return the number of zero-bits before the least significant
+ *                 '1' bit
+ *
+ * Note: Thus also the zero-based index of the least significant '1' bit
+ *
+ * \param X        MPI to use
+ */
+size_t mbedcrypto_mpi_lsb( const mbedcrypto_mpi *X );
+
+/**
+ * \brief          Return the number of bits up to and including the most
+ *                 significant '1' bit'
+ *
+ * Note: Thus also the one-based index of the most significant '1' bit
+ *
+ * \param X        MPI to use
+ */
+size_t mbedcrypto_mpi_bitlen( const mbedcrypto_mpi *X );
+
+/**
+ * \brief          Return the total size in bytes
+ *
+ * \param X        MPI to use
+ */
+size_t mbedcrypto_mpi_size( const mbedcrypto_mpi *X );
+
+/**
+ * \brief          Import from an ASCII string
+ *
+ * \param X        Destination MPI
+ * \param radix    Input numeric base
+ * \param s        Null-terminated string buffer
+ *
+ * \return         0 if successful, or a MBEDCRYPTO_ERR_MPI_XXX error code
+ */
+int mbedcrypto_mpi_read_string( mbedcrypto_mpi *X, int radix, const char *s );
+
+/**
+ * \brief          Export into an ASCII string
+ *
+ * \param X        Source MPI
+ * \param radix    Output numeric base
+ * \param buf      Buffer to write the string to
+ * \param buflen   Length of buf
+ * \param olen     Length of the string written, including final NUL byte
+ *
+ * \return         0 if successful, or a MBEDCRYPTO_ERR_MPI_XXX error code.
+ *                 *olen is always updated to reflect the amount
+ *                 of data that has (or would have) been written.
+ *
+ * \note           Call this function with buflen = 0 to obtain the
+ *                 minimum required buffer size in *olen.
+ */
+int mbedcrypto_mpi_write_string( const mbedcrypto_mpi *X, int radix,
+                              char *buf, size_t buflen, size_t *olen );
+
+#if defined(MBEDCRYPTO_FS_IO)
+/**
+ * \brief          Read MPI from a line in an opened file
+ *
+ * \param X        Destination MPI
+ * \param radix    Input numeric base
+ * \param fin      Input file handle
+ *
+ * \return         0 if successful, MBEDCRYPTO_ERR_MPI_BUFFER_TOO_SMALL if
+ *                 the file read buffer is too small or a
+ *                 MBEDCRYPTO_ERR_MPI_XXX error code
+ *
+ * \note           On success, this function advances the file stream
+ *                 to the end of the current line or to EOF.
+ *
+ *                 The function returns 0 on an empty line.
+ *
+ *                 Leading whitespaces are ignored, as is a
+ *                 '0x' prefix for radix 16.
+ *
+ */
+int mbedcrypto_mpi_read_file( mbedcrypto_mpi *X, int radix, FILE *fin );
+
+/**
+ * \brief          Write X into an opened file, or stdout if fout is NULL
+ *
+ * \param p        Prefix, can be NULL
+ * \param X        Source MPI
+ * \param radix    Output numeric base
+ * \param fout     Output file handle (can be NULL)
+ *
+ * \return         0 if successful, or a MBEDCRYPTO_ERR_MPI_XXX error code
+ *
+ * \note           Set fout == NULL to print X on the console.
+ */
+int mbedcrypto_mpi_write_file( const char *p, const mbedcrypto_mpi *X, int radix, FILE *fout );
+#endif /* MBEDCRYPTO_FS_IO */
+
+/**
+ * \brief          Import X from unsigned binary data, big endian
+ *
+ * \param X        Destination MPI
+ * \param buf      Input buffer
+ * \param buflen   Input buffer size
+ *
+ * \return         0 if successful,
+ *                 MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedcrypto_mpi_read_binary( mbedcrypto_mpi *X, const unsigned char *buf, size_t buflen );
+
+/**
+ * \brief          Export X into unsigned binary data, big endian.
+ *                 Always fills the whole buffer, which will start with zeros
+ *                 if the number is smaller.
+ *
+ * \param X        Source MPI
+ * \param buf      Output buffer
+ * \param buflen   Output buffer size
+ *
+ * \return         0 if successful,
+ *                 MBEDCRYPTO_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough
+ */
+int mbedcrypto_mpi_write_binary( const mbedcrypto_mpi *X, unsigned char *buf, size_t buflen );
+
+/**
+ * \brief          Left-shift: X <<= count
+ *
+ * \param X        MPI to shift
+ * \param count    Amount to shift
+ *
+ * \return         0 if successful,
+ *                 MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedcrypto_mpi_shift_l( mbedcrypto_mpi *X, size_t count );
+
+/**
+ * \brief          Right-shift: X >>= count
+ *
+ * \param X        MPI to shift
+ * \param count    Amount to shift
+ *
+ * \return         0 if successful,
+ *                 MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedcrypto_mpi_shift_r( mbedcrypto_mpi *X, size_t count );
+
+/**
+ * \brief          Compare unsigned values
+ *
+ * \param X        Left-hand MPI
+ * \param Y        Right-hand MPI
+ *
+ * \return         1 if |X| is greater than |Y|,
+ *                -1 if |X| is lesser  than |Y| or
+ *                 0 if |X| is equal to |Y|
+ */
+int mbedcrypto_mpi_cmp_abs( const mbedcrypto_mpi *X, const mbedcrypto_mpi *Y );
+
+/**
+ * \brief          Compare signed values
+ *
+ * \param X        Left-hand MPI
+ * \param Y        Right-hand MPI
+ *
+ * \return         1 if X is greater than Y,
+ *                -1 if X is lesser  than Y or
+ *                 0 if X is equal to Y
+ */
+int mbedcrypto_mpi_cmp_mpi( const mbedcrypto_mpi *X, const mbedcrypto_mpi *Y );
+
+/**
+ * \brief          Compare signed values
+ *
+ * \param X        Left-hand MPI
+ * \param z        The integer value to compare to
+ *
+ * \return         1 if X is greater than z,
+ *                -1 if X is lesser  than z or
+ *                 0 if X is equal to z
+ */
+int mbedcrypto_mpi_cmp_int( const mbedcrypto_mpi *X, mbedcrypto_mpi_sint z );
+
+/**
+ * \brief          Unsigned addition: X = |A| + |B|
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param B        Right-hand MPI
+ *
+ * \return         0 if successful,
+ *                 MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedcrypto_mpi_add_abs( mbedcrypto_mpi *X, const mbedcrypto_mpi *A, const mbedcrypto_mpi *B );
+
+/**
+ * \brief          Unsigned subtraction: X = |A| - |B|
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param B        Right-hand MPI
+ *
+ * \return         0 if successful,
+ *                 MBEDCRYPTO_ERR_MPI_NEGATIVE_VALUE if B is greater than A
+ */
+int mbedcrypto_mpi_sub_abs( mbedcrypto_mpi *X, const mbedcrypto_mpi *A, const mbedcrypto_mpi *B );
+
+/**
+ * \brief          Signed addition: X = A + B
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param B        Right-hand MPI
+ *
+ * \return         0 if successful,
+ *                 MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedcrypto_mpi_add_mpi( mbedcrypto_mpi *X, const mbedcrypto_mpi *A, const mbedcrypto_mpi *B );
+
+/**
+ * \brief          Signed subtraction: X = A - B
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param B        Right-hand MPI
+ *
+ * \return         0 if successful,
+ *                 MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedcrypto_mpi_sub_mpi( mbedcrypto_mpi *X, const mbedcrypto_mpi *A, const mbedcrypto_mpi *B );
+
+/**
+ * \brief          Signed addition: X = A + b
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param b        The integer value to add
+ *
+ * \return         0 if successful,
+ *                 MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedcrypto_mpi_add_int( mbedcrypto_mpi *X, const mbedcrypto_mpi *A, mbedcrypto_mpi_sint b );
+
+/**
+ * \brief          Signed subtraction: X = A - b
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param b        The integer value to subtract
+ *
+ * \return         0 if successful,
+ *                 MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedcrypto_mpi_sub_int( mbedcrypto_mpi *X, const mbedcrypto_mpi *A, mbedcrypto_mpi_sint b );
+
+/**
+ * \brief          Baseline multiplication: X = A * B
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param B        Right-hand MPI
+ *
+ * \return         0 if successful,
+ *                 MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedcrypto_mpi_mul_mpi( mbedcrypto_mpi *X, const mbedcrypto_mpi *A, const mbedcrypto_mpi *B );
+
+/**
+ * \brief          Baseline multiplication: X = A * b
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param b        The unsigned integer value to multiply with
+ *
+ * \note           b is unsigned
+ *
+ * \return         0 if successful,
+ *                 MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedcrypto_mpi_mul_int( mbedcrypto_mpi *X, const mbedcrypto_mpi *A, mbedcrypto_mpi_uint b );
+
+/**
+ * \brief          Division by mbedcrypto_mpi: A = Q * B + R
+ *
+ * \param Q        Destination MPI for the quotient
+ * \param R        Destination MPI for the rest value
+ * \param A        Left-hand MPI
+ * \param B        Right-hand MPI
+ *
+ * \return         0 if successful,
+ *                 MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed,
+ *                 MBEDCRYPTO_ERR_MPI_DIVISION_BY_ZERO if B == 0
+ *
+ * \note           Either Q or R can be NULL.
+ */
+int mbedcrypto_mpi_div_mpi( mbedcrypto_mpi *Q, mbedcrypto_mpi *R, const mbedcrypto_mpi *A, const mbedcrypto_mpi *B );
+
+/**
+ * \brief          Division by int: A = Q * b + R
+ *
+ * \param Q        Destination MPI for the quotient
+ * \param R        Destination MPI for the rest value
+ * \param A        Left-hand MPI
+ * \param b        Integer to divide by
+ *
+ * \return         0 if successful,
+ *                 MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed,
+ *                 MBEDCRYPTO_ERR_MPI_DIVISION_BY_ZERO if b == 0
+ *
+ * \note           Either Q or R can be NULL.
+ */
+int mbedcrypto_mpi_div_int( mbedcrypto_mpi *Q, mbedcrypto_mpi *R, const mbedcrypto_mpi *A, mbedcrypto_mpi_sint b );
+
+/**
+ * \brief          Modulo: R = A mod B
+ *
+ * \param R        Destination MPI for the rest value
+ * \param A        Left-hand MPI
+ * \param B        Right-hand MPI
+ *
+ * \return         0 if successful,
+ *                 MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed,
+ *                 MBEDCRYPTO_ERR_MPI_DIVISION_BY_ZERO if B == 0,
+ *                 MBEDCRYPTO_ERR_MPI_NEGATIVE_VALUE if B < 0
+ */
+int mbedcrypto_mpi_mod_mpi( mbedcrypto_mpi *R, const mbedcrypto_mpi *A, const mbedcrypto_mpi *B );
+
+/**
+ * \brief          Modulo: r = A mod b
+ *
+ * \param r        Destination mbedcrypto_mpi_uint
+ * \param A        Left-hand MPI
+ * \param b        Integer to divide by
+ *
+ * \return         0 if successful,
+ *                 MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed,
+ *                 MBEDCRYPTO_ERR_MPI_DIVISION_BY_ZERO if b == 0,
+ *                 MBEDCRYPTO_ERR_MPI_NEGATIVE_VALUE if b < 0
+ */
+int mbedcrypto_mpi_mod_int( mbedcrypto_mpi_uint *r, const mbedcrypto_mpi *A, mbedcrypto_mpi_sint b );
+
+/**
+ * \brief          Sliding-window exponentiation: X = A^E mod N
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param E        Exponent MPI
+ * \param N        Modular MPI
+ * \param _RR      Speed-up MPI used for recalculations
+ *
+ * \return         0 if successful,
+ *                 MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed,
+ *                 MBEDCRYPTO_ERR_MPI_BAD_INPUT_DATA if N is negative or even or
+ *                 if E is negative
+ *
+ * \note           _RR is used to avoid re-computing R*R mod N across
+ *                 multiple calls, which speeds up things a bit. It can
+ *                 be set to NULL if the extra performance is unneeded.
+ */
+int mbedcrypto_mpi_exp_mod( mbedcrypto_mpi *X, const mbedcrypto_mpi *A, const mbedcrypto_mpi *E, const mbedcrypto_mpi *N, mbedcrypto_mpi *_RR );
+
+/**
+ * \brief          Fill an MPI X with size bytes of random
+ *
+ * \param X        Destination MPI
+ * \param size     Size in bytes
+ * \param f_rng    RNG function
+ * \param p_rng    RNG parameter
+ *
+ * \return         0 if successful,
+ *                 MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ *
+ * \note           The bytes obtained from the PRNG are interpreted
+ *                 as a big-endian representation of an MPI; this can
+ *                 be relevant in applications like deterministic ECDSA.
+ */
+int mbedcrypto_mpi_fill_random( mbedcrypto_mpi *X, size_t size,
+                     int (*f_rng)(void *, unsigned char *, size_t),
+                     void *p_rng );
+
+/**
+ * \brief          Greatest common divisor: G = gcd(A, B)
+ *
+ * \param G        Destination MPI
+ * \param A        Left-hand MPI
+ * \param B        Right-hand MPI
+ *
+ * \return         0 if successful,
+ *                 MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedcrypto_mpi_gcd( mbedcrypto_mpi *G, const mbedcrypto_mpi *A, const mbedcrypto_mpi *B );
+
+/**
+ * \brief          Modular inverse: X = A^-1 mod N
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param N        Right-hand MPI
+ *
+ * \return         0 if successful,
+ *                 MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed,
+ *                 MBEDCRYPTO_ERR_MPI_BAD_INPUT_DATA if N is <= 1,
+                   MBEDCRYPTO_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N.
+ */
+int mbedcrypto_mpi_inv_mod( mbedcrypto_mpi *X, const mbedcrypto_mpi *A, const mbedcrypto_mpi *N );
+
+/**
+ * \brief          Miller-Rabin primality test
+ *
+ * \param X        MPI to check
+ * \param f_rng    RNG function
+ * \param p_rng    RNG parameter
+ *
+ * \return         0 if successful (probably prime),
+ *                 MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed,
+ *                 MBEDCRYPTO_ERR_MPI_NOT_ACCEPTABLE if X is not prime
+ */
+int mbedcrypto_mpi_is_prime( const mbedcrypto_mpi *X,
+                  int (*f_rng)(void *, unsigned char *, size_t),
+                  void *p_rng );
+
+/**
+ * \brief          Prime number generation
+ *
+ * \param X        Destination MPI
+ * \param nbits    Required size of X in bits
+ *                 ( 3 <= nbits <= MBEDCRYPTO_MPI_MAX_BITS )
+ * \param dh_flag  If 1, then (X-1)/2 will be prime too
+ * \param f_rng    RNG function
+ * \param p_rng    RNG parameter
+ *
+ * \return         0 if successful (probably prime),
+ *                 MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed,
+ *                 MBEDCRYPTO_ERR_MPI_BAD_INPUT_DATA if nbits is < 3
+ */
+int mbedcrypto_mpi_gen_prime( mbedcrypto_mpi *X, size_t nbits, int dh_flag,
+                   int (*f_rng)(void *, unsigned char *, size_t),
+                   void *p_rng );
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int mbedcrypto_mpi_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* bignum.h */
diff --git a/include/mbedcrypto/blowfish.h b/include/mbedcrypto/blowfish.h
new file mode 100644
index 0000000..b11c2e8
--- /dev/null
+++ b/include/mbedcrypto/blowfish.h
@@ -0,0 +1,205 @@
+/**
+ * \file blowfish.h
+ *
+ * \brief Blowfish block cipher
+ */
+/*
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_BLOWFISH_H
+#define MBEDCRYPTO_BLOWFISH_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+#define MBEDCRYPTO_BLOWFISH_ENCRYPT     1
+#define MBEDCRYPTO_BLOWFISH_DECRYPT     0
+#define MBEDCRYPTO_BLOWFISH_MAX_KEY_BITS     448
+#define MBEDCRYPTO_BLOWFISH_MIN_KEY_BITS     32
+#define MBEDCRYPTO_BLOWFISH_ROUNDS      16         /**< Rounds to use. When increasing this value, make sure to extend the initialisation vectors */
+#define MBEDCRYPTO_BLOWFISH_BLOCKSIZE   8          /* Blowfish uses 64 bit blocks */
+
+#define MBEDCRYPTO_ERR_BLOWFISH_INVALID_KEY_LENGTH                -0x0016  /**< Invalid key length. */
+#define MBEDCRYPTO_ERR_BLOWFISH_HW_ACCEL_FAILED                   -0x0017  /**< Blowfish hardware accelerator failed. */
+#define MBEDCRYPTO_ERR_BLOWFISH_INVALID_INPUT_LENGTH              -0x0018  /**< Invalid data input length. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDCRYPTO_BLOWFISH_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief          Blowfish context structure
+ */
+typedef struct
+{
+    uint32_t P[MBEDCRYPTO_BLOWFISH_ROUNDS + 2];    /*!<  Blowfish round keys    */
+    uint32_t S[4][256];                 /*!<  key dependent S-boxes  */
+}
+mbedcrypto_blowfish_context;
+
+#else  /* MBEDCRYPTO_BLOWFISH_ALT */
+#include "blowfish_alt.h"
+#endif /* MBEDCRYPTO_BLOWFISH_ALT */
+
+/**
+ * \brief          Initialize Blowfish context
+ *
+ * \param ctx      Blowfish context to be initialized
+ */
+void mbedcrypto_blowfish_init( mbedcrypto_blowfish_context *ctx );
+
+/**
+ * \brief          Clear Blowfish context
+ *
+ * \param ctx      Blowfish context to be cleared
+ */
+void mbedcrypto_blowfish_free( mbedcrypto_blowfish_context *ctx );
+
+/**
+ * \brief          Blowfish key schedule
+ *
+ * \param ctx      Blowfish context to be initialized
+ * \param key      encryption key
+ * \param keybits  must be between 32 and 448 bits
+ *
+ * \return         0 if successful, or MBEDCRYPTO_ERR_BLOWFISH_INVALID_KEY_LENGTH
+ */
+int mbedcrypto_blowfish_setkey( mbedcrypto_blowfish_context *ctx, const unsigned char *key,
+                     unsigned int keybits );
+
+/**
+ * \brief          Blowfish-ECB block encryption/decryption
+ *
+ * \param ctx      Blowfish context
+ * \param mode     MBEDCRYPTO_BLOWFISH_ENCRYPT or MBEDCRYPTO_BLOWFISH_DECRYPT
+ * \param input    8-byte input block
+ * \param output   8-byte output block
+ *
+ * \return         0 if successful
+ */
+int mbedcrypto_blowfish_crypt_ecb( mbedcrypto_blowfish_context *ctx,
+                        int mode,
+                        const unsigned char input[MBEDCRYPTO_BLOWFISH_BLOCKSIZE],
+                        unsigned char output[MBEDCRYPTO_BLOWFISH_BLOCKSIZE] );
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+/**
+ * \brief          Blowfish-CBC buffer encryption/decryption
+ *                 Length should be a multiple of the block
+ *                 size (8 bytes)
+ *
+ * \note           Upon exit, the content of the IV is updated so that you can
+ *                 call the function same function again on the following
+ *                 block(s) of data and get the same result as if it was
+ *                 encrypted in one call. This allows a "streaming" usage.
+ *                 If on the other hand you need to retain the contents of the
+ *                 IV, you should either save it manually or use the cipher
+ *                 module instead.
+ *
+ * \param ctx      Blowfish context
+ * \param mode     MBEDCRYPTO_BLOWFISH_ENCRYPT or MBEDCRYPTO_BLOWFISH_DECRYPT
+ * \param length   length of the input data
+ * \param iv       initialization vector (updated after use)
+ * \param input    buffer holding the input data
+ * \param output   buffer holding the output data
+ *
+ * \return         0 if successful, or
+ *                 MBEDCRYPTO_ERR_BLOWFISH_INVALID_INPUT_LENGTH
+ */
+int mbedcrypto_blowfish_crypt_cbc( mbedcrypto_blowfish_context *ctx,
+                        int mode,
+                        size_t length,
+                        unsigned char iv[MBEDCRYPTO_BLOWFISH_BLOCKSIZE],
+                        const unsigned char *input,
+                        unsigned char *output );
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+/**
+ * \brief          Blowfish CFB buffer encryption/decryption.
+ *
+ * \note           Upon exit, the content of the IV is updated so that you can
+ *                 call the function same function again on the following
+ *                 block(s) of data and get the same result as if it was
+ *                 encrypted in one call. This allows a "streaming" usage.
+ *                 If on the other hand you need to retain the contents of the
+ *                 IV, you should either save it manually or use the cipher
+ *                 module instead.
+ *
+ * \param ctx      Blowfish context
+ * \param mode     MBEDCRYPTO_BLOWFISH_ENCRYPT or MBEDCRYPTO_BLOWFISH_DECRYPT
+ * \param length   length of the input data
+ * \param iv_off   offset in IV (updated after use)
+ * \param iv       initialization vector (updated after use)
+ * \param input    buffer holding the input data
+ * \param output   buffer holding the output data
+ *
+ * \return         0 if successful
+ */
+int mbedcrypto_blowfish_crypt_cfb64( mbedcrypto_blowfish_context *ctx,
+                          int mode,
+                          size_t length,
+                          size_t *iv_off,
+                          unsigned char iv[MBEDCRYPTO_BLOWFISH_BLOCKSIZE],
+                          const unsigned char *input,
+                          unsigned char *output );
+#endif /*MBEDCRYPTO_CIPHER_MODE_CFB */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+/**
+ * \brief               Blowfish-CTR buffer encryption/decryption
+ *
+ * Warning: You have to keep the maximum use of your counter in mind!
+ *
+ * \param ctx           Blowfish context
+ * \param length        The length of the data
+ * \param nc_off        The offset in the current stream_block (for resuming
+ *                      within current cipher stream). The offset pointer to
+ *                      should be 0 at the start of a stream.
+ * \param nonce_counter The 64-bit nonce and counter.
+ * \param stream_block  The saved stream-block for resuming. Is overwritten
+ *                      by the function.
+ * \param input         The input data stream
+ * \param output        The output data stream
+ *
+ * \return         0 if successful
+ */
+int mbedcrypto_blowfish_crypt_ctr( mbedcrypto_blowfish_context *ctx,
+                        size_t length,
+                        size_t *nc_off,
+                        unsigned char nonce_counter[MBEDCRYPTO_BLOWFISH_BLOCKSIZE],
+                        unsigned char stream_block[MBEDCRYPTO_BLOWFISH_BLOCKSIZE],
+                        const unsigned char *input,
+                        unsigned char *output );
+#endif /* MBEDCRYPTO_CIPHER_MODE_CTR */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* blowfish.h */
diff --git a/include/mbedcrypto/bn_mul.h b/include/mbedcrypto/bn_mul.h
new file mode 100644
index 0000000..7d70c2e
--- /dev/null
+++ b/include/mbedcrypto/bn_mul.h
@@ -0,0 +1,886 @@
+/**
+ * \file bn_mul.h
+ *
+ * \brief Multi-precision integer library
+ */
+/*
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+/*
+ *      Multiply source vector [s] with b, add result
+ *       to destination vector [d] and set carry c.
+ *
+ *      Currently supports:
+ *
+ *         . IA-32 (386+)         . AMD64 / EM64T
+ *         . IA-32 (SSE2)         . Motorola 68000
+ *         . PowerPC, 32-bit      . MicroBlaze
+ *         . PowerPC, 64-bit      . TriCore
+ *         . SPARC v8             . ARM v3+
+ *         . Alpha                . MIPS32
+ *         . C, longlong          . C, generic
+ */
+#ifndef MBEDCRYPTO_BN_MUL_H
+#define MBEDCRYPTO_BN_MUL_H
+
+#include "bignum.h"
+
+#if defined(MBEDCRYPTO_HAVE_ASM)
+
+#ifndef asm
+#define asm __asm
+#endif
+
+/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */
+#if defined(__GNUC__) && \
+    ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 )
+#if defined(__i386__)
+
+#define MULADDC_INIT                        \
+    asm(                                    \
+        "movl   %%ebx, %0           \n\t"   \
+        "movl   %5, %%esi           \n\t"   \
+        "movl   %6, %%edi           \n\t"   \
+        "movl   %7, %%ecx           \n\t"   \
+        "movl   %8, %%ebx           \n\t"
+
+#define MULADDC_CORE                        \
+        "lodsl                      \n\t"   \
+        "mull   %%ebx               \n\t"   \
+        "addl   %%ecx,   %%eax      \n\t"   \
+        "adcl   $0,      %%edx      \n\t"   \
+        "addl   (%%edi), %%eax      \n\t"   \
+        "adcl   $0,      %%edx      \n\t"   \
+        "movl   %%edx,   %%ecx      \n\t"   \
+        "stosl                      \n\t"
+
+#if defined(MBEDCRYPTO_HAVE_SSE2)
+
+#define MULADDC_HUIT                            \
+        "movd     %%ecx,     %%mm1      \n\t"   \
+        "movd     %%ebx,     %%mm0      \n\t"   \
+        "movd     (%%edi),   %%mm3      \n\t"   \
+        "paddq    %%mm3,     %%mm1      \n\t"   \
+        "movd     (%%esi),   %%mm2      \n\t"   \
+        "pmuludq  %%mm0,     %%mm2      \n\t"   \
+        "movd     4(%%esi),  %%mm4      \n\t"   \
+        "pmuludq  %%mm0,     %%mm4      \n\t"   \
+        "movd     8(%%esi),  %%mm6      \n\t"   \
+        "pmuludq  %%mm0,     %%mm6      \n\t"   \
+        "movd     12(%%esi), %%mm7      \n\t"   \
+        "pmuludq  %%mm0,     %%mm7      \n\t"   \
+        "paddq    %%mm2,     %%mm1      \n\t"   \
+        "movd     4(%%edi),  %%mm3      \n\t"   \
+        "paddq    %%mm4,     %%mm3      \n\t"   \
+        "movd     8(%%edi),  %%mm5      \n\t"   \
+        "paddq    %%mm6,     %%mm5      \n\t"   \
+        "movd     12(%%edi), %%mm4      \n\t"   \
+        "paddq    %%mm4,     %%mm7      \n\t"   \
+        "movd     %%mm1,     (%%edi)    \n\t"   \
+        "movd     16(%%esi), %%mm2      \n\t"   \
+        "pmuludq  %%mm0,     %%mm2      \n\t"   \
+        "psrlq    $32,       %%mm1      \n\t"   \
+        "movd     20(%%esi), %%mm4      \n\t"   \
+        "pmuludq  %%mm0,     %%mm4      \n\t"   \
+        "paddq    %%mm3,     %%mm1      \n\t"   \
+        "movd     24(%%esi), %%mm6      \n\t"   \
+        "pmuludq  %%mm0,     %%mm6      \n\t"   \
+        "movd     %%mm1,     4(%%edi)   \n\t"   \
+        "psrlq    $32,       %%mm1      \n\t"   \
+        "movd     28(%%esi), %%mm3      \n\t"   \
+        "pmuludq  %%mm0,     %%mm3      \n\t"   \
+        "paddq    %%mm5,     %%mm1      \n\t"   \
+        "movd     16(%%edi), %%mm5      \n\t"   \
+        "paddq    %%mm5,     %%mm2      \n\t"   \
+        "movd     %%mm1,     8(%%edi)   \n\t"   \
+        "psrlq    $32,       %%mm1      \n\t"   \
+        "paddq    %%mm7,     %%mm1      \n\t"   \
+        "movd     20(%%edi), %%mm5      \n\t"   \
+        "paddq    %%mm5,     %%mm4      \n\t"   \
+        "movd     %%mm1,     12(%%edi)  \n\t"   \
+        "psrlq    $32,       %%mm1      \n\t"   \
+        "paddq    %%mm2,     %%mm1      \n\t"   \
+        "movd     24(%%edi), %%mm5      \n\t"   \
+        "paddq    %%mm5,     %%mm6      \n\t"   \
+        "movd     %%mm1,     16(%%edi)  \n\t"   \
+        "psrlq    $32,       %%mm1      \n\t"   \
+        "paddq    %%mm4,     %%mm1      \n\t"   \
+        "movd     28(%%edi), %%mm5      \n\t"   \
+        "paddq    %%mm5,     %%mm3      \n\t"   \
+        "movd     %%mm1,     20(%%edi)  \n\t"   \
+        "psrlq    $32,       %%mm1      \n\t"   \
+        "paddq    %%mm6,     %%mm1      \n\t"   \
+        "movd     %%mm1,     24(%%edi)  \n\t"   \
+        "psrlq    $32,       %%mm1      \n\t"   \
+        "paddq    %%mm3,     %%mm1      \n\t"   \
+        "movd     %%mm1,     28(%%edi)  \n\t"   \
+        "addl     $32,       %%edi      \n\t"   \
+        "addl     $32,       %%esi      \n\t"   \
+        "psrlq    $32,       %%mm1      \n\t"   \
+        "movd     %%mm1,     %%ecx      \n\t"
+
+#define MULADDC_STOP                    \
+        "emms                   \n\t"   \
+        "movl   %4, %%ebx       \n\t"   \
+        "movl   %%ecx, %1       \n\t"   \
+        "movl   %%edi, %2       \n\t"   \
+        "movl   %%esi, %3       \n\t"   \
+        : "=m" (t), "=m" (c), "=m" (d), "=m" (s)        \
+        : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b)   \
+        : "eax", "ecx", "edx", "esi", "edi"             \
+    );
+
+#else
+
+#define MULADDC_STOP                    \
+        "movl   %4, %%ebx       \n\t"   \
+        "movl   %%ecx, %1       \n\t"   \
+        "movl   %%edi, %2       \n\t"   \
+        "movl   %%esi, %3       \n\t"   \
+        : "=m" (t), "=m" (c), "=m" (d), "=m" (s)        \
+        : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b)   \
+        : "eax", "ecx", "edx", "esi", "edi"             \
+    );
+#endif /* SSE2 */
+#endif /* i386 */
+
+#if defined(__amd64__) || defined (__x86_64__)
+
+#define MULADDC_INIT                        \
+    asm(                                    \
+        "xorq   %%r8, %%r8          \n\t"
+
+#define MULADDC_CORE                        \
+        "movq   (%%rsi), %%rax      \n\t"   \
+        "mulq   %%rbx               \n\t"   \
+        "addq   $8,      %%rsi      \n\t"   \
+        "addq   %%rcx,   %%rax      \n\t"   \
+        "movq   %%r8,    %%rcx      \n\t"   \
+        "adcq   $0,      %%rdx      \n\t"   \
+        "nop                        \n\t"   \
+        "addq   %%rax,   (%%rdi)    \n\t"   \
+        "adcq   %%rdx,   %%rcx      \n\t"   \
+        "addq   $8,      %%rdi      \n\t"
+
+#define MULADDC_STOP                        \
+        : "+c" (c), "+D" (d), "+S" (s)      \
+        : "b" (b)                           \
+        : "rax", "rdx", "r8"                \
+    );
+
+#endif /* AMD64 */
+
+#if defined(__mc68020__) || defined(__mcpu32__)
+
+#define MULADDC_INIT                    \
+    asm(                                \
+        "movl   %3, %%a2        \n\t"   \
+        "movl   %4, %%a3        \n\t"   \
+        "movl   %5, %%d3        \n\t"   \
+        "movl   %6, %%d2        \n\t"   \
+        "moveq  #0, %%d0        \n\t"
+
+#define MULADDC_CORE                    \
+        "movel  %%a2@+, %%d1    \n\t"   \
+        "mulul  %%d2, %%d4:%%d1 \n\t"   \
+        "addl   %%d3, %%d1      \n\t"   \
+        "addxl  %%d0, %%d4      \n\t"   \
+        "moveq  #0,   %%d3      \n\t"   \
+        "addl   %%d1, %%a3@+    \n\t"   \
+        "addxl  %%d4, %%d3      \n\t"
+
+#define MULADDC_STOP                    \
+        "movl   %%d3, %0        \n\t"   \
+        "movl   %%a3, %1        \n\t"   \
+        "movl   %%a2, %2        \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)              \
+        : "m" (s), "m" (d), "m" (c), "m" (b)        \
+        : "d0", "d1", "d2", "d3", "d4", "a2", "a3"  \
+    );
+
+#define MULADDC_HUIT                        \
+        "movel  %%a2@+,  %%d1       \n\t"   \
+        "mulul  %%d2,    %%d4:%%d1  \n\t"   \
+        "addxl  %%d3,    %%d1       \n\t"   \
+        "addxl  %%d0,    %%d4       \n\t"   \
+        "addl   %%d1,    %%a3@+     \n\t"   \
+        "movel  %%a2@+,  %%d1       \n\t"   \
+        "mulul  %%d2,    %%d3:%%d1  \n\t"   \
+        "addxl  %%d4,    %%d1       \n\t"   \
+        "addxl  %%d0,    %%d3       \n\t"   \
+        "addl   %%d1,    %%a3@+     \n\t"   \
+        "movel  %%a2@+,  %%d1       \n\t"   \
+        "mulul  %%d2,    %%d4:%%d1  \n\t"   \
+        "addxl  %%d3,    %%d1       \n\t"   \
+        "addxl  %%d0,    %%d4       \n\t"   \
+        "addl   %%d1,    %%a3@+     \n\t"   \
+        "movel  %%a2@+,  %%d1       \n\t"   \
+        "mulul  %%d2,    %%d3:%%d1  \n\t"   \
+        "addxl  %%d4,    %%d1       \n\t"   \
+        "addxl  %%d0,    %%d3       \n\t"   \
+        "addl   %%d1,    %%a3@+     \n\t"   \
+        "movel  %%a2@+,  %%d1       \n\t"   \
+        "mulul  %%d2,    %%d4:%%d1  \n\t"   \
+        "addxl  %%d3,    %%d1       \n\t"   \
+        "addxl  %%d0,    %%d4       \n\t"   \
+        "addl   %%d1,    %%a3@+     \n\t"   \
+        "movel  %%a2@+,  %%d1       \n\t"   \
+        "mulul  %%d2,    %%d3:%%d1  \n\t"   \
+        "addxl  %%d4,    %%d1       \n\t"   \
+        "addxl  %%d0,    %%d3       \n\t"   \
+        "addl   %%d1,    %%a3@+     \n\t"   \
+        "movel  %%a2@+,  %%d1       \n\t"   \
+        "mulul  %%d2,    %%d4:%%d1  \n\t"   \
+        "addxl  %%d3,    %%d1       \n\t"   \
+        "addxl  %%d0,    %%d4       \n\t"   \
+        "addl   %%d1,    %%a3@+     \n\t"   \
+        "movel  %%a2@+,  %%d1       \n\t"   \
+        "mulul  %%d2,    %%d3:%%d1  \n\t"   \
+        "addxl  %%d4,    %%d1       \n\t"   \
+        "addxl  %%d0,    %%d3       \n\t"   \
+        "addl   %%d1,    %%a3@+     \n\t"   \
+        "addxl  %%d0,    %%d3       \n\t"
+
+#endif /* MC68000 */
+
+#if defined(__powerpc64__) || defined(__ppc64__)
+
+#if defined(__MACH__) && defined(__APPLE__)
+
+#define MULADDC_INIT                        \
+    asm(                                    \
+        "ld     r3, %3              \n\t"   \
+        "ld     r4, %4              \n\t"   \
+        "ld     r5, %5              \n\t"   \
+        "ld     r6, %6              \n\t"   \
+        "addi   r3, r3, -8          \n\t"   \
+        "addi   r4, r4, -8          \n\t"   \
+        "addic  r5, r5,  0          \n\t"
+
+#define MULADDC_CORE                        \
+        "ldu    r7, 8(r3)           \n\t"   \
+        "mulld  r8, r7, r6          \n\t"   \
+        "mulhdu r9, r7, r6          \n\t"   \
+        "adde   r8, r8, r5          \n\t"   \
+        "ld     r7, 8(r4)           \n\t"   \
+        "addze  r5, r9              \n\t"   \
+        "addc   r8, r8, r7          \n\t"   \
+        "stdu   r8, 8(r4)           \n\t"
+
+#define MULADDC_STOP                        \
+        "addze  r5, r5              \n\t"   \
+        "addi   r4, r4, 8           \n\t"   \
+        "addi   r3, r3, 8           \n\t"   \
+        "std    r5, %0              \n\t"   \
+        "std    r4, %1              \n\t"   \
+        "std    r3, %2              \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)              \
+        : "m" (s), "m" (d), "m" (c), "m" (b)        \
+        : "r3", "r4", "r5", "r6", "r7", "r8", "r9"  \
+    );
+
+
+#else /* __MACH__ && __APPLE__ */
+
+#define MULADDC_INIT                        \
+    asm(                                    \
+        "ld     %%r3, %3            \n\t"   \
+        "ld     %%r4, %4            \n\t"   \
+        "ld     %%r5, %5            \n\t"   \
+        "ld     %%r6, %6            \n\t"   \
+        "addi   %%r3, %%r3, -8      \n\t"   \
+        "addi   %%r4, %%r4, -8      \n\t"   \
+        "addic  %%r5, %%r5,  0      \n\t"
+
+#define MULADDC_CORE                        \
+        "ldu    %%r7, 8(%%r3)       \n\t"   \
+        "mulld  %%r8, %%r7, %%r6    \n\t"   \
+        "mulhdu %%r9, %%r7, %%r6    \n\t"   \
+        "adde   %%r8, %%r8, %%r5    \n\t"   \
+        "ld     %%r7, 8(%%r4)       \n\t"   \
+        "addze  %%r5, %%r9          \n\t"   \
+        "addc   %%r8, %%r8, %%r7    \n\t"   \
+        "stdu   %%r8, 8(%%r4)       \n\t"
+
+#define MULADDC_STOP                        \
+        "addze  %%r5, %%r5          \n\t"   \
+        "addi   %%r4, %%r4, 8       \n\t"   \
+        "addi   %%r3, %%r3, 8       \n\t"   \
+        "std    %%r5, %0            \n\t"   \
+        "std    %%r4, %1            \n\t"   \
+        "std    %%r3, %2            \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)              \
+        : "m" (s), "m" (d), "m" (c), "m" (b)        \
+        : "r3", "r4", "r5", "r6", "r7", "r8", "r9"  \
+    );
+
+#endif /* __MACH__ && __APPLE__ */
+
+#elif defined(__powerpc__) || defined(__ppc__) /* end PPC64/begin PPC32  */
+
+#if defined(__MACH__) && defined(__APPLE__)
+
+#define MULADDC_INIT                    \
+    asm(                                \
+        "lwz    r3, %3          \n\t"   \
+        "lwz    r4, %4          \n\t"   \
+        "lwz    r5, %5          \n\t"   \
+        "lwz    r6, %6          \n\t"   \
+        "addi   r3, r3, -4      \n\t"   \
+        "addi   r4, r4, -4      \n\t"   \
+        "addic  r5, r5,  0      \n\t"
+
+#define MULADDC_CORE                    \
+        "lwzu   r7, 4(r3)       \n\t"   \
+        "mullw  r8, r7, r6      \n\t"   \
+        "mulhwu r9, r7, r6      \n\t"   \
+        "adde   r8, r8, r5      \n\t"   \
+        "lwz    r7, 4(r4)       \n\t"   \
+        "addze  r5, r9          \n\t"   \
+        "addc   r8, r8, r7      \n\t"   \
+        "stwu   r8, 4(r4)       \n\t"
+
+#define MULADDC_STOP                    \
+        "addze  r5, r5          \n\t"   \
+        "addi   r4, r4, 4       \n\t"   \
+        "addi   r3, r3, 4       \n\t"   \
+        "stw    r5, %0          \n\t"   \
+        "stw    r4, %1          \n\t"   \
+        "stw    r3, %2          \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)              \
+        : "m" (s), "m" (d), "m" (c), "m" (b)        \
+        : "r3", "r4", "r5", "r6", "r7", "r8", "r9"  \
+    );
+
+#else /* __MACH__ && __APPLE__ */
+
+#define MULADDC_INIT                        \
+    asm(                                    \
+        "lwz    %%r3, %3            \n\t"   \
+        "lwz    %%r4, %4            \n\t"   \
+        "lwz    %%r5, %5            \n\t"   \
+        "lwz    %%r6, %6            \n\t"   \
+        "addi   %%r3, %%r3, -4      \n\t"   \
+        "addi   %%r4, %%r4, -4      \n\t"   \
+        "addic  %%r5, %%r5,  0      \n\t"
+
+#define MULADDC_CORE                        \
+        "lwzu   %%r7, 4(%%r3)       \n\t"   \
+        "mullw  %%r8, %%r7, %%r6    \n\t"   \
+        "mulhwu %%r9, %%r7, %%r6    \n\t"   \
+        "adde   %%r8, %%r8, %%r5    \n\t"   \
+        "lwz    %%r7, 4(%%r4)       \n\t"   \
+        "addze  %%r5, %%r9          \n\t"   \
+        "addc   %%r8, %%r8, %%r7    \n\t"   \
+        "stwu   %%r8, 4(%%r4)       \n\t"
+
+#define MULADDC_STOP                        \
+        "addze  %%r5, %%r5          \n\t"   \
+        "addi   %%r4, %%r4, 4       \n\t"   \
+        "addi   %%r3, %%r3, 4       \n\t"   \
+        "stw    %%r5, %0            \n\t"   \
+        "stw    %%r4, %1            \n\t"   \
+        "stw    %%r3, %2            \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)              \
+        : "m" (s), "m" (d), "m" (c), "m" (b)        \
+        : "r3", "r4", "r5", "r6", "r7", "r8", "r9"  \
+    );
+
+#endif /* __MACH__ && __APPLE__ */
+
+#endif /* PPC32 */
+
+/*
+ * The Sparc(64) assembly is reported to be broken.
+ * Disable it for now, until we're able to fix it.
+ */
+#if 0 && defined(__sparc__)
+#if defined(__sparc64__)
+
+#define MULADDC_INIT                                    \
+    asm(                                                \
+                "ldx     %3, %%o0               \n\t"   \
+                "ldx     %4, %%o1               \n\t"   \
+                "ld      %5, %%o2               \n\t"   \
+                "ld      %6, %%o3               \n\t"
+
+#define MULADDC_CORE                                    \
+                "ld      [%%o0], %%o4           \n\t"   \
+                "inc     4, %%o0                \n\t"   \
+                "ld      [%%o1], %%o5           \n\t"   \
+                "umul    %%o3, %%o4, %%o4       \n\t"   \
+                "addcc   %%o4, %%o2, %%o4       \n\t"   \
+                "rd      %%y, %%g1              \n\t"   \
+                "addx    %%g1, 0, %%g1          \n\t"   \
+                "addcc   %%o4, %%o5, %%o4       \n\t"   \
+                "st      %%o4, [%%o1]           \n\t"   \
+                "addx    %%g1, 0, %%o2          \n\t"   \
+                "inc     4, %%o1                \n\t"
+
+        #define MULADDC_STOP                            \
+                "st      %%o2, %0               \n\t"   \
+                "stx     %%o1, %1               \n\t"   \
+                "stx     %%o0, %2               \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)          \
+        : "m" (s), "m" (d), "m" (c), "m" (b)    \
+        : "g1", "o0", "o1", "o2", "o3", "o4",   \
+          "o5"                                  \
+        );
+
+#else /* __sparc64__ */
+
+#define MULADDC_INIT                                    \
+    asm(                                                \
+                "ld      %3, %%o0               \n\t"   \
+                "ld      %4, %%o1               \n\t"   \
+                "ld      %5, %%o2               \n\t"   \
+                "ld      %6, %%o3               \n\t"
+
+#define MULADDC_CORE                                    \
+                "ld      [%%o0], %%o4           \n\t"   \
+                "inc     4, %%o0                \n\t"   \
+                "ld      [%%o1], %%o5           \n\t"   \
+                "umul    %%o3, %%o4, %%o4       \n\t"   \
+                "addcc   %%o4, %%o2, %%o4       \n\t"   \
+                "rd      %%y, %%g1              \n\t"   \
+                "addx    %%g1, 0, %%g1          \n\t"   \
+                "addcc   %%o4, %%o5, %%o4       \n\t"   \
+                "st      %%o4, [%%o1]           \n\t"   \
+                "addx    %%g1, 0, %%o2          \n\t"   \
+                "inc     4, %%o1                \n\t"
+
+#define MULADDC_STOP                                    \
+                "st      %%o2, %0               \n\t"   \
+                "st      %%o1, %1               \n\t"   \
+                "st      %%o0, %2               \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)          \
+        : "m" (s), "m" (d), "m" (c), "m" (b)    \
+        : "g1", "o0", "o1", "o2", "o3", "o4",   \
+          "o5"                                  \
+        );
+
+#endif /* __sparc64__ */
+#endif /* __sparc__ */
+
+#if defined(__microblaze__) || defined(microblaze)
+
+#define MULADDC_INIT                    \
+    asm(                                \
+        "lwi   r3,   %3         \n\t"   \
+        "lwi   r4,   %4         \n\t"   \
+        "lwi   r5,   %5         \n\t"   \
+        "lwi   r6,   %6         \n\t"   \
+        "andi  r7,   r6, 0xffff \n\t"   \
+        "bsrli r6,   r6, 16     \n\t"
+
+#define MULADDC_CORE                    \
+        "lhui  r8,   r3,   0    \n\t"   \
+        "addi  r3,   r3,   2    \n\t"   \
+        "lhui  r9,   r3,   0    \n\t"   \
+        "addi  r3,   r3,   2    \n\t"   \
+        "mul   r10,  r9,  r6    \n\t"   \
+        "mul   r11,  r8,  r7    \n\t"   \
+        "mul   r12,  r9,  r7    \n\t"   \
+        "mul   r13,  r8,  r6    \n\t"   \
+        "bsrli  r8, r10,  16    \n\t"   \
+        "bsrli  r9, r11,  16    \n\t"   \
+        "add   r13, r13,  r8    \n\t"   \
+        "add   r13, r13,  r9    \n\t"   \
+        "bslli r10, r10,  16    \n\t"   \
+        "bslli r11, r11,  16    \n\t"   \
+        "add   r12, r12, r10    \n\t"   \
+        "addc  r13, r13,  r0    \n\t"   \
+        "add   r12, r12, r11    \n\t"   \
+        "addc  r13, r13,  r0    \n\t"   \
+        "lwi   r10,  r4,   0    \n\t"   \
+        "add   r12, r12, r10    \n\t"   \
+        "addc  r13, r13,  r0    \n\t"   \
+        "add   r12, r12,  r5    \n\t"   \
+        "addc   r5, r13,  r0    \n\t"   \
+        "swi   r12,  r4,   0    \n\t"   \
+        "addi   r4,  r4,   4    \n\t"
+
+#define MULADDC_STOP                    \
+        "swi   r5,   %0         \n\t"   \
+        "swi   r4,   %1         \n\t"   \
+        "swi   r3,   %2         \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)              \
+        : "m" (s), "m" (d), "m" (c), "m" (b)        \
+        : "r3", "r4"  "r5", "r6", "r7", "r8",       \
+          "r9", "r10", "r11", "r12", "r13"          \
+    );
+
+#endif /* MicroBlaze */
+
+#if defined(__tricore__)
+
+#define MULADDC_INIT                            \
+    asm(                                        \
+        "ld.a   %%a2, %3                \n\t"   \
+        "ld.a   %%a3, %4                \n\t"   \
+        "ld.w   %%d4, %5                \n\t"   \
+        "ld.w   %%d1, %6                \n\t"   \
+        "xor    %%d5, %%d5              \n\t"
+
+#define MULADDC_CORE                            \
+        "ld.w   %%d0,   [%%a2+]         \n\t"   \
+        "madd.u %%e2, %%e4, %%d0, %%d1  \n\t"   \
+        "ld.w   %%d0,   [%%a3]          \n\t"   \
+        "addx   %%d2,    %%d2,  %%d0    \n\t"   \
+        "addc   %%d3,    %%d3,    0     \n\t"   \
+        "mov    %%d4,    %%d3           \n\t"   \
+        "st.w  [%%a3+],  %%d2           \n\t"
+
+#define MULADDC_STOP                            \
+        "st.w   %0, %%d4                \n\t"   \
+        "st.a   %1, %%a3                \n\t"   \
+        "st.a   %2, %%a2                \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)          \
+        : "m" (s), "m" (d), "m" (c), "m" (b)    \
+        : "d0", "d1", "e2", "d4", "a2", "a3"    \
+    );
+
+#endif /* TriCore */
+
+/*
+ * gcc -O0 by default uses r7 for the frame pointer, so it complains about our
+ * use of r7 below, unless -fomit-frame-pointer is passed. Unfortunately,
+ * passing that option is not easy when building with yotta.
+ *
+ * On the other hand, -fomit-frame-pointer is implied by any -Ox options with
+ * x !=0, which we can detect using __OPTIMIZE__ (which is also defined by
+ * clang and armcc5 under the same conditions).
+ *
+ * So, only use the optimized assembly below for optimized build, which avoids
+ * the build error and is pretty reasonable anyway.
+ */
+#if defined(__GNUC__) && !defined(__OPTIMIZE__)
+#define MULADDC_CANNOT_USE_R7
+#endif
+
+#if defined(__arm__) && !defined(MULADDC_CANNOT_USE_R7)
+
+#if defined(__thumb__) && !defined(__thumb2__)
+
+#define MULADDC_INIT                                    \
+    asm(                                                \
+            "ldr    r0, %3                      \n\t"   \
+            "ldr    r1, %4                      \n\t"   \
+            "ldr    r2, %5                      \n\t"   \
+            "ldr    r3, %6                      \n\t"   \
+            "lsr    r7, r3, #16                 \n\t"   \
+            "mov    r9, r7                      \n\t"   \
+            "lsl    r7, r3, #16                 \n\t"   \
+            "lsr    r7, r7, #16                 \n\t"   \
+            "mov    r8, r7                      \n\t"
+
+#define MULADDC_CORE                                    \
+            "ldmia  r0!, {r6}                   \n\t"   \
+            "lsr    r7, r6, #16                 \n\t"   \
+            "lsl    r6, r6, #16                 \n\t"   \
+            "lsr    r6, r6, #16                 \n\t"   \
+            "mov    r4, r8                      \n\t"   \
+            "mul    r4, r6                      \n\t"   \
+            "mov    r3, r9                      \n\t"   \
+            "mul    r6, r3                      \n\t"   \
+            "mov    r5, r9                      \n\t"   \
+            "mul    r5, r7                      \n\t"   \
+            "mov    r3, r8                      \n\t"   \
+            "mul    r7, r3                      \n\t"   \
+            "lsr    r3, r6, #16                 \n\t"   \
+            "add    r5, r5, r3                  \n\t"   \
+            "lsr    r3, r7, #16                 \n\t"   \
+            "add    r5, r5, r3                  \n\t"   \
+            "add    r4, r4, r2                  \n\t"   \
+            "mov    r2, #0                      \n\t"   \
+            "adc    r5, r2                      \n\t"   \
+            "lsl    r3, r6, #16                 \n\t"   \
+            "add    r4, r4, r3                  \n\t"   \
+            "adc    r5, r2                      \n\t"   \
+            "lsl    r3, r7, #16                 \n\t"   \
+            "add    r4, r4, r3                  \n\t"   \
+            "adc    r5, r2                      \n\t"   \
+            "ldr    r3, [r1]                    \n\t"   \
+            "add    r4, r4, r3                  \n\t"   \
+            "adc    r2, r5                      \n\t"   \
+            "stmia  r1!, {r4}                   \n\t"
+
+#define MULADDC_STOP                                    \
+            "str    r2, %0                      \n\t"   \
+            "str    r1, %1                      \n\t"   \
+            "str    r0, %2                      \n\t"   \
+         : "=m" (c),  "=m" (d), "=m" (s)        \
+         : "m" (s), "m" (d), "m" (c), "m" (b)   \
+         : "r0", "r1", "r2", "r3", "r4", "r5",  \
+           "r6", "r7", "r8", "r9", "cc"         \
+         );
+
+#else
+
+#define MULADDC_INIT                                    \
+    asm(                                                \
+            "ldr    r0, %3                      \n\t"   \
+            "ldr    r1, %4                      \n\t"   \
+            "ldr    r2, %5                      \n\t"   \
+            "ldr    r3, %6                      \n\t"
+
+#define MULADDC_CORE                                    \
+            "ldr    r4, [r0], #4                \n\t"   \
+            "mov    r5, #0                      \n\t"   \
+            "ldr    r6, [r1]                    \n\t"   \
+            "umlal  r2, r5, r3, r4              \n\t"   \
+            "adds   r7, r6, r2                  \n\t"   \
+            "adc    r2, r5, #0                  \n\t"   \
+            "str    r7, [r1], #4                \n\t"
+
+#define MULADDC_STOP                                    \
+            "str    r2, %0                      \n\t"   \
+            "str    r1, %1                      \n\t"   \
+            "str    r0, %2                      \n\t"   \
+         : "=m" (c),  "=m" (d), "=m" (s)        \
+         : "m" (s), "m" (d), "m" (c), "m" (b)   \
+         : "r0", "r1", "r2", "r3", "r4", "r5",  \
+           "r6", "r7", "cc"                     \
+         );
+
+#endif /* Thumb */
+
+#endif /* ARMv3 */
+
+#if defined(__alpha__)
+
+#define MULADDC_INIT                    \
+    asm(                                \
+        "ldq    $1, %3          \n\t"   \
+        "ldq    $2, %4          \n\t"   \
+        "ldq    $3, %5          \n\t"   \
+        "ldq    $4, %6          \n\t"
+
+#define MULADDC_CORE                    \
+        "ldq    $6,  0($1)      \n\t"   \
+        "addq   $1,  8, $1      \n\t"   \
+        "mulq   $6, $4, $7      \n\t"   \
+        "umulh  $6, $4, $6      \n\t"   \
+        "addq   $7, $3, $7      \n\t"   \
+        "cmpult $7, $3, $3      \n\t"   \
+        "ldq    $5,  0($2)      \n\t"   \
+        "addq   $7, $5, $7      \n\t"   \
+        "cmpult $7, $5, $5      \n\t"   \
+        "stq    $7,  0($2)      \n\t"   \
+        "addq   $2,  8, $2      \n\t"   \
+        "addq   $6, $3, $3      \n\t"   \
+        "addq   $5, $3, $3      \n\t"
+
+#define MULADDC_STOP                                    \
+        "stq    $3, %0          \n\t"   \
+        "stq    $2, %1          \n\t"   \
+        "stq    $1, %2          \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)              \
+        : "m" (s), "m" (d), "m" (c), "m" (b)        \
+        : "$1", "$2", "$3", "$4", "$5", "$6", "$7"  \
+    );
+#endif /* Alpha */
+
+#if defined(__mips__) && !defined(__mips64)
+
+#define MULADDC_INIT                    \
+    asm(                                \
+        "lw     $10, %3         \n\t"   \
+        "lw     $11, %4         \n\t"   \
+        "lw     $12, %5         \n\t"   \
+        "lw     $13, %6         \n\t"
+
+#define MULADDC_CORE                    \
+        "lw     $14, 0($10)     \n\t"   \
+        "multu  $13, $14        \n\t"   \
+        "addi   $10, $10, 4     \n\t"   \
+        "mflo   $14             \n\t"   \
+        "mfhi   $9              \n\t"   \
+        "addu   $14, $12, $14   \n\t"   \
+        "lw     $15, 0($11)     \n\t"   \
+        "sltu   $12, $14, $12   \n\t"   \
+        "addu   $15, $14, $15   \n\t"   \
+        "sltu   $14, $15, $14   \n\t"   \
+        "addu   $12, $12, $9    \n\t"   \
+        "sw     $15, 0($11)     \n\t"   \
+        "addu   $12, $12, $14   \n\t"   \
+        "addi   $11, $11, 4     \n\t"
+
+#define MULADDC_STOP                    \
+        "sw     $12, %0         \n\t"   \
+        "sw     $11, %1         \n\t"   \
+        "sw     $10, %2         \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)                      \
+        : "m" (s), "m" (d), "m" (c), "m" (b)                \
+        : "$9", "$10", "$11", "$12", "$13", "$14", "$15"    \
+    );
+
+#endif /* MIPS */
+#endif /* GNUC */
+
+#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
+
+#define MULADDC_INIT                            \
+    __asm   mov     esi, s                      \
+    __asm   mov     edi, d                      \
+    __asm   mov     ecx, c                      \
+    __asm   mov     ebx, b
+
+#define MULADDC_CORE                            \
+    __asm   lodsd                               \
+    __asm   mul     ebx                         \
+    __asm   add     eax, ecx                    \
+    __asm   adc     edx, 0                      \
+    __asm   add     eax, [edi]                  \
+    __asm   adc     edx, 0                      \
+    __asm   mov     ecx, edx                    \
+    __asm   stosd
+
+#if defined(MBEDCRYPTO_HAVE_SSE2)
+
+#define EMIT __asm _emit
+
+#define MULADDC_HUIT                            \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0xC9             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0xC3             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x1F             \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCB             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x16             \
+    EMIT 0x0F  EMIT 0xF4  EMIT 0xD0             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x66  EMIT 0x04  \
+    EMIT 0x0F  EMIT 0xF4  EMIT 0xE0             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x76  EMIT 0x08  \
+    EMIT 0x0F  EMIT 0xF4  EMIT 0xF0             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x7E  EMIT 0x0C  \
+    EMIT 0x0F  EMIT 0xF4  EMIT 0xF8             \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCA             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x5F  EMIT 0x04  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xDC             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x08  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xEE             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x67  EMIT 0x0C  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xFC             \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0x0F             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x56  EMIT 0x10  \
+    EMIT 0x0F  EMIT 0xF4  EMIT 0xD0             \
+    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x66  EMIT 0x14  \
+    EMIT 0x0F  EMIT 0xF4  EMIT 0xE0             \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCB             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x76  EMIT 0x18  \
+    EMIT 0x0F  EMIT 0xF4  EMIT 0xF0             \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x04  \
+    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x5E  EMIT 0x1C  \
+    EMIT 0x0F  EMIT 0xF4  EMIT 0xD8             \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCD             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x10  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xD5             \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x08  \
+    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCF             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x14  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xE5             \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x0C  \
+    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCA             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x18  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xF5             \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x10  \
+    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCC             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x1C  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xDD             \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x14  \
+    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCE             \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x18  \
+    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCB             \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x1C  \
+    EMIT 0x83  EMIT 0xC7  EMIT 0x20             \
+    EMIT 0x83  EMIT 0xC6  EMIT 0x20             \
+    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0xC9
+
+#define MULADDC_STOP                            \
+    EMIT 0x0F  EMIT 0x77                        \
+    __asm   mov     c, ecx                      \
+    __asm   mov     d, edi                      \
+    __asm   mov     s, esi                      \
+
+#else
+
+#define MULADDC_STOP                            \
+    __asm   mov     c, ecx                      \
+    __asm   mov     d, edi                      \
+    __asm   mov     s, esi                      \
+
+#endif /* SSE2 */
+#endif /* MSVC */
+
+#endif /* MBEDCRYPTO_HAVE_ASM */
+
+#if !defined(MULADDC_CORE)
+#if defined(MBEDCRYPTO_HAVE_UDBL)
+
+#define MULADDC_INIT                    \
+{                                       \
+    mbedcrypto_t_udbl r;                           \
+    mbedcrypto_mpi_uint r0, r1;
+
+#define MULADDC_CORE                    \
+    r   = *(s++) * (mbedcrypto_t_udbl) b;          \
+    r0  = (mbedcrypto_mpi_uint) r;                   \
+    r1  = (mbedcrypto_mpi_uint)( r >> biL );         \
+    r0 += c;  r1 += (r0 <  c);          \
+    r0 += *d; r1 += (r0 < *d);          \
+    c = r1; *(d++) = r0;
+
+#define MULADDC_STOP                    \
+}
+
+#else
+#define MULADDC_INIT                    \
+{                                       \
+    mbedcrypto_mpi_uint s0, s1, b0, b1;              \
+    mbedcrypto_mpi_uint r0, r1, rx, ry;              \
+    b0 = ( b << biH ) >> biH;           \
+    b1 = ( b >> biH );
+
+#define MULADDC_CORE                    \
+    s0 = ( *s << biH ) >> biH;          \
+    s1 = ( *s >> biH ); s++;            \
+    rx = s0 * b1; r0 = s0 * b0;         \
+    ry = s1 * b0; r1 = s1 * b1;         \
+    r1 += ( rx >> biH );                \
+    r1 += ( ry >> biH );                \
+    rx <<= biH; ry <<= biH;             \
+    r0 += rx; r1 += (r0 < rx);          \
+    r0 += ry; r1 += (r0 < ry);          \
+    r0 +=  c; r1 += (r0 <  c);          \
+    r0 += *d; r1 += (r0 < *d);          \
+    c = r1; *(d++) = r0;
+
+#define MULADDC_STOP                    \
+}
+
+#endif /* C (generic)  */
+#endif /* C (longlong) */
+
+#endif /* bn_mul.h */
diff --git a/include/mbedcrypto/camellia.h b/include/mbedcrypto/camellia.h
new file mode 100644
index 0000000..21607e2
--- /dev/null
+++ b/include/mbedcrypto/camellia.h
@@ -0,0 +1,229 @@
+/**
+ * \file camellia.h
+ *
+ * \brief Camellia block cipher
+ */
+/*
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_CAMELLIA_H
+#define MBEDCRYPTO_CAMELLIA_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+#define MBEDCRYPTO_CAMELLIA_ENCRYPT     1
+#define MBEDCRYPTO_CAMELLIA_DECRYPT     0
+
+#define MBEDCRYPTO_ERR_CAMELLIA_INVALID_KEY_LENGTH           -0x0024  /**< Invalid key length. */
+#define MBEDCRYPTO_ERR_CAMELLIA_INVALID_INPUT_LENGTH         -0x0026  /**< Invalid data input length. */
+#define MBEDCRYPTO_ERR_CAMELLIA_HW_ACCEL_FAILED              -0x0027  /**< Camellia hardware accelerator failed. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDCRYPTO_CAMELLIA_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief          CAMELLIA context structure
+ */
+typedef struct
+{
+    int nr;                     /*!<  number of rounds  */
+    uint32_t rk[68];            /*!<  CAMELLIA round keys    */
+}
+mbedcrypto_camellia_context;
+
+#else  /* MBEDCRYPTO_CAMELLIA_ALT */
+#include "camellia_alt.h"
+#endif /* MBEDCRYPTO_CAMELLIA_ALT */
+
+/**
+ * \brief          Initialize CAMELLIA context
+ *
+ * \param ctx      CAMELLIA context to be initialized
+ */
+void mbedcrypto_camellia_init( mbedcrypto_camellia_context *ctx );
+
+/**
+ * \brief          Clear CAMELLIA context
+ *
+ * \param ctx      CAMELLIA context to be cleared
+ */
+void mbedcrypto_camellia_free( mbedcrypto_camellia_context *ctx );
+
+/**
+ * \brief          CAMELLIA key schedule (encryption)
+ *
+ * \param ctx      CAMELLIA context to be initialized
+ * \param key      encryption key
+ * \param keybits  must be 128, 192 or 256
+ *
+ * \return         0 if successful, or MBEDCRYPTO_ERR_CAMELLIA_INVALID_KEY_LENGTH
+ */
+int mbedcrypto_camellia_setkey_enc( mbedcrypto_camellia_context *ctx, const unsigned char *key,
+                         unsigned int keybits );
+
+/**
+ * \brief          CAMELLIA key schedule (decryption)
+ *
+ * \param ctx      CAMELLIA context to be initialized
+ * \param key      decryption key
+ * \param keybits  must be 128, 192 or 256
+ *
+ * \return         0 if successful, or MBEDCRYPTO_ERR_CAMELLIA_INVALID_KEY_LENGTH
+ */
+int mbedcrypto_camellia_setkey_dec( mbedcrypto_camellia_context *ctx, const unsigned char *key,
+                         unsigned int keybits );
+
+/**
+ * \brief          CAMELLIA-ECB block encryption/decryption
+ *
+ * \param ctx      CAMELLIA context
+ * \param mode     MBEDCRYPTO_CAMELLIA_ENCRYPT or MBEDCRYPTO_CAMELLIA_DECRYPT
+ * \param input    16-byte input block
+ * \param output   16-byte output block
+ *
+ * \return         0 if successful
+ */
+int mbedcrypto_camellia_crypt_ecb( mbedcrypto_camellia_context *ctx,
+                    int mode,
+                    const unsigned char input[16],
+                    unsigned char output[16] );
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+/**
+ * \brief          CAMELLIA-CBC buffer encryption/decryption
+ *                 Length should be a multiple of the block
+ *                 size (16 bytes)
+ *
+ * \note           Upon exit, the content of the IV is updated so that you can
+ *                 call the function same function again on the following
+ *                 block(s) of data and get the same result as if it was
+ *                 encrypted in one call. This allows a "streaming" usage.
+ *                 If on the other hand you need to retain the contents of the
+ *                 IV, you should either save it manually or use the cipher
+ *                 module instead.
+ *
+ * \param ctx      CAMELLIA context
+ * \param mode     MBEDCRYPTO_CAMELLIA_ENCRYPT or MBEDCRYPTO_CAMELLIA_DECRYPT
+ * \param length   length of the input data
+ * \param iv       initialization vector (updated after use)
+ * \param input    buffer holding the input data
+ * \param output   buffer holding the output data
+ *
+ * \return         0 if successful, or
+ *                 MBEDCRYPTO_ERR_CAMELLIA_INVALID_INPUT_LENGTH
+ */
+int mbedcrypto_camellia_crypt_cbc( mbedcrypto_camellia_context *ctx,
+                    int mode,
+                    size_t length,
+                    unsigned char iv[16],
+                    const unsigned char *input,
+                    unsigned char *output );
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+/**
+ * \brief          CAMELLIA-CFB128 buffer encryption/decryption
+ *
+ * Note: Due to the nature of CFB you should use the same key schedule for
+ * both encryption and decryption. So a context initialized with
+ * mbedcrypto_camellia_setkey_enc() for both MBEDCRYPTO_CAMELLIA_ENCRYPT and CAMELLIE_DECRYPT.
+ *
+ * \note           Upon exit, the content of the IV is updated so that you can
+ *                 call the function same function again on the following
+ *                 block(s) of data and get the same result as if it was
+ *                 encrypted in one call. This allows a "streaming" usage.
+ *                 If on the other hand you need to retain the contents of the
+ *                 IV, you should either save it manually or use the cipher
+ *                 module instead.
+ *
+ * \param ctx      CAMELLIA context
+ * \param mode     MBEDCRYPTO_CAMELLIA_ENCRYPT or MBEDCRYPTO_CAMELLIA_DECRYPT
+ * \param length   length of the input data
+ * \param iv_off   offset in IV (updated after use)
+ * \param iv       initialization vector (updated after use)
+ * \param input    buffer holding the input data
+ * \param output   buffer holding the output data
+ *
+ * \return         0 if successful, or
+ *                 MBEDCRYPTO_ERR_CAMELLIA_INVALID_INPUT_LENGTH
+ */
+int mbedcrypto_camellia_crypt_cfb128( mbedcrypto_camellia_context *ctx,
+                       int mode,
+                       size_t length,
+                       size_t *iv_off,
+                       unsigned char iv[16],
+                       const unsigned char *input,
+                       unsigned char *output );
+#endif /* MBEDCRYPTO_CIPHER_MODE_CFB */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+/**
+ * \brief               CAMELLIA-CTR buffer encryption/decryption
+ *
+ * Warning: You have to keep the maximum use of your counter in mind!
+ *
+ * Note: Due to the nature of CTR you should use the same key schedule for
+ * both encryption and decryption. So a context initialized with
+ * mbedcrypto_camellia_setkey_enc() for both MBEDCRYPTO_CAMELLIA_ENCRYPT and MBEDCRYPTO_CAMELLIA_DECRYPT.
+ *
+ * \param ctx           CAMELLIA context
+ * \param length        The length of the data
+ * \param nc_off        The offset in the current stream_block (for resuming
+ *                      within current cipher stream). The offset pointer to
+ *                      should be 0 at the start of a stream.
+ * \param nonce_counter The 128-bit nonce and counter.
+ * \param stream_block  The saved stream-block for resuming. Is overwritten
+ *                      by the function.
+ * \param input         The input data stream
+ * \param output        The output data stream
+ *
+ * \return         0 if successful
+ */
+int mbedcrypto_camellia_crypt_ctr( mbedcrypto_camellia_context *ctx,
+                       size_t length,
+                       size_t *nc_off,
+                       unsigned char nonce_counter[16],
+                       unsigned char stream_block[16],
+                       const unsigned char *input,
+                       unsigned char *output );
+#endif /* MBEDCRYPTO_CIPHER_MODE_CTR */
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int mbedcrypto_camellia_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* camellia.h */
diff --git a/include/mbedcrypto/ccm.h b/include/mbedcrypto/ccm.h
new file mode 100644
index 0000000..14e178e
--- /dev/null
+++ b/include/mbedcrypto/ccm.h
@@ -0,0 +1,178 @@
+/**
+ * \file ccm.h
+ *
+ * \brief This file provides an API for the CCM authenticated encryption
+ *        mode for block ciphers.
+ *
+ * CCM combines Counter mode encryption with CBC-MAC authentication
+ * for 128-bit block ciphers.
+ *
+ * Input to CCM includes the following elements:
+ * <ul><li>Payload - data that is both authenticated and encrypted.</li>
+ * <li>Associated data (Adata) - data that is authenticated but not
+ * encrypted, For example, a header.</li>
+ * <li>Nonce - A unique value that is assigned to the payload and the
+ * associated data.</li></ul>
+ *
+ */
+/*
+ *  Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#ifndef MBEDCRYPTO_CCM_H
+#define MBEDCRYPTO_CCM_H
+
+#include "cipher.h"
+
+#define MBEDCRYPTO_ERR_CCM_BAD_INPUT       -0x000D /**< Bad input parameters to the function. */
+#define MBEDCRYPTO_ERR_CCM_AUTH_FAILED     -0x000F /**< Authenticated decryption failed. */
+#define MBEDCRYPTO_ERR_CCM_HW_ACCEL_FAILED -0x0011 /**< CCM hardware accelerator failed. */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDCRYPTO_CCM_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief    The CCM context-type definition. The CCM context is passed
+ *           to the APIs called.
+ */
+typedef struct {
+    mbedcrypto_cipher_context_t cipher_ctx;    /*!< The cipher context used. */
+}
+mbedcrypto_ccm_context;
+
+#else  /* MBEDCRYPTO_CCM_ALT */
+#include "ccm_alt.h"
+#endif /* MBEDCRYPTO_CCM_ALT */
+
+/**
+ * \brief           This function initializes the specified CCM context,
+ *                  to make references valid, and prepare the context
+ *                  for mbedcrypto_ccm_setkey() or mbedcrypto_ccm_free().
+ *
+ * \param ctx       The CCM context to initialize.
+ */
+void mbedcrypto_ccm_init( mbedcrypto_ccm_context *ctx );
+
+/**
+ * \brief           This function initializes the CCM context set in the
+ *                  \p ctx parameter and sets the encryption key.
+ *
+ * \param ctx       The CCM context to initialize.
+ * \param cipher    The 128-bit block cipher to use.
+ * \param key       The encryption key.
+ * \param keybits   The key size in bits. This must be acceptable by the cipher.
+ *
+ * \return          \c 0 on success.
+ * \return          A CCM or cipher-specific error code on failure.
+ */
+int mbedcrypto_ccm_setkey( mbedcrypto_ccm_context *ctx,
+                        mbedcrypto_cipher_id_t cipher,
+                        const unsigned char *key,
+                        unsigned int keybits );
+
+/**
+ * \brief   This function releases and clears the specified CCM context
+ *          and underlying cipher sub-context.
+ *
+ * \param ctx       The CCM context to clear.
+ */
+void mbedcrypto_ccm_free( mbedcrypto_ccm_context *ctx );
+
+/**
+ * \brief           This function encrypts a buffer using CCM.
+ *
+ *
+ * \note            The tag is written to a separate buffer. To concatenate
+ *                  the \p tag with the \p output, as done in <em>RFC-3610:
+ *                  Counter with CBC-MAC (CCM)</em>, use
+ *                  \p tag = \p output + \p length, and make sure that the
+ *                  output buffer is at least \p length + \p tag_len wide.
+ *
+ * \param ctx       The CCM context to use for encryption.
+ * \param length    The length of the input data in Bytes.
+ * \param iv        Initialization vector (nonce).
+ * \param iv_len    The length of the IV in Bytes: 7, 8, 9, 10, 11, 12, or 13.
+ * \param add       The additional data field.
+ * \param add_len   The length of additional data in Bytes.
+ *                  Must be less than 2^16 - 2^8.
+ * \param input     The buffer holding the input data.
+ * \param output    The buffer holding the output data.
+ *                  Must be at least \p length Bytes wide.
+ * \param tag       The buffer holding the tag.
+ * \param tag_len   The length of the tag to generate in Bytes:
+ *                  4, 6, 8, 10, 12, 14 or 16.
+ *
+ * \return          \c 0 on success.
+ * \return          A CCM or cipher-specific error code on failure.
+ */
+int mbedcrypto_ccm_encrypt_and_tag( mbedcrypto_ccm_context *ctx, 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,
+                         unsigned char *tag, size_t tag_len );
+
+/**
+ * \brief           This function performs a CCM authenticated decryption of a
+ *                  buffer.
+ *
+ * \param ctx       The CCM context to use for decryption.
+ * \param length    The length of the input data in Bytes.
+ * \param iv        Initialization vector.
+ * \param iv_len    The length of the IV in Bytes: 7, 8, 9, 10, 11, 12, or 13.
+ * \param add       The additional data field.
+ * \param add_len   The length of additional data in Bytes.
+ *                  Must be less than 2^16 - 2^8.
+ * \param input     The buffer holding the input data.
+ * \param output    The buffer holding the output data.
+ *                  Must be at least \p length Bytes wide.
+ * \param tag       The buffer holding the tag.
+ * \param tag_len   The length of the tag in Bytes.
+ *                  4, 6, 8, 10, 12, 14 or 16.
+ *
+ * \return          \c 0 on success. This indicates that the message is authentic.
+ * \return          #MBEDCRYPTO_ERR_CCM_AUTH_FAILED if the tag does not match.
+ * \return          A cipher-specific error code on calculation failure.
+ */
+int mbedcrypto_ccm_auth_decrypt( mbedcrypto_ccm_context *ctx, 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,
+                      const unsigned char *tag, size_t tag_len );
+
+
+#if defined(MBEDCRYPTO_SELF_TEST) && defined(MBEDCRYPTO_AES_C)
+/**
+ * \brief          The CCM checkup routine.
+ *
+ * \return         \c 0 on success.
+ * \return         \c 1 on failure.
+ */
+int mbedcrypto_ccm_self_test( int verbose );
+#endif /* MBEDCRYPTO_SELF_TEST && MBEDCRYPTO_AES_C */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDCRYPTO_CCM_H */
diff --git a/include/mbedcrypto/certs.h b/include/mbedcrypto/certs.h
new file mode 100644
index 0000000..c4d27e9
--- /dev/null
+++ b/include/mbedcrypto/certs.h
@@ -0,0 +1,100 @@
+/**
+ * \file certs.h
+ *
+ * \brief Sample certificates and DHM parameters for testing
+ */
+/*
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_CERTS_H
+#define MBEDCRYPTO_CERTS_H
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(MBEDCRYPTO_PEM_PARSE_C)
+/* Concatenation of all CA certificates in PEM format if available */
+extern const char   mbedcrypto_test_cas_pem[];
+extern const size_t mbedcrypto_test_cas_pem_len;
+#endif
+
+/* List of all CA certificates, terminated by NULL */
+extern const char * mbedcrypto_test_cas[];
+extern const size_t mbedcrypto_test_cas_len[];
+
+/*
+ * Convenience for users who just want a certificate:
+ * RSA by default, or ECDSA if RSA is not available
+ */
+extern const char * mbedcrypto_test_ca_crt;
+extern const size_t mbedcrypto_test_ca_crt_len;
+extern const char * mbedcrypto_test_ca_key;
+extern const size_t mbedcrypto_test_ca_key_len;
+extern const char * mbedcrypto_test_ca_pwd;
+extern const size_t mbedcrypto_test_ca_pwd_len;
+extern const char * mbedcrypto_test_srv_crt;
+extern const size_t mbedcrypto_test_srv_crt_len;
+extern const char * mbedcrypto_test_srv_key;
+extern const size_t mbedcrypto_test_srv_key_len;
+extern const char * mbedcrypto_test_cli_crt;
+extern const size_t mbedcrypto_test_cli_crt_len;
+extern const char * mbedcrypto_test_cli_key;
+extern const size_t mbedcrypto_test_cli_key_len;
+
+#if defined(MBEDCRYPTO_ECDSA_C)
+extern const char   mbedcrypto_test_ca_crt_ec[];
+extern const size_t mbedcrypto_test_ca_crt_ec_len;
+extern const char   mbedcrypto_test_ca_key_ec[];
+extern const size_t mbedcrypto_test_ca_key_ec_len;
+extern const char   mbedcrypto_test_ca_pwd_ec[];
+extern const size_t mbedcrypto_test_ca_pwd_ec_len;
+extern const char   mbedcrypto_test_srv_crt_ec[];
+extern const size_t mbedcrypto_test_srv_crt_ec_len;
+extern const char   mbedcrypto_test_srv_key_ec[];
+extern const size_t mbedcrypto_test_srv_key_ec_len;
+extern const char   mbedcrypto_test_cli_crt_ec[];
+extern const size_t mbedcrypto_test_cli_crt_ec_len;
+extern const char   mbedcrypto_test_cli_key_ec[];
+extern const size_t mbedcrypto_test_cli_key_ec_len;
+#endif
+
+#if defined(MBEDCRYPTO_RSA_C)
+extern const char   mbedcrypto_test_ca_crt_rsa[];
+extern const size_t mbedcrypto_test_ca_crt_rsa_len;
+extern const char   mbedcrypto_test_ca_key_rsa[];
+extern const size_t mbedcrypto_test_ca_key_rsa_len;
+extern const char   mbedcrypto_test_ca_pwd_rsa[];
+extern const size_t mbedcrypto_test_ca_pwd_rsa_len;
+extern const char   mbedcrypto_test_srv_crt_rsa[];
+extern const size_t mbedcrypto_test_srv_crt_rsa_len;
+extern const char   mbedcrypto_test_srv_key_rsa[];
+extern const size_t mbedcrypto_test_srv_key_rsa_len;
+extern const char   mbedcrypto_test_cli_crt_rsa[];
+extern const size_t mbedcrypto_test_cli_crt_rsa_len;
+extern const char   mbedcrypto_test_cli_key_rsa[];
+extern const size_t mbedcrypto_test_cli_key_rsa_len;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* certs.h */
diff --git a/include/mbedcrypto/check_config.h b/include/mbedcrypto/check_config.h
new file mode 100644
index 0000000..9948f0e
--- /dev/null
+++ b/include/mbedcrypto/check_config.h
@@ -0,0 +1,684 @@
+/**
+ * \file check_config.h
+ *
+ * \brief Consistency checks for configuration options
+ */
+/*
+ *  Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+/*
+ * It is recommended to include this file from your config.h
+ * in order to catch dependency issues early.
+ */
+
+#ifndef MBEDCRYPTO_CHECK_CONFIG_H
+#define MBEDCRYPTO_CHECK_CONFIG_H
+
+/*
+ * We assume CHAR_BIT is 8 in many places. In practice, this is true on our
+ * target platforms, so not an issue, but let's just be extra sure.
+ */
+#include <limits.h>
+#if CHAR_BIT != 8
+#error "Mbed Crypto requires a platform with 8-bit chars"
+#endif
+
+#if defined(_WIN32)
+#if !defined(MBEDCRYPTO_PLATFORM_C)
+#error "MBEDCRYPTO_PLATFORM_C is required on Windows"
+#endif
+
+/* Fix the config here. Not convenient to put an #ifdef _WIN32 in config.h as
+ * it would confuse config.pl. */
+#if !defined(MBEDCRYPTO_PLATFORM_SNPRINTF_ALT) && \
+    !defined(MBEDCRYPTO_PLATFORM_SNPRINTF_MACRO)
+#define MBEDCRYPTO_PLATFORM_SNPRINTF_ALT
+#endif
+#endif /* _WIN32 */
+
+#if defined(TARGET_LIKE_MBED) && \
+    ( defined(MBEDCRYPTO_NET_C) || defined(MBEDCRYPTO_TIMING_C) )
+#error "The NET and TIMING modules are not available for mbed OS - please use the network and timing functions provided by mbed OS"
+#endif
+
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING) && \
+    !defined(__GNUC__) && !defined(__clang__)
+#error "MBEDCRYPTO_DEPRECATED_WARNING only works with GCC and Clang"
+#endif
+
+#if defined(MBEDCRYPTO_HAVE_TIME_DATE) && !defined(MBEDCRYPTO_HAVE_TIME)
+#error "MBEDCRYPTO_HAVE_TIME_DATE without MBEDCRYPTO_HAVE_TIME does not make sense"
+#endif
+
+#if defined(MBEDCRYPTO_AESNI_C) && !defined(MBEDCRYPTO_HAVE_ASM)
+#error "MBEDCRYPTO_AESNI_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_CTR_DRBG_C) && !defined(MBEDCRYPTO_AES_C)
+#error "MBEDCRYPTO_CTR_DRBG_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_DHM_C) && !defined(MBEDCRYPTO_BIGNUM_C)
+#error "MBEDCRYPTO_DHM_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_TRUNCATED_HMAC_COMPAT) && !defined(MBEDCRYPTO_SSL_TRUNCATED_HMAC)
+#error "MBEDCRYPTO_SSL_TRUNCATED_HMAC_COMPAT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_CMAC_C) && \
+    !defined(MBEDCRYPTO_AES_C) && !defined(MBEDCRYPTO_DES_C)
+#error "MBEDCRYPTO_CMAC_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_ECDH_C) && !defined(MBEDCRYPTO_ECP_C)
+#error "MBEDCRYPTO_ECDH_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_ECDSA_C) &&            \
+    ( !defined(MBEDCRYPTO_ECP_C) ||           \
+      !defined(MBEDCRYPTO_ASN1_PARSE_C) ||    \
+      !defined(MBEDCRYPTO_ASN1_WRITE_C) )
+#error "MBEDCRYPTO_ECDSA_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_ECJPAKE_C) &&           \
+    ( !defined(MBEDCRYPTO_ECP_C) || !defined(MBEDCRYPTO_MD_C) )
+#error "MBEDCRYPTO_ECJPAKE_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_ECDSA_DETERMINISTIC) && !defined(MBEDCRYPTO_HMAC_DRBG_C)
+#error "MBEDCRYPTO_ECDSA_DETERMINISTIC defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_ECP_C) && ( !defined(MBEDCRYPTO_BIGNUM_C) || (   \
+    !defined(MBEDCRYPTO_ECP_DP_SECP192R1_ENABLED) &&                  \
+    !defined(MBEDCRYPTO_ECP_DP_SECP224R1_ENABLED) &&                  \
+    !defined(MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED) &&                  \
+    !defined(MBEDCRYPTO_ECP_DP_SECP384R1_ENABLED) &&                  \
+    !defined(MBEDCRYPTO_ECP_DP_SECP521R1_ENABLED) &&                  \
+    !defined(MBEDCRYPTO_ECP_DP_BP256R1_ENABLED)   &&                  \
+    !defined(MBEDCRYPTO_ECP_DP_BP384R1_ENABLED)   &&                  \
+    !defined(MBEDCRYPTO_ECP_DP_BP512R1_ENABLED)   &&                  \
+    !defined(MBEDCRYPTO_ECP_DP_SECP192K1_ENABLED) &&                  \
+    !defined(MBEDCRYPTO_ECP_DP_SECP224K1_ENABLED) &&                  \
+    !defined(MBEDCRYPTO_ECP_DP_SECP256K1_ENABLED) ) )
+#error "MBEDCRYPTO_ECP_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_ENTROPY_C) && (!defined(MBEDCRYPTO_SHA512_C) &&      \
+                                    !defined(MBEDCRYPTO_SHA256_C))
+#error "MBEDCRYPTO_ENTROPY_C defined, but not all prerequisites"
+#endif
+#if defined(MBEDCRYPTO_ENTROPY_C) && defined(MBEDCRYPTO_SHA512_C) &&         \
+    defined(MBEDCRYPTO_CTR_DRBG_ENTROPY_LEN) && (MBEDCRYPTO_CTR_DRBG_ENTROPY_LEN > 64)
+#error "MBEDCRYPTO_CTR_DRBG_ENTROPY_LEN value too high"
+#endif
+#if defined(MBEDCRYPTO_ENTROPY_C) &&                                            \
+    ( !defined(MBEDCRYPTO_SHA512_C) || defined(MBEDCRYPTO_ENTROPY_FORCE_SHA256) ) \
+    && defined(MBEDCRYPTO_CTR_DRBG_ENTROPY_LEN) && (MBEDCRYPTO_CTR_DRBG_ENTROPY_LEN > 32)
+#error "MBEDCRYPTO_CTR_DRBG_ENTROPY_LEN value too high"
+#endif
+#if defined(MBEDCRYPTO_ENTROPY_C) && \
+    defined(MBEDCRYPTO_ENTROPY_FORCE_SHA256) && !defined(MBEDCRYPTO_SHA256_C)
+#error "MBEDCRYPTO_ENTROPY_FORCE_SHA256 defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_TEST_NULL_ENTROPY) && \
+    ( !defined(MBEDCRYPTO_ENTROPY_C) || !defined(MBEDCRYPTO_NO_DEFAULT_ENTROPY_SOURCES) )
+#error "MBEDCRYPTO_TEST_NULL_ENTROPY defined, but not all prerequisites"
+#endif
+#if defined(MBEDCRYPTO_TEST_NULL_ENTROPY) && \
+     ( defined(MBEDCRYPTO_ENTROPY_NV_SEED) || defined(MBEDCRYPTO_ENTROPY_HARDWARE_ALT) || \
+    defined(MBEDCRYPTO_HAVEGE_C) )
+#error "MBEDCRYPTO_TEST_NULL_ENTROPY defined, but entropy sources too"
+#endif
+
+#if defined(MBEDCRYPTO_GCM_C) && (                                        \
+        !defined(MBEDCRYPTO_AES_C) && !defined(MBEDCRYPTO_CAMELLIA_C) )
+#error "MBEDCRYPTO_GCM_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_ECP_RANDOMIZE_JAC_ALT) && !defined(MBEDCRYPTO_ECP_INTERNAL_ALT)
+#error "MBEDCRYPTO_ECP_RANDOMIZE_JAC_ALT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_ECP_ADD_MIXED_ALT) && !defined(MBEDCRYPTO_ECP_INTERNAL_ALT)
+#error "MBEDCRYPTO_ECP_ADD_MIXED_ALT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_ECP_DOUBLE_JAC_ALT) && !defined(MBEDCRYPTO_ECP_INTERNAL_ALT)
+#error "MBEDCRYPTO_ECP_DOUBLE_JAC_ALT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_ECP_NORMALIZE_JAC_MANY_ALT) && !defined(MBEDCRYPTO_ECP_INTERNAL_ALT)
+#error "MBEDCRYPTO_ECP_NORMALIZE_JAC_MANY_ALT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_ECP_NORMALIZE_JAC_ALT) && !defined(MBEDCRYPTO_ECP_INTERNAL_ALT)
+#error "MBEDCRYPTO_ECP_NORMALIZE_JAC_ALT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_ECP_DOUBLE_ADD_MXZ_ALT) && !defined(MBEDCRYPTO_ECP_INTERNAL_ALT)
+#error "MBEDCRYPTO_ECP_DOUBLE_ADD_MXZ_ALT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_ECP_RANDOMIZE_MXZ_ALT) && !defined(MBEDCRYPTO_ECP_INTERNAL_ALT)
+#error "MBEDCRYPTO_ECP_RANDOMIZE_MXZ_ALT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_ECP_NORMALIZE_MXZ_ALT) && !defined(MBEDCRYPTO_ECP_INTERNAL_ALT)
+#error "MBEDCRYPTO_ECP_NORMALIZE_MXZ_ALT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_HAVEGE_C) && !defined(MBEDCRYPTO_TIMING_C)
+#error "MBEDCRYPTO_HAVEGE_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_HMAC_DRBG_C) && !defined(MBEDCRYPTO_MD_C)
+#error "MBEDCRYPTO_HMAC_DRBG_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) &&                 \
+    ( !defined(MBEDCRYPTO_ECDH_C) || !defined(MBEDCRYPTO_X509_CRT_PARSE_C) )
+#error "MBEDCRYPTO_KEY_EXCHANGE_ECDH_ECDSA_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_KEY_EXCHANGE_ECDH_RSA_ENABLED) &&                 \
+    ( !defined(MBEDCRYPTO_ECDH_C) || !defined(MBEDCRYPTO_X509_CRT_PARSE_C) )
+#error "MBEDCRYPTO_KEY_EXCHANGE_ECDH_RSA_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_KEY_EXCHANGE_DHE_PSK_ENABLED) && !defined(MBEDCRYPTO_DHM_C)
+#error "MBEDCRYPTO_KEY_EXCHANGE_DHE_PSK_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_KEY_EXCHANGE_ECDHE_PSK_ENABLED) &&                     \
+    !defined(MBEDCRYPTO_ECDH_C)
+#error "MBEDCRYPTO_KEY_EXCHANGE_ECDHE_PSK_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_KEY_EXCHANGE_DHE_RSA_ENABLED) &&                   \
+    ( !defined(MBEDCRYPTO_DHM_C) || !defined(MBEDCRYPTO_RSA_C) ||           \
+      !defined(MBEDCRYPTO_X509_CRT_PARSE_C) || !defined(MBEDCRYPTO_PKCS1_V15) )
+#error "MBEDCRYPTO_KEY_EXCHANGE_DHE_RSA_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_KEY_EXCHANGE_ECDHE_RSA_ENABLED) &&                 \
+    ( !defined(MBEDCRYPTO_ECDH_C) || !defined(MBEDCRYPTO_RSA_C) ||          \
+      !defined(MBEDCRYPTO_X509_CRT_PARSE_C) || !defined(MBEDCRYPTO_PKCS1_V15) )
+#error "MBEDCRYPTO_KEY_EXCHANGE_ECDHE_RSA_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) &&                 \
+    ( !defined(MBEDCRYPTO_ECDH_C) || !defined(MBEDCRYPTO_ECDSA_C) ||          \
+      !defined(MBEDCRYPTO_X509_CRT_PARSE_C) )
+#error "MBEDCRYPTO_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_KEY_EXCHANGE_RSA_PSK_ENABLED) &&                   \
+    ( !defined(MBEDCRYPTO_RSA_C) || !defined(MBEDCRYPTO_X509_CRT_PARSE_C) || \
+      !defined(MBEDCRYPTO_PKCS1_V15) )
+#error "MBEDCRYPTO_KEY_EXCHANGE_RSA_PSK_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_KEY_EXCHANGE_RSA_ENABLED) &&                       \
+    ( !defined(MBEDCRYPTO_RSA_C) || !defined(MBEDCRYPTO_X509_CRT_PARSE_C) || \
+      !defined(MBEDCRYPTO_PKCS1_V15) )
+#error "MBEDCRYPTO_KEY_EXCHANGE_RSA_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_KEY_EXCHANGE_ECJPAKE_ENABLED) &&                    \
+    ( !defined(MBEDCRYPTO_ECJPAKE_C) || !defined(MBEDCRYPTO_SHA256_C) ||      \
+      !defined(MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED) )
+#error "MBEDCRYPTO_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_MEMORY_BUFFER_ALLOC_C) &&                          \
+    ( !defined(MBEDCRYPTO_PLATFORM_C) || !defined(MBEDCRYPTO_PLATFORM_MEMORY) )
+#error "MBEDCRYPTO_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PADLOCK_C) && !defined(MBEDCRYPTO_HAVE_ASM)
+#error "MBEDCRYPTO_PADLOCK_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PEM_PARSE_C) && !defined(MBEDCRYPTO_BASE64_C)
+#error "MBEDCRYPTO_PEM_PARSE_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PEM_WRITE_C) && !defined(MBEDCRYPTO_BASE64_C)
+#error "MBEDCRYPTO_PEM_WRITE_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PK_C) && \
+    ( !defined(MBEDCRYPTO_RSA_C) && !defined(MBEDCRYPTO_ECP_C) )
+#error "MBEDCRYPTO_PK_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PK_PARSE_C) && !defined(MBEDCRYPTO_PK_C)
+#error "MBEDCRYPTO_PK_PARSE_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PK_WRITE_C) && !defined(MBEDCRYPTO_PK_C)
+#error "MBEDCRYPTO_PK_WRITE_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PKCS11_C) && !defined(MBEDCRYPTO_PK_C)
+#error "MBEDCRYPTO_PKCS11_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_EXIT_ALT) && !defined(MBEDCRYPTO_PLATFORM_C)
+#error "MBEDCRYPTO_PLATFORM_EXIT_ALT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_EXIT_MACRO) && !defined(MBEDCRYPTO_PLATFORM_C)
+#error "MBEDCRYPTO_PLATFORM_EXIT_MACRO defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_EXIT_MACRO) &&\
+    ( defined(MBEDCRYPTO_PLATFORM_STD_EXIT) ||\
+        defined(MBEDCRYPTO_PLATFORM_EXIT_ALT) )
+#error "MBEDCRYPTO_PLATFORM_EXIT_MACRO and MBEDCRYPTO_PLATFORM_STD_EXIT/MBEDCRYPTO_PLATFORM_EXIT_ALT cannot be defined simultaneously"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_TIME_ALT) &&\
+    ( !defined(MBEDCRYPTO_PLATFORM_C) ||\
+        !defined(MBEDCRYPTO_HAVE_TIME) )
+#error "MBEDCRYPTO_PLATFORM_TIME_ALT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_TIME_MACRO) &&\
+    ( !defined(MBEDCRYPTO_PLATFORM_C) ||\
+        !defined(MBEDCRYPTO_HAVE_TIME) )
+#error "MBEDCRYPTO_PLATFORM_TIME_MACRO defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_TIME_TYPE_MACRO) &&\
+    ( !defined(MBEDCRYPTO_PLATFORM_C) ||\
+        !defined(MBEDCRYPTO_HAVE_TIME) )
+#error "MBEDCRYPTO_PLATFORM_TIME_TYPE_MACRO defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_TIME_MACRO) &&\
+    ( defined(MBEDCRYPTO_PLATFORM_STD_TIME) ||\
+        defined(MBEDCRYPTO_PLATFORM_TIME_ALT) )
+#error "MBEDCRYPTO_PLATFORM_TIME_MACRO and MBEDCRYPTO_PLATFORM_STD_TIME/MBEDCRYPTO_PLATFORM_TIME_ALT cannot be defined simultaneously"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_TIME_TYPE_MACRO) &&\
+    ( defined(MBEDCRYPTO_PLATFORM_STD_TIME) ||\
+        defined(MBEDCRYPTO_PLATFORM_TIME_ALT) )
+#error "MBEDCRYPTO_PLATFORM_TIME_TYPE_MACRO and MBEDCRYPTO_PLATFORM_STD_TIME/MBEDCRYPTO_PLATFORM_TIME_ALT cannot be defined simultaneously"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_FPRINTF_ALT) && !defined(MBEDCRYPTO_PLATFORM_C)
+#error "MBEDCRYPTO_PLATFORM_FPRINTF_ALT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_FPRINTF_MACRO) && !defined(MBEDCRYPTO_PLATFORM_C)
+#error "MBEDCRYPTO_PLATFORM_FPRINTF_MACRO defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_FPRINTF_MACRO) &&\
+    ( defined(MBEDCRYPTO_PLATFORM_STD_FPRINTF) ||\
+        defined(MBEDCRYPTO_PLATFORM_FPRINTF_ALT) )
+#error "MBEDCRYPTO_PLATFORM_FPRINTF_MACRO and MBEDCRYPTO_PLATFORM_STD_FPRINTF/MBEDCRYPTO_PLATFORM_FPRINTF_ALT cannot be defined simultaneously"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_FREE_MACRO) &&\
+    ( !defined(MBEDCRYPTO_PLATFORM_C) || !defined(MBEDCRYPTO_PLATFORM_MEMORY) )
+#error "MBEDCRYPTO_PLATFORM_FREE_MACRO defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_FREE_MACRO) &&\
+    defined(MBEDCRYPTO_PLATFORM_STD_FREE)
+#error "MBEDCRYPTO_PLATFORM_FREE_MACRO and MBEDCRYPTO_PLATFORM_STD_FREE cannot be defined simultaneously"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_FREE_MACRO) && !defined(MBEDCRYPTO_PLATFORM_CALLOC_MACRO)
+#error "MBEDCRYPTO_PLATFORM_CALLOC_MACRO must be defined if MBEDCRYPTO_PLATFORM_FREE_MACRO is"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_CALLOC_MACRO) &&\
+    ( !defined(MBEDCRYPTO_PLATFORM_C) || !defined(MBEDCRYPTO_PLATFORM_MEMORY) )
+#error "MBEDCRYPTO_PLATFORM_CALLOC_MACRO defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_CALLOC_MACRO) &&\
+    defined(MBEDCRYPTO_PLATFORM_STD_CALLOC)
+#error "MBEDCRYPTO_PLATFORM_CALLOC_MACRO and MBEDCRYPTO_PLATFORM_STD_CALLOC cannot be defined simultaneously"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_CALLOC_MACRO) && !defined(MBEDCRYPTO_PLATFORM_FREE_MACRO)
+#error "MBEDCRYPTO_PLATFORM_FREE_MACRO must be defined if MBEDCRYPTO_PLATFORM_CALLOC_MACRO is"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_MEMORY) && !defined(MBEDCRYPTO_PLATFORM_C)
+#error "MBEDCRYPTO_PLATFORM_MEMORY defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_PRINTF_ALT) && !defined(MBEDCRYPTO_PLATFORM_C)
+#error "MBEDCRYPTO_PLATFORM_PRINTF_ALT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_PRINTF_MACRO) && !defined(MBEDCRYPTO_PLATFORM_C)
+#error "MBEDCRYPTO_PLATFORM_PRINTF_MACRO defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_PRINTF_MACRO) &&\
+    ( defined(MBEDCRYPTO_PLATFORM_STD_PRINTF) ||\
+        defined(MBEDCRYPTO_PLATFORM_PRINTF_ALT) )
+#error "MBEDCRYPTO_PLATFORM_PRINTF_MACRO and MBEDCRYPTO_PLATFORM_STD_PRINTF/MBEDCRYPTO_PLATFORM_PRINTF_ALT cannot be defined simultaneously"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_SNPRINTF_ALT) && !defined(MBEDCRYPTO_PLATFORM_C)
+#error "MBEDCRYPTO_PLATFORM_SNPRINTF_ALT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_SNPRINTF_MACRO) && !defined(MBEDCRYPTO_PLATFORM_C)
+#error "MBEDCRYPTO_PLATFORM_SNPRINTF_MACRO defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_SNPRINTF_MACRO) &&\
+    ( defined(MBEDCRYPTO_PLATFORM_STD_SNPRINTF) ||\
+        defined(MBEDCRYPTO_PLATFORM_SNPRINTF_ALT) )
+#error "MBEDCRYPTO_PLATFORM_SNPRINTF_MACRO and MBEDCRYPTO_PLATFORM_STD_SNPRINTF/MBEDCRYPTO_PLATFORM_SNPRINTF_ALT cannot be defined simultaneously"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_STD_MEM_HDR) &&\
+    !defined(MBEDCRYPTO_PLATFORM_NO_STD_FUNCTIONS)
+#error "MBEDCRYPTO_PLATFORM_STD_MEM_HDR defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_STD_CALLOC) && !defined(MBEDCRYPTO_PLATFORM_MEMORY)
+#error "MBEDCRYPTO_PLATFORM_STD_CALLOC defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_STD_CALLOC) && !defined(MBEDCRYPTO_PLATFORM_MEMORY)
+#error "MBEDCRYPTO_PLATFORM_STD_CALLOC defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_STD_FREE) && !defined(MBEDCRYPTO_PLATFORM_MEMORY)
+#error "MBEDCRYPTO_PLATFORM_STD_FREE defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_STD_EXIT) &&\
+    !defined(MBEDCRYPTO_PLATFORM_EXIT_ALT)
+#error "MBEDCRYPTO_PLATFORM_STD_EXIT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_STD_TIME) &&\
+    ( !defined(MBEDCRYPTO_PLATFORM_TIME_ALT) ||\
+        !defined(MBEDCRYPTO_HAVE_TIME) )
+#error "MBEDCRYPTO_PLATFORM_STD_TIME defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_STD_FPRINTF) &&\
+    !defined(MBEDCRYPTO_PLATFORM_FPRINTF_ALT)
+#error "MBEDCRYPTO_PLATFORM_STD_FPRINTF defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_STD_PRINTF) &&\
+    !defined(MBEDCRYPTO_PLATFORM_PRINTF_ALT)
+#error "MBEDCRYPTO_PLATFORM_STD_PRINTF defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_STD_SNPRINTF) &&\
+    !defined(MBEDCRYPTO_PLATFORM_SNPRINTF_ALT)
+#error "MBEDCRYPTO_PLATFORM_STD_SNPRINTF defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_ENTROPY_NV_SEED) &&\
+    ( !defined(MBEDCRYPTO_PLATFORM_C) || !defined(MBEDCRYPTO_ENTROPY_C) )
+#error "MBEDCRYPTO_ENTROPY_NV_SEED defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_NV_SEED_ALT) &&\
+    !defined(MBEDCRYPTO_ENTROPY_NV_SEED)
+#error "MBEDCRYPTO_PLATFORM_NV_SEED_ALT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_STD_NV_SEED_READ) &&\
+    !defined(MBEDCRYPTO_PLATFORM_NV_SEED_ALT)
+#error "MBEDCRYPTO_PLATFORM_STD_NV_SEED_READ defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_STD_NV_SEED_WRITE) &&\
+    !defined(MBEDCRYPTO_PLATFORM_NV_SEED_ALT)
+#error "MBEDCRYPTO_PLATFORM_STD_NV_SEED_WRITE defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_NV_SEED_READ_MACRO) &&\
+    ( defined(MBEDCRYPTO_PLATFORM_STD_NV_SEED_READ) ||\
+      defined(MBEDCRYPTO_PLATFORM_NV_SEED_ALT) )
+#error "MBEDCRYPTO_PLATFORM_NV_SEED_READ_MACRO and MBEDCRYPTO_PLATFORM_STD_NV_SEED_READ cannot be defined simultaneously"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_NV_SEED_WRITE_MACRO) &&\
+    ( defined(MBEDCRYPTO_PLATFORM_STD_NV_SEED_WRITE) ||\
+      defined(MBEDCRYPTO_PLATFORM_NV_SEED_ALT) )
+#error "MBEDCRYPTO_PLATFORM_NV_SEED_WRITE_MACRO and MBEDCRYPTO_PLATFORM_STD_NV_SEED_WRITE cannot be defined simultaneously"
+#endif
+
+#if defined(MBEDCRYPTO_PSA_CRYPTO_C) &&            \
+    !( defined(MBEDCRYPTO_CTR_DRBG_C) &&           \
+       defined(MBEDCRYPTO_ENTROPY_C) )
+#error "MBEDCRYPTO_PSA_CRYPTO_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PSA_CRYPTO_SPM) && !defined(MBEDCRYPTO_PSA_CRYPTO_C)
+#error "MBEDCRYPTO_PSA_CRYPTO_SPM defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_RSA_C) && ( !defined(MBEDCRYPTO_BIGNUM_C) ||         \
+    !defined(MBEDCRYPTO_OID_C) )
+#error "MBEDCRYPTO_RSA_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_RSA_C) && ( !defined(MBEDCRYPTO_PKCS1_V21) &&         \
+    !defined(MBEDCRYPTO_PKCS1_V15) )
+#error "MBEDCRYPTO_RSA_C defined, but none of the PKCS1 versions enabled"
+#endif
+
+#if defined(MBEDCRYPTO_X509_RSASSA_PSS_SUPPORT) &&                        \
+    ( !defined(MBEDCRYPTO_RSA_C) || !defined(MBEDCRYPTO_PKCS1_V21) )
+#error "MBEDCRYPTO_X509_RSASSA_PSS_SUPPORT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_PROTO_SSL3) && ( !defined(MBEDCRYPTO_MD5_C) ||     \
+    !defined(MBEDCRYPTO_SHA1_C) )
+#error "MBEDCRYPTO_SSL_PROTO_SSL3 defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_PROTO_TLS1) && ( !defined(MBEDCRYPTO_MD5_C) ||     \
+    !defined(MBEDCRYPTO_SHA1_C) )
+#error "MBEDCRYPTO_SSL_PROTO_TLS1 defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_PROTO_TLS1_1) && ( !defined(MBEDCRYPTO_MD5_C) ||     \
+    !defined(MBEDCRYPTO_SHA1_C) )
+#error "MBEDCRYPTO_SSL_PROTO_TLS1_1 defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_PROTO_TLS1_2) && ( !defined(MBEDCRYPTO_SHA1_C) &&     \
+    !defined(MBEDCRYPTO_SHA256_C) && !defined(MBEDCRYPTO_SHA512_C) )
+#error "MBEDCRYPTO_SSL_PROTO_TLS1_2 defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_PROTO_DTLS)     && \
+    !defined(MBEDCRYPTO_SSL_PROTO_TLS1_1)  && \
+    !defined(MBEDCRYPTO_SSL_PROTO_TLS1_2)
+#error "MBEDCRYPTO_SSL_PROTO_DTLS defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_CLI_C) && !defined(MBEDCRYPTO_SSL_TLS_C)
+#error "MBEDCRYPTO_SSL_CLI_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_TLS_C) && ( !defined(MBEDCRYPTO_CIPHER_C) ||     \
+    !defined(MBEDCRYPTO_MD_C) )
+#error "MBEDCRYPTO_SSL_TLS_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_SRV_C) && !defined(MBEDCRYPTO_SSL_TLS_C)
+#error "MBEDCRYPTO_SSL_SRV_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_TLS_C) && (!defined(MBEDCRYPTO_SSL_PROTO_SSL3) && \
+    !defined(MBEDCRYPTO_SSL_PROTO_TLS1) && !defined(MBEDCRYPTO_SSL_PROTO_TLS1_1) && \
+    !defined(MBEDCRYPTO_SSL_PROTO_TLS1_2))
+#error "MBEDCRYPTO_SSL_TLS_C defined, but no protocols are active"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_TLS_C) && (defined(MBEDCRYPTO_SSL_PROTO_SSL3) && \
+    defined(MBEDCRYPTO_SSL_PROTO_TLS1_1) && !defined(MBEDCRYPTO_SSL_PROTO_TLS1))
+#error "Illegal protocol selection"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_TLS_C) && (defined(MBEDCRYPTO_SSL_PROTO_TLS1) && \
+    defined(MBEDCRYPTO_SSL_PROTO_TLS1_2) && !defined(MBEDCRYPTO_SSL_PROTO_TLS1_1))
+#error "Illegal protocol selection"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_TLS_C) && (defined(MBEDCRYPTO_SSL_PROTO_SSL3) && \
+    defined(MBEDCRYPTO_SSL_PROTO_TLS1_2) && (!defined(MBEDCRYPTO_SSL_PROTO_TLS1) || \
+    !defined(MBEDCRYPTO_SSL_PROTO_TLS1_1)))
+#error "Illegal protocol selection"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_DTLS_HELLO_VERIFY) && !defined(MBEDCRYPTO_SSL_PROTO_DTLS)
+#error "MBEDCRYPTO_SSL_DTLS_HELLO_VERIFY  defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_DTLS_CLIENT_PORT_REUSE) && \
+    !defined(MBEDCRYPTO_SSL_DTLS_HELLO_VERIFY)
+#error "MBEDCRYPTO_SSL_DTLS_CLIENT_PORT_REUSE  defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_DTLS_ANTI_REPLAY) &&                              \
+    ( !defined(MBEDCRYPTO_SSL_TLS_C) || !defined(MBEDCRYPTO_SSL_PROTO_DTLS) )
+#error "MBEDCRYPTO_SSL_DTLS_ANTI_REPLAY  defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_DTLS_BADMAC_LIMIT) &&                              \
+    ( !defined(MBEDCRYPTO_SSL_TLS_C) || !defined(MBEDCRYPTO_SSL_PROTO_DTLS) )
+#error "MBEDCRYPTO_SSL_DTLS_BADMAC_LIMIT  defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_ENCRYPT_THEN_MAC) &&   \
+    !defined(MBEDCRYPTO_SSL_PROTO_TLS1)   &&      \
+    !defined(MBEDCRYPTO_SSL_PROTO_TLS1_1) &&      \
+    !defined(MBEDCRYPTO_SSL_PROTO_TLS1_2)
+#error "MBEDCRYPTO_SSL_ENCRYPT_THEN_MAC defined, but not all prerequsites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_EXTENDED_MASTER_SECRET) && \
+    !defined(MBEDCRYPTO_SSL_PROTO_TLS1)   &&          \
+    !defined(MBEDCRYPTO_SSL_PROTO_TLS1_1) &&          \
+    !defined(MBEDCRYPTO_SSL_PROTO_TLS1_2)
+#error "MBEDCRYPTO_SSL_EXTENDED_MASTER_SECRET defined, but not all prerequsites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_TICKET_C) && !defined(MBEDCRYPTO_CIPHER_C)
+#error "MBEDCRYPTO_SSL_TICKET_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_CBC_RECORD_SPLITTING) && \
+    !defined(MBEDCRYPTO_SSL_PROTO_SSL3) && !defined(MBEDCRYPTO_SSL_PROTO_TLS1)
+#error "MBEDCRYPTO_SSL_CBC_RECORD_SPLITTING defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_SERVER_NAME_INDICATION) && \
+        !defined(MBEDCRYPTO_X509_CRT_PARSE_C)
+#error "MBEDCRYPTO_SSL_SERVER_NAME_INDICATION defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_THREADING_PTHREAD)
+#if !defined(MBEDCRYPTO_THREADING_C) || defined(MBEDCRYPTO_THREADING_IMPL)
+#error "MBEDCRYPTO_THREADING_PTHREAD defined, but not all prerequisites"
+#endif
+#define MBEDCRYPTO_THREADING_IMPL
+#endif
+
+#if defined(MBEDCRYPTO_THREADING_ALT)
+#if !defined(MBEDCRYPTO_THREADING_C) || defined(MBEDCRYPTO_THREADING_IMPL)
+#error "MBEDCRYPTO_THREADING_ALT defined, but not all prerequisites"
+#endif
+#define MBEDCRYPTO_THREADING_IMPL
+#endif
+
+#if defined(MBEDCRYPTO_THREADING_C) && !defined(MBEDCRYPTO_THREADING_IMPL)
+#error "MBEDCRYPTO_THREADING_C defined, single threading implementation required"
+#endif
+#undef MBEDCRYPTO_THREADING_IMPL
+
+#if defined(MBEDCRYPTO_VERSION_FEATURES) && !defined(MBEDCRYPTO_VERSION_C)
+#error "MBEDCRYPTO_VERSION_FEATURES defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_X509_USE_C) && ( !defined(MBEDCRYPTO_BIGNUM_C) ||  \
+    !defined(MBEDCRYPTO_OID_C) || !defined(MBEDCRYPTO_ASN1_PARSE_C) ||      \
+    !defined(MBEDCRYPTO_PK_PARSE_C) )
+#error "MBEDCRYPTO_X509_USE_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_X509_CREATE_C) && ( !defined(MBEDCRYPTO_BIGNUM_C) ||  \
+    !defined(MBEDCRYPTO_OID_C) || !defined(MBEDCRYPTO_ASN1_WRITE_C) ||       \
+    !defined(MBEDCRYPTO_PK_WRITE_C) )
+#error "MBEDCRYPTO_X509_CREATE_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_X509_CRT_PARSE_C) && ( !defined(MBEDCRYPTO_X509_USE_C) )
+#error "MBEDCRYPTO_X509_CRT_PARSE_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_X509_CRL_PARSE_C) && ( !defined(MBEDCRYPTO_X509_USE_C) )
+#error "MBEDCRYPTO_X509_CRL_PARSE_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_X509_CSR_PARSE_C) && ( !defined(MBEDCRYPTO_X509_USE_C) )
+#error "MBEDCRYPTO_X509_CSR_PARSE_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_X509_CRT_WRITE_C) && ( !defined(MBEDCRYPTO_X509_CREATE_C) )
+#error "MBEDCRYPTO_X509_CRT_WRITE_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_X509_CSR_WRITE_C) && ( !defined(MBEDCRYPTO_X509_CREATE_C) )
+#error "MBEDCRYPTO_X509_CSR_WRITE_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_HAVE_INT32) && defined(MBEDCRYPTO_HAVE_INT64)
+#error "MBEDCRYPTO_HAVE_INT32 and MBEDCRYPTO_HAVE_INT64 cannot be defined simultaneously"
+#endif /* MBEDCRYPTO_HAVE_INT32 && MBEDCRYPTO_HAVE_INT64 */
+
+#if ( defined(MBEDCRYPTO_HAVE_INT32) || defined(MBEDCRYPTO_HAVE_INT64) ) && \
+    defined(MBEDCRYPTO_HAVE_ASM)
+#error "MBEDCRYPTO_HAVE_INT32/MBEDCRYPTO_HAVE_INT64 and MBEDCRYPTO_HAVE_ASM cannot be defined simultaneously"
+#endif /* (MBEDCRYPTO_HAVE_INT32 || MBEDCRYPTO_HAVE_INT64) && MBEDCRYPTO_HAVE_ASM */
+
+/*
+ * Avoid warning from -pedantic. This is a convenient place for this
+ * workaround since this is included by every single file before the
+ * #if defined(MBEDCRYPTO_xxx_C) that results in emtpy translation units.
+ */
+typedef int mbedcrypto_iso_c_forbids_empty_translation_units;
+
+#endif /* MBEDCRYPTO_CHECK_CONFIG_H */
diff --git a/include/mbedcrypto/cipher.h b/include/mbedcrypto/cipher.h
new file mode 100644
index 0000000..43f8f68
--- /dev/null
+++ b/include/mbedcrypto/cipher.h
@@ -0,0 +1,773 @@
+/**
+ * \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 (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#ifndef MBEDCRYPTO_CIPHER_H
+#define MBEDCRYPTO_CIPHER_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+
+#if defined(MBEDCRYPTO_GCM_C) || defined(MBEDCRYPTO_CCM_C)
+#define MBEDCRYPTO_CIPHER_MODE_AEAD
+#endif
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+#define MBEDCRYPTO_CIPHER_MODE_WITH_PADDING
+#endif
+
+#if defined(MBEDCRYPTO_ARC4_C)
+#define MBEDCRYPTO_CIPHER_MODE_STREAM
+#endif
+
+#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
+    !defined(inline) && !defined(__cplusplus)
+#define inline __inline
+#endif
+
+#define MBEDCRYPTO_ERR_CIPHER_FEATURE_UNAVAILABLE  -0x6080  /**< The selected feature is not available. */
+#define MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA       -0x6100  /**< Bad input parameters. */
+#define MBEDCRYPTO_ERR_CIPHER_ALLOC_FAILED         -0x6180  /**< Failed to allocate memory. */
+#define MBEDCRYPTO_ERR_CIPHER_INVALID_PADDING      -0x6200  /**< Input data contains invalid padding and is rejected. */
+#define MBEDCRYPTO_ERR_CIPHER_FULL_BLOCK_EXPECTED  -0x6280  /**< Decryption of block requires a full block. */
+#define MBEDCRYPTO_ERR_CIPHER_AUTH_FAILED          -0x6300  /**< Authentication failed (for AEAD modes). */
+#define MBEDCRYPTO_ERR_CIPHER_INVALID_CONTEXT      -0x6380  /**< The context is invalid. For example, because it was freed. */
+#define MBEDCRYPTO_ERR_CIPHER_HW_ACCEL_FAILED      -0x6400  /**< Cipher hardware accelerator failed. */
+
+#define MBEDCRYPTO_CIPHER_VARIABLE_IV_LEN     0x01    /**< Cipher accepts IVs of variable length. */
+#define MBEDCRYPTO_CIPHER_VARIABLE_KEY_LEN    0x02    /**< Cipher accepts keys of variable length. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief     Supported cipher types.
+ *
+ * \warning   RC4 and DES are considered weak ciphers and their use
+ *            constitutes a security risk. Arm recommends considering stronger
+ *            ciphers instead.
+ */
+typedef enum {
+    MBEDCRYPTO_CIPHER_ID_NONE = 0,  /**< Placeholder to mark the end of cipher ID lists. */
+    MBEDCRYPTO_CIPHER_ID_NULL,      /**< The identity cipher, treated as a stream cipher. */
+    MBEDCRYPTO_CIPHER_ID_AES,       /**< The AES cipher. */
+    MBEDCRYPTO_CIPHER_ID_DES,       /**< The DES cipher. */
+    MBEDCRYPTO_CIPHER_ID_3DES,      /**< The Triple DES cipher. */
+    MBEDCRYPTO_CIPHER_ID_CAMELLIA,  /**< The Camellia cipher. */
+    MBEDCRYPTO_CIPHER_ID_BLOWFISH,  /**< The Blowfish cipher. */
+    MBEDCRYPTO_CIPHER_ID_ARC4,      /**< The RC4 cipher. */
+} mbedcrypto_cipher_id_t;
+
+/**
+ * \brief     Supported {cipher type, cipher mode} pairs.
+ *
+ * \warning   RC4 and DES are considered weak ciphers and their use
+ *            constitutes a security risk. Arm recommends considering stronger
+ *            ciphers instead.
+ */
+typedef enum {
+    MBEDCRYPTO_CIPHER_NONE = 0,             /**< Placeholder to mark the end of cipher-pair lists. */
+    MBEDCRYPTO_CIPHER_NULL,                 /**< The identity stream cipher. */
+    MBEDCRYPTO_CIPHER_AES_128_ECB,          /**< AES cipher with 128-bit ECB mode. */
+    MBEDCRYPTO_CIPHER_AES_192_ECB,          /**< AES cipher with 192-bit ECB mode. */
+    MBEDCRYPTO_CIPHER_AES_256_ECB,          /**< AES cipher with 256-bit ECB mode. */
+    MBEDCRYPTO_CIPHER_AES_128_CBC,          /**< AES cipher with 128-bit CBC mode. */
+    MBEDCRYPTO_CIPHER_AES_192_CBC,          /**< AES cipher with 192-bit CBC mode. */
+    MBEDCRYPTO_CIPHER_AES_256_CBC,          /**< AES cipher with 256-bit CBC mode. */
+    MBEDCRYPTO_CIPHER_AES_128_CFB128,       /**< AES cipher with 128-bit CFB128 mode. */
+    MBEDCRYPTO_CIPHER_AES_192_CFB128,       /**< AES cipher with 192-bit CFB128 mode. */
+    MBEDCRYPTO_CIPHER_AES_256_CFB128,       /**< AES cipher with 256-bit CFB128 mode. */
+    MBEDCRYPTO_CIPHER_AES_128_CTR,          /**< AES cipher with 128-bit CTR mode. */
+    MBEDCRYPTO_CIPHER_AES_192_CTR,          /**< AES cipher with 192-bit CTR mode. */
+    MBEDCRYPTO_CIPHER_AES_256_CTR,          /**< AES cipher with 256-bit CTR mode. */
+    MBEDCRYPTO_CIPHER_AES_128_GCM,          /**< AES cipher with 128-bit GCM mode. */
+    MBEDCRYPTO_CIPHER_AES_192_GCM,          /**< AES cipher with 192-bit GCM mode. */
+    MBEDCRYPTO_CIPHER_AES_256_GCM,          /**< AES cipher with 256-bit GCM mode. */
+    MBEDCRYPTO_CIPHER_CAMELLIA_128_ECB,     /**< Camellia cipher with 128-bit ECB mode. */
+    MBEDCRYPTO_CIPHER_CAMELLIA_192_ECB,     /**< Camellia cipher with 192-bit ECB mode. */
+    MBEDCRYPTO_CIPHER_CAMELLIA_256_ECB,     /**< Camellia cipher with 256-bit ECB mode. */
+    MBEDCRYPTO_CIPHER_CAMELLIA_128_CBC,     /**< Camellia cipher with 128-bit CBC mode. */
+    MBEDCRYPTO_CIPHER_CAMELLIA_192_CBC,     /**< Camellia cipher with 192-bit CBC mode. */
+    MBEDCRYPTO_CIPHER_CAMELLIA_256_CBC,     /**< Camellia cipher with 256-bit CBC mode. */
+    MBEDCRYPTO_CIPHER_CAMELLIA_128_CFB128,  /**< Camellia cipher with 128-bit CFB128 mode. */
+    MBEDCRYPTO_CIPHER_CAMELLIA_192_CFB128,  /**< Camellia cipher with 192-bit CFB128 mode. */
+    MBEDCRYPTO_CIPHER_CAMELLIA_256_CFB128,  /**< Camellia cipher with 256-bit CFB128 mode. */
+    MBEDCRYPTO_CIPHER_CAMELLIA_128_CTR,     /**< Camellia cipher with 128-bit CTR mode. */
+    MBEDCRYPTO_CIPHER_CAMELLIA_192_CTR,     /**< Camellia cipher with 192-bit CTR mode. */
+    MBEDCRYPTO_CIPHER_CAMELLIA_256_CTR,     /**< Camellia cipher with 256-bit CTR mode. */
+    MBEDCRYPTO_CIPHER_CAMELLIA_128_GCM,     /**< Camellia cipher with 128-bit GCM mode. */
+    MBEDCRYPTO_CIPHER_CAMELLIA_192_GCM,     /**< Camellia cipher with 192-bit GCM mode. */
+    MBEDCRYPTO_CIPHER_CAMELLIA_256_GCM,     /**< Camellia cipher with 256-bit GCM mode. */
+    MBEDCRYPTO_CIPHER_DES_ECB,              /**< DES cipher with ECB mode. */
+    MBEDCRYPTO_CIPHER_DES_CBC,              /**< DES cipher with CBC mode. */
+    MBEDCRYPTO_CIPHER_DES_EDE_ECB,          /**< DES cipher with EDE ECB mode. */
+    MBEDCRYPTO_CIPHER_DES_EDE_CBC,          /**< DES cipher with EDE CBC mode. */
+    MBEDCRYPTO_CIPHER_DES_EDE3_ECB,         /**< DES cipher with EDE3 ECB mode. */
+    MBEDCRYPTO_CIPHER_DES_EDE3_CBC,         /**< DES cipher with EDE3 CBC mode. */
+    MBEDCRYPTO_CIPHER_BLOWFISH_ECB,         /**< Blowfish cipher with ECB mode. */
+    MBEDCRYPTO_CIPHER_BLOWFISH_CBC,         /**< Blowfish cipher with CBC mode. */
+    MBEDCRYPTO_CIPHER_BLOWFISH_CFB64,       /**< Blowfish cipher with CFB64 mode. */
+    MBEDCRYPTO_CIPHER_BLOWFISH_CTR,         /**< Blowfish cipher with CTR mode. */
+    MBEDCRYPTO_CIPHER_ARC4_128,             /**< RC4 cipher with 128-bit mode. */
+    MBEDCRYPTO_CIPHER_AES_128_CCM,          /**< AES cipher with 128-bit CCM mode. */
+    MBEDCRYPTO_CIPHER_AES_192_CCM,          /**< AES cipher with 192-bit CCM mode. */
+    MBEDCRYPTO_CIPHER_AES_256_CCM,          /**< AES cipher with 256-bit CCM mode. */
+    MBEDCRYPTO_CIPHER_CAMELLIA_128_CCM,     /**< Camellia cipher with 128-bit CCM mode. */
+    MBEDCRYPTO_CIPHER_CAMELLIA_192_CCM,     /**< Camellia cipher with 192-bit CCM mode. */
+    MBEDCRYPTO_CIPHER_CAMELLIA_256_CCM,     /**< Camellia cipher with 256-bit CCM mode. */
+} mbedcrypto_cipher_type_t;
+
+/** Supported cipher modes. */
+typedef enum {
+    MBEDCRYPTO_MODE_NONE = 0,               /**< None. */
+    MBEDCRYPTO_MODE_ECB,                    /**< The ECB cipher mode. */
+    MBEDCRYPTO_MODE_CBC,                    /**< The CBC cipher mode. */
+    MBEDCRYPTO_MODE_CFB,                    /**< The CFB cipher mode. */
+    MBEDCRYPTO_MODE_OFB,                    /**< The OFB cipher mode - unsupported. */
+    MBEDCRYPTO_MODE_CTR,                    /**< The CTR cipher mode. */
+    MBEDCRYPTO_MODE_GCM,                    /**< The GCM cipher mode. */
+    MBEDCRYPTO_MODE_STREAM,                 /**< The stream cipher mode. */
+    MBEDCRYPTO_MODE_CCM,                    /**< The CCM cipher mode. */
+} mbedcrypto_cipher_mode_t;
+
+/** Supported cipher padding types. */
+typedef enum {
+    MBEDCRYPTO_PADDING_PKCS7 = 0,     /**< PKCS7 padding (default).        */
+    MBEDCRYPTO_PADDING_ONE_AND_ZEROS, /**< ISO/IEC 7816-4 padding.         */
+    MBEDCRYPTO_PADDING_ZEROS_AND_LEN, /**< ANSI X.923 padding.             */
+    MBEDCRYPTO_PADDING_ZEROS,         /**< Zero padding (not reversible). */
+    MBEDCRYPTO_PADDING_NONE,          /**< Never pad (full blocks only).   */
+} mbedcrypto_cipher_padding_t;
+
+/** Type of operation. */
+typedef enum {
+    MBEDCRYPTO_OPERATION_NONE = -1,
+    MBEDCRYPTO_DECRYPT = 0,
+    MBEDCRYPTO_ENCRYPT,
+} mbedcrypto_operation_t;
+
+enum {
+    /** Undefined key length. */
+    MBEDCRYPTO_KEY_LENGTH_NONE = 0,
+    /** Key length, in bits (including parity), for DES keys. */
+    MBEDCRYPTO_KEY_LENGTH_DES  = 64,
+    /** Key length in bits, including parity, for DES in two-key EDE. */
+    MBEDCRYPTO_KEY_LENGTH_DES_EDE = 128,
+    /** Key length in bits, including parity, for DES in three-key EDE. */
+    MBEDCRYPTO_KEY_LENGTH_DES_EDE3 = 192,
+};
+
+/** Maximum length of any IV, in Bytes. */
+#define MBEDCRYPTO_MAX_IV_LENGTH      16
+/** Maximum block size of any cipher, in Bytes. */
+#define MBEDCRYPTO_MAX_BLOCK_LENGTH   16
+
+/**
+ * Base cipher information (opaque struct).
+ */
+typedef struct mbedcrypto_cipher_base_t mbedcrypto_cipher_base_t;
+
+/**
+ * CMAC context (opaque struct).
+ */
+typedef struct mbedcrypto_cmac_context_t mbedcrypto_cmac_context_t;
+
+/**
+ * Cipher information. Allows calling cipher functions
+ * in a generic way.
+ */
+typedef struct {
+    /** Full cipher identifier. For example,
+     * MBEDCRYPTO_CIPHER_AES_256_CBC.
+     */
+    mbedcrypto_cipher_type_t type;
+
+    /** The cipher mode. For example, MBEDCRYPTO_MODE_CBC. */
+    mbedcrypto_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 MBEDCRYPTO_CIPHER_VARIABLE_IV_LEN and
+     *  MBEDCRYPTO_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 mbedcrypto_cipher_base_t *base;
+
+} mbedcrypto_cipher_info_t;
+
+/**
+ * Generic cipher context.
+ */
+typedef struct {
+    /** Information about the associated cipher. */
+    const mbedcrypto_cipher_info_t *cipher_info;
+
+    /** Key length to use. */
+    int key_bitlen;
+
+    /** Operation that the key of the context has been
+     * initialized for.
+     */
+    mbedcrypto_operation_t operation;
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_WITH_PADDING)
+    /** Padding functions to use, if relevant for
+     * the specific cipher mode.
+     */
+    void (*add_padding)( unsigned char *output, size_t olen, size_t data_len );
+    int (*get_padding)( unsigned char *input, size_t ilen, size_t *data_len );
+#endif
+
+    /** Buffer for input that has not been processed yet. */
+    unsigned char unprocessed_data[MBEDCRYPTO_MAX_BLOCK_LENGTH];
+
+    /** Number of Bytes that have not been processed yet. */
+    size_t unprocessed_len;
+
+    /** Current IV or NONCE_COUNTER for CTR-mode. */
+    unsigned char iv[MBEDCRYPTO_MAX_IV_LENGTH];
+
+    /** IV size in Bytes, for ciphers with variable-length IVs. */
+    size_t iv_size;
+
+    /** The cipher-specific context. */
+    void *cipher_ctx;
+
+#if defined(MBEDCRYPTO_CMAC_C)
+    /** CMAC-specific context. */
+    mbedcrypto_cmac_context_t *cmac_ctx;
+#endif
+} mbedcrypto_cipher_context_t;
+
+/**
+ * \brief This function retrieves the list of ciphers supported by the generic
+ * cipher module.
+ *
+ * \return      A statically-allocated array of ciphers. The last entry
+ *              is zero.
+ */
+const int *mbedcrypto_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.
+ *
+ * \return              The cipher information structure associated with the
+ *                      given \p cipher_name.
+ * \return              NULL if the associated cipher information is not found.
+ */
+const mbedcrypto_cipher_info_t *mbedcrypto_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              NULL if the associated cipher information is not found.
+ */
+const mbedcrypto_cipher_info_t *mbedcrypto_cipher_info_from_type( const mbedcrypto_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,
+ *                      #MBEDCRYPTO_CIPHER_ID_AES.
+ * \param key_bitlen    The length of the key in bits.
+ * \param mode          The cipher mode. For example, #MBEDCRYPTO_MODE_CBC.
+ *
+ * \return              The cipher information structure associated with the
+ *                      given \p cipher_id.
+ * \return              NULL if the associated cipher information is not found.
+ */
+const mbedcrypto_cipher_info_t *mbedcrypto_cipher_info_from_values( const mbedcrypto_cipher_id_t cipher_id,
+                                              int key_bitlen,
+                                              const mbedcrypto_cipher_mode_t mode );
+
+/**
+ * \brief               This function initializes a \p cipher_context as NONE.
+ */
+void mbedcrypto_cipher_init( mbedcrypto_cipher_context_t *ctx );
+
+/**
+ * \brief               This function frees and clears the cipher-specific
+ *                      context of \p ctx. Freeing \p ctx itself remains the
+ *                      responsibility of the caller.
+ */
+void mbedcrypto_cipher_free( mbedcrypto_cipher_context_t *ctx );
+
+
+/**
+ * \brief               This function initializes and fills the cipher-context
+ *                      structure with the appropriate values. It also clears
+ *                      the structure.
+ *
+ * \param ctx           The context to initialize. May not be NULL.
+ * \param cipher_info   The cipher to use.
+ *
+ * \return              \c 0 on success.
+ * \return              #MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA on
+ *                      parameter-verification failure.
+ * \return              #MBEDCRYPTO_ERR_CIPHER_ALLOC_FAILED if allocation of the
+ *                      cipher-specific context fails.
+ *
+ * \internal Currently, the function also clears the structure.
+ * In future versions, the caller will be required to call
+ * mbedcrypto_cipher_init() on the structure first.
+ */
+int mbedcrypto_cipher_setup( mbedcrypto_cipher_context_t *ctx, const mbedcrypto_cipher_info_t *cipher_info );
+
+/**
+ * \brief        This function returns the block size of the given cipher.
+ *
+ * \param ctx    The context of the cipher. Must be initialized.
+ *
+ * \return       The size of the blocks of the cipher.
+ * \return       0 if \p ctx has not been initialized.
+ */
+static inline unsigned int mbedcrypto_cipher_get_block_size( const mbedcrypto_cipher_context_t *ctx )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info )
+        return 0;
+
+    return ctx->cipher_info->block_size;
+}
+
+/**
+ * \brief        This function returns the mode of operation for
+ *               the cipher. For example, MBEDCRYPTO_MODE_CBC.
+ *
+ * \param ctx    The context of the cipher. Must be initialized.
+ *
+ * \return       The mode of operation.
+ * \return       #MBEDCRYPTO_MODE_NONE if \p ctx has not been initialized.
+ */
+static inline mbedcrypto_cipher_mode_t mbedcrypto_cipher_get_cipher_mode( const mbedcrypto_cipher_context_t *ctx )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info )
+        return MBEDCRYPTO_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. 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 mbedcrypto_cipher_get_iv_size( const mbedcrypto_cipher_context_t *ctx )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info )
+        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. Must be initialized.
+ *
+ * \return              The type of the cipher.
+ * \return              #MBEDCRYPTO_CIPHER_NONE if \p ctx has not been initialized.
+ */
+static inline mbedcrypto_cipher_type_t mbedcrypto_cipher_get_type( const mbedcrypto_cipher_context_t *ctx )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info )
+        return MBEDCRYPTO_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. Must be initialized.
+ *
+ * \return              The name of the cipher.
+ * \return              NULL if \p ctx has not been not initialized.
+ */
+static inline const char *mbedcrypto_cipher_get_name( const mbedcrypto_cipher_context_t *ctx )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info )
+        return 0;
+
+    return ctx->cipher_info->name;
+}
+
+/**
+ * \brief               This function returns the key length of the cipher.
+ *
+ * \param ctx           The context of the cipher. Must be initialized.
+ *
+ * \return              The key length of the cipher in bits.
+ * \return              #MBEDCRYPTO_KEY_LENGTH_NONE if ctx \p has not been
+ *                      initialized.
+ */
+static inline int mbedcrypto_cipher_get_key_bitlen( const mbedcrypto_cipher_context_t *ctx )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info )
+        return MBEDCRYPTO_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. Must be initialized.
+ *
+ * \return         The type of operation: #MBEDCRYPTO_ENCRYPT or #MBEDCRYPTO_DECRYPT.
+ * \return         #MBEDCRYPTO_OPERATION_NONE if \p ctx has not been initialized.
+ */
+static inline mbedcrypto_operation_t mbedcrypto_cipher_get_operation( const mbedcrypto_cipher_context_t *ctx )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info )
+        return MBEDCRYPTO_OPERATION_NONE;
+
+    return ctx->operation;
+}
+
+/**
+ * \brief               This function sets the key to use with the given context.
+ *
+ * \param ctx           The generic cipher context. May not be NULL. Must have
+ *                      been initialized using mbedcrypto_cipher_info_from_type()
+ *                      or mbedcrypto_cipher_info_from_string().
+ * \param key           The key to use.
+ * \param key_bitlen    The key length to use, in bits.
+ * \param operation     The operation that the key will be used for:
+ *                      #MBEDCRYPTO_ENCRYPT or #MBEDCRYPTO_DECRYPT.
+ *
+ * \return              \c 0 on success.
+ * \return              #MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA on
+ *                      parameter-verification failure.
+ * \return              A cipher-specific error code on failure.
+ */
+int mbedcrypto_cipher_setkey( mbedcrypto_cipher_context_t *ctx, const unsigned char *key,
+                   int key_bitlen, const mbedcrypto_operation_t operation );
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_WITH_PADDING)
+/**
+ * \brief               This function sets the padding mode, for cipher modes
+ *                      that use padding.
+ *
+ *                      The default passing mode is PKCS7 padding.
+ *
+ * \param ctx           The generic cipher context.
+ * \param mode          The padding mode.
+ *
+ * \return              \c 0 on success.
+ * \return              #MBEDCRYPTO_ERR_CIPHER_FEATURE_UNAVAILABLE
+ *                      if the selected padding mode is not supported.
+ * \return              #MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA if the cipher mode
+ *                      does not support padding.
+ */
+int mbedcrypto_cipher_set_padding_mode( mbedcrypto_cipher_context_t *ctx, mbedcrypto_cipher_padding_t mode );
+#endif /* MBEDCRYPTO_CIPHER_MODE_WITH_PADDING */
+
+/**
+ * \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.
+ * \param iv        The IV to use, or NONCE_COUNTER for CTR-mode ciphers.
+ * \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          #MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA on
+ *                  parameter-verification failure.
+ */
+int mbedcrypto_cipher_set_iv( mbedcrypto_cipher_context_t *ctx,
+                   const unsigned char *iv, size_t iv_len );
+
+/**
+ * \brief         This function resets the cipher state.
+ *
+ * \param ctx     The generic cipher context.
+ *
+ * \return        \c 0 on success.
+ * \return        #MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA on
+ *                parameter-verification failure.
+ */
+int mbedcrypto_cipher_reset( mbedcrypto_cipher_context_t *ctx );
+
+#if defined(MBEDCRYPTO_GCM_C)
+/**
+ * \brief               This function adds additional data for AEAD ciphers.
+ *                      Only supported with GCM. Must be called
+ *                      exactly once, after mbedcrypto_cipher_reset().
+ *
+ * \param ctx           The generic cipher context.
+ * \param ad            The additional data to use.
+ * \param ad_len        the Length of \p ad.
+ *
+ * \return              \c 0 on success.
+ * \return              A specific error code on failure.
+ */
+int mbedcrypto_cipher_update_ad( mbedcrypto_cipher_context_t *ctx,
+                      const unsigned char *ad, size_t ad_len );
+#endif /* MBEDCRYPTO_GCM_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
+ *                      mbedcrypto_cipher_finish() is called.
+ *                      Exception: For MBEDCRYPTO_MODE_ECB, expects a single block
+ *                      in size. For example, 16 Bytes for AES.
+ *
+ * \note                If the underlying cipher is used in GCM mode, all calls
+ *                      to this function, except for the last one before
+ *                      mbedcrypto_cipher_finish(), must have \p ilen as a
+ *                      multiple of the block size of the cipher.
+ *
+ * \param ctx           The generic cipher context.
+ * \param input         The buffer holding the input data.
+ * \param ilen          The length of the input data.
+ * \param output        The buffer for the output data. Must be able to hold at
+ *                      least \p ilen + block_size. Must not be the same buffer
+ *                      as input.
+ * \param olen          The length of the output data, to be updated with the
+ *                      actual number of Bytes written.
+ *
+ * \return              \c 0 on success.
+ * \return              #MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA on
+ *                      parameter-verification failure.
+ * \return              #MBEDCRYPTO_ERR_CIPHER_FEATURE_UNAVAILABLE on an
+ *                      unsupported mode for a cipher.
+ * \return              A cipher-specific error code on failure.
+ */
+int mbedcrypto_cipher_update( mbedcrypto_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.
+ * \param output        The buffer to write data to. Needs block_size available.
+ * \param olen          The length of the data written to the \p output buffer.
+ *
+ * \return              \c 0 on success.
+ * \return              #MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA on
+ *                      parameter-verification failure.
+ * \return              #MBEDCRYPTO_ERR_CIPHER_FULL_BLOCK_EXPECTED on decryption
+ *                      expecting a full block but not receiving one.
+ * \return              #MBEDCRYPTO_ERR_CIPHER_INVALID_PADDING on invalid padding
+ *                      while decrypting.
+ * \return              A cipher-specific error code on failure.
+ */
+int mbedcrypto_cipher_finish( mbedcrypto_cipher_context_t *ctx,
+                   unsigned char *output, size_t *olen );
+
+#if defined(MBEDCRYPTO_GCM_C)
+/**
+ * \brief               This function writes a tag for AEAD ciphers.
+ *                      Only supported with GCM.
+ *                      Must be called after mbedcrypto_cipher_finish().
+ *
+ * \param ctx           The generic cipher context.
+ * \param tag           The buffer to write the tag to.
+ * \param tag_len       The length of the tag to write.
+ *
+ * \return              \c 0 on success.
+ * \return              A specific error code on failure.
+ */
+int mbedcrypto_cipher_write_tag( mbedcrypto_cipher_context_t *ctx,
+                      unsigned char *tag, size_t tag_len );
+
+/**
+ * \brief               This function checks the tag for AEAD ciphers.
+ *                      Only supported with GCM.
+ *                      Must be called after mbedcrypto_cipher_finish().
+ *
+ * \param ctx           The generic cipher context.
+ * \param tag           The buffer holding the tag.
+ * \param tag_len       The length of the tag to check.
+ *
+ * \return              \c 0 on success.
+ * \return              A specific error code on failure.
+ */
+int mbedcrypto_cipher_check_tag( mbedcrypto_cipher_context_t *ctx,
+                      const unsigned char *tag, size_t tag_len );
+#endif /* MBEDCRYPTO_GCM_C */
+
+/**
+ * \brief               The generic all-in-one encryption/decryption function,
+ *                      for all ciphers except AEAD constructs.
+ *
+ * \param ctx           The generic cipher context.
+ * \param iv            The IV to use, or NONCE_COUNTER for CTR-mode ciphers.
+ * \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.
+ * \param ilen          The length of the input data.
+ * \param output        The buffer for the output data. Must be able to hold at
+ *                      least \p ilen + block_size. Must not be the same buffer
+ *                      as input.
+ * \param olen          The length of the output data, to be updated with the
+ *                      actual number of Bytes written.
+ *
+ * \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              #MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA on
+ *                      parameter-verification failure.
+ * \return              #MBEDCRYPTO_ERR_CIPHER_FULL_BLOCK_EXPECTED on decryption
+ *                      expecting a full block but not receiving one.
+ * \return              #MBEDCRYPTO_ERR_CIPHER_INVALID_PADDING on invalid padding
+ *                      while decrypting.
+ * \return              A cipher-specific error code on failure.
+ */
+int mbedcrypto_cipher_crypt( mbedcrypto_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 );
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_AEAD)
+/**
+ * \brief               The generic autenticated encryption (AEAD) function.
+ *
+ * \param ctx           The generic cipher context.
+ * \param iv            The IV to use, or NONCE_COUNTER for CTR-mode ciphers.
+ * \param iv_len        The IV length for ciphers with variable-size IV.
+ *                      This parameter is discarded by ciphers with fixed-size IV.
+ * \param ad            The additional data to authenticate.
+ * \param ad_len        The length of \p ad.
+ * \param input         The buffer holding the input data.
+ * \param ilen          The length of the input data.
+ * \param output        The buffer for the output data.
+ *                      Must be able to hold at least \p ilen.
+ * \param olen          The length of the output data, to be updated with the
+ *                      actual number of Bytes written.
+ * \param tag           The buffer for the authentication tag.
+ * \param tag_len       The desired length of the authentication tag.
+ *
+ * \return              \c 0 on success.
+ * \return              #MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA on
+ *                      parameter-verification failure.
+ * \return              A cipher-specific error code on failure.
+ */
+int mbedcrypto_cipher_auth_encrypt( mbedcrypto_cipher_context_t *ctx,
+                         const unsigned char *iv, size_t iv_len,
+                         const unsigned char *ad, size_t ad_len,
+                         const unsigned char *input, size_t ilen,
+                         unsigned char *output, size_t *olen,
+                         unsigned char *tag, size_t tag_len );
+
+/**
+ * \brief               The generic autenticated decryption (AEAD) function.
+ *
+ * \note                If the data is not authentic, then the output buffer
+ *                      is zeroed out to prevent the unauthentic plaintext being
+ *                      used, making this interface safer.
+ *
+ * \param ctx           The generic cipher context.
+ * \param iv            The IV to use, or NONCE_COUNTER for CTR-mode ciphers.
+ * \param iv_len        The IV length for ciphers with variable-size IV.
+ *                      This parameter is discarded by ciphers with fixed-size IV.
+ * \param ad            The additional data to be authenticated.
+ * \param ad_len        The length of \p ad.
+ * \param input         The buffer holding the input data.
+ * \param ilen          The length of the input data.
+ * \param output        The buffer for the output data.
+ *                      Must be able to hold at least \p ilen.
+ * \param olen          The length of the output data, to be updated with the
+ *                      actual number of Bytes written.
+ * \param tag           The buffer holding the authentication tag.
+ * \param tag_len       The length of the authentication tag.
+ *
+ * \return              \c 0 on success.
+ * \return              #MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA on
+ *                      parameter-verification failure.
+ * \return              #MBEDCRYPTO_ERR_CIPHER_AUTH_FAILED if data is not authentic.
+ * \return              A cipher-specific error code on failure.
+ */
+int mbedcrypto_cipher_auth_decrypt( mbedcrypto_cipher_context_t *ctx,
+                         const unsigned char *iv, size_t iv_len,
+                         const unsigned char *ad, size_t ad_len,
+                         const unsigned char *input, size_t ilen,
+                         unsigned char *output, size_t *olen,
+                         const unsigned char *tag, size_t tag_len );
+#endif /* MBEDCRYPTO_CIPHER_MODE_AEAD */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDCRYPTO_CIPHER_H */
diff --git a/include/mbedcrypto/cipher_internal.h b/include/mbedcrypto/cipher_internal.h
new file mode 100644
index 0000000..3d4451b
--- /dev/null
+++ b/include/mbedcrypto/cipher_internal.h
@@ -0,0 +1,110 @@
+/**
+ * \file cipher_internal.h
+ *
+ * \brief Cipher wrappers.
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ */
+/*
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_CIPHER_WRAP_H
+#define MBEDCRYPTO_CIPHER_WRAP_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include "cipher.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Base cipher information. The non-mode specific functions and values.
+ */
+struct mbedcrypto_cipher_base_t
+{
+    /** Base Cipher type (e.g. MBEDCRYPTO_CIPHER_ID_AES) */
+    mbedcrypto_cipher_id_t cipher;
+
+    /** Encrypt using ECB */
+    int (*ecb_func)( void *ctx, mbedcrypto_operation_t mode,
+                     const unsigned char *input, unsigned char *output );
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+    /** Encrypt using CBC */
+    int (*cbc_func)( void *ctx, mbedcrypto_operation_t mode, size_t length,
+                     unsigned char *iv, const unsigned char *input,
+                     unsigned char *output );
+#endif
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+    /** Encrypt using CFB (Full length) */
+    int (*cfb_func)( void *ctx, mbedcrypto_operation_t mode, size_t length, size_t *iv_off,
+                     unsigned char *iv, const unsigned char *input,
+                     unsigned char *output );
+#endif
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+    /** Encrypt using CTR */
+    int (*ctr_func)( void *ctx, size_t length, size_t *nc_off,
+                     unsigned char *nonce_counter, unsigned char *stream_block,
+                     const unsigned char *input, unsigned char *output );
+#endif
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_STREAM)
+    /** Encrypt using STREAM */
+    int (*stream_func)( void *ctx, size_t length,
+                        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 );
+
+};
+
+typedef struct
+{
+    mbedcrypto_cipher_type_t type;
+    const mbedcrypto_cipher_info_t *info;
+} mbedcrypto_cipher_definition_t;
+
+extern const mbedcrypto_cipher_definition_t mbedcrypto_cipher_definitions[];
+
+extern int mbedcrypto_cipher_supported[];
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDCRYPTO_CIPHER_WRAP_H */
diff --git a/include/mbedcrypto/cmac.h b/include/mbedcrypto/cmac.h
new file mode 100644
index 0000000..4c697d1
--- /dev/null
+++ b/include/mbedcrypto/cmac.h
@@ -0,0 +1,206 @@
+/**
+ * \file cmac.h
+ *
+ * \brief This file contains CMAC definitions and functions.
+ *
+ * The Cipher-based Message Authentication Code (CMAC) Mode for
+ * Authentication is defined in <em>RFC-4493: The AES-CMAC Algorithm</em>.
+ */
+/*
+ *  Copyright (C) 2015-2018, Arm Limited (or its affiliates), All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#ifndef MBEDCRYPTO_CMAC_H
+#define MBEDCRYPTO_CMAC_H
+
+#include "mbedcrypto/cipher.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MBEDCRYPTO_ERR_CMAC_HW_ACCEL_FAILED -0x007A  /**< CMAC hardware accelerator failed. */
+
+#define MBEDCRYPTO_AES_BLOCK_SIZE          16
+#define MBEDCRYPTO_DES3_BLOCK_SIZE         8
+
+#if defined(MBEDCRYPTO_AES_C)
+#define MBEDCRYPTO_CIPHER_BLKSIZE_MAX      16  /**< The longest block used by CMAC is that of AES. */
+#else
+#define MBEDCRYPTO_CIPHER_BLKSIZE_MAX      8   /**< The longest block used by CMAC is that of 3DES. */
+#endif
+
+#if !defined(MBEDCRYPTO_CMAC_ALT)
+
+/**
+ * The CMAC context structure.
+ */
+struct mbedcrypto_cmac_context_t
+{
+    /** The internal state of the CMAC algorithm.  */
+    unsigned char       state[MBEDCRYPTO_CIPHER_BLKSIZE_MAX];
+
+    /** Unprocessed data - either data that was not block aligned and is still
+     *  pending processing, or the final block. */
+    unsigned char       unprocessed_block[MBEDCRYPTO_CIPHER_BLKSIZE_MAX];
+
+    /** The length of data pending processing. */
+    size_t              unprocessed_len;
+};
+
+#else  /* !MBEDCRYPTO_CMAC_ALT */
+#include "cmac_alt.h"
+#endif /* !MBEDCRYPTO_CMAC_ALT */
+
+/**
+ * \brief               This function sets the CMAC key, and prepares to authenticate
+ *                      the input data.
+ *                      Must be called with an initialized cipher context.
+ *
+ * \param ctx           The cipher context used for the CMAC operation, initialized
+ *                      as one of the following types: MBEDCRYPTO_CIPHER_AES_128_ECB,
+ *                      MBEDCRYPTO_CIPHER_AES_192_ECB, MBEDCRYPTO_CIPHER_AES_256_ECB,
+ *                      or MBEDCRYPTO_CIPHER_DES_EDE3_ECB.
+ * \param key           The CMAC key.
+ * \param keybits       The length of the CMAC key in bits.
+ *                      Must be supported by the cipher.
+ *
+ * \return              \c 0 on success.
+ * \return              A cipher-specific error code on failure.
+ */
+int mbedcrypto_cipher_cmac_starts( mbedcrypto_cipher_context_t *ctx,
+                                const unsigned char *key, size_t keybits );
+
+/**
+ * \brief               This function feeds an input buffer into an ongoing CMAC
+ *                      computation.
+ *
+ *                      It is called between mbedcrypto_cipher_cmac_starts() or
+ *                      mbedcrypto_cipher_cmac_reset(), and mbedcrypto_cipher_cmac_finish().
+ *                      Can be called repeatedly.
+ *
+ * \param ctx           The cipher context used for the CMAC operation.
+ * \param input         The buffer holding the input data.
+ * \param ilen          The length of the input data.
+ *
+ * \return             \c 0 on success.
+ * \return             #MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA
+ *                     if parameter verification fails.
+ */
+int mbedcrypto_cipher_cmac_update( mbedcrypto_cipher_context_t *ctx,
+                                const unsigned char *input, size_t ilen );
+
+/**
+ * \brief               This function finishes the CMAC operation, and writes
+ *                      the result to the output buffer.
+ *
+ *                      It is called after mbedcrypto_cipher_cmac_update().
+ *                      It can be followed by mbedcrypto_cipher_cmac_reset() and
+ *                      mbedcrypto_cipher_cmac_update(), or mbedcrypto_cipher_free().
+ *
+ * \param ctx           The cipher context used for the CMAC operation.
+ * \param output        The output buffer for the CMAC checksum result.
+ *
+ * \return              \c 0 on success.
+ * \return              #MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA
+ *                      if parameter verification fails.
+ */
+int mbedcrypto_cipher_cmac_finish( mbedcrypto_cipher_context_t *ctx,
+                                unsigned char *output );
+
+/**
+ * \brief               This function prepares the authentication of another
+ *                      message with the same key as the previous CMAC
+ *                      operation.
+ *
+ *                      It is called after mbedcrypto_cipher_cmac_finish()
+ *                      and before mbedcrypto_cipher_cmac_update().
+ *
+ * \param ctx           The cipher context used for the CMAC operation.
+ *
+ * \return              \c 0 on success.
+ * \return              #MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA
+ *                      if parameter verification fails.
+ */
+int mbedcrypto_cipher_cmac_reset( mbedcrypto_cipher_context_t *ctx );
+
+/**
+ * \brief               This function calculates the full generic CMAC
+ *                      on the input buffer with the provided key.
+ *
+ *                      The function allocates the context, performs the
+ *                      calculation, and frees the context.
+ *
+ *                      The CMAC result is calculated as
+ *                      output = generic CMAC(cmac key, input buffer).
+ *
+ *
+ * \param cipher_info   The cipher information.
+ * \param key           The CMAC key.
+ * \param keylen        The length of the CMAC key in bits.
+ * \param input         The buffer holding the input data.
+ * \param ilen          The length of the input data.
+ * \param output        The buffer for the generic CMAC result.
+ *
+ * \return              \c 0 on success.
+ * \return              #MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA
+ *                      if parameter verification fails.
+ */
+int mbedcrypto_cipher_cmac( const mbedcrypto_cipher_info_t *cipher_info,
+                         const unsigned char *key, size_t keylen,
+                         const unsigned char *input, size_t ilen,
+                         unsigned char *output );
+
+#if defined(MBEDCRYPTO_AES_C)
+/**
+ * \brief           This function implements the AES-CMAC-PRF-128 pseudorandom
+ *                  function, as defined in
+ *                  <em>RFC-4615: The Advanced Encryption Standard-Cipher-based
+ *                  Message Authentication Code-Pseudo-Random Function-128
+ *                  (AES-CMAC-PRF-128) Algorithm for the Internet Key
+ *                  Exchange Protocol (IKE).</em>
+ *
+ * \param key       The key to use.
+ * \param key_len   The key length in Bytes.
+ * \param input     The buffer holding the input data.
+ * \param in_len    The length of the input data in Bytes.
+ * \param output    The buffer holding the generated 16 Bytes of
+ *                  pseudorandom output.
+ *
+ * \return          \c 0 on success.
+ */
+int mbedcrypto_aes_cmac_prf_128( const unsigned char *key, size_t key_len,
+                              const unsigned char *input, size_t in_len,
+                              unsigned char output[16] );
+#endif /* MBEDCRYPTO_AES_C */
+
+#if defined(MBEDCRYPTO_SELF_TEST) && ( defined(MBEDCRYPTO_AES_C) || defined(MBEDCRYPTO_DES_C) )
+/**
+ * \brief          The CMAC checkup routine.
+ *
+ * \return         \c 0 on success.
+ * \return         \c 1 on failure.
+ */
+int mbedcrypto_cmac_self_test( int verbose );
+#endif /* MBEDCRYPTO_SELF_TEST && ( MBEDCRYPTO_AES_C || MBEDCRYPTO_DES_C ) */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDCRYPTO_CMAC_H */
diff --git a/include/mbedcrypto/config.h b/include/mbedcrypto/config.h
new file mode 100644
index 0000000..502b42f
--- /dev/null
+++ b/include/mbedcrypto/config.h
@@ -0,0 +1,1753 @@
+/**
+ * \file config.h
+ *
+ * \brief Configuration with all cryptography features and no X.509 or TLS.
+ *
+ * This configuration is intended to prototype the PSA reference implementation.
+ */
+/*
+ *  Copyright (C) 2006-2018, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#ifndef MBEDCRYPTO_CONFIG_H
+#define MBEDCRYPTO_CONFIG_H
+
+#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+
+/**
+ * \name SECTION: System support
+ *
+ * This section sets system specific settings.
+ * \{
+ */
+
+/**
+ * \def MBEDCRYPTO_HAVE_ASM
+ *
+ * The compiler has support for asm().
+ *
+ * Requires support for asm() in compiler.
+ *
+ * Used in:
+ *      library/timing.c
+ *      library/padlock.c
+ *      include/mbedcrypto/bn_mul.h
+ *
+ * Comment to disable the use of assembly code.
+ */
+#define MBEDCRYPTO_HAVE_ASM
+
+/**
+ * \def MBEDCRYPTO_NO_UDBL_DIVISION
+ *
+ * The platform lacks support for double-width integer division (64-bit
+ * division on a 32-bit platform, 128-bit division on a 64-bit platform).
+ *
+ * Used in:
+ *      include/mbedcrypto/bignum.h
+ *      library/bignum.c
+ *
+ * The bignum code uses double-width division to speed up some operations.
+ * Double-width division is often implemented in software that needs to
+ * be linked with the program. The presence of a double-width integer
+ * type is usually detected automatically through preprocessor macros,
+ * but the automatic detection cannot know whether the code needs to
+ * and can be linked with an implementation of division for that type.
+ * By default division is assumed to be usable if the type is present.
+ * Uncomment this option to prevent the use of double-width division.
+ *
+ * Note that division for the native integer type is always required.
+ * Furthermore, a 64-bit type is always required even on a 32-bit
+ * platform, but it need not support multiplication or division. In some
+ * cases it is also desirable to disable some double-width operations. For
+ * example, if double-width division is implemented in software, disabling
+ * it can reduce code size in some embedded targets.
+ */
+//#define MBEDCRYPTO_NO_UDBL_DIVISION
+
+/**
+ * \def MBEDCRYPTO_HAVE_SSE2
+ *
+ * CPU supports SSE2 instruction set.
+ *
+ * Uncomment if the CPU supports SSE2 (IA-32 specific).
+ */
+//#define MBEDCRYPTO_HAVE_SSE2
+
+/**
+ * \def MBEDCRYPTO_PLATFORM_MEMORY
+ *
+ * Enable the memory allocation layer.
+ *
+ * By default Mbed Crypto uses the system-provided calloc() and free().
+ * This allows different allocators (self-implemented or provided) to be
+ * provided to the platform abstraction layer.
+ *
+ * Enabling MBEDCRYPTO_PLATFORM_MEMORY without the
+ * MBEDCRYPTO_PLATFORM_{FREE,CALLOC}_MACROs will provide
+ * "mbedcrypto_platform_set_calloc_free()" allowing you to set an alternative calloc() and
+ * free() function pointer at runtime.
+ *
+ * Enabling MBEDCRYPTO_PLATFORM_MEMORY and specifying
+ * MBEDCRYPTO_PLATFORM_{CALLOC,FREE}_MACROs will allow you to specify the
+ * alternate function at compile time.
+ *
+ * Requires: MBEDCRYPTO_PLATFORM_C
+ *
+ * Enable this layer to allow use of alternative memory allocators.
+ */
+//#define MBEDCRYPTO_PLATFORM_MEMORY
+
+/**
+ * \def MBEDCRYPTO_PLATFORM_NO_STD_FUNCTIONS
+ *
+ * Do not assign standard functions in the platform layer (e.g. calloc() to
+ * MBEDCRYPTO_PLATFORM_STD_CALLOC and printf() to MBEDCRYPTO_PLATFORM_STD_PRINTF)
+ *
+ * This makes sure there are no linking errors on platforms that do not support
+ * these functions. You will HAVE to provide alternatives, either at runtime
+ * via the platform_set_xxx() functions or at compile time by setting
+ * the MBEDCRYPTO_PLATFORM_STD_XXX defines, or enabling a
+ * MBEDCRYPTO_PLATFORM_XXX_MACRO.
+ *
+ * Requires: MBEDCRYPTO_PLATFORM_C
+ *
+ * Uncomment to prevent default assignment of standard functions in the
+ * platform layer.
+ */
+//#define MBEDCRYPTO_PLATFORM_NO_STD_FUNCTIONS
+
+/**
+ * \def MBEDCRYPTO_PLATFORM_EXIT_ALT
+ *
+ * MBEDCRYPTO_PLATFORM_XXX_ALT: Uncomment a macro to let Mbed Crypto support the
+ * function in the platform abstraction layer.
+ *
+ * Example: In case you uncomment MBEDCRYPTO_PLATFORM_PRINTF_ALT, Mbed Crypto will
+ * provide a function "mbedcrypto_platform_set_printf()" that allows you to set an
+ * alternative printf function pointer.
+ *
+ * All these define require MBEDCRYPTO_PLATFORM_C to be defined!
+ *
+ * \note MBEDCRYPTO_PLATFORM_SNPRINTF_ALT is required on Windows;
+ * it will be enabled automatically by check_config.h
+ *
+ * \warning MBEDCRYPTO_PLATFORM_XXX_ALT cannot be defined at the same time as
+ * MBEDCRYPTO_PLATFORM_XXX_MACRO!
+ *
+ * Uncomment a macro to enable alternate implementation of specific base
+ * platform function
+ */
+//#define MBEDCRYPTO_PLATFORM_EXIT_ALT
+//#define MBEDCRYPTO_PLATFORM_FPRINTF_ALT
+//#define MBEDCRYPTO_PLATFORM_PRINTF_ALT
+//#define MBEDCRYPTO_PLATFORM_SNPRINTF_ALT
+//#define MBEDCRYPTO_PLATFORM_NV_SEED_ALT
+//#define MBEDCRYPTO_PLATFORM_SETUP_TEARDOWN_ALT
+
+/**
+ * \def MBEDCRYPTO_DEPRECATED_WARNING
+ *
+ * Mark deprecated functions so that they generate a warning if used.
+ * Functions deprecated in one version will usually be removed in the next
+ * version. You can enable this to help you prepare the transition to a new
+ * major version by making sure your code is not using these functions.
+ *
+ * This only works with GCC and Clang. With other compilers, you may want to
+ * use MBEDCRYPTO_DEPRECATED_REMOVED
+ *
+ * Uncomment to get warnings on using deprecated functions.
+ */
+//#define MBEDCRYPTO_DEPRECATED_WARNING
+
+/**
+ * \def MBEDCRYPTO_DEPRECATED_REMOVED
+ *
+ * Remove deprecated functions so that they generate an error if used.
+ * Functions deprecated in one version will usually be removed in the next
+ * version. You can enable this to help you prepare the transition to a new
+ * major version by making sure your code is not using these functions.
+ *
+ * Uncomment to get errors on using deprecated functions.
+ */
+//#define MBEDCRYPTO_DEPRECATED_REMOVED
+
+/* \} name SECTION: System support */
+
+/**
+ * \name SECTION: Mbed Crypto feature support
+ *
+ * This section sets support for features that are or are not needed
+ * within the modules that are enabled.
+ * \{
+ */
+
+/**
+ * \def MBEDCRYPTO_AES_ALT
+ *
+ * MBEDCRYPTO__MODULE_NAME__ALT: Uncomment a macro to let Mbed Crypto use your
+ * alternate core implementation of a symmetric crypto, an arithmetic or hash
+ * module (e.g. platform specific assembly optimized implementations). Keep
+ * in mind that the function prototypes should remain the same.
+ *
+ * This replaces the whole module. If you only want to replace one of the
+ * functions, use one of the MBEDCRYPTO__FUNCTION_NAME__ALT flags.
+ *
+ * Example: In case you uncomment MBEDCRYPTO_AES_ALT, Mbed Crypto will no longer
+ * provide the "struct mbedcrypto_aes_context" definition and omit the base
+ * function declarations and implementations. "aes_alt.h" will be included from
+ * "aes.h" to include the new function definitions.
+ *
+ * Uncomment a macro to enable alternate implementation of the corresponding
+ * module.
+ *
+ * \warning   MD2, MD4, MD5, ARC4, DES and SHA-1 are considered weak and their
+ *            use constitutes a security risk. If possible, we recommend
+ *            avoiding dependencies on them, and considering stronger message
+ *            digests and ciphers instead.
+ *
+ */
+//#define MBEDCRYPTO_AES_ALT
+//#define MBEDCRYPTO_ARC4_ALT
+//#define MBEDCRYPTO_BLOWFISH_ALT
+//#define MBEDCRYPTO_CAMELLIA_ALT
+//#define MBEDCRYPTO_CCM_ALT
+//#define MBEDCRYPTO_CMAC_ALT
+//#define MBEDCRYPTO_DES_ALT
+//#define MBEDCRYPTO_DHM_ALT
+//#define MBEDCRYPTO_ECJPAKE_ALT
+//#define MBEDCRYPTO_GCM_ALT
+//#define MBEDCRYPTO_MD2_ALT
+//#define MBEDCRYPTO_MD4_ALT
+//#define MBEDCRYPTO_MD5_ALT
+//#define MBEDCRYPTO_RIPEMD160_ALT
+//#define MBEDCRYPTO_RSA_ALT
+//#define MBEDCRYPTO_SHA1_ALT
+//#define MBEDCRYPTO_SHA256_ALT
+//#define MBEDCRYPTO_SHA512_ALT
+//#define MBEDCRYPTO_XTEA_ALT
+/*
+ * When replacing the elliptic curve module, pleace consider, that it is
+ * implemented with two .c files:
+ *      - ecp.c
+ *      - ecp_curves.c
+ * You can replace them very much like all the other MBEDCRYPTO__MODULE_NAME__ALT
+ * macros as described above. The only difference is that you have to make sure
+ * that you provide functionality for both .c files.
+ */
+//#define MBEDCRYPTO_ECP_ALT
+
+/**
+ * \def MBEDCRYPTO_MD2_PROCESS_ALT
+ *
+ * MBEDCRYPTO__FUNCTION_NAME__ALT: Uncomment a macro to let Mbed Crypto use you
+ * alternate core implementation of symmetric crypto or hash function. Keep in
+ * mind that function prototypes should remain the same.
+ *
+ * This replaces only one function. The header file from Mbed Crypto is still
+ * used, in contrast to the MBEDCRYPTO__MODULE_NAME__ALT flags.
+ *
+ * Example: In case you uncomment MBEDCRYPTO_SHA256_PROCESS_ALT, Mbed Crypto will
+ * no longer provide the mbedcrypto_sha1_process() function, but it will still provide
+ * the other function (using your mbedcrypto_sha1_process() function) and the definition
+ * of mbedcrypto_sha1_context, so your implementation of mbedcrypto_sha1_process must be compatible
+ * with this definition.
+ *
+ * \note Because of a signature change, the core AES encryption and decryption routines are
+ *       currently named mbedcrypto_aes_internal_encrypt and mbedcrypto_aes_internal_decrypt,
+ *       respectively. When setting up alternative implementations, these functions should
+ *       be overriden, but the wrapper functions mbedcrypto_aes_decrypt and mbedcrypto_aes_encrypt
+ *       must stay untouched.
+ *
+ * \note If you use the AES_xxx_ALT macros, then is is recommended to also set
+ *       MBEDCRYPTO_AES_ROM_TABLES in order to help the linker garbage-collect the AES
+ *       tables.
+ *
+ * Uncomment a macro to enable alternate implementation of the corresponding
+ * function.
+ *
+ * \warning   MD2, MD4, MD5, DES and SHA-1 are considered weak and their use
+ *            constitutes a security risk. If possible, we recommend avoiding
+ *            dependencies on them, and considering stronger message digests
+ *            and ciphers instead.
+ *
+ */
+//#define MBEDCRYPTO_MD2_PROCESS_ALT
+//#define MBEDCRYPTO_MD4_PROCESS_ALT
+//#define MBEDCRYPTO_MD5_PROCESS_ALT
+//#define MBEDCRYPTO_RIPEMD160_PROCESS_ALT
+//#define MBEDCRYPTO_SHA1_PROCESS_ALT
+//#define MBEDCRYPTO_SHA256_PROCESS_ALT
+//#define MBEDCRYPTO_SHA512_PROCESS_ALT
+//#define MBEDCRYPTO_DES_SETKEY_ALT
+//#define MBEDCRYPTO_DES_CRYPT_ECB_ALT
+//#define MBEDCRYPTO_DES3_CRYPT_ECB_ALT
+//#define MBEDCRYPTO_AES_SETKEY_ENC_ALT
+//#define MBEDCRYPTO_AES_SETKEY_DEC_ALT
+//#define MBEDCRYPTO_AES_ENCRYPT_ALT
+//#define MBEDCRYPTO_AES_DECRYPT_ALT
+//#define MBEDCRYPTO_ECDH_GEN_PUBLIC_ALT
+//#define MBEDCRYPTO_ECDH_COMPUTE_SHARED_ALT
+//#define MBEDCRYPTO_ECDSA_VERIFY_ALT
+//#define MBEDCRYPTO_ECDSA_SIGN_ALT
+//#define MBEDCRYPTO_ECDSA_GENKEY_ALT
+
+/**
+ * \def MBEDCRYPTO_ECP_INTERNAL_ALT
+ *
+ * Expose a part of the internal interface of the Elliptic Curve Point module.
+ *
+ * MBEDCRYPTO_ECP__FUNCTION_NAME__ALT: Uncomment a macro to let Mbed Crypto use your
+ * alternative core implementation of elliptic curve arithmetic. Keep in mind
+ * that function prototypes should remain the same.
+ *
+ * This partially replaces one function. The header file from Mbed Crypto is still
+ * used, in contrast to the MBEDCRYPTO_ECP_ALT flag. The original implementation
+ * is still present and it is used for group structures not supported by the
+ * alternative.
+ *
+ * Any of these options become available by defining MBEDCRYPTO_ECP_INTERNAL_ALT
+ * and implementing the following functions:
+ *      unsigned char mbedcrypto_internal_ecp_grp_capable(
+ *          const mbedcrypto_ecp_group *grp )
+ *      int  mbedcrypto_internal_ecp_init( const mbedcrypto_ecp_group *grp )
+ *      void mbedcrypto_internal_ecp_deinit( const mbedcrypto_ecp_group *grp )
+ * The mbedcrypto_internal_ecp_grp_capable function should return 1 if the
+ * replacement functions implement arithmetic for the given group and 0
+ * otherwise.
+ * The functions mbedcrypto_internal_ecp_init and mbedcrypto_internal_ecp_deinit are
+ * called before and after each point operation and provide an opportunity to
+ * implement optimized set up and tear down instructions.
+ *
+ * Example: In case you uncomment MBEDCRYPTO_ECP_INTERNAL_ALT and
+ * MBEDCRYPTO_ECP_DOUBLE_JAC_ALT, Mbed Crypto will still provide the ecp_double_jac
+ * function, but will use your mbedcrypto_internal_ecp_double_jac if the group is
+ * supported (your mbedcrypto_internal_ecp_grp_capable function returns 1 when
+ * receives it as an argument). If the group is not supported then the original
+ * implementation is used. The other functions and the definition of
+ * mbedcrypto_ecp_group and mbedcrypto_ecp_point will not change, so your
+ * implementation of mbedcrypto_internal_ecp_double_jac and
+ * mbedcrypto_internal_ecp_grp_capable must be compatible with this definition.
+ *
+ * Uncomment a macro to enable alternate implementation of the corresponding
+ * function.
+ */
+/* Required for all the functions in this section */
+//#define MBEDCRYPTO_ECP_INTERNAL_ALT
+/* Support for Weierstrass curves with Jacobi representation */
+//#define MBEDCRYPTO_ECP_RANDOMIZE_JAC_ALT
+//#define MBEDCRYPTO_ECP_ADD_MIXED_ALT
+//#define MBEDCRYPTO_ECP_DOUBLE_JAC_ALT
+//#define MBEDCRYPTO_ECP_NORMALIZE_JAC_MANY_ALT
+//#define MBEDCRYPTO_ECP_NORMALIZE_JAC_ALT
+/* Support for curves with Montgomery arithmetic */
+//#define MBEDCRYPTO_ECP_DOUBLE_ADD_MXZ_ALT
+//#define MBEDCRYPTO_ECP_RANDOMIZE_MXZ_ALT
+//#define MBEDCRYPTO_ECP_NORMALIZE_MXZ_ALT
+
+/**
+ * \def MBEDCRYPTO_TEST_NULL_ENTROPY
+ *
+ * Enables testing and use of Mbed Crypto without any configured entropy sources.
+ * This permits use of the library on platforms before an entropy source has
+ * been integrated (see for example the MBEDCRYPTO_ENTROPY_HARDWARE_ALT or the
+ * MBEDCRYPTO_ENTROPY_NV_SEED switches).
+ *
+ * WARNING! This switch MUST be disabled in production builds, and is suitable
+ * only for development.
+ * Enabling the switch negates any security provided by the library.
+ *
+ * Requires MBEDCRYPTO_ENTROPY_C, MBEDCRYPTO_NO_DEFAULT_ENTROPY_SOURCES
+ *
+ */
+//#define MBEDCRYPTO_TEST_NULL_ENTROPY
+
+/**
+ * \def MBEDCRYPTO_ENTROPY_HARDWARE_ALT
+ *
+ * Uncomment this macro to let Mbed Crypto use your own implementation of a
+ * hardware entropy collector.
+ *
+ * Your function must be called \c mbedcrypto_hardware_poll(), have the same
+ * prototype as declared in entropy_poll.h, and accept NULL as first argument.
+ *
+ * Uncomment to use your own hardware entropy collector.
+ */
+//#define MBEDCRYPTO_ENTROPY_HARDWARE_ALT
+
+/**
+ * \def MBEDCRYPTO_AES_ROM_TABLES
+ *
+ * Use precomputed AES tables stored in ROM.
+ *
+ * Uncomment this macro to use precomputed AES tables stored in ROM.
+ * Comment this macro to generate AES tables in RAM at runtime.
+ *
+ * Tradeoff: Using precomputed ROM tables reduces RAM usage by ~8kb
+ * (or ~2kb if \c MBEDCRYPTO_AES_FEWER_TABLES is used) and reduces the
+ * initialization time before the first AES operation can be performed.
+ * It comes at the cost of additional ~8kb ROM use (resp. ~2kb if \c
+ * MBEDCRYPTO_AES_FEWER_TABLES below is used), and potentially degraded
+ * performance if ROM access is slower than RAM access.
+ *
+ * This option is independent of \c MBEDCRYPTO_AES_FEWER_TABLES.
+ *
+ */
+//#define MBEDCRYPTO_AES_ROM_TABLES
+
+/**
+ * \def MBEDCRYPTO_AES_FEWER_TABLES
+ *
+ * Use less ROM/RAM for AES tables.
+ *
+ * Uncommenting this macro omits 75% of the AES tables from
+ * ROM / RAM (depending on the value of \c MBEDCRYPTO_AES_ROM_TABLES)
+ * by computing their values on the fly during operations
+ * (the tables are entry-wise rotations of one another).
+ *
+ * Tradeoff: Uncommenting this reduces the RAM / ROM footprint
+ * by ~6kb but at the cost of more arithmetic operations during
+ * runtime. Specifically, one has to compare 4 accesses within
+ * different tables to 4 accesses with additional arithmetic
+ * operations within the same table. The performance gain/loss
+ * depends on the system and memory details.
+ *
+ * This option is independent of \c MBEDCRYPTO_AES_ROM_TABLES.
+ *
+ */
+//#define MBEDCRYPTO_AES_FEWER_TABLES
+
+/**
+ * \def MBEDCRYPTO_CAMELLIA_SMALL_MEMORY
+ *
+ * Use less ROM for the Camellia implementation (saves about 768 bytes).
+ *
+ * Uncomment this macro to use less memory for Camellia.
+ */
+//#define MBEDCRYPTO_CAMELLIA_SMALL_MEMORY
+
+/**
+ * \def MBEDCRYPTO_CIPHER_MODE_CBC
+ *
+ * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers.
+ */
+#define MBEDCRYPTO_CIPHER_MODE_CBC
+
+/**
+ * \def MBEDCRYPTO_CIPHER_MODE_CFB
+ *
+ * Enable Cipher Feedback mode (CFB) for symmetric ciphers.
+ */
+#define MBEDCRYPTO_CIPHER_MODE_CFB
+
+/**
+ * \def MBEDCRYPTO_CIPHER_MODE_CTR
+ *
+ * Enable Counter Block Cipher mode (CTR) for symmetric ciphers.
+ */
+#define MBEDCRYPTO_CIPHER_MODE_CTR
+
+/**
+ * \def MBEDCRYPTO_CIPHER_PADDING_PKCS7
+ *
+ * MBEDCRYPTO_CIPHER_PADDING_XXX: Uncomment or comment macros to add support for
+ * specific padding modes in the cipher layer with cipher modes that support
+ * padding (e.g. CBC)
+ *
+ * If you disable all padding modes, only full blocks can be used with CBC.
+ *
+ * Enable padding modes in the cipher layer.
+ */
+#define MBEDCRYPTO_CIPHER_PADDING_PKCS7
+#define MBEDCRYPTO_CIPHER_PADDING_ONE_AND_ZEROS
+#define MBEDCRYPTO_CIPHER_PADDING_ZEROS_AND_LEN
+#define MBEDCRYPTO_CIPHER_PADDING_ZEROS
+
+/**
+ * \def MBEDCRYPTO_ECP_DP_SECP192R1_ENABLED
+ *
+ * MBEDCRYPTO_ECP_XXXX_ENABLED: Enables specific curves within the Elliptic Curve
+ * module.  By default all supported curves are enabled.
+ *
+ * Comment macros to disable the curve and functions for it
+ */
+#define MBEDCRYPTO_ECP_DP_SECP192R1_ENABLED
+#define MBEDCRYPTO_ECP_DP_SECP224R1_ENABLED
+#define MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED
+#define MBEDCRYPTO_ECP_DP_SECP384R1_ENABLED
+#define MBEDCRYPTO_ECP_DP_SECP521R1_ENABLED
+#define MBEDCRYPTO_ECP_DP_SECP192K1_ENABLED
+#define MBEDCRYPTO_ECP_DP_SECP224K1_ENABLED
+#define MBEDCRYPTO_ECP_DP_SECP256K1_ENABLED
+#define MBEDCRYPTO_ECP_DP_BP256R1_ENABLED
+#define MBEDCRYPTO_ECP_DP_BP384R1_ENABLED
+#define MBEDCRYPTO_ECP_DP_BP512R1_ENABLED
+#define MBEDCRYPTO_ECP_DP_CURVE25519_ENABLED
+#define MBEDCRYPTO_ECP_DP_CURVE448_ENABLED
+
+/**
+ * \def MBEDCRYPTO_ECP_NIST_OPTIM
+ *
+ * Enable specific 'modulo p' routines for each NIST prime.
+ * Depending on the prime and architecture, makes operations 4 to 8 times
+ * faster on the corresponding curve.
+ *
+ * Comment this macro to disable NIST curves optimisation.
+ */
+#define MBEDCRYPTO_ECP_NIST_OPTIM
+
+/**
+ * \def MBEDCRYPTO_ECDSA_DETERMINISTIC
+ *
+ * Enable deterministic ECDSA (RFC 6979).
+ * Standard ECDSA is "fragile" in the sense that lack of entropy when signing
+ * may result in a compromise of the long-term signing key. This is avoided by
+ * the deterministic variant.
+ *
+ * Requires: MBEDCRYPTO_HMAC_DRBG_C
+ *
+ * Comment this macro to disable deterministic ECDSA.
+ */
+#define MBEDCRYPTO_ECDSA_DETERMINISTIC
+
+/**
+ * \def MBEDCRYPTO_PK_PARSE_EC_EXTENDED
+ *
+ * Enhance support for reading EC keys using variants of SEC1 not allowed by
+ * RFC 5915 and RFC 5480.
+ *
+ * Currently this means parsing the SpecifiedECDomain choice of EC
+ * parameters (only known groups are supported, not arbitrary domains, to
+ * avoid validation issues).
+ *
+ * Disable if you only need to support RFC 5915 + 5480 key formats.
+ */
+#define MBEDCRYPTO_PK_PARSE_EC_EXTENDED
+
+/**
+ * \def MBEDCRYPTO_ERROR_STRERROR_DUMMY
+ *
+ * Enable a dummy error function to make use of mbedcrypto_strerror() in
+ * third party libraries easier when MBEDCRYPTO_ERROR_C is disabled
+ * (no effect when MBEDCRYPTO_ERROR_C is enabled).
+ *
+ * You can safely disable this if MBEDCRYPTO_ERROR_C is enabled, or if you're
+ * not using mbedcrypto_strerror() or error_strerror() in your application.
+ *
+ * Disable if you run into name conflicts and want to really remove the
+ * mbedcrypto_strerror()
+ */
+#define MBEDCRYPTO_ERROR_STRERROR_DUMMY
+
+/**
+ * \def MBEDCRYPTO_GENPRIME
+ *
+ * Enable the prime-number generation code.
+ *
+ * Requires: MBEDCRYPTO_BIGNUM_C
+ */
+#define MBEDCRYPTO_GENPRIME
+
+/**
+ * \def MBEDCRYPTO_FS_IO
+ *
+ * Enable functions that use the filesystem.
+ */
+#define MBEDCRYPTO_FS_IO
+
+/**
+ * \def MBEDCRYPTO_NO_DEFAULT_ENTROPY_SOURCES
+ *
+ * Do not add default entropy sources. These are the platform specific,
+ * mbedcrypto_timing_hardclock and HAVEGE based poll functions.
+ *
+ * This is useful to have more control over the added entropy sources in an
+ * application.
+ *
+ * Uncomment this macro to prevent loading of default entropy functions.
+ */
+//#define MBEDCRYPTO_NO_DEFAULT_ENTROPY_SOURCES
+
+/**
+ * \def MBEDCRYPTO_NO_PLATFORM_ENTROPY
+ *
+ * Do not use built-in platform entropy functions.
+ * This is useful if your platform does not support
+ * standards like the /dev/urandom or Windows CryptoAPI.
+ *
+ * Uncomment this macro to disable the built-in platform entropy functions.
+ */
+//#define MBEDCRYPTO_NO_PLATFORM_ENTROPY
+
+/**
+ * \def MBEDCRYPTO_ENTROPY_FORCE_SHA256
+ *
+ * Force the entropy accumulator to use a SHA-256 accumulator instead of the
+ * default SHA-512 based one (if both are available).
+ *
+ * Requires: MBEDCRYPTO_SHA256_C
+ *
+ * On 32-bit systems SHA-256 can be much faster than SHA-512. Use this option
+ * if you have performance concerns.
+ *
+ * This option is only useful if both MBEDCRYPTO_SHA256_C and
+ * MBEDCRYPTO_SHA512_C are defined. Otherwise the available hash module is used.
+ */
+//#define MBEDCRYPTO_ENTROPY_FORCE_SHA256
+
+/**
+ * \def MBEDCRYPTO_ENTROPY_NV_SEED
+ *
+ * Enable the non-volatile (NV) seed file-based entropy source.
+ * (Also enables the NV seed read/write functions in the platform layer)
+ *
+ * This is crucial (if not required) on systems that do not have a
+ * cryptographic entropy source (in hardware or kernel) available.
+ *
+ * Requires: MBEDCRYPTO_ENTROPY_C, MBEDCRYPTO_PLATFORM_C
+ *
+ * \note The read/write functions that are used by the entropy source are
+ *       determined in the platform layer, and can be modified at runtime and/or
+ *       compile-time depending on the flags (MBEDCRYPTO_PLATFORM_NV_SEED_*) used.
+ *
+ * \note If you use the default implementation functions that read a seedfile
+ *       with regular fopen(), please make sure you make a seedfile with the
+ *       proper name (defined in MBEDCRYPTO_PLATFORM_STD_NV_SEED_FILE) and at
+ *       least MBEDCRYPTO_ENTROPY_BLOCK_SIZE bytes in size that can be read from
+ *       and written to or you will get an entropy source error! The default
+ *       implementation will only use the first MBEDCRYPTO_ENTROPY_BLOCK_SIZE
+ *       bytes from the file.
+ *
+ * \note The entropy collector will write to the seed file before entropy is
+ *       given to an external source, to update it.
+ */
+//#define MBEDCRYPTO_ENTROPY_NV_SEED
+
+/**
+ * \def MBEDCRYPTO_MEMORY_DEBUG
+ *
+ * Enable debugging of buffer allocator memory issues. Automatically prints
+ * (to stderr) all (fatal) messages on memory allocation issues. Enables
+ * function for 'debug output' of allocated memory.
+ *
+ * Requires: MBEDCRYPTO_MEMORY_BUFFER_ALLOC_C
+ *
+ * Uncomment this macro to let the buffer allocator print out error messages.
+ */
+//#define MBEDCRYPTO_MEMORY_DEBUG
+
+/**
+ * \def MBEDCRYPTO_MEMORY_BACKTRACE
+ *
+ * Include backtrace information with each allocated block.
+ *
+ * Requires: MBEDCRYPTO_MEMORY_BUFFER_ALLOC_C
+ *           GLIBC-compatible backtrace() an backtrace_symbols() support
+ *
+ * Uncomment this macro to include backtrace information
+ */
+//#define MBEDCRYPTO_MEMORY_BACKTRACE
+
+/**
+ * \def MBEDCRYPTO_PK_RSA_ALT_SUPPORT
+ *
+ * Support external private RSA keys (eg from a HSM) in the PK layer.
+ *
+ * Comment this macro to disable support for external private RSA keys.
+ */
+#define MBEDCRYPTO_PK_RSA_ALT_SUPPORT
+
+/**
+ * \def MBEDCRYPTO_PKCS1_V15
+ *
+ * Enable support for PKCS#1 v1.5 encoding.
+ *
+ * Requires: MBEDCRYPTO_RSA_C
+ *
+ * This enables support for PKCS#1 v1.5 operations.
+ */
+#define MBEDCRYPTO_PKCS1_V15
+
+/**
+ * \def MBEDCRYPTO_PKCS1_V21
+ *
+ * Enable support for PKCS#1 v2.1 encoding.
+ *
+ * Requires: MBEDCRYPTO_MD_C, MBEDCRYPTO_RSA_C
+ *
+ * This enables support for RSAES-OAEP and RSASSA-PSS operations.
+ */
+#define MBEDCRYPTO_PKCS1_V21
+
+/**
+ * \def MBEDCRYPTO_PSA_CRYPTO_SPM
+ *
+ * When MBEDCRYPTO_PSA_CRYPTO_SPM is defined, the code is built for SPM (Secure
+ * Partition Manager) integration which separates the code into two parts: a
+ * NSPE (Non-Secure Process Environment) and an SPE (Secure Process
+ * Environment).
+ *
+ * Module:  library/psa_crypto.c
+ * Requires: MBEDCRYPTO_PSA_CRYPTO_C
+ *
+ */
+//#define MBEDCRYPTO_PSA_CRYPTO_SPM
+
+/**
+ * \def MBEDCRYPTO_RSA_NO_CRT
+ *
+ * Do not use the Chinese Remainder Theorem for the RSA private operation.
+ *
+ * Uncomment this macro to disable the use of CRT in RSA.
+ *
+ */
+//#define MBEDCRYPTO_RSA_NO_CRT
+
+/**
+ * \def MBEDCRYPTO_SELF_TEST
+ *
+ * Enable the checkup functions (*_self_test).
+ */
+#define MBEDCRYPTO_SELF_TEST
+
+/**
+ * \def MBEDCRYPTO_SHA256_SMALLER
+ *
+ * Enable an implementation of SHA-256 that has lower ROM footprint but also
+ * lower performance.
+ *
+ * The default implementation is meant to be a reasonnable compromise between
+ * performance and size. This version optimizes more aggressively for size at
+ * the expense of performance. Eg on Cortex-M4 it reduces the size of
+ * mbedcrypto_sha256_process() from ~2KB to ~0.5KB for a performance hit of about
+ * 30%.
+ *
+ * Uncomment to enable the smaller implementation of SHA256.
+ */
+//#define MBEDCRYPTO_SHA256_SMALLER
+
+/**
+ * \def MBEDCRYPTO_THREADING_ALT
+ *
+ * Provide your own alternate threading implementation.
+ *
+ * Requires: MBEDCRYPTO_THREADING_C
+ *
+ * Uncomment this to allow your own alternate threading implementation.
+ */
+//#define MBEDCRYPTO_THREADING_ALT
+
+/**
+ * \def MBEDCRYPTO_THREADING_PTHREAD
+ *
+ * Enable the pthread wrapper layer for the threading layer.
+ *
+ * Requires: MBEDCRYPTO_THREADING_C
+ *
+ * Uncomment this to enable pthread mutexes.
+ */
+//#define MBEDCRYPTO_THREADING_PTHREAD
+
+/**
+ * \def MBEDCRYPTO_VERSION_FEATURES
+ *
+ * Allow run-time checking of compile-time enabled features. Thus allowing users
+ * to check at run-time if the library is for instance compiled with threading
+ * support via mbedcrypto_version_check_feature().
+ *
+ * Requires: MBEDCRYPTO_VERSION_C
+ *
+ * Comment this to disable run-time checking and save ROM space
+ */
+#define MBEDCRYPTO_VERSION_FEATURES
+
+/* \} name SECTION: Mbed Crypto feature support */
+
+/**
+ * \name SECTION: Mbed Crypto modules
+ *
+ * This section enables or disables entire modules in Mbed Crypto
+ * \{
+ */
+
+/**
+ * \def MBEDCRYPTO_AESNI_C
+ *
+ * Enable AES-NI support on x86-64.
+ *
+ * Module:  library/aesni.c
+ * Caller:  library/aes.c
+ *
+ * Requires: MBEDCRYPTO_HAVE_ASM
+ *
+ * This modules adds support for the AES-NI instructions on x86-64
+ */
+#define MBEDCRYPTO_AESNI_C
+
+/**
+ * \def MBEDCRYPTO_AES_C
+ *
+ * Enable the AES block cipher.
+ *
+ * Module:  library/aes.c
+ * Caller:  library/ssl_tls.c
+ *          library/pem.c
+ *          library/ctr_drbg.c
+ *
+ * This module enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDCRYPTO_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
+ *      MBEDCRYPTO_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
+ *      MBEDCRYPTO_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
+ *      MBEDCRYPTO_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
+ *      MBEDCRYPTO_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
+ *      MBEDCRYPTO_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
+ *      MBEDCRYPTO_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
+ *      MBEDCRYPTO_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
+ *      MBEDCRYPTO_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
+ *      MBEDCRYPTO_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
+ *      MBEDCRYPTO_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
+ *      MBEDCRYPTO_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
+ *      MBEDCRYPTO_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
+ *      MBEDCRYPTO_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
+ *      MBEDCRYPTO_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
+ *      MBEDCRYPTO_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
+ *      MBEDCRYPTO_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
+ *      MBEDCRYPTO_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
+ *      MBEDCRYPTO_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
+ *      MBEDCRYPTO_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
+ *      MBEDCRYPTO_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+ *      MBEDCRYPTO_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+ *      MBEDCRYPTO_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
+ *      MBEDCRYPTO_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
+ *      MBEDCRYPTO_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
+ *      MBEDCRYPTO_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+ *      MBEDCRYPTO_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+ *      MBEDCRYPTO_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
+ *      MBEDCRYPTO_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
+ *      MBEDCRYPTO_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+ *      MBEDCRYPTO_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
+ *      MBEDCRYPTO_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384
+ *      MBEDCRYPTO_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
+ *      MBEDCRYPTO_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA
+ *      MBEDCRYPTO_TLS_DHE_PSK_WITH_AES_256_CBC_SHA
+ *      MBEDCRYPTO_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
+ *      MBEDCRYPTO_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
+ *      MBEDCRYPTO_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
+ *      MBEDCRYPTO_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA
+ *      MBEDCRYPTO_TLS_DHE_PSK_WITH_AES_128_CBC_SHA
+ *      MBEDCRYPTO_TLS_RSA_WITH_AES_256_GCM_SHA384
+ *      MBEDCRYPTO_TLS_RSA_WITH_AES_256_CBC_SHA256
+ *      MBEDCRYPTO_TLS_RSA_WITH_AES_256_CBC_SHA
+ *      MBEDCRYPTO_TLS_RSA_WITH_AES_128_GCM_SHA256
+ *      MBEDCRYPTO_TLS_RSA_WITH_AES_128_CBC_SHA256
+ *      MBEDCRYPTO_TLS_RSA_WITH_AES_128_CBC_SHA
+ *      MBEDCRYPTO_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384
+ *      MBEDCRYPTO_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384
+ *      MBEDCRYPTO_TLS_RSA_PSK_WITH_AES_256_CBC_SHA
+ *      MBEDCRYPTO_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256
+ *      MBEDCRYPTO_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256
+ *      MBEDCRYPTO_TLS_RSA_PSK_WITH_AES_128_CBC_SHA
+ *      MBEDCRYPTO_TLS_PSK_WITH_AES_256_GCM_SHA384
+ *      MBEDCRYPTO_TLS_PSK_WITH_AES_256_CBC_SHA384
+ *      MBEDCRYPTO_TLS_PSK_WITH_AES_256_CBC_SHA
+ *      MBEDCRYPTO_TLS_PSK_WITH_AES_128_GCM_SHA256
+ *      MBEDCRYPTO_TLS_PSK_WITH_AES_128_CBC_SHA256
+ *      MBEDCRYPTO_TLS_PSK_WITH_AES_128_CBC_SHA
+ *
+ * PEM_PARSE uses AES for decrypting encrypted keys.
+ */
+#define MBEDCRYPTO_AES_C
+
+/**
+ * \def MBEDCRYPTO_ARC4_C
+ *
+ * Enable the ARCFOUR stream cipher.
+ *
+ * Module:  library/arc4.c
+ * Caller:  library/ssl_tls.c
+ *
+ * This module enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDCRYPTO_TLS_ECDH_ECDSA_WITH_RC4_128_SHA
+ *      MBEDCRYPTO_TLS_ECDH_RSA_WITH_RC4_128_SHA
+ *      MBEDCRYPTO_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
+ *      MBEDCRYPTO_TLS_ECDHE_RSA_WITH_RC4_128_SHA
+ *      MBEDCRYPTO_TLS_ECDHE_PSK_WITH_RC4_128_SHA
+ *      MBEDCRYPTO_TLS_DHE_PSK_WITH_RC4_128_SHA
+ *      MBEDCRYPTO_TLS_RSA_WITH_RC4_128_SHA
+ *      MBEDCRYPTO_TLS_RSA_WITH_RC4_128_MD5
+ *      MBEDCRYPTO_TLS_RSA_PSK_WITH_RC4_128_SHA
+ *      MBEDCRYPTO_TLS_PSK_WITH_RC4_128_SHA
+ *
+ * \warning   ARC4 is considered a weak cipher and its use constitutes a
+ *            security risk. If possible, we recommend avoidng dependencies on
+ *            it, and considering stronger ciphers instead.
+ *
+ */
+#define MBEDCRYPTO_ARC4_C
+
+/**
+ * \def MBEDCRYPTO_ASN1_PARSE_C
+ *
+ * Enable the generic ASN1 parser.
+ *
+ * Module:  library/asn1.c
+ * Caller:  library/x509.c
+ *          library/dhm.c
+ *          library/pkcs12.c
+ *          library/pkcs5.c
+ *          library/pkparse.c
+ */
+#define MBEDCRYPTO_ASN1_PARSE_C
+
+/**
+ * \def MBEDCRYPTO_ASN1_WRITE_C
+ *
+ * Enable the generic ASN1 writer.
+ *
+ * Module:  library/asn1write.c
+ * Caller:  library/ecdsa.c
+ *          library/pkwrite.c
+ *          library/x509_create.c
+ *          library/x509write_crt.c
+ *          library/x509write_csr.c
+ */
+#define MBEDCRYPTO_ASN1_WRITE_C
+
+/**
+ * \def MBEDCRYPTO_BASE64_C
+ *
+ * Enable the Base64 module.
+ *
+ * Module:  library/base64.c
+ * Caller:  library/pem.c
+ *
+ * This module is required for PEM support (required by X.509).
+ */
+#define MBEDCRYPTO_BASE64_C
+
+/**
+ * \def MBEDCRYPTO_BIGNUM_C
+ *
+ * Enable the multi-precision integer library.
+ *
+ * Module:  library/bignum.c
+ * Caller:  library/dhm.c
+ *          library/ecp.c
+ *          library/ecdsa.c
+ *          library/rsa.c
+ *          library/rsa_internal.c
+ *          library/ssl_tls.c
+ *
+ * This module is required for RSA, DHM and ECC (ECDH, ECDSA) support.
+ */
+#define MBEDCRYPTO_BIGNUM_C
+
+/**
+ * \def MBEDCRYPTO_BLOWFISH_C
+ *
+ * Enable the Blowfish block cipher.
+ *
+ * Module:  library/blowfish.c
+ */
+#define MBEDCRYPTO_BLOWFISH_C
+
+/**
+ * \def MBEDCRYPTO_CAMELLIA_C
+ *
+ * Enable the Camellia block cipher.
+ *
+ * Module:  library/camellia.c
+ * Caller:  library/ssl_tls.c
+ *
+ * This module enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDCRYPTO_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDCRYPTO_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDCRYPTO_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDCRYPTO_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDCRYPTO_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDCRYPTO_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDCRYPTO_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDCRYPTO_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDCRYPTO_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDCRYPTO_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDCRYPTO_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDCRYPTO_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDCRYPTO_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDCRYPTO_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
+ *      MBEDCRYPTO_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
+ *      MBEDCRYPTO_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDCRYPTO_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDCRYPTO_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDCRYPTO_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDCRYPTO_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDCRYPTO_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDCRYPTO_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
+ *      MBEDCRYPTO_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDCRYPTO_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDCRYPTO_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDCRYPTO_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDCRYPTO_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDCRYPTO_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDCRYPTO_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDCRYPTO_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
+ *      MBEDCRYPTO_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
+ *      MBEDCRYPTO_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDCRYPTO_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDCRYPTO_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
+ *      MBEDCRYPTO_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDCRYPTO_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDCRYPTO_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDCRYPTO_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDCRYPTO_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDCRYPTO_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDCRYPTO_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDCRYPTO_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ */
+#define MBEDCRYPTO_CAMELLIA_C
+
+/**
+ * \def MBEDCRYPTO_CCM_C
+ *
+ * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher.
+ *
+ * Module:  library/ccm.c
+ *
+ * Requires: MBEDCRYPTO_AES_C or MBEDCRYPTO_CAMELLIA_C
+ *
+ * This module enables the AES-CCM ciphersuites, if other requisites are
+ * enabled as well.
+ */
+#define MBEDCRYPTO_CCM_C
+
+/**
+ * \def MBEDCRYPTO_CIPHER_C
+ *
+ * Enable the generic cipher layer.
+ *
+ * Module:  library/cipher.c
+ * Caller:  library/ssl_tls.c
+ *
+ * Uncomment to enable generic cipher wrappers.
+ */
+#define MBEDCRYPTO_CIPHER_C
+
+/**
+ * \def MBEDCRYPTO_CMAC_C
+ *
+ * Enable the CMAC (Cipher-based Message Authentication Code) mode for block
+ * ciphers.
+ *
+ * Module:  library/cmac.c
+ *
+ * Requires: MBEDCRYPTO_AES_C or MBEDCRYPTO_DES_C
+ *
+ */
+#define MBEDCRYPTO_CMAC_C
+
+/**
+ * \def MBEDCRYPTO_CTR_DRBG_C
+ *
+ * Enable the CTR_DRBG AES-256-based random generator.
+ *
+ * Module:  library/ctr_drbg.c
+ * Caller:
+ *
+ * Requires: MBEDCRYPTO_AES_C
+ *
+ * This module provides the CTR_DRBG AES-256 random number generator.
+ */
+#define MBEDCRYPTO_CTR_DRBG_C
+
+/**
+ * \def MBEDCRYPTO_DES_C
+ *
+ * Enable the DES block cipher.
+ *
+ * Module:  library/des.c
+ * Caller:  library/pem.c
+ *          library/ssl_tls.c
+ *
+ * This module enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDCRYPTO_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDCRYPTO_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDCRYPTO_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDCRYPTO_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDCRYPTO_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDCRYPTO_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA
+ *      MBEDCRYPTO_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA
+ *      MBEDCRYPTO_TLS_RSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDCRYPTO_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA
+ *      MBEDCRYPTO_TLS_PSK_WITH_3DES_EDE_CBC_SHA
+ *
+ * PEM_PARSE uses DES/3DES for decrypting encrypted keys.
+ *
+ * \warning   DES is considered a weak cipher and its use constitutes a
+ *            security risk. We recommend considering stronger ciphers instead.
+ */
+#define MBEDCRYPTO_DES_C
+
+/**
+ * \def MBEDCRYPTO_DHM_C
+ *
+ * Enable the Diffie-Hellman-Merkle module.
+ *
+ * Module:  library/dhm.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *
+ * This module is used by the following key exchanges:
+ *      DHE-RSA, DHE-PSK
+ *
+ * \warning    Using DHE constitutes a security risk as it
+ *             is not possible to validate custom DH parameters.
+ *             If possible, it is recommended users should consider
+ *             preferring other methods of key exchange.
+ *             See dhm.h for more details.
+ *
+ */
+#define MBEDCRYPTO_DHM_C
+
+/**
+ * \def MBEDCRYPTO_ECDH_C
+ *
+ * Enable the elliptic curve Diffie-Hellman library.
+ *
+ * Module:  library/ecdh.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *
+ * This module is used by the following key exchanges:
+ *      ECDHE-ECDSA, ECDHE-RSA, DHE-PSK
+ *
+ * Requires: MBEDCRYPTO_ECP_C
+ */
+#define MBEDCRYPTO_ECDH_C
+
+/**
+ * \def MBEDCRYPTO_ECDSA_C
+ *
+ * Enable the elliptic curve DSA library.
+ *
+ * Module:  library/ecdsa.c
+ * Caller:
+ *
+ * This module is used by the following key exchanges:
+ *      ECDHE-ECDSA
+ *
+ * Requires: MBEDCRYPTO_ECP_C, MBEDCRYPTO_ASN1_WRITE_C, MBEDCRYPTO_ASN1_PARSE_C
+ */
+#define MBEDCRYPTO_ECDSA_C
+
+/**
+ * \def MBEDCRYPTO_ECJPAKE_C
+ *
+ * Enable the elliptic curve J-PAKE library.
+ *
+ * \warning This is currently experimental. EC J-PAKE support is based on the
+ * Thread v1.0.0 specification; incompatible changes to the specification
+ * might still happen. For this reason, this is disabled by default.
+ *
+ * Module:  library/ecjpake.c
+ * Caller:
+ *
+ * This module is used by the following key exchanges:
+ *      ECJPAKE
+ *
+ * Requires: MBEDCRYPTO_ECP_C, MBEDCRYPTO_MD_C
+ */
+#define MBEDCRYPTO_ECJPAKE_C
+
+/**
+ * \def MBEDCRYPTO_ECP_C
+ *
+ * Enable the elliptic curve over GF(p) library.
+ *
+ * Module:  library/ecp.c
+ * Caller:  library/ecdh.c
+ *          library/ecdsa.c
+ *          library/ecjpake.c
+ *
+ * Requires: MBEDCRYPTO_BIGNUM_C and at least one MBEDCRYPTO_ECP_DP_XXX_ENABLED
+ */
+#define MBEDCRYPTO_ECP_C
+
+/**
+ * \def MBEDCRYPTO_ENTROPY_C
+ *
+ * Enable the platform-specific entropy code.
+ *
+ * Module:  library/entropy.c
+ * Caller:
+ *
+ * Requires: MBEDCRYPTO_SHA512_C or MBEDCRYPTO_SHA256_C
+ *
+ * This module provides a generic entropy pool
+ */
+#define MBEDCRYPTO_ENTROPY_C
+
+/**
+ * \def MBEDCRYPTO_ERROR_C
+ *
+ * Enable error code to error string conversion.
+ *
+ * Module:  library/error.c
+ * Caller:
+ *
+ * This module enables mbedcrypto_strerror().
+ */
+#define MBEDCRYPTO_ERROR_C
+
+/**
+ * \def MBEDCRYPTO_GCM_C
+ *
+ * Enable the Galois/Counter Mode (GCM) for AES.
+ *
+ * Module:  library/gcm.c
+ *
+ * Requires: MBEDCRYPTO_AES_C or MBEDCRYPTO_CAMELLIA_C
+ *
+ * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other
+ * requisites are enabled as well.
+ */
+#define MBEDCRYPTO_GCM_C
+
+/**
+ * \def MBEDCRYPTO_HMAC_DRBG_C
+ *
+ * Enable the HMAC_DRBG random generator.
+ *
+ * Module:  library/hmac_drbg.c
+ * Caller:
+ *
+ * Requires: MBEDCRYPTO_MD_C
+ *
+ * Uncomment to enable the HMAC_DRBG random number geerator.
+ */
+#define MBEDCRYPTO_HMAC_DRBG_C
+
+/**
+ * \def MBEDCRYPTO_MD_C
+ *
+ * Enable the generic message digest layer.
+ *
+ * Module:  library/md.c
+ * Caller:
+ *
+ * Uncomment to enable generic message digest wrappers.
+ */
+#define MBEDCRYPTO_MD_C
+
+/**
+ * \def MBEDCRYPTO_MD2_C
+ *
+ * Enable the MD2 hash algorithm.
+ *
+ * Module:  library/md2.c
+ * Caller:
+ *
+ * Uncomment to enable support for (rare) MD2-signed X.509 certs.
+ *
+ * \warning   MD2 is considered a weak message digest and its use constitutes a
+ *            security risk. If possible, we recommend avoiding dependencies on
+ *            it, and considering stronger message digests instead.
+ *
+ */
+#define MBEDCRYPTO_MD2_C
+
+/**
+ * \def MBEDCRYPTO_MD4_C
+ *
+ * Enable the MD4 hash algorithm.
+ *
+ * Module:  library/md4.c
+ * Caller:
+ *
+ * Uncomment to enable support for (rare) MD4-signed X.509 certs.
+ *
+ * \warning   MD4 is considered a weak message digest and its use constitutes a
+ *            security risk. If possible, we recommend avoiding dependencies on
+ *            it, and considering stronger message digests instead.
+ *
+ */
+#define MBEDCRYPTO_MD4_C
+
+/**
+ * \def MBEDCRYPTO_MD5_C
+ *
+ * Enable the MD5 hash algorithm.
+ *
+ * Module:  library/md5.c
+ * Caller:  library/md.c
+ *          library/pem.c
+ *          library/ssl_tls.c
+ *
+ * This module is required for SSL/TLS up to version 1.1, and for TLS 1.2
+ * depending on the handshake parameters. Further, it is used for checking
+ * MD5-signed certificates, and for PBKDF1 when decrypting PEM-encoded
+ * encrypted keys.
+ *
+ * \warning   MD5 is considered a weak message digest and its use constitutes a
+ *            security risk. If possible, we recommend avoiding dependencies on
+ *            it, and considering stronger message digests instead.
+ *
+ */
+#define MBEDCRYPTO_MD5_C
+
+/**
+ * \def MBEDCRYPTO_MEMORY_BUFFER_ALLOC_C
+ *
+ * Enable the buffer allocator implementation that makes use of a (stack)
+ * based buffer to 'allocate' dynamic memory. (replaces calloc() and free()
+ * calls)
+ *
+ * Module:  library/memory_buffer_alloc.c
+ *
+ * Requires: MBEDCRYPTO_PLATFORM_C
+ *           MBEDCRYPTO_PLATFORM_MEMORY (to use it within Mbed Crypto)
+ *
+ * Enable this module to enable the buffer memory allocator.
+ */
+//#define MBEDCRYPTO_MEMORY_BUFFER_ALLOC_C
+
+/**
+ * \def MBEDCRYPTO_OID_C
+ *
+ * Enable the OID database.
+ *
+ * Module:  library/oid.c
+ * Caller:  library/asn1write.c
+ *          library/pkcs5.c
+ *          library/pkparse.c
+ *          library/pkwrite.c
+ *          library/rsa.c
+ *          library/x509.c
+ *          library/x509_create.c
+ *          library/x509_crl.c
+ *          library/x509_crt.c
+ *          library/x509_csr.c
+ *          library/x509write_crt.c
+ *          library/x509write_csr.c
+ *
+ * This modules translates between OIDs and internal values.
+ */
+#define MBEDCRYPTO_OID_C
+
+/**
+ * \def MBEDCRYPTO_PADLOCK_C
+ *
+ * Enable VIA Padlock support on x86.
+ *
+ * Module:  library/padlock.c
+ * Caller:  library/aes.c
+ *
+ * Requires: MBEDCRYPTO_HAVE_ASM
+ *
+ * This modules adds support for the VIA PadLock on x86.
+ */
+//#define MBEDCRYPTO_PADLOCK_C
+
+/**
+ * \def MBEDCRYPTO_PEM_PARSE_C
+ *
+ * Enable PEM decoding / parsing.
+ *
+ * Module:  library/pem.c
+ * Caller:  library/dhm.c
+ *          library/pkparse.c
+ *          library/x509_crl.c
+ *          library/x509_crt.c
+ *          library/x509_csr.c
+ *
+ * Requires: MBEDCRYPTO_BASE64_C
+ *
+ * This modules adds support for decoding / parsing PEM files.
+ */
+#define MBEDCRYPTO_PEM_PARSE_C
+
+/**
+ * \def MBEDCRYPTO_PEM_WRITE_C
+ *
+ * Enable PEM encoding / writing.
+ *
+ * Module:  library/pem.c
+ * Caller:  library/pkwrite.c
+ *          library/x509write_crt.c
+ *          library/x509write_csr.c
+ *
+ * Requires: MBEDCRYPTO_BASE64_C
+ *
+ * This modules adds support for encoding / writing PEM files.
+ */
+#define MBEDCRYPTO_PEM_WRITE_C
+
+/**
+ * \def MBEDCRYPTO_PK_C
+ *
+ * Enable the generic public (asymetric) key layer.
+ *
+ * Module:  library/pk.c
+ * Caller:  library/ssl_tls.c
+ *          library/ssl_cli.c
+ *          library/ssl_srv.c
+ *
+ * Requires: MBEDCRYPTO_RSA_C or MBEDCRYPTO_ECP_C
+ *
+ * Uncomment to enable generic public key wrappers.
+ */
+#define MBEDCRYPTO_PK_C
+
+/**
+ * \def MBEDCRYPTO_PK_PARSE_C
+ *
+ * Enable the generic public (asymetric) key parser.
+ *
+ * Module:  library/pkparse.c
+ * Caller:  library/x509_crt.c
+ *          library/x509_csr.c
+ *
+ * Requires: MBEDCRYPTO_PK_C
+ *
+ * Uncomment to enable generic public key parse functions.
+ */
+#define MBEDCRYPTO_PK_PARSE_C
+
+/**
+ * \def MBEDCRYPTO_PK_WRITE_C
+ *
+ * Enable the generic public (asymetric) key writer.
+ *
+ * Module:  library/pkwrite.c
+ * Caller:  library/x509write.c
+ *
+ * Requires: MBEDCRYPTO_PK_C
+ *
+ * Uncomment to enable generic public key write functions.
+ */
+#define MBEDCRYPTO_PK_WRITE_C
+
+/**
+ * \def MBEDCRYPTO_PKCS5_C
+ *
+ * Enable PKCS#5 functions.
+ *
+ * Module:  library/pkcs5.c
+ *
+ * Requires: MBEDCRYPTO_MD_C
+ *
+ * This module adds support for the PKCS#5 functions.
+ */
+#define MBEDCRYPTO_PKCS5_C
+
+/**
+ * \def MBEDCRYPTO_PKCS11_C
+ *
+ * Enable wrapper for PKCS#11 smartcard support.
+ *
+ * Module:  library/pkcs11.c
+ * Caller:  library/pk.c
+ *
+ * Requires: MBEDCRYPTO_PK_C
+ *
+ * This module enables SSL/TLS PKCS #11 smartcard support.
+ * Requires the presence of the PKCS#11 helper library (libpkcs11-helper)
+ */
+//#define MBEDCRYPTO_PKCS11_C
+
+/**
+ * \def MBEDCRYPTO_PKCS12_C
+ *
+ * Enable PKCS#12 PBE functions.
+ * Adds algorithms for parsing PKCS#8 encrypted private keys
+ *
+ * Module:  library/pkcs12.c
+ * Caller:  library/pkparse.c
+ *
+ * Requires: MBEDCRYPTO_ASN1_PARSE_C, MBEDCRYPTO_CIPHER_C, MBEDCRYPTO_MD_C
+ * Can use:  MBEDCRYPTO_ARC4_C
+ *
+ * This module enables PKCS#12 functions.
+ */
+#define MBEDCRYPTO_PKCS12_C
+
+/**
+ * \def MBEDCRYPTO_PLATFORM_C
+ *
+ * Enable the platform abstraction layer that allows you to re-assign
+ * functions like calloc(), free(), snprintf(), printf(), fprintf(), exit().
+ *
+ * Enabling MBEDCRYPTO_PLATFORM_C enables to use of MBEDCRYPTO_PLATFORM_XXX_ALT
+ * or MBEDCRYPTO_PLATFORM_XXX_MACRO directives, allowing the functions mentioned
+ * above to be specified at runtime or compile time respectively.
+ *
+ * \note This abstraction layer must be enabled on Windows (including MSYS2)
+ * as other module rely on it for a fixed snprintf implementation.
+ *
+ * Module:  library/platform.c
+ * Caller:  Most other .c files
+ *
+ * This module enables abstraction of common (libc) functions.
+ */
+#define MBEDCRYPTO_PLATFORM_C
+
+/**
+ * \def MBEDCRYPTO_PSA_CRYPTO_C
+ *
+ * Enable the Platform Security Architecture cryptography API.
+ *
+ * Module:  library/psa_crypto.c
+ *
+ * Requires: MBEDCRYPTO_CTR_DRBG_C, MBEDCRYPTO_ENTROPY_C
+ *
+ */
+#define MBEDCRYPTO_PSA_CRYPTO_C
+
+/**
+ * \def MBEDCRYPTO_RIPEMD160_C
+ *
+ * Enable the RIPEMD-160 hash algorithm.
+ *
+ * Module:  library/ripemd160.c
+ * Caller:  library/md.c
+ *
+ */
+#define MBEDCRYPTO_RIPEMD160_C
+
+/**
+ * \def MBEDCRYPTO_RSA_C
+ *
+ * Enable the RSA public-key cryptosystem.
+ *
+ * Module:  library/rsa.c
+ *          library/rsa_internal.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *          library/ssl_tls.c
+ *          library/x509.c
+ *
+ * This module is used by the following key exchanges:
+ *      RSA, DHE-RSA, ECDHE-RSA, RSA-PSK
+ *
+ * Requires: MBEDCRYPTO_BIGNUM_C, MBEDCRYPTO_OID_C
+ */
+#define MBEDCRYPTO_RSA_C
+
+/**
+ * \def MBEDCRYPTO_SHA1_C
+ *
+ * Enable the SHA1 cryptographic hash algorithm.
+ *
+ * Module:  library/sha1.c
+ * Caller:  library/md.c
+ *          library/ssl_cli.c
+ *          library/ssl_srv.c
+ *          library/ssl_tls.c
+ *          library/x509write_crt.c
+ *
+ * This module is required for SSL/TLS up to version 1.1, for TLS 1.2
+ * depending on the handshake parameters, and for SHA1-signed certificates.
+ *
+ * \warning   SHA-1 is considered a weak message digest and its use constitutes
+ *            a security risk. If possible, we recommend avoiding dependencies
+ *            on it, and considering stronger message digests instead.
+ *
+ */
+#define MBEDCRYPTO_SHA1_C
+
+/**
+ * \def MBEDCRYPTO_SHA256_C
+ *
+ * Enable the SHA-224 and SHA-256 cryptographic hash algorithms.
+ *
+ * Module:  library/sha256.c
+ * Caller:  library/entropy.c
+ *          library/md.c
+ *          library/ssl_cli.c
+ *          library/ssl_srv.c
+ *          library/ssl_tls.c
+ *
+ * This module adds support for SHA-224 and SHA-256.
+ * This module is required for the SSL/TLS 1.2 PRF function.
+ */
+#define MBEDCRYPTO_SHA256_C
+
+/**
+ * \def MBEDCRYPTO_SHA512_C
+ *
+ * Enable the SHA-384 and SHA-512 cryptographic hash algorithms.
+ *
+ * Module:  library/sha512.c
+ * Caller:  library/entropy.c
+ *          library/md.c
+ *          library/ssl_cli.c
+ *          library/ssl_srv.c
+ *
+ * This module adds support for SHA-384 and SHA-512.
+ */
+#define MBEDCRYPTO_SHA512_C
+
+/**
+ * \def MBEDCRYPTO_THREADING_C
+ *
+ * Enable the threading abstraction layer.
+ * By default Mbed Crypto assumes it is used in a non-threaded environment or that
+ * contexts are not shared between threads. If you do intend to use contexts
+ * between threads, you will need to enable this layer to prevent race
+ * conditions. See also our Knowledge Base article about threading:
+ * https://tls.mbed.org/kb/development/thread-safety-and-multi-threading
+ *
+ * Module:  library/threading.c
+ *
+ * This allows different threading implementations (self-implemented or
+ * provided).
+ *
+ * You will have to enable either MBEDCRYPTO_THREADING_ALT or
+ * MBEDCRYPTO_THREADING_PTHREAD.
+ *
+ * Enable this layer to allow use of mutexes within Mbed Crypto
+ */
+//#define MBEDCRYPTO_THREADING_C
+
+/**
+ * \def MBEDCRYPTO_VERSION_C
+ *
+ * Enable run-time version information.
+ *
+ * Module:  library/version.c
+ *
+ * This module provides run-time version information.
+ */
+#define MBEDCRYPTO_VERSION_C
+
+/**
+ * \def MBEDCRYPTO_XTEA_C
+ *
+ * Enable the XTEA block cipher.
+ *
+ * Module:  library/xtea.c
+ * Caller:
+ */
+#define MBEDCRYPTO_XTEA_C
+
+/* \} name SECTION: Mbed Crypto modules */
+
+/**
+ * \name SECTION: Module configuration options
+ *
+ * This section allows for the setting of module specific sizes and
+ * configuration options. The default values are already present in the
+ * relevant header files and should suffice for the regular use cases.
+ *
+ * Our advice is to enable options and change their values here
+ * only if you have a good reason and know the consequences.
+ *
+ * Please check the respective header file for documentation on these
+ * parameters (to prevent duplicate documentation).
+ * \{
+ */
+
+/* MPI / BIGNUM options */
+//#define MBEDCRYPTO_MPI_WINDOW_SIZE            6 /**< Maximum windows size used. */
+//#define MBEDCRYPTO_MPI_MAX_SIZE            1024 /**< Maximum number of bytes for usable MPIs. */
+
+/* CTR_DRBG options */
+//#define MBEDCRYPTO_CTR_DRBG_ENTROPY_LEN               48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */
+//#define MBEDCRYPTO_CTR_DRBG_RESEED_INTERVAL        10000 /**< Interval before reseed is performed by default */
+//#define MBEDCRYPTO_CTR_DRBG_MAX_INPUT                256 /**< Maximum number of additional input bytes */
+//#define MBEDCRYPTO_CTR_DRBG_MAX_REQUEST             1024 /**< Maximum number of requested bytes per call */
+//#define MBEDCRYPTO_CTR_DRBG_MAX_SEED_INPUT           384 /**< Maximum size of (re)seed buffer */
+
+/* HMAC_DRBG options */
+//#define MBEDCRYPTO_HMAC_DRBG_RESEED_INTERVAL   10000 /**< Interval before reseed is performed by default */
+//#define MBEDCRYPTO_HMAC_DRBG_MAX_INPUT           256 /**< Maximum number of additional input bytes */
+//#define MBEDCRYPTO_HMAC_DRBG_MAX_REQUEST        1024 /**< Maximum number of requested bytes per call */
+//#define MBEDCRYPTO_HMAC_DRBG_MAX_SEED_INPUT      384 /**< Maximum size of (re)seed buffer */
+
+/* ECP options */
+//#define MBEDCRYPTO_ECP_MAX_BITS             521 /**< Maximum bit size of groups */
+//#define MBEDCRYPTO_ECP_WINDOW_SIZE            6 /**< Maximum window size used */
+//#define MBEDCRYPTO_ECP_FIXED_POINT_OPTIM      1 /**< Enable fixed-point speed-up */
+
+/* Entropy options */
+//#define MBEDCRYPTO_ENTROPY_MAX_SOURCES                20 /**< Maximum number of sources supported */
+//#define MBEDCRYPTO_ENTROPY_MAX_GATHER                128 /**< Maximum amount requested from entropy sources */
+//#define MBEDCRYPTO_ENTROPY_MIN_HARDWARE               32 /**< Default minimum number of bytes required for the hardware entropy source mbedcrypto_hardware_poll() before entropy is released */
+
+/* Memory buffer allocator options */
+//#define MBEDCRYPTO_MEMORY_ALIGN_MULTIPLE      4 /**< Align on multiples of this value */
+
+/* Platform options */
+//#define MBEDCRYPTO_PLATFORM_STD_MEM_HDR   <stdlib.h> /**< Header to include if MBEDCRYPTO_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */
+//#define MBEDCRYPTO_PLATFORM_STD_CALLOC        calloc /**< Default allocator to use, can be undefined */
+//#define MBEDCRYPTO_PLATFORM_STD_FREE            free /**< Default free to use, can be undefined */
+//#define MBEDCRYPTO_PLATFORM_STD_EXIT            exit /**< Default exit to use, can be undefined */
+//#define MBEDCRYPTO_PLATFORM_STD_TIME            time /**< Default time to use, can be undefined. MBEDCRYPTO_HAVE_TIME must be enabled */
+//#define MBEDCRYPTO_PLATFORM_STD_FPRINTF      fprintf /**< Default fprintf to use, can be undefined */
+//#define MBEDCRYPTO_PLATFORM_STD_PRINTF        printf /**< Default printf to use, can be undefined */
+/* Note: your snprintf must correclty zero-terminate the buffer! */
+//#define MBEDCRYPTO_PLATFORM_STD_SNPRINTF    snprintf /**< Default snprintf to use, can be undefined */
+//#define MBEDCRYPTO_PLATFORM_STD_EXIT_SUCCESS       0 /**< Default exit value to use, can be undefined */
+//#define MBEDCRYPTO_PLATFORM_STD_EXIT_FAILURE       1 /**< Default exit value to use, can be undefined */
+//#define MBEDCRYPTO_PLATFORM_STD_NV_SEED_READ   mbedcrypto_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */
+//#define MBEDCRYPTO_PLATFORM_STD_NV_SEED_WRITE  mbedcrypto_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */
+//#define MBEDCRYPTO_PLATFORM_STD_NV_SEED_FILE  "seedfile" /**< Seed file to read/write with default implementation */
+
+/* To Use Function Macros MBEDCRYPTO_PLATFORM_C must be enabled */
+/* MBEDCRYPTO_PLATFORM_XXX_MACRO and MBEDCRYPTO_PLATFORM_XXX_ALT cannot both be defined */
+//#define MBEDCRYPTO_PLATFORM_CALLOC_MACRO        calloc /**< Default allocator macro to use, can be undefined */
+//#define MBEDCRYPTO_PLATFORM_FREE_MACRO            free /**< Default free macro to use, can be undefined */
+//#define MBEDCRYPTO_PLATFORM_EXIT_MACRO            exit /**< Default exit macro to use, can be undefined */
+//#define MBEDCRYPTO_PLATFORM_TIME_MACRO            time /**< Default time macro to use, can be undefined. MBEDCRYPTO_HAVE_TIME must be enabled */
+//#define MBEDCRYPTO_PLATFORM_TIME_TYPE_MACRO       time_t /**< Default time macro to use, can be undefined. MBEDCRYPTO_HAVE_TIME must be enabled */
+//#define MBEDCRYPTO_PLATFORM_FPRINTF_MACRO      fprintf /**< Default fprintf macro to use, can be undefined */
+//#define MBEDCRYPTO_PLATFORM_PRINTF_MACRO        printf /**< Default printf macro to use, can be undefined */
+/* Note: your snprintf must correclty zero-terminate the buffer! */
+//#define MBEDCRYPTO_PLATFORM_SNPRINTF_MACRO    snprintf /**< Default snprintf macro to use, can be undefined */
+//#define MBEDCRYPTO_PLATFORM_NV_SEED_READ_MACRO   mbedcrypto_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */
+//#define MBEDCRYPTO_PLATFORM_NV_SEED_WRITE_MACRO  mbedcrypto_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */
+
+/**
+ * Uncomment the macro to let Mbed Crypto use your alternate implementation of
+ * mbedcrypto_platform_zeroize(). This replaces the default implementation in
+ * platform_util.c.
+ *
+ * mbedcrypto_platform_zeroize() is a widely used function across the library to
+ * zero a block of memory. The implementation is expected to be secure in the
+ * sense that it has been written to prevent the compiler from removing calls
+ * to mbedcrypto_platform_zeroize() as part of redundant code elimination
+ * optimizations. However, it is difficult to guarantee that calls to
+ * mbedcrypto_platform_zeroize() will not be optimized by the compiler as older
+ * versions of the C language standards do not provide a secure implementation
+ * of memset(). Therefore, MBEDCRYPTO_PLATFORM_ZEROIZE_ALT enables users to
+ * configure their own implementation of mbedcrypto_platform_zeroize(), for
+ * example by using directives specific to their compiler, features from newer
+ * C standards (e.g using memset_s() in C11) or calling a secure memset() from
+ * their system (e.g explicit_bzero() in BSD).
+ */
+//#define MBEDCRYPTO_PLATFORM_ZEROIZE_ALT
+
+/* \} name SECTION: Customisation configuration options */
+
+#include "mbedcrypto/check_config.h"
+
+#endif /* MBEDCRYPTO_CONFIG_H */
diff --git a/include/mbedcrypto/ctr_drbg.h b/include/mbedcrypto/ctr_drbg.h
new file mode 100644
index 0000000..eca2d9d
--- /dev/null
+++ b/include/mbedcrypto/ctr_drbg.h
@@ -0,0 +1,330 @@
+/**
+ * \file ctr_drbg.h
+ *
+ * \brief    This file contains CTR_DRBG definitions and functions.
+ *
+ * CTR_DRBG is a standardized way of building a PRNG from a block-cipher
+ * in counter mode operation, as defined in <em>NIST SP 800-90A:
+ * Recommendation for Random Number Generation Using Deterministic Random
+ * Bit Generators</em>.
+ *
+ * The Mbed Crypto implementation of CTR_DRBG uses AES-256 as the underlying
+ * block cipher.
+ */
+/*
+ *  Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#ifndef MBEDCRYPTO_CTR_DRBG_H
+#define MBEDCRYPTO_CTR_DRBG_H
+
+#include "aes.h"
+
+#if defined(MBEDCRYPTO_THREADING_C)
+#include "mbedcrypto/threading.h"
+#endif
+
+#define MBEDCRYPTO_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED        -0x0034  /**< The entropy source failed. */
+#define MBEDCRYPTO_ERR_CTR_DRBG_REQUEST_TOO_BIG              -0x0036  /**< The requested random buffer length is too big. */
+#define MBEDCRYPTO_ERR_CTR_DRBG_INPUT_TOO_BIG                -0x0038  /**< The input (entropy + additional data) is too large. */
+#define MBEDCRYPTO_ERR_CTR_DRBG_FILE_IO_ERROR                -0x003A  /**< Read or write error in file. */
+
+#define MBEDCRYPTO_CTR_DRBG_BLOCKSIZE          16 /**< The block size used by the cipher. */
+#define MBEDCRYPTO_CTR_DRBG_KEYSIZE            32 /**< The key size used by the cipher. */
+#define MBEDCRYPTO_CTR_DRBG_KEYBITS            ( MBEDCRYPTO_CTR_DRBG_KEYSIZE * 8 ) /**< The key size for the DRBG operation, in bits. */
+#define MBEDCRYPTO_CTR_DRBG_SEEDLEN            ( MBEDCRYPTO_CTR_DRBG_KEYSIZE + MBEDCRYPTO_CTR_DRBG_BLOCKSIZE ) /**< The seed length, calculated as (counter + AES key). */
+
+/**
+ * \name SECTION: Module settings
+ *
+ * The configuration options you can set for this module are in this section.
+ * Either change them in config.h or define them using the compiler command
+ * line.
+ * \{
+ */
+
+#if !defined(MBEDCRYPTO_CTR_DRBG_ENTROPY_LEN)
+#if defined(MBEDCRYPTO_SHA512_C) && !defined(MBEDCRYPTO_ENTROPY_FORCE_SHA256)
+#define MBEDCRYPTO_CTR_DRBG_ENTROPY_LEN        48
+/**< The amount of entropy used per seed by default:
+ * <ul><li>48 with SHA-512.</li>
+ * <li>32 with SHA-256.</li></ul>
+ */
+#else
+#define MBEDCRYPTO_CTR_DRBG_ENTROPY_LEN        32
+/**< Amount of entropy used per seed by default:
+ * <ul><li>48 with SHA-512.</li>
+ * <li>32 with SHA-256.</li></ul>
+ */
+#endif
+#endif
+
+#if !defined(MBEDCRYPTO_CTR_DRBG_RESEED_INTERVAL)
+#define MBEDCRYPTO_CTR_DRBG_RESEED_INTERVAL    10000
+/**< The interval before reseed is performed by default. */
+#endif
+
+#if !defined(MBEDCRYPTO_CTR_DRBG_MAX_INPUT)
+#define MBEDCRYPTO_CTR_DRBG_MAX_INPUT          256
+/**< The maximum number of additional input Bytes. */
+#endif
+
+#if !defined(MBEDCRYPTO_CTR_DRBG_MAX_REQUEST)
+#define MBEDCRYPTO_CTR_DRBG_MAX_REQUEST        1024
+/**< The maximum number of requested Bytes per call. */
+#endif
+
+#if !defined(MBEDCRYPTO_CTR_DRBG_MAX_SEED_INPUT)
+#define MBEDCRYPTO_CTR_DRBG_MAX_SEED_INPUT     384
+/**< The maximum size of seed or reseed buffer. */
+#endif
+
+/* \} name SECTION: Module settings */
+
+#define MBEDCRYPTO_CTR_DRBG_PR_OFF             0
+/**< Prediction resistance is disabled. */
+#define MBEDCRYPTO_CTR_DRBG_PR_ON              1
+/**< Prediction resistance is enabled. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          The CTR_DRBG context structure.
+ */
+typedef struct
+{
+    unsigned char counter[16];  /*!< The counter (V). */
+    int reseed_counter;         /*!< The reseed counter. */
+    int prediction_resistance;  /*!< This determines whether prediction
+                                     resistance is enabled, that is
+                                     whether to systematically reseed before
+                                     each random generation. */
+    size_t entropy_len;         /*!< The amount of entropy grabbed on each
+                                     seed or reseed operation. */
+    int reseed_interval;        /*!< The reseed interval. */
+
+    mbedcrypto_aes_context aes_ctx;        /*!< The AES context. */
+
+    /*
+     * Callbacks (Entropy)
+     */
+    int (*f_entropy)(void *, unsigned char *, size_t);
+                                /*!< The entropy callback function. */
+
+    void *p_entropy;            /*!< The context for the entropy function. */
+
+#if defined(MBEDCRYPTO_THREADING_C)
+    mbedcrypto_threading_mutex_t mutex;
+#endif
+}
+mbedcrypto_ctr_drbg_context;
+
+/**
+ * \brief               This function initializes the CTR_DRBG context,
+ *                      and prepares it for mbedcrypto_ctr_drbg_seed()
+ *                      or mbedcrypto_ctr_drbg_free().
+ *
+ * \param ctx           The CTR_DRBG context to initialize.
+ */
+void mbedcrypto_ctr_drbg_init( mbedcrypto_ctr_drbg_context *ctx );
+
+/**
+ * \brief               This function seeds and sets up the CTR_DRBG
+ *                      entropy source for future reseeds.
+ *
+ * \note Personalization data can be provided in addition to the more generic
+ *       entropy source, to make this instantiation as unique as possible.
+ *
+ * \param ctx           The CTR_DRBG context to seed.
+ * \param f_entropy     The entropy callback, taking as arguments the
+ *                      \p p_entropy context, the buffer to fill, and the
+                        length of the buffer.
+ * \param p_entropy     The entropy context.
+ * \param custom        Personalization data, that is device-specific
+                        identifiers. Can be NULL.
+ * \param len           The length of the personalization data.
+ *
+ * \return              \c 0 on success.
+ * \return              #MBEDCRYPTO_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure.
+ */
+int mbedcrypto_ctr_drbg_seed( mbedcrypto_ctr_drbg_context *ctx,
+                   int (*f_entropy)(void *, unsigned char *, size_t),
+                   void *p_entropy,
+                   const unsigned char *custom,
+                   size_t len );
+
+/**
+ * \brief               This function clears CTR_CRBG context data.
+ *
+ * \param ctx           The CTR_DRBG context to clear.
+ */
+void mbedcrypto_ctr_drbg_free( mbedcrypto_ctr_drbg_context *ctx );
+
+/**
+ * \brief               This function turns prediction resistance on or off.
+ *                      The default value is off.
+ *
+ * \note                If enabled, entropy is gathered at the beginning of
+ *                      every call to mbedcrypto_ctr_drbg_random_with_add().
+ *                      Only use this if your entropy source has sufficient
+ *                      throughput.
+ *
+ * \param ctx           The CTR_DRBG context.
+ * \param resistance    #MBEDCRYPTO_CTR_DRBG_PR_ON or #MBEDCRYPTO_CTR_DRBG_PR_OFF.
+ */
+void mbedcrypto_ctr_drbg_set_prediction_resistance( mbedcrypto_ctr_drbg_context *ctx,
+                                         int resistance );
+
+/**
+ * \brief               This function sets the amount of entropy grabbed on each
+ *                      seed or reseed. The default value is
+ *                      #MBEDCRYPTO_CTR_DRBG_ENTROPY_LEN.
+ *
+ * \param ctx           The CTR_DRBG context.
+ * \param len           The amount of entropy to grab.
+ */
+void mbedcrypto_ctr_drbg_set_entropy_len( mbedcrypto_ctr_drbg_context *ctx,
+                               size_t len );
+
+/**
+ * \brief               This function sets the reseed interval.
+ *                      The default value is #MBEDCRYPTO_CTR_DRBG_RESEED_INTERVAL.
+ *
+ * \param ctx           The CTR_DRBG context.
+ * \param interval      The reseed interval.
+ */
+void mbedcrypto_ctr_drbg_set_reseed_interval( mbedcrypto_ctr_drbg_context *ctx,
+                                   int interval );
+
+/**
+ * \brief               This function reseeds the CTR_DRBG context, that is
+ *                      extracts data from the entropy source.
+ *
+ * \param ctx           The CTR_DRBG context.
+ * \param additional    Additional data to add to the state. Can be NULL.
+ * \param len           The length of the additional data.
+ *
+ * \return              \c 0 on success.
+ * \return              #MBEDCRYPTO_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure.
+ */
+int mbedcrypto_ctr_drbg_reseed( mbedcrypto_ctr_drbg_context *ctx,
+                     const unsigned char *additional, size_t len );
+
+/**
+ * \brief              This function updates the state of the CTR_DRBG context.
+ *
+ * \note               If \p add_len is greater than
+ *                     #MBEDCRYPTO_CTR_DRBG_MAX_SEED_INPUT, only the first
+ *                     #MBEDCRYPTO_CTR_DRBG_MAX_SEED_INPUT Bytes are used.
+ *                     The remaining Bytes are silently discarded.
+ *
+ * \param ctx          The CTR_DRBG context.
+ * \param additional   The data to update the state with.
+ * \param add_len      Length of \p additional data.
+ *
+ */
+void mbedcrypto_ctr_drbg_update( mbedcrypto_ctr_drbg_context *ctx,
+                      const unsigned char *additional, size_t add_len );
+
+/**
+ * \brief   This function updates a CTR_DRBG instance with additional
+ *          data and uses it to generate random data.
+ *
+ * \note    The function automatically reseeds if the reseed counter is exceeded.
+ *
+ * \param p_rng         The CTR_DRBG context. This must be a pointer to a
+ *                      #mbedcrypto_ctr_drbg_context structure.
+ * \param output        The buffer to fill.
+ * \param output_len    The length of the buffer.
+ * \param additional    Additional data to update. Can be NULL.
+ * \param add_len       The length of the additional data.
+ *
+ * \return    \c 0 on success.
+ * \return    #MBEDCRYPTO_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or
+ *            #MBEDCRYPTO_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure.
+ */
+int mbedcrypto_ctr_drbg_random_with_add( void *p_rng,
+                              unsigned char *output, size_t output_len,
+                              const unsigned char *additional, size_t add_len );
+
+/**
+ * \brief   This function uses CTR_DRBG to generate random data.
+ *
+ * \note    The function automatically reseeds if the reseed counter is exceeded.
+ *
+ * \param p_rng         The CTR_DRBG context. This must be a pointer to a
+ *                      #mbedcrypto_ctr_drbg_context structure.
+ * \param output        The buffer to fill.
+ * \param output_len    The length of the buffer.
+ *
+ * \return              \c 0 on success.
+ * \return              #MBEDCRYPTO_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or
+ *                      #MBEDCRYPTO_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure.
+ */
+int mbedcrypto_ctr_drbg_random( void *p_rng,
+                     unsigned char *output, size_t output_len );
+
+#if defined(MBEDCRYPTO_FS_IO)
+/**
+ * \brief               This function writes a seed file.
+ *
+ * \param ctx           The CTR_DRBG context.
+ * \param path          The name of the file.
+ *
+ * \return              \c 0 on success.
+ * \return              #MBEDCRYPTO_ERR_CTR_DRBG_FILE_IO_ERROR on file error.
+ * \return              #MBEDCRYPTO_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on
+ *                      failure.
+ */
+int mbedcrypto_ctr_drbg_write_seed_file( mbedcrypto_ctr_drbg_context *ctx, const char *path );
+
+/**
+ * \brief               This function reads and updates a seed file. The seed
+ *                      is added to this instance.
+ *
+ * \param ctx           The CTR_DRBG context.
+ * \param path          The name of the file.
+ *
+ * \return              \c 0 on success.
+ * \return              #MBEDCRYPTO_ERR_CTR_DRBG_FILE_IO_ERROR on file error.
+ * \return              #MBEDCRYPTO_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or
+ *                      #MBEDCRYPTO_ERR_CTR_DRBG_INPUT_TOO_BIG on failure.
+ */
+int mbedcrypto_ctr_drbg_update_seed_file( mbedcrypto_ctr_drbg_context *ctx, const char *path );
+#endif /* MBEDCRYPTO_FS_IO */
+
+/**
+ * \brief               The CTR_DRBG checkup routine.
+ *
+ * \return              \c 0 on success.
+ * \return              \c 1 on failure.
+ */
+int mbedcrypto_ctr_drbg_self_test( int verbose );
+
+/* Internal functions (do not call directly) */
+int mbedcrypto_ctr_drbg_seed_entropy_len( mbedcrypto_ctr_drbg_context *,
+                               int (*)(void *, unsigned char *, size_t), void *,
+                               const unsigned char *, size_t, size_t );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ctr_drbg.h */
diff --git a/include/mbedcrypto/des.h b/include/mbedcrypto/des.h
new file mode 100644
index 0000000..1eeb760
--- /dev/null
+++ b/include/mbedcrypto/des.h
@@ -0,0 +1,350 @@
+/**
+ * \file des.h
+ *
+ * \brief DES block cipher
+ *
+ * \warning   DES is considered a weak cipher and its use constitutes a
+ *            security risk. We recommend considering stronger ciphers
+ *            instead.
+ */
+/*
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ *
+ */
+#ifndef MBEDCRYPTO_DES_H
+#define MBEDCRYPTO_DES_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+#define MBEDCRYPTO_DES_ENCRYPT     1
+#define MBEDCRYPTO_DES_DECRYPT     0
+
+#define MBEDCRYPTO_ERR_DES_INVALID_INPUT_LENGTH              -0x0032  /**< The data input has an invalid length. */
+#define MBEDCRYPTO_ERR_DES_HW_ACCEL_FAILED                   -0x0033  /**< DES hardware accelerator failed. */
+
+#define MBEDCRYPTO_DES_KEY_SIZE    8
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDCRYPTO_DES_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief          DES context structure
+ *
+ * \warning        DES is considered a weak cipher and its use constitutes a
+ *                 security risk. We recommend considering stronger ciphers
+ *                 instead.
+ */
+typedef struct
+{
+    uint32_t sk[32];            /*!<  DES subkeys       */
+}
+mbedcrypto_des_context;
+
+/**
+ * \brief          Triple-DES context structure
+ */
+typedef struct
+{
+    uint32_t sk[96];            /*!<  3DES subkeys      */
+}
+mbedcrypto_des3_context;
+
+#else  /* MBEDCRYPTO_DES_ALT */
+#include "des_alt.h"
+#endif /* MBEDCRYPTO_DES_ALT */
+
+/**
+ * \brief          Initialize DES context
+ *
+ * \param ctx      DES context to be initialized
+ *
+ * \warning        DES is considered a weak cipher and its use constitutes a
+ *                 security risk. We recommend considering stronger ciphers
+ *                 instead.
+ */
+void mbedcrypto_des_init( mbedcrypto_des_context *ctx );
+
+/**
+ * \brief          Clear DES context
+ *
+ * \param ctx      DES context to be cleared
+ *
+ * \warning        DES is considered a weak cipher and its use constitutes a
+ *                 security risk. We recommend considering stronger ciphers
+ *                 instead.
+ */
+void mbedcrypto_des_free( mbedcrypto_des_context *ctx );
+
+/**
+ * \brief          Initialize Triple-DES context
+ *
+ * \param ctx      DES3 context to be initialized
+ */
+void mbedcrypto_des3_init( mbedcrypto_des3_context *ctx );
+
+/**
+ * \brief          Clear Triple-DES context
+ *
+ * \param ctx      DES3 context to be cleared
+ */
+void mbedcrypto_des3_free( mbedcrypto_des3_context *ctx );
+
+/**
+ * \brief          Set key parity on the given key to odd.
+ *
+ *                 DES keys are 56 bits long, but each byte is padded with
+ *                 a parity bit to allow verification.
+ *
+ * \param key      8-byte secret key
+ *
+ * \warning        DES is considered a weak cipher and its use constitutes a
+ *                 security risk. We recommend considering stronger ciphers
+ *                 instead.
+ */
+void mbedcrypto_des_key_set_parity( unsigned char key[MBEDCRYPTO_DES_KEY_SIZE] );
+
+/**
+ * \brief          Check that key parity on the given key is odd.
+ *
+ *                 DES keys are 56 bits long, but each byte is padded with
+ *                 a parity bit to allow verification.
+ *
+ * \param key      8-byte secret key
+ *
+ * \return         0 is parity was ok, 1 if parity was not correct.
+ *
+ * \warning        DES is considered a weak cipher and its use constitutes a
+ *                 security risk. We recommend considering stronger ciphers
+ *                 instead.
+ */
+int mbedcrypto_des_key_check_key_parity( const unsigned char key[MBEDCRYPTO_DES_KEY_SIZE] );
+
+/**
+ * \brief          Check that key is not a weak or semi-weak DES key
+ *
+ * \param key      8-byte secret key
+ *
+ * \return         0 if no weak key was found, 1 if a weak key was identified.
+ *
+ * \warning        DES is considered a weak cipher and its use constitutes a
+ *                 security risk. We recommend considering stronger ciphers
+ *                 instead.
+ */
+int mbedcrypto_des_key_check_weak( const unsigned char key[MBEDCRYPTO_DES_KEY_SIZE] );
+
+/**
+ * \brief          DES key schedule (56-bit, encryption)
+ *
+ * \param ctx      DES context to be initialized
+ * \param key      8-byte secret key
+ *
+ * \return         0
+ *
+ * \warning        DES is considered a weak cipher and its use constitutes a
+ *                 security risk. We recommend considering stronger ciphers
+ *                 instead.
+ */
+int mbedcrypto_des_setkey_enc( mbedcrypto_des_context *ctx, const unsigned char key[MBEDCRYPTO_DES_KEY_SIZE] );
+
+/**
+ * \brief          DES key schedule (56-bit, decryption)
+ *
+ * \param ctx      DES context to be initialized
+ * \param key      8-byte secret key
+ *
+ * \return         0
+ *
+ * \warning        DES is considered a weak cipher and its use constitutes a
+ *                 security risk. We recommend considering stronger ciphers
+ *                 instead.
+ */
+int mbedcrypto_des_setkey_dec( mbedcrypto_des_context *ctx, const unsigned char key[MBEDCRYPTO_DES_KEY_SIZE] );
+
+/**
+ * \brief          Triple-DES key schedule (112-bit, encryption)
+ *
+ * \param ctx      3DES context to be initialized
+ * \param key      16-byte secret key
+ *
+ * \return         0
+ */
+int mbedcrypto_des3_set2key_enc( mbedcrypto_des3_context *ctx,
+                      const unsigned char key[MBEDCRYPTO_DES_KEY_SIZE * 2] );
+
+/**
+ * \brief          Triple-DES key schedule (112-bit, decryption)
+ *
+ * \param ctx      3DES context to be initialized
+ * \param key      16-byte secret key
+ *
+ * \return         0
+ */
+int mbedcrypto_des3_set2key_dec( mbedcrypto_des3_context *ctx,
+                      const unsigned char key[MBEDCRYPTO_DES_KEY_SIZE * 2] );
+
+/**
+ * \brief          Triple-DES key schedule (168-bit, encryption)
+ *
+ * \param ctx      3DES context to be initialized
+ * \param key      24-byte secret key
+ *
+ * \return         0
+ */
+int mbedcrypto_des3_set3key_enc( mbedcrypto_des3_context *ctx,
+                      const unsigned char key[MBEDCRYPTO_DES_KEY_SIZE * 3] );
+
+/**
+ * \brief          Triple-DES key schedule (168-bit, decryption)
+ *
+ * \param ctx      3DES context to be initialized
+ * \param key      24-byte secret key
+ *
+ * \return         0
+ */
+int mbedcrypto_des3_set3key_dec( mbedcrypto_des3_context *ctx,
+                      const unsigned char key[MBEDCRYPTO_DES_KEY_SIZE * 3] );
+
+/**
+ * \brief          DES-ECB block encryption/decryption
+ *
+ * \param ctx      DES context
+ * \param input    64-bit input block
+ * \param output   64-bit output block
+ *
+ * \return         0 if successful
+ *
+ * \warning        DES is considered a weak cipher and its use constitutes a
+ *                 security risk. We recommend considering stronger ciphers
+ *                 instead.
+ */
+int mbedcrypto_des_crypt_ecb( mbedcrypto_des_context *ctx,
+                    const unsigned char input[8],
+                    unsigned char output[8] );
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+/**
+ * \brief          DES-CBC buffer encryption/decryption
+ *
+ * \note           Upon exit, the content of the IV is updated so that you can
+ *                 call the function same function again on the following
+ *                 block(s) of data and get the same result as if it was
+ *                 encrypted in one call. This allows a "streaming" usage.
+ *                 If on the other hand you need to retain the contents of the
+ *                 IV, you should either save it manually or use the cipher
+ *                 module instead.
+ *
+ * \param ctx      DES context
+ * \param mode     MBEDCRYPTO_DES_ENCRYPT or MBEDCRYPTO_DES_DECRYPT
+ * \param length   length of the input data
+ * \param iv       initialization vector (updated after use)
+ * \param input    buffer holding the input data
+ * \param output   buffer holding the output data
+ *
+ * \warning        DES is considered a weak cipher and its use constitutes a
+ *                 security risk. We recommend considering stronger ciphers
+ *                 instead.
+ */
+int mbedcrypto_des_crypt_cbc( mbedcrypto_des_context *ctx,
+                    int mode,
+                    size_t length,
+                    unsigned char iv[8],
+                    const unsigned char *input,
+                    unsigned char *output );
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+
+/**
+ * \brief          3DES-ECB block encryption/decryption
+ *
+ * \param ctx      3DES context
+ * \param input    64-bit input block
+ * \param output   64-bit output block
+ *
+ * \return         0 if successful
+ */
+int mbedcrypto_des3_crypt_ecb( mbedcrypto_des3_context *ctx,
+                     const unsigned char input[8],
+                     unsigned char output[8] );
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+/**
+ * \brief          3DES-CBC buffer encryption/decryption
+ *
+ * \note           Upon exit, the content of the IV is updated so that you can
+ *                 call the function same function again on the following
+ *                 block(s) of data and get the same result as if it was
+ *                 encrypted in one call. This allows a "streaming" usage.
+ *                 If on the other hand you need to retain the contents of the
+ *                 IV, you should either save it manually or use the cipher
+ *                 module instead.
+ *
+ * \param ctx      3DES context
+ * \param mode     MBEDCRYPTO_DES_ENCRYPT or MBEDCRYPTO_DES_DECRYPT
+ * \param length   length of the input data
+ * \param iv       initialization vector (updated after use)
+ * \param input    buffer holding the input data
+ * \param output   buffer holding the output data
+ *
+ * \return         0 if successful, or MBEDCRYPTO_ERR_DES_INVALID_INPUT_LENGTH
+ */
+int mbedcrypto_des3_crypt_cbc( mbedcrypto_des3_context *ctx,
+                     int mode,
+                     size_t length,
+                     unsigned char iv[8],
+                     const unsigned char *input,
+                     unsigned char *output );
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+
+/**
+ * \brief          Internal function for key expansion.
+ *                 (Only exposed to allow overriding it,
+ *                 see MBEDCRYPTO_DES_SETKEY_ALT)
+ *
+ * \param SK       Round keys
+ * \param key      Base key
+ *
+ * \warning        DES is considered a weak cipher and its use constitutes a
+ *                 security risk. We recommend considering stronger ciphers
+ *                 instead.
+ */
+void mbedcrypto_des_setkey( uint32_t SK[32],
+                         const unsigned char key[MBEDCRYPTO_DES_KEY_SIZE] );
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int mbedcrypto_des_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* des.h */
diff --git a/include/mbedcrypto/ecdsa.h b/include/mbedcrypto/ecdsa.h
new file mode 100644
index 0000000..93084a5
--- /dev/null
+++ b/include/mbedcrypto/ecdsa.h
@@ -0,0 +1,339 @@
+/**
+ * \file ecdsa.h
+ *
+ * \brief This file contains ECDSA definitions and functions.
+ *
+ * The Elliptic Curve Digital Signature Algorithm (ECDSA) is defined in
+ * <em>Standards for Efficient Cryptography Group (SECG):
+ * SEC1 Elliptic Curve Cryptography</em>.
+ * The use of ECDSA for TLS is defined in <em>RFC-4492: Elliptic Curve
+ * Cryptography (ECC) Cipher Suites for Transport Layer Security (TLS)</em>.
+ *
+ */
+/*
+ *  Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#ifndef MBEDCRYPTO_ECDSA_H
+#define MBEDCRYPTO_ECDSA_H
+
+#include "ecp.h"
+#include "md.h"
+
+/*
+ * RFC-4492 page 20:
+ *
+ *     Ecdsa-Sig-Value ::= SEQUENCE {
+ *         r       INTEGER,
+ *         s       INTEGER
+ *     }
+ *
+ * Size is at most
+ *    1 (tag) + 1 (len) + 1 (initial 0) + ECP_MAX_BYTES for each of r and s,
+ *    twice that + 1 (tag) + 2 (len) for the sequence
+ * (assuming ECP_MAX_BYTES is less than 126 for r and s,
+ * and less than 124 (total len <= 255) for the sequence)
+ */
+#if MBEDCRYPTO_ECP_MAX_BYTES > 124
+#error "MBEDCRYPTO_ECP_MAX_BYTES bigger than expected, please fix MBEDCRYPTO_ECDSA_MAX_LEN"
+#endif
+/** The maximal size of an ECDSA signature in Bytes. */
+#define MBEDCRYPTO_ECDSA_MAX_LEN  ( 3 + 2 * ( 3 + MBEDCRYPTO_ECP_MAX_BYTES ) )
+
+/**
+ * \brief           The ECDSA context structure.
+ */
+typedef mbedcrypto_ecp_keypair mbedcrypto_ecdsa_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief           This function computes the ECDSA signature of a
+ *                  previously-hashed message.
+ *
+ * \note            The deterministic version is usually preferred.
+ *
+ * \note            If the bitlength of the message hash is larger than the
+ *                  bitlength of the group order, then the hash is truncated
+ *                  as defined in <em>Standards for Efficient Cryptography Group
+ *                  (SECG): SEC1 Elliptic Curve Cryptography</em>, section
+ *                  4.1.3, step 5.
+ *
+ * \see             ecp.h
+ *
+ * \param grp       The ECP group.
+ * \param r         The first output integer.
+ * \param s         The second output integer.
+ * \param d         The private signing key.
+ * \param buf       The message hash.
+ * \param blen      The length of \p buf.
+ * \param f_rng     The RNG function.
+ * \param p_rng     The RNG context.
+ *
+ * \return          \c 0 on success.
+ * \return          An \c MBEDCRYPTO_ERR_ECP_XXX
+ *                  or \c MBEDCRYPTO_MPI_XXX error code on failure.
+ */
+int mbedcrypto_ecdsa_sign( mbedcrypto_ecp_group *grp, mbedcrypto_mpi *r, mbedcrypto_mpi *s,
+                const mbedcrypto_mpi *d, const unsigned char *buf, size_t blen,
+                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
+
+#if defined(MBEDCRYPTO_ECDSA_DETERMINISTIC)
+/**
+ * \brief           This function computes the ECDSA signature of a
+ *                  previously-hashed message, deterministic version.
+ *
+ *                  For more information, see <em>RFC-6979: Deterministic
+ *                  Usage of the Digital Signature Algorithm (DSA) and Elliptic
+ *                  Curve Digital Signature Algorithm (ECDSA)</em>.
+ *
+ * \note            If the bitlength of the message hash is larger than the
+ *                  bitlength of the group order, then the hash is truncated as
+ *                  defined in <em>Standards for Efficient Cryptography Group
+ *                  (SECG): SEC1 Elliptic Curve Cryptography</em>, section
+ *                  4.1.3, step 5.
+ *
+ * \see             ecp.h
+ *
+ * \param grp       The ECP group.
+ * \param r         The first output integer.
+ * \param s         The second output integer.
+ * \param d         The private signing key.
+ * \param buf       The message hash.
+ * \param blen      The length of \p buf.
+ * \param md_alg    The MD algorithm used to hash the message.
+ *
+ * \return          \c 0 on success.
+ * \return          An \c MBEDCRYPTO_ERR_ECP_XXX or \c MBEDCRYPTO_MPI_XXX
+ *                  error code on failure.
+ */
+int mbedcrypto_ecdsa_sign_det( mbedcrypto_ecp_group *grp, mbedcrypto_mpi *r, mbedcrypto_mpi *s,
+                    const mbedcrypto_mpi *d, const unsigned char *buf, size_t blen,
+                    mbedcrypto_md_type_t md_alg );
+#endif /* MBEDCRYPTO_ECDSA_DETERMINISTIC */
+
+/**
+ * \brief           This function verifies the ECDSA signature of a
+ *                  previously-hashed message.
+ *
+ * \note            If the bitlength of the message hash is larger than the
+ *                  bitlength of the group order, then the hash is truncated as
+ *                  defined in <em>Standards for Efficient Cryptography Group
+ *                  (SECG): SEC1 Elliptic Curve Cryptography</em>, section
+ *                  4.1.4, step 3.
+ *
+ * \see             ecp.h
+ *
+ * \param grp       The ECP group.
+ * \param buf       The message hash.
+ * \param blen      The length of \p buf.
+ * \param Q         The public key to use for verification.
+ * \param r         The first integer of the signature.
+ * \param s         The second integer of the signature.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA if the signature
+ *                  is invalid.
+ * \return          An \c MBEDCRYPTO_ERR_ECP_XXX or \c MBEDCRYPTO_MPI_XXX
+ *                  error code on failure for any other reason.
+ */
+int mbedcrypto_ecdsa_verify( mbedcrypto_ecp_group *grp,
+                  const unsigned char *buf, size_t blen,
+                  const mbedcrypto_ecp_point *Q, const mbedcrypto_mpi *r, const mbedcrypto_mpi *s);
+
+/**
+ * \brief           This function computes the ECDSA signature and writes it
+ *                  to a buffer, serialized as defined in <em>RFC-4492:
+ *                  Elliptic Curve Cryptography (ECC) Cipher Suites for
+ *                  Transport Layer Security (TLS)</em>.
+ *
+ * \warning         It is not thread-safe to use the same context in
+ *                  multiple threads.
+ *
+ * \note            The deterministic version is used if
+ *                  #MBEDCRYPTO_ECDSA_DETERMINISTIC is defined. For more
+ *                  information, see <em>RFC-6979: Deterministic Usage
+ *                  of the Digital Signature Algorithm (DSA) and Elliptic
+ *                  Curve Digital Signature Algorithm (ECDSA)</em>.
+ *
+ * \note            The \p sig buffer must be at least twice as large as the
+ *                  size of the curve used, plus 9. For example, 73 Bytes if
+ *                  a 256-bit curve is used. A buffer length of
+ *                  #MBEDCRYPTO_ECDSA_MAX_LEN is always safe.
+ *
+ * \note            If the bitlength of the message hash is larger than the
+ *                  bitlength of the group order, then the hash is truncated as
+ *                  defined in <em>Standards for Efficient Cryptography Group
+ *                  (SECG): SEC1 Elliptic Curve Cryptography</em>, section
+ *                  4.1.3, step 5.
+ *
+ * \see             ecp.h
+ *
+ * \param ctx       The ECDSA context.
+ * \param md_alg    The message digest that was used to hash the message.
+ * \param hash      The message hash.
+ * \param hlen      The length of the hash.
+ * \param sig       The buffer that holds the signature.
+ * \param slen      The length of the signature written.
+ * \param f_rng     The RNG function.
+ * \param p_rng     The RNG context.
+ *
+ * \return          \c 0 on success.
+ * \return          An \c MBEDCRYPTO_ERR_ECP_XXX, \c MBEDCRYPTO_ERR_MPI_XXX or
+ *                  \c MBEDCRYPTO_ERR_ASN1_XXX error code on failure.
+ */
+int mbedcrypto_ecdsa_write_signature( mbedcrypto_ecdsa_context *ctx, mbedcrypto_md_type_t md_alg,
+                           const unsigned char *hash, size_t hlen,
+                           unsigned char *sig, size_t *slen,
+                           int (*f_rng)(void *, unsigned char *, size_t),
+                           void *p_rng );
+
+#if defined(MBEDCRYPTO_ECDSA_DETERMINISTIC)
+#if ! defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING)
+#define MBEDCRYPTO_DEPRECATED    __attribute__((deprecated))
+#else
+#define MBEDCRYPTO_DEPRECATED
+#endif
+/**
+ * \brief           This function computes an ECDSA signature and writes
+ *                  it to a buffer, serialized as defined in <em>RFC-4492:
+ *                  Elliptic Curve Cryptography (ECC) Cipher Suites for
+ *                  Transport Layer Security (TLS)</em>.
+ *
+ *                  The deterministic version is defined in <em>RFC-6979:
+ *                  Deterministic Usage of the Digital Signature Algorithm (DSA)
+ *                  and Elliptic Curve Digital Signature Algorithm (ECDSA)</em>.
+ *
+ * \warning         It is not thread-safe to use the same context in
+ *                  multiple threads.
+ *
+ * \note            The \p sig buffer must be at least twice as large as the
+ *                  size of the curve used, plus 9. For example, 73 Bytes if a
+ *                  256-bit curve is used. A buffer length of
+ *                  #MBEDCRYPTO_ECDSA_MAX_LEN is always safe.
+ *
+ * \note            If the bitlength of the message hash is larger than the
+ *                  bitlength of the group order, then the hash is truncated as
+ *                  defined in <em>Standards for Efficient Cryptography Group
+ *                  (SECG): SEC1 Elliptic Curve Cryptography</em>, section
+ *                  4.1.3, step 5.
+ *
+ * \see             ecp.h
+ *
+ * \deprecated      Superseded by mbedcrypto_ecdsa_write_signature() in
+ *                  Mbed Crypto version 2.0 and later.
+ *
+ * \param ctx       The ECDSA context.
+ * \param hash      The message hash.
+ * \param hlen      The length of the hash.
+ * \param sig       The buffer that holds the signature.
+ * \param slen      The length of the signature written.
+ * \param md_alg    The MD algorithm used to hash the message.
+ *
+ * \return          \c 0 on success.
+ * \return          An \c MBEDCRYPTO_ERR_ECP_XXX, \c MBEDCRYPTO_ERR_MPI_XXX or
+ *                  \c MBEDCRYPTO_ERR_ASN1_XXX error code on failure.
+ */
+int mbedcrypto_ecdsa_write_signature_det( mbedcrypto_ecdsa_context *ctx,
+                               const unsigned char *hash, size_t hlen,
+                               unsigned char *sig, size_t *slen,
+                               mbedcrypto_md_type_t md_alg ) MBEDCRYPTO_DEPRECATED;
+#undef MBEDCRYPTO_DEPRECATED
+#endif /* MBEDCRYPTO_DEPRECATED_REMOVED */
+#endif /* MBEDCRYPTO_ECDSA_DETERMINISTIC */
+
+/**
+ * \brief           This function reads and verifies an ECDSA signature.
+ *
+ * \note            If the bitlength of the message hash is larger than the
+ *                  bitlength of the group order, then the hash is truncated as
+ *                  defined in <em>Standards for Efficient Cryptography Group
+ *                  (SECG): SEC1 Elliptic Curve Cryptography</em>, section
+ *                  4.1.4, step 3.
+ *
+ * \see             ecp.h
+ *
+ * \param ctx       The ECDSA context.
+ * \param hash      The message hash.
+ * \param hlen      The size of the hash.
+ * \param sig       The signature to read and verify.
+ * \param slen      The size of \p sig.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA if signature is invalid.
+ * \return          #MBEDCRYPTO_ERR_ECP_SIG_LEN_MISMATCH if there is a valid
+ *                  signature in \p sig, but its length is less than \p siglen.
+ * \return          An \c MBEDCRYPTO_ERR_ECP_XXX or \c MBEDCRYPTO_ERR_MPI_XXX
+ *                  error code on failure for any other reason.
+ */
+int mbedcrypto_ecdsa_read_signature( mbedcrypto_ecdsa_context *ctx,
+                          const unsigned char *hash, size_t hlen,
+                          const unsigned char *sig, size_t slen );
+
+/**
+ * \brief          This function generates an ECDSA keypair on the given curve.
+ *
+ * \see            ecp.h
+ *
+ * \param ctx      The ECDSA context to store the keypair in.
+ * \param gid      The elliptic curve to use. One of the various
+ *                 \c MBEDCRYPTO_ECP_DP_XXX macros depending on configuration.
+ * \param f_rng    The RNG function.
+ * \param p_rng    The RNG context.
+ *
+ * \return         \c 0 on success.
+ * \return         An \c MBEDCRYPTO_ERR_ECP_XXX code on failure.
+ */
+int mbedcrypto_ecdsa_genkey( mbedcrypto_ecdsa_context *ctx, mbedcrypto_ecp_group_id gid,
+                  int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
+
+/**
+ * \brief           This function sets an ECDSA context from an EC key pair.
+ *
+ * \see             ecp.h
+ *
+ * \param ctx       The ECDSA context to set.
+ * \param key       The EC key to use.
+ *
+ * \return          \c 0 on success.
+ * \return          An \c MBEDCRYPTO_ERR_ECP_XXX code on failure.
+ */
+int mbedcrypto_ecdsa_from_keypair( mbedcrypto_ecdsa_context *ctx, const mbedcrypto_ecp_keypair *key );
+
+/**
+ * \brief           This function initializes an ECDSA context.
+ *
+ * \param ctx       The ECDSA context to initialize.
+ */
+void mbedcrypto_ecdsa_init( mbedcrypto_ecdsa_context *ctx );
+
+/**
+ * \brief           This function frees an ECDSA context.
+ *
+ * \param ctx       The ECDSA context to free.
+ */
+void mbedcrypto_ecdsa_free( mbedcrypto_ecdsa_context *ctx );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ecdsa.h */
diff --git a/include/mbedcrypto/ecp.h b/include/mbedcrypto/ecp.h
new file mode 100644
index 0000000..eb6bf6c
--- /dev/null
+++ b/include/mbedcrypto/ecp.h
@@ -0,0 +1,764 @@
+/**
+ * \file ecp.h
+ *
+ * \brief This file provides an API for Elliptic Curves over GF(P) (ECP).
+ *
+ * The use of ECP in cryptography and TLS is defined in
+ * <em>Standards for Efficient Cryptography Group (SECG): SEC1
+ * Elliptic Curve Cryptography</em> and
+ * <em>RFC-4492: Elliptic Curve Cryptography (ECC) Cipher Suites
+ * for Transport Layer Security (TLS)</em>.
+ *
+ * <em>RFC-2409: The Internet Key Exchange (IKE)</em> defines ECP
+ * group types.
+ *
+ */
+
+/*
+ *  Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#ifndef MBEDCRYPTO_ECP_H
+#define MBEDCRYPTO_ECP_H
+
+#include "bignum.h"
+
+/*
+ * ECP error codes
+ */
+#define MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA                    -0x4F80  /**< Bad input parameters to function. */
+#define MBEDCRYPTO_ERR_ECP_BUFFER_TOO_SMALL                  -0x4F00  /**< The buffer is too small to write to. */
+#define MBEDCRYPTO_ERR_ECP_FEATURE_UNAVAILABLE               -0x4E80  /**< The requested feature is not available, for example, the requested curve is not supported. */
+#define MBEDCRYPTO_ERR_ECP_VERIFY_FAILED                     -0x4E00  /**< The signature is not valid. */
+#define MBEDCRYPTO_ERR_ECP_ALLOC_FAILED                      -0x4D80  /**< Memory allocation failed. */
+#define MBEDCRYPTO_ERR_ECP_RANDOM_FAILED                     -0x4D00  /**< Generation of random value, such as ephemeral key, failed. */
+#define MBEDCRYPTO_ERR_ECP_INVALID_KEY                       -0x4C80  /**< Invalid private or public key. */
+#define MBEDCRYPTO_ERR_ECP_SIG_LEN_MISMATCH                  -0x4C00  /**< The buffer contains a valid signature followed by more data. */
+#define MBEDCRYPTO_ERR_ECP_HW_ACCEL_FAILED                   -0x4B80  /**< The ECP hardware accelerator failed. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Domain-parameter identifiers: curve, subgroup, and generator.
+ *
+ * \note Only curves over prime fields are supported.
+ *
+ * \warning This library does not support validation of arbitrary domain
+ * parameters. Therefore, only standardized domain parameters from trusted
+ * sources should be used. See mbedcrypto_ecp_group_load().
+ */
+typedef enum
+{
+    MBEDCRYPTO_ECP_DP_NONE = 0,       /*!< Curve not defined. */
+    MBEDCRYPTO_ECP_DP_SECP192R1,      /*!< Domain parameters for the 192-bit curve defined by FIPS 186-4 and SEC1. */
+    MBEDCRYPTO_ECP_DP_SECP224R1,      /*!< Domain parameters for the 224-bit curve defined by FIPS 186-4 and SEC1. */
+    MBEDCRYPTO_ECP_DP_SECP256R1,      /*!< Domain parameters for the 256-bit curve defined by FIPS 186-4 and SEC1. */
+    MBEDCRYPTO_ECP_DP_SECP384R1,      /*!< Domain parameters for the 384-bit curve defined by FIPS 186-4 and SEC1. */
+    MBEDCRYPTO_ECP_DP_SECP521R1,      /*!< Domain parameters for the 521-bit curve defined by FIPS 186-4 and SEC1. */
+    MBEDCRYPTO_ECP_DP_BP256R1,        /*!< Domain parameters for 256-bit Brainpool curve. */
+    MBEDCRYPTO_ECP_DP_BP384R1,        /*!< Domain parameters for 384-bit Brainpool curve. */
+    MBEDCRYPTO_ECP_DP_BP512R1,        /*!< Domain parameters for 512-bit Brainpool curve. */
+    MBEDCRYPTO_ECP_DP_CURVE25519,     /*!< Domain parameters for Curve25519. */
+    MBEDCRYPTO_ECP_DP_SECP192K1,      /*!< Domain parameters for 192-bit "Koblitz" curve. */
+    MBEDCRYPTO_ECP_DP_SECP224K1,      /*!< Domain parameters for 224-bit "Koblitz" curve. */
+    MBEDCRYPTO_ECP_DP_SECP256K1,      /*!< Domain parameters for 256-bit "Koblitz" curve. */
+    MBEDCRYPTO_ECP_DP_CURVE448,       /*!< Domain parameters for Curve448. */
+} mbedcrypto_ecp_group_id;
+
+/**
+ * The number of supported curves, plus one for #MBEDCRYPTO_ECP_DP_NONE.
+ *
+ * \note Montgomery curves are currently excluded.
+ */
+#define MBEDCRYPTO_ECP_DP_MAX     12
+
+/**
+ * Curve information, for use by other modules.
+ */
+typedef struct
+{
+    mbedcrypto_ecp_group_id grp_id;    /*!< An internal identifier. */
+    uint16_t tls_id;                /*!< The TLS NamedCurve identifier. */
+    uint16_t bit_size;              /*!< The curve size in bits. */
+    const char *name;               /*!< A human-friendly name. */
+} mbedcrypto_ecp_curve_info;
+
+/**
+ * \brief           The ECP point structure, in Jacobian coordinates.
+ *
+ * \note            All functions expect and return points satisfying
+ *                  the following condition: <code>Z == 0</code> or
+ *                  <code>Z == 1</code>. Other values of \p Z are
+ *                  used only by internal functions.
+ *                  The point is zero, or "at infinity", if <code>Z == 0</code>.
+ *                  Otherwise, \p X and \p Y are its standard (affine)
+ *                  coordinates.
+ */
+typedef struct
+{
+    mbedcrypto_mpi X;          /*!< The X coordinate of the ECP point. */
+    mbedcrypto_mpi Y;          /*!< The Y coordinate of the ECP point. */
+    mbedcrypto_mpi Z;          /*!< The Z coordinate of the ECP point. */
+}
+mbedcrypto_ecp_point;
+
+#if !defined(MBEDCRYPTO_ECP_ALT)
+/*
+ * default Mbed Crypto elliptic curve arithmetic implementation
+ *
+ * (in case MBEDCRYPTO_ECP_ALT is defined then the developer has to provide an
+ * alternative implementation for the whole module and it will replace this
+ * one.)
+ */
+
+/**
+ * \brief           The ECP group structure.
+ *
+ * We consider two types of curve equations:
+ * <ul><li>Short Weierstrass: <code>y^2 = x^3 + A x + B mod P</code>
+ * (SEC1 + RFC-4492)</li>
+ * <li>Montgomery: <code>y^2 = x^3 + A x^2 + x mod P</code> (Curve25519,
+ * Curve448)</li></ul>
+ * In both cases, the generator (\p G) for a prime-order subgroup is fixed.
+ *
+ * For Short Weierstrass, this subgroup is the whole curve, and its
+ * cardinality is denoted by \p N. Our code requires that \p N is an
+ * odd prime as mbedcrypto_ecp_mul() requires an odd number, and
+ * mbedcrypto_ecdsa_sign() requires that it is prime for blinding purposes.
+ *
+ * For Montgomery curves, we do not store \p A, but <code>(A + 2) / 4</code>,
+ * which is the quantity used in the formulas. Additionally, \p nbits is
+ * not the size of \p N but the required size for private keys.
+ *
+ * If \p modp is NULL, reduction modulo \p P is done using a generic algorithm.
+ * Otherwise, \p modp must point to a function that takes an \p mbedcrypto_mpi in the
+ * range of <code>0..2^(2*pbits)-1</code>, and transforms it in-place to an integer
+ * which is congruent mod \p P to the given MPI, and is close enough to \p pbits
+ * in size, so that it may be efficiently brought in the 0..P-1 range by a few
+ * additions or subtractions. Therefore, it is only an approximative modular
+ * reduction. It must return 0 on success and non-zero on failure.
+ *
+ */
+typedef struct
+{
+    mbedcrypto_ecp_group_id id;    /*!< An internal group identifier. */
+    mbedcrypto_mpi P;              /*!< The prime modulus of the base field. */
+    mbedcrypto_mpi A;              /*!< For Short Weierstrass: \p A in the equation. For
+                                     Montgomery curves: <code>(A + 2) / 4</code>. */
+    mbedcrypto_mpi B;              /*!< For Short Weierstrass: \p B in the equation.
+                                     For Montgomery curves: unused. */
+    mbedcrypto_ecp_point G;        /*!< The generator of the subgroup used. */
+    mbedcrypto_mpi N;              /*!< The order of \p G. */
+    size_t pbits;               /*!< The number of bits in \p P.*/
+    size_t nbits;               /*!< For Short Weierstrass: The number of bits in \p P.
+                                     For Montgomery curves: the number of bits in the
+                                     private keys. */
+    unsigned int h;             /*!< \internal 1 if the constants are static. */
+    int (*modp)(mbedcrypto_mpi *); /*!< The function for fast pseudo-reduction
+                                     mod \p P (see above).*/
+    int (*t_pre)(mbedcrypto_ecp_point *, void *);  /*!< Unused. */
+    int (*t_post)(mbedcrypto_ecp_point *, void *); /*!< Unused. */
+    void *t_data;               /*!< Unused. */
+    mbedcrypto_ecp_point *T;       /*!< Pre-computed points for ecp_mul_comb(). */
+    size_t T_size;              /*!< The number of pre-computed points. */
+}
+mbedcrypto_ecp_group;
+
+/**
+ * \name SECTION: Module settings
+ *
+ * The configuration options you can set for this module are in this section.
+ * Either change them in config.h, or define them using the compiler command line.
+ * \{
+ */
+
+#if !defined(MBEDCRYPTO_ECP_MAX_BITS)
+/**
+ * The maximum size of the groups, that is, of \c N and \c P.
+ */
+#define MBEDCRYPTO_ECP_MAX_BITS     521   /**< The maximum size of groups, in bits. */
+#endif
+
+#define MBEDCRYPTO_ECP_MAX_BYTES    ( ( MBEDCRYPTO_ECP_MAX_BITS + 7 ) / 8 )
+#define MBEDCRYPTO_ECP_MAX_PT_LEN   ( 2 * MBEDCRYPTO_ECP_MAX_BYTES + 1 )
+
+#if !defined(MBEDCRYPTO_ECP_WINDOW_SIZE)
+/*
+ * Maximum "window" size used for point multiplication.
+ * Default: 6.
+ * Minimum value: 2. Maximum value: 7.
+ *
+ * Result is an array of at most ( 1 << ( MBEDCRYPTO_ECP_WINDOW_SIZE - 1 ) )
+ * points used for point multiplication. This value is directly tied to EC
+ * peak memory usage, so decreasing it by one should roughly cut memory usage
+ * by two (if large curves are in use).
+ *
+ * Reduction in size may reduce speed, but larger curves are impacted first.
+ * Sample performances (in ECDHE handshakes/s, with FIXED_POINT_OPTIM = 1):
+ *      w-size:     6       5       4       3       2
+ *      521       145     141     135     120      97
+ *      384       214     209     198     177     146
+ *      256       320     320     303     262     226
+ *      224       475     475     453     398     342
+ *      192       640     640     633     587     476
+ */
+#define MBEDCRYPTO_ECP_WINDOW_SIZE    6   /**< The maximum window size used. */
+#endif /* MBEDCRYPTO_ECP_WINDOW_SIZE */
+
+#if !defined(MBEDCRYPTO_ECP_FIXED_POINT_OPTIM)
+/*
+ * Trade memory for speed on fixed-point multiplication.
+ *
+ * This speeds up repeated multiplication of the generator (that is, the
+ * multiplication in ECDSA signatures, and half of the multiplications in
+ * ECDSA verification and ECDHE) by a factor roughly 3 to 4.
+ *
+ * The cost is increasing EC peak memory usage by a factor roughly 2.
+ *
+ * Change this value to 0 to reduce peak memory usage.
+ */
+#define MBEDCRYPTO_ECP_FIXED_POINT_OPTIM  1   /**< Enable fixed-point speed-up. */
+#endif /* MBEDCRYPTO_ECP_FIXED_POINT_OPTIM */
+
+/* \} name SECTION: Module settings */
+
+#else  /* MBEDCRYPTO_ECP_ALT */
+#include "ecp_alt.h"
+#endif /* MBEDCRYPTO_ECP_ALT */
+
+/**
+ * \brief    The ECP key-pair structure.
+ *
+ * A generic key-pair that may be used for ECDSA and fixed ECDH, for example.
+ *
+ * \note    Members are deliberately in the same order as in the
+ *          ::mbedcrypto_ecdsa_context structure.
+ */
+typedef struct
+{
+    mbedcrypto_ecp_group grp;      /*!<  Elliptic curve and base point     */
+    mbedcrypto_mpi d;              /*!<  our secret value                  */
+    mbedcrypto_ecp_point Q;        /*!<  our public value                  */
+}
+mbedcrypto_ecp_keypair;
+
+/*
+ * Point formats, from RFC 4492's enum ECPointFormat
+ */
+#define MBEDCRYPTO_ECP_PF_UNCOMPRESSED    0   /**< Uncompressed point format. */
+#define MBEDCRYPTO_ECP_PF_COMPRESSED      1   /**< Compressed point format. */
+
+/*
+ * Some other constants from RFC 4492
+ */
+#define MBEDCRYPTO_ECP_TLS_NAMED_CURVE    3   /**< The named_curve of ECCurveType. */
+
+/**
+ * \brief           This function retrieves the information defined in
+ *                  mbedcrypto_ecp_curve_info() for all supported curves in order
+ *                  of preference.
+ *
+ * \return          A statically allocated array. The last entry is 0.
+ */
+const mbedcrypto_ecp_curve_info *mbedcrypto_ecp_curve_list( void );
+
+/**
+ * \brief           This function retrieves the list of internal group
+ *                  identifiers of all supported curves in the order of
+ *                  preference.
+ *
+ * \return          A statically allocated array,
+ *                  terminated with MBEDCRYPTO_ECP_DP_NONE.
+ */
+const mbedcrypto_ecp_group_id *mbedcrypto_ecp_grp_id_list( void );
+
+/**
+ * \brief           This function retrieves curve information from an internal
+ *                  group identifier.
+ *
+ * \param grp_id    An \c MBEDCRYPTO_ECP_DP_XXX value.
+ *
+ * \return          The associated curve information on success.
+ * \return          NULL on failure.
+ */
+const mbedcrypto_ecp_curve_info *mbedcrypto_ecp_curve_info_from_grp_id( mbedcrypto_ecp_group_id grp_id );
+
+/**
+ * \brief           This function retrieves curve information from a TLS
+ *                  NamedCurve value.
+ *
+ * \param tls_id    An \c MBEDCRYPTO_ECP_DP_XXX value.
+ *
+ * \return          The associated curve information on success.
+ * \return          NULL on failure.
+ */
+const mbedcrypto_ecp_curve_info *mbedcrypto_ecp_curve_info_from_tls_id( uint16_t tls_id );
+
+/**
+ * \brief           This function retrieves curve information from a
+ *                  human-readable name.
+ *
+ * \param name      The human-readable name.
+ *
+ * \return          The associated curve information on success.
+ * \return          NULL on failure.
+ */
+const mbedcrypto_ecp_curve_info *mbedcrypto_ecp_curve_info_from_name( const char *name );
+
+/**
+ * \brief           This function initializes a point as zero.
+ *
+ * \param pt        The point to initialize.
+ */
+void mbedcrypto_ecp_point_init( mbedcrypto_ecp_point *pt );
+
+/**
+ * \brief           This function initializes an ECP group context
+ *                  without loading any domain parameters.
+ *
+ * \note            After this function is called, domain parameters
+ *                  for various ECP groups can be loaded through the
+ *                  mbedcrypto_ecp_load() or mbedcrypto_ecp_tls_read_group()
+ *                  functions.
+ */
+void mbedcrypto_ecp_group_init( mbedcrypto_ecp_group *grp );
+
+/**
+ * \brief           This function initializes a key pair as an invalid one.
+ *
+ * \param key       The key pair to initialize.
+ */
+void mbedcrypto_ecp_keypair_init( mbedcrypto_ecp_keypair *key );
+
+/**
+ * \brief           This function frees the components of a point.
+ *
+ * \param pt        The point to free.
+ */
+void mbedcrypto_ecp_point_free( mbedcrypto_ecp_point *pt );
+
+/**
+ * \brief           This function frees the components of an ECP group.
+ * \param grp       The group to free.
+ */
+void mbedcrypto_ecp_group_free( mbedcrypto_ecp_group *grp );
+
+/**
+ * \brief           This function frees the components of a key pair.
+ * \param key       The key pair to free.
+ */
+void mbedcrypto_ecp_keypair_free( mbedcrypto_ecp_keypair *key );
+
+/**
+ * \brief           This function copies the contents of point \p Q into
+ *                  point \p P.
+ *
+ * \param P         The destination point.
+ * \param Q         The source point.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDCRYPTO_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
+ */
+int mbedcrypto_ecp_copy( mbedcrypto_ecp_point *P, const mbedcrypto_ecp_point *Q );
+
+/**
+ * \brief           This function copies the contents of group \p src into
+ *                  group \p dst.
+ *
+ * \param dst       The destination group.
+ * \param src       The source group.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDCRYPTO_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
+ */
+int mbedcrypto_ecp_group_copy( mbedcrypto_ecp_group *dst, const mbedcrypto_ecp_group *src );
+
+/**
+ * \brief           This function sets a point to zero.
+ *
+ * \param pt        The point to set.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDCRYPTO_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
+ */
+int mbedcrypto_ecp_set_zero( mbedcrypto_ecp_point *pt );
+
+/**
+ * \brief           This function checks if a point is zero.
+ *
+ * \param pt        The point to test.
+ *
+ * \return          \c 1 if the point is zero.
+ * \return          \c 0 if the point is non-zero.
+ */
+int mbedcrypto_ecp_is_zero( mbedcrypto_ecp_point *pt );
+
+/**
+ * \brief           This function compares two points.
+ *
+ * \note            This assumes that the points are normalized. Otherwise,
+ *                  they may compare as "not equal" even if they are.
+ *
+ * \param P         The first point to compare.
+ * \param Q         The second point to compare.
+ *
+ * \return          \c 0 if the points are equal.
+ * \return          #MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA if the points are not equal.
+ */
+int mbedcrypto_ecp_point_cmp( const mbedcrypto_ecp_point *P,
+                           const mbedcrypto_ecp_point *Q );
+
+/**
+ * \brief           This function imports a non-zero point from two ASCII
+ *                  strings.
+ *
+ * \param P         The destination point.
+ * \param radix     The numeric base of the input.
+ * \param x         The first affine coordinate, as a null-terminated string.
+ * \param y         The second affine coordinate, as a null-terminated string.
+ *
+ * \return          \c 0 on success.
+ * \return          An \c MBEDCRYPTO_ERR_MPI_XXX error code on failure.
+ */
+int mbedcrypto_ecp_point_read_string( mbedcrypto_ecp_point *P, int radix,
+                           const char *x, const char *y );
+
+/**
+ * \brief           This function exports a point into unsigned binary data.
+ *
+ * \param grp       The group to which the point should belong.
+ * \param P         The point to export.
+ * \param format    The point format. Should be an \c MBEDCRYPTO_ECP_PF_XXX macro.
+ * \param olen      The length of the output.
+ * \param buf       The output buffer.
+ * \param buflen    The length of the output buffer.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA
+ *                  or #MBEDCRYPTO_ERR_ECP_BUFFER_TOO_SMALL on failure.
+ */
+int mbedcrypto_ecp_point_write_binary( const mbedcrypto_ecp_group *grp, const mbedcrypto_ecp_point *P,
+                            int format, size_t *olen,
+                            unsigned char *buf, size_t buflen );
+
+/**
+ * \brief           This function imports a point from unsigned binary data.
+ *
+ * \note            This function does not check that the point actually
+ *                  belongs to the given group, see mbedcrypto_ecp_check_pubkey()
+ *                  for that.
+ *
+ * \param grp       The group to which the point should belong.
+ * \param P         The point to import.
+ * \param buf       The input buffer.
+ * \param ilen      The length of the input.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA if input is invalid.
+ * \return          #MBEDCRYPTO_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
+ * \return          #MBEDCRYPTO_ERR_ECP_FEATURE_UNAVAILABLE if the point format
+ *                  is not implemented.
+ *
+ */
+int mbedcrypto_ecp_point_read_binary( const mbedcrypto_ecp_group *grp, mbedcrypto_ecp_point *P,
+                           const unsigned char *buf, size_t ilen );
+
+/**
+ * \brief           This function imports a point from a TLS ECPoint record.
+ *
+ * \note            On function return, \p buf is updated to point to immediately
+ *                  after the ECPoint record.
+ *
+ * \param grp       The ECP group used.
+ * \param pt        The destination point.
+ * \param buf       The address of the pointer to the start of the input buffer.
+ * \param len       The length of the buffer.
+ *
+ * \return          \c 0 on success.
+ * \return          An \c MBEDCRYPTO_ERR_MPI_XXX error code on initialization failure.
+ * \return          #MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA if input is invalid.
+ */
+int mbedcrypto_ecp_tls_read_point( const mbedcrypto_ecp_group *grp, mbedcrypto_ecp_point *pt,
+                        const unsigned char **buf, size_t len );
+
+/**
+ * \brief           This function exports a point as a TLS ECPoint record.
+ *
+ * \param grp       The ECP group used.
+ * \param pt        The point format to export to. The point format is an
+ *                  \c MBEDCRYPTO_ECP_PF_XXX constant.
+ * \param format    The export format.
+ * \param olen      The length of the data written.
+ * \param buf       The buffer to write to.
+ * \param blen      The length of the buffer.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA or
+ *                  #MBEDCRYPTO_ERR_ECP_BUFFER_TOO_SMALL on failure.
+ */
+int mbedcrypto_ecp_tls_write_point( const mbedcrypto_ecp_group *grp, const mbedcrypto_ecp_point *pt,
+                         int format, size_t *olen,
+                         unsigned char *buf, size_t blen );
+
+/**
+ * \brief           This function sets a group using standardized domain parameters.
+ *
+ * \note            The index should be a value of the NamedCurve enum,
+ *                  as defined in <em>RFC-4492: Elliptic Curve Cryptography
+ *                  (ECC) Cipher Suites for Transport Layer Security (TLS)</em>,
+ *                  usually in the form of an \c MBEDCRYPTO_ECP_DP_XXX macro.
+ *
+ * \param grp       The destination group.
+ * \param id        The identifier of the domain parameter set to load.
+ *
+ * \return          \c 0 on success,
+ * \return          An \c MBEDCRYPTO_ERR_MPI_XXX error code on initialization failure.
+ * \return          #MBEDCRYPTO_ERR_ECP_FEATURE_UNAVAILABLE for unkownn groups.
+
+ */
+int mbedcrypto_ecp_group_load( mbedcrypto_ecp_group *grp, mbedcrypto_ecp_group_id id );
+
+/**
+ * \brief           This function sets a group from a TLS ECParameters record.
+ *
+ * \note            \p buf is updated to point right after the ECParameters record
+ *                  on exit.
+ *
+ * \param grp       The destination group.
+ * \param buf       The address of the pointer to the start of the input buffer.
+ * \param len       The length of the buffer.
+ *
+ * \return          \c 0 on success.
+ * \return          An \c MBEDCRYPTO_ERR_MPI_XXX error code on initialization failure.
+ * \return          #MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA if input is invalid.
+ */
+int mbedcrypto_ecp_tls_read_group( mbedcrypto_ecp_group *grp, const unsigned char **buf, size_t len );
+
+/**
+ * \brief           This function writes the TLS ECParameters record for a group.
+ *
+ * \param grp       The ECP group used.
+ * \param olen      The number of Bytes written.
+ * \param buf       The buffer to write to.
+ * \param blen      The length of the buffer.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDCRYPTO_ERR_ECP_BUFFER_TOO_SMALL on failure.
+ */
+int mbedcrypto_ecp_tls_write_group( const mbedcrypto_ecp_group *grp, size_t *olen,
+                         unsigned char *buf, size_t blen );
+
+/**
+ * \brief           This function performs multiplication of a point by
+ *                  an integer: \p R = \p m * \p P.
+ *
+ *                  It is not thread-safe to use same group in multiple threads.
+ *
+ * \note            To prevent timing attacks, this function
+ *                  executes the exact same sequence of base-field
+ *                  operations for any valid \p m. It avoids any if-branch or
+ *                  array index depending on the value of \p m.
+ *
+ * \note            If \p f_rng is not NULL, it is used to randomize
+ *                  intermediate results to prevent potential timing attacks
+ *                  targeting these results. We recommend always providing
+ *                  a non-NULL \p f_rng. The overhead is negligible.
+ *
+ * \param grp       The ECP group.
+ * \param R         The destination point.
+ * \param m         The integer by which to multiply.
+ * \param P         The point to multiply.
+ * \param f_rng     The RNG function.
+ * \param p_rng     The RNG context.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDCRYPTO_ERR_ECP_INVALID_KEY if \p m is not a valid private
+ *                  key, or \p P is not a valid public key.
+ * \return          #MBEDCRYPTO_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
+ */
+int mbedcrypto_ecp_mul( mbedcrypto_ecp_group *grp, mbedcrypto_ecp_point *R,
+             const mbedcrypto_mpi *m, const mbedcrypto_ecp_point *P,
+             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
+
+/**
+ * \brief           This function performs multiplication and addition of two
+ *                  points by integers: \p R = \p m * \p P + \p n * \p Q
+ *
+ *                  It is not thread-safe to use same group in multiple threads.
+ *
+ * \note            In contrast to mbedcrypto_ecp_mul(), this function does not
+ *                  guarantee a constant execution flow and timing.
+ *
+ * \param grp       The ECP group.
+ * \param R         The destination point.
+ * \param m         The integer by which to multiply \p P.
+ * \param P         The point to multiply by \p m.
+ * \param n         The integer by which to multiply \p Q.
+ * \param Q         The point to be multiplied by \p n.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDCRYPTO_ERR_ECP_INVALID_KEY if \p m or \p n are not
+ *                  valid private keys, or \p P or \p Q are not valid public
+ *                  keys.
+ * \return          #MBEDCRYPTO_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
+ */
+int mbedcrypto_ecp_muladd( mbedcrypto_ecp_group *grp, mbedcrypto_ecp_point *R,
+             const mbedcrypto_mpi *m, const mbedcrypto_ecp_point *P,
+             const mbedcrypto_mpi *n, const mbedcrypto_ecp_point *Q );
+
+/**
+ * \brief           This function checks that a point is a valid public key
+ *                  on this curve.
+ *
+ *                  It only checks that the point is non-zero, has
+ *                  valid coordinates and lies on the curve. It does not verify
+ *                  that it is indeed a multiple of \p G. This additional
+ *                  check is computationally more expensive, is not required
+ *                  by standards, and should not be necessary if the group
+ *                  used has a small cofactor. In particular, it is useless for
+ *                  the NIST groups which all have a cofactor of 1.
+ *
+ * \note            This function uses bare components rather than an
+ *                  ::mbedcrypto_ecp_keypair structure, to ease use with other
+ *                  structures, such as ::mbedcrypto_ecdh_context or
+ *                  ::mbedcrypto_ecdsa_context.
+ *
+ * \param grp       The curve the point should lie on.
+ * \param pt        The point to check.
+ *
+ * \return          \c 0 if the point is a valid public key.
+ * \return          #MBEDCRYPTO_ERR_ECP_INVALID_KEY on failure.
+ */
+int mbedcrypto_ecp_check_pubkey( const mbedcrypto_ecp_group *grp, const mbedcrypto_ecp_point *pt );
+
+/**
+ * \brief           This function checks that an \p mbedcrypto_mpi is a valid private
+ *                  key for this curve.
+ *
+ * \note            This function uses bare components rather than an
+ *                  ::mbedcrypto_ecp_keypair structure to ease use with other
+ *                  structures, such as ::mbedcrypto_ecdh_context or
+ *                  ::mbedcrypto_ecdsa_context.
+ *
+ * \param grp       The group used.
+ * \param d         The integer to check.
+ *
+ * \return          \c 0 if the point is a valid private key.
+ * \return          #MBEDCRYPTO_ERR_ECP_INVALID_KEY on failure.
+ */
+int mbedcrypto_ecp_check_privkey( const mbedcrypto_ecp_group *grp, const mbedcrypto_mpi *d );
+
+/**
+ * \brief           This function generates a keypair with a configurable base
+ *                  point.
+ *
+ * \note            This function uses bare components rather than an
+ *                  ::mbedcrypto_ecp_keypair structure to ease use with other
+ *                  structures, such as ::mbedcrypto_ecdh_context or
+ *                  ::mbedcrypto_ecdsa_context.
+ *
+ * \param grp       The ECP group.
+ * \param G         The chosen base point.
+ * \param d         The destination MPI (secret part).
+ * \param Q         The destination point (public part).
+ * \param f_rng     The RNG function.
+ * \param p_rng     The RNG context.
+ *
+ * \return          \c 0 on success.
+ * \return          An \c MBEDCRYPTO_ERR_ECP_XXX or \c MBEDCRYPTO_MPI_XXX error code
+ *                  on failure.
+ */
+int mbedcrypto_ecp_gen_keypair_base( mbedcrypto_ecp_group *grp,
+                     const mbedcrypto_ecp_point *G,
+                     mbedcrypto_mpi *d, mbedcrypto_ecp_point *Q,
+                     int (*f_rng)(void *, unsigned char *, size_t),
+                     void *p_rng );
+
+/**
+ * \brief           This function generates an ECP keypair.
+ *
+ * \note            This function uses bare components rather than an
+ *                  ::mbedcrypto_ecp_keypair structure to ease use with other
+ *                  structures, such as ::mbedcrypto_ecdh_context or
+ *                  ::mbedcrypto_ecdsa_context.
+ *
+ * \param grp       The ECP group.
+ * \param d         The destination MPI (secret part).
+ * \param Q         The destination point (public part).
+ * \param f_rng     The RNG function.
+ * \param p_rng     The RNG context.
+ *
+ * \return          \c 0 on success.
+ * \return          An \c MBEDCRYPTO_ERR_ECP_XXX or \c MBEDCRYPTO_MPI_XXX error code
+ *                  on failure.
+ */
+int mbedcrypto_ecp_gen_keypair( mbedcrypto_ecp_group *grp, mbedcrypto_mpi *d, mbedcrypto_ecp_point *Q,
+                     int (*f_rng)(void *, unsigned char *, size_t),
+                     void *p_rng );
+
+/**
+ * \brief           This function generates an ECP key.
+ *
+ * \param grp_id    The ECP group identifier.
+ * \param key       The destination key.
+ * \param f_rng     The RNG function.
+ * \param p_rng     The RNG context.
+ *
+ * \return          \c 0 on success.
+ * \return          An \c MBEDCRYPTO_ERR_ECP_XXX or \c MBEDCRYPTO_MPI_XXX error code
+ *                  on failure.
+ */
+int mbedcrypto_ecp_gen_key( mbedcrypto_ecp_group_id grp_id, mbedcrypto_ecp_keypair *key,
+                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
+
+/**
+ * \brief           This function checks that the keypair objects
+ *                  \p pub and \p prv have the same group and the
+ *                  same public point, and that the private key in
+ *                  \p prv is consistent with the public key.
+ *
+ * \param pub       The keypair structure holding the public key.
+ *                  If it contains a private key, that part is ignored.
+ * \param prv       The keypair structure holding the full keypair.
+ *
+ * \return          \c 0 on success, meaning that the keys are valid and match.
+ * \return          #MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA if the keys are invalid or do not match.
+ * \return          An \c MBEDCRYPTO_ERR_ECP_XXX or an \c MBEDCRYPTO_ERR_MPI_XXX
+ *                  error code on calculation failure.
+ */
+int mbedcrypto_ecp_check_pub_priv( const mbedcrypto_ecp_keypair *pub, const mbedcrypto_ecp_keypair *prv );
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+
+/**
+ * \brief          The ECP checkup routine.
+ *
+ * \return         \c 0 on success.
+ * \return         \c 1 on failure.
+ */
+int mbedcrypto_ecp_self_test( int verbose );
+
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ecp.h */
diff --git a/include/mbedcrypto/ecp_internal.h b/include/mbedcrypto/ecp_internal.h
new file mode 100644
index 0000000..98a6bb7
--- /dev/null
+++ b/include/mbedcrypto/ecp_internal.h
@@ -0,0 +1,293 @@
+/**
+ * \file ecp_internal.h
+ *
+ * \brief Function declarations for alternative implementation of elliptic curve
+ * point arithmetic.
+ */
+/*
+ *  Copyright (C) 2016, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+/*
+ * References:
+ *
+ * [1] BERNSTEIN, Daniel J. Curve25519: new Diffie-Hellman speed records.
+ *     <http://cr.yp.to/ecdh/curve25519-20060209.pdf>
+ *
+ * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis
+ *     for elliptic curve cryptosystems. In : Cryptographic Hardware and
+ *     Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302.
+ *     <http://link.springer.com/chapter/10.1007/3-540-48059-5_25>
+ *
+ * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to
+ *     render ECC resistant against Side Channel Attacks. IACR Cryptology
+ *     ePrint Archive, 2004, vol. 2004, p. 342.
+ *     <http://eprint.iacr.org/2004/342.pdf>
+ *
+ * [4] Certicom Research. SEC 2: Recommended Elliptic Curve Domain Parameters.
+ *     <http://www.secg.org/sec2-v2.pdf>
+ *
+ * [5] HANKERSON, Darrel, MENEZES, Alfred J., VANSTONE, Scott. Guide to Elliptic
+ *     Curve Cryptography.
+ *
+ * [6] Digital Signature Standard (DSS), FIPS 186-4.
+ *     <http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf>
+ *
+ * [7] Elliptic Curve Cryptography (ECC) Cipher Suites for Transport Layer
+ *     Security (TLS), RFC 4492.
+ *     <https://tools.ietf.org/search/rfc4492>
+ *
+ * [8] <http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html>
+ *
+ * [9] COHEN, Henri. A Course in Computational Algebraic Number Theory.
+ *     Springer Science & Business Media, 1 Aug 2000
+ */
+
+#ifndef MBEDCRYPTO_ECP_INTERNAL_H
+#define MBEDCRYPTO_ECP_INTERNAL_H
+
+#if defined(MBEDCRYPTO_ECP_INTERNAL_ALT)
+
+/**
+ * \brief           Indicate if the Elliptic Curve Point module extension can
+ *                  handle the group.
+ *
+ * \param grp       The pointer to the elliptic curve group that will be the
+ *                  basis of the cryptographic computations.
+ *
+ * \return          Non-zero if successful.
+ */
+unsigned char mbedcrypto_internal_ecp_grp_capable( const mbedcrypto_ecp_group *grp );
+
+/**
+ * \brief           Initialise the Elliptic Curve Point module extension.
+ *
+ *                  If mbedcrypto_internal_ecp_grp_capable returns true for a
+ *                  group, this function has to be able to initialise the
+ *                  module for it.
+ *
+ *                  This module can be a driver to a crypto hardware
+ *                  accelerator, for which this could be an initialise function.
+ *
+ * \param grp       The pointer to the group the module needs to be
+ *                  initialised for.
+ *
+ * \return          0 if successful.
+ */
+int mbedcrypto_internal_ecp_init( const mbedcrypto_ecp_group *grp );
+
+/**
+ * \brief           Frees and deallocates the Elliptic Curve Point module
+ *                  extension.
+ *
+ * \param grp       The pointer to the group the module was initialised for.
+ */
+void mbedcrypto_internal_ecp_free( const mbedcrypto_ecp_group *grp );
+
+#if defined(ECP_SHORTWEIERSTRASS)
+
+#if defined(MBEDCRYPTO_ECP_RANDOMIZE_JAC_ALT)
+/**
+ * \brief           Randomize jacobian coordinates:
+ *                  (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l.
+ *
+ * \param grp       Pointer to the group representing the curve.
+ *
+ * \param pt        The point on the curve to be randomised, given with Jacobian
+ *                  coordinates.
+ *
+ * \param f_rng     A function pointer to the random number generator.
+ *
+ * \param p_rng     A pointer to the random number generator state.
+ *
+ * \return          0 if successful.
+ */
+int mbedcrypto_internal_ecp_randomize_jac( const mbedcrypto_ecp_group *grp,
+        mbedcrypto_ecp_point *pt, int (*f_rng)(void *, unsigned char *, size_t),
+        void *p_rng );
+#endif
+
+#if defined(MBEDCRYPTO_ECP_ADD_MIXED_ALT)
+/**
+ * \brief           Addition: R = P + Q, mixed affine-Jacobian coordinates.
+ *
+ *                  The coordinates of Q must be normalized (= affine),
+ *                  but those of P don't need to. R is not normalized.
+ *
+ *                  This function is used only as a subrutine of
+ *                  ecp_mul_comb().
+ *
+ *                  Special cases: (1) P or Q is zero, (2) R is zero,
+ *                      (3) P == Q.
+ *                  None of these cases can happen as intermediate step in
+ *                  ecp_mul_comb():
+ *                      - at each step, P, Q and R are multiples of the base
+ *                      point, the factor being less than its order, so none of
+ *                      them is zero;
+ *                      - Q is an odd multiple of the base point, P an even
+ *                      multiple, due to the choice of precomputed points in the
+ *                      modified comb method.
+ *                  So branches for these cases do not leak secret information.
+ *
+ *                  We accept Q->Z being unset (saving memory in tables) as
+ *                  meaning 1.
+ *
+ *                  Cost in field operations if done by [5] 3.22:
+ *                      1A := 8M + 3S
+ *
+ * \param grp       Pointer to the group representing the curve.
+ *
+ * \param R         Pointer to a point structure to hold the result.
+ *
+ * \param P         Pointer to the first summand, given with Jacobian
+ *                  coordinates
+ *
+ * \param Q         Pointer to the second summand, given with affine
+ *                  coordinates.
+ *
+ * \return          0 if successful.
+ */
+int mbedcrypto_internal_ecp_add_mixed( const mbedcrypto_ecp_group *grp,
+        mbedcrypto_ecp_point *R, const mbedcrypto_ecp_point *P,
+        const mbedcrypto_ecp_point *Q );
+#endif
+
+/**
+ * \brief           Point doubling R = 2 P, Jacobian coordinates.
+ *
+ *                  Cost:   1D := 3M + 4S    (A ==  0)
+ *                          4M + 4S          (A == -3)
+ *                          3M + 6S + 1a     otherwise
+ *                  when the implementation is based on the "dbl-1998-cmo-2"
+ *                  doubling formulas in [8] and standard optimizations are
+ *                  applied when curve parameter A is one of { 0, -3 }.
+ *
+ * \param grp       Pointer to the group representing the curve.
+ *
+ * \param R         Pointer to a point structure to hold the result.
+ *
+ * \param P         Pointer to the point that has to be doubled, given with
+ *                  Jacobian coordinates.
+ *
+ * \return          0 if successful.
+ */
+#if defined(MBEDCRYPTO_ECP_DOUBLE_JAC_ALT)
+int mbedcrypto_internal_ecp_double_jac( const mbedcrypto_ecp_group *grp,
+        mbedcrypto_ecp_point *R, const mbedcrypto_ecp_point *P );
+#endif
+
+/**
+ * \brief           Normalize jacobian coordinates of an array of (pointers to)
+ *                  points.
+ *
+ *                  Using Montgomery's trick to perform only one inversion mod P
+ *                  the cost is:
+ *                      1N(t) := 1I + (6t - 3)M + 1S
+ *                  (See for example Algorithm 10.3.4. in [9])
+ *
+ *                  This function is used only as a subrutine of
+ *                  ecp_mul_comb().
+ *
+ *                  Warning: fails (returning an error) if one of the points is
+ *                  zero!
+ *                  This should never happen, see choice of w in ecp_mul_comb().
+ *
+ * \param grp       Pointer to the group representing the curve.
+ *
+ * \param T         Array of pointers to the points to normalise.
+ *
+ * \param t_len     Number of elements in the array.
+ *
+ * \return          0 if successful,
+ *                      an error if one of the points is zero.
+ */
+#if defined(MBEDCRYPTO_ECP_NORMALIZE_JAC_MANY_ALT)
+int mbedcrypto_internal_ecp_normalize_jac_many( const mbedcrypto_ecp_group *grp,
+        mbedcrypto_ecp_point *T[], size_t t_len );
+#endif
+
+/**
+ * \brief           Normalize jacobian coordinates so that Z == 0 || Z == 1.
+ *
+ *                  Cost in field operations if done by [5] 3.2.1:
+ *                      1N := 1I + 3M + 1S
+ *
+ * \param grp       Pointer to the group representing the curve.
+ *
+ * \param pt        pointer to the point to be normalised. This is an
+ *                  input/output parameter.
+ *
+ * \return          0 if successful.
+ */
+#if defined(MBEDCRYPTO_ECP_NORMALIZE_JAC_ALT)
+int mbedcrypto_internal_ecp_normalize_jac( const mbedcrypto_ecp_group *grp,
+        mbedcrypto_ecp_point *pt );
+#endif
+
+#endif /* ECP_SHORTWEIERSTRASS */
+
+#if defined(ECP_MONTGOMERY)
+
+#if defined(MBEDCRYPTO_ECP_DOUBLE_ADD_MXZ_ALT)
+int mbedcrypto_internal_ecp_double_add_mxz( const mbedcrypto_ecp_group *grp,
+        mbedcrypto_ecp_point *R, mbedcrypto_ecp_point *S, const mbedcrypto_ecp_point *P,
+        const mbedcrypto_ecp_point *Q, const mbedcrypto_mpi *d );
+#endif
+
+/**
+ * \brief           Randomize projective x/z coordinates:
+ *                      (X, Z) -> (l X, l Z) for random l
+ *
+ * \param grp       pointer to the group representing the curve
+ *
+ * \param P         the point on the curve to be randomised given with
+ *                  projective coordinates. This is an input/output parameter.
+ *
+ * \param f_rng     a function pointer to the random number generator
+ *
+ * \param p_rng     a pointer to the random number generator state
+ *
+ * \return          0 if successful
+ */
+#if defined(MBEDCRYPTO_ECP_RANDOMIZE_MXZ_ALT)
+int mbedcrypto_internal_ecp_randomize_mxz( const mbedcrypto_ecp_group *grp,
+        mbedcrypto_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t),
+        void *p_rng );
+#endif
+
+/**
+ * \brief           Normalize Montgomery x/z coordinates: X = X/Z, Z = 1.
+ *
+ * \param grp       pointer to the group representing the curve
+ *
+ * \param P         pointer to the point to be normalised. This is an
+ *                  input/output parameter.
+ *
+ * \return          0 if successful
+ */
+#if defined(MBEDCRYPTO_ECP_NORMALIZE_MXZ_ALT)
+int mbedcrypto_internal_ecp_normalize_mxz( const mbedcrypto_ecp_group *grp,
+        mbedcrypto_ecp_point *P );
+#endif
+
+#endif /* ECP_MONTGOMERY */
+
+#endif /* MBEDCRYPTO_ECP_INTERNAL_ALT */
+
+#endif /* ecp_internal.h */
+
diff --git a/include/mbedcrypto/entropy.h b/include/mbedcrypto/entropy.h
new file mode 100644
index 0000000..9ba727f
--- /dev/null
+++ b/include/mbedcrypto/entropy.h
@@ -0,0 +1,289 @@
+/**
+ * \file entropy.h
+ *
+ * \brief Entropy accumulator implementation
+ */
+/*
+ *  Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_ENTROPY_H
+#define MBEDCRYPTO_ENTROPY_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+
+#if defined(MBEDCRYPTO_SHA512_C) && !defined(MBEDCRYPTO_ENTROPY_FORCE_SHA256)
+#include "sha512.h"
+#define MBEDCRYPTO_ENTROPY_SHA512_ACCUMULATOR
+#else
+#if defined(MBEDCRYPTO_SHA256_C)
+#define MBEDCRYPTO_ENTROPY_SHA256_ACCUMULATOR
+#include "sha256.h"
+#endif
+#endif
+
+#if defined(MBEDCRYPTO_THREADING_C)
+#include "threading.h"
+#endif
+
+#if defined(MBEDCRYPTO_HAVEGE_C)
+#include "havege.h"
+#endif
+
+#define MBEDCRYPTO_ERR_ENTROPY_SOURCE_FAILED                 -0x003C  /**< Critical entropy source failure. */
+#define MBEDCRYPTO_ERR_ENTROPY_MAX_SOURCES                   -0x003E  /**< No more sources can be added. */
+#define MBEDCRYPTO_ERR_ENTROPY_NO_SOURCES_DEFINED            -0x0040  /**< No sources have been added to poll. */
+#define MBEDCRYPTO_ERR_ENTROPY_NO_STRONG_SOURCE              -0x003D  /**< No strong sources have been added to poll. */
+#define MBEDCRYPTO_ERR_ENTROPY_FILE_IO_ERROR                 -0x003F  /**< Read/write error in file. */
+
+/**
+ * \name SECTION: Module settings
+ *
+ * The configuration options you can set for this module are in this section.
+ * Either change them in config.h or define them on the compiler command line.
+ * \{
+ */
+
+#if !defined(MBEDCRYPTO_ENTROPY_MAX_SOURCES)
+#define MBEDCRYPTO_ENTROPY_MAX_SOURCES     20      /**< Maximum number of sources supported */
+#endif
+
+#if !defined(MBEDCRYPTO_ENTROPY_MAX_GATHER)
+#define MBEDCRYPTO_ENTROPY_MAX_GATHER      128     /**< Maximum amount requested from entropy sources */
+#endif
+
+/* \} name SECTION: Module settings */
+
+#if defined(MBEDCRYPTO_ENTROPY_SHA512_ACCUMULATOR)
+#define MBEDCRYPTO_ENTROPY_BLOCK_SIZE      64      /**< Block size of entropy accumulator (SHA-512) */
+#else
+#define MBEDCRYPTO_ENTROPY_BLOCK_SIZE      32      /**< Block size of entropy accumulator (SHA-256) */
+#endif
+
+#define MBEDCRYPTO_ENTROPY_MAX_SEED_SIZE   1024    /**< Maximum size of seed we read from seed file */
+#define MBEDCRYPTO_ENTROPY_SOURCE_MANUAL   MBEDCRYPTO_ENTROPY_MAX_SOURCES
+
+#define MBEDCRYPTO_ENTROPY_SOURCE_STRONG   1       /**< Entropy source is strong   */
+#define MBEDCRYPTO_ENTROPY_SOURCE_WEAK     0       /**< Entropy source is weak     */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief           Entropy poll callback pointer
+ *
+ * \param data      Callback-specific data pointer
+ * \param output    Data to fill
+ * \param len       Maximum size to provide
+ * \param olen      The actual amount of bytes put into the buffer (Can be 0)
+ *
+ * \return          0 if no critical failures occurred,
+ *                  MBEDCRYPTO_ERR_ENTROPY_SOURCE_FAILED otherwise
+ */
+typedef int (*mbedcrypto_entropy_f_source_ptr)(void *data, unsigned char *output, size_t len,
+                            size_t *olen);
+
+/**
+ * \brief           Entropy source state
+ */
+typedef struct
+{
+    mbedcrypto_entropy_f_source_ptr    f_source;   /**< The entropy source callback */
+    void *          p_source;   /**< The callback data pointer */
+    size_t          size;       /**< Amount received in bytes */
+    size_t          threshold;  /**< Minimum bytes required before release */
+    int             strong;     /**< Is the source strong? */
+}
+mbedcrypto_entropy_source_state;
+
+/**
+ * \brief           Entropy context structure
+ */
+typedef struct
+{
+    int accumulator_started;
+#if defined(MBEDCRYPTO_ENTROPY_SHA512_ACCUMULATOR)
+    mbedcrypto_sha512_context  accumulator;
+#else
+    mbedcrypto_sha256_context  accumulator;
+#endif
+    int             source_count;
+    mbedcrypto_entropy_source_state    source[MBEDCRYPTO_ENTROPY_MAX_SOURCES];
+#if defined(MBEDCRYPTO_HAVEGE_C)
+    mbedcrypto_havege_state    havege_data;
+#endif
+#if defined(MBEDCRYPTO_THREADING_C)
+    mbedcrypto_threading_mutex_t mutex;    /*!< mutex                  */
+#endif
+#if defined(MBEDCRYPTO_ENTROPY_NV_SEED)
+    int initial_entropy_run;
+#endif
+}
+mbedcrypto_entropy_context;
+
+/**
+ * \brief           Initialize the context
+ *
+ * \param ctx       Entropy context to initialize
+ */
+void mbedcrypto_entropy_init( mbedcrypto_entropy_context *ctx );
+
+/**
+ * \brief           Free the data in the context
+ *
+ * \param ctx       Entropy context to free
+ */
+void mbedcrypto_entropy_free( mbedcrypto_entropy_context *ctx );
+
+/**
+ * \brief           Adds an entropy source to poll
+ *                  (Thread-safe if MBEDCRYPTO_THREADING_C is enabled)
+ *
+ * \param ctx       Entropy context
+ * \param f_source  Entropy function
+ * \param p_source  Function data
+ * \param threshold Minimum required from source before entropy is released
+ *                  ( with mbedcrypto_entropy_func() ) (in bytes)
+ * \param strong    MBEDCRYPTO_ENTROPY_SOURCE_STRONG or
+ *                  MBEDCRYPTO_ENTROPY_SOURCE_WEAK.
+ *                  At least one strong source needs to be added.
+ *                  Weaker sources (such as the cycle counter) can be used as
+ *                  a complement.
+ *
+ * \return          0 if successful or MBEDCRYPTO_ERR_ENTROPY_MAX_SOURCES
+ */
+int mbedcrypto_entropy_add_source( mbedcrypto_entropy_context *ctx,
+                        mbedcrypto_entropy_f_source_ptr f_source, void *p_source,
+                        size_t threshold, int strong );
+
+/**
+ * \brief           Trigger an extra gather poll for the accumulator
+ *                  (Thread-safe if MBEDCRYPTO_THREADING_C is enabled)
+ *
+ * \param ctx       Entropy context
+ *
+ * \return          0 if successful, or MBEDCRYPTO_ERR_ENTROPY_SOURCE_FAILED
+ */
+int mbedcrypto_entropy_gather( mbedcrypto_entropy_context *ctx );
+
+/**
+ * \brief           Retrieve entropy from the accumulator
+ *                  (Maximum length: MBEDCRYPTO_ENTROPY_BLOCK_SIZE)
+ *                  (Thread-safe if MBEDCRYPTO_THREADING_C is enabled)
+ *
+ * \param data      Entropy context
+ * \param output    Buffer to fill
+ * \param len       Number of bytes desired, must be at most MBEDCRYPTO_ENTROPY_BLOCK_SIZE
+ *
+ * \return          0 if successful, or MBEDCRYPTO_ERR_ENTROPY_SOURCE_FAILED
+ */
+int mbedcrypto_entropy_func( void *data, unsigned char *output, size_t len );
+
+/**
+ * \brief           Add data to the accumulator manually
+ *                  (Thread-safe if MBEDCRYPTO_THREADING_C is enabled)
+ *
+ * \param ctx       Entropy context
+ * \param data      Data to add
+ * \param len       Length of data
+ *
+ * \return          0 if successful
+ */
+int mbedcrypto_entropy_update_manual( mbedcrypto_entropy_context *ctx,
+                           const unsigned char *data, size_t len );
+
+#if defined(MBEDCRYPTO_ENTROPY_NV_SEED)
+/**
+ * \brief           Trigger an update of the seed file in NV by using the
+ *                  current entropy pool.
+ *
+ * \param ctx       Entropy context
+ *
+ * \return          0 if successful
+ */
+int mbedcrypto_entropy_update_nv_seed( mbedcrypto_entropy_context *ctx );
+#endif /* MBEDCRYPTO_ENTROPY_NV_SEED */
+
+#if defined(MBEDCRYPTO_FS_IO)
+/**
+ * \brief               Write a seed file
+ *
+ * \param ctx           Entropy context
+ * \param path          Name of the file
+ *
+ * \return              0 if successful,
+ *                      MBEDCRYPTO_ERR_ENTROPY_FILE_IO_ERROR on file error, or
+ *                      MBEDCRYPTO_ERR_ENTROPY_SOURCE_FAILED
+ */
+int mbedcrypto_entropy_write_seed_file( mbedcrypto_entropy_context *ctx, const char *path );
+
+/**
+ * \brief               Read and update a seed file. Seed is added to this
+ *                      instance. No more than MBEDCRYPTO_ENTROPY_MAX_SEED_SIZE bytes are
+ *                      read from the seed file. The rest is ignored.
+ *
+ * \param ctx           Entropy context
+ * \param path          Name of the file
+ *
+ * \return              0 if successful,
+ *                      MBEDCRYPTO_ERR_ENTROPY_FILE_IO_ERROR on file error,
+ *                      MBEDCRYPTO_ERR_ENTROPY_SOURCE_FAILED
+ */
+int mbedcrypto_entropy_update_seed_file( mbedcrypto_entropy_context *ctx, const char *path );
+#endif /* MBEDCRYPTO_FS_IO */
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+/**
+ * \brief          Checkup routine
+ *
+ *                 This module self-test also calls the entropy self-test,
+ *                 mbedcrypto_entropy_source_self_test();
+ *
+ * \return         0 if successful, or 1 if a test failed
+ */
+int mbedcrypto_entropy_self_test( int verbose );
+
+#if defined(MBEDCRYPTO_ENTROPY_HARDWARE_ALT)
+/**
+ * \brief          Checkup routine
+ *
+ *                 Verifies the integrity of the hardware entropy source
+ *                 provided by the function 'mbedcrypto_hardware_poll()'.
+ *
+ *                 Note this is the only hardware entropy source that is known
+ *                 at link time, and other entropy sources configured
+ *                 dynamically at runtime by the function
+ *                 mbedcrypto_entropy_add_source() will not be tested.
+ *
+ * \return         0 if successful, or 1 if a test failed
+ */
+int mbedcrypto_entropy_source_self_test( int verbose );
+#endif /* MBEDCRYPTO_ENTROPY_HARDWARE_ALT */
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* entropy.h */
diff --git a/include/mbedcrypto/entropy_poll.h b/include/mbedcrypto/entropy_poll.h
new file mode 100644
index 0000000..a044557
--- /dev/null
+++ b/include/mbedcrypto/entropy_poll.h
@@ -0,0 +1,110 @@
+/**
+ * \file entropy_poll.h
+ *
+ * \brief Platform-specific and custom entropy polling functions
+ */
+/*
+ *  Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_ENTROPY_POLL_H
+#define MBEDCRYPTO_ENTROPY_POLL_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Default thresholds for built-in sources, in bytes
+ */
+#define MBEDCRYPTO_ENTROPY_MIN_PLATFORM     32     /**< Minimum for platform source    */
+#define MBEDCRYPTO_ENTROPY_MIN_HAVEGE       32     /**< Minimum for HAVEGE             */
+#define MBEDCRYPTO_ENTROPY_MIN_HARDCLOCK     4     /**< Minimum for mbedcrypto_timing_hardclock()        */
+#if !defined(MBEDCRYPTO_ENTROPY_MIN_HARDWARE)
+#define MBEDCRYPTO_ENTROPY_MIN_HARDWARE     32     /**< Minimum for the hardware source */
+#endif
+
+/**
+ * \brief           Entropy poll callback that provides 0 entropy.
+ */
+#if defined(MBEDCRYPTO_TEST_NULL_ENTROPY)
+    int mbedcrypto_null_entropy_poll( void *data,
+                                unsigned char *output, size_t len, size_t *olen );
+#endif
+
+#if !defined(MBEDCRYPTO_NO_PLATFORM_ENTROPY)
+/**
+ * \brief           Platform-specific entropy poll callback
+ */
+int mbedcrypto_platform_entropy_poll( void *data,
+                           unsigned char *output, size_t len, size_t *olen );
+#endif
+
+#if defined(MBEDCRYPTO_HAVEGE_C)
+/**
+ * \brief           HAVEGE based entropy poll callback
+ *
+ * Requires an HAVEGE state as its data pointer.
+ */
+int mbedcrypto_havege_poll( void *data,
+                 unsigned char *output, size_t len, size_t *olen );
+#endif
+
+#if defined(MBEDCRYPTO_TIMING_C)
+/**
+ * \brief           mbedcrypto_timing_hardclock-based entropy poll callback
+ */
+int mbedcrypto_hardclock_poll( void *data,
+                    unsigned char *output, size_t len, size_t *olen );
+#endif
+
+#if defined(MBEDCRYPTO_ENTROPY_HARDWARE_ALT)
+/**
+ * \brief           Entropy poll callback for a hardware source
+ *
+ * \warning         This is not provided by Mbed Crypto!
+ *                  See \c MBEDCRYPTO_ENTROPY_HARDWARE_ALT in config.h.
+ *
+ * \note            This must accept NULL as its first argument.
+ */
+int mbedcrypto_hardware_poll( void *data,
+                           unsigned char *output, size_t len, size_t *olen );
+#endif
+
+#if defined(MBEDCRYPTO_ENTROPY_NV_SEED)
+/**
+ * \brief           Entropy poll callback for a non-volatile seed file
+ *
+ * \note            This must accept NULL as its first argument.
+ */
+int mbedcrypto_nv_seed_poll( void *data,
+                          unsigned char *output, size_t len, size_t *olen );
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* entropy_poll.h */
diff --git a/include/mbedcrypto/error.h b/include/mbedcrypto/error.h
new file mode 100644
index 0000000..3c7721f
--- /dev/null
+++ b/include/mbedcrypto/error.h
@@ -0,0 +1,117 @@
+/**
+ * \file error.h
+ *
+ * \brief Error to string translation
+ */
+/*
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_ERROR_H
+#define MBEDCRYPTO_ERROR_H
+
+#include <stddef.h>
+
+/**
+ * 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, 0x0003-0x007F)
+ *
+ * Module   Nr  Codes assigned
+ * MPI       7  0x0002-0x0010
+ * GCM       3  0x0012-0x0014   0x0013-0x0013
+ * BLOWFISH  3  0x0016-0x0018   0x0017-0x0017
+ * THREADING 3  0x001A-0x001E
+ * AES       4  0x0020-0x0022   0x0023-0x0025
+ * CAMELLIA  3  0x0024-0x0026   0x0027-0x0027
+ * XTEA      2  0x0028-0x0028   0x0029-0x0029
+ * 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      11  0x0042-0x0052   0x0043-0x0045
+ * ASN1      7  0x0060-0x006C
+ * CMAC      1  0x007A-0x007A
+ * PBKDF2    1  0x007C-0x007C
+ * HMAC_DRBG 4                  0x0003-0x0009
+ * CCM       3                  0x000D-0x0011
+ * ARC4      1                  0x0019-0x0019
+ * MD2       1                  0x002B-0x002B
+ * MD4       1                  0x002D-0x002D
+ * MD5       1                  0x002F-0x002F
+ * RIPEMD160 1                  0x0031-0x0031
+ * SHA1      1                  0x0035-0x0035
+ * SHA256    1                  0x0037-0x0037
+ * SHA512    1                  0x0039-0x0039
+ *
+ * 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   9 (Started from top)
+ * MD        5   5
+ * CIPHER    6   8
+ * SSL       6   17 (Started from top)
+ * SSL       7   31
+ *
+ * Module dependent error code (5 bits 0x.00.-0x.F8.)
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Translate a Mbed Crypto 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 mbedcrypto_strerror( int errnum, char *buffer, size_t buflen );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* error.h */
diff --git a/include/mbedcrypto/gcm.h b/include/mbedcrypto/gcm.h
new file mode 100644
index 0000000..373797a
--- /dev/null
+++ b/include/mbedcrypto/gcm.h
@@ -0,0 +1,266 @@
+/**
+ * \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 (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#ifndef MBEDCRYPTO_GCM_H
+#define MBEDCRYPTO_GCM_H
+
+#include "cipher.h"
+
+#include <stdint.h>
+
+#define MBEDCRYPTO_GCM_ENCRYPT     1
+#define MBEDCRYPTO_GCM_DECRYPT     0
+
+#define MBEDCRYPTO_ERR_GCM_AUTH_FAILED                       -0x0012  /**< Authenticated decryption failed. */
+#define MBEDCRYPTO_ERR_GCM_HW_ACCEL_FAILED                   -0x0013  /**< GCM hardware accelerator failed. */
+#define MBEDCRYPTO_ERR_GCM_BAD_INPUT                         -0x0014  /**< Bad input parameters to function. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDCRYPTO_GCM_ALT)
+
+/**
+ * \brief          The GCM context structure.
+ */
+typedef struct {
+    mbedcrypto_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:
+                                               #MBEDCRYPTO_GCM_ENCRYPT or
+                                               #MBEDCRYPTO_GCM_DECRYPT. */
+}
+mbedcrypto_gcm_context;
+
+#else  /* !MBEDCRYPTO_GCM_ALT */
+#include "gcm_alt.h"
+#endif /* !MBEDCRYPTO_GCM_ALT */
+
+/**
+ * \brief           This function initializes the specified GCM context,
+ *                  to make references valid, and prepares the context
+ *                  for mbedcrypto_gcm_setkey() or mbedcrypto_gcm_free().
+ *
+ *                  The function does not bind the GCM context to a particular
+ *                  cipher, nor set the key. For this purpose, use
+ *                  mbedcrypto_gcm_setkey().
+ *
+ * \param ctx       The GCM context to initialize.
+ */
+void mbedcrypto_gcm_init( mbedcrypto_gcm_context *ctx );
+
+/**
+ * \brief           This function associates a GCM context with a
+ *                  cipher algorithm and a key.
+ *
+ * \param ctx       The GCM context to initialize.
+ * \param cipher    The 128-bit block cipher to use.
+ * \param key       The encryption key.
+ * \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 mbedcrypto_gcm_setkey( mbedcrypto_gcm_context *ctx,
+                        mbedcrypto_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.
+ *
+ * \param ctx       The GCM context to use for encryption or decryption.
+ * \param mode      The operation to perform: #MBEDCRYPTO_GCM_ENCRYPT or
+ *                  #MBEDCRYPTO_GCM_DECRYPT.
+ * \param length    The length of the input data. This must be a multiple of
+ *                  16 except in the last call before mbedcrypto_gcm_finish().
+ * \param iv        The initialization vector.
+ * \param iv_len    The length of the IV.
+ * \param add       The buffer holding the additional data.
+ * \param add_len   The length of the additional data.
+ * \param input     The buffer holding the input data.
+ * \param output    The buffer for holding the output data.
+ * \param tag_len   The length of the tag to generate.
+ * \param tag       The buffer for holding the tag.
+ *
+ * \return         \c 0 on success.
+ */
+int mbedcrypto_gcm_crypt_and_tag( mbedcrypto_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.
+ * \param length    The length of the input data. This must be a multiple
+ *                  of 16 except in the last call before mbedcrypto_gcm_finish().
+ * \param iv        The initialization vector.
+ * \param iv_len    The length of the IV.
+ * \param add       The buffer holding the additional data.
+ * \param add_len   The length of the additional data.
+ * \param tag       The buffer holding the tag.
+ * \param tag_len   The length of the tag.
+ * \param input     The buffer holding the input data.
+ * \param output    The buffer for holding the output data.
+ *
+ * \return         0 if successful and authenticated.
+ * \return         #MBEDCRYPTO_ERR_GCM_AUTH_FAILED if the tag does not match.
+ */
+int mbedcrypto_gcm_auth_decrypt( mbedcrypto_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.
+ * \param mode      The operation to perform: #MBEDCRYPTO_GCM_ENCRYPT or
+ *                  #MBEDCRYPTO_GCM_DECRYPT.
+ * \param iv        The initialization vector.
+ * \param iv_len    The length of the IV.
+ * \param add       The buffer holding the additional data, or NULL
+ *                  if \p add_len is 0.
+ * \param add_len   The length of the additional data. If 0,
+ *                  \p add is NULL.
+ *
+ * \return          \c 0 on success.
+ */
+int mbedcrypto_gcm_starts( mbedcrypto_gcm_context *ctx,
+                int mode,
+                const unsigned char *iv,
+                size_t iv_len,
+                const unsigned char *add,
+                size_t add_len );
+
+/**
+ * \brief           This function feeds an input buffer into an ongoing GCM
+ *                  encryption or decryption operation.
+ *
+ *    `             The function expects input to be a multiple of 16
+ *                  Bytes. Only the last call before calling
+ *                  mbedcrypto_gcm_finish() can be less than 16 Bytes.
+ *
+ * \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.
+ * \param length    The length of the input data. This must be a multiple of
+ *                  16 except in the last call before mbedcrypto_gcm_finish().
+ * \param input     The buffer holding the input data.
+ * \param output    The buffer for holding the output data.
+ *
+ * \return         \c 0 on success.
+ * \return         #MBEDCRYPTO_ERR_GCM_BAD_INPUT on failure.
+ */
+int mbedcrypto_gcm_update( mbedcrypto_gcm_context *ctx,
+                size_t length,
+                const unsigned char *input,
+                unsigned char *output );
+
+/**
+ * \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.
+ * \param tag       The buffer for holding the tag.
+ * \param tag_len   The length of the tag to generate. Must be at least four.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDCRYPTO_ERR_GCM_BAD_INPUT on failure.
+ */
+int mbedcrypto_gcm_finish( mbedcrypto_gcm_context *ctx,
+                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.
+ */
+void mbedcrypto_gcm_free( mbedcrypto_gcm_context *ctx );
+
+/**
+ * \brief          The GCM checkup routine.
+ *
+ * \return         \c 0 on success.
+ * \return         \c 1 on failure.
+ */
+int mbedcrypto_gcm_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* gcm.h */
diff --git a/include/mbedcrypto/hmac_drbg.h b/include/mbedcrypto/hmac_drbg.h
new file mode 100644
index 0000000..4e87fcd
--- /dev/null
+++ b/include/mbedcrypto/hmac_drbg.h
@@ -0,0 +1,300 @@
+/**
+ * \file hmac_drbg.h
+ *
+ * \brief HMAC_DRBG (NIST SP 800-90A)
+ */
+/*
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_HMAC_DRBG_H
+#define MBEDCRYPTO_HMAC_DRBG_H
+
+#include "md.h"
+
+#if defined(MBEDCRYPTO_THREADING_C)
+#include "mbedcrypto/threading.h"
+#endif
+
+/*
+ * Error codes
+ */
+#define MBEDCRYPTO_ERR_HMAC_DRBG_REQUEST_TOO_BIG              -0x0003  /**< Too many random requested in single call. */
+#define MBEDCRYPTO_ERR_HMAC_DRBG_INPUT_TOO_BIG                -0x0005  /**< Input too large (Entropy + additional). */
+#define MBEDCRYPTO_ERR_HMAC_DRBG_FILE_IO_ERROR                -0x0007  /**< Read/write error in file. */
+#define MBEDCRYPTO_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED        -0x0009  /**< The entropy source failed. */
+
+/**
+ * \name SECTION: Module settings
+ *
+ * The configuration options you can set for this module are in this section.
+ * Either change them in config.h or define them on the compiler command line.
+ * \{
+ */
+
+#if !defined(MBEDCRYPTO_HMAC_DRBG_RESEED_INTERVAL)
+#define MBEDCRYPTO_HMAC_DRBG_RESEED_INTERVAL   10000   /**< Interval before reseed is performed by default */
+#endif
+
+#if !defined(MBEDCRYPTO_HMAC_DRBG_MAX_INPUT)
+#define MBEDCRYPTO_HMAC_DRBG_MAX_INPUT         256     /**< Maximum number of additional input bytes */
+#endif
+
+#if !defined(MBEDCRYPTO_HMAC_DRBG_MAX_REQUEST)
+#define MBEDCRYPTO_HMAC_DRBG_MAX_REQUEST       1024    /**< Maximum number of requested bytes per call */
+#endif
+
+#if !defined(MBEDCRYPTO_HMAC_DRBG_MAX_SEED_INPUT)
+#define MBEDCRYPTO_HMAC_DRBG_MAX_SEED_INPUT    384     /**< Maximum size of (re)seed buffer */
+#endif
+
+/* \} name SECTION: Module settings */
+
+#define MBEDCRYPTO_HMAC_DRBG_PR_OFF   0   /**< No prediction resistance       */
+#define MBEDCRYPTO_HMAC_DRBG_PR_ON    1   /**< Prediction resistance enabled  */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * HMAC_DRBG context.
+ */
+typedef struct
+{
+    /* Working state: the key K is not stored explicitely,
+     * but is implied by the HMAC context */
+    mbedcrypto_md_context_t md_ctx;                    /*!< HMAC context (inc. K)  */
+    unsigned char V[MBEDCRYPTO_MD_MAX_SIZE];  /*!< V in the spec          */
+    int reseed_counter;                     /*!< reseed counter         */
+
+    /* Administrative state */
+    size_t entropy_len;         /*!< entropy bytes grabbed on each (re)seed */
+    int prediction_resistance;  /*!< enable prediction resistance (Automatic
+                                     reseed before every random generation) */
+    int reseed_interval;        /*!< reseed interval   */
+
+    /* Callbacks */
+    int (*f_entropy)(void *, unsigned char *, size_t); /*!< entropy function */
+    void *p_entropy;            /*!< context for the entropy function        */
+
+#if defined(MBEDCRYPTO_THREADING_C)
+    mbedcrypto_threading_mutex_t mutex;
+#endif
+} mbedcrypto_hmac_drbg_context;
+
+/**
+ * \brief               HMAC_DRBG context initialization
+ *                      Makes the context ready for mbedcrypto_hmac_drbg_seed(),
+ *                      mbedcrypto_hmac_drbg_seed_buf() or
+ *                      mbedcrypto_hmac_drbg_free().
+ *
+ * \param ctx           HMAC_DRBG context to be initialized
+ */
+void mbedcrypto_hmac_drbg_init( mbedcrypto_hmac_drbg_context *ctx );
+
+/**
+ * \brief               HMAC_DRBG initial seeding
+ *                      Seed and setup entropy source for future reseeds.
+ *
+ * \param ctx           HMAC_DRBG context to be seeded
+ * \param md_info       MD algorithm to use for HMAC_DRBG
+ * \param f_entropy     Entropy callback (p_entropy, buffer to fill, buffer
+ *                      length)
+ * \param p_entropy     Entropy context
+ * \param custom        Personalization data (Device specific identifiers)
+ *                      (Can be NULL)
+ * \param len           Length of personalization data
+ *
+ * \note                The "security strength" as defined by NIST is set to:
+ *                      128 bits if md_alg is SHA-1,
+ *                      192 bits if md_alg is SHA-224,
+ *                      256 bits if md_alg is SHA-256 or higher.
+ *                      Note that SHA-256 is just as efficient as SHA-224.
+ *
+ * \return              0 if successful, or
+ *                      MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA, or
+ *                      MBEDCRYPTO_ERR_MD_ALLOC_FAILED, or
+ *                      MBEDCRYPTO_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED.
+ */
+int mbedcrypto_hmac_drbg_seed( mbedcrypto_hmac_drbg_context *ctx,
+                    const mbedcrypto_md_info_t * md_info,
+                    int (*f_entropy)(void *, unsigned char *, size_t),
+                    void *p_entropy,
+                    const unsigned char *custom,
+                    size_t len );
+
+/**
+ * \brief               Initilisation of simpified HMAC_DRBG (never reseeds).
+ *                      (For use with deterministic ECDSA.)
+ *
+ * \param ctx           HMAC_DRBG context to be initialised
+ * \param md_info       MD algorithm to use for HMAC_DRBG
+ * \param data          Concatenation of entropy string and additional data
+ * \param data_len      Length of data in bytes
+ *
+ * \return              0 if successful, or
+ *                      MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA, or
+ *                      MBEDCRYPTO_ERR_MD_ALLOC_FAILED.
+ */
+int mbedcrypto_hmac_drbg_seed_buf( mbedcrypto_hmac_drbg_context *ctx,
+                        const mbedcrypto_md_info_t * md_info,
+                        const unsigned char *data, size_t data_len );
+
+/**
+ * \brief               Enable / disable prediction resistance (Default: Off)
+ *
+ * Note: If enabled, entropy is used for ctx->entropy_len before each call!
+ *       Only use this if you have ample supply of good entropy!
+ *
+ * \param ctx           HMAC_DRBG context
+ * \param resistance    MBEDCRYPTO_HMAC_DRBG_PR_ON or MBEDCRYPTO_HMAC_DRBG_PR_OFF
+ */
+void mbedcrypto_hmac_drbg_set_prediction_resistance( mbedcrypto_hmac_drbg_context *ctx,
+                                          int resistance );
+
+/**
+ * \brief               Set the amount of entropy grabbed on each reseed
+ *                      (Default: given by the security strength, which
+ *                      depends on the hash used, see \c mbedcrypto_hmac_drbg_init() )
+ *
+ * \param ctx           HMAC_DRBG context
+ * \param len           Amount of entropy to grab, in bytes
+ */
+void mbedcrypto_hmac_drbg_set_entropy_len( mbedcrypto_hmac_drbg_context *ctx,
+                                size_t len );
+
+/**
+ * \brief               Set the reseed interval
+ *                      (Default: MBEDCRYPTO_HMAC_DRBG_RESEED_INTERVAL)
+ *
+ * \param ctx           HMAC_DRBG context
+ * \param interval      Reseed interval
+ */
+void mbedcrypto_hmac_drbg_set_reseed_interval( mbedcrypto_hmac_drbg_context *ctx,
+                                    int interval );
+
+/**
+ * \brief               HMAC_DRBG update state
+ *
+ * \param ctx           HMAC_DRBG context
+ * \param additional    Additional data to update state with, or NULL
+ * \param add_len       Length of additional data, or 0
+ *
+ * \note                Additional data is optional, pass NULL and 0 as second
+ *                      third argument if no additional data is being used.
+ */
+void mbedcrypto_hmac_drbg_update( mbedcrypto_hmac_drbg_context *ctx,
+                       const unsigned char *additional, size_t add_len );
+
+/**
+ * \brief               HMAC_DRBG reseeding (extracts data from entropy source)
+ *
+ * \param ctx           HMAC_DRBG context
+ * \param additional    Additional data to add to state (Can be NULL)
+ * \param len           Length of additional data
+ *
+ * \return              0 if successful, or
+ *                      MBEDCRYPTO_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
+ */
+int mbedcrypto_hmac_drbg_reseed( mbedcrypto_hmac_drbg_context *ctx,
+                      const unsigned char *additional, size_t len );
+
+/**
+ * \brief               HMAC_DRBG generate random with additional update input
+ *
+ * Note: Automatically reseeds if reseed_counter is reached or PR is enabled.
+ *
+ * \param p_rng         HMAC_DRBG context
+ * \param output        Buffer to fill
+ * \param output_len    Length of the buffer
+ * \param additional    Additional data to update with (can be NULL)
+ * \param add_len       Length of additional data (can be 0)
+ *
+ * \return              0 if successful, or
+ *                      MBEDCRYPTO_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or
+ *                      MBEDCRYPTO_ERR_HMAC_DRBG_REQUEST_TOO_BIG, or
+ *                      MBEDCRYPTO_ERR_HMAC_DRBG_INPUT_TOO_BIG.
+ */
+int mbedcrypto_hmac_drbg_random_with_add( void *p_rng,
+                               unsigned char *output, size_t output_len,
+                               const unsigned char *additional,
+                               size_t add_len );
+
+/**
+ * \brief               HMAC_DRBG generate random
+ *
+ * Note: Automatically reseeds if reseed_counter is reached or PR is enabled.
+ *
+ * \param p_rng         HMAC_DRBG context
+ * \param output        Buffer to fill
+ * \param out_len       Length of the buffer
+ *
+ * \return              0 if successful, or
+ *                      MBEDCRYPTO_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or
+ *                      MBEDCRYPTO_ERR_HMAC_DRBG_REQUEST_TOO_BIG
+ */
+int mbedcrypto_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len );
+
+/**
+ * \brief               Free an HMAC_DRBG context
+ *
+ * \param ctx           HMAC_DRBG context to free.
+ */
+void mbedcrypto_hmac_drbg_free( mbedcrypto_hmac_drbg_context *ctx );
+
+#if defined(MBEDCRYPTO_FS_IO)
+/**
+ * \brief               Write a seed file
+ *
+ * \param ctx           HMAC_DRBG context
+ * \param path          Name of the file
+ *
+ * \return              0 if successful, 1 on file error, or
+ *                      MBEDCRYPTO_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
+ */
+int mbedcrypto_hmac_drbg_write_seed_file( mbedcrypto_hmac_drbg_context *ctx, const char *path );
+
+/**
+ * \brief               Read and update a seed file. Seed is added to this
+ *                      instance
+ *
+ * \param ctx           HMAC_DRBG context
+ * \param path          Name of the file
+ *
+ * \return              0 if successful, 1 on file error,
+ *                      MBEDCRYPTO_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED or
+ *                      MBEDCRYPTO_ERR_HMAC_DRBG_INPUT_TOO_BIG
+ */
+int mbedcrypto_hmac_drbg_update_seed_file( mbedcrypto_hmac_drbg_context *ctx, const char *path );
+#endif /* MBEDCRYPTO_FS_IO */
+
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+/**
+ * \brief               Checkup routine
+ *
+ * \return              0 if successful, or 1 if the test failed
+ */
+int mbedcrypto_hmac_drbg_self_test( int verbose );
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* hmac_drbg.h */
diff --git a/include/mbedcrypto/md.h b/include/mbedcrypto/md.h
new file mode 100644
index 0000000..4098662
--- /dev/null
+++ b/include/mbedcrypto/md.h
@@ -0,0 +1,465 @@
+ /**
+ * \file md.h
+ *
+ * \brief This file contains the generic message-digest wrapper.
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ */
+/*
+ *  Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#ifndef MBEDCRYPTO_MD_H
+#define MBEDCRYPTO_MD_H
+
+#include <stddef.h>
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#define MBEDCRYPTO_ERR_MD_FEATURE_UNAVAILABLE                -0x5080  /**< The selected feature is not available. */
+#define MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA                     -0x5100  /**< Bad input parameters to function. */
+#define MBEDCRYPTO_ERR_MD_ALLOC_FAILED                       -0x5180  /**< Failed to allocate memory. */
+#define MBEDCRYPTO_ERR_MD_FILE_IO_ERROR                      -0x5200  /**< Opening or reading of file failed. */
+#define MBEDCRYPTO_ERR_MD_HW_ACCEL_FAILED                    -0x5280  /**< MD hardware accelerator failed. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief     Supported message digests.
+ *
+ * \warning   MD2, MD4, MD5 and SHA-1 are considered weak message digests and
+ *            their use constitutes a security risk. We recommend considering
+ *            stronger message digests instead.
+ *
+ */
+typedef enum {
+    MBEDCRYPTO_MD_NONE=0,    /**< None. */
+    MBEDCRYPTO_MD_MD2,       /**< The MD2 message digest. */
+    MBEDCRYPTO_MD_MD4,       /**< The MD4 message digest. */
+    MBEDCRYPTO_MD_MD5,       /**< The MD5 message digest. */
+    MBEDCRYPTO_MD_SHA1,      /**< The SHA-1 message digest. */
+    MBEDCRYPTO_MD_SHA224,    /**< The SHA-224 message digest. */
+    MBEDCRYPTO_MD_SHA256,    /**< The SHA-256 message digest. */
+    MBEDCRYPTO_MD_SHA384,    /**< The SHA-384 message digest. */
+    MBEDCRYPTO_MD_SHA512,    /**< The SHA-512 message digest. */
+    MBEDCRYPTO_MD_RIPEMD160, /**< The RIPEMD-160 message digest. */
+} mbedcrypto_md_type_t;
+
+#if defined(MBEDCRYPTO_SHA512_C)
+#define MBEDCRYPTO_MD_MAX_SIZE         64  /* longest known is SHA512 */
+#else
+#define MBEDCRYPTO_MD_MAX_SIZE         32  /* longest known is SHA256 or less */
+#endif
+
+/**
+ * Opaque struct defined in md_internal.h.
+ */
+typedef struct mbedcrypto_md_info_t mbedcrypto_md_info_t;
+
+/**
+ * The generic message-digest context.
+ */
+typedef struct {
+    /** Information about the associated message digest. */
+    const mbedcrypto_md_info_t *md_info;
+
+    /** The digest-specific context. */
+    void *md_ctx;
+
+    /** The HMAC part of the context. */
+    void *hmac_ctx;
+} mbedcrypto_md_context_t;
+
+/**
+ * \brief           This function returns the list of digests supported by the
+ *                  generic digest module.
+ *
+ * \return          A statically allocated array of digests. Each element
+ *                  in the returned list is an integer belonging to the
+ *                  message-digest enumeration #mbedcrypto_md_type_t.
+ *                  The last entry is 0.
+ */
+const int *mbedcrypto_md_list( void );
+
+/**
+ * \brief           This function returns the message-digest information
+ *                  associated with the given digest name.
+ *
+ * \param md_name   The name of the digest to search for.
+ *
+ * \return          The message-digest information associated with \p md_name.
+ * \return          NULL if the associated message-digest information is not found.
+ */
+const mbedcrypto_md_info_t *mbedcrypto_md_info_from_string( const char *md_name );
+
+/**
+ * \brief           This function returns the message-digest information
+ *                  associated with the given digest type.
+ *
+ * \param md_type   The type of digest to search for.
+ *
+ * \return          The message-digest information associated with \p md_type.
+ * \return          NULL if the associated message-digest information is not found.
+ */
+const mbedcrypto_md_info_t *mbedcrypto_md_info_from_type( mbedcrypto_md_type_t md_type );
+
+/**
+ * \brief           This function initializes a message-digest context without
+ *                  binding it to a particular message-digest algorithm.
+ *
+ *                  This function should always be called first. It prepares the
+ *                  context for mbedcrypto_md_setup() for binding it to a
+ *                  message-digest algorithm.
+ */
+void mbedcrypto_md_init( mbedcrypto_md_context_t *ctx );
+
+/**
+ * \brief           This function clears the internal structure of \p ctx and
+ *                  frees any embedded internal structure, but does not free
+ *                  \p ctx itself.
+ *
+ *                  If you have called mbedcrypto_md_setup() on \p ctx, you must
+ *                  call mbedcrypto_md_free() when you are no longer using the
+ *                  context.
+ *                  Calling this function if you have previously
+ *                  called mbedcrypto_md_init() and nothing else is optional.
+ *                  You must not call this function if you have not called
+ *                  mbedcrypto_md_init().
+ */
+void mbedcrypto_md_free( mbedcrypto_md_context_t *ctx );
+
+#if ! defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING)
+#define MBEDCRYPTO_DEPRECATED    __attribute__((deprecated))
+#else
+#define MBEDCRYPTO_DEPRECATED
+#endif
+/**
+ * \brief           This function selects the message digest algorithm to use,
+ *                  and allocates internal structures.
+ *
+ *                  It should be called after mbedcrypto_md_init() or mbedcrypto_md_free().
+ *                  Makes it necessary to call mbedcrypto_md_free() later.
+ *
+ * \deprecated      Superseded by mbedcrypto_md_setup() in 2.0.0
+ *
+ * \param ctx       The context to set up.
+ * \param md_info   The information structure of the message-digest algorithm
+ *                  to use.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA on parameter-verification
+ *                  failure.
+ * \return          #MBEDCRYPTO_ERR_MD_ALLOC_FAILED on memory-allocation failure.
+ */
+int mbedcrypto_md_init_ctx( mbedcrypto_md_context_t *ctx, const mbedcrypto_md_info_t *md_info ) MBEDCRYPTO_DEPRECATED;
+#undef MBEDCRYPTO_DEPRECATED
+#endif /* MBEDCRYPTO_DEPRECATED_REMOVED */
+
+/**
+ * \brief           This function selects the message digest algorithm to use,
+ *                  and allocates internal structures.
+ *
+ *                  It should be called after mbedcrypto_md_init() or
+ *                  mbedcrypto_md_free(). Makes it necessary to call
+ *                  mbedcrypto_md_free() later.
+ *
+ * \param ctx       The context to set up.
+ * \param md_info   The information structure of the message-digest algorithm
+ *                  to use.
+ * \param hmac      Defines if HMAC is used. 0: HMAC is not used (saves some memory),
+ *                  or non-zero: HMAC is used with this context.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA on parameter-verification
+ *                  failure.
+ * \return          #MBEDCRYPTO_ERR_MD_ALLOC_FAILED on memory-allocation failure.
+ */
+int mbedcrypto_md_setup( mbedcrypto_md_context_t *ctx, const mbedcrypto_md_info_t *md_info, int hmac );
+
+/**
+ * \brief           This function clones the state of an message-digest
+ *                  context.
+ *
+ * \note            You must call mbedcrypto_md_setup() on \c dst before calling
+ *                  this function.
+ *
+ * \note            The two contexts must have the same type,
+ *                  for example, both are SHA-256.
+ *
+ * \warning         This function clones the message-digest state, not the
+ *                  HMAC state.
+ *
+ * \param dst       The destination context.
+ * \param src       The context to be cloned.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA on parameter-verification failure.
+ */
+int mbedcrypto_md_clone( mbedcrypto_md_context_t *dst,
+                      const mbedcrypto_md_context_t *src );
+
+/**
+ * \brief           This function extracts the message-digest size from the
+ *                  message-digest information structure.
+ *
+ * \param md_info   The information structure of the message-digest algorithm
+ *                  to use.
+ *
+ * \return          The size of the message-digest output in Bytes.
+ */
+unsigned char mbedcrypto_md_get_size( const mbedcrypto_md_info_t *md_info );
+
+/**
+ * \brief           This function extracts the message-digest type from the
+ *                  message-digest information structure.
+ *
+ * \param md_info   The information structure of the message-digest algorithm
+ *                  to use.
+ *
+ * \return          The type of the message digest.
+ */
+mbedcrypto_md_type_t mbedcrypto_md_get_type( const mbedcrypto_md_info_t *md_info );
+
+/**
+ * \brief           This function extracts the message-digest name from the
+ *                  message-digest information structure.
+ *
+ * \param md_info   The information structure of the message-digest algorithm
+ *                  to use.
+ *
+ * \return          The name of the message digest.
+ */
+const char *mbedcrypto_md_get_name( const mbedcrypto_md_info_t *md_info );
+
+/**
+ * \brief           This function starts a message-digest computation.
+ *
+ *                  You must call this function after setting up the context
+ *                  with mbedcrypto_md_setup(), and before passing data with
+ *                  mbedcrypto_md_update().
+ *
+ * \param ctx       The generic message-digest context.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA on parameter-verification
+ *                  failure.
+ */
+int mbedcrypto_md_starts( mbedcrypto_md_context_t *ctx );
+
+/**
+ * \brief           This function feeds an input buffer into an ongoing
+ *                  message-digest computation.
+ *
+ *                  You must call mbedcrypto_md_starts() before calling this
+ *                  function. You may call this function multiple times.
+ *                  Afterwards, call mbedcrypto_md_finish().
+ *
+ * \param ctx       The generic message-digest context.
+ * \param input     The buffer holding the input data.
+ * \param ilen      The length of the input data.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA on parameter-verification
+ *                  failure.
+ */
+int mbedcrypto_md_update( mbedcrypto_md_context_t *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief           This function finishes the digest operation,
+ *                  and writes the result to the output buffer.
+ *
+ *                  Call this function after a call to mbedcrypto_md_starts(),
+ *                  followed by any number of calls to mbedcrypto_md_update().
+ *                  Afterwards, you may either clear the context with
+ *                  mbedcrypto_md_free(), or call mbedcrypto_md_starts() to reuse
+ *                  the context for another digest operation with the same
+ *                  algorithm.
+ *
+ * \param ctx       The generic message-digest context.
+ * \param output    The buffer for the generic message-digest checksum result.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA on parameter-verification
+ *                  failure.
+ */
+int mbedcrypto_md_finish( mbedcrypto_md_context_t *ctx, unsigned char *output );
+
+/**
+ * \brief          This function calculates the message-digest of a buffer,
+ *                 with respect to a configurable message-digest algorithm
+ *                 in a single call.
+ *
+ *                 The result is calculated as
+ *                 Output = message_digest(input buffer).
+ *
+ * \param md_info  The information structure of the message-digest algorithm
+ *                 to use.
+ * \param input    The buffer holding the data.
+ * \param ilen     The length of the input data.
+ * \param output   The generic message-digest checksum result.
+ *
+ * \return         \c 0 on success.
+ * \return         #MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA on parameter-verification
+ *                 failure.
+ */
+int mbedcrypto_md( const mbedcrypto_md_info_t *md_info, const unsigned char *input, size_t ilen,
+        unsigned char *output );
+
+#if defined(MBEDCRYPTO_FS_IO)
+/**
+ * \brief          This function calculates the message-digest checksum
+ *                 result of the contents of the provided file.
+ *
+ *                 The result is calculated as
+ *                 Output = message_digest(file contents).
+ *
+ * \param md_info  The information structure of the message-digest algorithm
+ *                 to use.
+ * \param path     The input file name.
+ * \param output   The generic message-digest checksum result.
+ *
+ * \return         \c 0 on success.
+ * \return         #MBEDCRYPTO_ERR_MD_FILE_IO_ERROR on an I/O error accessing
+ *                 the file pointed by \p path.
+ * \return         #MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA if \p md_info was NULL.
+ */
+int mbedcrypto_md_file( const mbedcrypto_md_info_t *md_info, const char *path,
+                     unsigned char *output );
+#endif /* MBEDCRYPTO_FS_IO */
+
+/**
+ * \brief           This function sets the HMAC key and prepares to
+ *                  authenticate a new message.
+ *
+ *                  Call this function after mbedcrypto_md_setup(), to use
+ *                  the MD context for an HMAC calculation, then call
+ *                  mbedcrypto_md_hmac_update() to provide the input data, and
+ *                  mbedcrypto_md_hmac_finish() to get the HMAC value.
+ *
+ * \param ctx       The message digest context containing an embedded HMAC
+ *                  context.
+ * \param key       The HMAC secret key.
+ * \param keylen    The length of the HMAC key in Bytes.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA on parameter-verification
+ *                  failure.
+ */
+int mbedcrypto_md_hmac_starts( mbedcrypto_md_context_t *ctx, const unsigned char *key,
+                    size_t keylen );
+
+/**
+ * \brief           This function feeds an input buffer into an ongoing HMAC
+ *                  computation.
+ *
+ *                  Call mbedcrypto_md_hmac_starts() or mbedcrypto_md_hmac_reset()
+ *                  before calling this function.
+ *                  You may call this function multiple times to pass the
+ *                  input piecewise.
+ *                  Afterwards, call mbedcrypto_md_hmac_finish().
+ *
+ * \param ctx       The message digest context containing an embedded HMAC
+ *                  context.
+ * \param input     The buffer holding the input data.
+ * \param ilen      The length of the input data.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA on parameter-verification
+ *                  failure.
+ */
+int mbedcrypto_md_hmac_update( mbedcrypto_md_context_t *ctx, const unsigned char *input,
+                    size_t ilen );
+
+/**
+ * \brief           This function finishes the HMAC operation, and writes
+ *                  the result to the output buffer.
+ *
+ *                  Call this function after mbedcrypto_md_hmac_starts() and
+ *                  mbedcrypto_md_hmac_update() to get the HMAC value. Afterwards
+ *                  you may either call mbedcrypto_md_free() to clear the context,
+ *                  or call mbedcrypto_md_hmac_reset() to reuse the context with
+ *                  the same HMAC key.
+ *
+ * \param ctx       The message digest context containing an embedded HMAC
+ *                  context.
+ * \param output    The generic HMAC checksum result.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA on parameter-verification
+ *                  failure.
+ */
+int mbedcrypto_md_hmac_finish( mbedcrypto_md_context_t *ctx, unsigned char *output);
+
+/**
+ * \brief           This function prepares to authenticate a new message with
+ *                  the same key as the previous HMAC operation.
+ *
+ *                  You may call this function after mbedcrypto_md_hmac_finish().
+ *                  Afterwards call mbedcrypto_md_hmac_update() to pass the new
+ *                  input.
+ *
+ * \param ctx       The message digest context containing an embedded HMAC
+ *                  context.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA on parameter-verification
+ *                  failure.
+ */
+int mbedcrypto_md_hmac_reset( mbedcrypto_md_context_t *ctx );
+
+/**
+ * \brief          This function calculates the full generic HMAC
+ *                 on the input buffer with the provided key.
+ *
+ *                 The function allocates the context, performs the
+ *                 calculation, and frees the context.
+ *
+ *                 The HMAC result is calculated as
+ *                 output = generic HMAC(hmac key, input buffer).
+ *
+ * \param md_info  The information structure of the message-digest algorithm
+ *                 to use.
+ * \param key      The HMAC secret key.
+ * \param keylen   The length of the HMAC secret key in Bytes.
+ * \param input    The buffer holding the input data.
+ * \param ilen     The length of the input data.
+ * \param output   The generic HMAC result.
+ *
+ * \return         \c 0 on success.
+ * \return         #MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA on parameter-verification
+ *                 failure.
+ */
+int mbedcrypto_md_hmac( const mbedcrypto_md_info_t *md_info, const unsigned char *key, size_t keylen,
+                const unsigned char *input, size_t ilen,
+                unsigned char *output );
+
+/* Internal use */
+int mbedcrypto_md_process( mbedcrypto_md_context_t *ctx, const unsigned char *data );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDCRYPTO_MD_H */
diff --git a/include/mbedcrypto/md2.h b/include/mbedcrypto/md2.h
new file mode 100644
index 0000000..dc56387
--- /dev/null
+++ b/include/mbedcrypto/md2.h
@@ -0,0 +1,301 @@
+/**
+ * \file md2.h
+ *
+ * \brief MD2 message digest algorithm (hash function)
+ *
+ * \warning MD2 is considered a weak message digest and its use constitutes a
+ *          security risk. We recommend considering stronger message digests
+ *          instead.
+ */
+/*
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ *
+ */
+#ifndef MBEDCRYPTO_MD2_H
+#define MBEDCRYPTO_MD2_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+
+#define MBEDCRYPTO_ERR_MD2_HW_ACCEL_FAILED                   -0x002B  /**< MD2 hardware accelerator failed */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDCRYPTO_MD2_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief          MD2 context structure
+ *
+ * \warning        MD2 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+typedef struct
+{
+    unsigned char cksum[16];    /*!< checksum of the data block */
+    unsigned char state[48];    /*!< intermediate digest state  */
+    unsigned char buffer[16];   /*!< data block being processed */
+    size_t left;                /*!< amount of data in buffer   */
+}
+mbedcrypto_md2_context;
+
+#else  /* MBEDCRYPTO_MD2_ALT */
+#include "md2_alt.h"
+#endif /* MBEDCRYPTO_MD2_ALT */
+
+/**
+ * \brief          Initialize MD2 context
+ *
+ * \param ctx      MD2 context to be initialized
+ *
+ * \warning        MD2 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+void mbedcrypto_md2_init( mbedcrypto_md2_context *ctx );
+
+/**
+ * \brief          Clear MD2 context
+ *
+ * \param ctx      MD2 context to be cleared
+ *
+ * \warning        MD2 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+void mbedcrypto_md2_free( mbedcrypto_md2_context *ctx );
+
+/**
+ * \brief          Clone (the state of) an MD2 context
+ *
+ * \param dst      The destination context
+ * \param src      The context to be cloned
+ *
+ * \warning        MD2 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+void mbedcrypto_md2_clone( mbedcrypto_md2_context *dst,
+                        const mbedcrypto_md2_context *src );
+
+/**
+ * \brief          MD2 context setup
+ *
+ * \param ctx      context to be initialized
+ *
+ * \return         0 if successful
+ *
+ * \warning        MD2 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+int mbedcrypto_md2_starts_ret( mbedcrypto_md2_context *ctx );
+
+/**
+ * \brief          MD2 process buffer
+ *
+ * \param ctx      MD2 context
+ * \param input    buffer holding the data
+ * \param ilen     length of the input data
+ *
+ * \return         0 if successful
+ *
+ * \warning        MD2 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+int mbedcrypto_md2_update_ret( mbedcrypto_md2_context *ctx,
+                            const unsigned char *input,
+                            size_t ilen );
+
+/**
+ * \brief          MD2 final digest
+ *
+ * \param ctx      MD2 context
+ * \param output   MD2 checksum result
+ *
+ * \return         0 if successful
+ *
+ * \warning        MD2 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+int mbedcrypto_md2_finish_ret( mbedcrypto_md2_context *ctx,
+                            unsigned char output[16] );
+
+/**
+ * \brief          MD2 process data block (internal use only)
+ *
+ * \param ctx      MD2 context
+ *
+ * \return         0 if successful
+ *
+ * \warning        MD2 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+int mbedcrypto_internal_md2_process( mbedcrypto_md2_context *ctx );
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING)
+#define MBEDCRYPTO_DEPRECATED      __attribute__((deprecated))
+#else
+#define MBEDCRYPTO_DEPRECATED
+#endif
+/**
+ * \brief          MD2 context setup
+ *
+ * \deprecated     Superseded by mbedcrypto_md2_starts_ret() in 2.7.0
+ *
+ * \param ctx      context to be initialized
+ *
+ * \warning        MD2 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_md2_starts( mbedcrypto_md2_context *ctx );
+
+/**
+ * \brief          MD2 process buffer
+ *
+ * \deprecated     Superseded by mbedcrypto_md2_update_ret() in 2.7.0
+ *
+ * \param ctx      MD2 context
+ * \param input    buffer holding the data
+ * \param ilen     length of the input data
+ *
+ * \warning        MD2 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_md2_update( mbedcrypto_md2_context *ctx,
+                                            const unsigned char *input,
+                                            size_t ilen );
+
+/**
+ * \brief          MD2 final digest
+ *
+ * \deprecated     Superseded by mbedcrypto_md2_finish_ret() in 2.7.0
+ *
+ * \param ctx      MD2 context
+ * \param output   MD2 checksum result
+ *
+ * \warning        MD2 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_md2_finish( mbedcrypto_md2_context *ctx,
+                                            unsigned char output[16] );
+
+/**
+ * \brief          MD2 process data block (internal use only)
+ *
+ * \deprecated     Superseded by mbedcrypto_internal_md2_process() in 2.7.0
+ *
+ * \param ctx      MD2 context
+ *
+ * \warning        MD2 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_md2_process( mbedcrypto_md2_context *ctx );
+
+#undef MBEDCRYPTO_DEPRECATED
+#endif /* !MBEDCRYPTO_DEPRECATED_REMOVED */
+
+/**
+ * \brief          Output = MD2( input buffer )
+ *
+ * \param input    buffer holding the data
+ * \param ilen     length of the input data
+ * \param output   MD2 checksum result
+ *
+ * \warning        MD2 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+int mbedcrypto_md2_ret( const unsigned char *input,
+                     size_t ilen,
+                     unsigned char output[16] );
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING)
+#define MBEDCRYPTO_DEPRECATED      __attribute__((deprecated))
+#else
+#define MBEDCRYPTO_DEPRECATED
+#endif
+/**
+ * \brief          Output = MD2( input buffer )
+ *
+ * \deprecated     Superseded by mbedcrypto_md2_ret() in 2.7.0
+ *
+ * \param input    buffer holding the data
+ * \param ilen     length of the input data
+ * \param output   MD2 checksum result
+ *
+ * \warning        MD2 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_md2( const unsigned char *input,
+                                     size_t ilen,
+                                     unsigned char output[16] );
+
+#undef MBEDCRYPTO_DEPRECATED
+#endif /* !MBEDCRYPTO_DEPRECATED_REMOVED */
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ *
+ * \warning        MD2 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+int mbedcrypto_md2_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* mbedcrypto_md2.h */
diff --git a/include/mbedcrypto/md4.h b/include/mbedcrypto/md4.h
new file mode 100644
index 0000000..5b61db3
--- /dev/null
+++ b/include/mbedcrypto/md4.h
@@ -0,0 +1,306 @@
+/**
+ * \file md4.h
+ *
+ * \brief MD4 message digest algorithm (hash function)
+ *
+ * \warning MD4 is considered a weak message digest and its use constitutes a
+ *          security risk. We recommend considering stronger message digests
+ *          instead.
+ */
+/*
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ *
+ */
+#ifndef MBEDCRYPTO_MD4_H
+#define MBEDCRYPTO_MD4_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+#define MBEDCRYPTO_ERR_MD4_HW_ACCEL_FAILED                   -0x002D  /**< MD4 hardware accelerator failed */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDCRYPTO_MD4_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief          MD4 context structure
+ *
+ * \warning        MD4 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+typedef struct
+{
+    uint32_t total[2];          /*!< number of bytes processed  */
+    uint32_t state[4];          /*!< intermediate digest state  */
+    unsigned char buffer[64];   /*!< data block being processed */
+}
+mbedcrypto_md4_context;
+
+#else  /* MBEDCRYPTO_MD4_ALT */
+#include "md4_alt.h"
+#endif /* MBEDCRYPTO_MD4_ALT */
+
+/**
+ * \brief          Initialize MD4 context
+ *
+ * \param ctx      MD4 context to be initialized
+ *
+ * \warning        MD4 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+void mbedcrypto_md4_init( mbedcrypto_md4_context *ctx );
+
+/**
+ * \brief          Clear MD4 context
+ *
+ * \param ctx      MD4 context to be cleared
+ *
+ * \warning        MD4 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+void mbedcrypto_md4_free( mbedcrypto_md4_context *ctx );
+
+/**
+ * \brief          Clone (the state of) an MD4 context
+ *
+ * \param dst      The destination context
+ * \param src      The context to be cloned
+ *
+ * \warning        MD4 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+void mbedcrypto_md4_clone( mbedcrypto_md4_context *dst,
+                        const mbedcrypto_md4_context *src );
+
+/**
+ * \brief          MD4 context setup
+ *
+ * \param ctx      context to be initialized
+ *
+ * \return         0 if successful
+ *
+ * \warning        MD4 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ */
+int mbedcrypto_md4_starts_ret( mbedcrypto_md4_context *ctx );
+
+/**
+ * \brief          MD4 process buffer
+ *
+ * \param ctx      MD4 context
+ * \param input    buffer holding the data
+ * \param ilen     length of the input data
+ *
+ * \return         0 if successful
+ *
+ * \warning        MD4 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+int mbedcrypto_md4_update_ret( mbedcrypto_md4_context *ctx,
+                            const unsigned char *input,
+                            size_t ilen );
+
+/**
+ * \brief          MD4 final digest
+ *
+ * \param ctx      MD4 context
+ * \param output   MD4 checksum result
+ *
+ * \return         0 if successful
+ *
+ * \warning        MD4 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+int mbedcrypto_md4_finish_ret( mbedcrypto_md4_context *ctx,
+                            unsigned char output[16] );
+
+/**
+ * \brief          MD4 process data block (internal use only)
+ *
+ * \param ctx      MD4 context
+ * \param data     buffer holding one block of data
+ *
+ * \return         0 if successful
+ *
+ * \warning        MD4 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+int mbedcrypto_internal_md4_process( mbedcrypto_md4_context *ctx,
+                                  const unsigned char data[64] );
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING)
+#define MBEDCRYPTO_DEPRECATED      __attribute__((deprecated))
+#else
+#define MBEDCRYPTO_DEPRECATED
+#endif
+/**
+ * \brief          MD4 context setup
+ *
+ * \deprecated     Superseded by mbedcrypto_md4_starts_ret() in 2.7.0
+ *
+ * \param ctx      context to be initialized
+ *
+ * \warning        MD4 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_md4_starts( mbedcrypto_md4_context *ctx );
+
+/**
+ * \brief          MD4 process buffer
+ *
+ * \deprecated     Superseded by mbedcrypto_md4_update_ret() in 2.7.0
+ *
+ * \param ctx      MD4 context
+ * \param input    buffer holding the data
+ * \param ilen     length of the input data
+ *
+ * \warning        MD4 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_md4_update( mbedcrypto_md4_context *ctx,
+                                            const unsigned char *input,
+                                            size_t ilen );
+
+/**
+ * \brief          MD4 final digest
+ *
+ * \deprecated     Superseded by mbedcrypto_md4_finish_ret() in 2.7.0
+ *
+ * \param ctx      MD4 context
+ * \param output   MD4 checksum result
+ *
+ * \warning        MD4 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_md4_finish( mbedcrypto_md4_context *ctx,
+                                            unsigned char output[16] );
+
+/**
+ * \brief          MD4 process data block (internal use only)
+ *
+ * \deprecated     Superseded by mbedcrypto_internal_md4_process() in 2.7.0
+ *
+ * \param ctx      MD4 context
+ * \param data     buffer holding one block of data
+ *
+ * \warning        MD4 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_md4_process( mbedcrypto_md4_context *ctx,
+                                             const unsigned char data[64] );
+
+#undef MBEDCRYPTO_DEPRECATED
+#endif /* !MBEDCRYPTO_DEPRECATED_REMOVED */
+
+/**
+ * \brief          Output = MD4( input buffer )
+ *
+ * \param input    buffer holding the data
+ * \param ilen     length of the input data
+ * \param output   MD4 checksum result
+ *
+ * \return         0 if successful
+ *
+ * \warning        MD4 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+int mbedcrypto_md4_ret( const unsigned char *input,
+                     size_t ilen,
+                     unsigned char output[16] );
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING)
+#define MBEDCRYPTO_DEPRECATED      __attribute__((deprecated))
+#else
+#define MBEDCRYPTO_DEPRECATED
+#endif
+/**
+ * \brief          Output = MD4( input buffer )
+ *
+ * \deprecated     Superseded by mbedcrypto_md4_ret() in 2.7.0
+ *
+ * \param input    buffer holding the data
+ * \param ilen     length of the input data
+ * \param output   MD4 checksum result
+ *
+ * \warning        MD4 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_md4( const unsigned char *input,
+                                     size_t ilen,
+                                     unsigned char output[16] );
+
+#undef MBEDCRYPTO_DEPRECATED
+#endif /* !MBEDCRYPTO_DEPRECATED_REMOVED */
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ *
+ * \warning        MD4 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+int mbedcrypto_md4_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* mbedcrypto_md4.h */
diff --git a/include/mbedcrypto/md5.h b/include/mbedcrypto/md5.h
new file mode 100644
index 0000000..8d24581
--- /dev/null
+++ b/include/mbedcrypto/md5.h
@@ -0,0 +1,306 @@
+/**
+ * \file md5.h
+ *
+ * \brief MD5 message digest algorithm (hash function)
+ *
+ * \warning   MD5 is considered a weak message digest and its use constitutes a
+ *            security risk. We recommend considering stronger message
+ *            digests instead.
+ */
+/*
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_MD5_H
+#define MBEDCRYPTO_MD5_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+#define MBEDCRYPTO_ERR_MD5_HW_ACCEL_FAILED                   -0x002F  /**< MD5 hardware accelerator failed */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDCRYPTO_MD5_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief          MD5 context structure
+ *
+ * \warning        MD5 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+typedef struct
+{
+    uint32_t total[2];          /*!< number of bytes processed  */
+    uint32_t state[4];          /*!< intermediate digest state  */
+    unsigned char buffer[64];   /*!< data block being processed */
+}
+mbedcrypto_md5_context;
+
+#else  /* MBEDCRYPTO_MD5_ALT */
+#include "md5_alt.h"
+#endif /* MBEDCRYPTO_MD5_ALT */
+
+/**
+ * \brief          Initialize MD5 context
+ *
+ * \param ctx      MD5 context to be initialized
+ *
+ * \warning        MD5 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+void mbedcrypto_md5_init( mbedcrypto_md5_context *ctx );
+
+/**
+ * \brief          Clear MD5 context
+ *
+ * \param ctx      MD5 context to be cleared
+ *
+ * \warning        MD5 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+void mbedcrypto_md5_free( mbedcrypto_md5_context *ctx );
+
+/**
+ * \brief          Clone (the state of) an MD5 context
+ *
+ * \param dst      The destination context
+ * \param src      The context to be cloned
+ *
+ * \warning        MD5 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+void mbedcrypto_md5_clone( mbedcrypto_md5_context *dst,
+                        const mbedcrypto_md5_context *src );
+
+/**
+ * \brief          MD5 context setup
+ *
+ * \param ctx      context to be initialized
+ *
+ * \return         0 if successful
+ *
+ * \warning        MD5 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+int mbedcrypto_md5_starts_ret( mbedcrypto_md5_context *ctx );
+
+/**
+ * \brief          MD5 process buffer
+ *
+ * \param ctx      MD5 context
+ * \param input    buffer holding the data
+ * \param ilen     length of the input data
+ *
+ * \return         0 if successful
+ *
+ * \warning        MD5 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+int mbedcrypto_md5_update_ret( mbedcrypto_md5_context *ctx,
+                            const unsigned char *input,
+                            size_t ilen );
+
+/**
+ * \brief          MD5 final digest
+ *
+ * \param ctx      MD5 context
+ * \param output   MD5 checksum result
+ *
+ * \return         0 if successful
+ *
+ * \warning        MD5 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+int mbedcrypto_md5_finish_ret( mbedcrypto_md5_context *ctx,
+                            unsigned char output[16] );
+
+/**
+ * \brief          MD5 process data block (internal use only)
+ *
+ * \param ctx      MD5 context
+ * \param data     buffer holding one block of data
+ *
+ * \return         0 if successful
+ *
+ * \warning        MD5 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+int mbedcrypto_internal_md5_process( mbedcrypto_md5_context *ctx,
+                                  const unsigned char data[64] );
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING)
+#define MBEDCRYPTO_DEPRECATED      __attribute__((deprecated))
+#else
+#define MBEDCRYPTO_DEPRECATED
+#endif
+/**
+ * \brief          MD5 context setup
+ *
+ * \deprecated     Superseded by mbedcrypto_md5_starts_ret() in 2.7.0
+ *
+ * \param ctx      context to be initialized
+ *
+ * \warning        MD5 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_md5_starts( mbedcrypto_md5_context *ctx );
+
+/**
+ * \brief          MD5 process buffer
+ *
+ * \deprecated     Superseded by mbedcrypto_md5_update_ret() in 2.7.0
+ *
+ * \param ctx      MD5 context
+ * \param input    buffer holding the data
+ * \param ilen     length of the input data
+ *
+ * \warning        MD5 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_md5_update( mbedcrypto_md5_context *ctx,
+                                            const unsigned char *input,
+                                            size_t ilen );
+
+/**
+ * \brief          MD5 final digest
+ *
+ * \deprecated     Superseded by mbedcrypto_md5_finish_ret() in 2.7.0
+ *
+ * \param ctx      MD5 context
+ * \param output   MD5 checksum result
+ *
+ * \warning        MD5 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_md5_finish( mbedcrypto_md5_context *ctx,
+                                            unsigned char output[16] );
+
+/**
+ * \brief          MD5 process data block (internal use only)
+ *
+ * \deprecated     Superseded by mbedcrypto_internal_md5_process() in 2.7.0
+ *
+ * \param ctx      MD5 context
+ * \param data     buffer holding one block of data
+ *
+ * \warning        MD5 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_md5_process( mbedcrypto_md5_context *ctx,
+                                             const unsigned char data[64] );
+
+#undef MBEDCRYPTO_DEPRECATED
+#endif /* !MBEDCRYPTO_DEPRECATED_REMOVED */
+
+/**
+ * \brief          Output = MD5( input buffer )
+ *
+ * \param input    buffer holding the data
+ * \param ilen     length of the input data
+ * \param output   MD5 checksum result
+ *
+ * \return         0 if successful
+ *
+ * \warning        MD5 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+int mbedcrypto_md5_ret( const unsigned char *input,
+                     size_t ilen,
+                     unsigned char output[16] );
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING)
+#define MBEDCRYPTO_DEPRECATED      __attribute__((deprecated))
+#else
+#define MBEDCRYPTO_DEPRECATED
+#endif
+/**
+ * \brief          Output = MD5( input buffer )
+ *
+ * \deprecated     Superseded by mbedcrypto_md5_ret() in 2.7.0
+ *
+ * \param input    buffer holding the data
+ * \param ilen     length of the input data
+ * \param output   MD5 checksum result
+ *
+ * \warning        MD5 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_md5( const unsigned char *input,
+                                     size_t ilen,
+                                     unsigned char output[16] );
+
+#undef MBEDCRYPTO_DEPRECATED
+#endif /* !MBEDCRYPTO_DEPRECATED_REMOVED */
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ *
+ * \warning        MD5 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+int mbedcrypto_md5_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* mbedcrypto_md5.h */
diff --git a/include/mbedcrypto/md_internal.h b/include/mbedcrypto/md_internal.h
new file mode 100644
index 0000000..bc151e9
--- /dev/null
+++ b/include/mbedcrypto/md_internal.h
@@ -0,0 +1,115 @@
+/**
+ * \file md_internal.h
+ *
+ * \brief Message digest wrappers.
+ *
+ * \warning This in an internal header. Do not include directly.
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ */
+/*
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_MD_WRAP_H
+#define MBEDCRYPTO_MD_WRAP_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include "md.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Message digest information.
+ * Allows message digest functions to be called in a generic way.
+ */
+struct mbedcrypto_md_info_t
+{
+    /** Digest identifier */
+    mbedcrypto_md_type_t type;
+
+    /** Name of the message digest */
+    const char * name;
+
+    /** Output length of the digest function in bytes */
+    int size;
+
+    /** Block length of the digest function in bytes */
+    int block_size;
+
+    /** Digest initialisation function */
+    int (*starts_func)( void *ctx );
+
+    /** Digest update function */
+    int (*update_func)( void *ctx, const unsigned char *input, size_t ilen );
+
+    /** Digest finalisation function */
+    int (*finish_func)( void *ctx, unsigned char *output );
+
+    /** Generic digest function */
+    int (*digest_func)( const unsigned char *input, size_t ilen,
+                        unsigned char *output );
+
+    /** Allocate a new context */
+    void * (*ctx_alloc_func)( void );
+
+    /** Free the given context */
+    void (*ctx_free_func)( void *ctx );
+
+    /** Clone state from a context */
+    void (*clone_func)( void *dst, const void *src );
+
+    /** Internal use only */
+    int (*process_func)( void *ctx, const unsigned char *input );
+};
+
+#if defined(MBEDCRYPTO_MD2_C)
+extern const mbedcrypto_md_info_t mbedcrypto_md2_info;
+#endif
+#if defined(MBEDCRYPTO_MD4_C)
+extern const mbedcrypto_md_info_t mbedcrypto_md4_info;
+#endif
+#if defined(MBEDCRYPTO_MD5_C)
+extern const mbedcrypto_md_info_t mbedcrypto_md5_info;
+#endif
+#if defined(MBEDCRYPTO_RIPEMD160_C)
+extern const mbedcrypto_md_info_t mbedcrypto_ripemd160_info;
+#endif
+#if defined(MBEDCRYPTO_SHA1_C)
+extern const mbedcrypto_md_info_t mbedcrypto_sha1_info;
+#endif
+#if defined(MBEDCRYPTO_SHA256_C)
+extern const mbedcrypto_md_info_t mbedcrypto_sha224_info;
+extern const mbedcrypto_md_info_t mbedcrypto_sha256_info;
+#endif
+#if defined(MBEDCRYPTO_SHA512_C)
+extern const mbedcrypto_md_info_t mbedcrypto_sha384_info;
+extern const mbedcrypto_md_info_t mbedcrypto_sha512_info;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDCRYPTO_MD_WRAP_H */
diff --git a/include/mbedcrypto/oid.h b/include/mbedcrypto/oid.h
new file mode 100644
index 0000000..d162b10
--- /dev/null
+++ b/include/mbedcrypto/oid.h
@@ -0,0 +1,589 @@
+/**
+ * \file oid.h
+ *
+ * \brief Object Identifier (OID) database
+ */
+/*
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_OID_H
+#define MBEDCRYPTO_OID_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include "asn1.h"
+#include "pk.h"
+
+#include <stddef.h>
+
+#if defined(MBEDCRYPTO_CIPHER_C)
+#include "cipher.h"
+#endif
+
+#if defined(MBEDCRYPTO_MD_C)
+#include "md.h"
+#endif
+
+#if defined(MBEDCRYPTO_X509_USE_C) || defined(MBEDCRYPTO_X509_CREATE_C)
+#include "x509.h"
+#endif
+
+#define MBEDCRYPTO_ERR_OID_NOT_FOUND                         -0x002E  /**< OID is not found. */
+#define MBEDCRYPTO_ERR_OID_BUF_TOO_SMALL                     -0x000B  /**< output buffer is too small */
+
+/*
+ * Top level OID tuples
+ */
+#define MBEDCRYPTO_OID_ISO_MEMBER_BODIES           "\x2a"          /* {iso(1) member-body(2)} */
+#define MBEDCRYPTO_OID_ISO_IDENTIFIED_ORG          "\x2b"          /* {iso(1) identified-organization(3)} */
+#define MBEDCRYPTO_OID_ISO_CCITT_DS                "\x55"          /* {joint-iso-ccitt(2) ds(5)} */
+#define MBEDCRYPTO_OID_ISO_ITU_COUNTRY             "\x60"          /* {joint-iso-itu-t(2) country(16)} */
+
+/*
+ * ISO Member bodies OID parts
+ */
+#define MBEDCRYPTO_OID_COUNTRY_US                  "\x86\x48"      /* {us(840)} */
+#define MBEDCRYPTO_OID_ORG_RSA_DATA_SECURITY       "\x86\xf7\x0d"  /* {rsadsi(113549)} */
+#define MBEDCRYPTO_OID_RSA_COMPANY                 MBEDCRYPTO_OID_ISO_MEMBER_BODIES MBEDCRYPTO_OID_COUNTRY_US \
+                                        MBEDCRYPTO_OID_ORG_RSA_DATA_SECURITY /* {iso(1) member-body(2) us(840) rsadsi(113549)} */
+#define MBEDCRYPTO_OID_ORG_ANSI_X9_62              "\xce\x3d" /* ansi-X9-62(10045) */
+#define MBEDCRYPTO_OID_ANSI_X9_62                  MBEDCRYPTO_OID_ISO_MEMBER_BODIES MBEDCRYPTO_OID_COUNTRY_US \
+                                        MBEDCRYPTO_OID_ORG_ANSI_X9_62
+
+/*
+ * ISO Identified organization OID parts
+ */
+#define MBEDCRYPTO_OID_ORG_DOD                     "\x06"          /* {dod(6)} */
+#define MBEDCRYPTO_OID_ORG_OIW                     "\x0e"
+#define MBEDCRYPTO_OID_OIW_SECSIG                  MBEDCRYPTO_OID_ORG_OIW "\x03"
+#define MBEDCRYPTO_OID_OIW_SECSIG_ALG              MBEDCRYPTO_OID_OIW_SECSIG "\x02"
+#define MBEDCRYPTO_OID_OIW_SECSIG_SHA1             MBEDCRYPTO_OID_OIW_SECSIG_ALG "\x1a"
+#define MBEDCRYPTO_OID_ORG_CERTICOM                "\x81\x04"  /* certicom(132) */
+#define MBEDCRYPTO_OID_CERTICOM                    MBEDCRYPTO_OID_ISO_IDENTIFIED_ORG MBEDCRYPTO_OID_ORG_CERTICOM
+#define MBEDCRYPTO_OID_ORG_TELETRUST               "\x24" /* teletrust(36) */
+#define MBEDCRYPTO_OID_TELETRUST                   MBEDCRYPTO_OID_ISO_IDENTIFIED_ORG MBEDCRYPTO_OID_ORG_TELETRUST
+
+/*
+ * ISO ITU OID parts
+ */
+#define MBEDCRYPTO_OID_ORGANIZATION                "\x01"          /* {organization(1)} */
+#define MBEDCRYPTO_OID_ISO_ITU_US_ORG              MBEDCRYPTO_OID_ISO_ITU_COUNTRY MBEDCRYPTO_OID_COUNTRY_US MBEDCRYPTO_OID_ORGANIZATION /* {joint-iso-itu-t(2) country(16) us(840) organization(1)} */
+
+#define MBEDCRYPTO_OID_ORG_GOV                     "\x65"          /* {gov(101)} */
+#define MBEDCRYPTO_OID_GOV                         MBEDCRYPTO_OID_ISO_ITU_US_ORG MBEDCRYPTO_OID_ORG_GOV /* {joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101)} */
+
+#define MBEDCRYPTO_OID_ORG_NETSCAPE                "\x86\xF8\x42"  /* {netscape(113730)} */
+#define MBEDCRYPTO_OID_NETSCAPE                    MBEDCRYPTO_OID_ISO_ITU_US_ORG MBEDCRYPTO_OID_ORG_NETSCAPE /* Netscape OID {joint-iso-itu-t(2) country(16) us(840) organization(1) netscape(113730)} */
+
+/* ISO arc for standard certificate and CRL extensions */
+#define MBEDCRYPTO_OID_ID_CE                       MBEDCRYPTO_OID_ISO_CCITT_DS "\x1D" /**< id-ce OBJECT IDENTIFIER  ::=  {joint-iso-ccitt(2) ds(5) 29} */
+
+/**
+ * Private Internet Extensions
+ * { iso(1) identified-organization(3) dod(6) internet(1)
+ *                      security(5) mechanisms(5) pkix(7) }
+ */
+#define MBEDCRYPTO_OID_PKIX                        MBEDCRYPTO_OID_ISO_IDENTIFIED_ORG MBEDCRYPTO_OID_ORG_DOD "\x01\x05\x05\x07"
+
+/*
+ * Arc for standard naming attributes
+ */
+#define MBEDCRYPTO_OID_AT                          MBEDCRYPTO_OID_ISO_CCITT_DS "\x04" /**< id-at OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 4} */
+#define MBEDCRYPTO_OID_AT_CN                       MBEDCRYPTO_OID_AT "\x03" /**< id-at-commonName AttributeType:= {id-at 3} */
+#define MBEDCRYPTO_OID_AT_SUR_NAME                 MBEDCRYPTO_OID_AT "\x04" /**< id-at-surName AttributeType:= {id-at 4} */
+#define MBEDCRYPTO_OID_AT_SERIAL_NUMBER            MBEDCRYPTO_OID_AT "\x05" /**< id-at-serialNumber AttributeType:= {id-at 5} */
+#define MBEDCRYPTO_OID_AT_COUNTRY                  MBEDCRYPTO_OID_AT "\x06" /**< id-at-countryName AttributeType:= {id-at 6} */
+#define MBEDCRYPTO_OID_AT_LOCALITY                 MBEDCRYPTO_OID_AT "\x07" /**< id-at-locality AttributeType:= {id-at 7} */
+#define MBEDCRYPTO_OID_AT_STATE                    MBEDCRYPTO_OID_AT "\x08" /**< id-at-state AttributeType:= {id-at 8} */
+#define MBEDCRYPTO_OID_AT_ORGANIZATION             MBEDCRYPTO_OID_AT "\x0A" /**< id-at-organizationName AttributeType:= {id-at 10} */
+#define MBEDCRYPTO_OID_AT_ORG_UNIT                 MBEDCRYPTO_OID_AT "\x0B" /**< id-at-organizationalUnitName AttributeType:= {id-at 11} */
+#define MBEDCRYPTO_OID_AT_TITLE                    MBEDCRYPTO_OID_AT "\x0C" /**< id-at-title AttributeType:= {id-at 12} */
+#define MBEDCRYPTO_OID_AT_POSTAL_ADDRESS           MBEDCRYPTO_OID_AT "\x10" /**< id-at-postalAddress AttributeType:= {id-at 16} */
+#define MBEDCRYPTO_OID_AT_POSTAL_CODE              MBEDCRYPTO_OID_AT "\x11" /**< id-at-postalCode AttributeType:= {id-at 17} */
+#define MBEDCRYPTO_OID_AT_GIVEN_NAME               MBEDCRYPTO_OID_AT "\x2A" /**< id-at-givenName AttributeType:= {id-at 42} */
+#define MBEDCRYPTO_OID_AT_INITIALS                 MBEDCRYPTO_OID_AT "\x2B" /**< id-at-initials AttributeType:= {id-at 43} */
+#define MBEDCRYPTO_OID_AT_GENERATION_QUALIFIER     MBEDCRYPTO_OID_AT "\x2C" /**< id-at-generationQualifier AttributeType:= {id-at 44} */
+#define MBEDCRYPTO_OID_AT_UNIQUE_IDENTIFIER        MBEDCRYPTO_OID_AT "\x2D" /**< id-at-uniqueIdentifier AttributType:= {id-at 45} */
+#define MBEDCRYPTO_OID_AT_DN_QUALIFIER             MBEDCRYPTO_OID_AT "\x2E" /**< id-at-dnQualifier AttributeType:= {id-at 46} */
+#define MBEDCRYPTO_OID_AT_PSEUDONYM                MBEDCRYPTO_OID_AT "\x41" /**< id-at-pseudonym AttributeType:= {id-at 65} */
+
+#define MBEDCRYPTO_OID_DOMAIN_COMPONENT            "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x19" /** id-domainComponent AttributeType:= {itu-t(0) data(9) pss(2342) ucl(19200300) pilot(100) pilotAttributeType(1) domainComponent(25)} */
+
+/*
+ * OIDs for standard certificate extensions
+ */
+#define MBEDCRYPTO_OID_AUTHORITY_KEY_IDENTIFIER    MBEDCRYPTO_OID_ID_CE "\x23" /**< id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::=  { id-ce 35 } */
+#define MBEDCRYPTO_OID_SUBJECT_KEY_IDENTIFIER      MBEDCRYPTO_OID_ID_CE "\x0E" /**< id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::=  { id-ce 14 } */
+#define MBEDCRYPTO_OID_KEY_USAGE                   MBEDCRYPTO_OID_ID_CE "\x0F" /**< id-ce-keyUsage OBJECT IDENTIFIER ::=  { id-ce 15 } */
+#define MBEDCRYPTO_OID_CERTIFICATE_POLICIES        MBEDCRYPTO_OID_ID_CE "\x20" /**< id-ce-certificatePolicies OBJECT IDENTIFIER ::=  { id-ce 32 } */
+#define MBEDCRYPTO_OID_POLICY_MAPPINGS             MBEDCRYPTO_OID_ID_CE "\x21" /**< id-ce-policyMappings OBJECT IDENTIFIER ::=  { id-ce 33 } */
+#define MBEDCRYPTO_OID_SUBJECT_ALT_NAME            MBEDCRYPTO_OID_ID_CE "\x11" /**< id-ce-subjectAltName OBJECT IDENTIFIER ::=  { id-ce 17 } */
+#define MBEDCRYPTO_OID_ISSUER_ALT_NAME             MBEDCRYPTO_OID_ID_CE "\x12" /**< id-ce-issuerAltName OBJECT IDENTIFIER ::=  { id-ce 18 } */
+#define MBEDCRYPTO_OID_SUBJECT_DIRECTORY_ATTRS     MBEDCRYPTO_OID_ID_CE "\x09" /**< id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::=  { id-ce 9 } */
+#define MBEDCRYPTO_OID_BASIC_CONSTRAINTS           MBEDCRYPTO_OID_ID_CE "\x13" /**< id-ce-basicConstraints OBJECT IDENTIFIER ::=  { id-ce 19 } */
+#define MBEDCRYPTO_OID_NAME_CONSTRAINTS            MBEDCRYPTO_OID_ID_CE "\x1E" /**< id-ce-nameConstraints OBJECT IDENTIFIER ::=  { id-ce 30 } */
+#define MBEDCRYPTO_OID_POLICY_CONSTRAINTS          MBEDCRYPTO_OID_ID_CE "\x24" /**< id-ce-policyConstraints OBJECT IDENTIFIER ::=  { id-ce 36 } */
+#define MBEDCRYPTO_OID_EXTENDED_KEY_USAGE          MBEDCRYPTO_OID_ID_CE "\x25" /**< id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } */
+#define MBEDCRYPTO_OID_CRL_DISTRIBUTION_POINTS     MBEDCRYPTO_OID_ID_CE "\x1F" /**< id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::=  { id-ce 31 } */
+#define MBEDCRYPTO_OID_INIHIBIT_ANYPOLICY          MBEDCRYPTO_OID_ID_CE "\x36" /**< id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::=  { id-ce 54 } */
+#define MBEDCRYPTO_OID_FRESHEST_CRL                MBEDCRYPTO_OID_ID_CE "\x2E" /**< id-ce-freshestCRL OBJECT IDENTIFIER ::=  { id-ce 46 } */
+
+/*
+ * Netscape certificate extensions
+ */
+#define MBEDCRYPTO_OID_NS_CERT                 MBEDCRYPTO_OID_NETSCAPE "\x01"
+#define MBEDCRYPTO_OID_NS_CERT_TYPE            MBEDCRYPTO_OID_NS_CERT  "\x01"
+#define MBEDCRYPTO_OID_NS_BASE_URL             MBEDCRYPTO_OID_NS_CERT  "\x02"
+#define MBEDCRYPTO_OID_NS_REVOCATION_URL       MBEDCRYPTO_OID_NS_CERT  "\x03"
+#define MBEDCRYPTO_OID_NS_CA_REVOCATION_URL    MBEDCRYPTO_OID_NS_CERT  "\x04"
+#define MBEDCRYPTO_OID_NS_RENEWAL_URL          MBEDCRYPTO_OID_NS_CERT  "\x07"
+#define MBEDCRYPTO_OID_NS_CA_POLICY_URL        MBEDCRYPTO_OID_NS_CERT  "\x08"
+#define MBEDCRYPTO_OID_NS_SSL_SERVER_NAME      MBEDCRYPTO_OID_NS_CERT  "\x0C"
+#define MBEDCRYPTO_OID_NS_COMMENT              MBEDCRYPTO_OID_NS_CERT  "\x0D"
+#define MBEDCRYPTO_OID_NS_DATA_TYPE            MBEDCRYPTO_OID_NETSCAPE "\x02"
+#define MBEDCRYPTO_OID_NS_CERT_SEQUENCE        MBEDCRYPTO_OID_NS_DATA_TYPE "\x05"
+
+/*
+ * OIDs for CRL extensions
+ */
+#define MBEDCRYPTO_OID_PRIVATE_KEY_USAGE_PERIOD    MBEDCRYPTO_OID_ID_CE "\x10"
+#define MBEDCRYPTO_OID_CRL_NUMBER                  MBEDCRYPTO_OID_ID_CE "\x14" /**< id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 } */
+
+/*
+ * X.509 v3 Extended key usage OIDs
+ */
+#define MBEDCRYPTO_OID_ANY_EXTENDED_KEY_USAGE      MBEDCRYPTO_OID_EXTENDED_KEY_USAGE "\x00" /**< anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 } */
+
+#define MBEDCRYPTO_OID_KP                          MBEDCRYPTO_OID_PKIX "\x03" /**< id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } */
+#define MBEDCRYPTO_OID_SERVER_AUTH                 MBEDCRYPTO_OID_KP "\x01" /**< id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } */
+#define MBEDCRYPTO_OID_CLIENT_AUTH                 MBEDCRYPTO_OID_KP "\x02" /**< id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } */
+#define MBEDCRYPTO_OID_CODE_SIGNING                MBEDCRYPTO_OID_KP "\x03" /**< id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } */
+#define MBEDCRYPTO_OID_EMAIL_PROTECTION            MBEDCRYPTO_OID_KP "\x04" /**< id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } */
+#define MBEDCRYPTO_OID_TIME_STAMPING               MBEDCRYPTO_OID_KP "\x08" /**< id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } */
+#define MBEDCRYPTO_OID_OCSP_SIGNING                MBEDCRYPTO_OID_KP "\x09" /**< id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } */
+
+/*
+ * PKCS definition OIDs
+ */
+
+#define MBEDCRYPTO_OID_PKCS                MBEDCRYPTO_OID_RSA_COMPANY "\x01" /**< pkcs OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) 1 } */
+#define MBEDCRYPTO_OID_PKCS1               MBEDCRYPTO_OID_PKCS "\x01" /**< pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } */
+#define MBEDCRYPTO_OID_PKCS5               MBEDCRYPTO_OID_PKCS "\x05" /**< pkcs-5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 } */
+#define MBEDCRYPTO_OID_PKCS9               MBEDCRYPTO_OID_PKCS "\x09" /**< pkcs-9 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 } */
+#define MBEDCRYPTO_OID_PKCS12              MBEDCRYPTO_OID_PKCS "\x0c" /**< pkcs-12 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 } */
+
+/*
+ * PKCS#1 OIDs
+ */
+#define MBEDCRYPTO_OID_PKCS1_RSA           MBEDCRYPTO_OID_PKCS1 "\x01" /**< rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 } */
+#define MBEDCRYPTO_OID_PKCS1_MD2           MBEDCRYPTO_OID_PKCS1 "\x02" /**< md2WithRSAEncryption ::= { pkcs-1 2 } */
+#define MBEDCRYPTO_OID_PKCS1_MD4           MBEDCRYPTO_OID_PKCS1 "\x03" /**< md4WithRSAEncryption ::= { pkcs-1 3 } */
+#define MBEDCRYPTO_OID_PKCS1_MD5           MBEDCRYPTO_OID_PKCS1 "\x04" /**< md5WithRSAEncryption ::= { pkcs-1 4 } */
+#define MBEDCRYPTO_OID_PKCS1_SHA1          MBEDCRYPTO_OID_PKCS1 "\x05" /**< sha1WithRSAEncryption ::= { pkcs-1 5 } */
+#define MBEDCRYPTO_OID_PKCS1_SHA224        MBEDCRYPTO_OID_PKCS1 "\x0e" /**< sha224WithRSAEncryption ::= { pkcs-1 14 } */
+#define MBEDCRYPTO_OID_PKCS1_SHA256        MBEDCRYPTO_OID_PKCS1 "\x0b" /**< sha256WithRSAEncryption ::= { pkcs-1 11 } */
+#define MBEDCRYPTO_OID_PKCS1_SHA384        MBEDCRYPTO_OID_PKCS1 "\x0c" /**< sha384WithRSAEncryption ::= { pkcs-1 12 } */
+#define MBEDCRYPTO_OID_PKCS1_SHA512        MBEDCRYPTO_OID_PKCS1 "\x0d" /**< sha512WithRSAEncryption ::= { pkcs-1 13 } */
+
+#define MBEDCRYPTO_OID_RSA_SHA_OBS         "\x2B\x0E\x03\x02\x1D"
+
+#define MBEDCRYPTO_OID_PKCS9_EMAIL         MBEDCRYPTO_OID_PKCS9 "\x01" /**< emailAddress AttributeType ::= { pkcs-9 1 } */
+
+/* RFC 4055 */
+#define MBEDCRYPTO_OID_RSASSA_PSS          MBEDCRYPTO_OID_PKCS1 "\x0a" /**< id-RSASSA-PSS ::= { pkcs-1 10 } */
+#define MBEDCRYPTO_OID_MGF1                MBEDCRYPTO_OID_PKCS1 "\x08" /**< id-mgf1 ::= { pkcs-1 8 } */
+
+/*
+ * Digest algorithms
+ */
+#define MBEDCRYPTO_OID_DIGEST_ALG_MD2              MBEDCRYPTO_OID_RSA_COMPANY "\x02\x02" /**< id-mbedcrypto_md2 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 2 } */
+#define MBEDCRYPTO_OID_DIGEST_ALG_MD4              MBEDCRYPTO_OID_RSA_COMPANY "\x02\x04" /**< id-mbedcrypto_md4 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 4 } */
+#define MBEDCRYPTO_OID_DIGEST_ALG_MD5              MBEDCRYPTO_OID_RSA_COMPANY "\x02\x05" /**< id-mbedcrypto_md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 } */
+#define MBEDCRYPTO_OID_DIGEST_ALG_SHA1             MBEDCRYPTO_OID_ISO_IDENTIFIED_ORG MBEDCRYPTO_OID_OIW_SECSIG_SHA1 /**< id-mbedcrypto_sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } */
+#define MBEDCRYPTO_OID_DIGEST_ALG_SHA224           MBEDCRYPTO_OID_GOV "\x03\x04\x02\x04" /**< id-sha224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 4 } */
+#define MBEDCRYPTO_OID_DIGEST_ALG_SHA256           MBEDCRYPTO_OID_GOV "\x03\x04\x02\x01" /**< id-mbedcrypto_sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */
+
+#define MBEDCRYPTO_OID_DIGEST_ALG_SHA384           MBEDCRYPTO_OID_GOV "\x03\x04\x02\x02" /**< id-sha384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 } */
+
+#define MBEDCRYPTO_OID_DIGEST_ALG_SHA512           MBEDCRYPTO_OID_GOV "\x03\x04\x02\x03" /**< id-mbedcrypto_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */
+
+#define MBEDCRYPTO_OID_HMAC_SHA1                   MBEDCRYPTO_OID_RSA_COMPANY "\x02\x07" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } */
+
+#define MBEDCRYPTO_OID_HMAC_SHA224                 MBEDCRYPTO_OID_RSA_COMPANY "\x02\x08" /**< id-hmacWithSHA224 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 8 } */
+
+#define MBEDCRYPTO_OID_HMAC_SHA256                 MBEDCRYPTO_OID_RSA_COMPANY "\x02\x09" /**< id-hmacWithSHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 9 } */
+
+#define MBEDCRYPTO_OID_HMAC_SHA384                 MBEDCRYPTO_OID_RSA_COMPANY "\x02\x0A" /**< id-hmacWithSHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 10 } */
+
+#define MBEDCRYPTO_OID_HMAC_SHA512                 MBEDCRYPTO_OID_RSA_COMPANY "\x02\x0B" /**< id-hmacWithSHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 11 } */
+
+/*
+ * Encryption algorithms
+ */
+#define MBEDCRYPTO_OID_DES_CBC                     MBEDCRYPTO_OID_ISO_IDENTIFIED_ORG MBEDCRYPTO_OID_OIW_SECSIG_ALG "\x07" /**< desCBC OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 7 } */
+#define MBEDCRYPTO_OID_DES_EDE3_CBC                MBEDCRYPTO_OID_RSA_COMPANY "\x03\x07" /**< des-ede3-cbc OBJECT IDENTIFIER ::= { iso(1) member-body(2) -- us(840) rsadsi(113549) encryptionAlgorithm(3) 7 } */
+
+/*
+ * PKCS#5 OIDs
+ */
+#define MBEDCRYPTO_OID_PKCS5_PBKDF2                MBEDCRYPTO_OID_PKCS5 "\x0c" /**< id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12} */
+#define MBEDCRYPTO_OID_PKCS5_PBES2                 MBEDCRYPTO_OID_PKCS5 "\x0d" /**< id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13} */
+#define MBEDCRYPTO_OID_PKCS5_PBMAC1                MBEDCRYPTO_OID_PKCS5 "\x0e" /**< id-PBMAC1 OBJECT IDENTIFIER ::= {pkcs-5 14} */
+
+/*
+ * PKCS#5 PBES1 algorithms
+ */
+#define MBEDCRYPTO_OID_PKCS5_PBE_MD2_DES_CBC       MBEDCRYPTO_OID_PKCS5 "\x01" /**< pbeWithMD2AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 1} */
+#define MBEDCRYPTO_OID_PKCS5_PBE_MD2_RC2_CBC       MBEDCRYPTO_OID_PKCS5 "\x04" /**< pbeWithMD2AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 4} */
+#define MBEDCRYPTO_OID_PKCS5_PBE_MD5_DES_CBC       MBEDCRYPTO_OID_PKCS5 "\x03" /**< pbeWithMD5AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 3} */
+#define MBEDCRYPTO_OID_PKCS5_PBE_MD5_RC2_CBC       MBEDCRYPTO_OID_PKCS5 "\x06" /**< pbeWithMD5AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 6} */
+#define MBEDCRYPTO_OID_PKCS5_PBE_SHA1_DES_CBC      MBEDCRYPTO_OID_PKCS5 "\x0a" /**< pbeWithSHA1AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 10} */
+#define MBEDCRYPTO_OID_PKCS5_PBE_SHA1_RC2_CBC      MBEDCRYPTO_OID_PKCS5 "\x0b" /**< pbeWithSHA1AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 11} */
+
+/*
+ * PKCS#8 OIDs
+ */
+#define MBEDCRYPTO_OID_PKCS9_CSR_EXT_REQ           MBEDCRYPTO_OID_PKCS9 "\x0e" /**< extensionRequest OBJECT IDENTIFIER ::= {pkcs-9 14} */
+
+/*
+ * PKCS#12 PBE OIDs
+ */
+#define MBEDCRYPTO_OID_PKCS12_PBE                      MBEDCRYPTO_OID_PKCS12 "\x01" /**< pkcs-12PbeIds OBJECT IDENTIFIER ::= {pkcs-12 1} */
+
+#define MBEDCRYPTO_OID_PKCS12_PBE_SHA1_RC4_128         MBEDCRYPTO_OID_PKCS12_PBE "\x01" /**< pbeWithSHAAnd128BitRC4 OBJECT IDENTIFIER ::= {pkcs-12PbeIds 1} */
+#define MBEDCRYPTO_OID_PKCS12_PBE_SHA1_RC4_40          MBEDCRYPTO_OID_PKCS12_PBE "\x02" /**< pbeWithSHAAnd40BitRC4 OBJECT IDENTIFIER ::= {pkcs-12PbeIds 2} */
+#define MBEDCRYPTO_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC    MBEDCRYPTO_OID_PKCS12_PBE "\x03" /**< pbeWithSHAAnd3-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 3} */
+#define MBEDCRYPTO_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC    MBEDCRYPTO_OID_PKCS12_PBE "\x04" /**< pbeWithSHAAnd2-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 4} */
+#define MBEDCRYPTO_OID_PKCS12_PBE_SHA1_RC2_128_CBC     MBEDCRYPTO_OID_PKCS12_PBE "\x05" /**< pbeWithSHAAnd128BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 5} */
+#define MBEDCRYPTO_OID_PKCS12_PBE_SHA1_RC2_40_CBC      MBEDCRYPTO_OID_PKCS12_PBE "\x06" /**< pbeWithSHAAnd40BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 6} */
+
+/*
+ * EC key algorithms from RFC 5480
+ */
+
+/* id-ecPublicKey OBJECT IDENTIFIER ::= {
+ *       iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 } */
+#define MBEDCRYPTO_OID_EC_ALG_UNRESTRICTED         MBEDCRYPTO_OID_ANSI_X9_62 "\x02\01"
+
+/*   id-ecDH OBJECT IDENTIFIER ::= {
+ *     iso(1) identified-organization(3) certicom(132)
+ *     schemes(1) ecdh(12) } */
+#define MBEDCRYPTO_OID_EC_ALG_ECDH                 MBEDCRYPTO_OID_CERTICOM "\x01\x0c"
+
+/*
+ * ECParameters namedCurve identifiers, from RFC 5480, RFC 5639, and SEC2
+ */
+
+/* secp192r1 OBJECT IDENTIFIER ::= {
+ *   iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 1 } */
+#define MBEDCRYPTO_OID_EC_GRP_SECP192R1        MBEDCRYPTO_OID_ANSI_X9_62 "\x03\x01\x01"
+
+/* secp224r1 OBJECT IDENTIFIER ::= {
+ *   iso(1) identified-organization(3) certicom(132) curve(0) 33 } */
+#define MBEDCRYPTO_OID_EC_GRP_SECP224R1        MBEDCRYPTO_OID_CERTICOM "\x00\x21"
+
+/* secp256r1 OBJECT IDENTIFIER ::= {
+ *   iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 7 } */
+#define MBEDCRYPTO_OID_EC_GRP_SECP256R1        MBEDCRYPTO_OID_ANSI_X9_62 "\x03\x01\x07"
+
+/* secp384r1 OBJECT IDENTIFIER ::= {
+ *   iso(1) identified-organization(3) certicom(132) curve(0) 34 } */
+#define MBEDCRYPTO_OID_EC_GRP_SECP384R1        MBEDCRYPTO_OID_CERTICOM "\x00\x22"
+
+/* secp521r1 OBJECT IDENTIFIER ::= {
+ *   iso(1) identified-organization(3) certicom(132) curve(0) 35 } */
+#define MBEDCRYPTO_OID_EC_GRP_SECP521R1        MBEDCRYPTO_OID_CERTICOM "\x00\x23"
+
+/* secp192k1 OBJECT IDENTIFIER ::= {
+ *   iso(1) identified-organization(3) certicom(132) curve(0) 31 } */
+#define MBEDCRYPTO_OID_EC_GRP_SECP192K1        MBEDCRYPTO_OID_CERTICOM "\x00\x1f"
+
+/* secp224k1 OBJECT IDENTIFIER ::= {
+ *   iso(1) identified-organization(3) certicom(132) curve(0) 32 } */
+#define MBEDCRYPTO_OID_EC_GRP_SECP224K1        MBEDCRYPTO_OID_CERTICOM "\x00\x20"
+
+/* secp256k1 OBJECT IDENTIFIER ::= {
+ *   iso(1) identified-organization(3) certicom(132) curve(0) 10 } */
+#define MBEDCRYPTO_OID_EC_GRP_SECP256K1        MBEDCRYPTO_OID_CERTICOM "\x00\x0a"
+
+/* RFC 5639 4.1
+ * ecStdCurvesAndGeneration OBJECT IDENTIFIER::= {iso(1)
+ * identified-organization(3) teletrust(36) algorithm(3) signature-
+ * algorithm(3) ecSign(2) 8}
+ * ellipticCurve OBJECT IDENTIFIER ::= {ecStdCurvesAndGeneration 1}
+ * versionOne OBJECT IDENTIFIER ::= {ellipticCurve 1} */
+#define MBEDCRYPTO_OID_EC_BRAINPOOL_V1         MBEDCRYPTO_OID_TELETRUST "\x03\x03\x02\x08\x01\x01"
+
+/* brainpoolP256r1 OBJECT IDENTIFIER ::= {versionOne 7} */
+#define MBEDCRYPTO_OID_EC_GRP_BP256R1          MBEDCRYPTO_OID_EC_BRAINPOOL_V1 "\x07"
+
+/* brainpoolP384r1 OBJECT IDENTIFIER ::= {versionOne 11} */
+#define MBEDCRYPTO_OID_EC_GRP_BP384R1          MBEDCRYPTO_OID_EC_BRAINPOOL_V1 "\x0B"
+
+/* brainpoolP512r1 OBJECT IDENTIFIER ::= {versionOne 13} */
+#define MBEDCRYPTO_OID_EC_GRP_BP512R1          MBEDCRYPTO_OID_EC_BRAINPOOL_V1 "\x0D"
+
+/*
+ * SEC1 C.1
+ *
+ * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 }
+ * id-fieldType OBJECT IDENTIFIER ::= { ansi-X9-62 fieldType(1)}
+ */
+#define MBEDCRYPTO_OID_ANSI_X9_62_FIELD_TYPE   MBEDCRYPTO_OID_ANSI_X9_62 "\x01"
+#define MBEDCRYPTO_OID_ANSI_X9_62_PRIME_FIELD  MBEDCRYPTO_OID_ANSI_X9_62_FIELD_TYPE "\x01"
+
+/*
+ * ECDSA signature identifiers, from RFC 5480
+ */
+#define MBEDCRYPTO_OID_ANSI_X9_62_SIG          MBEDCRYPTO_OID_ANSI_X9_62 "\x04" /* signatures(4) */
+#define MBEDCRYPTO_OID_ANSI_X9_62_SIG_SHA2     MBEDCRYPTO_OID_ANSI_X9_62_SIG "\x03" /* ecdsa-with-SHA2(3) */
+
+/* ecdsa-with-SHA1 OBJECT IDENTIFIER ::= {
+ *   iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) 1 } */
+#define MBEDCRYPTO_OID_ECDSA_SHA1              MBEDCRYPTO_OID_ANSI_X9_62_SIG "\x01"
+
+/* ecdsa-with-SHA224 OBJECT IDENTIFIER ::= {
+ *   iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4)
+ *   ecdsa-with-SHA2(3) 1 } */
+#define MBEDCRYPTO_OID_ECDSA_SHA224            MBEDCRYPTO_OID_ANSI_X9_62_SIG_SHA2 "\x01"
+
+/* ecdsa-with-SHA256 OBJECT IDENTIFIER ::= {
+ *   iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4)
+ *   ecdsa-with-SHA2(3) 2 } */
+#define MBEDCRYPTO_OID_ECDSA_SHA256            MBEDCRYPTO_OID_ANSI_X9_62_SIG_SHA2 "\x02"
+
+/* ecdsa-with-SHA384 OBJECT IDENTIFIER ::= {
+ *   iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4)
+ *   ecdsa-with-SHA2(3) 3 } */
+#define MBEDCRYPTO_OID_ECDSA_SHA384            MBEDCRYPTO_OID_ANSI_X9_62_SIG_SHA2 "\x03"
+
+/* ecdsa-with-SHA512 OBJECT IDENTIFIER ::= {
+ *   iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4)
+ *   ecdsa-with-SHA2(3) 4 } */
+#define MBEDCRYPTO_OID_ECDSA_SHA512            MBEDCRYPTO_OID_ANSI_X9_62_SIG_SHA2 "\x04"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Base OID descriptor structure
+ */
+typedef struct {
+    const char *asn1;               /*!< OID ASN.1 representation       */
+    size_t asn1_len;                /*!< length of asn1                 */
+    const char *name;               /*!< official name (e.g. from RFC)  */
+    const char *description;        /*!< human friendly description     */
+} mbedcrypto_oid_descriptor_t;
+
+/**
+ * \brief           Translate an ASN.1 OID into its numeric representation
+ *                  (e.g. "\x2A\x86\x48\x86\xF7\x0D" into "1.2.840.113549")
+ *
+ * \param buf       buffer to put representation in
+ * \param size      size of the buffer
+ * \param oid       OID to translate
+ *
+ * \return          Length of the string written (excluding final NULL) or
+ *                  MBEDCRYPTO_ERR_OID_BUF_TOO_SMALL in case of error
+ */
+int mbedcrypto_oid_get_numeric_string( char *buf, size_t size, const mbedcrypto_asn1_buf *oid );
+
+#if defined(MBEDCRYPTO_X509_USE_C) || defined(MBEDCRYPTO_X509_CREATE_C)
+/**
+ * \brief          Translate an X.509 extension OID into local values
+ *
+ * \param oid      OID to use
+ * \param ext_type place to store the extension type
+ *
+ * \return         0 if successful, or MBEDCRYPTO_ERR_OID_NOT_FOUND
+ */
+int mbedcrypto_oid_get_x509_ext_type( const mbedcrypto_asn1_buf *oid, int *ext_type );
+#endif
+
+/**
+ * \brief          Translate an X.509 attribute type OID into the short name
+ *                 (e.g. the OID for an X520 Common Name into "CN")
+ *
+ * \param oid      OID to use
+ * \param short_name    place to store the string pointer
+ *
+ * \return         0 if successful, or MBEDCRYPTO_ERR_OID_NOT_FOUND
+ */
+int mbedcrypto_oid_get_attr_short_name( const mbedcrypto_asn1_buf *oid, const char **short_name );
+
+/**
+ * \brief          Translate PublicKeyAlgorithm OID into pk_type
+ *
+ * \param oid      OID to use
+ * \param pk_alg   place to store public key algorithm
+ *
+ * \return         0 if successful, or MBEDCRYPTO_ERR_OID_NOT_FOUND
+ */
+int mbedcrypto_oid_get_pk_alg( const mbedcrypto_asn1_buf *oid, mbedcrypto_pk_type_t *pk_alg );
+
+/**
+ * \brief          Translate pk_type into PublicKeyAlgorithm OID
+ *
+ * \param pk_alg   Public key type to look for
+ * \param oid      place to store ASN.1 OID string pointer
+ * \param olen     length of the OID
+ *
+ * \return         0 if successful, or MBEDCRYPTO_ERR_OID_NOT_FOUND
+ */
+int mbedcrypto_oid_get_oid_by_pk_alg( mbedcrypto_pk_type_t pk_alg,
+                           const char **oid, size_t *olen );
+
+#if defined(MBEDCRYPTO_ECP_C)
+/**
+ * \brief          Translate NamedCurve OID into an EC group identifier
+ *
+ * \param oid      OID to use
+ * \param grp_id   place to store group id
+ *
+ * \return         0 if successful, or MBEDCRYPTO_ERR_OID_NOT_FOUND
+ */
+int mbedcrypto_oid_get_ec_grp( const mbedcrypto_asn1_buf *oid, mbedcrypto_ecp_group_id *grp_id );
+
+/**
+ * \brief          Translate EC group identifier into NamedCurve OID
+ *
+ * \param grp_id   EC group identifier
+ * \param oid      place to store ASN.1 OID string pointer
+ * \param olen     length of the OID
+ *
+ * \return         0 if successful, or MBEDCRYPTO_ERR_OID_NOT_FOUND
+ */
+int mbedcrypto_oid_get_oid_by_ec_grp( mbedcrypto_ecp_group_id grp_id,
+                           const char **oid, size_t *olen );
+#endif /* MBEDCRYPTO_ECP_C */
+
+#if defined(MBEDCRYPTO_MD_C)
+/**
+ * \brief          Translate SignatureAlgorithm OID into md_type and pk_type
+ *
+ * \param oid      OID to use
+ * \param md_alg   place to store message digest algorithm
+ * \param pk_alg   place to store public key algorithm
+ *
+ * \return         0 if successful, or MBEDCRYPTO_ERR_OID_NOT_FOUND
+ */
+int mbedcrypto_oid_get_sig_alg( const mbedcrypto_asn1_buf *oid,
+                     mbedcrypto_md_type_t *md_alg, mbedcrypto_pk_type_t *pk_alg );
+
+/**
+ * \brief          Translate SignatureAlgorithm OID into description
+ *
+ * \param oid      OID to use
+ * \param desc     place to store string pointer
+ *
+ * \return         0 if successful, or MBEDCRYPTO_ERR_OID_NOT_FOUND
+ */
+int mbedcrypto_oid_get_sig_alg_desc( const mbedcrypto_asn1_buf *oid, const char **desc );
+
+/**
+ * \brief          Translate md_type and pk_type into SignatureAlgorithm OID
+ *
+ * \param md_alg   message digest algorithm
+ * \param pk_alg   public key algorithm
+ * \param oid      place to store ASN.1 OID string pointer
+ * \param olen     length of the OID
+ *
+ * \return         0 if successful, or MBEDCRYPTO_ERR_OID_NOT_FOUND
+ */
+int mbedcrypto_oid_get_oid_by_sig_alg( mbedcrypto_pk_type_t pk_alg, mbedcrypto_md_type_t md_alg,
+                            const char **oid, size_t *olen );
+
+/**
+ * \brief          Translate hash algorithm OID into md_type
+ *
+ * \param oid      OID to use
+ * \param md_alg   place to store message digest algorithm
+ *
+ * \return         0 if successful, or MBEDCRYPTO_ERR_OID_NOT_FOUND
+ */
+int mbedcrypto_oid_get_md_alg( const mbedcrypto_asn1_buf *oid, mbedcrypto_md_type_t *md_alg );
+
+/**
+ * \brief          Translate hmac algorithm OID into md_type
+ *
+ * \param oid      OID to use
+ * \param md_hmac  place to store message hmac algorithm
+ *
+ * \return         0 if successful, or MBEDCRYPTO_ERR_OID_NOT_FOUND
+ */
+int mbedcrypto_oid_get_md_hmac( const mbedcrypto_asn1_buf *oid, mbedcrypto_md_type_t *md_hmac );
+#endif /* MBEDCRYPTO_MD_C */
+
+/**
+ * \brief          Translate Extended Key Usage OID into description
+ *
+ * \param oid      OID to use
+ * \param desc     place to store string pointer
+ *
+ * \return         0 if successful, or MBEDCRYPTO_ERR_OID_NOT_FOUND
+ */
+int mbedcrypto_oid_get_extended_key_usage( const mbedcrypto_asn1_buf *oid, const char **desc );
+
+/**
+ * \brief          Translate md_type into hash algorithm OID
+ *
+ * \param md_alg   message digest algorithm
+ * \param oid      place to store ASN.1 OID string pointer
+ * \param olen     length of the OID
+ *
+ * \return         0 if successful, or MBEDCRYPTO_ERR_OID_NOT_FOUND
+ */
+int mbedcrypto_oid_get_oid_by_md( mbedcrypto_md_type_t md_alg, const char **oid, size_t *olen );
+
+#if defined(MBEDCRYPTO_CIPHER_C)
+/**
+ * \brief          Translate encryption algorithm OID into cipher_type
+ *
+ * \param oid           OID to use
+ * \param cipher_alg    place to store cipher algorithm
+ *
+ * \return         0 if successful, or MBEDCRYPTO_ERR_OID_NOT_FOUND
+ */
+int mbedcrypto_oid_get_cipher_alg( const mbedcrypto_asn1_buf *oid, mbedcrypto_cipher_type_t *cipher_alg );
+#endif /* MBEDCRYPTO_CIPHER_C */
+
+#if defined(MBEDCRYPTO_PKCS12_C)
+/**
+ * \brief          Translate PKCS#12 PBE algorithm OID into md_type and
+ *                 cipher_type
+ *
+ * \param oid           OID to use
+ * \param md_alg        place to store message digest algorithm
+ * \param cipher_alg    place to store cipher algorithm
+ *
+ * \return         0 if successful, or MBEDCRYPTO_ERR_OID_NOT_FOUND
+ */
+int mbedcrypto_oid_get_pkcs12_pbe_alg( const mbedcrypto_asn1_buf *oid, mbedcrypto_md_type_t *md_alg,
+                            mbedcrypto_cipher_type_t *cipher_alg );
+#endif /* MBEDCRYPTO_PKCS12_C */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* oid.h */
diff --git a/include/mbedcrypto/pem.h b/include/mbedcrypto/pem.h
new file mode 100644
index 0000000..e742eea
--- /dev/null
+++ b/include/mbedcrypto/pem.h
@@ -0,0 +1,130 @@
+/**
+ * \file pem.h
+ *
+ * \brief Privacy Enhanced Mail (PEM) decoding
+ */
+/*
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_PEM_H
+#define MBEDCRYPTO_PEM_H
+
+#include <stddef.h>
+
+/**
+ * \name PEM Error codes
+ * These error codes are returned in case of errors reading the
+ * PEM data.
+ * \{
+ */
+#define MBEDCRYPTO_ERR_PEM_NO_HEADER_FOOTER_PRESENT          -0x1080  /**< No PEM header or footer found. */
+#define MBEDCRYPTO_ERR_PEM_INVALID_DATA                      -0x1100  /**< PEM string is not as expected. */
+#define MBEDCRYPTO_ERR_PEM_ALLOC_FAILED                      -0x1180  /**< Failed to allocate memory. */
+#define MBEDCRYPTO_ERR_PEM_INVALID_ENC_IV                    -0x1200  /**< RSA IV is not in hex-format. */
+#define MBEDCRYPTO_ERR_PEM_UNKNOWN_ENC_ALG                   -0x1280  /**< Unsupported key encryption algorithm. */
+#define MBEDCRYPTO_ERR_PEM_PASSWORD_REQUIRED                 -0x1300  /**< Private key password can't be empty. */
+#define MBEDCRYPTO_ERR_PEM_PASSWORD_MISMATCH                 -0x1380  /**< Given private key password does not allow for correct decryption. */
+#define MBEDCRYPTO_ERR_PEM_FEATURE_UNAVAILABLE               -0x1400  /**< Unavailable feature, e.g. hashing/encryption combination. */
+#define MBEDCRYPTO_ERR_PEM_BAD_INPUT_DATA                    -0x1480  /**< Bad input parameters to function. */
+/* \} name */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(MBEDCRYPTO_PEM_PARSE_C)
+/**
+ * \brief       PEM context structure
+ */
+typedef struct
+{
+    unsigned char *buf;     /*!< buffer for decoded data             */
+    size_t buflen;          /*!< length of the buffer                */
+    unsigned char *info;    /*!< buffer for extra header information */
+}
+mbedcrypto_pem_context;
+
+/**
+ * \brief       PEM context setup
+ *
+ * \param ctx   context to be initialized
+ */
+void mbedcrypto_pem_init( mbedcrypto_pem_context *ctx );
+
+/**
+ * \brief       Read a buffer for PEM information and store the resulting
+ *              data into the specified context buffers.
+ *
+ * \param ctx       context to use
+ * \param header    header string to seek and expect
+ * \param footer    footer string to seek and expect
+ * \param data      source data to look in (must be nul-terminated)
+ * \param pwd       password for decryption (can be NULL)
+ * \param pwdlen    length of password
+ * \param use_len   destination for total length used (set after header is
+ *                  correctly read, so unless you get
+ *                  MBEDCRYPTO_ERR_PEM_BAD_INPUT_DATA or
+ *                  MBEDCRYPTO_ERR_PEM_NO_HEADER_FOOTER_PRESENT, use_len is
+ *                  the length to skip)
+ *
+ * \note            Attempts to check password correctness by verifying if
+ *                  the decrypted text starts with an ASN.1 sequence of
+ *                  appropriate length
+ *
+ * \return          0 on success, or a specific PEM error code
+ */
+int mbedcrypto_pem_read_buffer( mbedcrypto_pem_context *ctx, const char *header, const char *footer,
+                     const unsigned char *data,
+                     const unsigned char *pwd,
+                     size_t pwdlen, size_t *use_len );
+
+/**
+ * \brief       PEM context memory freeing
+ *
+ * \param ctx   context to be freed
+ */
+void mbedcrypto_pem_free( mbedcrypto_pem_context *ctx );
+#endif /* MBEDCRYPTO_PEM_PARSE_C */
+
+#if defined(MBEDCRYPTO_PEM_WRITE_C)
+/**
+ * \brief           Write a buffer of PEM information from a DER encoded
+ *                  buffer.
+ *
+ * \param header    header string to write
+ * \param footer    footer string to write
+ * \param der_data  DER data to write
+ * \param der_len   length of the DER data
+ * \param buf       buffer to write to
+ * \param buf_len   length of output buffer
+ * \param olen      total length written / required (if buf_len is not enough)
+ *
+ * \return          0 on success, or a specific PEM or BASE64 error code. On
+ *                  MBEDCRYPTO_ERR_BASE64_BUFFER_TOO_SMALL olen is the required
+ *                  size.
+ */
+int mbedcrypto_pem_write_buffer( const char *header, const char *footer,
+                      const unsigned char *der_data, size_t der_len,
+                      unsigned char *buf, size_t buf_len, size_t *olen );
+#endif /* MBEDCRYPTO_PEM_WRITE_C */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* pem.h */
diff --git a/include/mbedcrypto/pk.h b/include/mbedcrypto/pk.h
new file mode 100644
index 0000000..469b96c
--- /dev/null
+++ b/include/mbedcrypto/pk.h
@@ -0,0 +1,618 @@
+/**
+ * \file pk.h
+ *
+ * \brief Public Key abstraction layer
+ */
+/*
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#ifndef MBEDCRYPTO_PK_H
+#define MBEDCRYPTO_PK_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include "md.h"
+
+#if defined(MBEDCRYPTO_RSA_C)
+#include "rsa.h"
+#endif
+
+#if defined(MBEDCRYPTO_ECP_C)
+#include "ecp.h"
+#endif
+
+#if defined(MBEDCRYPTO_ECDSA_C)
+#include "ecdsa.h"
+#endif
+
+#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
+    !defined(inline) && !defined(__cplusplus)
+#define inline __inline
+#endif
+
+#define MBEDCRYPTO_ERR_PK_ALLOC_FAILED        -0x3F80  /**< Memory allocation failed. */
+#define MBEDCRYPTO_ERR_PK_TYPE_MISMATCH       -0x3F00  /**< Type mismatch, eg attempt to encrypt with an ECDSA key */
+#define MBEDCRYPTO_ERR_PK_BAD_INPUT_DATA      -0x3E80  /**< Bad input parameters to function. */
+#define MBEDCRYPTO_ERR_PK_FILE_IO_ERROR       -0x3E00  /**< Read/write of file failed. */
+#define MBEDCRYPTO_ERR_PK_KEY_INVALID_VERSION -0x3D80  /**< Unsupported key version */
+#define MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT  -0x3D00  /**< Invalid key tag or value. */
+#define MBEDCRYPTO_ERR_PK_UNKNOWN_PK_ALG      -0x3C80  /**< Key algorithm is unsupported (only RSA and EC are supported). */
+#define MBEDCRYPTO_ERR_PK_PASSWORD_REQUIRED   -0x3C00  /**< Private key password can't be empty. */
+#define MBEDCRYPTO_ERR_PK_PASSWORD_MISMATCH   -0x3B80  /**< Given private key password does not allow for correct decryption. */
+#define MBEDCRYPTO_ERR_PK_INVALID_PUBKEY      -0x3B00  /**< The pubkey tag or value is invalid (only RSA and EC are supported). */
+#define MBEDCRYPTO_ERR_PK_INVALID_ALG         -0x3A80  /**< The algorithm tag or value is invalid. */
+#define MBEDCRYPTO_ERR_PK_UNKNOWN_NAMED_CURVE -0x3A00  /**< Elliptic curve is unsupported (only NIST curves are supported). */
+#define MBEDCRYPTO_ERR_PK_FEATURE_UNAVAILABLE -0x3980  /**< Unavailable feature, e.g. RSA disabled for RSA key. */
+#define MBEDCRYPTO_ERR_PK_SIG_LEN_MISMATCH    -0x3900  /**< The buffer contains a valid signature followed by more data. */
+#define MBEDCRYPTO_ERR_PK_HW_ACCEL_FAILED     -0x3880  /**< PK hardware accelerator failed. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          Public key types
+ */
+typedef enum {
+    MBEDCRYPTO_PK_NONE=0,
+    MBEDCRYPTO_PK_RSA,
+    MBEDCRYPTO_PK_ECKEY,
+    MBEDCRYPTO_PK_ECKEY_DH,
+    MBEDCRYPTO_PK_ECDSA,
+    MBEDCRYPTO_PK_RSA_ALT,
+    MBEDCRYPTO_PK_RSASSA_PSS,
+} mbedcrypto_pk_type_t;
+
+/**
+ * \brief           Options for RSASSA-PSS signature verification.
+ *                  See \c mbedcrypto_rsa_rsassa_pss_verify_ext()
+ */
+typedef struct
+{
+    mbedcrypto_md_type_t mgf1_hash_id;
+    int expected_salt_len;
+
+} mbedcrypto_pk_rsassa_pss_options;
+
+/**
+ * \brief           Types for interfacing with the debug module
+ */
+typedef enum
+{
+    MBEDCRYPTO_PK_DEBUG_NONE = 0,
+    MBEDCRYPTO_PK_DEBUG_MPI,
+    MBEDCRYPTO_PK_DEBUG_ECP,
+} mbedcrypto_pk_debug_type;
+
+/**
+ * \brief           Item to send to the debug module
+ */
+typedef struct
+{
+    mbedcrypto_pk_debug_type type;
+    const char *name;
+    void *value;
+} mbedcrypto_pk_debug_item;
+
+/** Maximum number of item send for debugging, plus 1 */
+#define MBEDCRYPTO_PK_DEBUG_MAX_ITEMS 3
+
+/**
+ * \brief           Public key information and operations
+ */
+typedef struct mbedcrypto_pk_info_t mbedcrypto_pk_info_t;
+
+/**
+ * \brief           Public key container
+ */
+typedef struct
+{
+    const mbedcrypto_pk_info_t *   pk_info; /**< Public key informations        */
+    void *                      pk_ctx;  /**< Underlying public key context  */
+} mbedcrypto_pk_context;
+
+#if defined(MBEDCRYPTO_RSA_C)
+/**
+ * Quick access to an RSA context inside a PK context.
+ *
+ * \warning You must make sure the PK context actually holds an RSA context
+ * before using this function!
+ */
+static inline mbedcrypto_rsa_context *mbedcrypto_pk_rsa( const mbedcrypto_pk_context pk )
+{
+    return( (mbedcrypto_rsa_context *) (pk).pk_ctx );
+}
+#endif /* MBEDCRYPTO_RSA_C */
+
+#if defined(MBEDCRYPTO_ECP_C)
+/**
+ * Quick access to an EC context inside a PK context.
+ *
+ * \warning You must make sure the PK context actually holds an EC context
+ * before using this function!
+ */
+static inline mbedcrypto_ecp_keypair *mbedcrypto_pk_ec( const mbedcrypto_pk_context pk )
+{
+    return( (mbedcrypto_ecp_keypair *) (pk).pk_ctx );
+}
+#endif /* MBEDCRYPTO_ECP_C */
+
+#if defined(MBEDCRYPTO_PK_RSA_ALT_SUPPORT)
+/**
+ * \brief           Types for RSA-alt abstraction
+ */
+typedef int (*mbedcrypto_pk_rsa_alt_decrypt_func)( void *ctx, int mode, size_t *olen,
+                    const unsigned char *input, unsigned char *output,
+                    size_t output_max_len );
+typedef int (*mbedcrypto_pk_rsa_alt_sign_func)( void *ctx,
+                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+                    int mode, mbedcrypto_md_type_t md_alg, unsigned int hashlen,
+                    const unsigned char *hash, unsigned char *sig );
+typedef size_t (*mbedcrypto_pk_rsa_alt_key_len_func)( void *ctx );
+#endif /* MBEDCRYPTO_PK_RSA_ALT_SUPPORT */
+
+/**
+ * \brief           Return information associated with the given PK type
+ *
+ * \param pk_type   PK type to search for.
+ *
+ * \return          The PK info associated with the type or NULL if not found.
+ */
+const mbedcrypto_pk_info_t *mbedcrypto_pk_info_from_type( mbedcrypto_pk_type_t pk_type );
+
+/**
+ * \brief           Initialize a mbedcrypto_pk_context (as NONE)
+ */
+void mbedcrypto_pk_init( mbedcrypto_pk_context *ctx );
+
+/**
+ * \brief           Free a mbedcrypto_pk_context
+ */
+void mbedcrypto_pk_free( mbedcrypto_pk_context *ctx );
+
+/**
+ * \brief           Initialize a PK context with the information given
+ *                  and allocates the type-specific PK subcontext.
+ *
+ * \param ctx       Context to initialize. Must be empty (type NONE).
+ * \param info      Information to use
+ *
+ * \return          0 on success,
+ *                  MBEDCRYPTO_ERR_PK_BAD_INPUT_DATA on invalid input,
+ *                  MBEDCRYPTO_ERR_PK_ALLOC_FAILED on allocation failure.
+ *
+ * \note            For contexts holding an RSA-alt key, use
+ *                  \c mbedcrypto_pk_setup_rsa_alt() instead.
+ */
+int mbedcrypto_pk_setup( mbedcrypto_pk_context *ctx, const mbedcrypto_pk_info_t *info );
+
+#if defined(MBEDCRYPTO_PK_RSA_ALT_SUPPORT)
+/**
+ * \brief           Initialize an RSA-alt context
+ *
+ * \param ctx       Context to initialize. Must be empty (type NONE).
+ * \param key       RSA key pointer
+ * \param decrypt_func  Decryption function
+ * \param sign_func     Signing function
+ * \param key_len_func  Function returning key length in bytes
+ *
+ * \return          0 on success, or MBEDCRYPTO_ERR_PK_BAD_INPUT_DATA if the
+ *                  context wasn't already initialized as RSA_ALT.
+ *
+ * \note            This function replaces \c mbedcrypto_pk_setup() for RSA-alt.
+ */
+int mbedcrypto_pk_setup_rsa_alt( mbedcrypto_pk_context *ctx, void * key,
+                         mbedcrypto_pk_rsa_alt_decrypt_func decrypt_func,
+                         mbedcrypto_pk_rsa_alt_sign_func sign_func,
+                         mbedcrypto_pk_rsa_alt_key_len_func key_len_func );
+#endif /* MBEDCRYPTO_PK_RSA_ALT_SUPPORT */
+
+/**
+ * \brief           Get the size in bits of the underlying key
+ *
+ * \param ctx       Context to use
+ *
+ * \return          Key size in bits, or 0 on error
+ */
+size_t mbedcrypto_pk_get_bitlen( const mbedcrypto_pk_context *ctx );
+
+/**
+ * \brief           Get the length in bytes of the underlying key
+ * \param ctx       Context to use
+ *
+ * \return          Key length in bytes, or 0 on error
+ */
+static inline size_t mbedcrypto_pk_get_len( const mbedcrypto_pk_context *ctx )
+{
+    return( ( mbedcrypto_pk_get_bitlen( ctx ) + 7 ) / 8 );
+}
+
+/**
+ * \brief           Tell if a context can do the operation given by type
+ *
+ * \param ctx       Context to test
+ * \param type      Target type
+ *
+ * \return          0 if context can't do the operations,
+ *                  1 otherwise.
+ */
+int mbedcrypto_pk_can_do( const mbedcrypto_pk_context *ctx, mbedcrypto_pk_type_t type );
+
+/**
+ * \brief           Verify signature (including padding if relevant).
+ *
+ * \param ctx       PK context to use
+ * \param md_alg    Hash algorithm used (see notes)
+ * \param hash      Hash of the message to sign
+ * \param hash_len  Hash length or 0 (see notes)
+ * \param sig       Signature to verify
+ * \param sig_len   Signature length
+ *
+ * \return          0 on success (signature is valid),
+ *                  #MBEDCRYPTO_ERR_PK_SIG_LEN_MISMATCH if there is a valid
+ *                  signature in sig but its length is less than \p siglen,
+ *                  or a specific error code.
+ *
+ * \note            For RSA keys, the default padding type is PKCS#1 v1.5.
+ *                  Use \c mbedcrypto_pk_verify_ext( MBEDCRYPTO_PK_RSASSA_PSS, ... )
+ *                  to verify RSASSA_PSS signatures.
+ *
+ * \note            If hash_len is 0, then the length associated with md_alg
+ *                  is used instead, or an error returned if it is invalid.
+ *
+ * \note            md_alg may be MBEDCRYPTO_MD_NONE, only if hash_len != 0
+ */
+int mbedcrypto_pk_verify( mbedcrypto_pk_context *ctx, mbedcrypto_md_type_t md_alg,
+               const unsigned char *hash, size_t hash_len,
+               const unsigned char *sig, size_t sig_len );
+
+/**
+ * \brief           Verify signature, with options.
+ *                  (Includes verification of the padding depending on type.)
+ *
+ * \param type      Signature type (inc. possible padding type) to verify
+ * \param options   Pointer to type-specific options, or NULL
+ * \param ctx       PK context to use
+ * \param md_alg    Hash algorithm used (see notes)
+ * \param hash      Hash of the message to sign
+ * \param hash_len  Hash length or 0 (see notes)
+ * \param sig       Signature to verify
+ * \param sig_len   Signature length
+ *
+ * \return          0 on success (signature is valid),
+ *                  #MBEDCRYPTO_ERR_PK_TYPE_MISMATCH if the PK context can't be
+ *                  used for this type of signatures,
+ *                  #MBEDCRYPTO_ERR_PK_SIG_LEN_MISMATCH if there is a valid
+ *                  signature in sig but its length is less than \p siglen,
+ *                  or a specific error code.
+ *
+ * \note            If hash_len is 0, then the length associated with md_alg
+ *                  is used instead, or an error returned if it is invalid.
+ *
+ * \note            md_alg may be MBEDCRYPTO_MD_NONE, only if hash_len != 0
+ *
+ * \note            If type is MBEDCRYPTO_PK_RSASSA_PSS, then options must point
+ *                  to a mbedcrypto_pk_rsassa_pss_options structure,
+ *                  otherwise it must be NULL.
+ */
+int mbedcrypto_pk_verify_ext( mbedcrypto_pk_type_t type, const void *options,
+                   mbedcrypto_pk_context *ctx, mbedcrypto_md_type_t md_alg,
+                   const unsigned char *hash, size_t hash_len,
+                   const unsigned char *sig, size_t sig_len );
+
+/**
+ * \brief           Make signature, including padding if relevant.
+ *
+ * \param ctx       PK context to use - must hold a private key
+ * \param md_alg    Hash algorithm used (see notes)
+ * \param hash      Hash of the message to sign
+ * \param hash_len  Hash length or 0 (see notes)
+ * \param sig       Place to write the signature
+ * \param sig_len   Number of bytes written
+ * \param f_rng     RNG function
+ * \param p_rng     RNG parameter
+ *
+ * \return          0 on success, or a specific error code.
+ *
+ * \note            For RSA keys, the default padding type is PKCS#1 v1.5.
+ *                  There is no interface in the PK module to make RSASSA-PSS
+ *                  signatures yet.
+ *
+ * \note            If hash_len is 0, then the length associated with md_alg
+ *                  is used instead, or an error returned if it is invalid.
+ *
+ * \note            For RSA, md_alg may be MBEDCRYPTO_MD_NONE if hash_len != 0.
+ *                  For ECDSA, md_alg may never be MBEDCRYPTO_MD_NONE.
+ */
+int mbedcrypto_pk_sign( mbedcrypto_pk_context *ctx, mbedcrypto_md_type_t md_alg,
+             const unsigned char *hash, size_t hash_len,
+             unsigned char *sig, size_t *sig_len,
+             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
+
+/**
+ * \brief           Decrypt message (including padding if relevant).
+ *
+ * \param ctx       PK context to use - must hold a private key
+ * \param input     Input to decrypt
+ * \param ilen      Input size
+ * \param output    Decrypted output
+ * \param olen      Decrypted message length
+ * \param osize     Size of the output buffer
+ * \param f_rng     RNG function
+ * \param p_rng     RNG parameter
+ *
+ * \note            For RSA keys, the default padding type is PKCS#1 v1.5.
+ *
+ * \return          0 on success, or a specific error code.
+ */
+int mbedcrypto_pk_decrypt( mbedcrypto_pk_context *ctx,
+                const unsigned char *input, size_t ilen,
+                unsigned char *output, size_t *olen, size_t osize,
+                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
+
+/**
+ * \brief           Encrypt message (including padding if relevant).
+ *
+ * \param ctx       PK context to use
+ * \param input     Message to encrypt
+ * \param ilen      Message size
+ * \param output    Encrypted output
+ * \param olen      Encrypted output length
+ * \param osize     Size of the output buffer
+ * \param f_rng     RNG function
+ * \param p_rng     RNG parameter
+ *
+ * \note            For RSA keys, the default padding type is PKCS#1 v1.5.
+ *
+ * \return          0 on success, or a specific error code.
+ */
+int mbedcrypto_pk_encrypt( mbedcrypto_pk_context *ctx,
+                const unsigned char *input, size_t ilen,
+                unsigned char *output, size_t *olen, size_t osize,
+                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
+
+/**
+ * \brief           Check if a public-private pair of keys matches.
+ *
+ * \param pub       Context holding a public key.
+ * \param prv       Context holding a private (and public) key.
+ *
+ * \return          0 on success or MBEDCRYPTO_ERR_PK_BAD_INPUT_DATA
+ */
+int mbedcrypto_pk_check_pair( const mbedcrypto_pk_context *pub, const mbedcrypto_pk_context *prv );
+
+/**
+ * \brief           Export debug information
+ *
+ * \param ctx       Context to use
+ * \param items     Place to write debug items
+ *
+ * \return          0 on success or MBEDCRYPTO_ERR_PK_BAD_INPUT_DATA
+ */
+int mbedcrypto_pk_debug( const mbedcrypto_pk_context *ctx, mbedcrypto_pk_debug_item *items );
+
+/**
+ * \brief           Access the type name
+ *
+ * \param ctx       Context to use
+ *
+ * \return          Type name on success, or "invalid PK"
+ */
+const char * mbedcrypto_pk_get_name( const mbedcrypto_pk_context *ctx );
+
+/**
+ * \brief           Get the key type
+ *
+ * \param ctx       Context to use
+ *
+ * \return          Type on success, or MBEDCRYPTO_PK_NONE
+ */
+mbedcrypto_pk_type_t mbedcrypto_pk_get_type( const mbedcrypto_pk_context *ctx );
+
+#if defined(MBEDCRYPTO_PK_PARSE_C)
+/** \ingroup pk_module */
+/**
+ * \brief           Parse a private key in PEM or DER format
+ *
+ * \param ctx       key to be initialized
+ * \param key       input buffer
+ * \param keylen    size of the buffer
+ *                  (including the terminating null byte for PEM data)
+ * \param pwd       password for decryption (optional)
+ * \param pwdlen    size of the password
+ *
+ * \note            On entry, ctx must be empty, either freshly initialised
+ *                  with mbedcrypto_pk_init() or reset with mbedcrypto_pk_free(). If you need a
+ *                  specific key type, check the result with mbedcrypto_pk_can_do().
+ *
+ * \note            The key is also checked for correctness.
+ *
+ * \return          0 if successful, or a specific PK or PEM error code
+ */
+int mbedcrypto_pk_parse_key( mbedcrypto_pk_context *ctx,
+                  const unsigned char *key, size_t keylen,
+                  const unsigned char *pwd, size_t pwdlen );
+
+/** \ingroup pk_module */
+/**
+ * \brief           Parse a public key in PEM or DER format
+ *
+ * \param ctx       key to be initialized
+ * \param key       input buffer
+ * \param keylen    size of the buffer
+ *                  (including the terminating null byte for PEM data)
+ *
+ * \note            On entry, ctx must be empty, either freshly initialised
+ *                  with mbedcrypto_pk_init() or reset with mbedcrypto_pk_free(). If you need a
+ *                  specific key type, check the result with mbedcrypto_pk_can_do().
+ *
+ * \note            The key is also checked for correctness.
+ *
+ * \return          0 if successful, or a specific PK or PEM error code
+ */
+int mbedcrypto_pk_parse_public_key( mbedcrypto_pk_context *ctx,
+                         const unsigned char *key, size_t keylen );
+
+#if defined(MBEDCRYPTO_FS_IO)
+/** \ingroup pk_module */
+/**
+ * \brief           Load and parse a private key
+ *
+ * \param ctx       key to be initialized
+ * \param path      filename to read the private key from
+ * \param password  password to decrypt the file (can be NULL)
+ *
+ * \note            On entry, ctx must be empty, either freshly initialised
+ *                  with mbedcrypto_pk_init() or reset with mbedcrypto_pk_free(). If you need a
+ *                  specific key type, check the result with mbedcrypto_pk_can_do().
+ *
+ * \note            The key is also checked for correctness.
+ *
+ * \return          0 if successful, or a specific PK or PEM error code
+ */
+int mbedcrypto_pk_parse_keyfile( mbedcrypto_pk_context *ctx,
+                      const char *path, const char *password );
+
+/** \ingroup pk_module */
+/**
+ * \brief           Load and parse a public key
+ *
+ * \param ctx       key to be initialized
+ * \param path      filename to read the public key from
+ *
+ * \note            On entry, ctx must be empty, either freshly initialised
+ *                  with mbedcrypto_pk_init() or reset with mbedcrypto_pk_free(). If
+ *                  you need a specific key type, check the result with
+ *                  mbedcrypto_pk_can_do().
+ *
+ * \note            The key is also checked for correctness.
+ *
+ * \return          0 if successful, or a specific PK or PEM error code
+ */
+int mbedcrypto_pk_parse_public_keyfile( mbedcrypto_pk_context *ctx, const char *path );
+#endif /* MBEDCRYPTO_FS_IO */
+#endif /* MBEDCRYPTO_PK_PARSE_C */
+
+#if defined(MBEDCRYPTO_PK_WRITE_C)
+/**
+ * \brief           Write a private key to a PKCS#1 or SEC1 DER structure
+ *                  Note: data is written at the end of the buffer! Use the
+ *                        return value to determine where you should start
+ *                        using the buffer
+ *
+ * \param ctx       private to write away
+ * \param buf       buffer to write to
+ * \param size      size of the buffer
+ *
+ * \return          length of data written if successful, or a specific
+ *                  error code
+ */
+int mbedcrypto_pk_write_key_der( mbedcrypto_pk_context *ctx, unsigned char *buf, size_t size );
+
+/**
+ * \brief           Write a public key to a SubjectPublicKeyInfo DER structure
+ *                  Note: data is written at the end of the buffer! Use the
+ *                        return value to determine where you should start
+ *                        using the buffer
+ *
+ * \param ctx       public key to write away
+ * \param buf       buffer to write to
+ * \param size      size of the buffer
+ *
+ * \return          length of data written if successful, or a specific
+ *                  error code
+ */
+int mbedcrypto_pk_write_pubkey_der( mbedcrypto_pk_context *ctx, unsigned char *buf, size_t size );
+
+#if defined(MBEDCRYPTO_PEM_WRITE_C)
+/**
+ * \brief           Write a public key to a PEM string
+ *
+ * \param ctx       public key to write away
+ * \param buf       buffer to write to
+ * \param size      size of the buffer
+ *
+ * \return          0 if successful, or a specific error code
+ */
+int mbedcrypto_pk_write_pubkey_pem( mbedcrypto_pk_context *ctx, unsigned char *buf, size_t size );
+
+/**
+ * \brief           Write a private key to a PKCS#1 or SEC1 PEM string
+ *
+ * \param ctx       private to write away
+ * \param buf       buffer to write to
+ * \param size      size of the buffer
+ *
+ * \return          0 if successful, or a specific error code
+ */
+int mbedcrypto_pk_write_key_pem( mbedcrypto_pk_context *ctx, unsigned char *buf, size_t size );
+#endif /* MBEDCRYPTO_PEM_WRITE_C */
+#endif /* MBEDCRYPTO_PK_WRITE_C */
+
+/*
+ * WARNING: Low-level functions. You probably do not want to use these unless
+ *          you are certain you do ;)
+ */
+
+#if defined(MBEDCRYPTO_PK_PARSE_C)
+/**
+ * \brief           Parse a SubjectPublicKeyInfo DER structure
+ *
+ * \param p         the position in the ASN.1 data
+ * \param end       end of the buffer
+ * \param pk        the key to fill
+ *
+ * \return          0 if successful, or a specific PK error code
+ */
+int mbedcrypto_pk_parse_subpubkey( unsigned char **p, const unsigned char *end,
+                        mbedcrypto_pk_context *pk );
+#endif /* MBEDCRYPTO_PK_PARSE_C */
+
+#if defined(MBEDCRYPTO_PK_WRITE_C)
+/**
+ * \brief           Write a subjectPublicKey to ASN.1 data
+ *                  Note: function works backwards in data buffer
+ *
+ * \param p         reference to current position pointer
+ * \param start     start of the buffer (for bounds-checking)
+ * \param key       public key to write away
+ *
+ * \return          the length written or a negative error code
+ */
+int mbedcrypto_pk_write_pubkey( unsigned char **p, unsigned char *start,
+                     const mbedcrypto_pk_context *key );
+#endif /* MBEDCRYPTO_PK_WRITE_C */
+
+/*
+ * Internal module functions. You probably do not want to use these unless you
+ * know you do.
+ */
+#if defined(MBEDCRYPTO_FS_IO)
+int mbedcrypto_pk_load_file( const char *path, unsigned char **buf, size_t *n );
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDCRYPTO_PK_H */
diff --git a/include/mbedcrypto/pk_internal.h b/include/mbedcrypto/pk_internal.h
new file mode 100644
index 0000000..b208c6e
--- /dev/null
+++ b/include/mbedcrypto/pk_internal.h
@@ -0,0 +1,115 @@
+/**
+ * \file pk_internal.h
+ *
+ * \brief Public Key abstraction layer: wrapper functions
+ */
+/*
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#ifndef MBEDCRYPTO_PK_WRAP_H
+#define MBEDCRYPTO_PK_WRAP_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include "pk.h"
+
+struct mbedcrypto_pk_info_t
+{
+    /** Public key type */
+    mbedcrypto_pk_type_t type;
+
+    /** Type name */
+    const char *name;
+
+    /** Get key size in bits */
+    size_t (*get_bitlen)( const void * );
+
+    /** Tell if the context implements this type (e.g. ECKEY can do ECDSA) */
+    int (*can_do)( mbedcrypto_pk_type_t type );
+
+    /** Verify signature */
+    int (*verify_func)( void *ctx, mbedcrypto_md_type_t md_alg,
+                        const unsigned char *hash, size_t hash_len,
+                        const unsigned char *sig, size_t sig_len );
+
+    /** Make signature */
+    int (*sign_func)( void *ctx, mbedcrypto_md_type_t md_alg,
+                      const unsigned char *hash, size_t hash_len,
+                      unsigned char *sig, size_t *sig_len,
+                      int (*f_rng)(void *, unsigned char *, size_t),
+                      void *p_rng );
+
+    /** Decrypt message */
+    int (*decrypt_func)( void *ctx, const unsigned char *input, size_t ilen,
+                         unsigned char *output, size_t *olen, size_t osize,
+                         int (*f_rng)(void *, unsigned char *, size_t),
+                         void *p_rng );
+
+    /** Encrypt message */
+    int (*encrypt_func)( void *ctx, const unsigned char *input, size_t ilen,
+                         unsigned char *output, size_t *olen, size_t osize,
+                         int (*f_rng)(void *, unsigned char *, size_t),
+                         void *p_rng );
+
+    /** Check public-private key pair */
+    int (*check_pair_func)( const void *pub, const void *prv );
+
+    /** Allocate a new context */
+    void * (*ctx_alloc_func)( void );
+
+    /** Free the given context */
+    void (*ctx_free_func)( void *ctx );
+
+    /** Interface with the debug module */
+    void (*debug_func)( const void *ctx, mbedcrypto_pk_debug_item *items );
+
+};
+#if defined(MBEDCRYPTO_PK_RSA_ALT_SUPPORT)
+/* Container for RSA-alt */
+typedef struct
+{
+    void *key;
+    mbedcrypto_pk_rsa_alt_decrypt_func decrypt_func;
+    mbedcrypto_pk_rsa_alt_sign_func sign_func;
+    mbedcrypto_pk_rsa_alt_key_len_func key_len_func;
+} mbedcrypto_rsa_alt_context;
+#endif
+
+#if defined(MBEDCRYPTO_RSA_C)
+extern const mbedcrypto_pk_info_t mbedcrypto_rsa_info;
+#endif
+
+#if defined(MBEDCRYPTO_ECP_C)
+extern const mbedcrypto_pk_info_t mbedcrypto_eckey_info;
+extern const mbedcrypto_pk_info_t mbedcrypto_eckeydh_info;
+#endif
+
+#if defined(MBEDCRYPTO_ECDSA_C)
+extern const mbedcrypto_pk_info_t mbedcrypto_ecdsa_info;
+#endif
+
+#if defined(MBEDCRYPTO_PK_RSA_ALT_SUPPORT)
+extern const mbedcrypto_pk_info_t mbedcrypto_rsa_alt_info;
+#endif
+
+#endif /* MBEDCRYPTO_PK_WRAP_H */
diff --git a/include/mbedcrypto/pkcs11.h b/include/mbedcrypto/pkcs11.h
new file mode 100644
index 0000000..2233ec8
--- /dev/null
+++ b/include/mbedcrypto/pkcs11.h
@@ -0,0 +1,174 @@
+/**
+ * \file pkcs11.h
+ *
+ * \brief Wrapper for PKCS#11 library libpkcs11-helper
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ */
+/*
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_PKCS11_H
+#define MBEDCRYPTO_PKCS11_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_PKCS11_C)
+
+#include "x509_crt.h"
+
+#include <pkcs11-helper-1.0/pkcs11h-certificate.h>
+
+#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
+    !defined(inline) && !defined(__cplusplus)
+#define inline __inline
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Context for PKCS #11 private keys.
+ */
+typedef struct {
+        pkcs11h_certificate_t pkcs11h_cert;
+        int len;
+} mbedcrypto_pkcs11_context;
+
+/**
+ * Initialize a mbedcrypto_pkcs11_context.
+ * (Just making memory references valid.)
+ */
+void mbedcrypto_pkcs11_init( mbedcrypto_pkcs11_context *ctx );
+
+/**
+ * Fill in a Mbed Crypto certificate, based on the given PKCS11 helper certificate.
+ *
+ * \param cert          X.509 certificate to fill
+ * \param pkcs11h_cert  PKCS #11 helper certificate
+ *
+ * \return              0 on success.
+ */
+int mbedcrypto_pkcs11_x509_cert_bind( mbedcrypto_x509_crt *cert, pkcs11h_certificate_t pkcs11h_cert );
+
+/**
+ * Set up a mbedcrypto_pkcs11_context storing the given certificate. Note that the
+ * mbedcrypto_pkcs11_context will take over control of the certificate, freeing it when
+ * done.
+ *
+ * \param priv_key      Private key structure to fill.
+ * \param pkcs11_cert   PKCS #11 helper certificate
+ *
+ * \return              0 on success
+ */
+int mbedcrypto_pkcs11_priv_key_bind( mbedcrypto_pkcs11_context *priv_key,
+        pkcs11h_certificate_t pkcs11_cert );
+
+/**
+ * Free the contents of the given private key context. Note that the structure
+ * itself is not freed.
+ *
+ * \param priv_key      Private key structure to cleanup
+ */
+void mbedcrypto_pkcs11_priv_key_free( mbedcrypto_pkcs11_context *priv_key );
+
+/**
+ * \brief          Do an RSA private key decrypt, then remove the message
+ *                 padding
+ *
+ * \param ctx      PKCS #11 context
+ * \param mode     must be MBEDCRYPTO_RSA_PRIVATE, for compatibility with rsa.c's signature
+ * \param input    buffer holding the encrypted data
+ * \param output   buffer that will hold the plaintext
+ * \param olen     will contain the plaintext length
+ * \param output_max_len    maximum length of the output buffer
+ *
+ * \return         0 if successful, or an MBEDCRYPTO_ERR_RSA_XXX error code
+ *
+ * \note           The output buffer must be as large as the size
+ *                 of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise
+ *                 an error is thrown.
+ */
+int mbedcrypto_pkcs11_decrypt( mbedcrypto_pkcs11_context *ctx,
+                       int mode, size_t *olen,
+                       const unsigned char *input,
+                       unsigned char *output,
+                       size_t output_max_len );
+
+/**
+ * \brief          Do a private RSA to sign a message digest
+ *
+ * \param ctx      PKCS #11 context
+ * \param mode     must be MBEDCRYPTO_RSA_PRIVATE, for compatibility with rsa.c's signature
+ * \param md_alg   a MBEDCRYPTO_MD_XXX (use MBEDCRYPTO_MD_NONE for signing raw data)
+ * \param hashlen  message digest length (for MBEDCRYPTO_MD_NONE only)
+ * \param hash     buffer holding the message digest
+ * \param sig      buffer that will hold the ciphertext
+ *
+ * \return         0 if the signing operation was successful,
+ *                 or an MBEDCRYPTO_ERR_RSA_XXX error code
+ *
+ * \note           The "sig" buffer must be as large as the size
+ *                 of ctx->N (eg. 128 bytes if RSA-1024 is used).
+ */
+int mbedcrypto_pkcs11_sign( mbedcrypto_pkcs11_context *ctx,
+                    int mode,
+                    mbedcrypto_md_type_t md_alg,
+                    unsigned int hashlen,
+                    const unsigned char *hash,
+                    unsigned char *sig );
+
+/**
+ * SSL/TLS wrappers for PKCS#11 functions
+ */
+static inline int mbedcrypto_ssl_pkcs11_decrypt( void *ctx, int mode, size_t *olen,
+                        const unsigned char *input, unsigned char *output,
+                        size_t output_max_len )
+{
+    return mbedcrypto_pkcs11_decrypt( (mbedcrypto_pkcs11_context *) ctx, mode, olen, input, output,
+                           output_max_len );
+}
+
+static inline int mbedcrypto_ssl_pkcs11_sign( void *ctx,
+                     int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+                     int mode, mbedcrypto_md_type_t md_alg, unsigned int hashlen,
+                     const unsigned char *hash, unsigned char *sig )
+{
+    ((void) f_rng);
+    ((void) p_rng);
+    return mbedcrypto_pkcs11_sign( (mbedcrypto_pkcs11_context *) ctx, mode, md_alg,
+                        hashlen, hash, sig );
+}
+
+static inline size_t mbedcrypto_ssl_pkcs11_key_len( void *ctx )
+{
+    return ( (mbedcrypto_pkcs11_context *) ctx )->len;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDCRYPTO_PKCS11_C */
+
+#endif /* MBEDCRYPTO_PKCS11_H */
diff --git a/include/mbedcrypto/pkcs12.h b/include/mbedcrypto/pkcs12.h
new file mode 100644
index 0000000..403f20a
--- /dev/null
+++ b/include/mbedcrypto/pkcs12.h
@@ -0,0 +1,120 @@
+/**
+ * \file pkcs12.h
+ *
+ * \brief PKCS#12 Personal Information Exchange Syntax
+ */
+/*
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_PKCS12_H
+#define MBEDCRYPTO_PKCS12_H
+
+#include "md.h"
+#include "cipher.h"
+#include "asn1.h"
+
+#include <stddef.h>
+
+#define MBEDCRYPTO_ERR_PKCS12_BAD_INPUT_DATA                 -0x1F80  /**< Bad input parameters to function. */
+#define MBEDCRYPTO_ERR_PKCS12_FEATURE_UNAVAILABLE            -0x1F00  /**< Feature not available, e.g. unsupported encryption scheme. */
+#define MBEDCRYPTO_ERR_PKCS12_PBE_INVALID_FORMAT             -0x1E80  /**< PBE ASN.1 data not as expected. */
+#define MBEDCRYPTO_ERR_PKCS12_PASSWORD_MISMATCH              -0x1E00  /**< Given private key password does not allow for correct decryption. */
+
+#define MBEDCRYPTO_PKCS12_DERIVE_KEY       1   /**< encryption/decryption key */
+#define MBEDCRYPTO_PKCS12_DERIVE_IV        2   /**< initialization vector     */
+#define MBEDCRYPTO_PKCS12_DERIVE_MAC_KEY   3   /**< integrity / MAC key       */
+
+#define MBEDCRYPTO_PKCS12_PBE_DECRYPT      0
+#define MBEDCRYPTO_PKCS12_PBE_ENCRYPT      1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief            PKCS12 Password Based function (encryption / decryption)
+ *                   for pbeWithSHAAnd128BitRC4
+ *
+ * \param pbe_params an ASN1 buffer containing the pkcs-12PbeParams structure
+ * \param mode       either MBEDCRYPTO_PKCS12_PBE_ENCRYPT or MBEDCRYPTO_PKCS12_PBE_DECRYPT
+ * \param pwd        the password used (may be NULL if no password is used)
+ * \param pwdlen     length of the password (may be 0)
+ * \param input      the input data
+ * \param len        data length
+ * \param output     the output buffer
+ *
+ * \return           0 if successful, or a MBEDCRYPTO_ERR_XXX code
+ */
+int mbedcrypto_pkcs12_pbe_sha1_rc4_128( mbedcrypto_asn1_buf *pbe_params, int mode,
+                             const unsigned char *pwd,  size_t pwdlen,
+                             const unsigned char *input, size_t len,
+                             unsigned char *output );
+
+/**
+ * \brief            PKCS12 Password Based function (encryption / decryption)
+ *                   for cipher-based and mbedcrypto_md-based PBE's
+ *
+ * \param pbe_params an ASN1 buffer containing the pkcs-12PbeParams structure
+ * \param mode       either MBEDCRYPTO_PKCS12_PBE_ENCRYPT or MBEDCRYPTO_PKCS12_PBE_DECRYPT
+ * \param cipher_type the cipher used
+ * \param md_type     the mbedcrypto_md used
+ * \param pwd        the password used (may be NULL if no password is used)
+ * \param pwdlen     length of the password (may be 0)
+ * \param input      the input data
+ * \param len        data length
+ * \param output     the output buffer
+ *
+ * \return           0 if successful, or a MBEDCRYPTO_ERR_XXX code
+ */
+int mbedcrypto_pkcs12_pbe( mbedcrypto_asn1_buf *pbe_params, int mode,
+                mbedcrypto_cipher_type_t cipher_type, mbedcrypto_md_type_t md_type,
+                const unsigned char *pwd,  size_t pwdlen,
+                const unsigned char *input, size_t len,
+                unsigned char *output );
+
+/**
+ * \brief            The PKCS#12 derivation function uses a password and a salt
+ *                   to produce pseudo-random bits for a particular "purpose".
+ *
+ *                   Depending on the given id, this function can produce an
+ *                   encryption/decryption key, an nitialization vector or an
+ *                   integrity key.
+ *
+ * \param data       buffer to store the derived data in
+ * \param datalen    length to fill
+ * \param pwd        password to use (may be NULL if no password is used)
+ * \param pwdlen     length of the password (may be 0)
+ * \param salt       salt buffer to use
+ * \param saltlen    length of the salt
+ * \param mbedcrypto_md         mbedcrypto_md type to use during the derivation
+ * \param id         id that describes the purpose (can be MBEDCRYPTO_PKCS12_DERIVE_KEY,
+ *                   MBEDCRYPTO_PKCS12_DERIVE_IV or MBEDCRYPTO_PKCS12_DERIVE_MAC_KEY)
+ * \param iterations number of iterations
+ *
+ * \return          0 if successful, or a MD, BIGNUM type error.
+ */
+int mbedcrypto_pkcs12_derivation( unsigned char *data, size_t datalen,
+                       const unsigned char *pwd, size_t pwdlen,
+                       const unsigned char *salt, size_t saltlen,
+                       mbedcrypto_md_type_t mbedcrypto_md, int id, int iterations );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* pkcs12.h */
diff --git a/include/mbedcrypto/pkcs5.h b/include/mbedcrypto/pkcs5.h
new file mode 100644
index 0000000..d3921cb
--- /dev/null
+++ b/include/mbedcrypto/pkcs5.h
@@ -0,0 +1,95 @@
+/**
+ * \file pkcs5.h
+ *
+ * \brief PKCS#5 functions
+ *
+ * \author Mathias Olsson <mathias@kompetensum.com>
+ */
+/*
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_PKCS5_H
+#define MBEDCRYPTO_PKCS5_H
+
+#include "asn1.h"
+#include "md.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#define MBEDCRYPTO_ERR_PKCS5_BAD_INPUT_DATA                  -0x2f80  /**< Bad input parameters to function. */
+#define MBEDCRYPTO_ERR_PKCS5_INVALID_FORMAT                  -0x2f00  /**< Unexpected ASN.1 data. */
+#define MBEDCRYPTO_ERR_PKCS5_FEATURE_UNAVAILABLE             -0x2e80  /**< Requested encryption or digest alg not available. */
+#define MBEDCRYPTO_ERR_PKCS5_PASSWORD_MISMATCH               -0x2e00  /**< Given private key password does not allow for correct decryption. */
+
+#define MBEDCRYPTO_PKCS5_DECRYPT      0
+#define MBEDCRYPTO_PKCS5_ENCRYPT      1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          PKCS#5 PBES2 function
+ *
+ * \param pbe_params the ASN.1 algorithm parameters
+ * \param mode       either MBEDCRYPTO_PKCS5_DECRYPT or MBEDCRYPTO_PKCS5_ENCRYPT
+ * \param pwd        password to use when generating key
+ * \param pwdlen     length of password
+ * \param data       data to process
+ * \param datalen    length of data
+ * \param output     output buffer
+ *
+ * \returns        0 on success, or a MBEDCRYPTO_ERR_XXX code if verification fails.
+ */
+int mbedcrypto_pkcs5_pbes2( const mbedcrypto_asn1_buf *pbe_params, int mode,
+                 const unsigned char *pwd,  size_t pwdlen,
+                 const unsigned char *data, size_t datalen,
+                 unsigned char *output );
+
+/**
+ * \brief          PKCS#5 PBKDF2 using HMAC
+ *
+ * \param ctx      Generic HMAC context
+ * \param password Password to use when generating key
+ * \param plen     Length of password
+ * \param salt     Salt to use when generating key
+ * \param slen     Length of salt
+ * \param iteration_count       Iteration count
+ * \param key_length            Length of generated key in bytes
+ * \param output   Generated key. Must be at least as big as key_length
+ *
+ * \returns        0 on success, or a MBEDCRYPTO_ERR_XXX code if verification fails.
+ */
+int mbedcrypto_pkcs5_pbkdf2_hmac( mbedcrypto_md_context_t *ctx, const unsigned char *password,
+                       size_t plen, const unsigned char *salt, size_t slen,
+                       unsigned int iteration_count,
+                       uint32_t key_length, unsigned char *output );
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int mbedcrypto_pkcs5_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* pkcs5.h */
diff --git a/include/mbedcrypto/platform.h b/include/mbedcrypto/platform.h
new file mode 100644
index 0000000..61613f9
--- /dev/null
+++ b/include/mbedcrypto/platform.h
@@ -0,0 +1,363 @@
+/**
+ * \file platform.h
+ *
+ * \brief This file contains the definitions and functions of the
+ *        Mbed Crypto platform abstraction layer.
+ *
+ *        The platform abstraction layer removes the need for the library
+ *        to directly link to standard C library functions or operating
+ *        system services, making the library easier to port and embed.
+ *        Application developers and users of the library can provide their own
+ *        implementations of these functions, or implementations specific to
+ *        their platform, which can be statically linked to the library or
+ *        dynamically configured at runtime.
+ */
+/*
+ *  Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_PLATFORM_H
+#define MBEDCRYPTO_PLATFORM_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_HAVE_TIME)
+#include "mbedcrypto/platform_time.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \name SECTION: Module settings
+ *
+ * The configuration options you can set for this module are in this section.
+ * Either change them in config.h or define them on the compiler command line.
+ * \{
+ */
+
+#if !defined(MBEDCRYPTO_PLATFORM_NO_STD_FUNCTIONS)
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#if !defined(MBEDCRYPTO_PLATFORM_STD_SNPRINTF)
+#if defined(_WIN32)
+#define MBEDCRYPTO_PLATFORM_STD_SNPRINTF   mbedcrypto_platform_win32_snprintf /**< The default \c snprintf function to use.  */
+#else
+#define MBEDCRYPTO_PLATFORM_STD_SNPRINTF   snprintf /**< The default \c snprintf function to use.  */
+#endif
+#endif
+#if !defined(MBEDCRYPTO_PLATFORM_STD_PRINTF)
+#define MBEDCRYPTO_PLATFORM_STD_PRINTF   printf /**< The default \c printf function to use. */
+#endif
+#if !defined(MBEDCRYPTO_PLATFORM_STD_FPRINTF)
+#define MBEDCRYPTO_PLATFORM_STD_FPRINTF fprintf /**< The default \c fprintf function to use. */
+#endif
+#if !defined(MBEDCRYPTO_PLATFORM_STD_CALLOC)
+#define MBEDCRYPTO_PLATFORM_STD_CALLOC   calloc /**< The default \c calloc function to use. */
+#endif
+#if !defined(MBEDCRYPTO_PLATFORM_STD_FREE)
+#define MBEDCRYPTO_PLATFORM_STD_FREE       free /**< The default \c free function to use. */
+#endif
+#if !defined(MBEDCRYPTO_PLATFORM_STD_EXIT)
+#define MBEDCRYPTO_PLATFORM_STD_EXIT      exit /**< The default \c exit function to use. */
+#endif
+#if !defined(MBEDCRYPTO_PLATFORM_STD_TIME)
+#define MBEDCRYPTO_PLATFORM_STD_TIME       time    /**< The default \c time function to use. */
+#endif
+#if !defined(MBEDCRYPTO_PLATFORM_STD_EXIT_SUCCESS)
+#define MBEDCRYPTO_PLATFORM_STD_EXIT_SUCCESS  EXIT_SUCCESS /**< The default exit value to use. */
+#endif
+#if !defined(MBEDCRYPTO_PLATFORM_STD_EXIT_FAILURE)
+#define MBEDCRYPTO_PLATFORM_STD_EXIT_FAILURE  EXIT_FAILURE /**< The default exit value to use. */
+#endif
+#if defined(MBEDCRYPTO_FS_IO)
+#if !defined(MBEDCRYPTO_PLATFORM_STD_NV_SEED_READ)
+#define MBEDCRYPTO_PLATFORM_STD_NV_SEED_READ   mbedcrypto_platform_std_nv_seed_read
+#endif
+#if !defined(MBEDCRYPTO_PLATFORM_STD_NV_SEED_WRITE)
+#define MBEDCRYPTO_PLATFORM_STD_NV_SEED_WRITE  mbedcrypto_platform_std_nv_seed_write
+#endif
+#if !defined(MBEDCRYPTO_PLATFORM_STD_NV_SEED_FILE)
+#define MBEDCRYPTO_PLATFORM_STD_NV_SEED_FILE   "seedfile"
+#endif
+#endif /* MBEDCRYPTO_FS_IO */
+#else /* MBEDCRYPTO_PLATFORM_NO_STD_FUNCTIONS */
+#if defined(MBEDCRYPTO_PLATFORM_STD_MEM_HDR)
+#include MBEDCRYPTO_PLATFORM_STD_MEM_HDR
+#endif
+#endif /* MBEDCRYPTO_PLATFORM_NO_STD_FUNCTIONS */
+
+
+/* \} name SECTION: Module settings */
+
+/*
+ * The function pointers for calloc and free.
+ */
+#if defined(MBEDCRYPTO_PLATFORM_MEMORY)
+#if defined(MBEDCRYPTO_PLATFORM_FREE_MACRO) && \
+    defined(MBEDCRYPTO_PLATFORM_CALLOC_MACRO)
+#define mbedcrypto_free       MBEDCRYPTO_PLATFORM_FREE_MACRO
+#define mbedcrypto_calloc     MBEDCRYPTO_PLATFORM_CALLOC_MACRO
+#else
+/* For size_t */
+#include <stddef.h>
+extern void * (*mbedcrypto_calloc)( size_t n, size_t size );
+extern void (*mbedcrypto_free)( void *ptr );
+
+/**
+ * \brief               This function dynamically sets the memory-management
+ *                      functions used by the library, during runtime.
+ *
+ * \param calloc_func   The \c calloc function implementation.
+ * \param free_func     The \c free function implementation.
+ *
+ * \return              \c 0.
+ */
+int mbedcrypto_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ),
+                              void (*free_func)( void * ) );
+#endif /* MBEDCRYPTO_PLATFORM_FREE_MACRO && MBEDCRYPTO_PLATFORM_CALLOC_MACRO */
+#else /* !MBEDCRYPTO_PLATFORM_MEMORY */
+#define mbedcrypto_free       free
+#define mbedcrypto_calloc     calloc
+#endif /* MBEDCRYPTO_PLATFORM_MEMORY && !MBEDCRYPTO_PLATFORM_{FREE,CALLOC}_MACRO */
+
+/*
+ * The function pointers for fprintf
+ */
+#if defined(MBEDCRYPTO_PLATFORM_FPRINTF_ALT)
+/* We need FILE * */
+#include <stdio.h>
+extern int (*mbedcrypto_fprintf)( FILE *stream, const char *format, ... );
+
+/**
+ * \brief                This function dynamically configures the fprintf
+ *                       function that is called when the
+ *                       mbedcrypto_fprintf() function is invoked by the library.
+ *
+ * \param fprintf_func   The \c fprintf function implementation.
+ *
+ * \return               \c 0.
+ */
+int mbedcrypto_platform_set_fprintf( int (*fprintf_func)( FILE *stream, const char *,
+                                               ... ) );
+#else
+#if defined(MBEDCRYPTO_PLATFORM_FPRINTF_MACRO)
+#define mbedcrypto_fprintf    MBEDCRYPTO_PLATFORM_FPRINTF_MACRO
+#else
+#define mbedcrypto_fprintf    fprintf
+#endif /* MBEDCRYPTO_PLATFORM_FPRINTF_MACRO */
+#endif /* MBEDCRYPTO_PLATFORM_FPRINTF_ALT */
+
+/*
+ * The function pointers for printf
+ */
+#if defined(MBEDCRYPTO_PLATFORM_PRINTF_ALT)
+extern int (*mbedcrypto_printf)( const char *format, ... );
+
+/**
+ * \brief               This function dynamically configures the snprintf
+ *                      function that is called when the mbedcrypto_snprintf()
+ *                      function is invoked by the library.
+ *
+ * \param printf_func   The \c printf function implementation.
+ *
+ * \return              \c 0 on success.
+ */
+int mbedcrypto_platform_set_printf( int (*printf_func)( const char *, ... ) );
+#else /* !MBEDCRYPTO_PLATFORM_PRINTF_ALT */
+#if defined(MBEDCRYPTO_PLATFORM_PRINTF_MACRO)
+#define mbedcrypto_printf     MBEDCRYPTO_PLATFORM_PRINTF_MACRO
+#else
+#define mbedcrypto_printf     printf
+#endif /* MBEDCRYPTO_PLATFORM_PRINTF_MACRO */
+#endif /* MBEDCRYPTO_PLATFORM_PRINTF_ALT */
+
+/*
+ * The function pointers for snprintf
+ *
+ * The snprintf implementation should conform to C99:
+ * - it *must* always correctly zero-terminate the buffer
+ *   (except when n == 0, then it must leave the buffer untouched)
+ * - however it is acceptable to return -1 instead of the required length when
+ *   the destination buffer is too short.
+ */
+#if defined(_WIN32)
+/* For Windows (inc. MSYS2), we provide our own fixed implementation */
+int mbedcrypto_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... );
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_SNPRINTF_ALT)
+extern int (*mbedcrypto_snprintf)( char * s, size_t n, const char * format, ... );
+
+/**
+ * \brief                 This function allows configuring a custom
+ *                        \c snprintf function pointer.
+ *
+ * \param snprintf_func   The \c snprintf function implementation.
+ *
+ * \return                \c 0 on success.
+ */
+int mbedcrypto_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n,
+                                                 const char * format, ... ) );
+#else /* MBEDCRYPTO_PLATFORM_SNPRINTF_ALT */
+#if defined(MBEDCRYPTO_PLATFORM_SNPRINTF_MACRO)
+#define mbedcrypto_snprintf   MBEDCRYPTO_PLATFORM_SNPRINTF_MACRO
+#else
+#define mbedcrypto_snprintf   MBEDCRYPTO_PLATFORM_STD_SNPRINTF
+#endif /* MBEDCRYPTO_PLATFORM_SNPRINTF_MACRO */
+#endif /* MBEDCRYPTO_PLATFORM_SNPRINTF_ALT */
+
+/*
+ * The function pointers for exit
+ */
+#if defined(MBEDCRYPTO_PLATFORM_EXIT_ALT)
+extern void (*mbedcrypto_exit)( int status );
+
+/**
+ * \brief             This function dynamically configures the exit
+ *                    function that is called when the mbedcrypto_exit()
+ *                    function is invoked by the library.
+ *
+ * \param exit_func   The \c exit function implementation.
+ *
+ * \return            \c 0 on success.
+ */
+int mbedcrypto_platform_set_exit( void (*exit_func)( int status ) );
+#else
+#if defined(MBEDCRYPTO_PLATFORM_EXIT_MACRO)
+#define mbedcrypto_exit   MBEDCRYPTO_PLATFORM_EXIT_MACRO
+#else
+#define mbedcrypto_exit   exit
+#endif /* MBEDCRYPTO_PLATFORM_EXIT_MACRO */
+#endif /* MBEDCRYPTO_PLATFORM_EXIT_ALT */
+
+/*
+ * The default exit values
+ */
+#if defined(MBEDCRYPTO_PLATFORM_STD_EXIT_SUCCESS)
+#define MBEDCRYPTO_EXIT_SUCCESS MBEDCRYPTO_PLATFORM_STD_EXIT_SUCCESS
+#else
+#define MBEDCRYPTO_EXIT_SUCCESS 0
+#endif
+#if defined(MBEDCRYPTO_PLATFORM_STD_EXIT_FAILURE)
+#define MBEDCRYPTO_EXIT_FAILURE MBEDCRYPTO_PLATFORM_STD_EXIT_FAILURE
+#else
+#define MBEDCRYPTO_EXIT_FAILURE 1
+#endif
+
+/*
+ * The function pointers for reading from and writing a seed file to
+ * Non-Volatile storage (NV) in a platform-independent way
+ *
+ * Only enabled when the NV seed entropy source is enabled
+ */
+#if defined(MBEDCRYPTO_ENTROPY_NV_SEED)
+#if !defined(MBEDCRYPTO_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDCRYPTO_FS_IO)
+/* Internal standard platform definitions */
+int mbedcrypto_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len );
+int mbedcrypto_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len );
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_NV_SEED_ALT)
+extern int (*mbedcrypto_nv_seed_read)( unsigned char *buf, size_t buf_len );
+extern int (*mbedcrypto_nv_seed_write)( unsigned char *buf, size_t buf_len );
+
+/**
+ * \brief   This function allows configuring custom seed file writing and
+ *          reading functions.
+ *
+ * \param   nv_seed_read_func   The seed reading function implementation.
+ * \param   nv_seed_write_func  The seed writing function implementation.
+ *
+ * \return  \c 0 on success.
+ */
+int mbedcrypto_platform_set_nv_seed(
+            int (*nv_seed_read_func)( unsigned char *buf, size_t buf_len ),
+            int (*nv_seed_write_func)( unsigned char *buf, size_t buf_len )
+            );
+#else
+#if defined(MBEDCRYPTO_PLATFORM_NV_SEED_READ_MACRO) && \
+    defined(MBEDCRYPTO_PLATFORM_NV_SEED_WRITE_MACRO)
+#define mbedcrypto_nv_seed_read    MBEDCRYPTO_PLATFORM_NV_SEED_READ_MACRO
+#define mbedcrypto_nv_seed_write   MBEDCRYPTO_PLATFORM_NV_SEED_WRITE_MACRO
+#else
+#define mbedcrypto_nv_seed_read    mbedcrypto_platform_std_nv_seed_read
+#define mbedcrypto_nv_seed_write   mbedcrypto_platform_std_nv_seed_write
+#endif
+#endif /* MBEDCRYPTO_PLATFORM_NV_SEED_ALT */
+#endif /* MBEDCRYPTO_ENTROPY_NV_SEED */
+
+#if !defined(MBEDCRYPTO_PLATFORM_SETUP_TEARDOWN_ALT)
+
+/**
+ * \brief   The platform context structure.
+ *
+ * \note    This structure may be used to assist platform-specific
+ *          setup or teardown operations.
+ */
+typedef struct {
+    char dummy; /**< A placeholder member, as empty structs are not portable. */
+}
+mbedcrypto_platform_context;
+
+#else
+#include "platform_alt.h"
+#endif /* !MBEDCRYPTO_PLATFORM_SETUP_TEARDOWN_ALT */
+
+/**
+ * \brief   This function performs any platform-specific initialization
+ *          operations.
+ *
+ * \note    This function should be called before any other library functions.
+ *
+ *          Its implementation is platform-specific, and unless
+ *          platform-specific code is provided, it does nothing.
+ *
+ * \note    The usage and necessity of this function is dependent on the platform.
+ *
+ * \param   ctx     The platform context.
+ *
+ * \return  \c 0 on success.
+ */
+int mbedcrypto_platform_setup( mbedcrypto_platform_context *ctx );
+/**
+ * \brief   This function performs any platform teardown operations.
+ *
+ * \note    This function should be called after every other Mbed Crypto module
+ *          has been correctly freed using the appropriate free function.
+ *
+ *          Its implementation is platform-specific, and unless
+ *          platform-specific code is provided, it does nothing.
+ *
+ * \note    The usage and necessity of this function is dependent on the platform.
+ *
+ * \param   ctx     The platform context.
+ *
+ */
+void mbedcrypto_platform_teardown( mbedcrypto_platform_context *ctx );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* platform.h */
diff --git a/include/mbedcrypto/platform_util.h b/include/mbedcrypto/platform_util.h
new file mode 100644
index 0000000..5375313
--- /dev/null
+++ b/include/mbedcrypto/platform_util.h
@@ -0,0 +1,62 @@
+/**
+ * \file platform_util.h
+ *
+ * \brief Common and shared functions used by multiple modules in the Mbed Crypto
+ *        library.
+ */
+/*
+ *  Copyright (C) 2018, Arm Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_PLATFORM_UTIL_H
+#define MBEDCRYPTO_PLATFORM_UTIL_H
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief       Securely zeroize a buffer
+ *
+ *              The function is meant to wipe the data contained in a buffer so
+ *              that it can no longer be recovered even if the program memory
+ *              is later compromised. Call this function on sensitive data
+ *              stored on the stack before returning from a function, and on
+ *              sensitive data stored on the heap before freeing the heap
+ *              object.
+ *
+ *              It is extremely difficult to guarantee that calls to
+ *              mbedcrypto_platform_zeroize() are not removed by aggressive
+ *              compiler optimizations in a portable way. For this reason, Mbed
+ *              TLS provides the configuration option
+ *              MBEDCRYPTO_PLATFORM_ZEROIZE_ALT, which allows users to configure
+ *              mbedcrypto_platform_zeroize() to use a suitable implementation for
+ *              their platform and needs
+ *
+ * \param buf   Buffer to be zeroized
+ * \param len   Length of the buffer in bytes
+ *
+ */
+void mbedcrypto_platform_zeroize( void *buf, size_t len );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDCRYPTO_PLATFORM_UTIL_H */
diff --git a/include/mbedcrypto/ripemd160.h b/include/mbedcrypto/ripemd160.h
new file mode 100644
index 0000000..ca245fb
--- /dev/null
+++ b/include/mbedcrypto/ripemd160.h
@@ -0,0 +1,231 @@
+/**
+ * \file ripemd160.h
+ *
+ * \brief RIPE MD-160 message digest
+ */
+/*
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_RIPEMD160_H
+#define MBEDCRYPTO_RIPEMD160_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+#define MBEDCRYPTO_ERR_RIPEMD160_HW_ACCEL_FAILED             -0x0031  /**< RIPEMD160 hardware accelerator failed */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDCRYPTO_RIPEMD160_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief          RIPEMD-160 context structure
+ */
+typedef struct
+{
+    uint32_t total[2];          /*!< number of bytes processed  */
+    uint32_t state[5];          /*!< intermediate digest state  */
+    unsigned char buffer[64];   /*!< data block being processed */
+}
+mbedcrypto_ripemd160_context;
+
+#else  /* MBEDCRYPTO_RIPEMD160_ALT */
+#include "ripemd160.h"
+#endif /* MBEDCRYPTO_RIPEMD160_ALT */
+
+/**
+ * \brief          Initialize RIPEMD-160 context
+ *
+ * \param ctx      RIPEMD-160 context to be initialized
+ */
+void mbedcrypto_ripemd160_init( mbedcrypto_ripemd160_context *ctx );
+
+/**
+ * \brief          Clear RIPEMD-160 context
+ *
+ * \param ctx      RIPEMD-160 context to be cleared
+ */
+void mbedcrypto_ripemd160_free( mbedcrypto_ripemd160_context *ctx );
+
+/**
+ * \brief          Clone (the state of) an RIPEMD-160 context
+ *
+ * \param dst      The destination context
+ * \param src      The context to be cloned
+ */
+void mbedcrypto_ripemd160_clone( mbedcrypto_ripemd160_context *dst,
+                        const mbedcrypto_ripemd160_context *src );
+
+/**
+ * \brief          RIPEMD-160 context setup
+ *
+ * \param ctx      context to be initialized
+ *
+ * \return         0 if successful
+ */
+int mbedcrypto_ripemd160_starts_ret( mbedcrypto_ripemd160_context *ctx );
+
+/**
+ * \brief          RIPEMD-160 process buffer
+ *
+ * \param ctx      RIPEMD-160 context
+ * \param input    buffer holding the data
+ * \param ilen     length of the input data
+ *
+ * \return         0 if successful
+ */
+int mbedcrypto_ripemd160_update_ret( mbedcrypto_ripemd160_context *ctx,
+                                  const unsigned char *input,
+                                  size_t ilen );
+
+/**
+ * \brief          RIPEMD-160 final digest
+ *
+ * \param ctx      RIPEMD-160 context
+ * \param output   RIPEMD-160 checksum result
+ *
+ * \return         0 if successful
+ */
+int mbedcrypto_ripemd160_finish_ret( mbedcrypto_ripemd160_context *ctx,
+                                  unsigned char output[20] );
+
+/**
+ * \brief          RIPEMD-160 process data block (internal use only)
+ *
+ * \param ctx      RIPEMD-160 context
+ * \param data     buffer holding one block of data
+ *
+ * \return         0 if successful
+ */
+int mbedcrypto_internal_ripemd160_process( mbedcrypto_ripemd160_context *ctx,
+                                        const unsigned char data[64] );
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING)
+#define MBEDCRYPTO_DEPRECATED      __attribute__((deprecated))
+#else
+#define MBEDCRYPTO_DEPRECATED
+#endif
+/**
+ * \brief          RIPEMD-160 context setup
+ *
+ * \deprecated     Superseded by mbedcrypto_ripemd160_starts_ret() in 2.7.0
+ *
+ * \param ctx      context to be initialized
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_ripemd160_starts(
+                                            mbedcrypto_ripemd160_context *ctx );
+
+/**
+ * \brief          RIPEMD-160 process buffer
+ *
+ * \deprecated     Superseded by mbedcrypto_ripemd160_update_ret() in 2.7.0
+ *
+ * \param ctx      RIPEMD-160 context
+ * \param input    buffer holding the data
+ * \param ilen     length of the input data
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_ripemd160_update(
+                                                mbedcrypto_ripemd160_context *ctx,
+                                                const unsigned char *input,
+                                                size_t ilen );
+
+/**
+ * \brief          RIPEMD-160 final digest
+ *
+ * \deprecated     Superseded by mbedcrypto_ripemd160_finish_ret() in 2.7.0
+ *
+ * \param ctx      RIPEMD-160 context
+ * \param output   RIPEMD-160 checksum result
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_ripemd160_finish(
+                                                mbedcrypto_ripemd160_context *ctx,
+                                                unsigned char output[20] );
+
+/**
+ * \brief          RIPEMD-160 process data block (internal use only)
+ *
+ * \deprecated     Superseded by mbedcrypto_internal_ripemd160_process() in 2.7.0
+ *
+ * \param ctx      RIPEMD-160 context
+ * \param data     buffer holding one block of data
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_ripemd160_process(
+                                            mbedcrypto_ripemd160_context *ctx,
+                                            const unsigned char data[64] );
+
+#undef MBEDCRYPTO_DEPRECATED
+#endif /* !MBEDCRYPTO_DEPRECATED_REMOVED */
+
+/**
+ * \brief          Output = RIPEMD-160( input buffer )
+ *
+ * \param input    buffer holding the data
+ * \param ilen     length of the input data
+ * \param output   RIPEMD-160 checksum result
+ *
+ * \return         0 if successful
+ */
+int mbedcrypto_ripemd160_ret( const unsigned char *input,
+                           size_t ilen,
+                           unsigned char output[20] );
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING)
+#define MBEDCRYPTO_DEPRECATED      __attribute__((deprecated))
+#else
+#define MBEDCRYPTO_DEPRECATED
+#endif
+/**
+ * \brief          Output = RIPEMD-160( input buffer )
+ *
+ * \deprecated     Superseded by mbedcrypto_ripemd160_ret() in 2.7.0
+ *
+ * \param input    buffer holding the data
+ * \param ilen     length of the input data
+ * \param output   RIPEMD-160 checksum result
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_ripemd160( const unsigned char *input,
+                                           size_t ilen,
+                                           unsigned char output[20] );
+
+#undef MBEDCRYPTO_DEPRECATED
+#endif /* !MBEDCRYPTO_DEPRECATED_REMOVED */
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int mbedcrypto_ripemd160_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* mbedcrypto_ripemd160.h */
diff --git a/include/mbedcrypto/rsa.h b/include/mbedcrypto/rsa.h
new file mode 100644
index 0000000..0c33cae
--- /dev/null
+++ b/include/mbedcrypto/rsa.h
@@ -0,0 +1,1141 @@
+/**
+ * \file rsa.h
+ *
+ * \brief This file provides an API for the RSA public-key cryptosystem.
+ *
+ * The RSA public-key cryptosystem is defined in <em>Public-Key
+ * Cryptography Standards (PKCS) #1 v1.5: RSA Encryption</em>
+ * and <em>Public-Key Cryptography Standards (PKCS) #1 v2.1:
+ * RSA Cryptography Specifications</em>.
+ *
+ */
+/*
+ *  Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_RSA_H
+#define MBEDCRYPTO_RSA_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include "bignum.h"
+#include "md.h"
+
+#if defined(MBEDCRYPTO_THREADING_C)
+#include "threading.h"
+#endif
+
+/*
+ * RSA Error codes
+ */
+#define MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA                    -0x4080  /**< Bad input parameters to function. */
+#define MBEDCRYPTO_ERR_RSA_INVALID_PADDING                   -0x4100  /**< Input data contains invalid padding and is rejected. */
+#define MBEDCRYPTO_ERR_RSA_KEY_GEN_FAILED                    -0x4180  /**< Something failed during generation of a key. */
+#define MBEDCRYPTO_ERR_RSA_KEY_CHECK_FAILED                  -0x4200  /**< Key failed to pass the validity check of the library. */
+#define MBEDCRYPTO_ERR_RSA_PUBLIC_FAILED                     -0x4280  /**< The public key operation failed. */
+#define MBEDCRYPTO_ERR_RSA_PRIVATE_FAILED                    -0x4300  /**< The private key operation failed. */
+#define MBEDCRYPTO_ERR_RSA_VERIFY_FAILED                     -0x4380  /**< The PKCS#1 verification failed. */
+#define MBEDCRYPTO_ERR_RSA_OUTPUT_TOO_LARGE                  -0x4400  /**< The output buffer for decryption is not large enough. */
+#define MBEDCRYPTO_ERR_RSA_RNG_FAILED                        -0x4480  /**< The random generator failed to generate non-zeros. */
+#define MBEDCRYPTO_ERR_RSA_UNSUPPORTED_OPERATION             -0x4500  /**< The implementation does not offer the requested operation, for example, because of security violations or lack of functionality. */
+#define MBEDCRYPTO_ERR_RSA_HW_ACCEL_FAILED                   -0x4580  /**< RSA hardware accelerator failed. */
+
+/*
+ * RSA constants
+ */
+#define MBEDCRYPTO_RSA_PUBLIC      0 /**< Request private key operation. */
+#define MBEDCRYPTO_RSA_PRIVATE     1 /**< Request public key operation. */
+
+#define MBEDCRYPTO_RSA_PKCS_V15    0 /**< Use PKCS#1 v1.5 encoding. */
+#define MBEDCRYPTO_RSA_PKCS_V21    1 /**< Use PKCS#1 v2.1 encoding. */
+
+#define MBEDCRYPTO_RSA_SIGN        1 /**< Identifier for RSA signature operations. */
+#define MBEDCRYPTO_RSA_CRYPT       2 /**< Identifier for RSA encryption and decryption operations. */
+
+#define MBEDCRYPTO_RSA_SALT_LEN_ANY    -1
+
+/*
+ * The above constants may be used even if the RSA module is compile out,
+ * eg for alternative (PKCS#11) RSA implemenations in the PK layers.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDCRYPTO_RSA_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief   The RSA context structure.
+ *
+ * \note    Direct manipulation of the members of this structure
+ *          is deprecated. All manipulation should instead be done through
+ *          the public interface functions.
+ */
+typedef struct
+{
+    int ver;                    /*!<  Always 0.*/
+    size_t len;                 /*!<  The size of \p N in Bytes. */
+
+    mbedcrypto_mpi N;              /*!<  The public modulus. */
+    mbedcrypto_mpi E;              /*!<  The public exponent. */
+
+    mbedcrypto_mpi D;              /*!<  The private exponent. */
+    mbedcrypto_mpi P;              /*!<  The first prime factor. */
+    mbedcrypto_mpi Q;              /*!<  The second prime factor. */
+
+    mbedcrypto_mpi DP;             /*!<  <code>D % (P - 1)</code>. */
+    mbedcrypto_mpi DQ;             /*!<  <code>D % (Q - 1)</code>. */
+    mbedcrypto_mpi QP;             /*!<  <code>1 / (Q % P)</code>. */
+
+    mbedcrypto_mpi RN;             /*!<  cached <code>R^2 mod N</code>. */
+
+    mbedcrypto_mpi RP;             /*!<  cached <code>R^2 mod P</code>. */
+    mbedcrypto_mpi RQ;             /*!<  cached <code>R^2 mod Q</code>. */
+
+    mbedcrypto_mpi Vi;             /*!<  The cached blinding value. */
+    mbedcrypto_mpi Vf;             /*!<  The cached un-blinding value. */
+
+    int padding;                /*!< Selects padding mode:
+                                     #MBEDCRYPTO_RSA_PKCS_V15 for 1.5 padding and
+                                     #MBEDCRYPTO_RSA_PKCS_V21 for OAEP or PSS. */
+    int hash_id;                /*!< Hash identifier of mbedcrypto_md_type_t type,
+                                     as specified in md.h for use in the MGF
+                                     mask generating function used in the
+                                     EME-OAEP and EMSA-PSS encodings. */
+#if defined(MBEDCRYPTO_THREADING_C)
+    mbedcrypto_threading_mutex_t mutex;    /*!<  Thread-safety mutex. */
+#endif
+}
+mbedcrypto_rsa_context;
+
+#else  /* MBEDCRYPTO_RSA_ALT */
+#include "rsa_alt.h"
+#endif /* MBEDCRYPTO_RSA_ALT */
+
+/**
+ * \brief          This function initializes an RSA context.
+ *
+ * \note           Set padding to #MBEDCRYPTO_RSA_PKCS_V21 for the RSAES-OAEP
+ *                 encryption scheme and the RSASSA-PSS signature scheme.
+ *
+ * \note           The \p hash_id parameter is ignored when using
+ *                 #MBEDCRYPTO_RSA_PKCS_V15 padding.
+ *
+ * \note           The choice of padding mode is strictly enforced for private key
+ *                 operations, since there might be security concerns in
+ *                 mixing padding modes. For public key operations it is
+ *                 a default value, which can be overriden by calling specific
+ *                 \c rsa_rsaes_xxx or \c rsa_rsassa_xxx functions.
+ *
+ * \note           The hash selected in \p hash_id is always used for OEAP
+ *                 encryption. For PSS signatures, it is always used for
+ *                 making signatures, but can be overriden for verifying them.
+ *                 If set to #MBEDCRYPTO_MD_NONE, it is always overriden.
+ *
+ * \param ctx      The RSA context to initialize.
+ * \param padding  Selects padding mode: #MBEDCRYPTO_RSA_PKCS_V15 or
+ *                 #MBEDCRYPTO_RSA_PKCS_V21.
+ * \param hash_id  The hash identifier of #mbedcrypto_md_type_t type, if
+ *                 \p padding is #MBEDCRYPTO_RSA_PKCS_V21.
+ */
+void mbedcrypto_rsa_init( mbedcrypto_rsa_context *ctx,
+                       int padding,
+                       int hash_id);
+
+/**
+ * \brief          This function imports a set of core parameters into an
+ *                 RSA context.
+ *
+ * \note           This function can be called multiple times for successive
+ *                 imports, if the parameters are not simultaneously present.
+ *
+ *                 Any sequence of calls to this function should be followed
+ *                 by a call to mbedcrypto_rsa_complete(), which checks and
+ *                 completes the provided information to a ready-for-use
+ *                 public or private RSA key.
+ *
+ * \note           See mbedcrypto_rsa_complete() for more information on which
+ *                 parameters are necessary to set up a private or public
+ *                 RSA key.
+ *
+ * \note           The imported parameters are copied and need not be preserved
+ *                 for the lifetime of the RSA context being set up.
+ *
+ * \param ctx      The initialized RSA context to store the parameters in.
+ * \param N        The RSA modulus, or NULL.
+ * \param P        The first prime factor of \p N, or NULL.
+ * \param Q        The second prime factor of \p N, or NULL.
+ * \param D        The private exponent, or NULL.
+ * \param E        The public exponent, or NULL.
+ *
+ * \return         \c 0 on success.
+ * \return         A non-zero error code on failure.
+ */
+int mbedcrypto_rsa_import( mbedcrypto_rsa_context *ctx,
+                        const mbedcrypto_mpi *N,
+                        const mbedcrypto_mpi *P, const mbedcrypto_mpi *Q,
+                        const mbedcrypto_mpi *D, const mbedcrypto_mpi *E );
+
+/**
+ * \brief          This function imports core RSA parameters, in raw big-endian
+ *                 binary format, into an RSA context.
+ *
+ * \note           This function can be called multiple times for successive
+ *                 imports, if the parameters are not simultaneously present.
+ *
+ *                 Any sequence of calls to this function should be followed
+ *                 by a call to mbedcrypto_rsa_complete(), which checks and
+ *                 completes the provided information to a ready-for-use
+ *                 public or private RSA key.
+ *
+ * \note           See mbedcrypto_rsa_complete() for more information on which
+ *                 parameters are necessary to set up a private or public
+ *                 RSA key.
+ *
+ * \note           The imported parameters are copied and need not be preserved
+ *                 for the lifetime of the RSA context being set up.
+ *
+ * \param ctx      The initialized RSA context to store the parameters in.
+ * \param N        The RSA modulus, or NULL.
+ * \param N_len    The Byte length of \p N, ignored if \p N == NULL.
+ * \param P        The first prime factor of \p N, or NULL.
+ * \param P_len    The Byte length of \p P, ignored if \p P == NULL.
+ * \param Q        The second prime factor of \p N, or NULL.
+ * \param Q_len    The Byte length of \p Q, ignored if \p Q == NULL.
+ * \param D        The private exponent, or NULL.
+ * \param D_len    The Byte length of \p D, ignored if \p D == NULL.
+ * \param E        The public exponent, or NULL.
+ * \param E_len    The Byte length of \p E, ignored if \p E == NULL.
+ *
+ * \return         \c 0 on success.
+ * \return         A non-zero error code on failure.
+ */
+int mbedcrypto_rsa_import_raw( mbedcrypto_rsa_context *ctx,
+                            unsigned char const *N, size_t N_len,
+                            unsigned char const *P, size_t P_len,
+                            unsigned char const *Q, size_t Q_len,
+                            unsigned char const *D, size_t D_len,
+                            unsigned char const *E, size_t E_len );
+
+/**
+ * \brief          This function completes an RSA context from
+ *                 a set of imported core parameters.
+ *
+ *                 To setup an RSA public key, precisely \p N and \p E
+ *                 must have been imported.
+ *
+ *                 To setup an RSA private key, sufficient information must
+ *                 be present for the other parameters to be derivable.
+ *
+ *                 The default implementation supports the following:
+ *                 <ul><li>Derive \p P, \p Q from \p N, \p D, \p E.</li>
+ *                 <li>Derive \p N, \p D from \p P, \p Q, \p E.</li></ul>
+ *                 Alternative implementations need not support these.
+ *
+ *                 If this function runs successfully, it guarantees that
+ *                 the RSA context can be used for RSA operations without
+ *                 the risk of failure or crash.
+ *
+ * \warning        This function need not perform consistency checks
+ *                 for the imported parameters. In particular, parameters that
+ *                 are not needed by the implementation might be silently
+ *                 discarded and left unchecked. To check the consistency
+ *                 of the key material, see mbedcrypto_rsa_check_privkey().
+ *
+ * \param ctx      The initialized RSA context holding imported parameters.
+ *
+ * \return         \c 0 on success.
+ * \return         #MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA if the attempted derivations
+ *                 failed.
+ *
+ */
+int mbedcrypto_rsa_complete( mbedcrypto_rsa_context *ctx );
+
+/**
+ * \brief          This function exports the core parameters of an RSA key.
+ *
+ *                 If this function runs successfully, the non-NULL buffers
+ *                 pointed to by \p N, \p P, \p Q, \p D, and \p E are fully
+ *                 written, with additional unused space filled leading by
+ *                 zero Bytes.
+ *
+ *                 Possible reasons for returning
+ *                 #MBEDCRYPTO_ERR_RSA_UNSUPPORTED_OPERATION:<ul>
+ *                 <li>An alternative RSA implementation is in use, which
+ *                 stores the key externally, and either cannot or should
+ *                 not export it into RAM.</li>
+ *                 <li>A SW or HW implementation might not support a certain
+ *                 deduction. For example, \p P, \p Q from \p N, \p D,
+ *                 and \p E if the former are not part of the
+ *                 implementation.</li></ul>
+ *
+ *                 If the function fails due to an unsupported operation,
+ *                 the RSA context stays intact and remains usable.
+ *
+ * \param ctx      The initialized RSA context.
+ * \param N        The MPI to hold the RSA modulus, or NULL.
+ * \param P        The MPI to hold the first prime factor of \p N, or NULL.
+ * \param Q        The MPI to hold the second prime factor of \p N, or NULL.
+ * \param D        The MPI to hold the private exponent, or NULL.
+ * \param E        The MPI to hold the public exponent, or NULL.
+ *
+ * \return         \c 0 on success.
+ * \return         #MBEDCRYPTO_ERR_RSA_UNSUPPORTED_OPERATION if exporting the
+ *                 requested parameters cannot be done due to missing
+ *                 functionality or because of security policies.
+ * \return         A non-zero return code on any other failure.
+ *
+ */
+int mbedcrypto_rsa_export( const mbedcrypto_rsa_context *ctx,
+                        mbedcrypto_mpi *N, mbedcrypto_mpi *P, mbedcrypto_mpi *Q,
+                        mbedcrypto_mpi *D, mbedcrypto_mpi *E );
+
+/**
+ * \brief          This function exports core parameters of an RSA key
+ *                 in raw big-endian binary format.
+ *
+ *                 If this function runs successfully, the non-NULL buffers
+ *                 pointed to by \p N, \p P, \p Q, \p D, and \p E are fully
+ *                 written, with additional unused space filled leading by
+ *                 zero Bytes.
+ *
+ *                 Possible reasons for returning
+ *                 #MBEDCRYPTO_ERR_RSA_UNSUPPORTED_OPERATION:<ul>
+ *                 <li>An alternative RSA implementation is in use, which
+ *                 stores the key externally, and either cannot or should
+ *                 not export it into RAM.</li>
+ *                 <li>A SW or HW implementation might not support a certain
+ *                 deduction. For example, \p P, \p Q from \p N, \p D,
+ *                 and \p E if the former are not part of the
+ *                 implementation.</li></ul>
+ *                 If the function fails due to an unsupported operation,
+ *                 the RSA context stays intact and remains usable.
+ *
+ * \note           The length parameters are ignored if the corresponding
+ *                 buffer pointers are NULL.
+ *
+ * \param ctx      The initialized RSA context.
+ * \param N        The Byte array to store the RSA modulus, or NULL.
+ * \param N_len    The size of the buffer for the modulus.
+ * \param P        The Byte array to hold the first prime factor of \p N, or
+ *                 NULL.
+ * \param P_len    The size of the buffer for the first prime factor.
+ * \param Q        The Byte array to hold the second prime factor of \p N, or
+ *                 NULL.
+ * \param Q_len    The size of the buffer for the second prime factor.
+ * \param D        The Byte array to hold the private exponent, or NULL.
+ * \param D_len    The size of the buffer for the private exponent.
+ * \param E        The Byte array to hold the public exponent, or NULL.
+ * \param E_len    The size of the buffer for the public exponent.
+ *
+ * \return         \c 0 on success.
+ * \return         #MBEDCRYPTO_ERR_RSA_UNSUPPORTED_OPERATION if exporting the
+ *                 requested parameters cannot be done due to missing
+ *                 functionality or because of security policies.
+ * \return         A non-zero return code on any other failure.
+ */
+int mbedcrypto_rsa_export_raw( const mbedcrypto_rsa_context *ctx,
+                            unsigned char *N, size_t N_len,
+                            unsigned char *P, size_t P_len,
+                            unsigned char *Q, size_t Q_len,
+                            unsigned char *D, size_t D_len,
+                            unsigned char *E, size_t E_len );
+
+/**
+ * \brief          This function exports CRT parameters of a private RSA key.
+ *
+ * \note           Alternative RSA implementations not using CRT-parameters
+ *                 internally can implement this function based on
+ *                 mbedcrypto_rsa_deduce_opt().
+ *
+ * \param ctx      The initialized RSA context.
+ * \param DP       The MPI to hold D modulo P-1, or NULL.
+ * \param DQ       The MPI to hold D modulo Q-1, or NULL.
+ * \param QP       The MPI to hold modular inverse of Q modulo P, or NULL.
+ *
+ * \return         \c 0 on success.
+ * \return         A non-zero error code on failure.
+ *
+ */
+int mbedcrypto_rsa_export_crt( const mbedcrypto_rsa_context *ctx,
+                            mbedcrypto_mpi *DP, mbedcrypto_mpi *DQ, mbedcrypto_mpi *QP );
+
+/**
+ * \brief          This function sets padding for an already initialized RSA
+ *                 context. See mbedcrypto_rsa_init() for details.
+ *
+ * \param ctx      The RSA context to be set.
+ * \param padding  Selects padding mode: #MBEDCRYPTO_RSA_PKCS_V15 or
+ *                 #MBEDCRYPTO_RSA_PKCS_V21.
+ * \param hash_id  The #MBEDCRYPTO_RSA_PKCS_V21 hash identifier.
+ */
+void mbedcrypto_rsa_set_padding( mbedcrypto_rsa_context *ctx, int padding,
+                              int hash_id);
+
+/**
+ * \brief          This function retrieves the length of RSA modulus in Bytes.
+ *
+ * \param ctx      The initialized RSA context.
+ *
+ * \return         The length of the RSA modulus in Bytes.
+ *
+ */
+size_t mbedcrypto_rsa_get_len( const mbedcrypto_rsa_context *ctx );
+
+/**
+ * \brief          This function retrieves the length of the RSA modulus in bits.
+ *
+ * \param ctx      The initialized RSA context.
+ *
+ * \return         The length of the RSA modulus in bits.
+ *
+ */
+size_t mbedcrypto_rsa_get_bitlen( const mbedcrypto_rsa_context *ctx );
+
+/**
+ * \brief          This function generates an RSA keypair.
+ *
+ * \note           mbedcrypto_rsa_init() must be called before this function,
+ *                 to set up the RSA context.
+ *
+ * \param ctx      The RSA context used to hold the key.
+ * \param f_rng    The RNG function.
+ * \param p_rng    The RNG context.
+ * \param nbits    The size of the public key in bits.
+ * \param exponent The public exponent. For example, 65537.
+ *
+ * \return         \c 0 on success.
+ * \return         An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ */
+int mbedcrypto_rsa_gen_key( mbedcrypto_rsa_context *ctx,
+                         int (*f_rng)(void *, unsigned char *, size_t),
+                         void *p_rng,
+                         unsigned int nbits, int exponent );
+
+/**
+ * \brief          This function checks if a context contains at least an RSA
+ *                 public key.
+ *
+ *                 If the function runs successfully, it is guaranteed that
+ *                 enough information is present to perform an RSA public key
+ *                 operation using mbedcrypto_rsa_public().
+ *
+ * \param ctx      The RSA context to check.
+ *
+ * \return         \c 0 on success.
+ * \return         An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ *
+ */
+int mbedcrypto_rsa_check_pubkey( const mbedcrypto_rsa_context *ctx );
+
+/**
+ * \brief      This function checks if a context contains an RSA private key
+ *             and perform basic consistency checks.
+ *
+ * \note       The consistency checks performed by this function not only
+ *             ensure that mbedcrypto_rsa_private() can be called successfully
+ *             on the given context, but that the various parameters are
+ *             mutually consistent with high probability, in the sense that
+ *             mbedcrypto_rsa_public() and mbedcrypto_rsa_private() are inverses.
+ *
+ * \warning    This function should catch accidental misconfigurations
+ *             like swapping of parameters, but it cannot establish full
+ *             trust in neither the quality nor the consistency of the key
+ *             material that was used to setup the given RSA context:
+ *             <ul><li>Consistency: Imported parameters that are irrelevant
+ *             for the implementation might be silently dropped. If dropped,
+ *             the current function does not have access to them,
+ *             and therefore cannot check them. See mbedcrypto_rsa_complete().
+ *             If you want to check the consistency of the entire
+ *             content of an PKCS1-encoded RSA private key, for example, you
+ *             should use mbedcrypto_rsa_validate_params() before setting
+ *             up the RSA context.
+ *             Additionally, if the implementation performs empirical checks,
+ *             these checks substantiate but do not guarantee consistency.</li>
+ *             <li>Quality: This function is not expected to perform
+ *             extended quality assessments like checking that the prime
+ *             factors are safe. Additionally, it is the responsibility of the
+ *             user to ensure the trustworthiness of the source of his RSA
+ *             parameters, which goes beyond what is effectively checkable
+ *             by the library.</li></ul>
+ *
+ * \param ctx  The RSA context to check.
+ *
+ * \return     \c 0 on success.
+ * \return     An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ */
+int mbedcrypto_rsa_check_privkey( const mbedcrypto_rsa_context *ctx );
+
+/**
+ * \brief          This function checks a public-private RSA key pair.
+ *
+ *                 It checks each of the contexts, and makes sure they match.
+ *
+ * \param pub      The RSA context holding the public key.
+ * \param prv      The RSA context holding the private key.
+ *
+ * \return         \c 0 on success.
+ * \return         An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ */
+int mbedcrypto_rsa_check_pub_priv( const mbedcrypto_rsa_context *pub,
+                                const mbedcrypto_rsa_context *prv );
+
+/**
+ * \brief          This function performs an RSA public key operation.
+ *
+ * \note           This function does not handle message padding.
+ *
+ * \note           Make sure to set \p input[0] = 0 or ensure that
+ *                 input is smaller than \p N.
+ *
+ * \note           The input and output buffers must be large
+ *                 enough. For example, 128 Bytes if RSA-1024 is used.
+ *
+ * \param ctx      The RSA context.
+ * \param input    The input buffer.
+ * \param output   The output buffer.
+ *
+ * \return         \c 0 on success.
+ * \return         An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ */
+int mbedcrypto_rsa_public( mbedcrypto_rsa_context *ctx,
+                const unsigned char *input,
+                unsigned char *output );
+
+/**
+ * \brief          This function performs an RSA private key operation.
+ *
+ * \note           The input and output buffers must be large
+ *                 enough. For example, 128 Bytes if RSA-1024 is used.
+ *
+ * \note           Blinding is used if and only if a PRNG is provided.
+ *
+ * \note           If blinding is used, both the base of exponentation
+ *                 and the exponent are blinded, providing protection
+ *                 against some side-channel attacks.
+ *
+ * \warning        It is deprecated and a security risk to not provide
+ *                 a PRNG here and thereby prevent the use of blinding.
+ *                 Future versions of the library may enforce the presence
+ *                 of a PRNG.
+ *
+ * \param ctx      The RSA context.
+ * \param f_rng    The RNG function. Needed for blinding.
+ * \param p_rng    The RNG context.
+ * \param input    The input buffer.
+ * \param output   The output buffer.
+ *
+ * \return         \c 0 on success.
+ * \return         An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ *
+ */
+int mbedcrypto_rsa_private( mbedcrypto_rsa_context *ctx,
+                 int (*f_rng)(void *, unsigned char *, size_t),
+                 void *p_rng,
+                 const unsigned char *input,
+                 unsigned char *output );
+
+/**
+ * \brief          This function adds the message padding, then performs an RSA
+ *                 operation.
+ *
+ *                 It is the generic wrapper for performing a PKCS#1 encryption
+ *                 operation using the \p mode from the context.
+ *
+ * \note           The input and output buffers must be as large as the size
+ *                 of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
+ *
+ * \deprecated     It is deprecated and discouraged to call this function
+ *                 in #MBEDCRYPTO_RSA_PRIVATE mode. Future versions of the library
+ *                 are likely to remove the \p mode argument and have it
+ *                 implicitly set to #MBEDCRYPTO_RSA_PUBLIC.
+ *
+ * \note           Alternative implementations of RSA need not support
+ *                 mode being set to #MBEDCRYPTO_RSA_PRIVATE and might instead
+ *                 return #MBEDCRYPTO_ERR_RSA_UNSUPPORTED_OPERATION.
+ *
+ * \param ctx      The RSA context.
+ * \param f_rng    The RNG function. Needed for padding, PKCS#1 v2.1
+ *                 encoding, and #MBEDCRYPTO_RSA_PRIVATE.
+ * \param p_rng    The RNG context.
+ * \param mode     #MBEDCRYPTO_RSA_PUBLIC or #MBEDCRYPTO_RSA_PRIVATE.
+ * \param ilen     The length of the plaintext.
+ * \param input    The buffer holding the data to encrypt.
+ * \param output   The buffer used to hold the ciphertext.
+ *
+ * \return         \c 0 on success.
+ * \return         An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ */
+int mbedcrypto_rsa_pkcs1_encrypt( mbedcrypto_rsa_context *ctx,
+                       int (*f_rng)(void *, unsigned char *, size_t),
+                       void *p_rng,
+                       int mode, size_t ilen,
+                       const unsigned char *input,
+                       unsigned char *output );
+
+/**
+ * \brief          This function performs a PKCS#1 v1.5 encryption operation
+ *                 (RSAES-PKCS1-v1_5-ENCRYPT).
+ *
+ * \note           The output buffer must be as large as the size
+ *                 of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
+ *
+ * \deprecated     It is deprecated and discouraged to call this function
+ *                 in #MBEDCRYPTO_RSA_PRIVATE mode. Future versions of the library
+ *                 are likely to remove the \p mode argument and have it
+ *                 implicitly set to #MBEDCRYPTO_RSA_PUBLIC.
+ *
+ * \note           Alternative implementations of RSA need not support
+ *                 mode being set to #MBEDCRYPTO_RSA_PRIVATE and might instead
+ *                 return #MBEDCRYPTO_ERR_RSA_UNSUPPORTED_OPERATION.
+ *
+ * \param ctx      The RSA context.
+ * \param f_rng    The RNG function. Needed for padding and
+ *                 #MBEDCRYPTO_RSA_PRIVATE.
+ * \param p_rng    The RNG context.
+ * \param mode     #MBEDCRYPTO_RSA_PUBLIC or #MBEDCRYPTO_RSA_PRIVATE.
+ * \param ilen     The length of the plaintext.
+ * \param input    The buffer holding the data to encrypt.
+ * \param output   The buffer used to hold the ciphertext.
+ *
+ * \return         \c 0 on success.
+ * \return         An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ */
+int mbedcrypto_rsa_rsaes_pkcs1_v15_encrypt( mbedcrypto_rsa_context *ctx,
+                                 int (*f_rng)(void *, unsigned char *, size_t),
+                                 void *p_rng,
+                                 int mode, size_t ilen,
+                                 const unsigned char *input,
+                                 unsigned char *output );
+
+/**
+ * \brief            This function performs a PKCS#1 v2.1 OAEP encryption
+ *                   operation (RSAES-OAEP-ENCRYPT).
+ *
+ * \note             The output buffer must be as large as the size
+ *                   of ctx->N. For example, 128 Bytes if RSA-1024 is used.
+ *
+ * \deprecated       It is deprecated and discouraged to call this function
+ *                   in #MBEDCRYPTO_RSA_PRIVATE mode. Future versions of the library
+ *                   are likely to remove the \p mode argument and have it
+ *                   implicitly set to #MBEDCRYPTO_RSA_PUBLIC.
+ *
+ * \note             Alternative implementations of RSA need not support
+ *                   mode being set to #MBEDCRYPTO_RSA_PRIVATE and might instead
+ *                   return #MBEDCRYPTO_ERR_RSA_UNSUPPORTED_OPERATION.
+ *
+ * \param ctx        The RSA context.
+ * \param f_rng      The RNG function. Needed for padding and PKCS#1 v2.1
+ *                   encoding and #MBEDCRYPTO_RSA_PRIVATE.
+ * \param p_rng      The RNG context.
+ * \param mode       #MBEDCRYPTO_RSA_PUBLIC or #MBEDCRYPTO_RSA_PRIVATE.
+ * \param label      The buffer holding the custom label to use.
+ * \param label_len  The length of the label.
+ * \param ilen       The length of the plaintext.
+ * \param input      The buffer holding the data to encrypt.
+ * \param output     The buffer used to hold the ciphertext.
+ *
+ * \return           \c 0 on success.
+ * \return           An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ */
+int mbedcrypto_rsa_rsaes_oaep_encrypt( mbedcrypto_rsa_context *ctx,
+                            int (*f_rng)(void *, unsigned char *, size_t),
+                            void *p_rng,
+                            int mode,
+                            const unsigned char *label, size_t label_len,
+                            size_t ilen,
+                            const unsigned char *input,
+                            unsigned char *output );
+
+/**
+ * \brief          This function performs an RSA operation, then removes the
+ *                 message padding.
+ *
+ *                 It is the generic wrapper for performing a PKCS#1 decryption
+ *                 operation using the \p mode from the context.
+ *
+ * \note           The output buffer length \c output_max_len should be
+ *                 as large as the size \p ctx->len of \p ctx->N (for example,
+ *                 128 Bytes if RSA-1024 is used) to be able to hold an
+ *                 arbitrary decrypted message. If it is not large enough to
+ *                 hold the decryption of the particular ciphertext provided,
+ *                 the function returns \c MBEDCRYPTO_ERR_RSA_OUTPUT_TOO_LARGE.
+ *
+ * \note           The input buffer must be as large as the size
+ *                 of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
+ *
+ * \deprecated     It is deprecated and discouraged to call this function
+ *                 in #MBEDCRYPTO_RSA_PUBLIC mode. Future versions of the library
+ *                 are likely to remove the \p mode argument and have it
+ *                 implicitly set to #MBEDCRYPTO_RSA_PRIVATE.
+ *
+ * \note           Alternative implementations of RSA need not support
+ *                 mode being set to #MBEDCRYPTO_RSA_PUBLIC and might instead
+ *                 return #MBEDCRYPTO_ERR_RSA_UNSUPPORTED_OPERATION.
+ *
+ * \param ctx      The RSA context.
+ * \param f_rng    The RNG function. Only needed for #MBEDCRYPTO_RSA_PRIVATE.
+ * \param p_rng    The RNG context.
+ * \param mode     #MBEDCRYPTO_RSA_PUBLIC or #MBEDCRYPTO_RSA_PRIVATE.
+ * \param olen     The length of the plaintext.
+ * \param input    The buffer holding the encrypted data.
+ * \param output   The buffer used to hold the plaintext.
+ * \param output_max_len    The maximum length of the output buffer.
+ *
+ * \return         \c 0 on success.
+ * \return         An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ */
+int mbedcrypto_rsa_pkcs1_decrypt( mbedcrypto_rsa_context *ctx,
+                       int (*f_rng)(void *, unsigned char *, size_t),
+                       void *p_rng,
+                       int mode, size_t *olen,
+                       const unsigned char *input,
+                       unsigned char *output,
+                       size_t output_max_len );
+
+/**
+ * \brief          This function performs a PKCS#1 v1.5 decryption
+ *                 operation (RSAES-PKCS1-v1_5-DECRYPT).
+ *
+ * \note           The output buffer length \c output_max_len should be
+ *                 as large as the size \p ctx->len of \p ctx->N, for example,
+ *                 128 Bytes if RSA-1024 is used, to be able to hold an
+ *                 arbitrary decrypted message. If it is not large enough to
+ *                 hold the decryption of the particular ciphertext provided,
+ *                 the function returns #MBEDCRYPTO_ERR_RSA_OUTPUT_TOO_LARGE.
+ *
+ * \note           The input buffer must be as large as the size
+ *                 of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
+ *
+ * \deprecated     It is deprecated and discouraged to call this function
+ *                 in #MBEDCRYPTO_RSA_PUBLIC mode. Future versions of the library
+ *                 are likely to remove the \p mode argument and have it
+ *                 implicitly set to #MBEDCRYPTO_RSA_PRIVATE.
+ *
+ * \note           Alternative implementations of RSA need not support
+ *                 mode being set to #MBEDCRYPTO_RSA_PUBLIC and might instead
+ *                 return #MBEDCRYPTO_ERR_RSA_UNSUPPORTED_OPERATION.
+ *
+ * \param ctx      The RSA context.
+ * \param f_rng    The RNG function. Only needed for #MBEDCRYPTO_RSA_PRIVATE.
+ * \param p_rng    The RNG context.
+ * \param mode     #MBEDCRYPTO_RSA_PUBLIC or #MBEDCRYPTO_RSA_PRIVATE.
+ * \param olen     The length of the plaintext.
+ * \param input    The buffer holding the encrypted data.
+ * \param output   The buffer to hold the plaintext.
+ * \param output_max_len    The maximum length of the output buffer.
+ *
+ * \return         \c 0 on success.
+ * \return         An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ *
+ */
+int mbedcrypto_rsa_rsaes_pkcs1_v15_decrypt( mbedcrypto_rsa_context *ctx,
+                                 int (*f_rng)(void *, unsigned char *, size_t),
+                                 void *p_rng,
+                                 int mode, size_t *olen,
+                                 const unsigned char *input,
+                                 unsigned char *output,
+                                 size_t output_max_len );
+
+/**
+ * \brief            This function performs a PKCS#1 v2.1 OAEP decryption
+ *                   operation (RSAES-OAEP-DECRYPT).
+ *
+ * \note             The output buffer length \c output_max_len should be
+ *                   as large as the size \p ctx->len of \p ctx->N, for
+ *                   example, 128 Bytes if RSA-1024 is used, to be able to
+ *                   hold an arbitrary decrypted message. If it is not
+ *                   large enough to hold the decryption of the particular
+ *                   ciphertext provided, the function returns
+ *                   #MBEDCRYPTO_ERR_RSA_OUTPUT_TOO_LARGE.
+ *
+ * \note             The input buffer must be as large as the size
+ *                   of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
+ *
+ * \deprecated       It is deprecated and discouraged to call this function
+ *                   in #MBEDCRYPTO_RSA_PUBLIC mode. Future versions of the library
+ *                   are likely to remove the \p mode argument and have it
+ *                   implicitly set to #MBEDCRYPTO_RSA_PRIVATE.
+ *
+ * \note             Alternative implementations of RSA need not support
+ *                   mode being set to #MBEDCRYPTO_RSA_PUBLIC and might instead
+ *                   return #MBEDCRYPTO_ERR_RSA_UNSUPPORTED_OPERATION.
+ *
+ * \param ctx        The RSA context.
+ * \param f_rng      The RNG function. Only needed for #MBEDCRYPTO_RSA_PRIVATE.
+ * \param p_rng      The RNG context.
+ * \param mode       #MBEDCRYPTO_RSA_PUBLIC or #MBEDCRYPTO_RSA_PRIVATE.
+ * \param label      The buffer holding the custom label to use.
+ * \param label_len  The length of the label.
+ * \param olen       The length of the plaintext.
+ * \param input      The buffer holding the encrypted data.
+ * \param output     The buffer to hold the plaintext.
+ * \param output_max_len    The maximum length of the output buffer.
+ *
+ * \return         \c 0 on success.
+ * \return         An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ */
+int mbedcrypto_rsa_rsaes_oaep_decrypt( mbedcrypto_rsa_context *ctx,
+                            int (*f_rng)(void *, unsigned char *, size_t),
+                            void *p_rng,
+                            int mode,
+                            const unsigned char *label, size_t label_len,
+                            size_t *olen,
+                            const unsigned char *input,
+                            unsigned char *output,
+                            size_t output_max_len );
+
+/**
+ * \brief          This function performs a private RSA operation to sign
+ *                 a message digest using PKCS#1.
+ *
+ *                 It is the generic wrapper for performing a PKCS#1
+ *                 signature using the \p mode from the context.
+ *
+ * \note           The \p sig buffer must be as large as the size
+ *                 of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
+ *
+ * \note           For PKCS#1 v2.1 encoding, see comments on
+ *                 mbedcrypto_rsa_rsassa_pss_sign() for details on
+ *                 \p md_alg and \p hash_id.
+ *
+ * \deprecated     It is deprecated and discouraged to call this function
+ *                 in #MBEDCRYPTO_RSA_PUBLIC mode. Future versions of the library
+ *                 are likely to remove the \p mode argument and have it
+ *                 implicitly set to #MBEDCRYPTO_RSA_PRIVATE.
+ *
+ * \note           Alternative implementations of RSA need not support
+ *                 mode being set to #MBEDCRYPTO_RSA_PUBLIC and might instead
+ *                 return #MBEDCRYPTO_ERR_RSA_UNSUPPORTED_OPERATION.
+ *
+ * \param ctx      The RSA context.
+ * \param f_rng    The RNG function. Needed for PKCS#1 v2.1 encoding and for
+ *                 #MBEDCRYPTO_RSA_PRIVATE.
+ * \param p_rng    The RNG context.
+ * \param mode     #MBEDCRYPTO_RSA_PUBLIC or #MBEDCRYPTO_RSA_PRIVATE.
+ * \param md_alg   The message-digest algorithm used to hash the original data.
+ *                 Use #MBEDCRYPTO_MD_NONE for signing raw data.
+ * \param hashlen  The length of the message digest. Only used if \p md_alg is #MBEDCRYPTO_MD_NONE.
+ * \param hash     The buffer holding the message digest.
+ * \param sig      The buffer to hold the ciphertext.
+ *
+ * \return         \c 0 if the signing operation was successful.
+ * \return         An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ */
+int mbedcrypto_rsa_pkcs1_sign( mbedcrypto_rsa_context *ctx,
+                    int (*f_rng)(void *, unsigned char *, size_t),
+                    void *p_rng,
+                    int mode,
+                    mbedcrypto_md_type_t md_alg,
+                    unsigned int hashlen,
+                    const unsigned char *hash,
+                    unsigned char *sig );
+
+/**
+ * \brief          This function performs a PKCS#1 v1.5 signature
+ *                 operation (RSASSA-PKCS1-v1_5-SIGN).
+ *
+ * \note           The \p sig buffer must be as large as the size
+ *                 of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
+ *
+ * \deprecated     It is deprecated and discouraged to call this function
+ *                 in #MBEDCRYPTO_RSA_PUBLIC mode. Future versions of the library
+ *                 are likely to remove the \p mode argument and have it
+ *                 implicitly set to #MBEDCRYPTO_RSA_PRIVATE.
+ *
+ * \note           Alternative implementations of RSA need not support
+ *                 mode being set to #MBEDCRYPTO_RSA_PUBLIC and might instead
+ *                 return #MBEDCRYPTO_ERR_RSA_UNSUPPORTED_OPERATION.
+ *
+ * \param ctx      The RSA context.
+ * \param f_rng    The RNG function. Only needed for #MBEDCRYPTO_RSA_PRIVATE.
+ * \param p_rng    The RNG context.
+ * \param mode     #MBEDCRYPTO_RSA_PUBLIC or #MBEDCRYPTO_RSA_PRIVATE.
+ * \param md_alg   The message-digest algorithm used to hash the original data.
+ *                 Use #MBEDCRYPTO_MD_NONE for signing raw data.
+ * \param hashlen  The length of the message digest. Only used if \p md_alg is #MBEDCRYPTO_MD_NONE.
+ * \param hash     The buffer holding the message digest.
+ * \param sig      The buffer to hold the ciphertext.
+ *
+ * \return         \c 0 if the signing operation was successful.
+ * \return         An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ */
+int mbedcrypto_rsa_rsassa_pkcs1_v15_sign( mbedcrypto_rsa_context *ctx,
+                               int (*f_rng)(void *, unsigned char *, size_t),
+                               void *p_rng,
+                               int mode,
+                               mbedcrypto_md_type_t md_alg,
+                               unsigned int hashlen,
+                               const unsigned char *hash,
+                               unsigned char *sig );
+
+/**
+ * \brief          This function performs a PKCS#1 v2.1 PSS signature
+ *                 operation (RSASSA-PSS-SIGN).
+ *
+ * \note           The \p sig buffer must be as large as the size
+ *                 of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
+ *
+ * \note           The \p hash_id in the RSA context is the one used for the
+ *                 encoding. \p md_alg in the function call is the type of hash
+ *                 that is encoded. According to <em>RFC-3447: Public-Key
+ *                 Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography
+ *                 Specifications</em> it is advised to keep both hashes the
+ *                 same.
+ *
+ * \deprecated     It is deprecated and discouraged to call this function
+ *                 in #MBEDCRYPTO_RSA_PUBLIC mode. Future versions of the library
+ *                 are likely to remove the \p mode argument and have it
+ *                 implicitly set to #MBEDCRYPTO_RSA_PRIVATE.
+ *
+ * \note           Alternative implementations of RSA need not support
+ *                 mode being set to #MBEDCRYPTO_RSA_PUBLIC and might instead
+ *                 return #MBEDCRYPTO_ERR_RSA_UNSUPPORTED_OPERATION.
+ *
+ * \param ctx      The RSA context.
+ * \param f_rng    The RNG function. Needed for PKCS#1 v2.1 encoding and for
+ *                 #MBEDCRYPTO_RSA_PRIVATE.
+ * \param p_rng    The RNG context.
+ * \param mode     #MBEDCRYPTO_RSA_PUBLIC or #MBEDCRYPTO_RSA_PRIVATE.
+ * \param md_alg   The message-digest algorithm used to hash the original data.
+ *                 Use #MBEDCRYPTO_MD_NONE for signing raw data.
+ * \param hashlen  The length of the message digest. Only used if \p md_alg is #MBEDCRYPTO_MD_NONE.
+ * \param hash     The buffer holding the message digest.
+ * \param sig      The buffer to hold the ciphertext.
+ *
+ * \return         \c 0 if the signing operation was successful.
+ * \return         An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ */
+int mbedcrypto_rsa_rsassa_pss_sign( mbedcrypto_rsa_context *ctx,
+                         int (*f_rng)(void *, unsigned char *, size_t),
+                         void *p_rng,
+                         int mode,
+                         mbedcrypto_md_type_t md_alg,
+                         unsigned int hashlen,
+                         const unsigned char *hash,
+                         unsigned char *sig );
+
+/**
+ * \brief          This function performs a public RSA operation and checks
+ *                 the message digest.
+ *
+ *                 This is the generic wrapper for performing a PKCS#1
+ *                 verification using the mode from the context.
+ *
+ * \note           The \p sig buffer must be as large as the size
+ *                 of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
+ *
+ * \note           For PKCS#1 v2.1 encoding, see comments on
+ *                 mbedcrypto_rsa_rsassa_pss_verify() about \p md_alg and
+ *                 \p hash_id.
+ *
+ * \deprecated     It is deprecated and discouraged to call this function
+ *                 in #MBEDCRYPTO_RSA_PRIVATE mode. Future versions of the library
+ *                 are likely to remove the \p mode argument and have it
+ *                 set to #MBEDCRYPTO_RSA_PUBLIC.
+ *
+ * \note           Alternative implementations of RSA need not support
+ *                 mode being set to #MBEDCRYPTO_RSA_PRIVATE and might instead
+ *                 return #MBEDCRYPTO_ERR_RSA_UNSUPPORTED_OPERATION.
+ *
+ * \param ctx      The RSA public key context.
+ * \param f_rng    The RNG function. Only needed for #MBEDCRYPTO_RSA_PRIVATE.
+ * \param p_rng    The RNG context.
+ * \param mode     #MBEDCRYPTO_RSA_PUBLIC or #MBEDCRYPTO_RSA_PRIVATE.
+ * \param md_alg   The message-digest algorithm used to hash the original data.
+ *                 Use #MBEDCRYPTO_MD_NONE for signing raw data.
+ * \param hashlen  The length of the message digest. Only used if \p md_alg is #MBEDCRYPTO_MD_NONE.
+ * \param hash     The buffer holding the message digest.
+ * \param sig      The buffer holding the ciphertext.
+ *
+ * \return         \c 0 if the verify operation was successful.
+ * \return         An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ */
+int mbedcrypto_rsa_pkcs1_verify( mbedcrypto_rsa_context *ctx,
+                      int (*f_rng)(void *, unsigned char *, size_t),
+                      void *p_rng,
+                      int mode,
+                      mbedcrypto_md_type_t md_alg,
+                      unsigned int hashlen,
+                      const unsigned char *hash,
+                      const unsigned char *sig );
+
+/**
+ * \brief          This function performs a PKCS#1 v1.5 verification
+ *                 operation (RSASSA-PKCS1-v1_5-VERIFY).
+ *
+ * \note           The \p sig buffer must be as large as the size
+ *                 of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
+ *
+ * \deprecated     It is deprecated and discouraged to call this function
+ *                 in #MBEDCRYPTO_RSA_PRIVATE mode. Future versions of the library
+ *                 are likely to remove the \p mode argument and have it
+ *                 set to #MBEDCRYPTO_RSA_PUBLIC.
+ *
+ * \note           Alternative implementations of RSA need not support
+ *                 mode being set to #MBEDCRYPTO_RSA_PRIVATE and might instead
+ *                 return #MBEDCRYPTO_ERR_RSA_UNSUPPORTED_OPERATION.
+ *
+ * \param ctx      The RSA public key context.
+ * \param f_rng    The RNG function. Only needed for #MBEDCRYPTO_RSA_PRIVATE.
+ * \param p_rng    The RNG context.
+ * \param mode     #MBEDCRYPTO_RSA_PUBLIC or #MBEDCRYPTO_RSA_PRIVATE.
+ * \param md_alg   The message-digest algorithm used to hash the original data.
+ *                 Use #MBEDCRYPTO_MD_NONE for signing raw data.
+ * \param hashlen  The length of the message digest. Only used if \p md_alg is #MBEDCRYPTO_MD_NONE.
+ * \param hash     The buffer holding the message digest.
+ * \param sig      The buffer holding the ciphertext.
+ *
+ * \return         \c 0 if the verify operation was successful.
+ * \return         An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ */
+int mbedcrypto_rsa_rsassa_pkcs1_v15_verify( mbedcrypto_rsa_context *ctx,
+                                 int (*f_rng)(void *, unsigned char *, size_t),
+                                 void *p_rng,
+                                 int mode,
+                                 mbedcrypto_md_type_t md_alg,
+                                 unsigned int hashlen,
+                                 const unsigned char *hash,
+                                 const unsigned char *sig );
+
+/**
+ * \brief          This function performs a PKCS#1 v2.1 PSS verification
+ *                 operation (RSASSA-PSS-VERIFY).
+ *
+ *                 The hash function for the MGF mask generating function
+ *                 is that specified in the RSA context.
+ *
+ * \note           The \p sig buffer must be as large as the size
+ *                 of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
+ *
+ * \note           The \p hash_id in the RSA context is the one used for the
+ *                 verification. \p md_alg in the function call is the type of
+ *                 hash that is verified. According to <em>RFC-3447: Public-Key
+ *                 Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography
+ *                 Specifications</em> it is advised to keep both hashes the
+ *                 same. If \p hash_id in the RSA context is unset,
+ *                 the \p md_alg from the function call is used.
+ *
+ * \deprecated     It is deprecated and discouraged to call this function
+ *                 in #MBEDCRYPTO_RSA_PRIVATE mode. Future versions of the library
+ *                 are likely to remove the \p mode argument and have it
+ *                 implicitly set to #MBEDCRYPTO_RSA_PUBLIC.
+ *
+ * \note           Alternative implementations of RSA need not support
+ *                 mode being set to #MBEDCRYPTO_RSA_PRIVATE and might instead
+ *                 return #MBEDCRYPTO_ERR_RSA_UNSUPPORTED_OPERATION.
+ *
+ * \param ctx      The RSA public key context.
+ * \param f_rng    The RNG function. Only needed for #MBEDCRYPTO_RSA_PRIVATE.
+ * \param p_rng    The RNG context.
+ * \param mode     #MBEDCRYPTO_RSA_PUBLIC or #MBEDCRYPTO_RSA_PRIVATE.
+ * \param md_alg   The message-digest algorithm used to hash the original data.
+ *                 Use #MBEDCRYPTO_MD_NONE for signing raw data.
+ * \param hashlen  The length of the message digest. Only used if \p md_alg is #MBEDCRYPTO_MD_NONE.
+ * \param hash     The buffer holding the message digest.
+ * \param sig      The buffer holding the ciphertext.
+ *
+ * \return         \c 0 if the verify operation was successful.
+ * \return         An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ */
+int mbedcrypto_rsa_rsassa_pss_verify( mbedcrypto_rsa_context *ctx,
+                           int (*f_rng)(void *, unsigned char *, size_t),
+                           void *p_rng,
+                           int mode,
+                           mbedcrypto_md_type_t md_alg,
+                           unsigned int hashlen,
+                           const unsigned char *hash,
+                           const unsigned char *sig );
+
+/**
+ * \brief          This function performs a PKCS#1 v2.1 PSS verification
+ *                 operation (RSASSA-PSS-VERIFY).
+ *
+ *                 The hash function for the MGF mask generating function
+ *                 is that specified in \p mgf1_hash_id.
+ *
+ * \note           The \p sig buffer must be as large as the size
+ *                 of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
+ *
+ * \note           The \p hash_id in the RSA context is ignored.
+ *
+ * \param ctx      The RSA public key context.
+ * \param f_rng    The RNG function. Only needed for #MBEDCRYPTO_RSA_PRIVATE.
+ * \param p_rng    The RNG context.
+ * \param mode     #MBEDCRYPTO_RSA_PUBLIC or #MBEDCRYPTO_RSA_PRIVATE.
+ * \param md_alg   The message-digest algorithm used to hash the original data.
+ *                 Use #MBEDCRYPTO_MD_NONE for signing raw data.
+ * \param hashlen  The length of the message digest. Only used if \p md_alg is
+ *                 #MBEDCRYPTO_MD_NONE.
+ * \param hash     The buffer holding the message digest.
+ * \param mgf1_hash_id       The message digest used for mask generation.
+ * \param expected_salt_len  The length of the salt used in padding. Use
+ *                           #MBEDCRYPTO_RSA_SALT_LEN_ANY to accept any salt length.
+ * \param sig      The buffer holding the ciphertext.
+ *
+ * \return         \c 0 if the verify operation was successful.
+ * \return         An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ */
+int mbedcrypto_rsa_rsassa_pss_verify_ext( mbedcrypto_rsa_context *ctx,
+                               int (*f_rng)(void *, unsigned char *, size_t),
+                               void *p_rng,
+                               int mode,
+                               mbedcrypto_md_type_t md_alg,
+                               unsigned int hashlen,
+                               const unsigned char *hash,
+                               mbedcrypto_md_type_t mgf1_hash_id,
+                               int expected_salt_len,
+                               const unsigned char *sig );
+
+/**
+ * \brief          This function copies the components of an RSA context.
+ *
+ * \param dst      The destination context.
+ * \param src      The source context.
+ *
+ * \return         \c 0 on success.
+ * \return         #MBEDCRYPTO_ERR_MPI_ALLOC_FAILED on memory allocation failure.
+ */
+int mbedcrypto_rsa_copy( mbedcrypto_rsa_context *dst, const mbedcrypto_rsa_context *src );
+
+/**
+ * \brief          This function frees the components of an RSA key.
+ *
+ * \param ctx      The RSA Context to free.
+ */
+void mbedcrypto_rsa_free( mbedcrypto_rsa_context *ctx );
+
+/**
+ * \brief          The RSA checkup routine.
+ *
+ * \return         \c 0 on success.
+ * \return         \c 1 on failure.
+ */
+int mbedcrypto_rsa_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* rsa.h */
diff --git a/include/mbedcrypto/rsa_internal.h b/include/mbedcrypto/rsa_internal.h
new file mode 100644
index 0000000..635fa18
--- /dev/null
+++ b/include/mbedcrypto/rsa_internal.h
@@ -0,0 +1,226 @@
+/**
+ * \file rsa_internal.h
+ *
+ * \brief Context-independent RSA helper functions
+ *
+ *  This module declares some RSA-related helper functions useful when
+ *  implementing the RSA interface. These functions are provided in a separate
+ *  compilation unit in order to make it easy for designers of alternative RSA
+ *  implementations to use them in their own code, as it is conceived that the
+ *  functionality they provide will be necessary for most complete
+ *  implementations.
+ *
+ *  End-users of Mbed Crypto who are not providing their own alternative RSA
+ *  implementations should not use these functions directly, and should instead
+ *  use only the functions declared in rsa.h.
+ *
+ *  The interface provided by this module will be maintained through LTS (Long
+ *  Term Support) branches of Mbed Crypto, but may otherwise be subject to change,
+ *  and must be considered an internal interface of the library.
+ *
+ *  There are two classes of helper functions:
+ *
+ *  (1) Parameter-generating helpers. These are:
+ *      - mbedcrypto_rsa_deduce_primes
+ *      - mbedcrypto_rsa_deduce_private_exponent
+ *      - mbedcrypto_rsa_deduce_crt
+ *       Each of these functions takes a set of core RSA parameters and
+ *       generates some other, or CRT related parameters.
+ *
+ *  (2) Parameter-checking helpers. These are:
+ *      - mbedcrypto_rsa_validate_params
+ *      - mbedcrypto_rsa_validate_crt
+ *      They take a set of core or CRT related RSA parameters and check their
+ *      validity.
+ *
+ */
+/*
+ *  Copyright (C) 2006-2017, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ *
+ */
+
+#ifndef MBEDCRYPTO_RSA_INTERNAL_H
+#define MBEDCRYPTO_RSA_INTERNAL_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include "bignum.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * \brief          Compute RSA prime moduli P, Q from public modulus N=PQ
+ *                 and a pair of private and public key.
+ *
+ * \note           This is a 'static' helper function not operating on
+ *                 an RSA context. Alternative implementations need not
+ *                 overwrite it.
+ *
+ * \param N        RSA modulus N = PQ, with P, Q to be found
+ * \param E        RSA public exponent
+ * \param D        RSA private exponent
+ * \param P        Pointer to MPI holding first prime factor of N on success
+ * \param Q        Pointer to MPI holding second prime factor of N on success
+ *
+ * \return
+ *                 - 0 if successful. In this case, P and Q constitute a
+ *                   factorization of N.
+ *                 - A non-zero error code otherwise.
+ *
+ * \note           It is neither checked that P, Q are prime nor that
+ *                 D, E are modular inverses wrt. P-1 and Q-1. For that,
+ *                 use the helper function \c mbedcrypto_rsa_validate_params.
+ *
+ */
+int mbedcrypto_rsa_deduce_primes( mbedcrypto_mpi const *N, mbedcrypto_mpi const *E,
+                               mbedcrypto_mpi const *D,
+                               mbedcrypto_mpi *P, mbedcrypto_mpi *Q );
+
+/**
+ * \brief          Compute RSA private exponent from
+ *                 prime moduli and public key.
+ *
+ * \note           This is a 'static' helper function not operating on
+ *                 an RSA context. Alternative implementations need not
+ *                 overwrite it.
+ *
+ * \param P        First prime factor of RSA modulus
+ * \param Q        Second prime factor of RSA modulus
+ * \param E        RSA public exponent
+ * \param D        Pointer to MPI holding the private exponent on success.
+ *
+ * \return
+ *                 - 0 if successful. In this case, D is set to a simultaneous
+ *                   modular inverse of E modulo both P-1 and Q-1.
+ *                 - A non-zero error code otherwise.
+ *
+ * \note           This function does not check whether P and Q are primes.
+ *
+ */
+int mbedcrypto_rsa_deduce_private_exponent( mbedcrypto_mpi const *P,
+                                         mbedcrypto_mpi const *Q,
+                                         mbedcrypto_mpi const *E,
+                                         mbedcrypto_mpi *D );
+
+
+/**
+ * \brief          Generate RSA-CRT parameters
+ *
+ * \note           This is a 'static' helper function not operating on
+ *                 an RSA context. Alternative implementations need not
+ *                 overwrite it.
+ *
+ * \param P        First prime factor of N
+ * \param Q        Second prime factor of N
+ * \param D        RSA private exponent
+ * \param DP       Output variable for D modulo P-1
+ * \param DQ       Output variable for D modulo Q-1
+ * \param QP       Output variable for the modular inverse of Q modulo P.
+ *
+ * \return         0 on success, non-zero error code otherwise.
+ *
+ * \note           This function does not check whether P, Q are
+ *                 prime and whether D is a valid private exponent.
+ *
+ */
+int mbedcrypto_rsa_deduce_crt( const mbedcrypto_mpi *P, const mbedcrypto_mpi *Q,
+                            const mbedcrypto_mpi *D, mbedcrypto_mpi *DP,
+                            mbedcrypto_mpi *DQ, mbedcrypto_mpi *QP );
+
+
+/**
+ * \brief          Check validity of core RSA parameters
+ *
+ * \note           This is a 'static' helper function not operating on
+ *                 an RSA context. Alternative implementations need not
+ *                 overwrite it.
+ *
+ * \param N        RSA modulus N = PQ
+ * \param P        First prime factor of N
+ * \param Q        Second prime factor of N
+ * \param D        RSA private exponent
+ * \param E        RSA public exponent
+ * \param f_rng    PRNG to be used for primality check, or NULL
+ * \param p_rng    PRNG context for f_rng, or NULL
+ *
+ * \return
+ *                 - 0 if the following conditions are satisfied
+ *                   if all relevant parameters are provided:
+ *                    - P prime if f_rng != NULL (%)
+ *                    - Q prime if f_rng != NULL (%)
+ *                    - 1 < N = P * Q
+ *                    - 1 < D, E < N
+ *                    - D and E are modular inverses modulo P-1 and Q-1
+ *                   (%) This is only done if MBEDCRYPTO_GENPRIME is defined.
+ *                 - A non-zero error code otherwise.
+ *
+ * \note           The function can be used with a restricted set of arguments
+ *                 to perform specific checks only. E.g., calling it with
+ *                 (-,P,-,-,-) and a PRNG amounts to a primality check for P.
+ */
+int mbedcrypto_rsa_validate_params( const mbedcrypto_mpi *N, const mbedcrypto_mpi *P,
+                                 const mbedcrypto_mpi *Q, const mbedcrypto_mpi *D,
+                                 const mbedcrypto_mpi *E,
+                                 int (*f_rng)(void *, unsigned char *, size_t),
+                                 void *p_rng );
+
+/**
+ * \brief          Check validity of RSA CRT parameters
+ *
+ * \note           This is a 'static' helper function not operating on
+ *                 an RSA context. Alternative implementations need not
+ *                 overwrite it.
+ *
+ * \param P        First prime factor of RSA modulus
+ * \param Q        Second prime factor of RSA modulus
+ * \param D        RSA private exponent
+ * \param DP       MPI to check for D modulo P-1
+ * \param DQ       MPI to check for D modulo P-1
+ * \param QP       MPI to check for the modular inverse of Q modulo P.
+ *
+ * \return
+ *                 - 0 if the following conditions are satisfied:
+ *                    - D = DP mod P-1 if P, D, DP != NULL
+ *                    - Q = DQ mod P-1 if P, D, DQ != NULL
+ *                    - QP = Q^-1 mod P if P, Q, QP != NULL
+ *                 - \c MBEDCRYPTO_ERR_RSA_KEY_CHECK_FAILED if check failed,
+ *                   potentially including \c MBEDCRYPTO_ERR_MPI_XXX if some
+ *                   MPI calculations failed.
+ *                 - \c MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA if insufficient
+ *                   data was provided to check DP, DQ or QP.
+ *
+ * \note           The function can be used with a restricted set of arguments
+ *                 to perform specific checks only. E.g., calling it with the
+ *                 parameters (P, -, D, DP, -, -) will check DP = D mod P-1.
+ */
+int mbedcrypto_rsa_validate_crt( const mbedcrypto_mpi *P,  const mbedcrypto_mpi *Q,
+                              const mbedcrypto_mpi *D,  const mbedcrypto_mpi *DP,
+                              const mbedcrypto_mpi *DQ, const mbedcrypto_mpi *QP );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* rsa_internal.h */
diff --git a/include/mbedcrypto/sha1.h b/include/mbedcrypto/sha1.h
new file mode 100644
index 0000000..9f7fe5a
--- /dev/null
+++ b/include/mbedcrypto/sha1.h
@@ -0,0 +1,324 @@
+/**
+ * \file sha1.h
+ *
+ * \brief This file contains SHA-1 definitions and functions.
+ *
+ * The Secure Hash Algorithm 1 (SHA-1) cryptographic hash function is defined in
+ * <em>FIPS 180-4: Secure Hash Standard (SHS)</em>.
+ *
+ * \warning   SHA-1 is considered a weak message digest and its use constitutes
+ *            a security risk. We recommend considering stronger message
+ *            digests instead.
+ */
+/*
+ *  Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_SHA1_H
+#define MBEDCRYPTO_SHA1_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+#define MBEDCRYPTO_ERR_SHA1_HW_ACCEL_FAILED                  -0x0035  /**< SHA-1 hardware accelerator failed */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDCRYPTO_SHA1_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief          The SHA-1 context structure.
+ *
+ * \warning        SHA-1 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ */
+typedef struct
+{
+    uint32_t total[2];          /*!< The number of Bytes processed.  */
+    uint32_t state[5];          /*!< The intermediate digest state.  */
+    unsigned char buffer[64];   /*!< The data block being processed. */
+}
+mbedcrypto_sha1_context;
+
+#else  /* MBEDCRYPTO_SHA1_ALT */
+#include "sha1_alt.h"
+#endif /* MBEDCRYPTO_SHA1_ALT */
+
+/**
+ * \brief          This function initializes a SHA-1 context.
+ *
+ * \warning        SHA-1 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ * \param ctx      The SHA-1 context to initialize.
+ *
+ */
+void mbedcrypto_sha1_init( mbedcrypto_sha1_context *ctx );
+
+/**
+ * \brief          This function clears a SHA-1 context.
+ *
+ * \warning        SHA-1 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ * \param ctx      The SHA-1 context to clear.
+ *
+ */
+void mbedcrypto_sha1_free( mbedcrypto_sha1_context *ctx );
+
+/**
+ * \brief          This function clones the state of a SHA-1 context.
+ *
+ * \warning        SHA-1 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ * \param dst      The SHA-1 context to clone to.
+ * \param src      The SHA-1 context to clone from.
+ *
+ */
+void mbedcrypto_sha1_clone( mbedcrypto_sha1_context *dst,
+                         const mbedcrypto_sha1_context *src );
+
+/**
+ * \brief          This function starts a SHA-1 checksum calculation.
+ *
+ * \warning        SHA-1 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ * \param ctx      The SHA-1 context to initialize.
+ *
+ * \return         \c 0 on success.
+ *
+ */
+int mbedcrypto_sha1_starts_ret( mbedcrypto_sha1_context *ctx );
+
+/**
+ * \brief          This function feeds an input buffer into an ongoing SHA-1
+ *                 checksum calculation.
+ *
+ * \warning        SHA-1 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ * \param ctx      The SHA-1 context.
+ * \param input    The buffer holding the input data.
+ * \param ilen     The length of the input data.
+ *
+ * \return         \c 0 on success.
+ */
+int mbedcrypto_sha1_update_ret( mbedcrypto_sha1_context *ctx,
+                             const unsigned char *input,
+                             size_t ilen );
+
+/**
+ * \brief          This function finishes the SHA-1 operation, and writes
+ *                 the result to the output buffer.
+ *
+ * \warning        SHA-1 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ * \param ctx      The SHA-1 context.
+ * \param output   The SHA-1 checksum result.
+ *
+ * \return         \c 0 on success.
+ */
+int mbedcrypto_sha1_finish_ret( mbedcrypto_sha1_context *ctx,
+                             unsigned char output[20] );
+
+/**
+ * \brief          SHA-1 process data block (internal use only).
+ *
+ * \warning        SHA-1 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ * \param ctx      The SHA-1 context.
+ * \param data     The data block being processed.
+ *
+ * \return         \c 0 on success.
+ *
+ */
+int mbedcrypto_internal_sha1_process( mbedcrypto_sha1_context *ctx,
+                                   const unsigned char data[64] );
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING)
+#define MBEDCRYPTO_DEPRECATED      __attribute__((deprecated))
+#else
+#define MBEDCRYPTO_DEPRECATED
+#endif
+/**
+ * \brief          This function starts a SHA-1 checksum calculation.
+ *
+ * \warning        SHA-1 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ * \deprecated     Superseded by mbedcrypto_sha1_starts_ret() in 2.7.0.
+ *
+ * \param ctx      The SHA-1 context to initialize.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_sha1_starts( mbedcrypto_sha1_context *ctx );
+
+/**
+ * \brief          This function feeds an input buffer into an ongoing SHA-1
+ *                 checksum calculation.
+ *
+ * \warning        SHA-1 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ * \deprecated     Superseded by mbedcrypto_sha1_update_ret() in 2.7.0.
+ *
+ * \param ctx      The SHA-1 context.
+ * \param input    The buffer holding the input data.
+ * \param ilen     The length of the input data.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_sha1_update( mbedcrypto_sha1_context *ctx,
+                                             const unsigned char *input,
+                                             size_t ilen );
+
+/**
+ * \brief          This function finishes the SHA-1 operation, and writes
+ *                 the result to the output buffer.
+ *
+ * \warning        SHA-1 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ * \deprecated     Superseded by mbedcrypto_sha1_finish_ret() in 2.7.0.
+ *
+ * \param ctx      The SHA-1 context.
+ * \param output   The SHA-1 checksum result.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_sha1_finish( mbedcrypto_sha1_context *ctx,
+                                             unsigned char output[20] );
+
+/**
+ * \brief          SHA-1 process data block (internal use only).
+ *
+ * \warning        SHA-1 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ * \deprecated     Superseded by mbedcrypto_internal_sha1_process() in 2.7.0.
+ *
+ * \param ctx      The SHA-1 context.
+ * \param data     The data block being processed.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_sha1_process( mbedcrypto_sha1_context *ctx,
+                                              const unsigned char data[64] );
+
+#undef MBEDCRYPTO_DEPRECATED
+#endif /* !MBEDCRYPTO_DEPRECATED_REMOVED */
+
+/**
+ * \brief          This function calculates the SHA-1 checksum of a buffer.
+ *
+ *                 The function allocates the context, performs the
+ *                 calculation, and frees the context.
+ *
+ *                 The SHA-1 result is calculated as
+ *                 output = SHA-1(input buffer).
+ *
+ * \warning        SHA-1 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ * \param input    The buffer holding the input data.
+ * \param ilen     The length of the input data.
+ * \param output   The SHA-1 checksum result.
+ *
+ * \return         \c 0 on success.
+ *
+ */
+int mbedcrypto_sha1_ret( const unsigned char *input,
+                      size_t ilen,
+                      unsigned char output[20] );
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING)
+#define MBEDCRYPTO_DEPRECATED      __attribute__((deprecated))
+#else
+#define MBEDCRYPTO_DEPRECATED
+#endif
+/**
+ * \brief          This function calculates the SHA-1 checksum of a buffer.
+ *
+ *                 The function allocates the context, performs the
+ *                 calculation, and frees the context.
+ *
+ *                 The SHA-1 result is calculated as
+ *                 output = SHA-1(input buffer).
+ *
+ * \warning        SHA-1 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ * \deprecated     Superseded by mbedcrypto_sha1_ret() in 2.7.0
+ *
+ * \param input    The buffer holding the input data.
+ * \param ilen     The length of the input data.
+ * \param output   The SHA-1 checksum result.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_sha1( const unsigned char *input,
+                                      size_t ilen,
+                                      unsigned char output[20] );
+
+#undef MBEDCRYPTO_DEPRECATED
+#endif /* !MBEDCRYPTO_DEPRECATED_REMOVED */
+
+/**
+ * \brief          The SHA-1 checkup routine.
+ *
+ * \warning        SHA-1 is considered a weak message digest and its use
+ *                 constitutes a security risk. We recommend considering
+ *                 stronger message digests instead.
+ *
+ * \return         \c 0 on success.
+ * \return         \c 1 on failure.
+ *
+ */
+int mbedcrypto_sha1_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* mbedcrypto_sha1.h */
diff --git a/include/mbedcrypto/sha256.h b/include/mbedcrypto/sha256.h
new file mode 100644
index 0000000..edeb157
--- /dev/null
+++ b/include/mbedcrypto/sha256.h
@@ -0,0 +1,272 @@
+/**
+ * \file sha256.h
+ *
+ * \brief This file contains SHA-224 and SHA-256 definitions and functions.
+ *
+ * The Secure Hash Algorithms 224 and 256 (SHA-224 and SHA-256) cryptographic
+ * hash functions are defined in <em>FIPS 180-4: Secure Hash Standard (SHS)</em>.
+ */
+/*
+ *  Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_SHA256_H
+#define MBEDCRYPTO_SHA256_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+#define MBEDCRYPTO_ERR_SHA256_HW_ACCEL_FAILED                -0x0037  /**< SHA-256 hardware accelerator failed */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDCRYPTO_SHA256_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief          The SHA-256 context structure.
+ *
+ *                 The structure is used both for SHA-256 and for SHA-224
+ *                 checksum calculations. The choice between these two is
+ *                 made in the call to mbedcrypto_sha256_starts_ret().
+ */
+typedef struct
+{
+    uint32_t total[2];          /*!< The number of Bytes processed.  */
+    uint32_t state[8];          /*!< The intermediate digest state.  */
+    unsigned char buffer[64];   /*!< The data block being processed. */
+    int is224;                  /*!< Determines which function to use:
+                                     0: Use SHA-256, or 1: Use SHA-224. */
+}
+mbedcrypto_sha256_context;
+
+#else  /* MBEDCRYPTO_SHA256_ALT */
+#include "sha256_alt.h"
+#endif /* MBEDCRYPTO_SHA256_ALT */
+
+/**
+ * \brief          This function initializes a SHA-256 context.
+ *
+ * \param ctx      The SHA-256 context to initialize.
+ */
+void mbedcrypto_sha256_init( mbedcrypto_sha256_context *ctx );
+
+/**
+ * \brief          This function clears a SHA-256 context.
+ *
+ * \param ctx      The SHA-256 context to clear.
+ */
+void mbedcrypto_sha256_free( mbedcrypto_sha256_context *ctx );
+
+/**
+ * \brief          This function clones the state of a SHA-256 context.
+ *
+ * \param dst      The destination context.
+ * \param src      The context to clone.
+ */
+void mbedcrypto_sha256_clone( mbedcrypto_sha256_context *dst,
+                           const mbedcrypto_sha256_context *src );
+
+/**
+ * \brief          This function starts a SHA-224 or SHA-256 checksum
+ *                 calculation.
+ *
+ * \param ctx      The context to initialize.
+ * \param is224    Determines which function to use:
+ *                 0: Use SHA-256, or 1: Use SHA-224.
+ *
+ * \return         \c 0 on success.
+ */
+int mbedcrypto_sha256_starts_ret( mbedcrypto_sha256_context *ctx, int is224 );
+
+/**
+ * \brief          This function feeds an input buffer into an ongoing
+ *                 SHA-256 checksum calculation.
+ *
+ * \param ctx      The SHA-256 context.
+ * \param input    The buffer holding the data.
+ * \param ilen     The length of the input data.
+ *
+ * \return         \c 0 on success.
+ */
+int mbedcrypto_sha256_update_ret( mbedcrypto_sha256_context *ctx,
+                               const unsigned char *input,
+                               size_t ilen );
+
+/**
+ * \brief          This function finishes the SHA-256 operation, and writes
+ *                 the result to the output buffer.
+ *
+ * \param ctx      The SHA-256 context.
+ * \param output   The SHA-224 or SHA-256 checksum result.
+ *
+ * \return         \c 0 on success.
+ */
+int mbedcrypto_sha256_finish_ret( mbedcrypto_sha256_context *ctx,
+                               unsigned char output[32] );
+
+/**
+ * \brief          This function processes a single data block within
+ *                 the ongoing SHA-256 computation. This function is for
+ *                 internal use only.
+ *
+ * \param ctx      The SHA-256 context.
+ * \param data     The buffer holding one block of data.
+ *
+ * \return         \c 0 on success.
+ */
+int mbedcrypto_internal_sha256_process( mbedcrypto_sha256_context *ctx,
+                                     const unsigned char data[64] );
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING)
+#define MBEDCRYPTO_DEPRECATED      __attribute__((deprecated))
+#else
+#define MBEDCRYPTO_DEPRECATED
+#endif
+/**
+ * \brief          This function starts a SHA-224 or SHA-256 checksum
+ *                 calculation.
+ *
+ *
+ * \deprecated     Superseded by mbedcrypto_sha256_starts_ret() in 2.7.0.
+ *
+ * \param ctx      The context to initialize.
+ * \param is224    Determines which function to use:
+ *                 0: Use SHA-256, or 1: Use SHA-224.
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_sha256_starts( mbedcrypto_sha256_context *ctx,
+                                               int is224 );
+
+/**
+ * \brief          This function feeds an input buffer into an ongoing
+ *                 SHA-256 checksum calculation.
+ *
+ * \deprecated     Superseded by mbedcrypto_sha256_update_ret() in 2.7.0.
+ *
+ * \param ctx      The SHA-256 context to initialize.
+ * \param input    The buffer holding the data.
+ * \param ilen     The length of the input data.
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_sha256_update( mbedcrypto_sha256_context *ctx,
+                                               const unsigned char *input,
+                                               size_t ilen );
+
+/**
+ * \brief          This function finishes the SHA-256 operation, and writes
+ *                 the result to the output buffer.
+ *
+ * \deprecated     Superseded by mbedcrypto_sha256_finish_ret() in 2.7.0.
+ *
+ * \param ctx      The SHA-256 context.
+ * \param output   The SHA-224 or SHA-256 checksum result.
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_sha256_finish( mbedcrypto_sha256_context *ctx,
+                                               unsigned char output[32] );
+
+/**
+ * \brief          This function processes a single data block within
+ *                 the ongoing SHA-256 computation. This function is for
+ *                 internal use only.
+ *
+ * \deprecated     Superseded by mbedcrypto_internal_sha256_process() in 2.7.0.
+ *
+ * \param ctx      The SHA-256 context.
+ * \param data     The buffer holding one block of data.
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_sha256_process( mbedcrypto_sha256_context *ctx,
+                                                const unsigned char data[64] );
+
+#undef MBEDCRYPTO_DEPRECATED
+#endif /* !MBEDCRYPTO_DEPRECATED_REMOVED */
+
+/**
+ * \brief          This function calculates the SHA-224 or SHA-256
+ *                 checksum of a buffer.
+ *
+ *                 The function allocates the context, performs the
+ *                 calculation, and frees the context.
+ *
+ *                 The SHA-256 result is calculated as
+ *                 output = SHA-256(input buffer).
+ *
+ * \param input    The buffer holding the input data.
+ * \param ilen     The length of the input data.
+ * \param output   The SHA-224 or SHA-256 checksum result.
+ * \param is224    Determines which function to use:
+ *                 0: Use SHA-256, or 1: Use SHA-224.
+ */
+int mbedcrypto_sha256_ret( const unsigned char *input,
+                        size_t ilen,
+                        unsigned char output[32],
+                        int is224 );
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING)
+#define MBEDCRYPTO_DEPRECATED      __attribute__((deprecated))
+#else
+#define MBEDCRYPTO_DEPRECATED
+#endif
+
+/**
+ * \brief          This function calculates the SHA-224 or SHA-256 checksum
+ *                 of a buffer.
+ *
+ *                 The function allocates the context, performs the
+ *                 calculation, and frees the context.
+ *
+ *                 The SHA-256 result is calculated as
+ *                 output = SHA-256(input buffer).
+ *
+ * \deprecated     Superseded by mbedcrypto_sha256_ret() in 2.7.0.
+ *
+ * \param input    The buffer holding the data.
+ * \param ilen     The length of the input data.
+ * \param output   The SHA-224 or SHA-256 checksum result.
+ * \param is224    Determines which function to use:
+ *                 0: Use SHA-256, or 1: Use SHA-224.
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_sha256( const unsigned char *input,
+                                        size_t ilen,
+                                        unsigned char output[32],
+                                        int is224 );
+
+#undef MBEDCRYPTO_DEPRECATED
+#endif /* !MBEDCRYPTO_DEPRECATED_REMOVED */
+
+/**
+ * \brief          The SHA-224 and SHA-256 checkup routine.
+ *
+ * \return         \c 0 on success.
+ * \return         \c 1 on failure.
+ */
+int mbedcrypto_sha256_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* mbedcrypto_sha256.h */
diff --git a/include/mbedcrypto/sha512.h b/include/mbedcrypto/sha512.h
new file mode 100644
index 0000000..f3f0fdf
--- /dev/null
+++ b/include/mbedcrypto/sha512.h
@@ -0,0 +1,270 @@
+/**
+ * \file sha512.h
+ * \brief This file contains SHA-384 and SHA-512 definitions and functions.
+ *
+ * The Secure Hash Algorithms 384 and 512 (SHA-384 and SHA-512) cryptographic
+ * hash functions are defined in <em>FIPS 180-4: Secure Hash Standard (SHS)</em>.
+ */
+/*
+ *  Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_SHA512_H
+#define MBEDCRYPTO_SHA512_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+#define MBEDCRYPTO_ERR_SHA512_HW_ACCEL_FAILED                -0x0039  /**< SHA-512 hardware accelerator failed */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDCRYPTO_SHA512_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief          The SHA-512 context structure.
+ *
+ *                 The structure is used both for SHA-384 and for SHA-512
+ *                 checksum calculations. The choice between these two is
+ *                 made in the call to mbedcrypto_sha512_starts_ret().
+ */
+typedef struct
+{
+    uint64_t total[2];          /*!< The number of Bytes processed. */
+    uint64_t state[8];          /*!< The intermediate digest state. */
+    unsigned char buffer[128];  /*!< The data block being processed. */
+    int is384;                  /*!< Determines which function to use:
+                                     0: Use SHA-512, or 1: Use SHA-384. */
+}
+mbedcrypto_sha512_context;
+
+#else  /* MBEDCRYPTO_SHA512_ALT */
+#include "sha512_alt.h"
+#endif /* MBEDCRYPTO_SHA512_ALT */
+
+/**
+ * \brief          This function initializes a SHA-512 context.
+ *
+ * \param ctx      The SHA-512 context to initialize.
+ */
+void mbedcrypto_sha512_init( mbedcrypto_sha512_context *ctx );
+
+/**
+ * \brief          This function clears a SHA-512 context.
+ *
+ * \param ctx      The SHA-512 context to clear.
+ */
+void mbedcrypto_sha512_free( mbedcrypto_sha512_context *ctx );
+
+/**
+ * \brief          This function clones the state of a SHA-512 context.
+ *
+ * \param dst      The destination context.
+ * \param src      The context to clone.
+ */
+void mbedcrypto_sha512_clone( mbedcrypto_sha512_context *dst,
+                           const mbedcrypto_sha512_context *src );
+
+/**
+ * \brief          This function starts a SHA-384 or SHA-512 checksum
+ *                 calculation.
+ *
+ * \param ctx      The SHA-512 context to initialize.
+ * \param is384    Determines which function to use:
+ *                 0: Use SHA-512, or 1: Use SHA-384.
+ *
+ * \return         \c 0 on success.
+ */
+int mbedcrypto_sha512_starts_ret( mbedcrypto_sha512_context *ctx, int is384 );
+
+/**
+ * \brief          This function feeds an input buffer into an ongoing
+ *                 SHA-512 checksum calculation.
+ *
+ * \param ctx      The SHA-512 context.
+ * \param input    The buffer holding the input data.
+ * \param ilen     The length of the input data.
+ *
+ * \return         \c 0 on success.
+ */
+int mbedcrypto_sha512_update_ret( mbedcrypto_sha512_context *ctx,
+                    const unsigned char *input,
+                    size_t ilen );
+
+/**
+ * \brief          This function finishes the SHA-512 operation, and writes
+ *                 the result to the output buffer. This function is for
+ *                 internal use only.
+ *
+ * \param ctx      The SHA-512 context.
+ * \param output   The SHA-384 or SHA-512 checksum result.
+ *
+ * \return         \c 0 on success.
+ */
+int mbedcrypto_sha512_finish_ret( mbedcrypto_sha512_context *ctx,
+                               unsigned char output[64] );
+
+/**
+ * \brief          This function processes a single data block within
+ *                 the ongoing SHA-512 computation.
+ *
+ * \param ctx      The SHA-512 context.
+ * \param data     The buffer holding one block of data.
+ *
+ * \return         \c 0 on success.
+ */
+int mbedcrypto_internal_sha512_process( mbedcrypto_sha512_context *ctx,
+                                     const unsigned char data[128] );
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING)
+#define MBEDCRYPTO_DEPRECATED      __attribute__((deprecated))
+#else
+#define MBEDCRYPTO_DEPRECATED
+#endif
+/**
+ * \brief          This function starts a SHA-384 or SHA-512 checksum
+ *                 calculation.
+ *
+ * \deprecated     Superseded by mbedcrypto_sha512_starts_ret() in 2.7.0
+ *
+ * \param ctx      The SHA-512 context to initialize.
+ * \param is384    Determines which function to use:
+ *                 0: Use SHA-512, or 1: Use SHA-384.
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_sha512_starts( mbedcrypto_sha512_context *ctx,
+                                               int is384 );
+
+/**
+ * \brief          This function feeds an input buffer into an ongoing
+ *                 SHA-512 checksum calculation.
+ *
+ * \deprecated     Superseded by mbedcrypto_sha512_update_ret() in 2.7.0.
+ *
+ * \param ctx      The SHA-512 context.
+ * \param input    The buffer holding the data.
+ * \param ilen     The length of the input data.
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_sha512_update( mbedcrypto_sha512_context *ctx,
+                                               const unsigned char *input,
+                                               size_t ilen );
+
+/**
+ * \brief          This function finishes the SHA-512 operation, and writes
+ *                 the result to the output buffer.
+ *
+ * \deprecated     Superseded by mbedcrypto_sha512_finish_ret() in 2.7.0.
+ *
+ * \param ctx      The SHA-512 context.
+ * \param output   The SHA-384 or SHA-512 checksum result.
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_sha512_finish( mbedcrypto_sha512_context *ctx,
+                                               unsigned char output[64] );
+
+/**
+ * \brief          This function processes a single data block within
+ *                 the ongoing SHA-512 computation. This function is for
+ *                 internal use only.
+ *
+ * \deprecated     Superseded by mbedcrypto_internal_sha512_process() in 2.7.0.
+ *
+ * \param ctx      The SHA-512 context.
+ * \param data     The buffer holding one block of data.
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_sha512_process(
+                                            mbedcrypto_sha512_context *ctx,
+                                            const unsigned char data[128] );
+
+#undef MBEDCRYPTO_DEPRECATED
+#endif /* !MBEDCRYPTO_DEPRECATED_REMOVED */
+
+/**
+ * \brief          This function calculates the SHA-512 or SHA-384
+ *                 checksum of a buffer.
+ *
+ *                 The function allocates the context, performs the
+ *                 calculation, and frees the context.
+ *
+ *                 The SHA-512 result is calculated as
+ *                 output = SHA-512(input buffer).
+ *
+ * \param input    The buffer holding the input data.
+ * \param ilen     The length of the input data.
+ * \param output   The SHA-384 or SHA-512 checksum result.
+ * \param is384    Determines which function to use:
+ *                 0: Use SHA-512, or 1: Use SHA-384.
+ *
+ * \return         \c 0 on success.
+ */
+int mbedcrypto_sha512_ret( const unsigned char *input,
+                        size_t ilen,
+                        unsigned char output[64],
+                        int is384 );
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING)
+#define MBEDCRYPTO_DEPRECATED      __attribute__((deprecated))
+#else
+#define MBEDCRYPTO_DEPRECATED
+#endif
+/**
+ * \brief          This function calculates the SHA-512 or SHA-384
+ *                 checksum of a buffer.
+ *
+ *                 The function allocates the context, performs the
+ *                 calculation, and frees the context.
+ *
+ *                 The SHA-512 result is calculated as
+ *                 output = SHA-512(input buffer).
+ *
+ * \deprecated     Superseded by mbedcrypto_sha512_ret() in 2.7.0
+ *
+ * \param input    The buffer holding the data.
+ * \param ilen     The length of the input data.
+ * \param output   The SHA-384 or SHA-512 checksum result.
+ * \param is384    Determines which function to use:
+ *                 0: Use SHA-512, or 1: Use SHA-384.
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_sha512( const unsigned char *input,
+                                        size_t ilen,
+                                        unsigned char output[64],
+                                        int is384 );
+
+#undef MBEDCRYPTO_DEPRECATED
+#endif /* !MBEDCRYPTO_DEPRECATED_REMOVED */
+ /**
+ * \brief          The SHA-384 or SHA-512 checkup routine.
+ *
+ * \return         \c 0 on success.
+ * \return         \c 1 on failure.
+ */
+int mbedcrypto_sha512_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* mbedcrypto_sha512.h */
diff --git a/include/mbedcrypto/threading.h b/include/mbedcrypto/threading.h
new file mode 100644
index 0000000..8e14f6b
--- /dev/null
+++ b/include/mbedcrypto/threading.h
@@ -0,0 +1,111 @@
+/**
+ * \file threading.h
+ *
+ * \brief Threading abstraction layer
+ */
+/*
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_THREADING_H
+#define MBEDCRYPTO_THREADING_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MBEDCRYPTO_ERR_THREADING_FEATURE_UNAVAILABLE         -0x001A  /**< The selected feature is not available. */
+#define MBEDCRYPTO_ERR_THREADING_BAD_INPUT_DATA              -0x001C  /**< Bad input parameters to function. */
+#define MBEDCRYPTO_ERR_THREADING_MUTEX_ERROR                 -0x001E  /**< Locking / unlocking / free failed with error code. */
+
+#if defined(MBEDCRYPTO_THREADING_PTHREAD)
+#include <pthread.h>
+typedef struct
+{
+    pthread_mutex_t mutex;
+    char is_valid;
+} mbedcrypto_threading_mutex_t;
+#endif
+
+#if defined(MBEDCRYPTO_THREADING_ALT)
+/* You should define the mbedcrypto_threading_mutex_t type in your header */
+#include "threading_alt.h"
+
+/**
+ * \brief           Set your alternate threading implementation function
+ *                  pointers and initialize global mutexes. If used, this
+ *                  function must be called once in the main thread before any
+ *                  other Mbed Crypto function is called, and
+ *                  mbedcrypto_threading_free_alt() must be called once in the main
+ *                  thread after all other Mbed Crypto functions.
+ *
+ * \note            mutex_init() and mutex_free() don't return a status code.
+ *                  If mutex_init() fails, it should leave its argument (the
+ *                  mutex) in a state such that mutex_lock() will fail when
+ *                  called with this argument.
+ *
+ * \param mutex_init    the init function implementation
+ * \param mutex_free    the free function implementation
+ * \param mutex_lock    the lock function implementation
+ * \param mutex_unlock  the unlock function implementation
+ */
+void mbedcrypto_threading_set_alt( void (*mutex_init)( mbedcrypto_threading_mutex_t * ),
+                       void (*mutex_free)( mbedcrypto_threading_mutex_t * ),
+                       int (*mutex_lock)( mbedcrypto_threading_mutex_t * ),
+                       int (*mutex_unlock)( mbedcrypto_threading_mutex_t * ) );
+
+/**
+ * \brief               Free global mutexes.
+ */
+void mbedcrypto_threading_free_alt( void );
+#endif /* MBEDCRYPTO_THREADING_ALT */
+
+#if defined(MBEDCRYPTO_THREADING_C)
+/*
+ * The function pointers for mutex_init, mutex_free, mutex_ and mutex_unlock
+ *
+ * All these functions are expected to work or the result will be undefined.
+ */
+extern void (*mbedcrypto_mutex_init)( mbedcrypto_threading_mutex_t *mutex );
+extern void (*mbedcrypto_mutex_free)( mbedcrypto_threading_mutex_t *mutex );
+extern int (*mbedcrypto_mutex_lock)( mbedcrypto_threading_mutex_t *mutex );
+extern int (*mbedcrypto_mutex_unlock)( mbedcrypto_threading_mutex_t *mutex );
+
+/*
+ * Global mutexes
+ */
+#if defined(MBEDCRYPTO_FS_IO)
+extern mbedcrypto_threading_mutex_t mbedcrypto_threading_readdir_mutex;
+#endif
+#if defined(MBEDCRYPTO_HAVE_TIME_DATE)
+extern mbedcrypto_threading_mutex_t mbedcrypto_threading_gmtime_mutex;
+#endif
+#endif /* MBEDCRYPTO_THREADING_C */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* threading.h */
diff --git a/include/mbedcrypto/xtea.h b/include/mbedcrypto/xtea.h
new file mode 100644
index 0000000..5db947d
--- /dev/null
+++ b/include/mbedcrypto/xtea.h
@@ -0,0 +1,133 @@
+/**
+ * \file xtea.h
+ *
+ * \brief XTEA block cipher (32-bit)
+ */
+/*
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_XTEA_H
+#define MBEDCRYPTO_XTEA_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+#define MBEDCRYPTO_XTEA_ENCRYPT     1
+#define MBEDCRYPTO_XTEA_DECRYPT     0
+
+#define MBEDCRYPTO_ERR_XTEA_INVALID_INPUT_LENGTH             -0x0028  /**< The data input has an invalid length. */
+#define MBEDCRYPTO_ERR_XTEA_HW_ACCEL_FAILED                  -0x0029  /**< XTEA hardware accelerator failed. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDCRYPTO_XTEA_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief          XTEA context structure
+ */
+typedef struct
+{
+    uint32_t k[4];       /*!< key */
+}
+mbedcrypto_xtea_context;
+
+#else  /* MBEDCRYPTO_XTEA_ALT */
+#include "xtea_alt.h"
+#endif /* MBEDCRYPTO_XTEA_ALT */
+
+/**
+ * \brief          Initialize XTEA context
+ *
+ * \param ctx      XTEA context to be initialized
+ */
+void mbedcrypto_xtea_init( mbedcrypto_xtea_context *ctx );
+
+/**
+ * \brief          Clear XTEA context
+ *
+ * \param ctx      XTEA context to be cleared
+ */
+void mbedcrypto_xtea_free( mbedcrypto_xtea_context *ctx );
+
+/**
+ * \brief          XTEA key schedule
+ *
+ * \param ctx      XTEA context to be initialized
+ * \param key      the secret key
+ */
+void mbedcrypto_xtea_setup( mbedcrypto_xtea_context *ctx, const unsigned char key[16] );
+
+/**
+ * \brief          XTEA cipher function
+ *
+ * \param ctx      XTEA context
+ * \param mode     MBEDCRYPTO_XTEA_ENCRYPT or MBEDCRYPTO_XTEA_DECRYPT
+ * \param input    8-byte input block
+ * \param output   8-byte output block
+ *
+ * \return         0 if successful
+ */
+int mbedcrypto_xtea_crypt_ecb( mbedcrypto_xtea_context *ctx,
+                    int mode,
+                    const unsigned char input[8],
+                    unsigned char output[8] );
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+/**
+ * \brief          XTEA CBC cipher function
+ *
+ * \param ctx      XTEA context
+ * \param mode     MBEDCRYPTO_XTEA_ENCRYPT or MBEDCRYPTO_XTEA_DECRYPT
+ * \param length   the length of input, multiple of 8
+ * \param iv       initialization vector for CBC mode
+ * \param input    input block
+ * \param output   output block
+ *
+ * \return         0 if successful,
+ *                 MBEDCRYPTO_ERR_XTEA_INVALID_INPUT_LENGTH if the length % 8 != 0
+ */
+int mbedcrypto_xtea_crypt_cbc( mbedcrypto_xtea_context *ctx,
+                    int mode,
+                    size_t length,
+                    unsigned char iv[8],
+                    const unsigned char *input,
+                    unsigned char *output);
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int mbedcrypto_xtea_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* xtea.h */
diff --git a/include/psa/crypto.h b/include/psa/crypto.h
new file mode 100644
index 0000000..6d31322
--- /dev/null
+++ b/include/psa/crypto.h
@@ -0,0 +1,2839 @@
+/**
+ * \file psa/crypto.h
+ * \brief Platform Security Architecture cryptography module
+ */
+/*
+ *  Copyright (C) 2018, ARM Limited, All Rights Reserved
+ *  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 PSA_CRYPTO_H
+#define PSA_CRYPTO_H
+
+#include "crypto_platform.h"
+
+#include <stddef.h>
+
+#ifdef __DOXYGEN_ONLY__
+/* This __DOXYGEN_ONLY__ block contains mock definitions for things that
+ * must be defined in the crypto_platform.h header. These mock definitions
+ * are present in this file as a convenience to generate pretty-printed
+ * documentation that includes those definitions. */
+
+/** \defgroup platform Implementation-specific definitions
+ * @{
+ */
+
+/** \brief Key slot number.
+ *
+ * This type represents key slots. It must be an unsigned integral
+ * type. The choice of type is implementation-dependent.
+ * 0 is not a valid key slot number. The meaning of other values is
+ * implementation dependent.
+ *
+ * At any given point in time, each key slot either contains a
+ * cryptographic object, or is empty. Key slots are persistent:
+ * once set, the cryptographic object remains in the key slot until
+ * explicitly destroyed.
+ */
+typedef _unsigned_integral_type_ psa_key_slot_t;
+
+/**@}*/
+#endif /* __DOXYGEN_ONLY__ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** \defgroup basic Basic definitions
+ * @{
+ */
+
+#if defined(PSA_SUCCESS)
+/* If PSA_SUCCESS is defined, assume that PSA crypto is being used
+ * together with PSA IPC, which also defines the identifier
+ * PSA_SUCCESS. We must not define PSA_SUCCESS ourselves in that case;
+ * the other error code names don't clash. Also define psa_status_t as
+ * an alias for the type used by PSA IPC. This is a temporary hack
+ * until we unify error reporting in PSA IPC and PSA crypto.
+ *
+ * Note that psa_defs.h must be included before this header!
+ */
+typedef psa_error_t psa_status_t;
+
+#else /* defined(PSA_SUCCESS) */
+
+/**
+ * \brief Function return status.
+ *
+ * This is either #PSA_SUCCESS (which is zero), indicating success,
+ * or a nonzero value indicating that an error occurred. Errors are
+ * encoded as one of the \c PSA_ERROR_xxx values defined here.
+ */
+typedef int32_t psa_status_t;
+
+/** The action was completed successfully. */
+#define PSA_SUCCESS ((psa_status_t)0)
+
+#endif /* !defined(PSA_SUCCESS) */
+
+/** An error occurred that does not correspond to any defined
+ * failure cause.
+ *
+ * Implementations may use this error code if none of the other standard
+ * error codes are applicable. */
+#define PSA_ERROR_UNKNOWN_ERROR         ((psa_status_t)1)
+
+/** The requested operation or a parameter is not supported
+ * by this implementation.
+ *
+ * Implementations should return this error code when an enumeration
+ * parameter such as a key type, algorithm, etc. is not recognized.
+ * If a combination of parameters is recognized and identified as
+ * not valid, return #PSA_ERROR_INVALID_ARGUMENT instead. */
+#define PSA_ERROR_NOT_SUPPORTED         ((psa_status_t)2)
+
+/** The requested action is denied by a policy.
+ *
+ * Implementations should return this error code when the parameters
+ * are recognized as valid and supported, and a policy explicitly
+ * denies the requested operation.
+ *
+ * If a subset of the parameters of a function call identify a
+ * forbidden operation, and another subset of the parameters are
+ * not valid or not supported, it is unspecified whether the function
+ * returns #PSA_ERROR_NOT_PERMITTED, #PSA_ERROR_NOT_SUPPORTED or
+ * #PSA_ERROR_INVALID_ARGUMENT. */
+#define PSA_ERROR_NOT_PERMITTED         ((psa_status_t)3)
+
+/** An output buffer is too small.
+ *
+ * Applications can call the \c PSA_xxx_SIZE macro listed in the function
+ * description to determine a sufficient buffer size.
+ *
+ * Implementations should preferably return this error code only
+ * in cases when performing the operation with a larger output
+ * buffer would succeed. However implementations may return this
+ * error if a function has invalid or unsupported parameters in addition
+ * to the parameters that determine the necessary output buffer size. */
+#define PSA_ERROR_BUFFER_TOO_SMALL      ((psa_status_t)4)
+
+/** A slot is occupied, but must be empty to carry out the
+ * requested action.
+ *
+ * If the slot number is invalid (i.e. the requested action could
+ * not be performed even after erasing the slot's content),
+ * implementations shall return #PSA_ERROR_INVALID_ARGUMENT instead. */
+#define PSA_ERROR_OCCUPIED_SLOT         ((psa_status_t)5)
+
+/** A slot is empty, but must be occupied to carry out the
+ * requested action.
+ *
+ * If the slot number is invalid (i.e. the requested action could
+ * not be performed even after creating appropriate content in the slot),
+ * implementations shall return #PSA_ERROR_INVALID_ARGUMENT instead. */
+#define PSA_ERROR_EMPTY_SLOT            ((psa_status_t)6)
+
+/** The requested action cannot be performed in the current state.
+ *
+ * Multipart operations return this error when one of the
+ * functions is called out of sequence. Refer to the function
+ * descriptions for permitted sequencing of functions.
+ *
+ * Implementations shall not return this error code to indicate
+ * that a key slot is occupied when it needs to be free or vice versa,
+ * but shall return #PSA_ERROR_OCCUPIED_SLOT or #PSA_ERROR_EMPTY_SLOT
+ * as applicable. */
+#define PSA_ERROR_BAD_STATE             ((psa_status_t)7)
+
+/** The parameters passed to the function are invalid.
+ *
+ * Implementations may return this error any time a parameter or
+ * combination of parameters are recognized as invalid.
+ *
+ * Implementations shall not return this error code to indicate
+ * that a key slot is occupied when it needs to be free or vice versa,
+ * but shall return #PSA_ERROR_OCCUPIED_SLOT or #PSA_ERROR_EMPTY_SLOT
+ * as applicable. */
+#define PSA_ERROR_INVALID_ARGUMENT      ((psa_status_t)8)
+
+/** There is not enough runtime memory.
+ *
+ * If the action is carried out across multiple security realms, this
+ * error can refer to available memory in any of the security realms. */
+#define PSA_ERROR_INSUFFICIENT_MEMORY   ((psa_status_t)9)
+
+/** There is not enough persistent storage.
+ *
+ * Functions that modify the key storage return this error code if
+ * there is insufficient storage space on the host media. In addition,
+ * many functions that do not otherwise access storage may return this
+ * error code if the implementation requires a mandatory log entry for
+ * the requested action and the log storage space is full. */
+#define PSA_ERROR_INSUFFICIENT_STORAGE  ((psa_status_t)10)
+
+/** There was a communication failure inside the implementation.
+ *
+ * This can indicate a communication failure between the application
+ * and an external cryptoprocessor or between the cryptoprocessor and
+ * an external volatile or persistent memory. A communication failure
+ * may be transient or permanent depending on the cause.
+ *
+ * \warning If a function returns this error, it is undetermined
+ * whether the requested action has completed or not. Implementations
+ * should return #PSA_SUCCESS on successful completion whenver
+ * possible, however functions may return #PSA_ERROR_COMMUNICATION_FAILURE
+ * if the requested action was completed successfully in an external
+ * cryptoprocessor but there was a breakdown of communication before
+ * the cryptoprocessor could report the status to the application.
+ */
+#define PSA_ERROR_COMMUNICATION_FAILURE ((psa_status_t)11)
+
+/** There was a storage failure that may have led to data loss.
+ *
+ * This error indicates that some persistent storage is corrupted.
+ * It should not be used for a corruption of volatile memory
+ * (use #PSA_ERROR_TAMPERING_DETECTED), for a communication error
+ * between the cryptoprocessor and its external storage (use
+ * #PSA_ERROR_COMMUNICATION_FAILURE), or when the storage is
+ * in a valid state but is full (use #PSA_ERROR_INSUFFICIENT_STORAGE).
+ *
+ * Note that a storage failure does not indicate that any data that was
+ * previously read is invalid. However this previously read data may no
+ * longer be readable from storage.
+ *
+ * When a storage failure occurs, it is no longer possible to ensure
+ * the global integrity of the keystore. Depending on the global
+ * integrity guarantees offered by the implementation, access to other
+ * data may or may not fail even if the data is still readable but
+ * its integrity canont be guaranteed.
+ *
+ * Implementations should only use this error code to report a
+ * permanent storage corruption. However application writers should
+ * keep in mind that transient errors while reading the storage may be
+ * reported using this error code. */
+#define PSA_ERROR_STORAGE_FAILURE       ((psa_status_t)12)
+
+/** A hardware failure was detected.
+ *
+ * A hardware failure may be transient or permanent depending on the
+ * cause. */
+#define PSA_ERROR_HARDWARE_FAILURE      ((psa_status_t)13)
+
+/** A tampering attempt was detected.
+ *
+ * If an application receives this error code, there is no guarantee
+ * that previously accessed or computed data was correct and remains
+ * confidential. Applications should not perform any security function
+ * and should enter a safe failure state.
+ *
+ * Implementations may return this error code if they detect an invalid
+ * state that cannot happen during normal operation and that indicates
+ * that the implementation's security guarantees no longer hold. Depending
+ * on the implementation architecture and on its security and safety goals,
+ * the implementation may forcibly terminate the application.
+ *
+ * This error code is intended as a last resort when a security breach
+ * is detected and it is unsure whether the keystore data is still
+ * protected. Implementations shall only return this error code
+ * to report an alarm from a tampering detector, to indicate that
+ * the confidentiality of stored data can no longer be guaranteed,
+ * or to indicate that the integrity of previously returned data is now
+ * considered compromised. Implementations shall not use this error code
+ * to indicate a hardware failure that merely makes it impossible to
+ * perform the requested operation (use #PSA_ERROR_COMMUNICATION_FAILURE,
+ * #PSA_ERROR_STORAGE_FAILURE, #PSA_ERROR_HARDWARE_FAILURE,
+ * #PSA_ERROR_INSUFFICIENT_ENTROPY or other applicable error code
+ * instead).
+ *
+ * This error indicates an attack against the application. Implementations
+ * shall not return this error code as a consequence of the behavior of
+ * the application itself. */
+#define PSA_ERROR_TAMPERING_DETECTED    ((psa_status_t)14)
+
+/** There is not enough entropy to generate random data needed
+ * for the requested action.
+ *
+ * This error indicates a failure of a hardware random generator.
+ * Application writers should note that this error can be returned not
+ * only by functions whose purpose is to generate random data, such
+ * as key, IV or nonce generation, but also by functions that execute
+ * an algorithm with a randomized result, as well as functions that
+ * use randomization of intermediate computations as a countermeasure
+ * to certain attacks.
+ *
+ * Implementations should avoid returning this error after psa_crypto_init()
+ * has succeeded. Implementations should generate sufficient
+ * entropy during initialization and subsequently use a cryptographically
+ * secure pseudorandom generator (PRNG). However implementations may return
+ * this error at any time if a policy requires the PRNG to be reseeded
+ * during normal operation. */
+#define PSA_ERROR_INSUFFICIENT_ENTROPY  ((psa_status_t)15)
+
+/** The signature, MAC or hash is incorrect.
+ *
+ * Verification functions return this error if the verification
+ * calculations completed successfully, and the value to be verified
+ * was determined to be incorrect.
+ *
+ * If the value to verify has an invalid size, implementations may return
+ * either #PSA_ERROR_INVALID_ARGUMENT or #PSA_ERROR_INVALID_SIGNATURE. */
+#define PSA_ERROR_INVALID_SIGNATURE     ((psa_status_t)16)
+
+/** The decrypted padding is incorrect.
+ *
+ * \warning In some protocols, when decrypting data, it is essential that
+ * the behavior of the application does not depend on whether the padding
+ * is correct, down to precise timing. Applications should prefer
+ * protocols that use authenticated encryption rather than plain
+ * encryption. If the application must perform a decryption of
+ * unauthenticated data, the application writer should take care not
+ * to reveal whether the padding is invalid.
+ *
+ * Implementations should strive to make valid and invalid padding
+ * as close as possible to indistinguishable to an external observer.
+ * In particular, the timing of a decryption operation should not
+ * depend on the validity of the padding. */
+#define PSA_ERROR_INVALID_PADDING       ((psa_status_t)17)
+
+/** The generator has insufficient capacity left.
+ *
+ * Once a function returns this error, attempts to read from the
+ * generator will always return this error. */
+#define PSA_ERROR_INSUFFICIENT_CAPACITY ((psa_status_t)18)
+
+/**
+ * \brief Library initialization.
+ *
+ * Applications must call this function before calling any other
+ * function in this module.
+ *
+ * Applications may call this function more than once. Once a call
+ * succeeds, subsequent calls are guaranteed to succeed.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
+ */
+psa_status_t psa_crypto_init(void);
+
+#define PSA_BITS_TO_BYTES(bits) (((bits) + 7) / 8)
+#define PSA_BYTES_TO_BITS(bytes) ((bytes) * 8)
+
+/**@}*/
+
+/** \defgroup crypto_types Key and algorithm types
+ * @{
+ */
+
+/** \brief Encoding of a key type.
+ */
+typedef uint32_t psa_key_type_t;
+
+/** An invalid key type value.
+ *
+ * Zero is not the encoding of any key type.
+ */
+#define PSA_KEY_TYPE_NONE                       ((psa_key_type_t)0x00000000)
+
+/** Vendor-defined flag
+ *
+ * Key types defined by this standard will never have the
+ * #PSA_KEY_TYPE_VENDOR_FLAG bit set. Vendors who define additional key types
+ * must use an encoding with the #PSA_KEY_TYPE_VENDOR_FLAG bit set and should
+ * respect the bitwise structure used by standard encodings whenever practical.
+ */
+#define PSA_KEY_TYPE_VENDOR_FLAG                ((psa_key_type_t)0x80000000)
+
+#define PSA_KEY_TYPE_CATEGORY_MASK              ((psa_key_type_t)0x7e000000)
+
+/** Raw data.
+ *
+ * A "key" of this type cannot be used for any cryptographic operation.
+ * Applications may use this type to store arbitrary data in the keystore. */
+#define PSA_KEY_TYPE_RAW_DATA                   ((psa_key_type_t)0x02000000)
+
+#define PSA_KEY_TYPE_CATEGORY_SYMMETRIC         ((psa_key_type_t)0x04000000)
+#define PSA_KEY_TYPE_CATEGORY_ASYMMETRIC        ((psa_key_type_t)0x06000000)
+#define PSA_KEY_TYPE_PAIR_FLAG                  ((psa_key_type_t)0x01000000)
+
+/** HMAC key.
+ *
+ * The key policy determines which underlying hash algorithm the key can be
+ * used for.
+ *
+ * HMAC keys should generally have the same size as the underlying hash.
+ * This size can be calculated with #PSA_HASH_SIZE(\c alg) where
+ * \c alg is the HMAC algorithm or the underlying hash algorithm. */
+#define PSA_KEY_TYPE_HMAC                       ((psa_key_type_t)0x02000001)
+
+/** A secret for key derivation.
+ *
+ * The key policy determines which key derivation algorithm the key
+ * can be used for.
+ */
+#define PSA_KEY_TYPE_DERIVE                     ((psa_key_type_t)0x02000101)
+
+/** Key for an cipher, AEAD or MAC algorithm based on the AES block cipher.
+ *
+ * The size of the key can be 16 bytes (AES-128), 24 bytes (AES-192) or
+ * 32 bytes (AES-256).
+ */
+#define PSA_KEY_TYPE_AES                        ((psa_key_type_t)0x04000001)
+
+/** Key for a cipher or MAC algorithm based on DES or 3DES (Triple-DES).
+ *
+ * The size of the key can be 8 bytes (single DES), 16 bytes (2-key 3DES) or
+ * 24 bytes (3-key 3DES).
+ *
+ * Note that single DES and 2-key 3DES are weak and strongly
+ * deprecated and should only be used to decrypt legacy data. 3-key 3DES
+ * is weak and deprecated and should only be used in legacy protocols.
+ */
+#define PSA_KEY_TYPE_DES                        ((psa_key_type_t)0x04000002)
+
+/** Key for an cipher, AEAD or MAC algorithm based on the
+ * Camellia block cipher. */
+#define PSA_KEY_TYPE_CAMELLIA                   ((psa_key_type_t)0x04000003)
+
+/** Key for the RC4 stream cipher.
+ *
+ * Note that RC4 is weak and deprecated and should only be used in
+ * legacy protocols. */
+#define PSA_KEY_TYPE_ARC4                       ((psa_key_type_t)0x04000004)
+
+/** RSA public key. */
+#define PSA_KEY_TYPE_RSA_PUBLIC_KEY             ((psa_key_type_t)0x06010000)
+/** RSA key pair (private and public key). */
+#define PSA_KEY_TYPE_RSA_KEYPAIR                ((psa_key_type_t)0x07010000)
+
+/** DSA public key. */
+#define PSA_KEY_TYPE_DSA_PUBLIC_KEY             ((psa_key_type_t)0x06020000)
+/** DSA key pair (private and public key). */
+#define PSA_KEY_TYPE_DSA_KEYPAIR                ((psa_key_type_t)0x07020000)
+
+#define PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE        ((psa_key_type_t)0x06030000)
+#define PSA_KEY_TYPE_ECC_KEYPAIR_BASE           ((psa_key_type_t)0x07030000)
+#define PSA_KEY_TYPE_ECC_CURVE_MASK             ((psa_key_type_t)0x0000ffff)
+/** Elliptic curve key pair. */
+#define PSA_KEY_TYPE_ECC_KEYPAIR(curve)         \
+    (PSA_KEY_TYPE_ECC_KEYPAIR_BASE | (curve))
+/** Elliptic curve public key. */
+#define PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve)              \
+    (PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE | (curve))
+
+/** Whether a key type is vendor-defined. */
+#define PSA_KEY_TYPE_IS_VENDOR_DEFINED(type) \
+    (((type) & PSA_KEY_TYPE_VENDOR_FLAG) != 0)
+
+/** Whether a key type is asymmetric: either a key pair or a public key. */
+#define PSA_KEY_TYPE_IS_ASYMMETRIC(type)                                \
+    (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_ASYMMETRIC)
+/** Whether a key type is the public part of a key pair. */
+#define PSA_KEY_TYPE_IS_PUBLIC_KEY(type)                                \
+    (((type) & (PSA_KEY_TYPE_CATEGORY_MASK | PSA_KEY_TYPE_PAIR_FLAG)) == \
+      PSA_KEY_TYPE_CATEGORY_ASYMMETRIC)
+/** Whether a key type is a key pair containing a private part and a public
+ * part. */
+#define PSA_KEY_TYPE_IS_KEYPAIR(type)                                   \
+    (((type) & (PSA_KEY_TYPE_CATEGORY_MASK | PSA_KEY_TYPE_PAIR_FLAG)) == \
+     (PSA_KEY_TYPE_CATEGORY_ASYMMETRIC | PSA_KEY_TYPE_PAIR_FLAG))
+/** The key pair type corresponding to a public key type. */
+#define PSA_KEY_TYPE_KEYPAIR_OF_PUBLIC_KEY(type)        \
+    ((type) | PSA_KEY_TYPE_PAIR_FLAG)
+/** The public key type corresponding to a key pair type. */
+#define PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(type)        \
+    ((type) & ~PSA_KEY_TYPE_PAIR_FLAG)
+/** Whether a key type is an RSA key (pair or public-only). */
+#define PSA_KEY_TYPE_IS_RSA(type)                                       \
+    (PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY)
+
+/** Whether a key type is an elliptic curve key (pair or public-only). */
+#define PSA_KEY_TYPE_IS_ECC(type)                                       \
+    ((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(type) &                        \
+      ~PSA_KEY_TYPE_ECC_CURVE_MASK) == PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE)
+#define PSA_KEY_TYPE_IS_ECC_KEYPAIR(type)                               \
+    (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) ==                         \
+     PSA_KEY_TYPE_ECC_KEYPAIR_BASE)
+#define PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(type)                            \
+    (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) ==                         \
+     PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE)
+
+/** The type of PSA elliptic curve identifiers. */
+typedef uint16_t psa_ecc_curve_t;
+/** Extract the curve from an elliptic curve key type. */
+#define PSA_KEY_TYPE_GET_CURVE(type)                             \
+    ((psa_ecc_curve_t) (PSA_KEY_TYPE_IS_ECC(type) ?              \
+                        ((type) & PSA_KEY_TYPE_ECC_CURVE_MASK) : \
+                        0))
+
+/* The encoding of curve identifiers is currently aligned with the
+ * TLS Supported Groups Registry (formerly known as the
+ * TLS EC Named Curve Registry)
+ * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8
+ * The values are defined by RFC 4492, RFC 7027 and RFC 7919. */
+#define PSA_ECC_CURVE_SECT163K1         ((psa_ecc_curve_t) 0x0001)
+#define PSA_ECC_CURVE_SECT163R1         ((psa_ecc_curve_t) 0x0002)
+#define PSA_ECC_CURVE_SECT163R2         ((psa_ecc_curve_t) 0x0003)
+#define PSA_ECC_CURVE_SECT193R1         ((psa_ecc_curve_t) 0x0004)
+#define PSA_ECC_CURVE_SECT193R2         ((psa_ecc_curve_t) 0x0005)
+#define PSA_ECC_CURVE_SECT233K1         ((psa_ecc_curve_t) 0x0006)
+#define PSA_ECC_CURVE_SECT233R1         ((psa_ecc_curve_t) 0x0007)
+#define PSA_ECC_CURVE_SECT239K1         ((psa_ecc_curve_t) 0x0008)
+#define PSA_ECC_CURVE_SECT283K1         ((psa_ecc_curve_t) 0x0009)
+#define PSA_ECC_CURVE_SECT283R1         ((psa_ecc_curve_t) 0x000a)
+#define PSA_ECC_CURVE_SECT409K1         ((psa_ecc_curve_t) 0x000b)
+#define PSA_ECC_CURVE_SECT409R1         ((psa_ecc_curve_t) 0x000c)
+#define PSA_ECC_CURVE_SECT571K1         ((psa_ecc_curve_t) 0x000d)
+#define PSA_ECC_CURVE_SECT571R1         ((psa_ecc_curve_t) 0x000e)
+#define PSA_ECC_CURVE_SECP160K1         ((psa_ecc_curve_t) 0x000f)
+#define PSA_ECC_CURVE_SECP160R1         ((psa_ecc_curve_t) 0x0010)
+#define PSA_ECC_CURVE_SECP160R2         ((psa_ecc_curve_t) 0x0011)
+#define PSA_ECC_CURVE_SECP192K1         ((psa_ecc_curve_t) 0x0012)
+#define PSA_ECC_CURVE_SECP192R1         ((psa_ecc_curve_t) 0x0013)
+#define PSA_ECC_CURVE_SECP224K1         ((psa_ecc_curve_t) 0x0014)
+#define PSA_ECC_CURVE_SECP224R1         ((psa_ecc_curve_t) 0x0015)
+#define PSA_ECC_CURVE_SECP256K1         ((psa_ecc_curve_t) 0x0016)
+#define PSA_ECC_CURVE_SECP256R1         ((psa_ecc_curve_t) 0x0017)
+#define PSA_ECC_CURVE_SECP384R1         ((psa_ecc_curve_t) 0x0018)
+#define PSA_ECC_CURVE_SECP521R1         ((psa_ecc_curve_t) 0x0019)
+#define PSA_ECC_CURVE_BRAINPOOL_P256R1  ((psa_ecc_curve_t) 0x001a)
+#define PSA_ECC_CURVE_BRAINPOOL_P384R1  ((psa_ecc_curve_t) 0x001b)
+#define PSA_ECC_CURVE_BRAINPOOL_P512R1  ((psa_ecc_curve_t) 0x001c)
+#define PSA_ECC_CURVE_CURVE25519        ((psa_ecc_curve_t) 0x001d)
+#define PSA_ECC_CURVE_CURVE448          ((psa_ecc_curve_t) 0x001e)
+#define PSA_ECC_CURVE_FFDHE_2048        ((psa_ecc_curve_t) 0x0100)
+#define PSA_ECC_CURVE_FFDHE_3072        ((psa_ecc_curve_t) 0x0101)
+#define PSA_ECC_CURVE_FFDHE_4096        ((psa_ecc_curve_t) 0x0102)
+#define PSA_ECC_CURVE_FFDHE_6144        ((psa_ecc_curve_t) 0x0103)
+#define PSA_ECC_CURVE_FFDHE_8192        ((psa_ecc_curve_t) 0x0104)
+
+/** The block size of a block cipher.
+ *
+ * \param type  A cipher key type (value of type #psa_key_type_t).
+ *
+ * \return      The block size for a block cipher, or 1 for a stream cipher.
+ *              The return value is undefined if \p type is not a supported
+ *              cipher key type.
+ *
+ * \note It is possible to build stream cipher algorithms on top of a block
+ *       cipher, for example CTR mode (#PSA_ALG_CTR).
+ *       This macro only takes the key type into account, so it cannot be
+ *       used to determine the size of the data that #psa_cipher_update()
+ *       might buffer for future processing in general.
+ *
+ * \note This macro returns a compile-time constant if its argument is one.
+ *
+ * \warning This macro may evaluate its argument multiple times.
+ */
+#define PSA_BLOCK_CIPHER_BLOCK_SIZE(type)            \
+    (                                                \
+        (type) == PSA_KEY_TYPE_AES ? 16 :            \
+        (type) == PSA_KEY_TYPE_DES ? 8 :             \
+        (type) == PSA_KEY_TYPE_CAMELLIA ? 16 :       \
+        (type) == PSA_KEY_TYPE_ARC4 ? 1 :            \
+        0)
+
+/** \brief Encoding of a cryptographic algorithm.
+ *
+ * For algorithms that can be applied to multiple key types, this type
+ * does not encode the key type. For example, for symmetric ciphers
+ * based on a block cipher, #psa_algorithm_t encodes the block cipher
+ * mode and the padding mode while the block cipher itself is encoded
+ * via #psa_key_type_t.
+ */
+typedef uint32_t psa_algorithm_t;
+
+#define PSA_ALG_VENDOR_FLAG                     ((psa_algorithm_t)0x80000000)
+#define PSA_ALG_CATEGORY_MASK                   ((psa_algorithm_t)0x7f000000)
+#define PSA_ALG_CATEGORY_HASH                   ((psa_algorithm_t)0x01000000)
+#define PSA_ALG_CATEGORY_MAC                    ((psa_algorithm_t)0x02000000)
+#define PSA_ALG_CATEGORY_CIPHER                 ((psa_algorithm_t)0x04000000)
+#define PSA_ALG_CATEGORY_AEAD                   ((psa_algorithm_t)0x06000000)
+#define PSA_ALG_CATEGORY_SIGN                   ((psa_algorithm_t)0x10000000)
+#define PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION  ((psa_algorithm_t)0x12000000)
+#define PSA_ALG_CATEGORY_KEY_AGREEMENT          ((psa_algorithm_t)0x22000000)
+#define PSA_ALG_CATEGORY_KEY_DERIVATION         ((psa_algorithm_t)0x30000000)
+
+#define PSA_ALG_IS_VENDOR_DEFINED(alg)                                  \
+    (((alg) & PSA_ALG_VENDOR_FLAG) != 0)
+
+/** Whether the specified algorithm is a hash algorithm.
+ *
+ * \param alg An algorithm identifier (value of type #psa_algorithm_t).
+ *
+ * \return 1 if \p alg is a hash algorithm, 0 otherwise.
+ *         This macro may return either 0 or 1 if \p alg is not a supported
+ *         algorithm identifier.
+ */
+#define PSA_ALG_IS_HASH(alg)                                            \
+    (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_HASH)
+
+/** Whether the specified algorithm is a MAC algorithm.
+ *
+ * \param alg An algorithm identifier (value of type #psa_algorithm_t).
+ *
+ * \return 1 if \p alg is a MAC algorithm, 0 otherwise.
+ *         This macro may return either 0 or 1 if \p alg is not a supported
+ *         algorithm identifier.
+ */
+#define PSA_ALG_IS_MAC(alg)                                             \
+    (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_MAC)
+
+/** Whether the specified algorithm is a symmetric cipher algorithm.
+ *
+ * \param alg An algorithm identifier (value of type #psa_algorithm_t).
+ *
+ * \return 1 if \p alg is a symmetric cipher algorithm, 0 otherwise.
+ *         This macro may return either 0 or 1 if \p alg is not a supported
+ *         algorithm identifier.
+ */
+#define PSA_ALG_IS_CIPHER(alg)                                          \
+    (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_CIPHER)
+
+/** Whether the specified algorithm is an authenticated encryption
+ * with associated data (AEAD) algorithm.
+ *
+ * \param alg An algorithm identifier (value of type #psa_algorithm_t).
+ *
+ * \return 1 if \p alg is an AEAD algorithm, 0 otherwise.
+ *         This macro may return either 0 or 1 if \p alg is not a supported
+ *         algorithm identifier.
+ */
+#define PSA_ALG_IS_AEAD(alg)                                            \
+    (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_AEAD)
+
+/** Whether the specified algorithm is a public-key signature algorithm.
+ *
+ * \param alg An algorithm identifier (value of type #psa_algorithm_t).
+ *
+ * \return 1 if \p alg is a public-key signature algorithm, 0 otherwise.
+ *         This macro may return either 0 or 1 if \p alg is not a supported
+ *         algorithm identifier.
+ */
+#define PSA_ALG_IS_SIGN(alg)                                            \
+    (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_SIGN)
+
+/** Whether the specified algorithm is a public-key encryption algorithm.
+ *
+ * \param alg An algorithm identifier (value of type #psa_algorithm_t).
+ *
+ * \return 1 if \p alg is a public-key encryption algorithm, 0 otherwise.
+ *         This macro may return either 0 or 1 if \p alg is not a supported
+ *         algorithm identifier.
+ */
+#define PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg)                           \
+    (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION)
+
+/** Whether the specified algorithm is a key agreement algorithm.
+ *
+ * \param alg An algorithm identifier (value of type #psa_algorithm_t).
+ *
+ * \return 1 if \p alg is a key agreement algorithm, 0 otherwise.
+ *         This macro may return either 0 or 1 if \p alg is not a supported
+ *         algorithm identifier.
+ */
+#define PSA_ALG_IS_KEY_AGREEMENT(alg)                                   \
+    (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_AGREEMENT)
+
+/** Whether the specified algorithm is a key derivation algorithm.
+ *
+ * \param alg An algorithm identifier (value of type #psa_algorithm_t).
+ *
+ * \return 1 if \p alg is a key derivation algorithm, 0 otherwise.
+ *         This macro may return either 0 or 1 if \p alg is not a supported
+ *         algorithm identifier.
+ */
+#define PSA_ALG_IS_KEY_DERIVATION(alg)                                  \
+    (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_DERIVATION)
+
+#define PSA_ALG_HASH_MASK                       ((psa_algorithm_t)0x000000ff)
+#define PSA_ALG_MD2                             ((psa_algorithm_t)0x01000001)
+#define PSA_ALG_MD4                             ((psa_algorithm_t)0x01000002)
+#define PSA_ALG_MD5                             ((psa_algorithm_t)0x01000003)
+#define PSA_ALG_RIPEMD160                       ((psa_algorithm_t)0x01000004)
+#define PSA_ALG_SHA_1                           ((psa_algorithm_t)0x01000005)
+/** SHA2-224 */
+#define PSA_ALG_SHA_224                         ((psa_algorithm_t)0x01000008)
+/** SHA2-256 */
+#define PSA_ALG_SHA_256                         ((psa_algorithm_t)0x01000009)
+/** SHA2-384 */
+#define PSA_ALG_SHA_384                         ((psa_algorithm_t)0x0100000a)
+/** SHA2-512 */
+#define PSA_ALG_SHA_512                         ((psa_algorithm_t)0x0100000b)
+/** SHA2-512/224 */
+#define PSA_ALG_SHA_512_224                     ((psa_algorithm_t)0x0100000c)
+/** SHA2-512/256 */
+#define PSA_ALG_SHA_512_256                     ((psa_algorithm_t)0x0100000d)
+/** SHA3-224 */
+#define PSA_ALG_SHA3_224                        ((psa_algorithm_t)0x01000010)
+/** SHA3-256 */
+#define PSA_ALG_SHA3_256                        ((psa_algorithm_t)0x01000011)
+/** SHA3-384 */
+#define PSA_ALG_SHA3_384                        ((psa_algorithm_t)0x01000012)
+/** SHA3-512 */
+#define PSA_ALG_SHA3_512                        ((psa_algorithm_t)0x01000013)
+
+#define PSA_ALG_MAC_SUBCATEGORY_MASK            ((psa_algorithm_t)0x00c00000)
+#define PSA_ALG_HMAC_BASE                       ((psa_algorithm_t)0x02800000)
+/** Macro to build an HMAC algorithm.
+ *
+ * For example, #PSA_ALG_HMAC(#PSA_ALG_SHA_256) is HMAC-SHA-256.
+ *
+ * \param hash_alg      A hash algorithm (\c PSA_ALG_XXX value such that
+ *                      #PSA_ALG_IS_HASH(\p hash_alg) is true).
+ *
+ * \return              The corresponding HMAC algorithm.
+ * \return              Unspecified if \p alg is not a supported
+ *                      hash algorithm.
+ */
+#define PSA_ALG_HMAC(hash_alg)                                  \
+    (PSA_ALG_HMAC_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))
+
+#define PSA_ALG_HMAC_HASH(hmac_alg)                             \
+    (PSA_ALG_CATEGORY_HASH | ((hmac_alg) & PSA_ALG_HASH_MASK))
+
+/** Whether the specified algorithm is an HMAC algorithm.
+ *
+ * HMAC is a family of MAC algorithms that are based on a hash function.
+ *
+ * \param alg An algorithm identifier (value of type #psa_algorithm_t).
+ *
+ * \return 1 if \p alg is an HMAC algorithm, 0 otherwise.
+ *         This macro may return either 0 or 1 if \p alg is not a supported
+ *         algorithm identifier.
+ */
+#define PSA_ALG_IS_HMAC(alg)                                            \
+    (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \
+     PSA_ALG_HMAC_BASE)
+
+#define PSA_ALG_CIPHER_MAC_BASE                 ((psa_algorithm_t)0x02c00000)
+#define PSA_ALG_CBC_MAC                         ((psa_algorithm_t)0x02c00001)
+#define PSA_ALG_CMAC                            ((psa_algorithm_t)0x02c00002)
+#define PSA_ALG_GMAC                            ((psa_algorithm_t)0x02c00003)
+
+/** Whether the specified algorithm is a MAC algorithm based on a block cipher.
+ *
+ * \param alg An algorithm identifier (value of type #psa_algorithm_t).
+ *
+ * \return 1 if \p alg is a MAC algorithm based on a block cipher, 0 otherwise.
+ *         This macro may return either 0 or 1 if \p alg is not a supported
+ *         algorithm identifier.
+ */
+#define PSA_ALG_IS_CIPHER_MAC(alg)                                      \
+    (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \
+     PSA_ALG_CIPHER_MAC_BASE)
+
+#define PSA_ALG_CIPHER_SUBCATEGORY_MASK         ((psa_algorithm_t)0x00c00000)
+#define PSA_ALG_BLOCK_CIPHER_BASE               ((psa_algorithm_t)0x04000000)
+#define PSA_ALG_BLOCK_CIPHER_MODE_MASK          ((psa_algorithm_t)0x000000ff)
+#define PSA_ALG_BLOCK_CIPHER_PADDING_MASK       ((psa_algorithm_t)0x003f0000)
+
+/** Use a block cipher mode without padding.
+ *
+ * This padding mode may only be used with messages whose lengths are a
+ * whole number of blocks for the chosen block cipher.
+ */
+#define PSA_ALG_BLOCK_CIPHER_PAD_NONE           ((psa_algorithm_t)0x00000000)
+
+#define PSA_ALG_BLOCK_CIPHER_PAD_PKCS7          ((psa_algorithm_t)0x00010000)
+
+/** Whether the specified algorithm is a block cipher.
+ *
+ * A block cipher is a symmetric cipher that encrypts or decrypts messages
+ * by chopping them into fixed-size blocks. Processing a message requires
+ * applying a _padding mode_ to transform the message into one whose
+ * length is a whole number of blocks. To construct an algorithm
+ * identifier for a block cipher, apply a bitwise-or between the block
+ * cipher mode and the padding mode. For example, CBC with PKCS#7 padding
+ * is `PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_PKCS7`.
+ *
+ * The transformation applied to each block is determined by the key type.
+ * For example, to use AES-128-CBC-PKCS7, use the algorithm above with
+ * a key of type #PSA_KEY_TYPE_AES and a length of 128 bits (16 bytes).
+ *
+ * \param alg An algorithm identifier (value of type #psa_algorithm_t).
+ *
+ * \return 1 if \p alg is a block cipher algorithm, 0 otherwise.
+ *         This macro may return either 0 or 1 if \p alg is not a supported
+ *         algorithm identifier or if it is not a symmetric cipher algorithm.
+ */
+#define PSA_ALG_IS_BLOCK_CIPHER(alg)            \
+    (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_CIPHER_SUBCATEGORY_MASK)) == \
+        PSA_ALG_BLOCK_CIPHER_BASE)
+
+/** The CBC block cipher mode.
+ */
+#define PSA_ALG_CBC_BASE                        ((psa_algorithm_t)0x04000001)
+#define PSA_ALG_CFB_BASE                        ((psa_algorithm_t)0x04000002)
+#define PSA_ALG_OFB_BASE                        ((psa_algorithm_t)0x04000003)
+#define PSA_ALG_XTS_BASE                        ((psa_algorithm_t)0x04000004)
+
+#define PSA_ALG_STREAM_CIPHER_BASE              ((psa_algorithm_t)0x04800000)
+
+/** The CTR stream cipher mode.
+ *
+ * CTR is a stream cipher which is built from a block cipher. The
+ * underlying block cipher is determined by the key type. For example,
+ * to use AES-128-CTR, use this algorithm with
+ * a key of type #PSA_KEY_TYPE_AES and a length of 128 bits (16 bytes).
+ */
+#define PSA_ALG_CTR                             ((psa_algorithm_t)0x04800001)
+
+/** The ARC4 stream cipher algorithm.
+ */
+#define PSA_ALG_ARC4                            ((psa_algorithm_t)0x04800002)
+
+/** Whether the specified algorithm is a stream cipher.
+ *
+ * A stream cipher is a symmetric cipher that encrypts or decrypts messages
+ * by applying a bitwise-xor with a stream of bytes that is generated
+ * from a key.
+ *
+ * \param alg An algorithm identifier (value of type #psa_algorithm_t).
+ *
+ * \return 1 if \p alg is a stream cipher algorithm, 0 otherwise.
+ *         This macro may return either 0 or 1 if \p alg is not a supported
+ *         algorithm identifier or if it is not a symmetric cipher algorithm.
+ */
+#define PSA_ALG_IS_STREAM_CIPHER(alg)            \
+    (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_CIPHER_SUBCATEGORY_MASK)) == \
+        PSA_ALG_STREAM_CIPHER_BASE)
+
+#define PSA_ALG_CCM                             ((psa_algorithm_t)0x06000001)
+#define PSA_ALG_GCM                             ((psa_algorithm_t)0x06000002)
+
+#define PSA_ALG_RSA_PKCS1V15_SIGN_BASE          ((psa_algorithm_t)0x10020000)
+/** RSA PKCS#1 v1.5 signature with hashing.
+ *
+ * This is the signature scheme defined by RFC 8017
+ * (PKCS#1: RSA Cryptography Specifications) under the name
+ * RSASSA-PKCS1-v1_5.
+ *
+ * \param hash_alg      A hash algorithm (\c PSA_ALG_XXX value such that
+ *                      #PSA_ALG_IS_HASH(\p hash_alg) is true).
+ *
+ * \return              The corresponding RSA PKCS#1 v1.5 signature algorithm.
+ * \return              Unspecified if \p alg is not a supported
+ *                      hash algorithm.
+ */
+#define PSA_ALG_RSA_PKCS1V15_SIGN(hash_alg)                             \
+    (PSA_ALG_RSA_PKCS1V15_SIGN_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))
+/** Raw PKCS#1 v1.5 signature.
+ *
+ * The input to this algorithm is the DigestInfo structure used by
+ * RFC 8017 (PKCS#1: RSA Cryptography Specifications), &sect;9.2
+ * steps 3&ndash;6.
+ */
+#define PSA_ALG_RSA_PKCS1V15_SIGN_RAW PSA_ALG_RSA_PKCS1V15_SIGN_BASE
+#define PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg)                               \
+    (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PKCS1V15_SIGN_BASE)
+
+#define PSA_ALG_RSA_PSS_BASE               ((psa_algorithm_t)0x10030000)
+/** RSA PSS signature with hashing.
+ *
+ * This is the signature scheme defined by RFC 8017
+ * (PKCS#1: RSA Cryptography Specifications) under the name
+ * RSASSA-PSS, with the message generation function MGF1, and with
+ * a salt length equal to the length of the hash. The specified
+ * hash algorithm is used to hash the input message, to create the
+ * salted hash, and for the mask generation.
+ *
+ * \param hash_alg      A hash algorithm (\c PSA_ALG_XXX value such that
+ *                      #PSA_ALG_IS_HASH(\p hash_alg) is true).
+ *
+ * \return              The corresponding RSA PSS signature algorithm.
+ * \return              Unspecified if \p alg is not a supported
+ *                      hash algorithm.
+ */
+#define PSA_ALG_RSA_PSS(hash_alg)                               \
+    (PSA_ALG_RSA_PSS_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))
+#define PSA_ALG_IS_RSA_PSS(alg)                                 \
+    (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PSS_BASE)
+
+#define PSA_ALG_DSA_BASE                        ((psa_algorithm_t)0x10040000)
+/** DSA signature with hashing.
+ *
+ * This is the signature scheme defined by FIPS 186-4,
+ * with a random per-message secret number (*k*).
+ *
+ * \param hash_alg      A hash algorithm (\c PSA_ALG_XXX value such that
+ *                      #PSA_ALG_IS_HASH(\p hash_alg) is true).
+ *
+ * \return              The corresponding DSA signature algorithm.
+ * \return              Unspecified if \p alg is not a supported
+ *                      hash algorithm.
+ */
+#define PSA_ALG_DSA(hash_alg)                             \
+    (PSA_ALG_DSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))
+#define PSA_ALG_DETERMINISTIC_DSA_BASE          ((psa_algorithm_t)0x10050000)
+#define PSA_ALG_DSA_DETERMINISTIC_FLAG          ((psa_algorithm_t)0x00010000)
+#define PSA_ALG_DETERMINISTIC_DSA(hash_alg)                             \
+    (PSA_ALG_DETERMINISTIC_DSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))
+#define PSA_ALG_IS_DSA(alg)                                             \
+    (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_DSA_DETERMINISTIC_FLAG) ==  \
+     PSA_ALG_DSA_BASE)
+#define PSA_ALG_DSA_IS_DETERMINISTIC(alg)               \
+    (((alg) & PSA_ALG_DSA_DETERMINISTIC_FLAG) != 0)
+#define PSA_ALG_IS_DETERMINISTIC_DSA(alg)                       \
+    (PSA_ALG_IS_DSA(alg) && PSA_ALG_DSA_IS_DETERMINISTIC(alg))
+#define PSA_ALG_IS_RANDOMIZED_DSA(alg)                          \
+    (PSA_ALG_IS_DSA(alg) && !PSA_ALG_DSA_IS_DETERMINISTIC(alg))
+
+#define PSA_ALG_ECDSA_BASE                      ((psa_algorithm_t)0x10060000)
+/** ECDSA signature with hashing.
+ *
+ * This is the ECDSA signature scheme defined by ANSI X9.62,
+ * with a random per-message secret number (*k*).
+ *
+ * The representation of the signature as a byte string consists of
+ * the concatentation of the signature values *r* and *s*. Each of
+ * *r* and *s* is encoded as an *N*-octet string, where *N* is the length
+ * of the base point of the curve in octets. Each value is represented
+ * in big-endian order (most significant octet first).
+ *
+ * \param hash_alg      A hash algorithm (\c PSA_ALG_XXX value such that
+ *                      #PSA_ALG_IS_HASH(\p hash_alg) is true).
+ *
+ * \return              The corresponding ECDSA signature algorithm.
+ * \return              Unspecified if \p alg is not a supported
+ *                      hash algorithm.
+ */
+#define PSA_ALG_ECDSA(hash_alg)                                 \
+    (PSA_ALG_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))
+/** ECDSA signature without hashing.
+ *
+ * This is the same signature scheme as #PSA_ALG_ECDSA(), but
+ * without specifying a hash algorithm. This algorithm may only be
+ * used to sign or verify a sequence of bytes that should be an
+ * already-calculated hash. Note that the input is padded with
+ * zeros on the left or truncated on the left as required to fit
+ * the curve size.
+ */
+#define PSA_ALG_ECDSA_ANY PSA_ALG_ECDSA_BASE
+#define PSA_ALG_DETERMINISTIC_ECDSA_BASE        ((psa_algorithm_t)0x10070000)
+/** Deterministic ECDSA signature with hashing.
+ *
+ * This is the deterministic ECDSA signature scheme defined by RFC 6979.
+ *
+ * The representation of a signature is the same as with #PSA_ALG_ECDSA().
+ *
+ * Note that when this algorithm is used for verification, signatures
+ * made with randomized ECDSA (#PSA_ALG_ECDSA(\p hash_alg)) with the
+ * same private key are accepted. In other words,
+ * #PSA_ALG_DETERMINISTIC_ECDSA(\p hash_alg) differs from
+ * #PSA_ALG_ECDSA(\p hash_alg) only for signature, not for verification.
+ *
+ * \param hash_alg      A hash algorithm (\c PSA_ALG_XXX value such that
+ *                      #PSA_ALG_IS_HASH(\p hash_alg) is true).
+ *
+ * \return              The corresponding deterministic ECDSA signature
+ *                      algorithm.
+ * \return              Unspecified if \p alg is not a supported
+ *                      hash algorithm.
+ */
+#define PSA_ALG_DETERMINISTIC_ECDSA(hash_alg)                           \
+    (PSA_ALG_DETERMINISTIC_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))
+#define PSA_ALG_IS_ECDSA(alg)                                           \
+    (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_DSA_DETERMINISTIC_FLAG) ==  \
+     PSA_ALG_ECDSA_BASE)
+#define PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)             \
+    (((alg) & PSA_ALG_DSA_DETERMINISTIC_FLAG) != 0)
+#define PSA_ALG_IS_DETERMINISTIC_ECDSA(alg)                             \
+    (PSA_ALG_IS_ECDSA(alg) && PSA_ALG_ECDSA_IS_DETERMINISTIC(alg))
+#define PSA_ALG_IS_RANDOMIZED_ECDSA(alg)                                \
+    (PSA_ALG_IS_ECDSA(alg) && !PSA_ALG_ECDSA_IS_DETERMINISTIC(alg))
+
+/** Get the hash used by a hash-and-sign signature algorithm.
+ *
+ * A hash-and-sign algorithm is a signature algorithm which is
+ * composed of two phases: first a hashing phase which does not use
+ * the key and produces a hash of the input message, then a signing
+ * phase which only uses the hash and the key and not the message
+ * itself.
+ *
+ * \param alg   A signature algorithm (\c PSA_ALG_XXX value such that
+ *              #PSA_ALG_IS_SIGN(\p alg) is true).
+ *
+ * \return      The underlying hash algorithm if \p alg is a hash-and-sign
+ *              algorithm.
+ * \return      0 if \p alg is a signature algorithm that does not
+ *              follow the hash-and-sign structure.
+ * \return      Unspecified if \p alg is not a signature algorithm or
+ *              if it is not supported by the implementation.
+ */
+#define PSA_ALG_SIGN_GET_HASH(alg)                                     \
+    (PSA_ALG_IS_RSA_PSS(alg) || PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) ||   \
+     PSA_ALG_IS_DSA(alg) || PSA_ALG_IS_ECDSA(alg) ?                    \
+     ((alg) & PSA_ALG_HASH_MASK) == 0 ? /*"raw" algorithm*/ 0 :        \
+     ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH :             \
+     0)
+
+/** RSA PKCS#1 v1.5 encryption.
+ */
+#define PSA_ALG_RSA_PKCS1V15_CRYPT              ((psa_algorithm_t)0x12020000)
+
+#define PSA_ALG_RSA_OAEP_BASE                   ((psa_algorithm_t)0x12030000)
+/** RSA OAEP encryption.
+ *
+ * This is the encryption scheme defined by RFC 8017
+ * (PKCS#1: RSA Cryptography Specifications) under the name
+ * RSAES-OAEP, with the message generation function MGF1.
+ *
+ * \param hash_alg      The hash algorithm (\c PSA_ALG_XXX value such that
+ *                      #PSA_ALG_IS_HASH(\p hash_alg) is true) to use
+ *                      for MGF1.
+ *
+ * \return              The corresponding RSA OAEP signature algorithm.
+ * \return              Unspecified if \p alg is not a supported
+ *                      hash algorithm.
+ */
+#define PSA_ALG_RSA_OAEP(hash_alg)                              \
+    (PSA_ALG_RSA_OAEP_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))
+#define PSA_ALG_IS_RSA_OAEP(alg)                                \
+    (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_OAEP_BASE)
+#define PSA_ALG_RSA_OAEP_GET_HASH(alg)                          \
+    (PSA_ALG_IS_RSA_OAEP(alg) ?                                 \
+     ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH :      \
+     0)
+
+#define PSA_ALG_HKDF_BASE                       ((psa_algorithm_t)0x30000100)
+/** Macro to build an HKDF algorithm.
+ *
+ * For example, `PSA_ALG_HKDF(PSA_ALG_SHA256)` is HKDF using HMAC-SHA-256.
+ *
+ * \param hash_alg      A hash algorithm (\c PSA_ALG_XXX value such that
+ *                      #PSA_ALG_IS_HASH(\p hash_alg) is true).
+ *
+ * \return              The corresponding HKDF algorithm.
+ * \return              Unspecified if \p alg is not a supported
+ *                      hash algorithm.
+ */
+#define PSA_ALG_HKDF(hash_alg)                                  \
+    (PSA_ALG_HKDF_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))
+/** Whether the specified algorithm is an HKDF algorithm.
+ *
+ * HKDF is a family of key derivation algorithms that are based on a hash
+ * function and the HMAC construction.
+ *
+ * \param alg An algorithm identifier (value of type #psa_algorithm_t).
+ *
+ * \return 1 if \c alg is an HKDF algorithm, 0 otherwise.
+ *         This macro may return either 0 or 1 if \c alg is not a supported
+ *         key derivation algorithm identifier.
+ */
+#define PSA_ALG_IS_HKDF(alg)                            \
+    (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_BASE)
+#define PSA_ALG_HKDF_GET_HASH(hkdf_alg)                         \
+    (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK))
+
+/**@}*/
+
+/** \defgroup key_management Key management
+ * @{
+ */
+
+/**
+ * \brief Import a key in binary format.
+ *
+ * This function supports any output from psa_export_key(). Refer to the
+ * documentation of psa_export_key() for the format for each key type.
+ *
+ * \param key         Slot where the key will be stored. This must be a
+ *                    valid slot for a key of the chosen type. It must
+ *                    be unoccupied.
+ * \param type        Key type (a \c PSA_KEY_TYPE_XXX value).
+ * \param[in] data    Buffer containing the key data.
+ * \param data_length Size of the \p data buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         The key type or key size is not supported, either by the
+ *         implementation in general or in this particular slot.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         The key slot is invalid,
+ *         or the key data is not correctly formatted.
+ * \retval #PSA_ERROR_OCCUPIED_SLOT
+ *         There is already a key in the specified slot.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_import_key(psa_key_slot_t key,
+                            psa_key_type_t type,
+                            const uint8_t *data,
+                            size_t data_length);
+
+/**
+ * \brief Destroy a key and restore the slot to its default state.
+ *
+ * This function destroys the content of the key slot from both volatile
+ * memory and, if applicable, non-volatile storage. Implementations shall
+ * make a best effort to ensure that any previous content of the slot is
+ * unrecoverable.
+ *
+ * This function also erases any metadata such as policies. It returns the
+ * specified slot to its default state.
+ *
+ * \param key           The key slot to erase.
+ *
+ * \retval #PSA_SUCCESS
+ *         The slot's content, if any, has been erased.
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ *         The slot holds content and cannot be erased because it is
+ *         read-only, either due to a policy or due to physical restrictions.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         The specified slot number does not designate a valid slot.
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ *         There was an failure in communication with the cryptoprocessor.
+ *         The key material may still be present in the cryptoprocessor.
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ *         The storage is corrupted. Implementations shall make a best effort
+ *         to erase key material even in this stage, however applications
+ *         should be aware that it may be impossible to guarantee that the
+ *         key material is not recoverable in such cases.
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ *         An unexpected condition which is not a storage corruption or
+ *         a communication failure occurred. The cryptoprocessor may have
+ *         been compromised.
+ */
+psa_status_t psa_destroy_key(psa_key_slot_t key);
+
+/**
+ * \brief Get basic metadata about a key.
+ *
+ * \param key           Slot whose content is queried. This must
+ *                      be an occupied key slot.
+ * \param[out] type     On success, the key type (a \c PSA_KEY_TYPE_XXX value).
+ *                      This may be a null pointer, in which case the key type
+ *                      is not written.
+ * \param[out] bits     On success, the key size in bits.
+ *                      This may be a null pointer, in which case the key size
+ *                      is not written.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_EMPTY_SLOT
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_get_key_information(psa_key_slot_t key,
+                                     psa_key_type_t *type,
+                                     size_t *bits);
+
+/**
+ * \brief Export a key in binary format.
+ *
+ * The output of this function can be passed to psa_import_key() to
+ * create an equivalent object.
+ *
+ * If a key is created with psa_import_key() and then exported with
+ * this function, it is not guaranteed that the resulting data is
+ * identical: the implementation may choose a different representation
+ * of the same key if the format permits it.
+ *
+ * For standard key types, the output format is as follows:
+ *
+ * - For symmetric keys (including MAC keys), the format is the
+ *   raw bytes of the key.
+ * - For DES, the key data consists of 8 bytes. The parity bits must be
+ *   correct.
+ * - For Triple-DES, the format is the concatenation of the
+ *   two or three DES keys.
+ * - For RSA key pairs (#PSA_KEY_TYPE_RSA_KEYPAIR), the format
+ *   is the non-encrypted DER representation defined by PKCS\#1 (RFC 8017)
+ *   as RSAPrivateKey.
+ * - For RSA public keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY), the format
+ *   is the DER representation defined by RFC 5280 as SubjectPublicKeyInfo.
+ *
+ * \param key               Slot whose content is to be exported. This must
+ *                          be an occupied key slot.
+ * \param[out] data         Buffer where the key data is to be written.
+ * \param data_size         Size of the \p data buffer in bytes.
+ * \param[out] data_length  On success, the number of bytes
+ *                          that make up the key data.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_EMPTY_SLOT
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_export_key(psa_key_slot_t key,
+                            uint8_t *data,
+                            size_t data_size,
+                            size_t *data_length);
+
+/**
+ * \brief Export a public key or the public part of a key pair in binary format.
+ *
+ * The output of this function can be passed to psa_import_key() to
+ * create an object that is equivalent to the public key.
+ *
+ * For standard key types, the output format is as follows:
+ *
+ * - For RSA keys (#PSA_KEY_TYPE_RSA_KEYPAIR or #PSA_KEY_TYPE_RSA_PUBLIC_KEY),
+ *   the format is the DER representation of the public key defined by RFC 5280
+ *   as SubjectPublicKeyInfo.
+ *
+ * \param key               Slot whose content is to be exported. This must
+ *                          be an occupied key slot.
+ * \param[out] data         Buffer where the key data is to be written.
+ * \param data_size         Size of the \p data buffer in bytes.
+ * \param[out] data_length  On success, the number of bytes
+ *                          that make up the key data.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_EMPTY_SLOT
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_export_public_key(psa_key_slot_t key,
+                                   uint8_t *data,
+                                   size_t data_size,
+                                   size_t *data_length);
+
+/**@}*/
+
+/** \defgroup policy Key policies
+ * @{
+ */
+
+/** \brief Encoding of permitted usage on a key. */
+typedef uint32_t psa_key_usage_t;
+
+/** Whether the key may be exported.
+ *
+ * A public key or the public part of a key pair may always be exported
+ * regardless of the value of this permission flag.
+ *
+ * If a key does not have export permission, implementations shall not
+ * allow the key to be exported in plain form from the cryptoprocessor,
+ * whether through psa_export_key() or through a proprietary interface.
+ * The key may however be exportable in a wrapped form, i.e. in a form
+ * where it is encrypted by another key.
+ */
+#define PSA_KEY_USAGE_EXPORT                    ((psa_key_usage_t)0x00000001)
+
+/** Whether the key may be used to encrypt a message.
+ *
+ * This flag allows the key to be used for a symmetric encryption operation,
+ * for an AEAD encryption-and-authentication operation,
+ * or for an asymmetric encryption operation,
+ * if otherwise permitted by the key's type and policy.
+ *
+ * For a key pair, this concerns the public key.
+ */
+#define PSA_KEY_USAGE_ENCRYPT                   ((psa_key_usage_t)0x00000100)
+
+/** Whether the key may be used to decrypt a message.
+ *
+ * This flag allows the key to be used for a symmetric decryption operation,
+ * for an AEAD decryption-and-verification operation,
+ * or for an asymmetric decryption operation,
+ * if otherwise permitted by the key's type and policy.
+ *
+ * For a key pair, this concerns the private key.
+ */
+#define PSA_KEY_USAGE_DECRYPT                   ((psa_key_usage_t)0x00000200)
+
+/** Whether the key may be used to sign a message.
+ *
+ * This flag allows the key to be used for a MAC calculation operation
+ * or for an asymmetric signature operation,
+ * if otherwise permitted by the key's type and policy.
+ *
+ * For a key pair, this concerns the private key.
+ */
+#define PSA_KEY_USAGE_SIGN                      ((psa_key_usage_t)0x00000400)
+
+/** Whether the key may be used to verify a message signature.
+ *
+ * This flag allows the key to be used for a MAC verification operation
+ * or for an asymmetric signature verification operation,
+ * if otherwise permitted by by the key's type and policy.
+ *
+ * For a key pair, this concerns the public key.
+ */
+#define PSA_KEY_USAGE_VERIFY                    ((psa_key_usage_t)0x00000800)
+
+/** Whether the key may be used to derive other keys.
+ */
+#define PSA_KEY_USAGE_DERIVE                    ((psa_key_usage_t)0x00001000)
+
+/** The type of the key policy data structure.
+ *
+ * This is an implementation-defined \c struct. Applications should not
+ * make any assumptions about the content of this structure except
+ * as directed by the documentation of a specific implementation. */
+typedef struct psa_key_policy_s psa_key_policy_t;
+
+/** \brief Initialize a key policy structure to a default that forbids all
+ * usage of the key.
+ *
+ * \param[out] policy   The policy object to initialize.
+ */
+void psa_key_policy_init(psa_key_policy_t *policy);
+
+/** \brief Set the standard fields of a policy structure.
+ *
+ * Note that this function does not make any consistency check of the
+ * parameters. The values are only checked when applying the policy to
+ * a key slot with psa_set_key_policy().
+ *
+ * \param[out] policy   The policy object to modify.
+ * \param usage         The permitted uses for the key.
+ * \param alg           The algorithm that the key may be used for.
+ */
+void psa_key_policy_set_usage(psa_key_policy_t *policy,
+                              psa_key_usage_t usage,
+                              psa_algorithm_t alg);
+
+/** \brief Retrieve the usage field of a policy structure.
+ *
+ * \param[in] policy    The policy object to query.
+ *
+ * \return The permitted uses for a key with this policy.
+ */
+psa_key_usage_t psa_key_policy_get_usage(const psa_key_policy_t *policy);
+
+/** \brief Retrieve the algorithm field of a policy structure.
+ *
+ * \param[in] policy    The policy object to query.
+ *
+ * \return The permitted algorithm for a key with this policy.
+ */
+psa_algorithm_t psa_key_policy_get_algorithm(const psa_key_policy_t *policy);
+
+/** \brief Set the usage policy on a key slot.
+ *
+ * This function must be called on an empty key slot, before importing,
+ * generating or creating a key in the slot. Changing the policy of an
+ * existing key is not permitted.
+ *
+ * Implementations may set restrictions on supported key policies
+ * depending on the key type and the key slot.
+ *
+ * \param key           The key slot whose policy is to be changed.
+ * \param[in] policy    The policy object to query.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_OCCUPIED_SLOT
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_set_key_policy(psa_key_slot_t key,
+                                const psa_key_policy_t *policy);
+
+/** \brief Get the usage policy for a key slot.
+ *
+ * \param key           The key slot whose policy is being queried.
+ * \param[out] policy   On success, the key's policy.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_get_key_policy(psa_key_slot_t key,
+                                psa_key_policy_t *policy);
+
+/**@}*/
+
+/** \defgroup persistence Key lifetime
+ * @{
+ */
+
+/** Encoding of key lifetimes.
+ */
+typedef uint32_t psa_key_lifetime_t;
+
+/** A volatile key slot retains its content as long as the application is
+ * running. It is guaranteed to be erased on a power reset.
+ */
+#define PSA_KEY_LIFETIME_VOLATILE               ((psa_key_lifetime_t)0x00000000)
+
+/** A persistent key slot retains its content as long as it is not explicitly
+ * destroyed.
+ */
+#define PSA_KEY_LIFETIME_PERSISTENT             ((psa_key_lifetime_t)0x00000001)
+
+/** A write-once key slot may not be modified once a key has been set.
+ * It will retain its content as long as the device remains operational.
+ */
+#define PSA_KEY_LIFETIME_WRITE_ONCE             ((psa_key_lifetime_t)0x7fffffff)
+
+/** \brief Retrieve the lifetime of a key slot.
+ *
+ * The assignment of lifetimes to slots is implementation-dependent.
+ *
+ * \param key           Slot to query.
+ * \param[out] lifetime On success, the lifetime value.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         The key slot is invalid.
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_get_key_lifetime(psa_key_slot_t key,
+                                  psa_key_lifetime_t *lifetime);
+
+/** \brief Change the lifetime of a key slot.
+ *
+ * Whether the lifetime of a key slot can be changed at all, and if so
+ * whether the lifetime of an occupied key slot can be changed, is
+ * implementation-dependent.
+ *
+ * \param key           Slot whose lifetime is to be changed.
+ * \param lifetime      The lifetime value to set for the given key slot.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         The key slot is invalid,
+ *         or the lifetime value is invalid.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         The implementation does not support the specified lifetime value,
+ *         at least for the specified key slot.
+ * \retval #PSA_ERROR_OCCUPIED_SLOT
+ *         The slot contains a key, and the implementation does not support
+ *         changing the lifetime of an occupied slot.
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_set_key_lifetime(psa_key_slot_t key,
+                                  psa_key_lifetime_t lifetime);
+
+/**@}*/
+
+/** \defgroup hash Message digests
+ * @{
+ */
+
+/** The type of the state data structure for multipart hash operations.
+ *
+ * This is an implementation-defined \c struct. Applications should not
+ * make any assumptions about the content of this structure except
+ * as directed by the documentation of a specific implementation. */
+typedef struct psa_hash_operation_s psa_hash_operation_t;
+
+/** The size of the output of psa_hash_finish(), in bytes.
+ *
+ * This is also the hash size that psa_hash_verify() expects.
+ *
+ * \param alg   A hash algorithm (\c PSA_ALG_XXX value such that
+ *              #PSA_ALG_IS_HASH(\p alg) is true), or an HMAC algorithm
+ *              (#PSA_ALG_HMAC(\c hash_alg) where \c hash_alg is a
+ *              hash algorithm).
+ *
+ * \return The hash size for the specified hash algorithm.
+ *         If the hash algorithm is not recognized, return 0.
+ *         An implementation may return either 0 or the correct size
+ *         for a hash algorithm that it recognizes, but does not support.
+ */
+#define PSA_HASH_SIZE(alg)                                      \
+    (                                                           \
+        PSA_ALG_HMAC_HASH(alg) == PSA_ALG_MD2 ? 16 :            \
+        PSA_ALG_HMAC_HASH(alg) == PSA_ALG_MD4 ? 16 :            \
+        PSA_ALG_HMAC_HASH(alg) == PSA_ALG_MD5 ? 16 :            \
+        PSA_ALG_HMAC_HASH(alg) == PSA_ALG_RIPEMD160 ? 20 :      \
+        PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA_1 ? 20 :          \
+        PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA_224 ? 28 :        \
+        PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA_256 ? 32 :        \
+        PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA_384 ? 48 :        \
+        PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA_512 ? 64 :        \
+        PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA_512_224 ? 28 :    \
+        PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA_512_256 ? 32 :    \
+        PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA3_224 ? 28 :       \
+        PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA3_256 ? 32 :       \
+        PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA3_384 ? 48 :       \
+        PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA3_512 ? 64 :       \
+        0)
+
+/** Start a multipart hash operation.
+ *
+ * The sequence of operations to calculate a hash (message digest)
+ * is as follows:
+ * -# Allocate an operation object which will be passed to all the functions
+ *    listed here.
+ * -# Call psa_hash_setup() to specify the algorithm.
+ * -# Call psa_hash_update() zero, one or more times, passing a fragment
+ *    of the message each time. The hash that is calculated is the hash
+ *    of the concatenation of these messages in order.
+ * -# To calculate the hash, call psa_hash_finish().
+ *    To compare the hash with an expected value, call psa_hash_verify().
+ *
+ * The application may call psa_hash_abort() at any time after the operation
+ * has been initialized with psa_hash_setup().
+ *
+ * After a successful call to psa_hash_setup(), the application must
+ * eventually terminate the operation. The following events terminate an
+ * operation:
+ * - A failed call to psa_hash_update().
+ * - A call to psa_hash_finish(), psa_hash_verify() or psa_hash_abort().
+ *
+ * \param[out] operation    The operation object to use.
+ * \param alg               The hash algorithm to compute (\c PSA_ALG_XXX value
+ *                          such that #PSA_ALG_IS_HASH(\p alg) is true).
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p alg is not supported or is not a hash algorithm.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_hash_setup(psa_hash_operation_t *operation,
+                            psa_algorithm_t alg);
+
+/** Add a message fragment to a multipart hash operation.
+ *
+ * The application must call psa_hash_setup() before calling this function.
+ *
+ * If this function returns an error status, the operation becomes inactive.
+ *
+ * \param[in,out] operation Active hash operation.
+ * \param[in] input         Buffer containing the message fragment to hash.
+ * \param input_length      Size of the \p input buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid (not started, or already completed).
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_hash_update(psa_hash_operation_t *operation,
+                             const uint8_t *input,
+                             size_t input_length);
+
+/** Finish the calculation of the hash of a message.
+ *
+ * The application must call psa_hash_setup() before calling this function.
+ * This function calculates the hash of the message formed by concatenating
+ * the inputs passed to preceding calls to psa_hash_update().
+ *
+ * When this function returns, the operation becomes inactive.
+ *
+ * \warning Applications should not call this function if they expect
+ *          a specific value for the hash. Call psa_hash_verify() instead.
+ *          Beware that comparing integrity or authenticity data such as
+ *          hash values with a function such as \c memcmp is risky
+ *          because the time taken by the comparison may leak information
+ *          about the hashed data which could allow an attacker to guess
+ *          a valid hash and thereby bypass security controls.
+ *
+ * \param[in,out] operation     Active hash operation.
+ * \param[out] hash             Buffer where the hash is to be written.
+ * \param hash_size             Size of the \p hash buffer in bytes.
+ * \param[out] hash_length      On success, the number of bytes
+ *                              that make up the hash value. This is always
+ *                              #PSA_HASH_SIZE(\c alg) where \c alg is the
+ *                              hash algorithm that is calculated.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid (not started, or already completed).
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p hash buffer is too small. You can determine a
+ *         sufficient buffer size by calling #PSA_HASH_SIZE(\c alg)
+ *         where \c alg is the hash algorithm that is calculated.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_hash_finish(psa_hash_operation_t *operation,
+                             uint8_t *hash,
+                             size_t hash_size,
+                             size_t *hash_length);
+
+/** Finish the calculation of the hash of a message and compare it with
+ * an expected value.
+ *
+ * The application must call psa_hash_setup() before calling this function.
+ * This function calculates the hash of the message formed by concatenating
+ * the inputs passed to preceding calls to psa_hash_update(). It then
+ * compares the calculated hash with the expected hash passed as a
+ * parameter to this function.
+ *
+ * When this function returns, the operation becomes inactive.
+ *
+ * \note Implementations shall make the best effort to ensure that the
+ * comparison between the actual hash and the expected hash is performed
+ * in constant time.
+ *
+ * \param[in,out] operation     Active hash operation.
+ * \param[in] hash              Buffer containing the expected hash value.
+ * \param hash_length           Size of the \p hash buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         The expected hash is identical to the actual hash of the message.
+ * \retval #PSA_ERROR_INVALID_SIGNATURE
+ *         The hash of the message was calculated successfully, but it
+ *         differs from the expected hash.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid (not started, or already completed).
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_hash_verify(psa_hash_operation_t *operation,
+                             const uint8_t *hash,
+                             size_t hash_length);
+
+/** Abort a hash operation.
+ *
+ * Aborting an operation frees all associated resources except for the
+ * \p operation structure itself. Once aborted, the operation object
+ * can be reused for another operation by calling
+ * psa_hash_setup() again.
+ *
+ * You may call this function any time after the operation object has
+ * been initialized by any of the following methods:
+ * - A call to psa_hash_setup(), whether it succeeds or not.
+ * - Initializing the \c struct to all-bits-zero.
+ * - Initializing the \c struct to logical zeros, e.g.
+ *   `psa_hash_operation_t operation = {0}`.
+ *
+ * In particular, calling psa_hash_abort() after the operation has been
+ * terminated by a call to psa_hash_abort(), psa_hash_finish() or
+ * psa_hash_verify() is safe and has no effect.
+ *
+ * \param[in,out] operation     Initialized hash operation.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_BAD_STATE
+ *         \p operation is not an active hash operation.
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_hash_abort(psa_hash_operation_t *operation);
+
+/**@}*/
+
+/** \defgroup MAC Message authentication codes
+ * @{
+ */
+
+/** The type of the state data structure for multipart MAC operations.
+ *
+ * This is an implementation-defined \c struct. Applications should not
+ * make any assumptions about the content of this structure except
+ * as directed by the documentation of a specific implementation. */
+typedef struct psa_mac_operation_s psa_mac_operation_t;
+
+/** Start a multipart MAC calculation operation.
+ *
+ * This function sets up the calculation of the MAC
+ * (message authentication code) of a byte string.
+ * To verify the MAC of a message against an
+ * expected value, use psa_mac_verify_setup() instead.
+ *
+ * The sequence of operations to calculate a MAC is as follows:
+ * -# Allocate an operation object which will be passed to all the functions
+ *    listed here.
+ * -# Call psa_mac_sign_setup() to specify the algorithm and key.
+ *    The key remains associated with the operation even if the content
+ *    of the key slot changes.
+ * -# Call psa_mac_update() zero, one or more times, passing a fragment
+ *    of the message each time. The MAC that is calculated is the MAC
+ *    of the concatenation of these messages in order.
+ * -# At the end of the message, call psa_mac_sign_finish() to finish
+ *    calculating the MAC value and retrieve it.
+ *
+ * The application may call psa_mac_abort() at any time after the operation
+ * has been initialized with psa_mac_sign_setup().
+ *
+ * After a successful call to psa_mac_sign_setup(), the application must
+ * eventually terminate the operation through one of the following methods:
+ * - A failed call to psa_mac_update().
+ * - A call to psa_mac_sign_finish() or psa_mac_abort().
+ *
+ * \param[out] operation    The operation object to use.
+ * \param key               Slot containing the key to use for the operation.
+ * \param alg               The MAC algorithm to compute (\c PSA_ALG_XXX value
+ *                          such that #PSA_ALG_IS_MAC(alg) is true).
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_EMPTY_SLOT
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         \p key is not compatible with \p alg.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p alg is not supported or is not a MAC algorithm.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation,
+                                psa_key_slot_t key,
+                                psa_algorithm_t alg);
+
+/** Start a multipart MAC verification operation.
+ *
+ * This function sets up the verification of the MAC
+ * (message authentication code) of a byte string against an expected value.
+ *
+ * The sequence of operations to verify a MAC is as follows:
+ * -# Allocate an operation object which will be passed to all the functions
+ *    listed here.
+ * -# Call psa_mac_verify_setup() to specify the algorithm and key.
+ *    The key remains associated with the operation even if the content
+ *    of the key slot changes.
+ * -# Call psa_mac_update() zero, one or more times, passing a fragment
+ *    of the message each time. The MAC that is calculated is the MAC
+ *    of the concatenation of these messages in order.
+ * -# At the end of the message, call psa_mac_verify_finish() to finish
+ *    calculating the actual MAC of the message and verify it against
+ *    the expected value.
+ *
+ * The application may call psa_mac_abort() at any time after the operation
+ * has been initialized with psa_mac_verify_setup().
+ *
+ * After a successful call to psa_mac_verify_setup(), the application must
+ * eventually terminate the operation through one of the following methods:
+ * - A failed call to psa_mac_update().
+ * - A call to psa_mac_verify_finish() or psa_mac_abort().
+ *
+ * \param[out] operation    The operation object to use.
+ * \param key               Slot containing the key to use for the operation.
+ * \param alg               The MAC algorithm to compute (\c PSA_ALG_XXX value
+ *                          such that #PSA_ALG_IS_MAC(\p alg) is true).
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_EMPTY_SLOT
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         \c key is not compatible with \c alg.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \c alg is not supported or is not a MAC algorithm.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation,
+                                  psa_key_slot_t key,
+                                  psa_algorithm_t alg);
+
+/** Add a message fragment to a multipart MAC operation.
+ *
+ * The application must call psa_mac_sign_setup() or psa_mac_verify_setup()
+ * before calling this function.
+ *
+ * If this function returns an error status, the operation becomes inactive.
+ *
+ * \param[in,out] operation Active MAC operation.
+ * \param[in] input         Buffer containing the message fragment to add to
+ *                          the MAC calculation.
+ * \param input_length      Size of the \p input buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid (not started, or already completed).
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_mac_update(psa_mac_operation_t *operation,
+                            const uint8_t *input,
+                            size_t input_length);
+
+/** Finish the calculation of the MAC of a message.
+ *
+ * The application must call psa_mac_sign_setup() before calling this function.
+ * This function calculates the MAC of the message formed by concatenating
+ * the inputs passed to preceding calls to psa_mac_update().
+ *
+ * When this function returns, the operation becomes inactive.
+ *
+ * \warning Applications should not call this function if they expect
+ *          a specific value for the MAC. Call psa_mac_verify_finish() instead.
+ *          Beware that comparing integrity or authenticity data such as
+ *          MAC values with a function such as \c memcmp is risky
+ *          because the time taken by the comparison may leak information
+ *          about the MAC value which could allow an attacker to guess
+ *          a valid MAC and thereby bypass security controls.
+ *
+ * \param[in,out] operation Active MAC operation.
+ * \param[out] mac          Buffer where the MAC value is to be written.
+ * \param mac_size          Size of the \p mac buffer in bytes.
+ * \param[out] mac_length   On success, the number of bytes
+ *                          that make up the MAC value. This is always
+ *                          #PSA_MAC_FINAL_SIZE(\c key_type, \c key_bits, \c alg)
+ *                          where \c key_type and \c key_bits are the type and
+ *                          bit-size respectively of the key and \c alg is the
+ *                          MAC algorithm that is calculated.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid (not started, or already completed).
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p mac buffer is too small. You can determine a
+ *         sufficient buffer size by calling PSA_MAC_FINAL_SIZE().
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation,
+                                 uint8_t *mac,
+                                 size_t mac_size,
+                                 size_t *mac_length);
+
+/** Finish the calculation of the MAC of a message and compare it with
+ * an expected value.
+ *
+ * The application must call psa_mac_verify_setup() before calling this function.
+ * This function calculates the MAC of the message formed by concatenating
+ * the inputs passed to preceding calls to psa_mac_update(). It then
+ * compares the calculated MAC with the expected MAC passed as a
+ * parameter to this function.
+ *
+ * When this function returns, the operation becomes inactive.
+ *
+ * \note Implementations shall make the best effort to ensure that the
+ * comparison between the actual MAC and the expected MAC is performed
+ * in constant time.
+ *
+ * \param[in,out] operation Active MAC operation.
+ * \param[in] mac           Buffer containing the expected MAC value.
+ * \param mac_length        Size of the \p mac buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         The expected MAC is identical to the actual MAC of the message.
+ * \retval #PSA_ERROR_INVALID_SIGNATURE
+ *         The MAC of the message was calculated successfully, but it
+ *         differs from the expected MAC.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid (not started, or already completed).
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation,
+                                   const uint8_t *mac,
+                                   size_t mac_length);
+
+/** Abort a MAC operation.
+ *
+ * Aborting an operation frees all associated resources except for the
+ * \p operation structure itself. Once aborted, the operation object
+ * can be reused for another operation by calling
+ * psa_mac_sign_setup() or psa_mac_verify_setup() again.
+ *
+ * You may call this function any time after the operation object has
+ * been initialized by any of the following methods:
+ * - A call to psa_mac_sign_setup() or psa_mac_verify_setup(), whether
+ *   it succeeds or not.
+ * - Initializing the \c struct to all-bits-zero.
+ * - Initializing the \c struct to logical zeros, e.g.
+ *   `psa_mac_operation_t operation = {0}`.
+ *
+ * In particular, calling psa_mac_abort() after the operation has been
+ * terminated by a call to psa_mac_abort(), psa_mac_sign_finish() or
+ * psa_mac_verify_finish() is safe and has no effect.
+ *
+ * \param[in,out] operation Initialized MAC operation.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_BAD_STATE
+ *         \p operation is not an active MAC operation.
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_mac_abort(psa_mac_operation_t *operation);
+
+/**@}*/
+
+/** \defgroup cipher Symmetric ciphers
+ * @{
+ */
+
+/** The type of the state data structure for multipart cipher operations.
+ *
+ * This is an implementation-defined \c struct. Applications should not
+ * make any assumptions about the content of this structure except
+ * as directed by the documentation of a specific implementation. */
+typedef struct psa_cipher_operation_s psa_cipher_operation_t;
+
+/** Set the key for a multipart symmetric encryption operation.
+ *
+ * The sequence of operations to encrypt a message with a symmetric cipher
+ * is as follows:
+ * -# Allocate an operation object which will be passed to all the functions
+ *    listed here.
+ * -# Call psa_cipher_encrypt_setup() to specify the algorithm and key.
+ *    The key remains associated with the operation even if the content
+ *    of the key slot changes.
+ * -# Call either psa_cipher_generate_iv() or psa_cipher_set_iv() to
+ *    generate or set the IV (initialization vector). You should use
+ *    psa_cipher_generate_iv() unless the protocol you are implementing
+ *    requires a specific IV value.
+ * -# Call psa_cipher_update() zero, one or more times, passing a fragment
+ *    of the message each time.
+ * -# Call psa_cipher_finish().
+ *
+ * The application may call psa_cipher_abort() at any time after the operation
+ * has been initialized with psa_cipher_encrypt_setup().
+ *
+ * After a successful call to psa_cipher_encrypt_setup(), the application must
+ * eventually terminate the operation. The following events terminate an
+ * operation:
+ * - A failed call to psa_cipher_generate_iv(), psa_cipher_set_iv()
+ *   or psa_cipher_update().
+ * - A call to psa_cipher_finish() or psa_cipher_abort().
+ *
+ * \param[out] operation        The operation object to use.
+ * \param key                   Slot containing the key to use for the operation.
+ * \param alg                   The cipher algorithm to compute
+ *                              (\c PSA_ALG_XXX value such that
+ *                              #PSA_ALG_IS_CIPHER(\p alg) is true).
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_EMPTY_SLOT
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         \p key is not compatible with \p alg.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p alg is not supported or is not a cipher algorithm.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation,
+                                      psa_key_slot_t key,
+                                      psa_algorithm_t alg);
+
+/** Set the key for a multipart symmetric decryption operation.
+ *
+ * The sequence of operations to decrypt a message with a symmetric cipher
+ * is as follows:
+ * -# Allocate an operation object which will be passed to all the functions
+ *    listed here.
+ * -# Call psa_cipher_decrypt_setup() to specify the algorithm and key.
+ *    The key remains associated with the operation even if the content
+ *    of the key slot changes.
+ * -# Call psa_cipher_update() with the IV (initialization vector) for the
+ *    decryption. If the IV is prepended to the ciphertext, you can call
+ *    psa_cipher_update() on a buffer containing the IV followed by the
+ *    beginning of the message.
+ * -# Call psa_cipher_update() zero, one or more times, passing a fragment
+ *    of the message each time.
+ * -# Call psa_cipher_finish().
+ *
+ * The application may call psa_cipher_abort() at any time after the operation
+ * has been initialized with psa_cipher_decrypt_setup().
+ *
+ * After a successful call to psa_cipher_decrypt_setup(), the application must
+ * eventually terminate the operation. The following events terminate an
+ * operation:
+ * - A failed call to psa_cipher_update().
+ * - A call to psa_cipher_finish() or psa_cipher_abort().
+ *
+ * \param[out] operation        The operation object to use.
+ * \param key                   Slot containing the key to use for the operation.
+ * \param alg                   The cipher algorithm to compute
+ *                              (\c PSA_ALG_XXX value such that
+ *                              #PSA_ALG_IS_CIPHER(\p alg) is true).
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_EMPTY_SLOT
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         \p key is not compatible with \p alg.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p alg is not supported or is not a cipher algorithm.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation,
+                                      psa_key_slot_t key,
+                                      psa_algorithm_t alg);
+
+/** Generate an IV for a symmetric encryption operation.
+ *
+ * This function generates a random IV (initialization vector), nonce
+ * or initial counter value for the encryption operation as appropriate
+ * for the chosen algorithm, key type and key size.
+ *
+ * The application must call psa_cipher_encrypt_setup() before
+ * calling this function.
+ *
+ * If this function returns an error status, the operation becomes inactive.
+ *
+ * \param[in,out] operation     Active cipher operation.
+ * \param[out] iv               Buffer where the generated IV is to be written.
+ * \param iv_size               Size of the \p iv buffer in bytes.
+ * \param[out] iv_length        On success, the number of bytes of the
+ *                              generated IV.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid (not started, or IV already set).
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p iv buffer is too small.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation,
+                                    unsigned char *iv,
+                                    size_t iv_size,
+                                    size_t *iv_length);
+
+/** Set the IV for a symmetric encryption or decryption operation.
+ *
+ * This function sets the random IV (initialization vector), nonce
+ * or initial counter value for the encryption or decryption operation.
+ *
+ * The application must call psa_cipher_encrypt_setup() before
+ * calling this function.
+ *
+ * If this function returns an error status, the operation becomes inactive.
+ *
+ * \note When encrypting, applications should use psa_cipher_generate_iv()
+ * instead of this function, unless implementing a protocol that requires
+ * a non-random IV.
+ *
+ * \param[in,out] operation     Active cipher operation.
+ * \param[in] iv                Buffer containing the IV to use.
+ * \param iv_length             Size of the IV in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid (not started, or IV already set).
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         The size of \p iv is not acceptable for the chosen algorithm,
+ *         or the chosen algorithm does not use an IV.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation,
+                               const unsigned char *iv,
+                               size_t iv_length);
+
+/** Encrypt or decrypt a message fragment in an active cipher operation.
+ *
+ * Before calling this function, you must:
+ * 1. Call either psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup().
+ *    The choice of setup function determines whether this function
+ *    encrypts or decrypts its input.
+ * 2. If the algorithm requires an IV, call psa_cipher_generate_iv()
+ *    (recommended when encrypting) or psa_cipher_set_iv().
+ *
+ * If this function returns an error status, the operation becomes inactive.
+ *
+ * \param[in,out] operation     Active cipher operation.
+ * \param[in] input             Buffer containing the message fragment to
+ *                              encrypt or decrypt.
+ * \param input_length          Size of the \p input buffer in bytes.
+ * \param[out] output           Buffer where the output is to be written.
+ * \param output_size           Size of the \p output buffer in bytes.
+ * \param[out] output_length    On success, the number of bytes
+ *                              that make up the returned output.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid (not started, IV required but
+ *         not set, or already completed).
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p output buffer is too small.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_cipher_update(psa_cipher_operation_t *operation,
+                               const uint8_t *input,
+                               size_t input_length,
+                               unsigned char *output,
+                               size_t output_size,
+                               size_t *output_length);
+
+/** Finish encrypting or decrypting a message in a cipher operation.
+ *
+ * The application must call psa_cipher_encrypt_setup() or
+ * psa_cipher_decrypt_setup() before calling this function. The choice
+ * of setup function determines whether this function encrypts or
+ * decrypts its input.
+ *
+ * This function finishes the encryption or decryption of the message
+ * formed by concatenating the inputs passed to preceding calls to
+ * psa_cipher_update().
+ *
+ * When this function returns, the operation becomes inactive.
+ *
+ * \param[in,out] operation     Active cipher operation.
+ * \param[out] output           Buffer where the output is to be written.
+ * \param output_size           Size of the \p output buffer in bytes.
+ * \param[out] output_length    On success, the number of bytes
+ *                              that make up the returned output.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid (not started, IV required but
+ *         not set, or already completed).
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p output buffer is too small.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation,
+                               uint8_t *output,
+                               size_t output_size,
+                               size_t *output_length);
+
+/** Abort a cipher operation.
+ *
+ * Aborting an operation frees all associated resources except for the
+ * \p operation structure itself. Once aborted, the operation object
+ * can be reused for another operation by calling
+ * psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup() again.
+ *
+ * You may call this function any time after the operation object has
+ * been initialized by any of the following methods:
+ * - A call to psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup(),
+ *   whether it succeeds or not.
+ * - Initializing the \c struct to all-bits-zero.
+ * - Initializing the \c struct to logical zeros, e.g.
+ *   `psa_cipher_operation_t operation = {0}`.
+ *
+ * In particular, calling psa_cipher_abort() after the operation has been
+ * terminated by a call to psa_cipher_abort() or psa_cipher_finish()
+ * is safe and has no effect.
+ *
+ * \param[in,out] operation     Initialized cipher operation.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_BAD_STATE
+ *         \p operation is not an active cipher operation.
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation);
+
+/**@}*/
+
+/** \defgroup aead Authenticated encryption with associated data (AEAD)
+ * @{
+ */
+
+/** The tag size for an AEAD algorithm, in bytes.
+ *
+ * \param alg                 An AEAD algorithm
+ *                            (\c PSA_ALG_XXX value such that
+ *                            #PSA_ALG_IS_AEAD(\p alg) is true).
+ *
+ * \return                    The tag size for the specified algorithm.
+ *                            If the AEAD algorithm does not have an identified
+ *                            tag that can be distinguished from the rest of
+ *                            the ciphertext, return 0.
+ *                            If the AEAD algorithm is not recognized, return 0.
+ *                            An implementation may return either 0 or a
+ *                            correct size for an AEAD algorithm that it
+ *                            recognizes, but does not support.
+ */
+#define PSA_AEAD_TAG_SIZE(alg)             \
+    ((alg) == PSA_ALG_GCM ? 16 :           \
+     (alg) == PSA_ALG_CCM ? 16 :           \
+     0)
+
+/** Process an authenticated encryption operation.
+ *
+ * \param key                     Slot containing the key to use.
+ * \param alg                     The AEAD algorithm to compute
+ *                                (\c PSA_ALG_XXX value such that
+ *                                #PSA_ALG_IS_AEAD(\p alg) is true).
+ * \param[in] nonce               Nonce or IV to use.
+ * \param nonce_length            Size of the \p nonce buffer in bytes.
+ * \param[in] additional_data     Additional data that will be authenticated
+ *                                but not encrypted.
+ * \param additional_data_length  Size of \p additional_data in bytes.
+ * \param[in] plaintext           Data that will be authenticated and
+ *                                encrypted.
+ * \param plaintext_length        Size of \p plaintext in bytes.
+ * \param[out] ciphertext         Output buffer for the authenticated and
+ *                                encrypted data. The additional data is not
+ *                                part of this output. For algorithms where the
+ *                                encrypted data and the authentication tag
+ *                                are defined as separate outputs, the
+ *                                authentication tag is appended to the
+ *                                encrypted data.
+ * \param ciphertext_size         Size of the \p ciphertext buffer in bytes.
+ *                                This must be at least
+ *                                #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(\p alg,
+ *                                \p plaintext_length).
+ * \param[out] ciphertext_length  On success, the size of the output
+ *                                in the \b ciphertext buffer.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_EMPTY_SLOT
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         \p key is not compatible with \p alg.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p alg is not supported or is not an AEAD algorithm.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_aead_encrypt(psa_key_slot_t key,
+                              psa_algorithm_t alg,
+                              const uint8_t *nonce,
+                              size_t nonce_length,
+                              const uint8_t *additional_data,
+                              size_t additional_data_length,
+                              const uint8_t *plaintext,
+                              size_t plaintext_length,
+                              uint8_t *ciphertext,
+                              size_t ciphertext_size,
+                              size_t *ciphertext_length);
+
+/** Process an authenticated decryption operation.
+ *
+ * \param key                     Slot containing the key to use.
+ * \param alg                     The AEAD algorithm to compute
+ *                                (\c PSA_ALG_XXX value such that
+ *                                #PSA_ALG_IS_AEAD(\p alg) is true).
+ * \param[in] nonce               Nonce or IV to use.
+ * \param nonce_length            Size of the \p nonce buffer in bytes.
+ * \param[in] additional_data     Additional data that has been authenticated
+ *                                but not encrypted.
+ * \param additional_data_length  Size of \p additional_data in bytes.
+ * \param[in] ciphertext          Data that has been authenticated and
+ *                                encrypted. For algorithms where the
+ *                                encrypted data and the authentication tag
+ *                                are defined as separate inputs, the buffer
+ *                                must contain the encrypted data followed
+ *                                by the authentication tag.
+ * \param ciphertext_length       Size of \p ciphertext in bytes.
+ * \param[out] plaintext          Output buffer for the decrypted data.
+ * \param plaintext_size          Size of the \p plaintext buffer in bytes.
+ *                                This must be at least
+ *                                #PSA_AEAD_DECRYPT_OUTPUT_SIZE(\p alg,
+ *                                \p ciphertext_length).
+ * \param[out] plaintext_length   On success, the size of the output
+ *                                in the \b plaintext buffer.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_EMPTY_SLOT
+ * \retval #PSA_ERROR_INVALID_SIGNATURE
+ *         The ciphertext is not authentic.
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         \p key is not compatible with \p alg.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p alg is not supported or is not an AEAD algorithm.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_aead_decrypt(psa_key_slot_t key,
+                              psa_algorithm_t alg,
+                              const uint8_t *nonce,
+                              size_t nonce_length,
+                              const uint8_t *additional_data,
+                              size_t additional_data_length,
+                              const uint8_t *ciphertext,
+                              size_t ciphertext_length,
+                              uint8_t *plaintext,
+                              size_t plaintext_size,
+                              size_t *plaintext_length);
+
+/**@}*/
+
+/** \defgroup asymmetric Asymmetric cryptography
+ * @{
+ */
+
+/**
+ * \brief ECDSA signature size for a given curve bit size
+ *
+ * \param curve_bits    Curve size in bits.
+ * \return              Signature size in bytes.
+ *
+ * \note This macro returns a compile-time constant if its argument is one.
+ */
+#define PSA_ECDSA_SIGNATURE_SIZE(curve_bits)    \
+    (PSA_BITS_TO_BYTES(curve_bits) * 2)
+
+/**
+ * \brief Sign a hash or short message with a private key.
+ *
+ * Note that to perform a hash-and-sign signature algorithm, you must
+ * first calculate the hash by calling psa_hash_setup(), psa_hash_update()
+ * and psa_hash_finish(). Then pass the resulting hash as the \p hash
+ * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg)
+ * to determine the hash algorithm to use.
+ *
+ * \param key                   Key slot containing an asymmetric key pair.
+ * \param alg                   A signature algorithm that is compatible with
+ *                              the type of \p key.
+ * \param[in] hash              The hash or message to sign.
+ * \param hash_length           Size of the \p hash buffer in bytes.
+ * \param[out] signature        Buffer where the signature is to be written.
+ * \param signature_size        Size of the \p signature buffer in bytes.
+ * \param[out] signature_length On success, the number of bytes
+ *                              that make up the returned signature value.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p signature buffer is too small. You can
+ *         determine a sufficient buffer size by calling
+ *         #PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg)
+ *         where \c key_type and \c key_bits are the type and bit-size
+ *         respectively of \p key.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
+ */
+psa_status_t psa_asymmetric_sign(psa_key_slot_t key,
+                                 psa_algorithm_t alg,
+                                 const uint8_t *hash,
+                                 size_t hash_length,
+                                 uint8_t *signature,
+                                 size_t signature_size,
+                                 size_t *signature_length);
+
+/**
+ * \brief Verify the signature a hash or short message using a public key.
+ *
+ * Note that to perform a hash-and-sign signature algorithm, you must
+ * first calculate the hash by calling psa_hash_setup(), psa_hash_update()
+ * and psa_hash_finish(). Then pass the resulting hash as the \p hash
+ * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg)
+ * to determine the hash algorithm to use.
+ *
+ * \param key               Key slot containing a public key or an
+ *                          asymmetric key pair.
+ * \param alg               A signature algorithm that is compatible with
+ *                          the type of \p key.
+ * \param[in] hash          The hash or message whose signature is to be
+ *                          verified.
+ * \param hash_length       Size of the \p hash buffer in bytes.
+ * \param[in] signature     Buffer containing the signature to verify.
+ * \param signature_length  Size of the \p signature buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         The signature is valid.
+ * \retval #PSA_ERROR_INVALID_SIGNATURE
+ *         The calculation was perfomed successfully, but the passed
+ *         signature is not a valid signature.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_asymmetric_verify(psa_key_slot_t key,
+                                   psa_algorithm_t alg,
+                                   const uint8_t *hash,
+                                   size_t hash_length,
+                                   const uint8_t *signature,
+                                   size_t signature_length);
+
+#define PSA_RSA_MINIMUM_PADDING_SIZE(alg)                               \
+    (PSA_ALG_IS_RSA_OAEP(alg) ?                                         \
+     2 * PSA_HASH_FINAL_SIZE(PSA_ALG_RSA_OAEP_GET_HASH(alg)) + 1 :      \
+     11 /*PKCS#1v1.5*/)
+
+/**
+ * \brief Encrypt a short message with a public key.
+ *
+ * \param key                   Key slot containing a public key or an
+ *                              asymmetric key pair.
+ * \param alg                   An asymmetric encryption algorithm that is
+ *                              compatible with the type of \p key.
+ * \param[in] input             The message to encrypt.
+ * \param input_length          Size of the \p input buffer in bytes.
+ * \param[in] salt              A salt or label, if supported by the
+ *                              encryption algorithm.
+ *                              If the algorithm does not support a
+ *                              salt, pass \c NULL.
+ *                              If the algorithm supports an optional
+ *                              salt and you do not want to pass a salt,
+ *                              pass \c NULL.
+ *
+ *                              - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is
+ *                                supported.
+ * \param salt_length           Size of the \p salt buffer in bytes.
+ *                              If \p salt is \c NULL, pass 0.
+ * \param[out] output           Buffer where the encrypted message is to
+ *                              be written.
+ * \param output_size           Size of the \p output buffer in bytes.
+ * \param[out] output_length    On success, the number of bytes
+ *                              that make up the returned output.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p output buffer is too small. You can
+ *         determine a sufficient buffer size by calling
+ *         #PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg)
+ *         where \c key_type and \c key_bits are the type and bit-size
+ *         respectively of \p key.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
+ */
+psa_status_t psa_asymmetric_encrypt(psa_key_slot_t key,
+                                    psa_algorithm_t alg,
+                                    const uint8_t *input,
+                                    size_t input_length,
+                                    const uint8_t *salt,
+                                    size_t salt_length,
+                                    uint8_t *output,
+                                    size_t output_size,
+                                    size_t *output_length);
+
+/**
+ * \brief Decrypt a short message with a private key.
+ *
+ * \param key                   Key slot containing an asymmetric key pair.
+ * \param alg                   An asymmetric encryption algorithm that is
+ *                              compatible with the type of \p key.
+ * \param[in] input             The message to decrypt.
+ * \param input_length          Size of the \p input buffer in bytes.
+ * \param[in] salt              A salt or label, if supported by the
+ *                              encryption algorithm.
+ *                              If the algorithm does not support a
+ *                              salt, pass \c NULL.
+ *                              If the algorithm supports an optional
+ *                              salt and you do not want to pass a salt,
+ *                              pass \c NULL.
+ *
+ *                              - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is
+ *                                supported.
+ * \param salt_length           Size of the \p salt buffer in bytes.
+ *                              If \p salt is \c NULL, pass 0.
+ * \param[out] output           Buffer where the decrypted message is to
+ *                              be written.
+ * \param output_size           Size of the \c output buffer in bytes.
+ * \param[out] output_length    On success, the number of bytes
+ *                              that make up the returned output.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p output buffer is too small. You can
+ *         determine a sufficient buffer size by calling
+ *         #PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg)
+ *         where \c key_type and \c key_bits are the type and bit-size
+ *         respectively of \p key.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
+ * \retval #PSA_ERROR_INVALID_PADDING
+ */
+psa_status_t psa_asymmetric_decrypt(psa_key_slot_t key,
+                                    psa_algorithm_t alg,
+                                    const uint8_t *input,
+                                    size_t input_length,
+                                    const uint8_t *salt,
+                                    size_t salt_length,
+                                    uint8_t *output,
+                                    size_t output_size,
+                                    size_t *output_length);
+
+/**@}*/
+
+/** \defgroup generators Generators
+ * @{
+ */
+
+/** The type of the state data structure for generators.
+ *
+ * Before calling any function on a generator, the application must
+ * initialize it by any of the following means:
+ * - Set the structure to all-bits-zero, for example:
+ *   \code
+ *   psa_crypto_generator_t generator;
+ *   memset(&generator, 0, sizeof(generator));
+ *   \endcode
+ * - Initialize the structure to logical zero values, for example:
+ *   \code
+ *   psa_crypto_generator_t generator = {0};
+ *   \endcode
+ * - Initialize the structure to the initializer #PSA_CRYPTO_GENERATOR_INIT,
+ *   for example:
+ *   \code
+ *   psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
+ *   \endcode
+ * - Assign the result of the function psa_crypto_generator_init()
+ *   to the structure, for example:
+ *   \code
+ *   psa_crypto_generator_t generator;
+ *   generator = psa_crypto_generator_init();
+ *   \endcode
+ *
+ * This is an implementation-defined \c struct. Applications should not
+ * make any assumptions about the content of this structure except
+ * as directed by the documentation of a specific implementation.
+ */
+typedef struct psa_crypto_generator_s psa_crypto_generator_t;
+
+/** \def PSA_CRYPTO_GENERATOR_INIT
+ *
+ * This macro returns a suitable initializer for a generator object
+ * of type #psa_crypto_generator_t.
+ */
+#ifdef __DOXYGEN_ONLY__
+/* This is an example definition for documentation purposes.
+ * Implementations should define a suitable value in `crypto_struct.h`.
+ */
+#define PSA_CRYPTO_GENERATOR_INIT {0}
+#endif
+
+/** Return an initial value for a generator object.
+ */
+static psa_crypto_generator_t psa_crypto_generator_init(void);
+
+/** Retrieve the current capacity of a generator.
+ *
+ * The capacity of a generator is the maximum number of bytes that it can
+ * return. Reading *N* bytes from a generator reduces its capacity by *N*.
+ *
+ * \param[in] generator     The generator to query.
+ * \param[out] capacity     On success, the capacity of the generator.
+ *
+ * \retval PSA_SUCCESS
+ * \retval PSA_ERROR_BAD_STATE
+ * \retval PSA_ERROR_COMMUNICATION_FAILURE
+ */
+psa_status_t psa_get_generator_capacity(const psa_crypto_generator_t *generator,
+                                        size_t *capacity);
+
+/** Read some data from a generator.
+ *
+ * This function reads and returns a sequence of bytes from a generator.
+ * The data that is read is discarded from the generator. The generator's
+ * capacity is decreased by the number of bytes read.
+ *
+ * \param[in,out] generator The generator object to read from.
+ * \param[out] output       Buffer where the generator output will be
+ *                          written.
+ * \param output_length     Number of bytes to output.
+ *
+ * \retval PSA_SUCCESS
+ * \retval PSA_ERROR_INSUFFICIENT_CAPACITY
+ *                          There were fewer than \p output_length bytes
+ *                          in the generator. Note that in this case, no
+ *                          output is written to the output buffer.
+ *                          The generator's capacity is set to 0, thus
+ *                          subsequent calls to this function will not
+ *                          succeed, even with a smaller output buffer.
+ * \retval PSA_ERROR_BAD_STATE
+ * \retval PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval PSA_ERROR_HARDWARE_FAILURE
+ * \retval PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_generator_read(psa_crypto_generator_t *generator,
+                                uint8_t *output,
+                                size_t output_length);
+
+/** Create a symmetric key from data read from a generator.
+ *
+ * This function reads a sequence of bytes from a generator and imports
+ * these bytes as a key.
+ * The data that is read is discarded from the generator. The generator's
+ * capacity is decreased by the number of bytes read.
+ *
+ * This function is equivalent to calling #psa_generator_read and
+ * passing the resulting output to #psa_import_key, but
+ * if the implementation provides an isolation boundary then
+ * the key material is not exposed outside the isolation boundary.
+ *
+ * \param key               Slot where the key will be stored. This must be a
+ *                          valid slot for a key of the chosen type. It must
+ *                          be unoccupied.
+ * \param type              Key type (a \c PSA_KEY_TYPE_XXX value).
+ *                          This must be a symmetric key type.
+ * \param bits              Key size in bits.
+ * \param[in,out] generator The generator object to read from.
+ *
+ * \retval PSA_SUCCESS
+ *         Success.
+ * \retval PSA_ERROR_INSUFFICIENT_CAPACITY
+ *                          There were fewer than \p output_length bytes
+ *                          in the generator. Note that in this case, no
+ *                          output is written to the output buffer.
+ *                          The generator's capacity is set to 0, thus
+ *                          subsequent calls to this function will not
+ *                          succeed, even with a smaller output buffer.
+ * \retval PSA_ERROR_NOT_SUPPORTED
+ *         The key type or key size is not supported, either by the
+ *         implementation in general or in this particular slot.
+ * \retval PSA_ERROR_BAD_STATE
+ * \retval PSA_ERROR_INVALID_ARGUMENT
+ *         The key slot is invalid.
+ * \retval PSA_ERROR_OCCUPIED_SLOT
+ *         There is already a key in the specified slot.
+ * \retval PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval PSA_ERROR_INSUFFICIENT_STORAGE
+ * \retval PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval PSA_ERROR_HARDWARE_FAILURE
+ * \retval PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_generator_import_key(psa_key_slot_t key,
+                                      psa_key_type_t type,
+                                      size_t bits,
+                                      psa_crypto_generator_t *generator);
+
+/** Abort a generator.
+ *
+ * Once a generator has been aborted, its capacity is zero.
+ * Aborting a generator frees all associated resources except for the
+ * \c generator structure itself.
+ *
+ * This function may be called at any time as long as the generator
+ * object has been initialized to #PSA_CRYPTO_GENERATOR_INIT, to
+ * psa_crypto_generator_init() or a zero value. In particular, it is valid
+ * to call psa_generator_abort() twice, or to call psa_generator_abort()
+ * on a generator that has not been set up.
+ *
+ * Once aborted, the generator object may be called.
+ *
+ * \param[in,out] generator    The generator to abort.
+ *
+ * \retval PSA_SUCCESS
+ * \retval PSA_ERROR_BAD_STATE
+ * \retval PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval PSA_ERROR_HARDWARE_FAILURE
+ * \retval PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_generator_abort(psa_crypto_generator_t *generator);
+
+/**@}*/
+
+/** \defgroup derivation Key derivation
+ * @{
+ */
+
+/** Set up a key derivation operation.
+ *
+ * A key derivation algorithm takes three inputs: a secret input \p key and
+ * two non-secret inputs \p label and p salt.
+ * The result of this function is a byte generator which can
+ * be used to produce keys and other cryptographic material.
+ *
+ * The role of \p label and \p salt is as follows:
+ * - For HKDF (#PSA_ALG_HKDF), \p salt is the salt used in the "extract" step
+ *   and \p label is the info string used in the "expand" step.
+ *
+ * \param[in,out] generator       The generator object to set up. It must
+ *                                have been initialized to .
+ * \param key                     Slot containing the secret key to use.
+ * \param alg                     The key derivation algorithm to compute
+ *                                (\c PSA_ALG_XXX value such that
+ *                                #PSA_ALG_IS_KEY_DERIVATION(\p alg) is true).
+ * \param[in] salt                Salt to use.
+ * \param salt_length             Size of the \p salt buffer in bytes.
+ * \param[in] label               Label to use.
+ * \param label_length            Size of the \p label buffer in bytes.
+ * \param capacity                The maximum number of bytes that the
+ *                                generator will be able to provide.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_EMPTY_SLOT
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         \c key is not compatible with \c alg,
+ *         or \p capacity is too large for the specified algorithm and key.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \c alg is not supported or is not a key derivation algorithm.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_key_derivation(psa_crypto_generator_t *generator,
+                                psa_key_slot_t key,
+                                psa_algorithm_t alg,
+                                const uint8_t *salt,
+                                size_t salt_length,
+                                const uint8_t *label,
+                                size_t label_length,
+                                size_t capacity);
+
+/**@}*/
+
+/** \defgroup random Random generation
+ * @{
+ */
+
+/**
+ * \brief Generate random bytes.
+ *
+ * \warning This function **can** fail! Callers MUST check the return status
+ *          and MUST NOT use the content of the output buffer if the return
+ *          status is not #PSA_SUCCESS.
+ *
+ * \note    To generate a key, use psa_generate_key() instead.
+ *
+ * \param[out] output       Output buffer for the generated data.
+ * \param output_size       Number of bytes to generate and output.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_generate_random(uint8_t *output,
+                                 size_t output_size);
+
+/** Extra parameters for RSA key generation.
+ *
+ * You may pass a pointer to a structure of this type as the \c extra
+ * parameter to psa_generate_key().
+ */
+typedef struct {
+    uint32_t e; /**< Public exponent value. Default: 65537. */
+} psa_generate_key_extra_rsa;
+
+/**
+ * \brief Generate a key or key pair.
+ *
+ * \param key               Slot where the key will be stored. This must be a
+ *                          valid slot for a key of the chosen type. It must
+ *                          be unoccupied.
+ * \param type              Key type (a \c PSA_KEY_TYPE_XXX value).
+ * \param bits              Key size in bits.
+ * \param[in] extra         Extra parameters for key generation. The
+ *                          interpretation of this parameter depends on
+ *                          \p type. All types support \c NULL to use
+ *                          default parameters. Implementation that support
+ *                          the generation of vendor-specific key types
+ *                          that allow extra parameters shall document
+ *                          the format of these extra parameters and
+ *                          the default values. For standard parameters,
+ *                          the meaning of \p extra is as follows:
+ *                          - For a symmetric key type (a type such
+ *                            that #PSA_KEY_TYPE_IS_ASYMMETRIC(\p type) is
+ *                            false), \p extra must be \c NULL.
+ *                          - For an elliptic curve key type (a type
+ *                            such that #PSA_KEY_TYPE_IS_ECC(\p type) is
+ *                            false), \p extra must be \c NULL.
+ *                          - For an RSA key (\p type is
+ *                            #PSA_KEY_TYPE_RSA_KEYPAIR), \p extra is an
+ *                            optional #psa_generate_key_extra_rsa structure
+ *                            specifying the public exponent. The
+ *                            default public exponent used when \p extra
+ *                            is \c NULL is 65537.
+ * \param extra_size        Size of the buffer that \p extra
+ *                          points to, in bytes. Note that if \p extra is
+ *                          \c NULL then \p extra_size must be zero.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_generate_key(psa_key_slot_t key,
+                              psa_key_type_t type,
+                              size_t bits,
+                              const void *extra,
+                              size_t extra_size);
+
+/**@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+/* The file "crypto_sizes.h" contains definitions for size calculation
+ * macros whose definitions are implementation-specific. */
+#include "crypto_sizes.h"
+
+/* The file "crypto_struct.h" contains definitions for
+ * implementation-specific structs that are declared above. */
+#include "crypto_struct.h"
+
+/* The file "crypto_extra.h" contains vendor-specific definitions. This
+ * can include vendor-defined algorithms, extra functions, etc. */
+#include "crypto_extra.h"
+
+#endif /* PSA_CRYPTO_H */
diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h
new file mode 100644
index 0000000..c587eb2
--- /dev/null
+++ b/include/psa/crypto_extra.h
@@ -0,0 +1,51 @@
+/**
+ * \file psa/crypto_extra.h
+ *
+ * \brief PSA cryptography module: Mbed Crypto vendor extensions
+ *
+ * \note This file may not be included directly. Applications must
+ * include psa/crypto.h.
+ *
+ * This file is reserved for vendor-specific definitions.
+ */
+/*
+ *  Copyright (C) 2018, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#ifndef PSA_CRYPTO_EXTRA_H
+#define PSA_CRYPTO_EXTRA_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Library deinitialization.
+ *
+ * This function clears all data associated with the PSA layer,
+ * including the whole key store.
+ *
+ * This is an Mbed Crypto extension.
+ */
+void mbedcrypto_psa_crypto_free( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PSA_CRYPTO_EXTRA_H */
diff --git a/include/psa/crypto_platform.h b/include/psa/crypto_platform.h
new file mode 100644
index 0000000..69ccd56
--- /dev/null
+++ b/include/psa/crypto_platform.h
@@ -0,0 +1,52 @@
+/**
+ * \file psa/crypto_platform.h
+ *
+ * \brief PSA cryptography module: Mbed Crypto platfom definitions
+ *
+ * \note This file may not be included directly. Applications must
+ * include psa/crypto.h.
+ *
+ * This file contains platform-dependent type definitions.
+ *
+ * In implementations with isolation between the application and the
+ * cryptography module, implementers should take care to ensure that
+ * the definitions that are exposed to applications match what the
+ * module implements.
+ */
+/*
+ *  Copyright (C) 2018, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#ifndef PSA_CRYPTO_PLATFORM_H
+#define PSA_CRYPTO_PLATFORM_H
+
+/* Include the Mbed Crypto configuration file, the way Mbed Crypto does it
+ * in each of its header files. */
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "../mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+/* PSA requires several types which C99 provides in stdint.h. */
+#include <stdint.h>
+
+/* Integral type representing a key slot number. */
+typedef uint16_t psa_key_slot_t;
+
+#endif /* PSA_CRYPTO_PLATFORM_H */
diff --git a/include/psa/crypto_sizes.h b/include/psa/crypto_sizes.h
new file mode 100644
index 0000000..9a0ae59
--- /dev/null
+++ b/include/psa/crypto_sizes.h
@@ -0,0 +1,308 @@
+/**
+ * \file psa/crypto_sizes.h
+ *
+ * \brief PSA cryptography module: Mbed Crypto buffer size macros
+ *
+ * \note This file may not be included directly. Applications must
+ * include psa/crypto.h.
+ *
+ * This file contains the definitions of macros that are useful to
+ * compute buffer sizes. The signatures and semantics of these macros
+ * are standardized, but the definitions are not, because they depend on
+ * the available algorithms and, in some cases, on permitted tolerances
+ * on buffer sizes.
+ *
+ * In implementations with isolation between the application and the
+ * cryptography module, implementers should take care to ensure that
+ * the definitions that are exposed to applications match what the
+ * module implements.
+ *
+ * Macros that compute sizes whose values do not depend on the
+ * implementation are in crypto.h.
+ */
+/*
+ *  Copyright (C) 2018, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#ifndef PSA_CRYPTO_SIZES_H
+#define PSA_CRYPTO_SIZES_H
+
+/* Include the Mbed Crypto configuration file, the way Mbed Crypto does it
+ * in each of its header files. */
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "../mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+/** \def PSA_HASH_MAX_SIZE
+ *
+ * Maximum size of a hash.
+ *
+ * This macro must expand to a compile-time constant integer. This value
+ * should be the maximum size of a hash supported by the implementation,
+ * in bytes, and must be no smaller than this maximum.
+ */
+#if defined(MBEDCRYPTO_SHA512_C)
+#define PSA_HASH_MAX_SIZE 64
+#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 128
+#else
+#define PSA_HASH_MAX_SIZE 32
+#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 64
+#endif
+
+/** \def PSA_MAC_MAX_SIZE
+ *
+ * Maximum size of a MAC.
+ *
+ * This macro must expand to a compile-time constant integer. This value
+ * should be the maximum size of a MAC supported by the implementation,
+ * in bytes, and must be no smaller than this maximum.
+ */
+/* All non-HMAC MACs have a maximum size that's smaller than the
+ * minimum possible value of PSA_HASH_MAX_SIZE in this implementation. */
+#define PSA_MAC_MAX_SIZE PSA_HASH_MAX_SIZE
+
+/* The maximum size of an RSA key on this implementation, in bits.
+ * This is a vendor-specific macro.
+ *
+ * Mbed Crypto does not set a hard limit on the size of RSA keys: any key
+ * whose parameters fit in a bignum is accepted. However large keys can
+ * induce a large memory usage and long computation times. Unlike other
+ * auxiliary macros in this file and in crypto.h, which reflect how the
+ * library is configured, this macro defines how the library is
+ * configured. This implementation refuses to import or generate an
+ * RSA key whose size is larger than the value defined here.
+ *
+ * Note that an implementation may set different size limits for different
+ * operations, and does not need to accept all key sizes up to the limit. */
+#define PSA_VENDOR_RSA_MAX_KEY_BITS 4096
+
+/* The maximum size of an ECC key on this implementation, in bits.
+ * This is a vendor-specific macro. */
+#if defined(MBEDCRYPTO_ECP_DP_SECP521R1_ENABLED)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 521
+#elif defined(MBEDCRYPTO_ECP_DP_BP512R1_ENABLED)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 512
+#elif defined(MBEDCRYPTO_ECP_DP_CURVE448_ENABLED)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 448
+#elif defined(MBEDCRYPTO_ECP_DP_SECP384R1_ENABLED)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 384
+#elif defined(MBEDCRYPTO_ECP_DP_BP384R1_ENABLED)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 384
+#elif defined(MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256
+#elif defined(MBEDCRYPTO_ECP_DP_SECP256K1_ENABLED)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256
+#elif defined(MBEDCRYPTO_ECP_DP_BP256R1_ENABLED)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256
+#elif defined(MBEDCRYPTO_ECP_DP_CURVE25519_ENABLED)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 255
+#elif defined(MBEDCRYPTO_ECP_DP_SECP224R1_ENABLED)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 224
+#elif defined(MBEDCRYPTO_ECP_DP_SECP224K1_ENABLED)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 224
+#elif defined(MBEDCRYPTO_ECP_DP_SECP192R1_ENABLED)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 192
+#elif defined(MBEDCRYPTO_ECP_DP_SECP192K1_ENABLED)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 192
+#else
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 0
+#endif
+
+/** \def PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE
+ *
+ * Maximum size of an asymmetric signature.
+ *
+ * This macro must expand to a compile-time constant integer. This value
+ * should be the maximum size of a MAC supported by the implementation,
+ * in bytes, and must be no smaller than this maximum.
+ */
+#define PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE                               \
+    PSA_BITS_TO_BYTES(                                                  \
+        PSA_VENDOR_RSA_MAX_KEY_BITS > PSA_VENDOR_ECC_MAX_CURVE_BITS ?   \
+        PSA_VENDOR_RSA_MAX_KEY_BITS :                                   \
+        PSA_VENDOR_ECC_MAX_CURVE_BITS                                   \
+        )
+
+
+
+/** The size of the output of psa_mac_sign_finish(), in bytes.
+ *
+ * This is also the MAC size that psa_mac_verify_finish() expects.
+ *
+ * \param key_type      The type of the MAC key.
+ * \param key_bits      The size of the MAC key in bits.
+ * \param alg           A MAC algorithm (\c PSA_ALG_XXX value such that
+ *                      #PSA_ALG_IS_MAC(alg) is true).
+ *
+ * \return              The MAC size for the specified algorithm with
+ *                      the specified key parameters.
+ * \return              0 if the MAC algorithm is not recognized.
+ * \return              Either 0 or the correct size for a MAC algorithm that
+ *                      the implementation recognizes, but does not support.
+ * \return              Unspecified if the key parameters are not consistent
+ *                      with the algorithm.
+ */
+#define PSA_MAC_FINAL_SIZE(key_type, key_bits, alg)                     \
+    (PSA_ALG_IS_HMAC(alg) ? PSA_HASH_SIZE(PSA_ALG_HMAC_HASH(alg)) : \
+     PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) ? PSA_BLOCK_CIPHER_BLOCK_SIZE(key_type) : \
+     0)
+
+/** The maximum size of the output of psa_aead_encrypt(), in bytes.
+ *
+ * If the size of the ciphertext buffer is at least this large, it is
+ * guaranteed that psa_aead_encrypt() will not fail due to an
+ * insufficient buffer size. Depending on the algorithm, the actual size of
+ * the ciphertext may be smaller.
+ *
+ * \param alg                 An AEAD algorithm
+ *                            (\c PSA_ALG_XXX value such that
+ *                            #PSA_ALG_IS_AEAD(alg) is true).
+ * \param plaintext_length    Size of the plaintext in bytes.
+ *
+ * \return                    The AEAD ciphertext size for the specified
+ *                            algorithm.
+ *                            If the AEAD algorithm is not recognized, return 0.
+ *                            An implementation may return either 0 or a
+ *                            correct size for an AEAD algorithm that it
+ *                            recognizes, but does not support.
+ */
+#define PSA_AEAD_ENCRYPT_OUTPUT_SIZE(alg, plaintext_length)     \
+    (PSA_AEAD_TAG_SIZE(alg) != 0 ?                              \
+     (plaintext_length) + PSA_AEAD_TAG_SIZE(alg) :              \
+     0)
+
+/** The maximum size of the output of psa_aead_decrypt(), in bytes.
+ *
+ * If the size of the plaintext buffer is at least this large, it is
+ * guaranteed that psa_aead_decrypt() will not fail due to an
+ * insufficient buffer size. Depending on the algorithm, the actual size of
+ * the plaintext may be smaller.
+ *
+ * \param alg                 An AEAD algorithm
+ *                            (\c PSA_ALG_XXX value such that
+ *                            #PSA_ALG_IS_AEAD(alg) is true).
+ * \param ciphertext_length   Size of the plaintext in bytes.
+ *
+ * \return                    The AEAD ciphertext size for the specified
+ *                            algorithm.
+ *                            If the AEAD algorithm is not recognized, return 0.
+ *                            An implementation may return either 0 or a
+ *                            correct size for an AEAD algorithm that it
+ *                            recognizes, but does not support.
+ */
+#define PSA_AEAD_DECRYPT_OUTPUT_SIZE(alg, ciphertext_length)    \
+    (PSA_AEAD_TAG_SIZE(alg) != 0 ?                              \
+     (plaintext_length) - PSA_AEAD_TAG_SIZE(alg) :              \
+     0)
+
+/** Safe signature buffer size for psa_asymmetric_sign().
+ *
+ * This macro returns a safe buffer size for a signature using a key
+ * of the specified type and size, with the specified algorithm.
+ * Note that the actual size of the signature may be smaller
+ * (some algorithms produce a variable-size signature).
+ *
+ * \warning This function may call its arguments multiple times or
+ *          zero times, so you should not pass arguments that contain
+ *          side effects.
+ *
+ * \param key_type  An asymmetric key type (this may indifferently be a
+ *                  key pair type or a public key type).
+ * \param key_bits  The size of the key in bits.
+ * \param alg       The signature algorithm.
+ *
+ * \return If the parameters are valid and supported, return
+ *         a buffer size in bytes that guarantees that
+ *         psa_asymmetric_sign() will not fail with
+ *         #PSA_ERROR_BUFFER_TOO_SMALL.
+ *         If the parameters are a valid combination that is not supported
+ *         by the implementation, this macro either shall return either a
+ *         sensible size or 0.
+ *         If the parameters are not valid, the
+ *         return value is unspecified.
+ */
+#define PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE(key_type, key_bits, alg)        \
+    (PSA_KEY_TYPE_IS_RSA(key_type) ? ((void)alg, PSA_BITS_TO_BYTES(key_bits)) : \
+     PSA_KEY_TYPE_IS_ECC(key_type) ? PSA_ECDSA_SIGNATURE_SIZE(key_bits) : \
+     ((void)alg, 0))
+
+/** Safe output buffer size for psa_asymmetric_encrypt().
+ *
+ * This macro returns a safe buffer size for a ciphertext produced using
+ * a key of the specified type and size, with the specified algorithm.
+ * Note that the actual size of the ciphertext may be smaller, depending
+ * on the algorithm.
+ *
+ * \warning This function may call its arguments multiple times or
+ *          zero times, so you should not pass arguments that contain
+ *          side effects.
+ *
+ * \param key_type  An asymmetric key type (this may indifferently be a
+ *                  key pair type or a public key type).
+ * \param key_bits  The size of the key in bits.
+ * \param alg       The signature algorithm.
+ *
+ * \return If the parameters are valid and supported, return
+ *         a buffer size in bytes that guarantees that
+ *         psa_asymmetric_encrypt() will not fail with
+ *         #PSA_ERROR_BUFFER_TOO_SMALL.
+ *         If the parameters are a valid combination that is not supported
+ *         by the implementation, this macro either shall return either a
+ *         sensible size or 0.
+ *         If the parameters are not valid, the
+ *         return value is unspecified.
+ */
+#define PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(key_type, key_bits, alg)     \
+    (PSA_KEY_TYPE_IS_RSA(key_type) ?                                    \
+     ((void)alg, PSA_BITS_TO_BYTES(key_bits)) :                         \
+     0)
+
+/** Safe output buffer size for psa_asymmetric_decrypt().
+ *
+ * This macro returns a safe buffer size for a ciphertext produced using
+ * a key of the specified type and size, with the specified algorithm.
+ * Note that the actual size of the ciphertext may be smaller, depending
+ * on the algorithm.
+ *
+ * \warning This function may call its arguments multiple times or
+ *          zero times, so you should not pass arguments that contain
+ *          side effects.
+ *
+ * \param key_type  An asymmetric key type (this may indifferently be a
+ *                  key pair type or a public key type).
+ * \param key_bits  The size of the key in bits.
+ * \param alg       The signature algorithm.
+ *
+ * \return If the parameters are valid and supported, return
+ *         a buffer size in bytes that guarantees that
+ *         psa_asymmetric_decrypt() will not fail with
+ *         #PSA_ERROR_BUFFER_TOO_SMALL.
+ *         If the parameters are a valid combination that is not supported
+ *         by the implementation, this macro either shall return either a
+ *         sensible size or 0.
+ *         If the parameters are not valid, the
+ *         return value is unspecified.
+ */
+#define PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(key_type, key_bits, alg)     \
+    (PSA_KEY_TYPE_IS_RSA(key_type) ?                                    \
+     PSA_BITS_TO_BYTES(key_bits) - PSA_RSA_MINIMUM_PADDING_SIZE(alg) :  \
+     0)
+
+#endif /* PSA_CRYPTO_SIZES_H */
diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h
new file mode 100644
index 0000000..5769a0c
--- /dev/null
+++ b/include/psa/crypto_struct.h
@@ -0,0 +1,177 @@
+/**
+ * \file psa/crypto_struct.h
+ *
+ * \brief PSA cryptography module: Mbed Crypto structured type implementations
+ *
+ * \note This file may not be included directly. Applications must
+ * include psa/crypto.h.
+ *
+ * This file contains the definitions of some data structures with
+ * implementation-specific definitions.
+ *
+ * In implementations with isolation between the application and the
+ * cryptography module, it is expected that the front-end and the back-end
+ * would have different versions of this file.
+ */
+/*
+ *  Copyright (C) 2018, ARM Limited, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#ifndef PSA_CRYPTO_STRUCT_H
+#define PSA_CRYPTO_STRUCT_H
+
+/* Include the Mbed Crypto configuration file, the way Mbed Crypto does it
+ * in each of its header files. */
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "../mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include "mbedcrypto/cipher.h"
+#include "mbedcrypto/cmac.h"
+#include "mbedcrypto/gcm.h"
+#include "mbedcrypto/md.h"
+#include "mbedcrypto/md2.h"
+#include "mbedcrypto/md4.h"
+#include "mbedcrypto/md5.h"
+#include "mbedcrypto/ripemd160.h"
+#include "mbedcrypto/sha1.h"
+#include "mbedcrypto/sha256.h"
+#include "mbedcrypto/sha512.h"
+
+struct psa_hash_operation_s
+{
+    psa_algorithm_t alg;
+    union
+    {
+        unsigned dummy; /* Make the union non-empty even with no supported algorithms. */
+#if defined(MBEDCRYPTO_MD2_C)
+        mbedcrypto_md2_context md2;
+#endif
+#if defined(MBEDCRYPTO_MD4_C)
+        mbedcrypto_md4_context md4;
+#endif
+#if defined(MBEDCRYPTO_MD5_C)
+        mbedcrypto_md5_context md5;
+#endif
+#if defined(MBEDCRYPTO_RIPEMD160_C)
+        mbedcrypto_ripemd160_context ripemd160;
+#endif
+#if defined(MBEDCRYPTO_SHA1_C)
+        mbedcrypto_sha1_context sha1;
+#endif
+#if defined(MBEDCRYPTO_SHA256_C)
+        mbedcrypto_sha256_context sha256;
+#endif
+#if defined(MBEDCRYPTO_SHA512_C)
+        mbedcrypto_sha512_context sha512;
+#endif
+    } ctx;
+};
+
+
+typedef struct
+{
+        /** The hash context. */
+        struct psa_hash_operation_s hash_ctx;
+        /** The HMAC part of the context. */
+        uint8_t opad[PSA_HMAC_MAX_HASH_BLOCK_SIZE];
+} psa_hmac_internal_data;
+
+
+struct psa_mac_operation_s
+{
+    psa_algorithm_t alg;
+    unsigned int key_set : 1;
+    unsigned int iv_required : 1;
+    unsigned int iv_set : 1;
+    unsigned int has_input : 1;
+    unsigned int is_sign : 1;
+    uint8_t mac_size;
+    union
+    {
+        unsigned dummy; /* Make the union non-empty even with no supported algorithms. */
+#if defined(MBEDCRYPTO_MD_C)
+        psa_hmac_internal_data hmac;
+#endif
+#if defined(MBEDCRYPTO_CMAC_C)
+        mbedcrypto_cipher_context_t cmac;
+#endif
+    } ctx;
+};
+
+struct psa_cipher_operation_s
+{
+    psa_algorithm_t alg;
+    unsigned int key_set : 1;
+    unsigned int iv_required : 1;
+    unsigned int iv_set : 1;
+    uint8_t iv_size;
+    uint8_t block_size;
+    union
+    {
+        mbedcrypto_cipher_context_t cipher;
+    } ctx;
+};
+
+typedef struct
+{
+    uint8_t *info;
+    size_t info_length;
+    psa_hmac_internal_data hmac;
+    uint8_t prk[PSA_HASH_MAX_SIZE];
+    uint8_t output_block[PSA_HASH_MAX_SIZE];
+#if PSA_HASH_MAX_SIZE > 0xff
+#error "PSA_HASH_MAX_SIZE does not fit in uint8_t"
+#endif
+    uint8_t offset_in_block;
+    uint8_t block_number;
+} psa_hkdf_generator_t;
+
+struct psa_crypto_generator_s
+{
+    psa_algorithm_t alg;
+    size_t capacity;
+    union
+    {
+        struct
+        {
+            uint8_t *data;
+            size_t size;
+        } buffer;
+#if defined(MBEDCRYPTO_MD_C)
+        psa_hkdf_generator_t hkdf;
+#endif
+    } ctx;
+};
+
+#define PSA_CRYPTO_GENERATOR_INIT {0, 0, {{0, 0}}}
+static inline struct psa_crypto_generator_s psa_crypto_generator_init( void )
+{
+    const struct psa_crypto_generator_s v = PSA_CRYPTO_GENERATOR_INIT;
+    return( v );
+}
+
+struct psa_key_policy_s
+{
+    psa_key_usage_t usage;
+    psa_algorithm_t alg;
+};
+
+#endif /* PSA_CRYPTO_STRUCT_H */