Example program to test AES-GCM functionality. Used for a workshop

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
HannesTschofenig
Date:
Thu Sep 27 06:34:22 2018 +0000
Commit message:
Example AES-GCM test program

Changed in this revision

SSL/include/polarssl/aes.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/aesni.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/arc4.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/asn1.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/asn1write.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/base64.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/bignum.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/blowfish.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/bn_mul.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/camellia.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/certs.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/check_config.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/cipher.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/cipher_wrap.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/compat-1.2.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/config.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/config_orig.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/ctr_drbg.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/debug.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/des.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/dhm.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/ecdh.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/ecdsa.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/ecp.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/entropy.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/entropy_poll.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/error.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/gcm.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/havege.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/hmac_drbg.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/md.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/md2.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/md4.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/md5.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/md_wrap.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/memory.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/memory_buffer_alloc.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/net.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/oid.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/openssl.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/padlock.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/pbkdf2.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/pem.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/pk.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/pk_wrap.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/pkcs11.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/pkcs12.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/pkcs5.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/platform.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/ripemd160.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/rsa.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/sha1.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/sha256.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/sha512.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/ssl.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/ssl_cache.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/ssl_ciphersuites.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/threading.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/timing.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/version.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/x509.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/x509_crl.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/x509_crt.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/x509_csr.h Show annotated file Show diff for this revision Revisions of this file
SSL/include/polarssl/xtea.h Show annotated file Show diff for this revision Revisions of this file
SSL/library/aes.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/aesni.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/arc4.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/asn1parse.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/asn1write.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/base64.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/bignum.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/blowfish.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/camellia.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/certs.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/cipher.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/cipher_wrap.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/ctr_drbg.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/debug.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/des.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/dhm.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/ecdh.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/ecdsa.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/ecp.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/ecp_curves.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/entropy.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/entropy_poll.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/error.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/gcm.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/havege.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/hmac_drbg.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/md.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/md2.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/md4.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/md5.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/md_wrap.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/memory_buffer_alloc.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/oid.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/padlock.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/pbkdf2.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/pem.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/pk.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/pk_wrap.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/pkcs11.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/pkcs12.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/pkcs5.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/pkparse.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/pkwrite.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/platform.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/ripemd160.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/rsa.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/sha1.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/sha256.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/sha512.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/ssl_cache.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/ssl_ciphersuites.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/ssl_cli.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/ssl_srv.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/ssl_tls.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/threading.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/timing.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/version.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/version_features.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/x509.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/x509_create.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/x509_crl.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/x509_crt.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/x509_csr.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/x509write_crt.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/x509write_csr.c Show annotated file Show diff for this revision Revisions of this file
SSL/library/xtea.c Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/aes.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,245 @@
+/**
+ * \file aes.h
+ *
+ * \brief AES block cipher
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_AES_H
+#define POLARSSL_AES_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#include <string.h>
+
+#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
+#include <basetsd.h>
+typedef UINT32 uint32_t;
+#else
+#include <inttypes.h>
+#endif
+
+/* padlock.c and aesni.c rely on these values! */
+#define AES_ENCRYPT     1
+#define AES_DECRYPT     0
+
+#define POLARSSL_ERR_AES_INVALID_KEY_LENGTH                -0x0020  /**< Invalid key length. */
+#define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH              -0x0022  /**< Invalid data input length. */
+
+#if !defined(POLARSSL_AES_ALT)
+// Regular implementation
+//
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          AES context structure
+ *
+ * \note           buf is able to hold 32 extra bytes, which can be used:
+ *                 - for alignment purposes if VIA padlock is used, and/or
+ *                 - to simplify key expansion in the 256-bit case by
+ *                 generating an extra round key
+ */
+typedef struct
+{
+    int nr;                     /*!<  number of rounds  */
+    uint32_t *rk;               /*!<  AES round keys    */
+    uint32_t buf[68];           /*!<  unaligned data    */
+}
+aes_context;
+
+/**
+ * \brief          AES key schedule (encryption)
+ *
+ * \param ctx      AES context to be initialized
+ * \param key      encryption key
+ * \param keysize  must be 128, 192 or 256
+ *
+ * \return         0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
+ */
+int aes_setkey_enc( aes_context *ctx, const unsigned char *key,
+                    unsigned int keysize );
+
+/**
+ * \brief          AES key schedule (decryption)
+ *
+ * \param ctx      AES context to be initialized
+ * \param key      decryption key
+ * \param keysize  must be 128, 192 or 256
+ *
+ * \return         0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
+ */
+int aes_setkey_dec( aes_context *ctx, const unsigned char *key,
+                    unsigned int keysize );
+
+/**
+ * \brief          AES-ECB block encryption/decryption
+ *
+ * \param ctx      AES context
+ * \param mode     AES_ENCRYPT or AES_DECRYPT
+ * \param input    16-byte input block
+ * \param output   16-byte output block
+ *
+ * \return         0 if successful
+ */
+int aes_crypt_ecb( aes_context *ctx,
+                    int mode,
+                    const unsigned char input[16],
+                    unsigned char output[16] );
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+/**
+ * \brief          AES-CBC buffer encryption/decryption
+ *                 Length should be a multiple of the block
+ *                 size (16 bytes)
+ *
+ * \param ctx      AES context
+ * \param mode     AES_ENCRYPT or AES_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 POLARSSL_ERR_AES_INVALID_INPUT_LENGTH
+ */
+int aes_crypt_cbc( aes_context *ctx,
+                    int mode,
+                    size_t length,
+                    unsigned char iv[16],
+                    const unsigned char *input,
+                    unsigned char *output );
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+/**
+ * \brief          AES-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
+ * aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
+ *
+ * \param ctx      AES context
+ * \param mode     AES_ENCRYPT or AES_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 aes_crypt_cfb128( aes_context *ctx,
+                       int mode,
+                       size_t length,
+                       size_t *iv_off,
+                       unsigned char iv[16],
+                       const unsigned char *input,
+                       unsigned char *output );
+
+/**
+ * \brief          AES-CFB8 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
+ * aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
+ *
+ * \param ctx      AES context
+ * \param mode     AES_ENCRYPT or AES_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
+ */
+int aes_crypt_cfb8( aes_context *ctx,
+                    int mode,
+                    size_t length,
+                    unsigned char iv[16],
+                    const unsigned char *input,
+                    unsigned char *output );
+#endif /*POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+/**
+ * \brief               AES-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
+ * aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
+ *
+ * \param ctx           AES 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 aes_crypt_ctr( 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 /* POLARSSL_CIPHER_MODE_CTR */
+
+#ifdef __cplusplus
+}
+#endif
+
+#else  /* POLARSSL_AES_ALT */
+#include "aes_alt.h"
+#endif /* POLARSSL_AES_ALT */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int aes_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* aes.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/aesni.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,109 @@
+/**
+ * \file aesni.h
+ *
+ * \brief AES-NI for hardware AES acceleration on some Intel processors
+ *
+ *  Copyright (C) 2013, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_AESNI_H
+#define POLARSSL_AESNI_H
+
+#include "aes.h"
+
+#define POLARSSL_AESNI_AES      0x02000000u
+#define POLARSSL_AESNI_CLMUL    0x00000002u
+
+#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) &&  \
+    ( defined(__amd64__) || defined(__x86_64__) )   &&  \
+    ! defined(POLARSSL_HAVE_X86_64)
+#define POLARSSL_HAVE_X86_64
+#endif
+
+#if defined(POLARSSL_HAVE_X86_64)
+
+/**
+ * \brief          AES-NI features detection routine
+ *
+ * \param what     The feature to detect
+ *                 (POLARSSL_AESNI_AES or POLARSSL_AESNI_CLMUL)
+ *
+ * \return         1 if CPU has support for the feature, 0 otherwise
+ */
+int aesni_supports( unsigned int what );
+
+/**
+ * \brief          AES-NI AES-ECB block en(de)cryption
+ *
+ * \param ctx      AES context
+ * \param mode     AES_ENCRYPT or AES_DECRYPT
+ * \param input    16-byte input block
+ * \param output   16-byte output block
+ *
+ * \return         0 on success (cannot fail)
+ */
+int aesni_crypt_ecb( 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 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 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 POLARSSL_ERR_AES_INVALID_KEY_LENGTH
+ */
+int aesni_setkey_enc( unsigned char *rk,
+                      const unsigned char *key,
+                      size_t bits );
+
+#endif /* POLARSSL_HAVE_X86_64 */
+
+#endif /* POLARSSL_AESNI_H */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/arc4.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,105 @@
+/**
+ * \file arc4.h
+ *
+ * \brief The ARCFOUR stream cipher
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_ARC4_H
+#define POLARSSL_ARC4_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#include <string.h>
+
+#if !defined(POLARSSL_ARC4_ALT)
+// Regular implementation
+//
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          ARC4 context structure
+ */
+typedef struct
+{
+    int x;                      /*!< permutation index */
+    int y;                      /*!< permutation index */
+    unsigned char m[256];       /*!< permutation table */
+}
+arc4_context;
+
+/**
+ * \brief          ARC4 key schedule
+ *
+ * \param ctx      ARC4 context to be initialized
+ * \param key      the secret key
+ * \param keylen   length of the key, in bytes
+ */
+void arc4_setup( 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
+ */
+int arc4_crypt( arc4_context *ctx, size_t length, const unsigned char *input,
+                unsigned char *output );
+
+#ifdef __cplusplus
+}
+#endif
+
+#else  /* POLARSSL_ARC4_ALT */
+#include "arc4_alt.h"
+#endif /* POLARSSL_ARC4_ALT */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int arc4_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* arc4.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/asn1.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,345 @@
+/**
+ * \file asn1.h
+ *
+ * \brief Generic ASN.1 parsing
+ *
+ *  Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_ASN1_H
+#define POLARSSL_ASN1_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_BIGNUM_C)
+#include "bignum.h"
+#endif
+
+#include <string.h>
+
+/**
+ * \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 POLARSSL_ERR_ASN1_OUT_OF_DATA                      -0x0060  /**< Out of data when parsing an ASN1 data structure. */
+#define POLARSSL_ERR_ASN1_UNEXPECTED_TAG                   -0x0062  /**< ASN1 tag was of an unexpected value. */
+#define POLARSSL_ERR_ASN1_INVALID_LENGTH                   -0x0064  /**< Error when trying to determine the length or invalid length. */
+#define POLARSSL_ERR_ASN1_LENGTH_MISMATCH                  -0x0066  /**< Actual length differs from expected length. */
+#define POLARSSL_ERR_ASN1_INVALID_DATA                     -0x0068  /**< Data is invalid. (not used) */
+#define POLARSSL_ERR_ASN1_MALLOC_FAILED                    -0x006A  /**< Memory allocation failed */
+#define POLARSSL_ERR_ASN1_BUF_TOO_SMALL                    -0x006C  /**< Buffer too small when writing ASN.1 data structure. */
+
+/* \} name */
+
+/**
+ * \name DER constants
+ * These constants comply with DER encoded the ANS1 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 ::x509_buf.
+ * \{
+ */
+#define ASN1_BOOLEAN                 0x01
+#define ASN1_INTEGER                 0x02
+#define ASN1_BIT_STRING              0x03
+#define ASN1_OCTET_STRING            0x04
+#define ASN1_NULL                    0x05
+#define ASN1_OID                     0x06
+#define ASN1_UTF8_STRING             0x0C
+#define ASN1_SEQUENCE                0x10
+#define ASN1_SET                     0x11
+#define ASN1_PRINTABLE_STRING        0x13
+#define ASN1_T61_STRING              0x14
+#define ASN1_IA5_STRING              0x16
+#define ASN1_UTC_TIME                0x17
+#define ASN1_GENERALIZED_TIME        0x18
+#define ASN1_UNIVERSAL_STRING        0x1C
+#define ASN1_BMP_STRING              0x1E
+#define ASN1_PRIMITIVE               0x00
+#define ASN1_CONSTRUCTED             0x20
+#define ASN1_CONTEXT_SPECIFIC        0x80
+/* \} name */
+/* \} addtogroup asn1_module */
+
+/** Returns the size of the binary string, without the trailing \\0 */
+#define OID_SIZE(x) (sizeof(x) - 1)
+
+/** Compares two asn1_buf structures for the same OID. Only works for
+ *  'defined' oid_str values (OID_HMAC_SHA1), you cannot use a 'unsigned
+ *  char *oid' here!
+ */
+#define OID_CMP(oid_str, oid_buf)                                   \
+        ( ( 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 _asn1_buf
+{
+    int tag;                /**< ASN1 type, e.g. ASN1_UTF8_STRING. */
+    size_t len;             /**< ASN1 length, e.g. in octets. */
+    unsigned char *p;       /**< ASN1 data, e.g. in ASCII. */
+}
+asn1_buf;
+
+/**
+ * Container for ASN1 bit strings.
+ */
+typedef struct _asn1_bitstring
+{
+    size_t len;                 /**< ASN1 length, e.g. 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 */
+}
+asn1_bitstring;
+
+/**
+ * Container for a sequence of ASN.1 items
+ */
+typedef struct _asn1_sequence
+{
+    asn1_buf buf;                   /**< Buffer containing the given ASN.1 item. */
+    struct _asn1_sequence *next;    /**< The next entry in the sequence. */
+}
+asn1_sequence;
+
+/**
+ * Container for a sequence or list of 'named' ASN.1 data items
+ */
+typedef struct _asn1_named_data
+{
+    asn1_buf oid;                   /**< The object identifier. */
+    asn1_buf val;                   /**< The named value. */
+    struct _asn1_named_data *next;  /**< The next entry in the sequence. */
+}
+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, POLARSSL_ERR_ASN1_OUT_OF_DATA on reaching
+ *              end of data, POLARSSL_ERR_ASN1_INVALID_LENGTH if length is
+ *              unparseable.
+ */
+int 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, POLARSSL_ERR_ASN1_UNEXPECTED_TAG if tag did
+ *              not match requested tag, or another specific ASN.1 error code.
+ */
+int 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 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 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 asn1_get_bitstring( unsigned char **p, const unsigned char *end,
+                        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 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 asn1_get_sequence_of( unsigned char **p,
+                          const unsigned char *end,
+                          asn1_sequence *cur,
+                          int tag);
+
+#if defined(POLARSSL_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 asn1_get_mpi( unsigned char **p,
+                  const unsigned char *end,
+                  mpi *X );
+#endif /* POLARSSL_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 asn1_get_alg( unsigned char **p,
+                  const unsigned char *end,
+                  asn1_buf *alg, 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 asn1_get_alg_null( unsigned char **p,
+                       const unsigned char *end,
+                       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.
+ */
+asn1_named_data *asn1_find_named_data( asn1_named_data *list,
+                                       const char *oid, size_t len );
+
+/**
+ * \brief       Free a asn1_named_data entry
+ *
+ * \param entry The named data entry to free
+ */
+void asn1_free_named_data( asn1_named_data *entry );
+
+/**
+ * \brief       Free all entries in a 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 asn1_free_named_data_list( asn1_named_data **head );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* asn1.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/asn1write.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,245 @@
+/**
+ * \file asn1write.h
+ *
+ * \brief ASN.1 buffer writing functionality
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_ASN1_WRITE_H
+#define POLARSSL_ASN1_WRITE_H
+
+#include "asn1.h"
+
+#define 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 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 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 asn1_write_raw_buffer( unsigned char **p, unsigned char *start,
+                           const unsigned char *buf, size_t size );
+
+#if defined(POLARSSL_BIGNUM_C)
+/**
+ * \brief           Write a big number (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 asn1_write_mpi( unsigned char **p, unsigned char *start, mpi *X );
+#endif /* POLARSSL_BIGNUM_C */
+
+/**
+ * \brief           Write a NULL tag (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 asn1_write_null( unsigned char **p, unsigned char *start );
+
+/**
+ * \brief           Write an OID tag (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 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 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 (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 asn1_write_bool( unsigned char **p, unsigned char *start, int boolean );
+
+/**
+ * \brief           Write an int tag (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 asn1_write_int( unsigned char **p, unsigned char *start, int val );
+
+/**
+ * \brief           Write a printable string tag (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 asn1_write_printable_string( unsigned char **p, unsigned char *start,
+                                 const char *text, size_t text_len );
+
+/**
+ * \brief           Write an IA5 string tag (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 asn1_write_ia5_string( unsigned char **p, unsigned char *start,
+                           const char *text, size_t text_len );
+
+/**
+ * \brief           Write a bitstring tag (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 asn1_write_bitstring( unsigned char **p, unsigned char *start,
+                          const unsigned char *buf, size_t bits );
+
+/**
+ * \brief           Write an octet string tag (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 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.
+ */
+asn1_named_data *asn1_store_named_data( asn1_named_data **list,
+                                        const char *oid, size_t oid_len,
+                                        const unsigned char *val,
+                                        size_t val_len );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* POLARSSL_ASN1_WRITE_H */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/base64.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,89 @@
+/**
+ * \file base64.h
+ *
+ * \brief RFC 1521 base64 encoding/decoding
+ *
+ *  Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_BASE64_H
+#define POLARSSL_BASE64_H
+
+#include <string.h>
+
+#define POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL               -0x002A  /**< Output buffer too small. */
+#define POLARSSL_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 buffer
+ * \param src      source buffer
+ * \param slen     amount of data to be encoded
+ *
+ * \return         0 if successful, or POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL.
+ *                 *dlen is always updated to reflect the amount
+ *                 of data that has (or would have) been written.
+ *
+ * \note           Call this function with *dlen = 0 to obtain the
+ *                 required buffer size in *dlen
+ */
+int base64_encode( unsigned char *dst, size_t *dlen,
+                   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 buffer
+ * \param src      source buffer
+ * \param slen     amount of data to be decoded
+ *
+ * \return         0 if successful, POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL, or
+ *                 POLARSSL_ERR_BASE64_INVALID_CHARACTER if the input data is
+ *                 not correct. *dlen 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 *dlen
+ */
+int base64_decode( unsigned char *dst, size_t *dlen,
+                   const unsigned char *src, size_t slen );
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int base64_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* base64.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/bignum.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,751 @@
+/**
+ * \file bignum.h
+ *
+ * \brief  Multi-precision integer library
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_BIGNUM_H
+#define POLARSSL_BIGNUM_H
+
+#include <stdio.h>
+#include <string.h>
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
+#include <basetsd.h>
+#if (_MSC_VER <= 1200)
+typedef   signed short  int16_t;
+typedef unsigned short uint16_t;
+#else
+typedef  INT16  int16_t;
+typedef UINT16 uint16_t;
+#endif
+typedef  INT32  int32_t;
+typedef  INT64  int64_t;
+typedef UINT32 uint32_t;
+typedef UINT64 uint64_t;
+#else
+#include <inttypes.h>
+#endif /* _MSC_VER && !EFIX64 && !EFI32 */
+
+#define POLARSSL_ERR_MPI_FILE_IO_ERROR                     -0x0002  /**< An error occurred while reading from or writing to a file. */
+#define POLARSSL_ERR_MPI_BAD_INPUT_DATA                    -0x0004  /**< Bad input parameters to function. */
+#define POLARSSL_ERR_MPI_INVALID_CHARACTER                 -0x0006  /**< There is an invalid character in the digit string. */
+#define POLARSSL_ERR_MPI_BUFFER_TOO_SMALL                  -0x0008  /**< The buffer is too small to write to. */
+#define POLARSSL_ERR_MPI_NEGATIVE_VALUE                    -0x000A  /**< The input arguments are negative or result in illegal output. */
+#define POLARSSL_ERR_MPI_DIVISION_BY_ZERO                  -0x000C  /**< The input argument for division is zero, which is not allowed. */
+#define POLARSSL_ERR_MPI_NOT_ACCEPTABLE                    -0x000E  /**< The input arguments are not acceptable. */
+#define POLARSSL_ERR_MPI_MALLOC_FAILED                     -0x0010  /**< Memory allocation failed. */
+
+#define 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 POLARSSL_MPI_MAX_LIMBS                             10000
+
+#if !defined(POLARSSL_CONFIG_OPTIONS)
+/*
+ * Maximum window size used for modular exponentiation. Default: 6
+ * Minimum value: 1. Maximum value: 6.
+ *
+ * Result is an array of ( 2 << POLARSSL_MPI_WINDOW_SIZE ) MPIs used
+ * for the sliding window calculation. (So 64 by default)
+ *
+ * Reduction in size, reduces speed.
+ */
+#define POLARSSL_MPI_WINDOW_SIZE                           6        /**< Maximum windows size used. */
+
+/*
+ * 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 results temporarily in larger MPIs. So the number
+ * of limbs required (POLARSSL_MPI_MAX_LIMBS) is higher.
+ */
+#define POLARSSL_MPI_MAX_SIZE                              512      /**< Maximum number of bytes for usable MPIs. */
+
+#endif /* !POLARSSL_CONFIG_OPTIONS */
+
+#define POLARSSL_MPI_MAX_BITS                              ( 8 * POLARSSL_MPI_MAX_SIZE )    /**< Maximum number of bits for usable MPIs. */
+
+/*
+ * When reading from files with mpi_read_file() and writing to files with
+ * 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 POLARSSL_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:
+ *  POLARSSL_MPI_RW_BUFFER_SIZE = ceil(POLARSSL_MPI_MAX_BITS / ln(10) * ln(2)) +
+ *                                LabelSize + 6
+ */
+#define POLARSSL_MPI_MAX_BITS_SCALE100          ( 100 * POLARSSL_MPI_MAX_BITS )
+#define LN_2_DIV_LN_10_SCALE100                 332
+#define POLARSSL_MPI_RW_BUFFER_SIZE             ( ((POLARSSL_MPI_MAX_BITS_SCALE100 + LN_2_DIV_LN_10_SCALE100 - 1) / LN_2_DIV_LN_10_SCALE100) + 10 + 6 )
+
+/*
+ * Define the base integer type, architecture-wise
+ */
+#if defined(POLARSSL_HAVE_INT8)
+typedef   signed char  t_sint;
+typedef unsigned char  t_uint;
+typedef uint16_t       t_udbl;
+#define POLARSSL_HAVE_UDBL
+#else
+#if defined(POLARSSL_HAVE_INT16)
+typedef  int16_t t_sint;
+typedef uint16_t t_uint;
+typedef uint32_t t_udbl;
+#define POLARSSL_HAVE_UDBL
+#else
+  /*
+   * 32-bit integers can be forced on 64-bit arches (eg. for testing purposes)
+   * by defining POLARSSL_HAVE_INT32 and undefining POARSSL_HAVE_ASM
+   */
+  #if ( ! defined(POLARSSL_HAVE_INT32) && \
+          defined(_MSC_VER) && defined(_M_AMD64) )
+    #define POLARSSL_HAVE_INT64
+    typedef  int64_t t_sint;
+    typedef uint64_t t_uint;
+  #else
+    #if ( ! defined(POLARSSL_HAVE_INT32) &&               \
+          defined(__GNUC__) && (                          \
+          defined(__amd64__) || defined(__x86_64__)    || \
+          defined(__ppc64__) || defined(__powerpc64__) || \
+          defined(__ia64__)  || defined(__alpha__)     || \
+          (defined(__sparc__) && defined(__arch64__))  || \
+          defined(__s390x__) ) )
+       #define POLARSSL_HAVE_INT64
+       typedef  int64_t t_sint;
+       typedef uint64_t t_uint;
+       typedef unsigned int t_udbl __attribute__((mode(TI)));
+       #define POLARSSL_HAVE_UDBL
+    #else
+       #define POLARSSL_HAVE_INT32
+       typedef  int32_t t_sint;
+       typedef uint32_t t_uint;
+       #if ( defined(_MSC_VER) && defined(_M_IX86) )
+         typedef uint64_t t_udbl;
+         #define POLARSSL_HAVE_UDBL
+       #else
+         #if defined( POLARSSL_HAVE_LONGLONG )
+           typedef unsigned long long t_udbl;
+           #define POLARSSL_HAVE_UDBL
+         #endif
+       #endif
+    #endif
+  #endif
+#endif /* POLARSSL_HAVE_INT16 */
+#endif /* POLARSSL_HAVE_INT8  */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          MPI structure
+ */
+typedef struct
+{
+    int s;              /*!<  integer sign      */
+    size_t n;           /*!<  total # of limbs  */
+    t_uint *p;          /*!<  pointer to limbs  */
+}
+mpi;
+
+/**
+ * \brief           Initialize one MPI
+ *
+ * \param X         One MPI to initialize.
+ */
+void mpi_init( mpi *X );
+
+/**
+ * \brief          Unallocate one MPI
+ *
+ * \param X        One MPI to unallocate.
+ */
+void mpi_free( mpi *X );
+
+/**
+ * \brief          Enlarge to the specified number of limbs
+ *
+ * \param X        MPI to grow
+ * \param nblimbs  The target number of limbs
+ *
+ * \return         0 if successful,
+ *                 POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_grow( mpi *X, size_t nblimbs );
+
+/**
+ * \brief          Resize down, keeping at least the specified number of limbs
+ *
+ * \param X        MPI to shrink
+ * \param nblimbs  The minimum number of limbs to keep
+ *
+ * \return         0 if successful,
+ *                 POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_shrink( mpi *X, size_t nblimbs );
+
+/**
+ * \brief          Copy the contents of Y into X
+ *
+ * \param X        Destination MPI
+ * \param Y        Source MPI
+ *
+ * \return         0 if successful,
+ *                 POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_copy( mpi *X, const mpi *Y );
+
+/**
+ * \brief          Swap the contents of X and Y
+ *
+ * \param X        First MPI value
+ * \param Y        Second MPI value
+ */
+void mpi_swap( mpi *X, 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,
+ *                 POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
+ *
+ * \note           This function is equivalent to
+ *                      if( assign ) 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 mpi_safe_cond_assign( mpi *X, const mpi *Y, unsigned char assign );
+
+/**
+ * \brief          Safe conditional swap X <-> Y if swap is 1
+ *
+ * \param X        First mpi value
+ * \param Y        Second mpi value
+ * \param assign   1: perform the swap, 0: keep X and Y's original values
+ *
+ * \return         0 if successful,
+ *                 POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
+ *
+ * \note           This function is equivalent to
+ *                      if( assign ) 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 mpi_safe_cond_swap( mpi *X, mpi *Y, unsigned char assign );
+
+/**
+ * \brief          Set value from integer
+ *
+ * \param X        MPI to set
+ * \param z        Value to use
+ *
+ * \return         0 if successful,
+ *                 POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_lset( mpi *X, t_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 mpi_get_bit( const 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,
+ *                 POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
+ *                 POLARSSL_ERR_MPI_BAD_INPUT_DATA if val is not 0 or 1
+ */
+int mpi_set_bit( 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 mpi_lsb( const 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 mpi_msb( const mpi *X );
+
+/**
+ * \brief          Return the total size in bytes
+ *
+ * \param X        MPI to use
+ */
+size_t mpi_size( const 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 POLARSSL_ERR_MPI_XXX error code
+ */
+int mpi_read_string( mpi *X, int radix, const char *s );
+
+/**
+ * \brief          Export into an ASCII string
+ *
+ * \param X        Source MPI
+ * \param radix    Output numeric base
+ * \param s        String buffer
+ * \param slen     String buffer size
+ *
+ * \return         0 if successful, or a POLARSSL_ERR_MPI_XXX error code.
+ *                 *slen is always updated to reflect the amount
+ *                 of data that has (or would have) been written.
+ *
+ * \note           Call this function with *slen = 0 to obtain the
+ *                 minimum required buffer size in *slen.
+ */
+int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen );
+
+#if defined(POLARSSL_FS_IO)
+/**
+ * \brief          Read X from an opened file
+ *
+ * \param X        Destination MPI
+ * \param radix    Input numeric base
+ * \param fin      Input file handle
+ *
+ * \return         0 if successful, POLARSSL_ERR_MPI_BUFFER_TOO_SMALL if
+ *                 the file read buffer is too small or a
+ *                 POLARSSL_ERR_MPI_XXX error code
+ */
+int mpi_read_file( 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 POLARSSL_ERR_MPI_XXX error code
+ *
+ * \note           Set fout == NULL to print X on the console.
+ */
+int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout );
+#endif /* POLARSSL_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,
+ *                 POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen );
+
+/**
+ * \brief          Export X into unsigned binary data, big endian
+ *
+ * \param X        Source MPI
+ * \param buf      Output buffer
+ * \param buflen   Output buffer size
+ *
+ * \return         0 if successful,
+ *                 POLARSSL_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough
+ */
+int mpi_write_binary( const 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,
+ *                 POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_shift_l( mpi *X, size_t count );
+
+/**
+ * \brief          Right-shift: X >>= count
+ *
+ * \param X        MPI to shift
+ * \param count    Amount to shift
+ *
+ * \return         0 if successful,
+ *                 POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_shift_r( 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 mpi_cmp_abs( const mpi *X, const 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 mpi_cmp_mpi( const mpi *X, const 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 mpi_cmp_int( const mpi *X, t_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,
+ *                 POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_add_abs( mpi *X, const mpi *A, const 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,
+ *                 POLARSSL_ERR_MPI_NEGATIVE_VALUE if B is greater than A
+ */
+int mpi_sub_abs( mpi *X, const mpi *A, const 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,
+ *                 POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_add_mpi( mpi *X, const mpi *A, const 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,
+ *                 POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_sub_mpi( mpi *X, const mpi *A, const 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,
+ *                 POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_add_int( mpi *X, const mpi *A, t_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,
+ *                 POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_sub_int( mpi *X, const mpi *A, t_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,
+ *                 POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B );
+
+/**
+ * \brief          Baseline multiplication: X = A * b
+ *                 Note: despite the functon signature, b is treated as a
+ *                 t_uint.  Negative values of b are treated as large positive
+ *                 values.
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param b        The integer value to multiply with
+ *
+ * \return         0 if successful,
+ *                 POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_mul_int( mpi *X, const mpi *A, t_sint b );
+
+/**
+ * \brief          Division by 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,
+ *                 POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
+ *                 POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0
+ *
+ * \note           Either Q or R can be NULL.
+ */
+int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const 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,
+ *                 POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
+ *                 POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0
+ *
+ * \note           Either Q or R can be NULL.
+ */
+int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_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,
+ *                 POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
+ *                 POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0,
+ *                 POLARSSL_ERR_MPI_NEGATIVE_VALUE if B < 0
+ */
+int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B );
+
+/**
+ * \brief          Modulo: r = A mod b
+ *
+ * \param r        Destination t_uint
+ * \param A        Left-hand MPI
+ * \param b        Integer to divide by
+ *
+ * \return         0 if successful,
+ *                 POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
+ *                 POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0,
+ *                 POLARSSL_ERR_MPI_NEGATIVE_VALUE if b < 0
+ */
+int mpi_mod_int( t_uint *r, const mpi *A, t_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,
+ *                 POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
+ *                 POLARSSL_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 mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, 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,
+ *                 POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_fill_random( 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,
+ *                 POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_gcd( mpi *G, const mpi *A, const 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,
+ *                 POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
+ *                 POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or nil
+                   POLARSSL_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N
+ */
+int mpi_inv_mod( mpi *X, const mpi *A, const 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),
+ *                 POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
+ *                 POLARSSL_ERR_MPI_NOT_ACCEPTABLE if X is not prime
+ */
+int mpi_is_prime( 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 <= POLARSSL_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),
+ *                 POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
+ *                 POLARSSL_ERR_MPI_BAD_INPUT_DATA if nbits is < 3
+ */
+int mpi_gen_prime( 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 mpi_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* bignum.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/blowfish.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,185 @@
+/**
+ * \file blowfish.h
+ *
+ * \brief Blowfish block cipher
+ *
+ *  Copyright (C) 2012-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_BLOWFISH_H
+#define POLARSSL_BLOWFISH_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#include <string.h>
+
+#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
+#include <basetsd.h>
+typedef UINT32 uint32_t;
+#else
+#include <inttypes.h>
+#endif
+
+#define BLOWFISH_ENCRYPT     1
+#define BLOWFISH_DECRYPT     0
+#define BLOWFISH_MAX_KEY     448
+#define BLOWFISH_MIN_KEY     32
+#define BLOWFISH_ROUNDS      16         /**< Rounds to use. When increasing this value, make sure to extend the initialisation vectors */
+#define BLOWFISH_BLOCKSIZE   8          /* Blowfish uses 64 bit blocks */
+
+#define POLARSSL_ERR_BLOWFISH_INVALID_KEY_LENGTH                -0x0016  /**< Invalid key length. */
+#define POLARSSL_ERR_BLOWFISH_INVALID_INPUT_LENGTH              -0x0018  /**< Invalid data input length. */
+
+#if !defined(POLARSSL_BLOWFISH_ALT)
+// Regular implementation
+//
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          Blowfish context structure
+ */
+typedef struct
+{
+    uint32_t P[BLOWFISH_ROUNDS + 2];    /*!<  Blowfish round keys    */
+    uint32_t S[4][256];                 /*!<  key dependent S-boxes  */
+}
+blowfish_context;
+
+/**
+ * \brief          Blowfish key schedule
+ *
+ * \param ctx      Blowfish context to be initialized
+ * \param key      encryption key
+ * \param keysize  must be between 32 and 448 bits
+ *
+ * \return         0 if successful, or POLARSSL_ERR_BLOWFISH_INVALID_KEY_LENGTH
+ */
+int blowfish_setkey( blowfish_context *ctx, const unsigned char *key,
+                     unsigned int keysize );
+
+/**
+ * \brief          Blowfish-ECB block encryption/decryption
+ *
+ * \param ctx      Blowfish context
+ * \param mode     BLOWFISH_ENCRYPT or BLOWFISH_DECRYPT
+ * \param input    8-byte input block
+ * \param output   8-byte output block
+ *
+ * \return         0 if successful
+ */
+int blowfish_crypt_ecb( blowfish_context *ctx,
+                        int mode,
+                        const unsigned char input[BLOWFISH_BLOCKSIZE],
+                        unsigned char output[BLOWFISH_BLOCKSIZE] );
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+/**
+ * \brief          Blowfish-CBC buffer encryption/decryption
+ *                 Length should be a multiple of the block
+ *                 size (8 bytes)
+ *
+ * \param ctx      Blowfish context
+ * \param mode     BLOWFISH_ENCRYPT or 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
+ *                 POLARSSL_ERR_BLOWFISH_INVALID_INPUT_LENGTH
+ */
+int blowfish_crypt_cbc( blowfish_context *ctx,
+                        int mode,
+                        size_t length,
+                        unsigned char iv[BLOWFISH_BLOCKSIZE],
+                        const unsigned char *input,
+                        unsigned char *output );
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+/**
+ * \brief          Blowfish CFB buffer encryption/decryption.
+ *
+ * \param ctx      Blowfish context
+ * \param mode     BLOWFISH_ENCRYPT or 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 blowfish_crypt_cfb64( blowfish_context *ctx,
+                          int mode,
+                          size_t length,
+                          size_t *iv_off,
+                          unsigned char iv[BLOWFISH_BLOCKSIZE],
+                          const unsigned char *input,
+                          unsigned char *output );
+#endif /*POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_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 blowfish_crypt_ctr( blowfish_context *ctx,
+                        size_t length,
+                        size_t *nc_off,
+                        unsigned char nonce_counter[BLOWFISH_BLOCKSIZE],
+                        unsigned char stream_block[BLOWFISH_BLOCKSIZE],
+                        const unsigned char *input,
+                        unsigned char *output );
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+#ifdef __cplusplus
+}
+#endif
+
+#else  /* POLARSSL_BLOWFISH_ALT */
+#include "blowfish_alt.h"
+#endif /* POLARSSL_BLOWFISH_ALT */
+
+#endif /* blowfish.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/bn_mul.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,968 @@
+/**
+ * \file bn_mul.h
+ *
+ * \brief  Multi-precision integer library
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *      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 POLARSSL_BN_MUL_H
+#define POLARSSL_BN_MUL_H
+
+#include "bignum.h"
+
+#if defined(POLARSSL_HAVE_ASM)
+
+#if defined(__GNUC__)
+#if defined(__i386__)
+
+#define MULADDC_INIT                \
+    asm( "                          \
+        movl   %%ebx, %0;           \
+        movl   %5, %%esi;           \
+        movl   %6, %%edi;           \
+        movl   %7, %%ecx;           \
+        movl   %8, %%ebx;           \
+        "
+
+#define MULADDC_CORE                \
+        "                           \
+        lodsl;                      \
+        mull   %%ebx;               \
+        addl   %%ecx,   %%eax;      \
+        adcl   $0,      %%edx;      \
+        addl   (%%edi), %%eax;      \
+        adcl   $0,      %%edx;      \
+        movl   %%edx,   %%ecx;      \
+        stosl;                      \
+        "
+
+#if defined(POLARSSL_HAVE_SSE2)
+
+#define MULADDC_HUIT                    \
+        "                               \
+        movd     %%ecx,     %%mm1;      \
+        movd     %%ebx,     %%mm0;      \
+        movd     (%%edi),   %%mm3;      \
+        paddq    %%mm3,     %%mm1;      \
+        movd     (%%esi),   %%mm2;      \
+        pmuludq  %%mm0,     %%mm2;      \
+        movd     4(%%esi),  %%mm4;      \
+        pmuludq  %%mm0,     %%mm4;      \
+        movd     8(%%esi),  %%mm6;      \
+        pmuludq  %%mm0,     %%mm6;      \
+        movd     12(%%esi), %%mm7;      \
+        pmuludq  %%mm0,     %%mm7;      \
+        paddq    %%mm2,     %%mm1;      \
+        movd     4(%%edi),  %%mm3;      \
+        paddq    %%mm4,     %%mm3;      \
+        movd     8(%%edi),  %%mm5;      \
+        paddq    %%mm6,     %%mm5;      \
+        movd     12(%%edi), %%mm4;      \
+        paddq    %%mm4,     %%mm7;      \
+        movd     %%mm1,     (%%edi);    \
+        movd     16(%%esi), %%mm2;      \
+        pmuludq  %%mm0,     %%mm2;      \
+        psrlq    $32,       %%mm1;      \
+        movd     20(%%esi), %%mm4;      \
+        pmuludq  %%mm0,     %%mm4;      \
+        paddq    %%mm3,     %%mm1;      \
+        movd     24(%%esi), %%mm6;      \
+        pmuludq  %%mm0,     %%mm6;      \
+        movd     %%mm1,     4(%%edi);   \
+        psrlq    $32,       %%mm1;      \
+        movd     28(%%esi), %%mm3;      \
+        pmuludq  %%mm0,     %%mm3;      \
+        paddq    %%mm5,     %%mm1;      \
+        movd     16(%%edi), %%mm5;      \
+        paddq    %%mm5,     %%mm2;      \
+        movd     %%mm1,     8(%%edi);   \
+        psrlq    $32,       %%mm1;      \
+        paddq    %%mm7,     %%mm1;      \
+        movd     20(%%edi), %%mm5;      \
+        paddq    %%mm5,     %%mm4;      \
+        movd     %%mm1,     12(%%edi);  \
+        psrlq    $32,       %%mm1;      \
+        paddq    %%mm2,     %%mm1;      \
+        movd     24(%%edi), %%mm5;      \
+        paddq    %%mm5,     %%mm6;      \
+        movd     %%mm1,     16(%%edi);  \
+        psrlq    $32,       %%mm1;      \
+        paddq    %%mm4,     %%mm1;      \
+        movd     28(%%edi), %%mm5;      \
+        paddq    %%mm5,     %%mm3;      \
+        movd     %%mm1,     20(%%edi);  \
+        psrlq    $32,       %%mm1;      \
+        paddq    %%mm6,     %%mm1;      \
+        movd     %%mm1,     24(%%edi);  \
+        psrlq    $32,       %%mm1;      \
+        paddq    %%mm3,     %%mm1;      \
+        movd     %%mm1,     28(%%edi);  \
+        addl     $32,       %%edi;      \
+        addl     $32,       %%esi;      \
+        psrlq    $32,       %%mm1;      \
+        movd     %%mm1,     %%ecx;      \
+        "
+
+#define MULADDC_STOP            \
+        "                       \
+        emms;                   \
+        movl   %4, %%ebx;       \
+        movl   %%ecx, %1;       \
+        movl   %%edi, %2;       \
+        movl   %%esi, %3;       \
+        "                       \
+        : "=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;       \
+        movl   %%ecx, %1;       \
+        movl   %%edi, %2;       \
+        movl   %%esi, %3;       \
+        "                       \
+        : "=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(                            \
+        "                           \
+        movq   %3, %%rsi;           \
+        movq   %4, %%rdi;           \
+        movq   %5, %%rcx;           \
+        movq   %6, %%rbx;           \
+        xorq   %%r8, %%r8;          \
+        "
+
+#define MULADDC_CORE                \
+        "                           \
+        movq   (%%rsi), %%rax;      \
+        mulq   %%rbx;               \
+        addq   $8,      %%rsi;      \
+        addq   %%rcx,   %%rax;      \
+        movq   %%r8,    %%rcx;      \
+        adcq   $0,      %%rdx;      \
+        nop;                        \
+        addq   %%rax,   (%%rdi);    \
+        adcq   %%rdx,   %%rcx;      \
+        addq   $8,      %%rdi;      \
+        "
+
+#define MULADDC_STOP                \
+        "                           \
+        movq   %%rcx, %0;           \
+        movq   %%rdi, %1;           \
+        movq   %%rsi, %2;           \
+        "                           \
+        : "=m" (c), "=m" (d), "=m" (s)                      \
+        : "m" (s), "m" (d), "m" (c), "m" (b)                \
+        : "rax", "rcx", "rdx", "rbx", "rsi", "rdi", "r8"    \
+    );
+
+#endif /* AMD64 */
+
+#if defined(__mc68020__) || defined(__mcpu32__)
+
+#define MULADDC_INIT            \
+    asm(                        \
+        "                       \
+        movl   %3, %%a2;        \
+        movl   %4, %%a3;        \
+        movl   %5, %%d3;        \
+        movl   %6, %%d2;        \
+        moveq  #0, %%d0;        \
+        "
+
+#define MULADDC_CORE            \
+        "                       \
+        movel  %%a2@+, %%d1;    \
+        mulul  %%d2, %%d4:%%d1; \
+        addl   %%d3, %%d1;      \
+        addxl  %%d0, %%d4;      \
+        moveq  #0,   %%d3;      \
+        addl   %%d1, %%a3@+;    \
+        addxl  %%d4, %%d3;      \
+        "
+
+#define MULADDC_STOP            \
+        "                       \
+        movl   %%d3, %0;        \
+        movl   %%a3, %1;        \
+        movl   %%a2, %2;        \
+        "                       \
+        : "=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;       \
+        mulul  %%d2,    %%d4:%%d1;  \
+        addxl  %%d3,    %%d1;       \
+        addxl  %%d0,    %%d4;       \
+        addl   %%d1,    %%a3@+;     \
+        movel  %%a2@+,  %%d1;       \
+        mulul  %%d2,    %%d3:%%d1;  \
+        addxl  %%d4,    %%d1;       \
+        addxl  %%d0,    %%d3;       \
+        addl   %%d1,    %%a3@+;     \
+        movel  %%a2@+,  %%d1;       \
+        mulul  %%d2,    %%d4:%%d1;  \
+        addxl  %%d3,    %%d1;       \
+        addxl  %%d0,    %%d4;       \
+        addl   %%d1,    %%a3@+;     \
+        movel  %%a2@+,  %%d1;       \
+        mulul  %%d2,    %%d3:%%d1;  \
+        addxl  %%d4,    %%d1;       \
+        addxl  %%d0,    %%d3;       \
+        addl   %%d1,    %%a3@+;     \
+        movel  %%a2@+,  %%d1;       \
+        mulul  %%d2,    %%d4:%%d1;  \
+        addxl  %%d3,    %%d1;       \
+        addxl  %%d0,    %%d4;       \
+        addl   %%d1,    %%a3@+;     \
+        movel  %%a2@+,  %%d1;       \
+        mulul  %%d2,    %%d3:%%d1;  \
+        addxl  %%d4,    %%d1;       \
+        addxl  %%d0,    %%d3;       \
+        addl   %%d1,    %%a3@+;     \
+        movel  %%a2@+,  %%d1;       \
+        mulul  %%d2,    %%d4:%%d1;  \
+        addxl  %%d3,    %%d1;       \
+        addxl  %%d0,    %%d4;       \
+        addl   %%d1,    %%a3@+;     \
+        movel  %%a2@+,  %%d1;       \
+        mulul  %%d2,    %%d3:%%d1;  \
+        addxl  %%d4,    %%d1;       \
+        addxl  %%d0,    %%d3;       \
+        addl   %%d1,    %%a3@+;     \
+        addxl  %%d0,    %%d3;       \
+        "
+
+#endif /* MC68000 */
+
+#if defined(__powerpc__)   || defined(__ppc__)
+#if defined(__powerpc64__) || defined(__ppc64__)
+
+#if defined(__MACH__) && defined(__APPLE__)
+
+#define MULADDC_INIT                \
+    asm(                            \
+        "                           \
+        ld     r3, %3;              \
+        ld     r4, %4;              \
+        ld     r5, %5;              \
+        ld     r6, %6;              \
+        addi   r3, r3, -8;          \
+        addi   r4, r4, -8;          \
+        addic  r5, r5,  0;          \
+        "
+
+#define MULADDC_CORE                \
+        "                           \
+        ldu    r7, 8(r3);           \
+        mulld  r8, r7, r6;          \
+        mulhdu r9, r7, r6;          \
+        adde   r8, r8, r5;          \
+        ld     r7, 8(r4);           \
+        addze  r5, r9;              \
+        addc   r8, r8, r7;          \
+        stdu   r8, 8(r4);           \
+        "
+
+#define MULADDC_STOP                \
+        "                           \
+        addze  r5, r5;              \
+        addi   r4, r4, 8;           \
+        addi   r3, r3, 8;           \
+        std    r5, %0;              \
+        std    r4, %1;              \
+        std    r3, %2;              \
+        "                           \
+        : "=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;            \
+        ld     %%r4, %4;            \
+        ld     %%r5, %5;            \
+        ld     %%r6, %6;            \
+        addi   %%r3, %%r3, -8;      \
+        addi   %%r4, %%r4, -8;      \
+        addic  %%r5, %%r5,  0;      \
+        "
+
+#define MULADDC_CORE                \
+        "                           \
+        ldu    %%r7, 8(%%r3);       \
+        mulld  %%r8, %%r7, %%r6;    \
+        mulhdu %%r9, %%r7, %%r6;    \
+        adde   %%r8, %%r8, %%r5;    \
+        ld     %%r7, 8(%%r4);       \
+        addze  %%r5, %%r9;          \
+        addc   %%r8, %%r8, %%r7;    \
+        stdu   %%r8, 8(%%r4);       \
+        "
+
+#define MULADDC_STOP                \
+        "                           \
+        addze  %%r5, %%r5;          \
+        addi   %%r4, %%r4, 8;       \
+        addi   %%r3, %%r3, 8;       \
+        std    %%r5, %0;            \
+        std    %%r4, %1;            \
+        std    %%r3, %2;            \
+        "                           \
+        : "=m" (c), "=m" (d), "=m" (s)              \
+        : "m" (s), "m" (d), "m" (c), "m" (b)        \
+        : "r3", "r4", "r5", "r6", "r7", "r8", "r9"  \
+    );
+
+#endif /* __MACH__ && __APPLE__ */
+
+#else /* PPC32 */
+
+#if defined(__MACH__) && defined(__APPLE__)
+
+#define MULADDC_INIT            \
+    asm(                        \
+        "                       \
+        lwz    r3, %3;          \
+        lwz    r4, %4;          \
+        lwz    r5, %5;          \
+        lwz    r6, %6;          \
+        addi   r3, r3, -4;      \
+        addi   r4, r4, -4;      \
+        addic  r5, r5,  0;      \
+        "
+
+#define MULADDC_CORE            \
+        "                       \
+        lwzu   r7, 4(r3);       \
+        mullw  r8, r7, r6;      \
+        mulhwu r9, r7, r6;      \
+        adde   r8, r8, r5;      \
+        lwz    r7, 4(r4);       \
+        addze  r5, r9;          \
+        addc   r8, r8, r7;      \
+        stwu   r8, 4(r4);       \
+        "
+
+#define MULADDC_STOP            \
+        "                       \
+        addze  r5, r5;          \
+        addi   r4, r4, 4;       \
+        addi   r3, r3, 4;       \
+        stw    r5, %0;          \
+        stw    r4, %1;          \
+        stw    r3, %2;          \
+        "                       \
+        : "=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;            \
+        lwz    %%r4, %4;            \
+        lwz    %%r5, %5;            \
+        lwz    %%r6, %6;            \
+        addi   %%r3, %%r3, -4;      \
+        addi   %%r4, %%r4, -4;      \
+        addic  %%r5, %%r5,  0;      \
+        "
+
+#define MULADDC_CORE                \
+        "                           \
+        lwzu   %%r7, 4(%%r3);       \
+        mullw  %%r8, %%r7, %%r6;    \
+        mulhwu %%r9, %%r7, %%r6;    \
+        adde   %%r8, %%r8, %%r5;    \
+        lwz    %%r7, 4(%%r4);       \
+        addze  %%r5, %%r9;          \
+        addc   %%r8, %%r8, %%r7;    \
+        stwu   %%r8, 4(%%r4);       \
+        "
+
+#define MULADDC_STOP                \
+        "                           \
+        addze  %%r5, %%r5;          \
+        addi   %%r4, %%r4, 4;       \
+        addi   %%r3, %%r3, 4;       \
+        stw    %%r5, %0;            \
+        stw    %%r4, %1;            \
+        stw    %%r3, %2;            \
+        "                           \
+        : "=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 */
+#endif /* PPC64 */
+
+#if defined(__sparc__) && defined(__sparc64__)
+
+#define MULADDC_INIT                            \
+    asm(                                        \
+         "                                      \
+                ldx     %3, %%o0;               \
+                ldx     %4, %%o1;               \
+                ld      %5, %%o2;               \
+                ld      %6, %%o3;               \
+         "
+
+#define MULADDC_CORE                            \
+         "                                      \
+                ld      [%%o0], %%o4;           \
+                inc     4, %%o0;                \
+                ld      [%%o1], %%o5;           \
+                umul    %%o3, %%o4, %%o4;       \
+                addcc   %%o4, %%o2, %%o4;       \
+                rd      %%y, %%g1;              \
+                addx    %%g1, 0, %%g1;          \
+                addcc   %%o4, %%o5, %%o4;       \
+                st      %%o4, [%%o1];           \
+                addx    %%g1, 0, %%o2;          \
+                inc     4, %%o1;                \
+        "
+
+#define MULADDC_STOP                            \
+        "                                       \
+                st      %%o2, %0;               \
+                stx     %%o1, %1;               \
+                stx     %%o0, %2;               \
+        "                                       \
+        : "=m" (c), "=m" (d), "=m" (s)          \
+        : "m" (s), "m" (d), "m" (c), "m" (b)    \
+        : "g1", "o0", "o1", "o2", "o3", "o4",   \
+          "o5"                                  \
+        );
+#endif /* SPARCv9 */
+
+#if defined(__sparc__) && !defined(__sparc64__)
+
+#define MULADDC_INIT                            \
+    asm(                                        \
+         "                                      \
+                ld      %3, %%o0;               \
+                ld      %4, %%o1;               \
+                ld      %5, %%o2;               \
+                ld      %6, %%o3;               \
+         "
+
+#define MULADDC_CORE                            \
+         "                                      \
+                ld      [%%o0], %%o4;           \
+                inc     4, %%o0;                \
+                ld      [%%o1], %%o5;           \
+                umul    %%o3, %%o4, %%o4;       \
+                addcc   %%o4, %%o2, %%o4;       \
+                rd      %%y, %%g1;              \
+                addx    %%g1, 0, %%g1;          \
+                addcc   %%o4, %%o5, %%o4;       \
+                st      %%o4, [%%o1];           \
+                addx    %%g1, 0, %%o2;          \
+                inc     4, %%o1;                \
+        "
+
+#define MULADDC_STOP                            \
+        "                                       \
+                st      %%o2, %0;               \
+                st      %%o1, %1;               \
+                st      %%o0, %2;               \
+        "                                       \
+        : "=m" (c), "=m" (d), "=m" (s)          \
+        : "m" (s), "m" (d), "m" (c), "m" (b)    \
+        : "g1", "o0", "o1", "o2", "o3", "o4",   \
+          "o5"                                  \
+        );
+
+#endif /* SPARCv8 */
+
+#if defined(__microblaze__) || defined(microblaze)
+
+#define MULADDC_INIT            \
+    asm(                        \
+        "                       \
+        lwi   r3,   %3;         \
+        lwi   r4,   %4;         \
+        lwi   r5,   %5;         \
+        lwi   r6,   %6;         \
+        andi  r7,   r6, 0xffff; \
+        bsrli r6,   r6, 16;     \
+        "
+
+#define MULADDC_CORE            \
+        "                       \
+        lhui  r8,   r3,   0;    \
+        addi  r3,   r3,   2;    \
+        lhui  r9,   r3,   0;    \
+        addi  r3,   r3,   2;    \
+        mul   r10,  r9,  r6;    \
+        mul   r11,  r8,  r7;    \
+        mul   r12,  r9,  r7;    \
+        mul   r13,  r8,  r6;    \
+        bsrli  r8, r10,  16;    \
+        bsrli  r9, r11,  16;    \
+        add   r13, r13,  r8;    \
+        add   r13, r13,  r9;    \
+        bslli r10, r10,  16;    \
+        bslli r11, r11,  16;    \
+        add   r12, r12, r10;    \
+        addc  r13, r13,  r0;    \
+        add   r12, r12, r11;    \
+        addc  r13, r13,  r0;    \
+        lwi   r10,  r4,   0;    \
+        add   r12, r12, r10;    \
+        addc  r13, r13,  r0;    \
+        add   r12, r12,  r5;    \
+        addc   r5, r13,  r0;    \
+        swi   r12,  r4,   0;    \
+        addi   r4,  r4,   4;    \
+        "
+
+#define MULADDC_STOP            \
+        "                       \
+        swi   r5,   %0;         \
+        swi   r4,   %1;         \
+        swi   r3,   %2;         \
+        "                       \
+        : "=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;                \
+        ld.a   %%a3, %4;                \
+        ld.w   %%d4, %5;                \
+        ld.w   %%d1, %6;                \
+        xor    %%d5, %%d5;              \
+        "
+
+#define MULADDC_CORE                    \
+        "                               \
+        ld.w   %%d0,   [%%a2+];         \
+        madd.u %%e2, %%e4, %%d0, %%d1;  \
+        ld.w   %%d0,   [%%a3];          \
+        addx   %%d2,    %%d2,  %%d0;    \
+        addc   %%d3,    %%d3,    0;     \
+        mov    %%d4,    %%d3;           \
+        st.w  [%%a3+],  %%d2;           \
+        "
+
+#define MULADDC_STOP                    \
+        "                               \
+        st.w   %0, %%d4;                \
+        st.a   %1, %%a3;                \
+        st.a   %2, %%a2;                \
+        "                               \
+        : "=m" (c), "=m" (d), "=m" (s)          \
+        : "m" (s), "m" (d), "m" (c), "m" (b)    \
+        : "d0", "d1", "e2", "d4", "a2", "a3"    \
+    );
+
+#endif /* TriCore */
+
+#if defined(__arm__)
+
+#if defined(__thumb__) && !defined(__thumb2__)
+
+#define MULADDC_INIT                            \
+    asm(                                        \
+         "                                      \
+            ldr    r0, %3;                      \
+            ldr    r1, %4;                      \
+            ldr    r2, %5;                      \
+            ldr    r3, %6;                      \
+            lsr    r7, r3, #16;                 \
+            mov    r9, r7;                      \
+            lsl    r7, r3, #16;                 \
+            lsr    r7, r7, #16;                 \
+            mov    r8, r7;                      \
+         "
+
+#define MULADDC_CORE                            \
+         "                                      \
+            ldmia  r0!, {r6};                   \
+            lsr    r7, r6, #16;                 \
+            lsl    r6, r6, #16;                 \
+            lsr    r6, r6, #16;                 \
+            mov    r4, r8;                      \
+            mul    r4, r6;                      \
+            mov    r3, r9;                      \
+            mul    r6, r3;                      \
+            mov    r5, r9;                      \
+            mul    r5, r7;                      \
+            mov    r3, r8;                      \
+            mul    r7, r3;                      \
+            lsr    r3, r6, #16;                 \
+            add    r5, r5, r3;                  \
+            lsr    r3, r7, #16;                 \
+            add    r5, r5, r3;                  \
+            add    r4, r4, r2;                  \
+            mov    r2, #0;                      \
+            adc    r5, r2;                      \
+            lsl    r3, r6, #16;                 \
+            add    r4, r4, r3;                  \
+            adc    r5, r2;                      \
+            lsl    r3, r7, #16;                 \
+            add    r4, r4, r3;                  \
+            adc    r5, r2;                      \
+            ldr    r3, [r1];                    \
+            add    r4, r4, r3;                  \
+            adc    r2, r5;                      \
+            stmia  r1!, {r4};                   \
+         "
+
+#define MULADDC_STOP                            \
+         "                                      \
+            str    r2, %0;                      \
+            str    r1, %1;                      \
+            str    r0, %2;                      \
+         "                                      \
+         : "=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;                      \
+            ldr    r1, %4;                      \
+            ldr    r2, %5;                      \
+            ldr    r3, %6;                      \
+         "
+
+#define MULADDC_CORE                            \
+         "                                      \
+            ldr    r4, [r0], #4;                \
+            mov    r5, #0;                      \
+            ldr    r6, [r1];                    \
+            umlal  r2, r5, r3, r4;              \
+            adds   r7, r6, r2;                  \
+            adc    r2, r5, #0;                  \
+            str    r7, [r1], #4;                \
+         "
+
+#define MULADDC_STOP                            \
+         "                                      \
+            str    r2, %0;                      \
+            str    r1, %1;                      \
+            str    r0, %2;                      \
+         "                                      \
+         : "=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;          \
+        ldq    $2, %4;          \
+        ldq    $3, %5;          \
+        ldq    $4, %6;          \
+        "
+
+#define MULADDC_CORE            \
+        "                       \
+        ldq    $6,  0($1);      \
+        addq   $1,  8, $1;      \
+        mulq   $6, $4, $7;      \
+        umulh  $6, $4, $6;      \
+        addq   $7, $3, $7;      \
+        cmpult $7, $3, $3;      \
+        ldq    $5,  0($2);      \
+        addq   $7, $5, $7;      \
+        cmpult $7, $5, $5;      \
+        stq    $7,  0($2);      \
+        addq   $2,  8, $2;      \
+        addq   $6, $3, $3;      \
+        addq   $5, $3, $3;      \
+        "
+
+#define MULADDC_STOP                            \
+        "                       \
+        stq    $3, %0;          \
+        stq    $2, %1;          \
+        stq    $1, %2;          \
+        "                       \
+        : "=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;         \
+        lw     $11, %4;         \
+        lw     $12, %5;         \
+        lw     $13, %6;         \
+        "
+
+#define MULADDC_CORE            \
+        "                       \
+        lw     $14, 0($10);     \
+        multu  $13, $14;        \
+        addi   $10, $10, 4;     \
+        mflo   $14;             \
+        mfhi   $9;              \
+        addu   $14, $12, $14;   \
+        lw     $15, 0($11);     \
+        sltu   $12, $14, $12;   \
+        addu   $15, $14, $15;   \
+        sltu   $14, $15, $14;   \
+        addu   $12, $12, $9;    \
+        sw     $15, 0($11);     \
+        addu   $12, $12, $14;   \
+        addi   $11, $11, 4;     \
+        "
+
+#define MULADDC_STOP            \
+        "                       \
+        sw     $12, %0;         \
+        sw     $11, %1;         \
+        sw     $10, %2;         \
+        "                       \
+        : "=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(POLARSSL_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 /* POLARSSL_HAVE_ASM */
+
+#if !defined(MULADDC_CORE)
+#if defined(POLARSSL_HAVE_UDBL)
+
+#define MULADDC_INIT                    \
+{                                       \
+    t_udbl r;                           \
+    t_uint r0, r1;
+
+#define MULADDC_CORE                    \
+    r   = *(s++) * (t_udbl) b;          \
+    r0  = r;                            \
+    r1  = r >> biL;                     \
+    r0 += c;  r1 += (r0 <  c);          \
+    r0 += *d; r1 += (r0 < *d);          \
+    c = r1; *(d++) = r0;
+
+#define MULADDC_STOP                    \
+}
+
+#else
+#define MULADDC_INIT                    \
+{                                       \
+    t_uint s0, s1, b0, b1;              \
+    t_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 */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/camellia.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,217 @@
+/**
+ * \file camellia.h
+ *
+ * \brief Camellia block cipher
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_CAMELLIA_H
+#define POLARSSL_CAMELLIA_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#include <string.h>
+
+#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
+#include <basetsd.h>
+typedef UINT32 uint32_t;
+#else
+#include <inttypes.h>
+#endif
+
+#define CAMELLIA_ENCRYPT     1
+#define CAMELLIA_DECRYPT     0
+
+#define POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH           -0x0024  /**< Invalid key length. */
+#define POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH         -0x0026  /**< Invalid data input length. */
+
+#if !defined(POLARSSL_CAMELLIA_ALT)
+// Regular implementation
+//
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          CAMELLIA context structure
+ */
+typedef struct
+{
+    int nr;                     /*!<  number of rounds  */
+    uint32_t rk[68];            /*!<  CAMELLIA round keys    */
+}
+camellia_context;
+
+/**
+ * \brief          CAMELLIA key schedule (encryption)
+ *
+ * \param ctx      CAMELLIA context to be initialized
+ * \param key      encryption key
+ * \param keysize  must be 128, 192 or 256
+ *
+ * \return         0 if successful, or POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH
+ */
+int camellia_setkey_enc( camellia_context *ctx, const unsigned char *key,
+                         unsigned int keysize );
+
+/**
+ * \brief          CAMELLIA key schedule (decryption)
+ *
+ * \param ctx      CAMELLIA context to be initialized
+ * \param key      decryption key
+ * \param keysize  must be 128, 192 or 256
+ *
+ * \return         0 if successful, or POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH
+ */
+int camellia_setkey_dec( camellia_context *ctx, const unsigned char *key,
+                         unsigned int keysize );
+
+/**
+ * \brief          CAMELLIA-ECB block encryption/decryption
+ *
+ * \param ctx      CAMELLIA context
+ * \param mode     CAMELLIA_ENCRYPT or CAMELLIA_DECRYPT
+ * \param input    16-byte input block
+ * \param output   16-byte output block
+ *
+ * \return         0 if successful
+ */
+int camellia_crypt_ecb( camellia_context *ctx,
+                    int mode,
+                    const unsigned char input[16],
+                    unsigned char output[16] );
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+/**
+ * \brief          CAMELLIA-CBC buffer encryption/decryption
+ *                 Length should be a multiple of the block
+ *                 size (16 bytes)
+ *
+ * \param ctx      CAMELLIA context
+ * \param mode     CAMELLIA_ENCRYPT or 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
+ *                 POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH
+ */
+int camellia_crypt_cbc( camellia_context *ctx,
+                    int mode,
+                    size_t length,
+                    unsigned char iv[16],
+                    const unsigned char *input,
+                    unsigned char *output );
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+#if defined(POLARSSL_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
+ * camellia_setkey_enc() for both CAMELLIA_ENCRYPT and CAMELLIE_DECRYPT.
+ *
+ * \param ctx      CAMELLIA context
+ * \param mode     CAMELLIA_ENCRYPT or 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
+ *                 POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH
+ */
+int camellia_crypt_cfb128( camellia_context *ctx,
+                       int mode,
+                       size_t length,
+                       size_t *iv_off,
+                       unsigned char iv[16],
+                       const unsigned char *input,
+                       unsigned char *output );
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_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
+ * camellia_setkey_enc() for both CAMELLIA_ENCRYPT and 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 camellia_crypt_ctr( 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 /* POLARSSL_CIPHER_MODE_CTR */
+
+#ifdef __cplusplus
+}
+#endif
+
+#else  /* POLARSSL_CAMELLIA_ALT */
+#include "camellia_alt.h"
+#endif /* POLARSSL_CAMELLIA_ALT */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int camellia_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* camellia.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/certs.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,79 @@
+/**
+ * \file certs.h
+ *
+ * \brief Sample certificates and DHM parameters for testing
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_CERTS_H
+#define POLARSSL_CERTS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Concatenation of all available CA certificates */
+extern const char test_ca_list[];
+
+/*
+ * Convenience for users who just want a certificate:
+ * RSA by default, or ECDSA if RSA i not available
+ */
+extern const char *test_ca_crt;
+extern const char *test_ca_key;
+extern const char *test_ca_pwd;
+extern const char *test_srv_crt;
+extern const char *test_srv_key;
+extern const char *test_cli_crt;
+extern const char *test_cli_key;
+
+#if defined(POLARSSL_ECDSA_C)
+extern const char test_ca_crt_ec[];
+extern const char test_ca_key_ec[];
+extern const char test_ca_pwd_ec[];
+extern const char test_srv_crt_ec[];
+extern const char test_srv_key_ec[];
+extern const char test_cli_crt_ec[];
+extern const char test_cli_key_ec[];
+#endif
+
+#if defined(POLARSSL_RSA_C)
+extern const char test_ca_crt_rsa[];
+extern const char test_ca_key_rsa[];
+extern const char test_ca_pwd_rsa[];
+extern const char test_srv_crt_rsa[];
+extern const char test_srv_key_rsa[];
+extern const char test_cli_crt_rsa[];
+extern const char test_cli_key_rsa[];
+#endif
+
+#if defined(POLARSSL_DHM_C)
+extern const char test_dhm_params[];
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* certs.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/check_config.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,323 @@
+/**
+ * \file check_config.h
+ *
+ * \brief Consistency checks for configuration options
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*
+ * It is recommended to include this file from your config.h
+ * in order to catch dependency issues early.
+ */
+
+#ifndef POLARSSL_CHECK_CONFIG_H
+#define POLARSSL_CHECK_CONFIG_H
+
+#if defined(POLARSSL_AESNI_C) && !defined(POLARSSL_HAVE_ASM)
+#error "POLARSSL_AESNI_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_CERTS_C) && !defined(POLARSSL_PEM_PARSE_C)
+#error "POLARSSL_CERTS_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_CTR_DRBG_C) && !defined(POLARSSL_AES_C)
+#error "POLARSSL_CTR_DRBG_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_DHM_C) && !defined(POLARSSL_BIGNUM_C)
+#error "POLARSSL_DHM_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_ECDH_C) && !defined(POLARSSL_ECP_C)
+#error "POLARSSL_ECDH_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_ECDSA_C) &&            \
+    ( !defined(POLARSSL_ECP_C) ||           \
+      !defined(POLARSSL_ASN1_PARSE_C) ||    \
+      !defined(POLARSSL_ASN1_WRITE_C) )
+#error "POLARSSL_ECDSA_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_ECDSA_DETERMINISTIC) && !defined(POLARSSL_HMAC_DRBG_C)
+#error "POLARSSL_ECDSA_DETERMINISTIC defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_ECP_C) && ( !defined(POLARSSL_BIGNUM_C) || (   \
+    !defined(POLARSSL_ECP_DP_SECP192R1_ENABLED) &&                  \
+    !defined(POLARSSL_ECP_DP_SECP224R1_ENABLED) &&                  \
+    !defined(POLARSSL_ECP_DP_SECP256R1_ENABLED) &&                  \
+    !defined(POLARSSL_ECP_DP_SECP384R1_ENABLED) &&                  \
+    !defined(POLARSSL_ECP_DP_SECP521R1_ENABLED) &&                  \
+    !defined(POLARSSL_ECP_DP_BP256R1_ENABLED)   &&                  \
+    !defined(POLARSSL_ECP_DP_BP384R1_ENABLED)   &&                  \
+    !defined(POLARSSL_ECP_DP_BP512R1_ENABLED)   &&                  \
+    !defined(POLARSSL_ECP_DP_SECP192K1_ENABLED) &&                  \
+    !defined(POLARSSL_ECP_DP_SECP224K1_ENABLED) &&                  \
+    !defined(POLARSSL_ECP_DP_SECP256K1_ENABLED) ) )
+#error "POLARSSL_ECP_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_ENTROPY_C) && (!defined(POLARSSL_SHA512_C) &&      \
+                                    !defined(POLARSSL_SHA256_C))
+#error "POLARSSL_ENTROPY_C defined, but not all prerequisites"
+#endif
+#if defined(POLARSSL_ENTROPY_C) && defined(POLARSSL_SHA512_C) &&         \
+    defined(POLARSSL_CONFIG_OPTIONS) && (CTR_DRBG_ENTROPY_LEN > 64)
+#error "CTR_DRBG_ENTROPY_LEN value too high"
+#endif
+#if defined(POLARSSL_ENTROPY_C) &&                                            \
+    ( !defined(POLARSSL_SHA512_C) || defined(POLARSSL_ENTROPY_FORCE_SHA256) ) \
+    && defined(POLARSSL_CONFIG_OPTIONS) && (CTR_DRBG_ENTROPY_LEN > 32)
+#error "CTR_DRBG_ENTROPY_LEN value too high"
+#endif
+#if defined(POLARSSL_ENTROPY_C) && \
+    defined(POLARSSL_ENTROPY_FORCE_SHA256) && !defined(POLARSSL_SHA256_C)
+#error "POLARSSL_ENTROPY_FORCE_SHA256 defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_GCM_C) && (                                        \
+        !defined(POLARSSL_AES_C) && !defined(POLARSSL_CAMELLIA_C) )
+#error "POLARSSL_GCM_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_HAVEGE_C) && !defined(POLARSSL_TIMING_C)
+#error "POLARSSL_HAVEGE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_HMAC_DRBG) && !defined(POLARSSL_MD_C)
+#error "POLARSSL_HMAC_DRBG_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) &&                 \
+    ( !defined(POLARSSL_ECDH_C) || !defined(POLARSSL_X509_CRT_PARSE_C) )
+#error "POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) &&                 \
+    ( !defined(POLARSSL_ECDH_C) || !defined(POLARSSL_X509_CRT_PARSE_C) )
+#error "POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) && !defined(POLARSSL_DHM_C)
+#error "POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) &&                     \
+    !defined(POLARSSL_ECDH_C)
+#error "POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) &&                   \
+    ( !defined(POLARSSL_DHM_C) || !defined(POLARSSL_RSA_C) ||           \
+      !defined(POLARSSL_X509_CRT_PARSE_C) || !defined(POLARSSL_PKCS1_V15) )
+#error "POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) &&                 \
+    ( !defined(POLARSSL_ECDH_C) || !defined(POLARSSL_RSA_C) ||          \
+      !defined(POLARSSL_X509_CRT_PARSE_C) || !defined(POLARSSL_PKCS1_V15) )
+#error "POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) &&                 \
+    ( !defined(POLARSSL_ECDH_C) || !defined(POLARSSL_ECDSA_C) ||          \
+      !defined(POLARSSL_X509_CRT_PARSE_C) )
+#error "POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) &&                   \
+    ( !defined(POLARSSL_RSA_C) || !defined(POLARSSL_X509_CRT_PARSE_C) ||\
+      !defined(POLARSSL_PKCS1_V15) )
+#error "POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) &&                       \
+    ( !defined(POLARSSL_RSA_C) || !defined(POLARSSL_X509_CRT_PARSE_C) ||\
+      !defined(POLARSSL_PKCS1_V15) )
+#error "POLARSSL_KEY_EXCHANGE_RSA_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_MEMORY_BUFFER_ALLOC_C) &&                          \
+    ( !defined(POLARSSL_PLATFORM_C) || !defined(POLARSSL_PLATFORM_MEMORY) )
+#error "POLARSSL_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PADLOCK_C) && !defined(POLARSSL_HAVE_ASM)
+#error "POLARSSL_PADLOCK_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PBKDF2_C) && !defined(POLARSSL_MD_C)
+#error "POLARSSL_PBKDF2_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PEM_PARSE_C) && !defined(POLARSSL_BASE64_C)
+#error "POLARSSL_PEM_PARSE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PEM_WRITE_C) && !defined(POLARSSL_BASE64_C)
+#error "POLARSSL_PEM_WRITE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PK_PARSE_C) && !defined(POLARSSL_PK_C)
+#error "POLARSSL_PK_PARSE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PK_WRITE_C) && !defined(POLARSSL_PK_C)
+#error "POLARSSL_PK_WRITE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PKCS11_C) && !defined(POLARSSL_PK_C)
+#error "POLARSSL_PKCS11_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_RSA_C) && ( !defined(POLARSSL_BIGNUM_C) ||         \
+    !defined(POLARSSL_OID_C) )
+#error "POLARSSL_RSA_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_SSL_PROTO_SSL3) && ( !defined(POLARSSL_MD5_C) ||     \
+    !defined(POLARSSL_SHA1_C) )
+#error "POLARSSL_SSL_PROTO_SSL3 defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_SSL_PROTO_TLS1) && ( !defined(POLARSSL_MD5_C) ||     \
+    !defined(POLARSSL_SHA1_C) )
+#error "POLARSSL_SSL_PROTO_TLS1 defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_SSL_PROTO_TLS1_1) && ( !defined(POLARSSL_MD5_C) ||     \
+    !defined(POLARSSL_SHA1_C) )
+#error "POLARSSL_SSL_PROTO_TLS1_1 defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_SSL_PROTO_TLS1_2) && ( !defined(POLARSSL_SHA1_C) &&     \
+    !defined(POLARSSL_SHA256_C) && !defined(POLARSSL_SHA512_C) )
+#error "POLARSSL_SSL_PROTO_TLS1_2 defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_SSL_CLI_C) && !defined(POLARSSL_SSL_TLS_C)
+#error "POLARSSL_SSL_CLI_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_SSL_TLS_C) && ( !defined(POLARSSL_CIPHER_C) ||     \
+    !defined(POLARSSL_MD_C) )
+#error "POLARSSL_SSL_TLS_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_SSL_SRV_C) && !defined(POLARSSL_SSL_TLS_C)
+#error "POLARSSL_SSL_SRV_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_SSL_TLS_C) && (!defined(POLARSSL_SSL_PROTO_SSL3) && \
+    !defined(POLARSSL_SSL_PROTO_TLS1) && !defined(POLARSSL_SSL_PROTO_TLS1_1) && \
+    !defined(POLARSSL_SSL_PROTO_TLS1_2))
+#error "POLARSSL_SSL_TLS_C defined, but no protocols are active"
+#endif
+
+#if defined(POLARSSL_SSL_TLS_C) && (defined(POLARSSL_SSL_PROTO_SSL3) && \
+    defined(POLARSSL_SSL_PROTO_TLS1_1) && !defined(POLARSSL_SSL_PROTO_TLS1))
+#error "Illegal protocol selection"
+#endif
+
+#if defined(POLARSSL_SSL_TLS_C) && (defined(POLARSSL_SSL_PROTO_TLS1) && \
+    defined(POLARSSL_SSL_PROTO_TLS1_2) && !defined(POLARSSL_SSL_PROTO_TLS1_1))
+#error "Illegal protocol selection"
+#endif
+
+#if defined(POLARSSL_SSL_TLS_C) && (defined(POLARSSL_SSL_PROTO_SSL3) && \
+    defined(POLARSSL_SSL_PROTO_TLS1_2) && (!defined(POLARSSL_SSL_PROTO_TLS1) || \
+    !defined(POLARSSL_SSL_PROTO_TLS1_1)))
+#error "Illegal protocol selection"
+#endif
+
+#if defined(POLARSSL_SSL_SESSION_TICKETS) && defined(POLARSSL_SSL_TLS_C) && \
+    ( !defined(POLARSSL_AES_C) || !defined(POLARSSL_SHA256_C) ||            \
+      !defined(POLARSSL_CIPHER_MODE_CBC) )
+#error "POLARSSL_SSL_SESSION_TICKETS_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) && \
+        !defined(POLARSSL_X509_CRT_PARSE_C)
+#error "POLARSSL_SSL_SERVER_NAME_INDICATION defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_THREADING_PTHREAD)
+#if !defined(POLARSSL_THREADING_C) || defined(POLARSSL_THREADING_IMPL)
+#error "POLARSSL_THREADING_PTHREAD defined, but not all prerequisites"
+#endif
+#define POLARSSL_THREADING_IMPL
+#endif
+
+#if defined(POLARSSL_THREADING_ALT)
+#if !defined(POLARSSL_THREADING_C) || defined(POLARSSL_THREADING_IMPL)
+#error "POLARSSL_THREADING_ALT defined, but not all prerequisites"
+#endif
+#define POLARSSL_THREADING_IMPL
+#endif
+
+#if defined(POLARSSL_THREADING_C) && !defined(POLARSSL_THREADING_IMPL)
+#error "POLARSSL_THREADING_C defined, single threading implementation required"
+#endif
+#undef POLARSSL_THREADING_IMPL
+
+#if defined(POLARSSL_VERSION_FEATURES) && !defined(POLARSSL_VERSION_C)
+#error "POLARSSL_VERSION_FEATURES defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_X509_USE_C) && ( !defined(POLARSSL_BIGNUM_C) ||  \
+    !defined(POLARSSL_OID_C) || !defined(POLARSSL_ASN1_PARSE_C) ||      \
+    !defined(POLARSSL_PK_PARSE_C) )
+#error "POLARSSL_X509_USE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_X509_CREATE_C) && ( !defined(POLARSSL_BIGNUM_C) ||  \
+    !defined(POLARSSL_OID_C) || !defined(POLARSSL_ASN1_WRITE_C) ||       \
+    !defined(POLARSSL_PK_WRITE_C) )
+#error "POLARSSL_X509_CREATE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_X509_CRT_PARSE_C) && ( !defined(POLARSSL_X509_USE_C) )
+#error "POLARSSL_X509_CRT_PARSE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_X509_CRL_PARSE_C) && ( !defined(POLARSSL_X509_USE_C) )
+#error "POLARSSL_X509_CRL_PARSE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_X509_CSR_PARSE_C) && ( !defined(POLARSSL_X509_USE_C) )
+#error "POLARSSL_X509_CSR_PARSE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_X509_CRT_WRITE_C) && ( !defined(POLARSSL_X509_CREATE_C) )
+#error "POLARSSL_X509_CRT_WRITE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_X509_CSR_WRITE_C) && ( !defined(POLARSSL_X509_CREATE_C) )
+#error "POLARSSL_X509_CSR_WRITE_C defined, but not all prerequisites"
+#endif
+
+#endif /* POLARSSL_CHECK_CONFIG_H */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/cipher.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,643 @@
+/**
+ * \file cipher.h
+ *
+ * \brief Generic cipher wrapper.
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef POLARSSL_CIPHER_H
+#define POLARSSL_CIPHER_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_GCM_C)
+#define POLARSSL_CIPHER_MODE_AEAD
+#endif
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+#define POLARSSL_CIPHER_MODE_WITH_PADDING
+#endif
+
+#include <string.h>
+
+#if defined(_MSC_VER) && !defined(inline)
+#define inline _inline
+#else
+#if defined(__ARMCC_VERSION) && !defined(inline)
+#define inline __inline
+#endif /* __ARMCC_VERSION */
+#endif /*_MSC_VER */
+
+#define POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE            -0x6080  /**< The selected feature is not available. */
+#define POLARSSL_ERR_CIPHER_BAD_INPUT_DATA                 -0x6100  /**< Bad input parameters to function. */
+#define POLARSSL_ERR_CIPHER_ALLOC_FAILED                   -0x6180  /**< Failed to allocate memory. */
+#define POLARSSL_ERR_CIPHER_INVALID_PADDING                -0x6200  /**< Input data contains invalid padding and is rejected. */
+#define POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED            -0x6280  /**< Decryption of block requires a full block. */
+#define POLARSSL_ERR_CIPHER_AUTH_FAILED                    -0x6300  /**< Authentication failed (for AEAD modes). */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+    POLARSSL_CIPHER_ID_NONE = 0,
+    POLARSSL_CIPHER_ID_NULL,
+    POLARSSL_CIPHER_ID_AES,
+    POLARSSL_CIPHER_ID_DES,
+    POLARSSL_CIPHER_ID_3DES,
+    POLARSSL_CIPHER_ID_CAMELLIA,
+    POLARSSL_CIPHER_ID_BLOWFISH,
+    POLARSSL_CIPHER_ID_ARC4,
+} cipher_id_t;
+
+typedef enum {
+    POLARSSL_CIPHER_NONE = 0,
+    POLARSSL_CIPHER_NULL,
+    POLARSSL_CIPHER_AES_128_ECB,
+    POLARSSL_CIPHER_AES_192_ECB,
+    POLARSSL_CIPHER_AES_256_ECB,
+    POLARSSL_CIPHER_AES_128_CBC,
+    POLARSSL_CIPHER_AES_192_CBC,
+    POLARSSL_CIPHER_AES_256_CBC,
+    POLARSSL_CIPHER_AES_128_CFB128,
+    POLARSSL_CIPHER_AES_192_CFB128,
+    POLARSSL_CIPHER_AES_256_CFB128,
+    POLARSSL_CIPHER_AES_128_CTR,
+    POLARSSL_CIPHER_AES_192_CTR,
+    POLARSSL_CIPHER_AES_256_CTR,
+    POLARSSL_CIPHER_AES_128_GCM,
+    POLARSSL_CIPHER_AES_192_GCM,
+    POLARSSL_CIPHER_AES_256_GCM,
+    POLARSSL_CIPHER_CAMELLIA_128_ECB,
+    POLARSSL_CIPHER_CAMELLIA_192_ECB,
+    POLARSSL_CIPHER_CAMELLIA_256_ECB,
+    POLARSSL_CIPHER_CAMELLIA_128_CBC,
+    POLARSSL_CIPHER_CAMELLIA_192_CBC,
+    POLARSSL_CIPHER_CAMELLIA_256_CBC,
+    POLARSSL_CIPHER_CAMELLIA_128_CFB128,
+    POLARSSL_CIPHER_CAMELLIA_192_CFB128,
+    POLARSSL_CIPHER_CAMELLIA_256_CFB128,
+    POLARSSL_CIPHER_CAMELLIA_128_CTR,
+    POLARSSL_CIPHER_CAMELLIA_192_CTR,
+    POLARSSL_CIPHER_CAMELLIA_256_CTR,
+    POLARSSL_CIPHER_CAMELLIA_128_GCM,
+    POLARSSL_CIPHER_CAMELLIA_192_GCM,
+    POLARSSL_CIPHER_CAMELLIA_256_GCM,
+    POLARSSL_CIPHER_DES_ECB,
+    POLARSSL_CIPHER_DES_CBC,
+    POLARSSL_CIPHER_DES_EDE_ECB,
+    POLARSSL_CIPHER_DES_EDE_CBC,
+    POLARSSL_CIPHER_DES_EDE3_ECB,
+    POLARSSL_CIPHER_DES_EDE3_CBC,
+    POLARSSL_CIPHER_BLOWFISH_ECB,
+    POLARSSL_CIPHER_BLOWFISH_CBC,
+    POLARSSL_CIPHER_BLOWFISH_CFB64,
+    POLARSSL_CIPHER_BLOWFISH_CTR,
+    POLARSSL_CIPHER_ARC4_128,
+} cipher_type_t;
+
+typedef enum {
+    POLARSSL_MODE_NONE = 0,
+    POLARSSL_MODE_ECB,
+    POLARSSL_MODE_CBC,
+    POLARSSL_MODE_CFB,
+    POLARSSL_MODE_OFB,
+    POLARSSL_MODE_CTR,
+    POLARSSL_MODE_GCM,
+    POLARSSL_MODE_STREAM,
+} cipher_mode_t;
+
+typedef enum {
+    POLARSSL_PADDING_PKCS7 = 0,     /**< PKCS7 padding (default)        */
+    POLARSSL_PADDING_ONE_AND_ZEROS, /**< ISO/IEC 7816-4 padding         */
+    POLARSSL_PADDING_ZEROS_AND_LEN, /**< ANSI X.923 padding             */
+    POLARSSL_PADDING_ZEROS,         /**< zero padding (not reversible!) */
+    POLARSSL_PADDING_NONE,          /**< never pad (full blocks only)   */
+} cipher_padding_t;
+
+typedef enum {
+    POLARSSL_OPERATION_NONE = -1,
+    POLARSSL_DECRYPT = 0,
+    POLARSSL_ENCRYPT,
+} operation_t;
+
+enum {
+    /** Undefined key length */
+    POLARSSL_KEY_LENGTH_NONE = 0,
+    /** Key length, in bits (including parity), for DES keys */
+    POLARSSL_KEY_LENGTH_DES  = 64,
+    /** Key length, in bits (including parity), for DES in two key EDE */
+    POLARSSL_KEY_LENGTH_DES_EDE = 128,
+    /** Key length, in bits (including parity), for DES in three-key EDE */
+    POLARSSL_KEY_LENGTH_DES_EDE3 = 192,
+};
+
+/** Maximum length of any IV, in bytes */
+#define POLARSSL_MAX_IV_LENGTH      16
+/** Maximum block size of any cipher, in bytes */
+#define POLARSSL_MAX_BLOCK_LENGTH   16
+
+/**
+ * Base cipher information. The non-mode specific functions and values.
+ */
+typedef struct {
+
+    /** Base Cipher type (e.g. POLARSSL_CIPHER_ID_AES) */
+    cipher_id_t cipher;
+
+    /** Encrypt using ECB */
+    int (*ecb_func)( void *ctx, operation_t mode,
+                     const unsigned char *input, unsigned char *output );
+
+    /** Encrypt using CBC */
+    int (*cbc_func)( void *ctx, operation_t mode, size_t length,
+                     unsigned char *iv, const unsigned char *input,
+                     unsigned char *output );
+
+    /** Encrypt using CFB (Full length) */
+    int (*cfb_func)( void *ctx, operation_t mode, size_t length, size_t *iv_off,
+                     unsigned char *iv, const unsigned char *input,
+                     unsigned char *output );
+
+    /** 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 );
+
+    /** Encrypt using STREAM */
+    int (*stream_func)( void *ctx, size_t length,
+                        const unsigned char *input, unsigned char *output );
+
+    /** Set key for encryption purposes */
+    int (*setkey_enc_func)( void *ctx, const unsigned char *key,
+                            unsigned int key_length );
+
+    /** Set key for decryption purposes */
+    int (*setkey_dec_func)( void *ctx, const unsigned char *key,
+                            unsigned int key_length);
+
+    /** Allocate a new context */
+    void * (*ctx_alloc_func)( void );
+
+    /** Free the given context */
+    void (*ctx_free_func)( void *ctx );
+
+} cipher_base_t;
+
+/**
+ * Cipher information. Allows cipher functions to be called in a generic way.
+ */
+typedef struct {
+    /** Full cipher identifier (e.g. POLARSSL_CIPHER_AES_256_CBC) */
+    cipher_type_t type;
+
+    /** Cipher mode (e.g. POLARSSL_MODE_CBC) */
+    cipher_mode_t mode;
+
+    /** Cipher key length, in bits (default length for variable sized ciphers)
+     *  (Includes parity bits for ciphers like DES) */
+    unsigned int key_length;
+
+    /** Name of the cipher */
+    const char * name;
+
+    /** IV/NONCE size, in bytes.
+     *  For cipher that accept many sizes: recommended size */
+    unsigned int iv_size;
+
+    /** Flag for ciphers that accept many sizes of IV/NONCE */
+    int accepts_variable_iv_size;
+
+    /** block size, in bytes */
+    unsigned int block_size;
+
+    /** Base cipher information and functions */
+    const cipher_base_t *base;
+
+} cipher_info_t;
+
+/**
+ * Generic cipher context.
+ */
+typedef struct {
+    /** Information about the associated cipher */
+    const cipher_info_t *cipher_info;
+
+    /** Key length to use */
+    int key_length;
+
+    /** Operation that the context's key has been initialised for */
+    operation_t operation;
+
+    /** Padding functions to use, if relevant for 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 );
+
+    /** Buffer for data that hasn't been encrypted yet */
+    unsigned char unprocessed_data[POLARSSL_MAX_BLOCK_LENGTH];
+
+    /** Number of bytes that still need processing */
+    size_t unprocessed_len;
+
+    /** Current IV or NONCE_COUNTER for CTR-mode */
+    unsigned char iv[POLARSSL_MAX_IV_LENGTH];
+
+    /** IV size in bytes (for ciphers with variable-length IVs) */
+    size_t iv_size;
+
+    /** Cipher-specific context */
+    void *cipher_ctx;
+} cipher_context_t;
+
+/**
+ * \brief Returns the list of ciphers supported by the generic cipher module.
+ *
+ * \return              a statically allocated array of ciphers, the last entry
+ *                      is 0.
+ */
+const int *cipher_list( void );
+
+/**
+ * \brief               Returns 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 cipher_name, or NULL if not found.
+ */
+const cipher_info_t *cipher_info_from_string( const char *cipher_name );
+
+/**
+ * \brief               Returns 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 cipher_type, or NULL if not found.
+ */
+const cipher_info_t *cipher_info_from_type( const cipher_type_t cipher_type );
+
+/**
+ * \brief               Returns the cipher information structure associated
+ *                      with the given cipher id, key size and mode.
+ *
+ * \param cipher_id     Id of the cipher to search for
+ *                      (e.g. POLARSSL_CIPHER_ID_AES)
+ * \param key_length    Length of the key in bits
+ * \param mode          Cipher mode (e.g. POLARSSL_MODE_CBC)
+ *
+ * \return              the cipher information structure associated with the
+ *                      given cipher_type, or NULL if not found.
+ */
+const cipher_info_t *cipher_info_from_values( const cipher_id_t cipher_id,
+                                              int key_length,
+                                              const cipher_mode_t mode );
+
+/**
+ * \brief               Initialises and fills the cipher context structure with
+ *                      the appropriate values.
+ *
+ * \param ctx           context to initialise. May not be NULL.
+ * \param cipher_info   cipher to use.
+ *
+ * \return              0 on success,
+ *                      POLARSSL_ERR_CIPHER_BAD_INPUT_DATA on parameter failure,
+ *                      POLARSSL_ERR_CIPHER_ALLOC_FAILED if allocation of the
+ *                      cipher-specific context failed.
+ */
+int cipher_init_ctx( cipher_context_t *ctx, const cipher_info_t *cipher_info );
+
+/**
+ * \brief               Free the cipher-specific context of ctx. Freeing ctx
+ *                      itself remains the responsibility of the caller.
+ *
+ * \param ctx           Free the cipher-specific context
+ *
+ * \returns             0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if
+ *                      parameter verification fails.
+ */
+int cipher_free_ctx( cipher_context_t *ctx );
+
+/**
+ * \brief               Returns the block size of the given cipher.
+ *
+ * \param ctx           cipher's context. Must have been initialised.
+ *
+ * \return              size of the cipher's blocks, or 0 if ctx has not been
+ *                      initialised.
+ */
+static inline unsigned int cipher_get_block_size( const cipher_context_t *ctx )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info )
+        return 0;
+
+    return ctx->cipher_info->block_size;
+}
+
+/**
+ * \brief               Returns the mode of operation for the cipher.
+ *                      (e.g. POLARSSL_MODE_CBC)
+ *
+ * \param ctx           cipher's context. Must have been initialised.
+ *
+ * \return              mode of operation, or POLARSSL_MODE_NONE if ctx
+ *                      has not been initialised.
+ */
+static inline cipher_mode_t cipher_get_cipher_mode( const cipher_context_t *ctx )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info )
+        return POLARSSL_MODE_NONE;
+
+    return ctx->cipher_info->mode;
+}
+
+/**
+ * \brief               Returns the size of the cipher's IV/NONCE in bytes.
+ *
+ * \param ctx           cipher's context. Must have been initialised.
+ *
+ * \return              If IV has not been set yet: (recommended) IV size
+ *                      (0 for ciphers not using IV/NONCE).
+ *                      If IV has already been set: actual size.
+ */
+static inline int cipher_get_iv_size( const cipher_context_t *ctx )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info )
+        return 0;
+
+    if( ctx->iv_size != 0 )
+        return (int) ctx->iv_size;
+
+    return ctx->cipher_info->iv_size;
+}
+
+/**
+ * \brief               Returns the type of the given cipher.
+ *
+ * \param ctx           cipher's context. Must have been initialised.
+ *
+ * \return              type of the cipher, or POLARSSL_CIPHER_NONE if ctx has
+ *                      not been initialised.
+ */
+static inline cipher_type_t cipher_get_type( const cipher_context_t *ctx )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info )
+        return POLARSSL_CIPHER_NONE;
+
+    return ctx->cipher_info->type;
+}
+
+/**
+ * \brief               Returns the name of the given cipher, as a string.
+ *
+ * \param ctx           cipher's context. Must have been initialised.
+ *
+ * \return              name of the cipher, or NULL if ctx was not initialised.
+ */
+static inline const char *cipher_get_name( const cipher_context_t *ctx )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info )
+        return 0;
+
+    return ctx->cipher_info->name;
+}
+
+/**
+ * \brief               Returns the key length of the cipher.
+ *
+ * \param ctx           cipher's context. Must have been initialised.
+ *
+ * \return              cipher's key length, in bits, or
+ *                      POLARSSL_KEY_LENGTH_NONE if ctx has not been
+ *                      initialised.
+ */
+static inline int cipher_get_key_size ( const cipher_context_t *ctx )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info )
+        return POLARSSL_KEY_LENGTH_NONE;
+
+    return ctx->cipher_info->key_length;
+}
+
+/**
+ * \brief               Returns the operation of the given cipher.
+ *
+ * \param ctx           cipher's context. Must have been initialised.
+ *
+ * \return              operation (POLARSSL_ENCRYPT or POLARSSL_DECRYPT),
+ *                      or POLARSSL_OPERATION_NONE if ctx has not been
+ *                      initialised.
+ */
+static inline operation_t cipher_get_operation( const cipher_context_t *ctx )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info )
+        return POLARSSL_OPERATION_NONE;
+
+    return ctx->operation;
+}
+
+/**
+ * \brief               Set the key to use with the given context.
+ *
+ * \param ctx           generic cipher context. May not be NULL. Must have been
+ *                      initialised using cipher_context_from_type or
+ *                      cipher_context_from_string.
+ * \param key           The key to use.
+ * \param key_length    key length to use, in bits.
+ * \param operation     Operation that the key will be used for, either
+ *                      POLARSSL_ENCRYPT or POLARSSL_DECRYPT.
+ *
+ * \returns             0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if
+ *                      parameter verification fails or a cipher specific
+ *                      error code.
+ */
+int cipher_setkey( cipher_context_t *ctx, const unsigned char *key,
+                   int key_length, const operation_t operation );
+
+#if defined(POLARSSL_CIPHER_MODE_WITH_PADDING)
+/**
+ * \brief               Set padding mode, for cipher modes that use padding.
+ *                      (Default: PKCS7 padding.)
+ *
+ * \param ctx           generic cipher context
+ * \param mode          padding mode
+ *
+ * \returns             0 on success, POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE
+ *                      if selected padding mode is not supported, or
+ *                      POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if the cipher mode
+ *                      does not support padding.
+ */
+int cipher_set_padding_mode( cipher_context_t *ctx, cipher_padding_t mode );
+#endif /* POLARSSL_CIPHER_MODE_WITH_PADDING */
+
+/**
+ * \brief               Set the initialization vector (IV) or nonce
+ *
+ * \param ctx           generic cipher context
+ * \param iv            IV to use (or NONCE_COUNTER for CTR-mode ciphers)
+ * \param iv_len        IV length for ciphers with variable-size IV;
+ *                      discarded by ciphers with fixed-size IV.
+ *
+ * \returns             O on success, or POLARSSL_ERR_CIPHER_BAD_INPUT_DATA
+ *
+ * \note                Some ciphers don't use IVs nor NONCE. For these
+ *                      ciphers, this function has no effect.
+ */
+int cipher_set_iv( cipher_context_t *ctx,
+                   const unsigned char *iv, size_t iv_len );
+
+/**
+ * \brief               Finish preparation of the given context
+ *
+ * \param ctx           generic cipher context
+ *
+ * \returns             0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA
+ *                      if parameter verification fails.
+ */
+int cipher_reset( cipher_context_t *ctx );
+
+#if defined(POLARSSL_CIPHER_MODE_AEAD)
+/**
+ * \brief               Add additional data (for AEAD ciphers).
+ *                      This function has no effect for non-AEAD ciphers.
+ *                      For AEAD ciphers, it may or may not be called
+ *                      repeatedly, and/or interleaved with calls to
+ *                      cipher_udpate(), depending on the cipher.
+ *                      E.g. for GCM is must be called exactly once, right
+ *                      after cipher_reset().
+ *
+ * \param ctx           generic cipher context
+ * \param ad            Additional data to use.
+ * \param ad_len        Length of ad.
+ *
+ * \returns             0 on success, or a specific error code.
+ */
+int cipher_update_ad( cipher_context_t *ctx,
+                      const unsigned char *ad, size_t ad_len );
+#endif /* POLARSSL_CIPHER_MODE_AEAD */
+
+/**
+ * \brief               Generic cipher update function. Encrypts/decrypts
+ *                      using the given cipher context. Writes as many block
+ *                      size'd blocks of data as possible to output. Any data
+ *                      that cannot be written immediately will either be added
+ *                      to the next block, or flushed when cipher_final is
+ *                      called.
+ *                      Exception: for POLARSSL_MODE_ECB, expects single block
+ *                                 in size (e.g. 16 bytes for AES)
+ *
+ * \param ctx           generic cipher context
+ * \param input         buffer holding the input data
+ * \param ilen          length of the input data
+ * \param output        buffer for the output data. Should be able to hold at
+ *                      least ilen + block_size. Cannot be the same buffer as
+ *                      input!
+ * \param olen          length of the output data, will be filled with the
+ *                      actual number of bytes written.
+ *
+ * \returns             0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if
+ *                      parameter verification fails,
+ *                      POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE on an
+ *                      unsupported mode for a cipher or a cipher specific
+ *                      error code.
+ *
+ * \note                If the underlying cipher is GCM, all calls to this
+ *                      function, except the last one before cipher_finish(),
+ *                      must have ilen a multiple of the block size.
+ */
+int cipher_update( cipher_context_t *ctx, const unsigned char *input,
+                   size_t ilen, unsigned char *output, size_t *olen );
+
+/**
+ * \brief               Generic cipher finalisation function. If data still
+ *                      needs to be flushed from an incomplete block, data
+ *                      contained within it will be padded with the size of
+ *                      the last block, and written to the output buffer.
+ *
+ * \param ctx           Generic cipher context
+ * \param output        buffer to write data to. Needs block_size available.
+ * \param olen          length of the data written to the output buffer.
+ *
+ * \returns             0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if
+ *                      parameter verification fails,
+ *                      POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED if decryption
+ *                      expected a full block but was not provided one,
+ *                      POLARSSL_ERR_CIPHER_INVALID_PADDING on invalid padding
+ *                      while decrypting or a cipher specific error code.
+ */
+int cipher_finish( cipher_context_t *ctx,
+                   unsigned char *output, size_t *olen );
+
+#if defined(POLARSSL_CIPHER_MODE_AEAD)
+/**
+ * \brief               Write tag for AEAD ciphers.
+ *                      No effect for other ciphers.
+ *                      Must be called after cipher_finish().
+ *
+ * \param ctx           Generic cipher context
+ * \param tag           buffer to write the tag
+ * \param tag_len       Length of the tag to write
+ *
+ * \return              0 on success, or a specific error code.
+ */
+int cipher_write_tag( cipher_context_t *ctx,
+                      unsigned char *tag, size_t tag_len );
+
+/**
+ * \brief               Check tag for AEAD ciphers.
+ *                      No effect for other ciphers.
+ *                      Calling time depends on the cipher:
+ *                      for GCM, must be called after cipher_finish().
+ *
+ * \param ctx           Generic cipher context
+ * \param tag           Buffer holding the tag
+ * \param tag_len       Length of the tag to check
+ *
+ * \return              0 on success, or a specific error code.
+ */
+int cipher_check_tag( cipher_context_t *ctx,
+                      const unsigned char *tag, size_t tag_len );
+#endif /* POLARSSL_CIPHER_MODE_AEAD */
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int cipher_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* POLARSSL_CIPHER_H */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/cipher_wrap.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,59 @@
+/**
+ * \file cipher_wrap.h
+ *
+ * \brief Cipher wrappers.
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ *  Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_CIPHER_WRAP_H
+#define POLARSSL_CIPHER_WRAP_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+#include "cipher.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct
+{
+    cipher_type_t type;
+    const cipher_info_t *info;
+} cipher_definition_t;
+
+extern const cipher_definition_t cipher_definitions[];
+
+extern int supported_ciphers[];
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* POLARSSL_CIPHER_WRAP_H */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/compat-1.2.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,391 @@
+/**
+ * \file compat-1.2.h
+ *
+ * \brief Backwards compatibility header for PolarSSL-1.2 from PolarSSL-1.3
+ *
+ *  Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_COMPAT_1_2_H
+#define POLARSSL_COMPAT_1_2_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+// Comment out to disable prototype change warnings
+#define SHOW_PROTOTYPE_CHANGE_WARNINGS
+
+#if defined(_MSC_VER) && !defined(inline)
+#define inline _inline
+#else
+#if defined(__ARMCC_VERSION) && !defined(inline)
+#define inline __inline
+#endif /* __ARMCC_VERSION */
+#endif /* _MSC_VER */
+
+#if defined(_MSC_VER)
+// MSVC does not support #warning
+#undef SHOW_PROTOTYPE_CHANGE_WARNINGS
+#endif
+
+#if defined(SHOW_PROTOTYPE_CHANGE_WARNINGS)
+#warning "You can disable these warnings by commenting SHOW_PROTOTYPE_CHANGE_WARNINGS in compat-1.2.h"
+#endif
+
+#if defined(POLARSSL_SHA256_C)
+#define POLARSSL_SHA2_C
+#include "sha256.h"
+
+/*
+ * SHA-2 -> SHA-256
+ */
+typedef sha256_context sha2_context;
+
+static inline void sha2_starts( sha256_context *ctx, int is224 ) {
+    sha256_starts( ctx, is224 );
+}
+static inline void sha2_update( sha256_context *ctx, const unsigned char *input,
+                         size_t ilen ) {
+    sha256_update( ctx, input, ilen );
+}
+static inline void sha2_finish( sha256_context *ctx, unsigned char output[32] ) {
+    sha256_finish( ctx, output );
+}
+static inline int sha2_file( const char *path, unsigned char output[32], int is224 ) {
+    return sha256_file( path, output, is224 );
+}
+static inline void sha2( const unsigned char *input, size_t ilen,
+                  unsigned char output[32], int is224 ) {
+    sha256( input, ilen, output, is224 );
+}
+static inline void sha2_hmac_starts( sha256_context *ctx, const unsigned char *key,
+                              size_t keylen, int is224 ) {
+    sha256_hmac_starts( ctx, key, keylen, is224 );
+}
+static inline void sha2_hmac_update( sha256_context *ctx, const unsigned char *input, size_t ilen ) {
+    sha256_hmac_update( ctx, input, ilen );
+}
+static inline void sha2_hmac_finish( sha256_context *ctx, unsigned char output[32] ) {
+    sha256_hmac_finish( ctx, output );
+}
+static inline void sha2_hmac_reset( sha256_context *ctx ) {
+    sha256_hmac_reset( ctx );
+}
+static inline void sha2_hmac( const unsigned char *key, size_t keylen,
+                       const unsigned char *input, size_t ilen,
+                       unsigned char output[32], int is224 ) {
+    sha256_hmac( key, keylen, input, ilen, output, is224 );
+}
+static inline int sha2_self_test( int verbose ) {
+    return sha256_self_test( verbose );
+}
+#endif /* POLARSSL_SHA256_C */
+
+#if defined(POLARSSL_SHA512_C)
+#define POLARSSL_SHA4_C
+#include "sha512.h"
+
+/*
+ * SHA-4 -> SHA-512
+ */
+typedef sha512_context sha4_context;
+
+static inline void sha4_starts( sha512_context *ctx, int is384 ) {
+    sha512_starts( ctx, is384 );
+}
+static inline void sha4_update( sha512_context *ctx, const unsigned char *input,
+                         size_t ilen ) {
+    sha512_update( ctx, input, ilen );
+}
+static inline void sha4_finish( sha512_context *ctx, unsigned char output[64] ) {
+    sha512_finish( ctx, output );
+}
+static inline int sha4_file( const char *path, unsigned char output[64], int is384 ) {
+    return sha512_file( path, output, is384 );
+}
+static inline void sha4( const unsigned char *input, size_t ilen,
+                  unsigned char output[32], int is384 ) {
+    sha512( input, ilen, output, is384 );
+}
+static inline void sha4_hmac_starts( sha512_context *ctx, const unsigned char *key,
+                              size_t keylen, int is384 ) {
+    sha512_hmac_starts( ctx, key, keylen, is384 );
+}
+static inline void sha4_hmac_update( sha512_context *ctx, const unsigned char *input, size_t ilen ) {
+    sha512_hmac_update( ctx, input, ilen );
+}
+static inline void sha4_hmac_finish( sha512_context *ctx, unsigned char output[64] ) {
+    sha512_hmac_finish( ctx, output );
+}
+static inline void sha4_hmac_reset( sha512_context *ctx ) {
+    sha512_hmac_reset( ctx );
+}
+static inline void sha4_hmac( const unsigned char *key, size_t keylen,
+                       const unsigned char *input, size_t ilen,
+                       unsigned char output[64], int is384 ) {
+    sha512_hmac( key, keylen, input, ilen, output, is384 );
+}
+static inline int sha4_self_test( int verbose ) {
+    return sha512_self_test( verbose );
+}
+#endif /* POLARSSL_SHA512_C */
+
+#if defined(POLARSSL_CIPHER_C)
+#if defined(SHOW_PROTOTYPE_CHANGE_WARNINGS)
+#warning "cipher_reset() prototype changed. Manual change required if used"
+#endif
+#endif
+
+#if defined(POLARSSL_RSA_C)
+#define SIG_RSA_RAW     POLARSSL_MD_NONE
+#define SIG_RSA_MD2     POLARSSL_MD_MD2
+#define SIG_RSA_MD4     POLARSSL_MD_MD4
+#define SIG_RSA_MD5     POLARSSL_MD_MD5
+#define SIG_RSA_SHA1    POLARSSL_MD_SHA1
+#define SIG_RSA_SHA224  POLARSSL_MD_SHA224
+#define SIG_RSA_SHA256  POLARSSL_MD_SHA256
+#define SIG_RSA_SHA384  POLARSSL_MD_SHA384
+#define SIG_RSA_SHA512  POLARSSL_MD_SHA512
+#if defined(SHOW_PROTOTYPE_CHANGE_WARNINGS)
+#warning "rsa_pkcs1_verify() prototype changed. Manual change required if used"
+#warning "rsa_pkcs1_decrypt() prototype changed. Manual change required if used"
+#endif
+#endif /* POLARSSL_RSA_C */
+
+#if defined(POLARSSL_DHM_C)
+#if defined(SHOW_PROTOTYPE_CHANGE_WARNINGS)
+#warning "dhm_calc_secret() prototype changed. Manual change required if used"
+#endif
+#endif
+
+#if defined(POLARSSL_GCM_C)
+#if defined(SHOW_PROTOTYPE_CHANGE_WARNINGS)
+#warning "gcm_init() prototype changed. Manual change required if used"
+#endif
+#endif
+
+#if defined(POLARSSL_SSL_CLI_C)
+#if defined(SHOW_PROTOTYPE_CHANGE_WARNINGS)
+#warning "ssl_set_own_cert() prototype changed. Change to ssl_set_own_cert_rsa(). Manual change required if used"
+#endif
+#endif
+
+#if defined(POLARSSL_X509_USE_C) || defined(POLARSSL_X509_CREATE_C)
+#include "x509.h"
+
+#define POLARSSL_ERR_X509_CERT_INVALID_FORMAT POLARSSL_ERR_X509_INVALID_FORMAT
+#define POLARSSL_ERR_X509_CERT_INVALID_VERSION POLARSSL_ERR_X509_INVALID_VERSION
+#define POLARSSL_ERR_X509_CERT_INVALID_ALG POLARSSL_ERR_X509_INVALID_ALG
+#define POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG POLARSSL_ERR_X509_UNKNOWN_SIG_ALG
+#define POLARSSL_ERR_X509_CERT_INVALID_NAME POLARSSL_ERR_X509_INVALID_NAME
+#define POLARSSL_ERR_X509_CERT_INVALID_DATE POLARSSL_ERR_X509_INVALID_DATE
+#define POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS POLARSSL_ERR_X509_INVALID_EXTENSIONS
+#define POLARSSL_ERR_X509_CERT_SIG_MISMATCH POLARSSL_ERR_X509_SIG_MISMATCH
+#define POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE POLARSSL_ERR_X509_INVALID_SIGNATURE
+#define POLARSSL_ERR_X509_CERT_INVALID_SERIAL POLARSSL_ERR_X509_INVALID_SERIAL
+#define POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION POLARSSL_ERR_X509_UNKNOWN_VERSION
+
+static inline int x509parse_serial_gets( char *buf, size_t size, const x509_buf *serial ) {
+    return x509_serial_gets( buf, size, serial );
+}
+static inline int x509parse_dn_gets( char *buf, size_t size, const x509_name *dn ) {
+    return x509_dn_gets( buf, size, dn );
+}
+static inline int x509parse_time_expired( const x509_time *time ) {
+    return x509_time_expired( time );
+}
+#endif /* POLARSSL_X509_USE_C || POLARSSL_X509_CREATE_C */
+
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+#define POLARSSL_X509_PARSE_C
+#include "x509_crt.h"
+typedef x509_crt x509_cert;
+
+static inline int x509parse_crt_der( x509_cert *chain, const unsigned char *buf,
+                              size_t buflen ) {
+    return x509_crt_parse_der( chain, buf, buflen );
+}
+static inline int x509parse_crt( x509_cert *chain, const unsigned char *buf, size_t buflen ) {
+    return x509_crt_parse( chain, buf, buflen );
+}
+static inline int x509parse_crtfile( x509_cert *chain, const char *path ) {
+    return x509_crt_parse_file( chain, path );
+}
+static inline int x509parse_crtpath( x509_cert *chain, const char *path ) {
+    return x509_crt_parse_path( chain, path );
+}
+static inline int x509parse_cert_info( char *buf, size_t size, const char *prefix,
+                                const x509_cert *crt ) {
+    return x509_crt_info( buf, size, prefix, crt );
+}
+static inline int x509parse_verify( x509_cert *crt, x509_cert *trust_ca,
+                             x509_crl *ca_crl, const char *cn, int *flags,
+                             int (*f_vrfy)(void *, x509_cert *, int, int *),
+                             void *p_vrfy ) {
+    return x509_crt_verify( crt, trust_ca, ca_crl, cn, flags, f_vrfy, p_vrfy );
+}
+static inline int x509parse_revoked( const x509_cert *crt, const x509_crl *crl ) {
+    return x509_crt_revoked( crt, crl );
+}
+static inline void x509_free( x509_cert *crt ) {
+    x509_crt_free( crt );
+}
+#endif /* POLARSSL_X509_CRT_PARSE_C */
+
+#if defined(POLARSSL_X509_CRL_PARSE_C)
+#define POLARSSL_X509_PARSE_C
+#include "x509_crl.h"
+static inline int x509parse_crl( x509_crl *chain, const unsigned char *buf, size_t buflen ) {
+    return x509_crl_parse( chain, buf, buflen );
+}
+static inline int x509parse_crlfile( x509_crl *chain, const char *path ) {
+    return x509_crl_parse_file( chain, path );
+}
+static inline int x509parse_crl_info( char *buf, size_t size, const char *prefix,
+                               const x509_crl *crl ) {
+    return x509_crl_info( buf, size, prefix, crl );
+}
+#endif /* POLARSSL_X509_CRL_PARSE_C */
+
+#if defined(POLARSSL_X509_CSR_PARSE_C)
+#define POLARSSL_X509_PARSE_C
+#include "x509_csr.h"
+static inline int x509parse_csr( x509_csr *csr, const unsigned char *buf, size_t buflen ) {
+    return x509_csr_parse( csr, buf, buflen );
+}
+static inline int x509parse_csrfile( x509_csr *csr, const char *path ) {
+    return x509_csr_parse_file( csr, path );
+}
+static inline int x509parse_csr_info( char *buf, size_t size, const char *prefix,
+                               const x509_csr *csr ) {
+    return x509_csr_info( buf, size, prefix, csr );
+}
+#endif /* POLARSSL_X509_CSR_PARSE_C */
+
+#if defined(POLARSSL_SSL_TLS_C)
+#include "ssl_ciphersuites.h"
+
+#define ssl_default_ciphersuites ssl_list_ciphersuites()
+#endif
+
+#if defined(POLARSSL_PK_PARSE_C) && defined(POLARSSL_RSA_C)
+#include "rsa.h"
+#include "pk.h"
+
+#define POLARSSL_ERR_X509_PASSWORD_MISMATCH POLARSSL_ERR_PK_PASSWORD_MISMATCH
+#define POLARSSL_ERR_X509_KEY_INVALID_FORMAT POLARSSL_ERR_PK_KEY_INVALID_FORMAT
+#define POLARSSL_ERR_X509_UNKNOWN_PK_ALG POLARSSL_ERR_PK_UNKNOWN_PK_ALG
+#define POLARSSL_ERR_X509_CERT_INVALID_PUBKEY POLARSSL_ERR_PK_INVALID_PUBKEY
+
+#if defined(POLARSSL_FS_IO)
+static inline int x509parse_keyfile( rsa_context *rsa, const char *path,
+                              const char *pwd ) {
+    int ret;
+    pk_context pk;
+    pk_init( &pk );
+    ret = pk_parse_keyfile( &pk, path, pwd );
+    if( ret == 0 && ! pk_can_do( &pk, POLARSSL_PK_RSA ) )
+        ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
+    if( ret == 0 )
+        rsa_copy( rsa, pk_rsa( pk ) );
+    else
+        rsa_free( rsa );
+    pk_free( &pk );
+    return( ret );
+}
+static inline int x509parse_public_keyfile( rsa_context *rsa, const char *path ) {
+    int ret;
+    pk_context pk;
+    pk_init( &pk );
+    ret = pk_parse_public_keyfile( &pk, path );
+    if( ret == 0 && ! pk_can_do( &pk, POLARSSL_PK_RSA ) )
+        ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
+    if( ret == 0 )
+        rsa_copy( rsa, pk_rsa( pk ) );
+    else
+        rsa_free( rsa );
+    pk_free( &pk );
+    return( ret );
+}
+#endif /* POLARSSL_FS_IO */
+
+static inline int x509parse_key( rsa_context *rsa, const unsigned char *key,
+                          size_t keylen,
+                          const unsigned char *pwd, size_t pwdlen ) {
+    int ret;
+    pk_context pk;
+    pk_init( &pk );
+    ret = pk_parse_key( &pk, key, keylen, pwd, pwdlen );
+    if( ret == 0 && ! pk_can_do( &pk, POLARSSL_PK_RSA ) )
+        ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
+    if( ret == 0 )
+        rsa_copy( rsa, pk_rsa( pk ) );
+    else
+        rsa_free( rsa );
+    pk_free( &pk );
+    return( ret );
+}
+
+static inline int x509parse_public_key( rsa_context *rsa,
+                                 const unsigned char *key, size_t keylen )
+{
+    int ret;
+    pk_context pk;
+    pk_init( &pk );
+    ret = pk_parse_public_key( &pk, key, keylen );
+    if( ret == 0 && ! pk_can_do( &pk, POLARSSL_PK_RSA ) )
+        ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
+    if( ret == 0 )
+        rsa_copy( rsa, pk_rsa( pk ) );
+    else
+        rsa_free( rsa );
+    pk_free( &pk );
+    return( ret );
+}
+#endif /* POLARSSL_PK_PARSE_C && POLARSSL_RSA_C */
+
+#if defined(POLARSSL_PK_WRITE_C) && defined(POLARSSL_RSA_C)
+#include "pk.h"
+static inline int x509_write_pubkey_der( unsigned char *buf, size_t len, rsa_context *rsa ) {
+    int ret;
+    pk_context ctx;
+    if( ( ret = pk_init_ctx( &ctx, pk_info_from_type( POLARSSL_PK_RSA ) ) ) != 0 ) return( ret );
+    if( ( ret = rsa_copy( pk_rsa( ctx ), rsa ) ) != 0 ) return( ret );
+    ret = pk_write_pubkey_der( &ctx, buf, len );
+    pk_free( &ctx );
+    return( ret );
+}
+static inline int x509_write_key_der( unsigned char *buf, size_t len, rsa_context *rsa ) {
+    int ret;
+    pk_context ctx;
+    if( ( ret = pk_init_ctx( &ctx, pk_info_from_type( POLARSSL_PK_RSA ) ) ) != 0 ) return( ret );
+    if( ( ret = rsa_copy( pk_rsa( ctx ), rsa ) ) != 0 ) return( ret );
+    ret = pk_write_key_der( &ctx, buf, len );
+    pk_free( &ctx );
+    return( ret );
+}
+#endif /* POLARSSL_PK_WRITE_C && POLARSSL_RSA_C */
+#endif /* compat-1.2.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/config.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,2380 @@
+/**
+ * \file config.h
+ *
+ * \brief Configuration options (set of defines)
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * This set of compile-time options may be used to enable
+ * or disable features selectively, and reduce the global
+ * memory footprint.
+ */
+#ifndef POLARSSL_CONFIG_H
+#define POLARSSL_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 POLARSSL_HAVE_INT8
+ *
+ * The system uses 8-bit wide native integers.
+ *
+ * Uncomment if native integers are 8-bit wide.
+ */
+//#define POLARSSL_HAVE_INT8
+
+
+/**
+ * \def POLARSSL_MBED
+ *
+ * Code generation for use with MBED. 
+ *
+ * Uncomment if MBED code should be included. .
+ */
+#define POLARSSL_MBED 1
+
+/**
+ * \def POLARSSL_HAVE_INT16
+ *
+ * The system uses 16-bit wide native integers.
+ *
+ * Uncomment if native integers are 16-bit wide.
+ */
+//#define POLARSSL_HAVE_INT16
+
+/**
+ * \def POLARSSL_HAVE_LONGLONG
+ *
+ * The compiler supports the 'long long' type.
+ * (Only used on 32-bit platforms)
+ */
+#define POLARSSL_HAVE_LONGLONG
+
+/**
+ * \def POLARSSL_HAVE_ASM
+ *
+ * The compiler has support for asm().
+ *
+ * Requires support for asm() in compiler.
+ *
+ * Used in:
+ *      library/timing.c
+ *      library/padlock.c
+ *      include/polarssl/bn_mul.h
+ *
+ * Comment to disable the use of assembly code.
+ */
+// #define POLARSSL_HAVE_ASM
+
+/**
+ * \def POLARSSL_HAVE_SSE2
+ *
+ * CPU supports SSE2 instruction set.
+ *
+ * Uncomment if the CPU supports SSE2 (IA-32 specific).
+ */
+//#define POLARSSL_HAVE_SSE2
+
+/**
+ * \def POLARSSL_HAVE_TIME
+ *
+ * System has time.h and time() / localtime()  / gettimeofday().
+ *
+ * Comment if your system does not support time functions
+ */
+//#define POLARSSL_HAVE_TIME
+
+/**
+ * \def POLARSSL_HAVE_IPV6
+ *
+ * System supports the basic socket interface for IPv6 (RFC 3493),
+ * specifically getaddrinfo(), freeaddrinfo() and struct sockaddr_storage.
+ *
+ * Note: on Windows/MingW, XP or higher is required.
+ *
+ * Comment if your system does not support the IPv6 socket interface
+ */
+//#define POLARSSL_HAVE_IPV6
+
+/**
+ * \def POLARSSL_PLATFORM_MEMORY
+ *
+ * Enable the memory allocation layer.
+ *
+ * By default PolarSSL uses the system-provided malloc() and free().
+ * This allows different allocators (self-implemented or provided) to be
+ * provided to the platform abstraction layer.
+ *
+ * Enabling POLARSSL_PLATFORM_MEMORY will provide "platform_set_malloc_free()"
+ * to allow you to set an alternative malloc() and free() function pointer.
+ *
+ * Requires: POLARSSL_PLATFORM_C
+ *
+ * Enable this layer to allow use of alternative memory allocators.
+ */
+//#define POLARSSL_PLATFORM_MEMORY
+
+/**
+ * \def POLARSSL_PLATFORM_XXX_ALT
+ *
+ * Uncomment a macro to let PolarSSL support the function in the platform
+ * abstraction layer.
+ *
+ * Example: In case you uncomment POLARSSL_PLATFORM_PRINTF_ALT, PolarSSL will
+ * provide a function "platform_set_printf()" that allows you to set an
+ * alternative printf function pointer.
+ *
+ * All these define require POLARSSL_PLATFORM_C to be defined!
+ *
+ * Uncomment a macro to enable alternate implementation of specific base
+ * platform function
+ */
+//#define POLARSSL_PLATFORM_PRINTF_ALT
+//#define POLARSSL_PLATFORM_FPRINTF_ALT
+/* \} name SECTION: System support */
+
+/**
+ * \name SECTION: PolarSSL feature support
+ *
+ * This section sets support for features that are or are not needed
+ * within the modules that are enabled.
+ * \{
+ */
+
+/**
+ * \def POLARSSL_TIMING_ALT
+ *
+ * Uncomment to provide your own alternate implementation for hardclock(),
+ * get_timer(), set_alarm() and m_sleep().
+ *
+ * Only works if you have POLARSSL_TIMING_C enabled.
+ *
+ * You will need to provide a header "timing_alt.h" and an implementation at
+ * compile time.
+ */
+//#define POLARSSL_TIMING_ALT
+
+/**
+ * \def POLARSSL_XXX_ALT
+ *
+ * Uncomment a macro to let PolarSSL use your alternate core implementation of
+ * a symmetric or hash algorithm (e.g. platform specific assembly optimized
+ * implementations). Keep in mind that the function prototypes should remain
+ * the same.
+ *
+ * Example: In case you uncomment POLARSSL_AES_ALT, PolarSSL will no longer
+ * provide the "struct 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 for core algorithm
+ * functions
+ */
+//#define POLARSSL_AES_ALT
+//#define POLARSSL_ARC4_ALT
+//#define POLARSSL_BLOWFISH_ALT
+//#define POLARSSL_CAMELLIA_ALT
+//#define POLARSSL_DES_ALT
+//#define POLARSSL_XTEA_ALT
+//#define POLARSSL_MD2_ALT
+//#define POLARSSL_MD4_ALT
+//#define POLARSSL_MD5_ALT
+//#define POLARSSL_RIPEMD160_ALT
+//#define POLARSSL_SHA1_ALT
+//#define POLARSSL_SHA256_ALT
+//#define POLARSSL_SHA512_ALT
+
+/**
+ * \def POLARSSL_AES_ROM_TABLES
+ *
+ * Store the AES tables in ROM.
+ *
+ * Uncomment this macro to store the AES tables in ROM.
+ *
+ */
+//#define POLARSSL_AES_ROM_TABLES
+
+/**
+ * \def POLARSSL_CIPHER_MODE_CBC
+ *
+ * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers.
+ */
+//#define POLARSSL_CIPHER_MODE_CBC
+
+/**
+ * \def POLARSSL_CIPHER_MODE_CFB
+ *
+ * Enable Cipher Feedback mode (CFB) for symmetric ciphers.
+ */
+//#define POLARSSL_CIPHER_MODE_CFB
+
+/**
+ * \def POLARSSL_CIPHER_MODE_CTR
+ *
+ * Enable Counter Block Cipher mode (CTR) for symmetric ciphers.
+ */
+//#define POLARSSL_CIPHER_MODE_CTR
+
+/**
+ * \def POLARSSL_CIPHER_NULL_CIPHER
+ *
+ * Enable NULL cipher.
+ * Warning: Only do so when you know what you are doing. This allows for
+ * encryption or channels without any security!
+ *
+ * Requires POLARSSL_ENABLE_WEAK_CIPHERSUITES as well to enable
+ * the following ciphersuites:
+ *      TLS_ECDH_ECDSA_WITH_NULL_SHA
+ *      TLS_ECDH_RSA_WITH_NULL_SHA
+ *      TLS_ECDHE_ECDSA_WITH_NULL_SHA
+ *      TLS_ECDHE_RSA_WITH_NULL_SHA
+ *      TLS_ECDHE_PSK_WITH_NULL_SHA384
+ *      TLS_ECDHE_PSK_WITH_NULL_SHA256
+ *      TLS_ECDHE_PSK_WITH_NULL_SHA
+ *      TLS_DHE_PSK_WITH_NULL_SHA384
+ *      TLS_DHE_PSK_WITH_NULL_SHA256
+ *      TLS_DHE_PSK_WITH_NULL_SHA
+ *      TLS_RSA_WITH_NULL_SHA256
+ *      TLS_RSA_WITH_NULL_SHA
+ *      TLS_RSA_WITH_NULL_MD5
+ *      TLS_RSA_PSK_WITH_NULL_SHA384
+ *      TLS_RSA_PSK_WITH_NULL_SHA256
+ *      TLS_RSA_PSK_WITH_NULL_SHA
+ *      TLS_PSK_WITH_NULL_SHA384
+ *      TLS_PSK_WITH_NULL_SHA256
+ *      TLS_PSK_WITH_NULL_SHA
+ *
+ * Uncomment this macro to enable the NULL cipher and ciphersuites
+#define POLARSSL_CIPHER_NULL_CIPHER
+ */
+
+/**
+ * \def POLARSSL_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 POLARSSL_CIPHER_PADDING_PKCS7
+#define POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS
+#define POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN
+#define POLARSSL_CIPHER_PADDING_ZEROS
+
+/**
+ * \def POLARSSL_ENABLE_WEAK_CIPHERSUITES
+ *
+ * Enable weak ciphersuites in SSL / TLS.
+ * Warning: Only do so when you know what you are doing. This allows for
+ * channels with virtually no security at all!
+ *
+ * This enables the following ciphersuites:
+ *      TLS_RSA_WITH_DES_CBC_SHA
+ *      TLS_DHE_RSA_WITH_DES_CBC_SHA
+ *
+ * Uncomment this macro to enable weak ciphersuites
+#define POLARSSL_ENABLE_WEAK_CIPHERSUITES
+ */
+
+/**
+ * \def POLARSSL_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 POLARSSL_ECP_DP_SECP192R1_ENABLED
+#define POLARSSL_ECP_DP_SECP224R1_ENABLED
+#define POLARSSL_ECP_DP_SECP256R1_ENABLED
+#define POLARSSL_ECP_DP_SECP384R1_ENABLED
+#define POLARSSL_ECP_DP_SECP521R1_ENABLED
+#define POLARSSL_ECP_DP_SECP192K1_ENABLED
+#define POLARSSL_ECP_DP_SECP224K1_ENABLED
+#define POLARSSL_ECP_DP_SECP256K1_ENABLED
+#define POLARSSL_ECP_DP_BP256R1_ENABLED
+#define POLARSSL_ECP_DP_BP384R1_ENABLED
+#define POLARSSL_ECP_DP_BP512R1_ENABLED
+//#define POLARSSL_ECP_DP_M221_ENABLED  // Not implemented yet!
+#define POLARSSL_ECP_DP_M255_ENABLED
+//#define POLARSSL_ECP_DP_M383_ENABLED  // Not implemented yet!
+//#define POLARSSL_ECP_DP_M511_ENABLED  // Not implemented yet!
+
+*/
+/**
+ * \def POLARSSL_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 POLARSSL_ECP_NIST_OPTIM
+
+/**
+ * \def POLARSSL_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: POLARSSL_HMAC_DRBG_C
+ *
+ * Comment this macro to disable deterministic ECDSA.
+ */
+//#define POLARSSL_ECDSA_DETERMINISTIC
+
+/**
+ * \def POLARSSL_KEY_EXCHANGE_PSK_ENABLED
+ *
+ * Enable the PSK based ciphersuite modes in SSL / TLS.
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      TLS_PSK_WITH_AES_256_GCM_SHA384
+ *      TLS_PSK_WITH_AES_256_CBC_SHA384
+ *      TLS_PSK_WITH_AES_256_CBC_SHA
+ *      TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ *      TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_PSK_WITH_AES_128_GCM_SHA256
+ *      TLS_PSK_WITH_AES_128_CBC_SHA256
+ *      TLS_PSK_WITH_AES_128_CBC_SHA
+ *      TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_PSK_WITH_3DES_EDE_CBC_SHA
+ *      TLS_PSK_WITH_RC4_128_SHA
+ */
+#define POLARSSL_KEY_EXCHANGE_PSK_ENABLED
+
+/**
+ * \def POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED
+ *
+ * Enable the DHE-PSK based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: POLARSSL_DHM_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
+ *      TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
+ *      TLS_DHE_PSK_WITH_AES_256_CBC_SHA
+ *      TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ *      TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
+ *      TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
+ *      TLS_DHE_PSK_WITH_AES_128_CBC_SHA
+ *      TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA
+ *      TLS_DHE_PSK_WITH_RC4_128_SHA
+ */
+//#define POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED
+
+/**
+ * \def POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED
+ *
+ * Enable the ECDHE-PSK based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: POLARSSL_ECDH_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384
+ *      TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA
+ *      TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
+ *      TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA
+ *      TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA
+ *      TLS_ECDHE_PSK_WITH_RC4_128_SHA
+ */
+//#define POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED
+
+/**
+ * \def POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED
+ *
+ * Enable the RSA-PSK based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: POLARSSL_RSA_C, POLARSSL_PKCS1_V15,
+ *           POLARSSL_X509_CRT_PARSE_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      TLS_RSA_PSK_WITH_AES_256_GCM_SHA384
+ *      TLS_RSA_PSK_WITH_AES_256_CBC_SHA384
+ *      TLS_RSA_PSK_WITH_AES_256_CBC_SHA
+ *      TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ *      TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_RSA_PSK_WITH_AES_128_GCM_SHA256
+ *      TLS_RSA_PSK_WITH_AES_128_CBC_SHA256
+ *      TLS_RSA_PSK_WITH_AES_128_CBC_SHA
+ *      TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA
+ *      TLS_RSA_PSK_WITH_RC4_128_SHA
+ */
+//#define POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED
+
+/**
+ * \def POLARSSL_KEY_EXCHANGE_RSA_ENABLED
+ *
+ * Enable the RSA-only based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: POLARSSL_RSA_C, POLARSSL_PKCS1_V15,
+ *           POLARSSL_X509_CRT_PARSE_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      TLS_RSA_WITH_AES_256_GCM_SHA384
+ *      TLS_RSA_WITH_AES_256_CBC_SHA256
+ *      TLS_RSA_WITH_AES_256_CBC_SHA
+ *      TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
+ *      TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
+ *      TLS_RSA_WITH_AES_128_GCM_SHA256
+ *      TLS_RSA_WITH_AES_128_CBC_SHA256
+ *      TLS_RSA_WITH_AES_128_CBC_SHA
+ *      TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
+ *      TLS_RSA_WITH_3DES_EDE_CBC_SHA
+ *      TLS_RSA_WITH_RC4_128_SHA
+ *      TLS_RSA_WITH_RC4_128_MD5
+ */
+//#define POLARSSL_KEY_EXCHANGE_RSA_ENABLED
+
+/**
+ * \def POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED
+ *
+ * Enable the DHE-RSA based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: POLARSSL_DHM_C, POLARSSL_RSA_C, POLARSSL_PKCS1_V15,
+ *           POLARSSL_X509_CRT_PARSE_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
+ *      TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
+ *      TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+ *      TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
+ *      TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
+ *      TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
+ *      TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+ *      TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+ *      TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
+ *      TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
+ */
+//#define POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED
+
+/**
+ * \def POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED
+ *
+ * Enable the ECDHE-RSA based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: POLARSSL_ECDH_C, POLARSSL_RSA_C, POLARSSL_PKCS1_V15,
+ *           POLARSSL_X509_CRT_PARSE_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
+ *      TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
+ *      TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
+ *      TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
+ *      TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+ *      TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
+ *      TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
+ *      TLS_ECDHE_RSA_WITH_RC4_128_SHA
+ */
+//#define POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED
+
+/**
+ * \def POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+ *
+ * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: POLARSSL_ECDH_C, POLARSSL_ECDSA_C, POLARSSL_X509_CRT_PARSE_C,
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
+ *      TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
+ *      TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
+ *      TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+ *      TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
+ *      TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
+ *      TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
+ *      TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
+ */
+//#define POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+
+/**
+ * \def POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
+ *
+ * Enable the ECDH-ECDSA based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: POLARSSL_ECDH_C, POLARSSL_X509_CRT_PARSE_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      TLS_ECDH_ECDSA_WITH_RC4_128_SHA
+ *      TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
+ *      TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
+ *      TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
+ *      TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
+ *      TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
+ *      TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
+ *      TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
+ *      TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
+ */
+//#define POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
+
+/**
+ * \def POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED
+ *
+ * Enable the ECDH-RSA based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: POLARSSL_ECDH_C, POLARSSL_X509_CRT_PARSE_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      TLS_ECDH_RSA_WITH_RC4_128_SHA
+ *      TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
+ *      TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
+ *      TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
+ *      TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
+ *      TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
+ *      TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
+ *      TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
+ *      TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ */
+//#define POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED
+
+/**
+ * \def POLARSSL_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 POLARSSL_PK_PARSE_EC_EXTENDED
+
+/**
+ * \def POLARSSL_ERROR_STRERROR_BC
+ *
+ * Make available the backward compatible error_strerror() next to the
+ * current polarssl_strerror().
+ *
+ * Disable if you run into name conflicts and want to really remove the
+ * error_strerror()
+ */
+#define POLARSSL_ERROR_STRERROR_BC
+
+/**
+ * \def POLARSSL_ERROR_STRERROR_DUMMY
+ *
+ * Enable a dummy error function to make use of polarssl_strerror() in
+ * third party libraries easier.
+ *
+ * Disable if you run into name conflicts and want to really remove the
+ * polarssl_strerror()
+ */
+#define POLARSSL_ERROR_STRERROR_DUMMY
+
+/**
+ * \def POLARSSL_GENPRIME
+ *
+ * Enable the prime-number generation code.
+ *
+ * Requires: POLARSSL_BIGNUM_C
+ */
+//#define POLARSSL_GENPRIME
+
+/**
+ * \def POLARSSL_FS_IO
+ *
+ * Enable functions that use the filesystem.
+ */
+//#define POLARSSL_FS_IO
+
+/**
+ * \def POLARSSL_NO_DEFAULT_ENTROPY_SOURCES
+ *
+ * Do not add default entropy sources. These are the platform specific,
+ * 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 POLARSSL_NO_DEFAULT_ENTROPY_SOURCES
+
+/**
+ * \def POLARSSL_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 POLARSSL_NO_PLATFORM_ENTROPY
+
+/**
+ * \def POLARSSL_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: POLARSSL_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 POLARSSL_SHA256_C and
+ * POLARSSL_SHA512_C are defined. Otherwise the available hash module is used.
+ */
+//#define POLARSSL_ENTROPY_FORCE_SHA256
+
+/**
+ * \def POLARSSL_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: POLARSSL_MEMORY_BUFFER_ALLOC_C
+ *
+ * Uncomment this macro to let the buffer allocator print out error messages.
+ */
+#define POLARSSL_MEMORY_DEBUG
+
+/**
+ * \def POLARSSL_MEMORY_BACKTRACE
+ *
+ * Include backtrace information with each allocated block.
+ *
+ * Requires: POLARSSL_MEMORY_BUFFER_ALLOC_C
+ *           GLIBC-compatible backtrace() an backtrace_symbols() support
+ *
+ * Uncomment this macro to include backtrace information
+ */
+//#define POLARSSL_MEMORY_BACKTRACE
+
+/**
+ * \def POLARSSL_PKCS1_V15
+ *
+ * Enable support for PKCS#1 v1.5 encoding.
+ *
+ * Requires: POLARSSL_RSA_C
+ *
+ * This enables support for PKCS#1 v1.5 operations.
+ */
+//#define POLARSSL_PKCS1_V15
+
+/**
+ * \def POLARSSL_PKCS1_V21
+ *
+ * Enable support for PKCS#1 v2.1 encoding.
+ *
+ * Requires: POLARSSL_MD_C, POLARSSL_RSA_C
+ *
+ * This enables support for RSAES-OAEP and RSASSA-PSS operations.
+ */
+//#define POLARSSL_PKCS1_V21
+
+/**
+ * \def POLARSSL_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 POLARSSL_RSA_NO_CRT
+
+/**
+ * \def POLARSSL_SELF_TEST
+ *
+ * Enable the checkup functions (*_self_test).
+ */
+#define POLARSSL_SELF_TEST
+
+/**
+ * \def POLARSSL_SSL_ALL_ALERT_MESSAGES
+ *
+ * Enable sending of alert messages in case of encountered errors as per RFC.
+ * If you choose not to send the alert messages, PolarSSL can still communicate
+ * with other servers, only debugging of failures is harder.
+ *
+ * The advantage of not sending alert messages, is that no information is given
+ * about reasons for failures thus preventing adversaries of gaining intel.
+ *
+ * Enable sending of all alert messages
+ */
+#define POLARSSL_SSL_ALERT_MESSAGES
+
+/**
+ * \def POLARSSL_SSL_DEBUG_ALL
+ *
+ * Enable the debug messages in SSL module for all issues.
+ * Debug messages have been disabled in some places to prevent timing
+ * attacks due to (unbalanced) debugging function calls.
+ *
+ * If you need all error reporting you should enable this during debugging,
+ * but remove this for production servers that should log as well.
+ *
+ * Uncomment this macro to report all debug messages on errors introducing
+ * a timing side-channel.
+ *
+ */
+#define POLARSSL_SSL_DEBUG_ALL
+
+/**
+ * \def POLARSSL_SSL_HW_RECORD_ACCEL
+ *
+ * Enable hooking functions in SSL module for hardware acceleration of
+ * individual records.
+ *
+ * Uncomment this macro to enable hooking functions.
+ */
+//#define POLARSSL_SSL_HW_RECORD_ACCEL
+
+/**
+ * \def POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO
+ *
+ * Enable support for receiving and parsing SSLv2 Client Hello messages for the
+ * SSL Server module (POLARSSL_SSL_SRV_C).
+ *
+ * Comment this macro to disable support for SSLv2 Client Hello messages.
+ */
+//#define POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO
+
+/**
+ * \def POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE
+ *
+ * Pick the ciphersuite according to the client's preferences rather than ours
+ * in the SSL Server module (POLARSSL_SSL_SRV_C).
+ *
+ * Uncomment this macro to respect client's ciphersuite order
+ */
+//#define POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE
+
+/**
+ * \def POLARSSL_SSL_MAX_FRAGMENT_LENGTH
+ *
+ * Enable support for RFC 6066 max_fragment_length extension in SSL.
+ *
+ * Comment this macro to disable support for the max_fragment_length extension
+ */
+#define POLARSSL_SSL_MAX_FRAGMENT_LENGTH
+
+/**
+ * \def POLARSSL_SSL_PROTO_SSL3
+ *
+ * Enable support for SSL 3.0.
+ *
+ * Requires: POLARSSL_MD5_C
+ *           POLARSSL_SHA1_C
+ *
+ * Comment this macro to disable support for SSL 3.0
+ */
+//#define POLARSSL_SSL_PROTO_SSL3
+
+/**
+ * \def POLARSSL_SSL_PROTO_TLS1
+ *
+ * Enable support for TLS 1.0.
+ *
+ * Requires: POLARSSL_MD5_C
+ *           POLARSSL_SHA1_C
+ *
+ * Comment this macro to disable support for TLS 1.0
+ */
+//#define POLARSSL_SSL_PROTO_TLS1
+
+/**
+ * \def POLARSSL_SSL_PROTO_TLS1_1
+ *
+ * Enable support for TLS 1.1 (and DTLS 1.0 if DTLS is enabled).
+ *
+ * Requires: POLARSSL_MD5_C
+ *           POLARSSL_SHA1_C
+ *
+ * Comment this macro to disable support for TLS 1.1 / DTLS 1.0
+ */
+//#define POLARSSL_SSL_PROTO_TLS1_1
+
+/**
+ * \def POLARSSL_SSL_PROTO_TLS1_2
+ *
+ * Enable support for TLS 1.2 (and DTLS 1.2 if DTLS is enabled).
+ *
+ * Requires: POLARSSL_SHA1_C or POLARSSL_SHA256_C or POLARSSL_SHA512_C
+ *           (Depends on ciphersuites)
+ *
+ * Comment this macro to disable support for TLS 1.2 / DTLS 1.2
+ */
+#define POLARSSL_SSL_PROTO_TLS1_2
+
+/**
+ * \def POLARSSL_SSL_PROTO_DTLS
+ *
+ * Enable support for DTLS (all available versions).
+ *
+ * Enable this and POLARSSL_SSL_PROTO_TLS11 to enable DTLS 1.0,
+ * and/or this and POLARSSL_SSL_PROTO_TLS12 to enable DTLS 1.2.
+ *
+ * Requires: POLARSSL_SSL_PROTO_TLS11
+ *        or POLARSSL_SSL_PROTO_TLS12
+ *
+ * Comment this macro to disable support for DTLS
+ */
+#define POLARSSL_SSL_PROTO_DTLS
+
+/**
+ * \def POLARSSL_SSL_SESSION_TICKETS
+ *
+ * Enable support for RFC 5077 session tickets in SSL.
+ *
+ * Requires: POLARSSL_AES_C
+ *           POLARSSL_SHA256_C
+ *           POLARSSL_CIPHER_MODE_CBC
+ *
+ * Comment this macro to disable support for SSL session tickets
+ */
+//#define POLARSSL_SSL_SESSION_TICKETS
+
+/**
+ * \def POLARSSL_SSL_SERVER_NAME_INDICATION
+ *
+ * Enable support for RFC 6066 server name indication (SNI) in SSL.
+ *
+ * Comment this macro to disable support for server name indication in SSL
+ */
+//#define POLARSSL_SSL_SERVER_NAME_INDICATION
+
+/**
+ * \def POLARSSL_SSL_TRUNCATED_HMAC
+ *
+ * Enable support for RFC 6066 truncated HMAC in SSL.
+ *
+ * Comment this macro to disable support for truncated HMAC in SSL
+ */
+#define POLARSSL_SSL_TRUNCATED_HMAC
+
+/**
+ * \def POLARSSL_SSL_SET_CURVES
+ *
+ * Enable ssl_set_curves().
+ *
+ * This is disabled by default since it breaks binary compatibility with the
+ * 1.3.x line. If you choose to enable it, you will need to rebuild your
+ * application against the new header files, relinking will not be enough.
+ * It will be enabled by default, or no longer an option, in the 1.4 branch.
+ *
+ * Uncomment to make ssl_set_curves() available.
+ */
+//#define POLARSSL_SSL_SET_CURVES
+
+/**
+ * \def POLARSSL_THREADING_ALT
+ *
+ * Provide your own alternate threading implementation.
+ *
+ * Requires: POLARSSL_THREADING_C
+ *
+ * Uncomment this to allow your own alternate threading implementation.
+ */
+//#define POLARSSL_THREADING_ALT
+
+/**
+ * \def POLARSSL_THREADING_PTHREAD
+ *
+ * Enable the pthread wrapper layer for the threading layer.
+ *
+ * Requires: POLARSSL_THREADING_C
+ *
+ * Uncomment this to enable pthread mutexes.
+ */
+//#define POLARSSL_THREADING_PTHREAD
+
+/**
+ * \def POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3
+ *
+ * If set, the X509 parser will not break-off when parsing an X509 certificate
+ * and encountering an extension in a v1 or v2 certificate.
+ *
+ * Uncomment to prevent an error.
+ */
+//#define POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3
+
+/**
+ * \def POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
+ *
+ * If set, the X509 parser will not break-off when parsing an X509 certificate
+ * and encountering an unknown critical extension.
+ *
+ * Uncomment to prevent an error.
+ */
+//#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
+
+/**
+ * \def POLARSSL_ZLIB_SUPPORT
+ *
+ * If set, the SSL/TLS module uses ZLIB to support compression and
+ * decompression of packet data.
+ *
+ * \warning TLS-level compression MAY REDUCE SECURITY! See for example the
+ * CRIME attack. Before enabling this option, you should examine with care if
+ * CRIME or similar exploits may be a applicable to your use case.
+ *
+ * Used in: library/ssl_tls.c
+ *          library/ssl_cli.c
+ *          library/ssl_srv.c
+ *
+ * This feature requires zlib library and headers to be present.
+ *
+ * Uncomment to enable use of ZLIB
+ */
+//#define POLARSSL_ZLIB_SUPPORT
+/* \} name SECTION: PolarSSL feature support */
+
+/**
+ * \name SECTION: PolarSSL modules
+ *
+ * This section enables or disables entire modules in PolarSSL
+ * \{
+ */
+
+/**
+ * \def POLARSSL_AESNI_C
+ *
+ * Enable AES-NI support on x86-64.
+ *
+ * Module:  library/aesni.c
+ * Caller:  library/aes.c
+ *
+ * Requires: POLARSSL_HAVE_ASM
+ *
+ * This modules adds support for the AES-NI instructions on x86-64
+ */
+//#define POLARSSL_AESNI_C
+
+/**
+ * \def POLARSSL_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):
+ *      TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
+ *      TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
+ *      TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
+ *      TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
+ *      TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
+ *      TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
+ *      TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
+ *      TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
+ *      TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
+ *      TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
+ *      TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
+ *      TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
+ *      TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
+ *      TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
+ *      TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
+ *      TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
+ *      TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
+ *      TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
+ *      TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
+ *      TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
+ *      TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+ *      TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+ *      TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
+ *      TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
+ *      TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
+ *      TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+ *      TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+ *      TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
+ *      TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
+ *      TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+ *      TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
+ *      TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384
+ *      TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
+ *      TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA
+ *      TLS_DHE_PSK_WITH_AES_256_CBC_SHA
+ *      TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
+ *      TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
+ *      TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
+ *      TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA
+ *      TLS_DHE_PSK_WITH_AES_128_CBC_SHA
+ *      TLS_RSA_WITH_AES_256_GCM_SHA384
+ *      TLS_RSA_WITH_AES_256_CBC_SHA256
+ *      TLS_RSA_WITH_AES_256_CBC_SHA
+ *      TLS_RSA_WITH_AES_128_GCM_SHA256
+ *      TLS_RSA_WITH_AES_128_CBC_SHA256
+ *      TLS_RSA_WITH_AES_128_CBC_SHA
+ *      TLS_RSA_PSK_WITH_AES_256_GCM_SHA384
+ *      TLS_RSA_PSK_WITH_AES_256_CBC_SHA384
+ *      TLS_RSA_PSK_WITH_AES_256_CBC_SHA
+ *      TLS_RSA_PSK_WITH_AES_128_GCM_SHA256
+ *      TLS_RSA_PSK_WITH_AES_128_CBC_SHA256
+ *      TLS_RSA_PSK_WITH_AES_128_CBC_SHA
+ *      TLS_PSK_WITH_AES_256_GCM_SHA384
+ *      TLS_PSK_WITH_AES_256_CBC_SHA384
+ *      TLS_PSK_WITH_AES_256_CBC_SHA
+ *      TLS_PSK_WITH_AES_128_GCM_SHA256
+ *      TLS_PSK_WITH_AES_128_CBC_SHA256
+ *      TLS_PSK_WITH_AES_128_CBC_SHA
+ *
+ * PEM_PARSE uses AES for decrypting encrypted keys.
+ */
+#define POLARSSL_AES_C
+
+/**
+ * \def POLARSSL_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):
+ *      TLS_ECDH_ECDSA_WITH_RC4_128_SHA
+ *      TLS_ECDH_RSA_WITH_RC4_128_SHA
+ *      TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
+ *      TLS_ECDHE_RSA_WITH_RC4_128_SHA
+ *      TLS_ECDHE_PSK_WITH_RC4_128_SHA
+ *      TLS_DHE_PSK_WITH_RC4_128_SHA
+ *      TLS_RSA_WITH_RC4_128_SHA
+ *      TLS_RSA_WITH_RC4_128_MD5
+ *      TLS_RSA_PSK_WITH_RC4_128_SHA
+ *      TLS_PSK_WITH_RC4_128_SHA
+ */
+//#define POLARSSL_ARC4_C
+
+/**
+ * \def POLARSSL_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 POLARSSL_ASN1_PARSE_C
+
+/**
+ * \def POLARSSL_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 POLARSSL_ASN1_WRITE_C
+
+/**
+ * \def POLARSSL_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 POLARSSL_BASE64_C
+
+/**
+ * \def POLARSSL_BIGNUM_C
+ *
+ * Enable the multi-precision integer library.
+ *
+ * Module:  library/bignum.c
+ * Caller:  library/dhm.c
+ *          library/ecp.c
+ *          library/rsa.c
+ *          library/ssl_tls.c
+ *
+ * This module is required for RSA and DHM support.
+ */
+//#define POLARSSL_BIGNUM_C
+
+/**
+ * \def POLARSSL_BLOWFISH_C
+ *
+ * Enable the Blowfish block cipher.
+ *
+ * Module:  library/blowfish.c
+ */
+//#define POLARSSL_BLOWFISH_C
+
+/**
+ * \def POLARSSL_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):
+ *      TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
+ *      TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
+ *      TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
+ *      TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ *      TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
+ *      TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
+ *      TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
+ *      TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ *      TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ *      TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ */
+//#define POLARSSL_CAMELLIA_C
+
+/**
+ * \def POLARSSL_CERTS_C
+ *
+ * Enable the test certificates.
+ *
+ * Module:  library/certs.c
+ * Caller:
+ *
+ * Requires: POLARSSL_PEM_PARSE_C
+ *
+ * This module is used for testing (ssl_client/server).
+ */
+//#define POLARSSL_CERTS_C
+
+/**
+ * \def POLARSSL_CIPHER_C
+ *
+ * Enable the generic cipher layer.
+ *
+ * Module:  library/cipher.c
+ * Caller:  library/ssl_tls.c
+ *
+ * Uncomment to enable generic cipher wrappers.
+ */
+#define POLARSSL_CIPHER_C
+
+/**
+ * \def POLARSSL_CTR_DRBG_C
+ *
+ * Enable the CTR_DRBG AES-256-based random generator.
+ *
+ * Module:  library/ctr_drbg.c
+ * Caller:
+ *
+ * Requires: POLARSSL_AES_C
+ *
+ * This module provides the CTR_DRBG AES-256 random number generator.
+ */
+//#define POLARSSL_CTR_DRBG_C
+
+/**
+ * \def POLARSSL_DEBUG_C
+ *
+ * Enable the debug functions.
+ *
+ * Module:  library/debug.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *          library/ssl_tls.c
+ *
+ * This module provides debugging functions.
+ */
+#define POLARSSL_DEBUG_C
+
+/**
+ * \def POLARSSL_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):
+ *      TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
+ *      TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
+ *      TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
+ *      TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
+ *      TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
+ *      TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA
+ *      TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA
+ *      TLS_RSA_WITH_3DES_EDE_CBC_SHA
+ *      TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA
+ *      TLS_PSK_WITH_3DES_EDE_CBC_SHA
+ *
+ * PEM_PARSE uses DES/3DES for decrypting encrypted keys.
+ */
+//#define POLARSSL_DES_C
+
+/**
+ * \def POLARSSL_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
+ */
+//#define POLARSSL_DHM_C
+
+/**
+ * \def POLARSSL_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: POLARSSL_ECP_C
+ */
+//#define POLARSSL_ECDH_C
+
+/**
+ * \def POLARSSL_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: POLARSSL_ECP_C, POLARSSL_ASN1_WRITE_C, POLARSSL_ASN1_PARSE_C
+ */
+//#define POLARSSL_ECDSA_C
+
+/**
+ * \def POLARSSL_ECP_C
+ *
+ * Enable the elliptic curve over GF(p) library.
+ *
+ * Module:  library/ecp.c
+ * Caller:  library/ecdh.c
+ *          library/ecdsa.c
+ *
+ * Requires: POLARSSL_BIGNUM_C and at least one POLARSSL_ECP_DP_XXX_ENABLED
+ */
+//#define POLARSSL_ECP_C
+
+/**
+ * \def POLARSSL_ENTROPY_C
+ *
+ * Enable the platform-specific entropy code.
+ *
+ * Module:  library/entropy.c
+ * Caller:
+ *
+ * Requires: POLARSSL_SHA512_C or POLARSSL_SHA256_C
+ *
+ * This module provides a generic entropy pool
+ */
+//#define POLARSSL_ENTROPY_C
+
+/**
+ * \def POLARSSL_ERROR_C
+ *
+ * Enable error code to error string conversion.
+ *
+ * Module:  library/error.c
+ * Caller:
+ *
+ * This module enables err_strerror().
+ */
+//#define POLARSSL_ERROR_C
+
+/**
+ * \def POLARSSL_GCM_C
+ *
+ * Enable the Galois/Counter Mode (GCM) for AES.
+ *
+ * Module:  library/gcm.c
+ *
+ * Requires: POLARSSL_AES_C or POLARSSL_CAMELLIA_C
+ *
+ * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other
+ * requisites are enabled as well.
+ */
+#define POLARSSL_GCM_C
+
+/**
+ * \def POLARSSL_HAVEGE_C
+ *
+ * Enable the HAVEGE random generator.
+ *
+ * Warning: the HAVEGE random generator is not suitable for virtualized
+ *          environments
+ *
+ * Warning: the HAVEGE random generator is dependent on timing and specific
+ *          processor traits. It is therefore not advised to use HAVEGE as
+ *          your applications primary random generator or primary entropy pool
+ *          input. As a secondary input to your entropy pool, it IS able add
+ *          the (limited) extra entropy it provides.
+ *
+ * Module:  library/havege.c
+ * Caller:
+ *
+ * Requires: POLARSSL_TIMING_C
+ *
+ * Uncomment to enable the HAVEGE random generator.
+ */
+//#define POLARSSL_HAVEGE_C
+
+/**
+ * \def POLARSSL_HMAC_DRBG_C
+ *
+ * Enable the HMAC_DRBG random generator.
+ *
+ * Module:  library/hmac_drbg.c
+ * Caller:
+ *
+ * Requires: POLARSSL_MD_C
+ *
+ * Uncomment to enable the HMAC_DRBG random number geerator.
+ */
+//#define POLARSSL_HMAC_DRBG_C
+
+/**
+ * \def POLARSSL_MD_C
+ *
+ * Enable the generic message digest layer.
+ *
+ * Module:  library/md.c
+ * Caller:
+ *
+ * Uncomment to enable generic message digest wrappers.
+ */
+#define POLARSSL_MD_C
+
+/**
+ * \def POLARSSL_MD2_C
+ *
+ * Enable the MD2 hash algorithm.
+ *
+ * Module:  library/md2.c
+ * Caller:
+ *
+ * Uncomment to enable support for (rare) MD2-signed X.509 certs.
+ */
+//#define POLARSSL_MD2_C
+
+/**
+ * \def POLARSSL_MD4_C
+ *
+ * Enable the MD4 hash algorithm.
+ *
+ * Module:  library/md4.c
+ * Caller:
+ *
+ * Uncomment to enable support for (rare) MD4-signed X.509 certs.
+ */
+//#define POLARSSL_MD4_C
+
+/**
+ * \def POLARSSL_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 and X.509.
+ * PEM_PARSE uses MD5 for decrypting encrypted keys.
+ */
+//#define POLARSSL_MD5_C
+
+/**
+ * \def POLARSSL_MEMORY_C
+ * Deprecated since 1.3.5. Please use POLARSSL_PLATFORM_MEMORY instead.
+ */
+//#define POLARSSL_MEMORY_C
+
+/**
+ * \def POLARSSL_MEMORY_BUFFER_ALLOC_C
+ *
+ * Enable the buffer allocator implementation that makes use of a (stack)
+ * based buffer to 'allocate' dynamic memory. (replaces malloc() and free()
+ * calls)
+ *
+ * Module:  library/memory_buffer_alloc.c
+ *
+ * Requires: POLARSSL_PLATFORM_C
+ *           POLARSSL_PLATFORM_MEMORY (to use it within PolarSSL)
+ *
+ * Enable this module to enable the buffer memory allocator.
+ */
+//#define POLARSSL_MEMORY_BUFFER_ALLOC_C
+
+/**
+ * \def POLARSSL_NET_C
+ *
+ * Enable the TCP/IP networking routines.
+ *
+ * Module:  library/net.c
+ *
+ * This module provides TCP/IP networking routines.
+ */
+//#define POLARSSL_NET_C
+
+/**
+ * \def POLARSSL_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 POLARSSL_OID_C
+
+/**
+ * \def POLARSSL_PADLOCK_C
+ *
+ * Enable VIA Padlock support on x86.
+ *
+ * Module:  library/padlock.c
+ * Caller:  library/aes.c
+ *
+ * Requires: POLARSSL_HAVE_ASM
+ *
+ * This modules adds support for the VIA PadLock on x86.
+ */
+//#define POLARSSL_PADLOCK_C
+
+/**
+ * \def POLARSSL_PBKDF2_C
+ *
+ * Enable PKCS#5 PBKDF2 key derivation function.
+ * DEPRECATED: Use POLARSSL_PKCS5_C instead
+ *
+ * Module:  library/pbkdf2.c
+ *
+ * Requires: POLARSSL_PKCS5_C
+ *
+ * This module adds support for the PKCS#5 PBKDF2 key derivation function.
+ */
+//#define POLARSSL_PBKDF2_C
+
+/**
+ * \def POLARSSL_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: POLARSSL_BASE64_C
+ *
+ * This modules adds support for decoding / parsing PEM files.
+ */
+//#define POLARSSL_PEM_PARSE_C
+
+/**
+ * \def POLARSSL_PEM_WRITE_C
+ *
+ * Enable PEM encoding / writing.
+ *
+ * Module:  library/pem.c
+ * Caller:  library/pkwrite.c
+ *          library/x509write_crt.c
+ *          library/x509write_csr.c
+ *
+ * Requires: POLARSSL_BASE64_C
+ *
+ * This modules adds support for encoding / writing PEM files.
+ */
+//#define POLARSSL_PEM_WRITE_C
+
+/**
+ * \def POLARSSL_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: POLARSSL_RSA_C or POLARSSL_ECP_C
+ *
+ * Uncomment to enable generic public key wrappers.
+ */
+//#define POLARSSL_PK_C
+
+/**
+ * \def POLARSSL_PK_PARSE_C
+ *
+ * Enable the generic public (asymetric) key parser.
+ *
+ * Module:  library/pkparse.c
+ * Caller:  library/x509_crt.c
+ *          library/x509_csr.c
+ *
+ * Requires: POLARSSL_PK_C
+ *
+ * Uncomment to enable generic public key parse functions.
+ */
+//#define POLARSSL_PK_PARSE_C
+
+/**
+ * \def POLARSSL_PK_WRITE_C
+ *
+ * Enable the generic public (asymetric) key writer.
+ *
+ * Module:  library/pkwrite.c
+ * Caller:  library/x509write.c
+ *
+ * Requires: POLARSSL_PK_C
+ *
+ * Uncomment to enable generic public key write functions.
+ */
+//#define POLARSSL_PK_WRITE_C
+
+/**
+ * \def POLARSSL_PKCS5_C
+ *
+ * Enable PKCS#5 functions.
+ *
+ * Module:  library/pkcs5.c
+ *
+ * Requires: POLARSSL_MD_C
+ *
+ * This module adds support for the PKCS#5 functions.
+ */
+//#define POLARSSL_PKCS5_C
+
+/**
+ * \def POLARSSL_PKCS11_C
+ *
+ * Enable wrapper for PKCS#11 smartcard support.
+ *
+ * Module:  library/pkcs11.c
+ * Caller:  library/pk.c
+ *
+ * Requires: POLARSSL_PK_C
+ *
+ * This module enables SSL/TLS PKCS #11 smartcard support.
+ * Requires the presence of the PKCS#11 helper library (libpkcs11-helper)
+ */
+//#define POLARSSL_PKCS11_C
+
+/**
+ * \def POLARSSL_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: POLARSSL_ASN1_PARSE_C, POLARSSL_CIPHER_C, POLARSSL_MD_C
+ * Can use:  POLARSSL_ARC4_C
+ *
+ * This module enables PKCS#12 functions.
+ */
+//#define POLARSSL_PKCS12_C
+
+/**
+ * \def POLARSSL_PLATFORM_C
+ *
+ * Enable the platform abstraction layer that allows you to re-assign
+ * functions like malloc(), free(), printf(), fprintf()
+ *
+ * Module:  library/platform.c
+ * Caller:  Most other .c files
+ *
+ * This module enables abstraction of common (libc) functions.
+ */
+#define POLARSSL_PLATFORM_C
+
+/**
+ * \def POLARSSL_RIPEMD160_C
+ *
+ * Enable the RIPEMD-160 hash algorithm.
+ *
+ * Module:  library/ripemd160.c
+ * Caller:  library/md.c
+ *
+ */
+//#define POLARSSL_RIPEMD160_C
+
+/**
+ * \def POLARSSL_RSA_C
+ *
+ * Enable the RSA public-key cryptosystem.
+ *
+ * Module:  library/rsa.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: POLARSSL_BIGNUM_C, POLARSSL_OID_C
+ */
+//#define POLARSSL_RSA_C
+
+/**
+ * \def POLARSSL_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 and SHA1-signed certificates.
+ */
+//#define POLARSSL_SHA1_C
+
+/**
+ * \def POLARSSL_SHA256_C
+ *
+ * Enable the SHA-224 and SHA-256 cryptographic hash algorithms.
+ * (Used to be POLARSSL_SHA2_C)
+ *
+ * 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 POLARSSL_SHA256_C
+
+/**
+ * \def POLARSSL_SHA512_C
+ *
+ * Enable the SHA-384 and SHA-512 cryptographic hash algorithms.
+ * (Used to be POLARSSL_SHA4_C)
+ *
+ * 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 POLARSSL_SHA512_C
+
+/**
+ * \def POLARSSL_SSL_CACHE_C
+ *
+ * Enable simple SSL cache implementation.
+ *
+ * Module:  library/ssl_cache.c
+ * Caller:
+ *
+ * Requires: POLARSSL_SSL_CACHE_C
+ */
+#define POLARSSL_SSL_CACHE_C
+
+/**
+ * \def POLARSSL_SSL_CLI_C
+ *
+ * Enable the SSL/TLS client code.
+ *
+ * Module:  library/ssl_cli.c
+ * Caller:
+ *
+ * Requires: POLARSSL_SSL_TLS_C
+ *
+ * This module is required for SSL/TLS client support.
+ */
+#define POLARSSL_SSL_CLI_C
+
+/**
+ * \def POLARSSL_SSL_SRV_C
+ *
+ * Enable the SSL/TLS server code.
+ *
+ * Module:  library/ssl_srv.c
+ * Caller:
+ *
+ * Requires: POLARSSL_SSL_TLS_C
+ *
+ * This module is required for SSL/TLS server support.
+ */
+//#define POLARSSL_SSL_SRV_C
+
+/**
+ * \def POLARSSL_SSL_TLS_C
+ *
+ * Enable the generic SSL/TLS code.
+ *
+ * Module:  library/ssl_tls.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *
+ * Requires: POLARSSL_CIPHER_C, POLARSSL_MD_C
+ *           and at least one of the POLARSSL_SSL_PROTO_* defines
+ *
+ * This module is required for SSL/TLS.
+ */
+#define POLARSSL_SSL_TLS_C
+
+/**
+ * \def POLARSSL_THREADING_C
+ *
+ * Enable the threading abstraction layer.
+ * By default PolarSSL 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.
+ *
+ * Module:  library/threading.c
+ *
+ * This allows different threading implementations (self-implemented or
+ * provided).
+ *
+ * You will have to enable either POLARSSL_THREADING_ALT or
+ * POLARSSL_THREADING_PTHREAD.
+ *
+ * Enable this layer to allow use of mutexes within PolarSSL
+ */
+//#define POLARSSL_THREADING_C
+
+/**
+ * \def POLARSSL_TIMING_C
+ *
+ * Enable the portable timing interface.
+ *
+ * Module:  library/timing.c
+ * Caller:  library/havege.c
+ *
+ * This module is used by the HAVEGE random number generator.
+ */
+//#define POLARSSL_TIMING_C
+
+/**
+ * \def POLARSSL_VERSION_C
+ *
+ * Enable run-time version information.
+ *
+ * Module:  library/version.c
+ *
+ * This module provides run-time version information.
+ */
+//#define POLARSSL_VERSION_C
+
+/**
+ * \def POLARSSL_X509_USE_C
+ *
+ * Enable X.509 core for using certificates.
+ *
+ * Module:  library/x509.c
+ * Caller:  library/x509_crl.c
+ *          library/x509_crt.c
+ *          library/x509_csr.c
+ *
+ * Requires: POLARSSL_ASN1_PARSE_C, POLARSSL_BIGNUM_C, POLARSSL_OID_C,
+ *           POLARSSL_PK_PARSE_C
+ *
+ * This module is required for the X.509 parsing modules.
+ */
+//#define POLARSSL_X509_USE_C
+
+/**
+ * \def POLARSSL_X509_CRT_PARSE_C
+ *
+ * Enable X.509 certificate parsing.
+ *
+ * Module:  library/x509_crt.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *          library/ssl_tls.c
+ *
+ * Requires: POLARSSL_X509_USE_C
+ *
+ * This module is required for X.509 certificate parsing.
+ */
+//#define POLARSSL_X509_CRT_PARSE_C
+
+/**
+ * \def POLARSSL_X509_CRL_PARSE_C
+ *
+ * Enable X.509 CRL parsing.
+ *
+ * Module:  library/x509_crl.c
+ * Caller:  library/x509_crt.c
+ *
+ * Requires: POLARSSL_X509_USE_C
+ *
+ * This module is required for X.509 CRL parsing.
+ */
+//#define POLARSSL_X509_CRL_PARSE_C
+
+/**
+ * \def POLARSSL_X509_CSR_PARSE_C
+ *
+ * Enable X.509 Certificate Signing Request (CSR) parsing.
+ *
+ * Module:  library/x509_csr.c
+ * Caller:  library/x509_crt_write.c
+ *
+ * Requires: POLARSSL_X509_USE_C
+ *
+ * This module is used for reading X.509 certificate request.
+ */
+//#define POLARSSL_X509_CSR_PARSE_C
+
+/**
+ * \def POLARSSL_X509_CREATE_C
+ *
+ * Enable X.509 core for creating certificates.
+ *
+ * Module:  library/x509_create.c
+ *
+ * Requires: POLARSSL_BIGNUM_C, POLARSSL_OID_C, POLARSSL_PK_WRITE_C
+ *
+ * This module is the basis for creating X.509 certificates and CSRs.
+ */
+//#define POLARSSL_X509_CREATE_C
+
+/**
+ * \def POLARSSL_X509_CRT_WRITE_C
+ *
+ * Enable creating X.509 certificates.
+ *
+ * Module:  library/x509_crt_write.c
+ *
+ * Requires: POLARSSL_CREATE_C
+ *
+ * This module is required for X.509 certificate creation.
+ */
+//#define POLARSSL_X509_CRT_WRITE_C
+
+/**
+ * \def POLARSSL_X509_CSR_WRITE_C
+ *
+ * Enable creating X.509 Certificate Signing Requests (CSR).
+ *
+ * Module:  library/x509_csr_write.c
+ *
+ * Requires: POLARSSL_CREATE_C
+ *
+ * This module is required for X.509 certificate request writing.
+ */
+//#define POLARSSL_X509_CSR_WRITE_C
+
+/**
+ * \def POLARSSL_XTEA_C
+ *
+ * Enable the XTEA block cipher.
+ *
+ * Module:  library/xtea.c
+ * Caller:
+ */
+//#define POLARSSL_XTEA_C
+
+/* \} name SECTION: PolarSSL 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 POLARSSL_CONFIG_OPTIONS and change values here
+ * only if you have a good reason and know the consequences.
+ *
+ * If POLARSSL_CONFIG_OPTIONS is undefined here the options in the module
+ * header file take precedence.
+ *
+ * Please check the respective header file for documentation on these
+ * parameters (to prevent duplicate documentation).
+ *
+ * Uncomment POLARSSL_CONFIG_OPTIONS to enable using the values defined here.
+ * \{
+ */
+#define POLARSSL_CONFIG_OPTIONS   /**< Enable config.h module value configuration */
+
+#if defined(POLARSSL_CONFIG_OPTIONS)
+
+// MPI / BIGNUM options
+//
+#define POLARSSL_MPI_WINDOW_SIZE            6 /**< Maximum windows size used. */
+#define POLARSSL_MPI_MAX_SIZE             512 /**< Maximum number of bytes for usable MPIs. */
+
+// CTR_DRBG options
+//
+#define CTR_DRBG_ENTROPY_LEN               48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */
+#define CTR_DRBG_RESEED_INTERVAL        10000 /**< Interval before reseed is performed by default */
+#define CTR_DRBG_MAX_INPUT                256 /**< Maximum number of additional input bytes */
+#define CTR_DRBG_MAX_REQUEST             1024 /**< Maximum number of requested bytes per call */
+#define CTR_DRBG_MAX_SEED_INPUT           384 /**< Maximum size of (re)seed buffer */
+
+// HMAC_DRBG options
+//
+#define POLARSSL_HMAC_DRBG_RESEED_INTERVAL   10000 /**< Interval before reseed is performed by default */
+#define POLARSSL_HMAC_DRBG_MAX_INPUT           256 /**< Maximum number of additional input bytes */
+#define POLARSSL_HMAC_DRBG_MAX_REQUEST        1024 /**< Maximum number of requested bytes per call */
+#define POLARSSL_HMAC_DRBG_MAX_SEED_INPUT      384 /**< Maximum size of (re)seed buffer */
+
+// ECP options
+//
+#define POLARSSL_ECP_MAX_BITS             521 /**< Maximum bit size of groups */
+#define POLARSSL_ECP_WINDOW_SIZE            6 /**< Maximum window size used */
+#define POLARSSL_ECP_FIXED_POINT_OPTIM      1 /**< Enable fixed-point speed-up */
+
+// Entropy options
+//
+#define ENTROPY_MAX_SOURCES                20 /**< Maximum number of sources supported */
+#define ENTROPY_MAX_GATHER                128 /**< Maximum amount requested from entropy sources */
+
+// Memory buffer allocator options
+#define MEMORY_ALIGN_MULTIPLE               4 /**< Align on multiples of this value */
+
+// Platform options
+#define POLARSSL_PLATFORM_STD_MALLOC   malloc /**< Default allocator to use, can be undefined */
+#define POLARSSL_PLATFORM_STD_FREE       free /**< Default free to use, can be undefined */
+#define POLARSSL_PLATFORM_STD_PRINTF   printf /**< Default printf to use, can be undefined */
+#define POLARSSL_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use, can be undefined */
+
+// SSL Cache options
+//
+#define SSL_CACHE_DEFAULT_TIMEOUT       86400 /**< 1 day  */
+#define SSL_CACHE_DEFAULT_MAX_ENTRIES      50 /**< Maximum entries in cache */
+
+// SSL options
+//
+//#define SSL_MAX_CONTENT_LEN             16384 /**< Size of the input / output buffer */
+#define SSL_MAX_CONTENT_LEN             1024 /**< Size of the input / output buffer */
+#define SSL_DEFAULT_TICKET_LIFETIME     86400 /**< Lifetime of session tickets (if enabled) */
+
+#endif /* POLARSSL_CONFIG_OPTIONS */
+
+/* \} name */
+
+/*
+ * Sanity checks on defines and dependencies
+ */
+#if defined(POLARSSL_AESNI_C) && !defined(POLARSSL_HAVE_ASM)
+#error "POLARSSL_AESNI_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_CERTS_C) && !defined(POLARSSL_PEM_PARSE_C)
+#error "POLARSSL_CERTS_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_CTR_DRBG_C) && !defined(POLARSSL_AES_C)
+#error "POLARSSL_CTR_DRBG_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_DHM_C) && !defined(POLARSSL_BIGNUM_C)
+#error "POLARSSL_DHM_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_ECDH_C) && !defined(POLARSSL_ECP_C)
+#error "POLARSSL_ECDH_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_ECDSA_C) &&            \
+    ( !defined(POLARSSL_ECP_C) ||           \
+      !defined(POLARSSL_ASN1_PARSE_C) ||    \
+      !defined(POLARSSL_ASN1_WRITE_C) )
+#error "POLARSSL_ECDSA_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_ECDSA_DETERMINISTIC) && !defined(POLARSSL_HMAC_DRBG_C)
+#error "POLARSSL_ECDSA_DETERMINISTIC defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_ECP_C) && ( !defined(POLARSSL_BIGNUM_C) || (   \
+    !defined(POLARSSL_ECP_DP_SECP192R1_ENABLED) &&                  \
+    !defined(POLARSSL_ECP_DP_SECP224R1_ENABLED) &&                  \
+    !defined(POLARSSL_ECP_DP_SECP256R1_ENABLED) &&                  \
+    !defined(POLARSSL_ECP_DP_SECP384R1_ENABLED) &&                  \
+    !defined(POLARSSL_ECP_DP_SECP521R1_ENABLED) &&                  \
+    !defined(POLARSSL_ECP_DP_BP256R1_ENABLED)   &&                  \
+    !defined(POLARSSL_ECP_DP_BP384R1_ENABLED)   &&                  \
+    !defined(POLARSSL_ECP_DP_BP512R1_ENABLED)   &&                  \
+    !defined(POLARSSL_ECP_DP_M255_ENABLED)      &&                  \
+    !defined(POLARSSL_ECP_DP_SECP192K1_ENABLED) &&                  \
+    !defined(POLARSSL_ECP_DP_SECP224K1_ENABLED) &&                  \
+    !defined(POLARSSL_ECP_DP_SECP256K1_ENABLED) ) )
+#error "POLARSSL_ECP_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_ENTROPY_C) && (!defined(POLARSSL_SHA512_C) &&      \
+                                    !defined(POLARSSL_SHA256_C))
+#error "POLARSSL_ENTROPY_C defined, but not all prerequisites"
+#endif
+#if defined(POLARSSL_ENTROPY_C) && defined(POLARSSL_SHA512_C) &&         \
+    defined(POLARSSL_CONFIG_OPTIONS) && (CTR_DRBG_ENTROPY_LEN > 64)
+#error "CTR_DRBG_ENTROPY_LEN value too high"
+#endif
+#if defined(POLARSSL_ENTROPY_C) && !defined(POLARSSL_SHA512_C) &&        \
+    defined(POLARSSL_CONFIG_OPTIONS) && (CTR_DRBG_ENTROPY_LEN > 32)
+#error "CTR_DRBG_ENTROPY_LEN value too high"
+#endif
+#if defined(POLARSSL_ENTROPY_C) && \
+    defined(POLARSSL_ENTROPY_FORCE_SHA256) && !defined(POLARSSL_SHA256_C)
+#error "POLARSSL_ENTROPY_FORCE_SHA256 defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_GCM_C) && (                                        \
+        !defined(POLARSSL_AES_C) && !defined(POLARSSL_CAMELLIA_C) )
+#error "POLARSSL_GCM_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_HAVEGE_C) && !defined(POLARSSL_TIMING_C)
+#error "POLARSSL_HAVEGE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_HMAC_DRBG) && !defined(POLARSSL_MD_C)
+#error "POLARSSL_HMAC_DRBG_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) &&                 \
+    ( !defined(POLARSSL_ECDH_C) || !defined(POLARSSL_X509_CRT_PARSE_C) )
+#error "POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) &&                 \
+    ( !defined(POLARSSL_ECDH_C) || !defined(POLARSSL_X509_CRT_PARSE_C) )
+#error "POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) && !defined(POLARSSL_DHM_C)
+#error "POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) &&                     \
+    !defined(POLARSSL_ECDH_C)
+#error "POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) &&                   \
+    ( !defined(POLARSSL_DHM_C) || !defined(POLARSSL_RSA_C) ||           \
+      !defined(POLARSSL_X509_CRT_PARSE_C) || !defined(POLARSSL_PKCS1_V15) )
+#error "POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) &&                 \
+    ( !defined(POLARSSL_ECDH_C) || !defined(POLARSSL_RSA_C) ||          \
+      !defined(POLARSSL_X509_CRT_PARSE_C) || !defined(POLARSSL_PKCS1_V15) )
+#error "POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) &&                 \
+    ( !defined(POLARSSL_ECDH_C) || !defined(POLARSSL_ECDSA_C) ||          \
+      !defined(POLARSSL_X509_CRT_PARSE_C) )
+#error "POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) &&                   \
+    ( !defined(POLARSSL_RSA_C) || !defined(POLARSSL_X509_CRT_PARSE_C) ||\
+      !defined(POLARSSL_PKCS1_V15) )
+#error "POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) &&                       \
+    ( !defined(POLARSSL_RSA_C) || !defined(POLARSSL_X509_CRT_PARSE_C) ||\
+      !defined(POLARSSL_PKCS1_V15) )
+#error "POLARSSL_KEY_EXCHANGE_RSA_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_MEMORY_BUFFER_ALLOC_C) &&                          \
+    ( !defined(POLARSSL_PLATFORM_C) || !defined(POLARSSL_PLATFORM_MEMORY) )
+#error "POLARSSL_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PADLOCK_C) && !defined(POLARSSL_HAVE_ASM)
+#error "POLARSSL_PADLOCK_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PBKDF2_C) && !defined(POLARSSL_MD_C)
+#error "POLARSSL_PBKDF2_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PEM_PARSE_C) && !defined(POLARSSL_BASE64_C)
+#error "POLARSSL_PEM_PARSE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PEM_WRITE_C) && !defined(POLARSSL_BASE64_C)
+#error "POLARSSL_PEM_WRITE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PK_PARSE_C) && !defined(POLARSSL_PK_C)
+#error "POLARSSL_PK_PARSE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PK_WRITE_C) && !defined(POLARSSL_PK_C)
+#error "POLARSSL_PK_WRITE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PKCS11_C) && !defined(POLARSSL_PK_C)
+#error "POLARSSL_PKCS11_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_RSA_C) && ( !defined(POLARSSL_BIGNUM_C) ||         \
+    !defined(POLARSSL_OID_C) )
+#error "POLARSSL_RSA_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_SSL_PROTO_SSL3) && ( !defined(POLARSSL_MD5_C) ||     \
+    !defined(POLARSSL_SHA1_C) )
+#error "POLARSSL_SSL_PROTO_SSL3 defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_SSL_PROTO_TLS1) && ( !defined(POLARSSL_MD5_C) ||     \
+    !defined(POLARSSL_SHA1_C) )
+#error "POLARSSL_SSL_PROTO_TLS1 defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_SSL_PROTO_TLS1_1) && ( !defined(POLARSSL_MD5_C) ||     \
+    !defined(POLARSSL_SHA1_C) )
+#error "POLARSSL_SSL_PROTO_TLS1_1 defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_SSL_PROTO_TLS1_2) && ( !defined(POLARSSL_SHA1_C) &&     \
+    !defined(POLARSSL_SHA256_C) && !defined(POLARSSL_SHA512_C) )
+#error "POLARSSL_SSL_PROTO_TLS1_2 defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_SSL_PROTO_DTLS) && (       \
+    !defined(POLARSSL_SSL_PROTO_TLS1_1) &&      \
+    !defined(POLARSSL_SSL_PROTO_TLS1_2) )
+#error "POLARSSL_SSL_PROTO_DTLS defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_SSL_CLI_C) && !defined(POLARSSL_SSL_TLS_C)
+#error "POLARSSL_SSL_CLI_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_SSL_TLS_C) && ( !defined(POLARSSL_CIPHER_C) ||     \
+    !defined(POLARSSL_MD_C) )
+#error "POLARSSL_SSL_TLS_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_SSL_SRV_C) && !defined(POLARSSL_SSL_TLS_C)
+#error "POLARSSL_SSL_SRV_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_SSL_TLS_C) && (!defined(POLARSSL_SSL_PROTO_SSL3) && \
+    !defined(POLARSSL_SSL_PROTO_TLS1) && !defined(POLARSSL_SSL_PROTO_TLS1_1) && \
+    !defined(POLARSSL_SSL_PROTO_TLS1_2))
+#error "POLARSSL_SSL_TLS_C defined, but no protocols are active"
+#endif
+
+#if defined(POLARSSL_SSL_TLS_C) && (defined(POLARSSL_SSL_PROTO_SSL3) && \
+    defined(POLARSSL_SSL_PROTO_TLS1_1) && !defined(POLARSSL_SSL_PROTO_TLS1))
+#error "Illegal protocol selection"
+#endif
+
+#if defined(POLARSSL_SSL_TLS_C) && (defined(POLARSSL_SSL_PROTO_TLS1) && \
+    defined(POLARSSL_SSL_PROTO_TLS1_2) && !defined(POLARSSL_SSL_PROTO_TLS1_1))
+#error "Illegal protocol selection"
+#endif
+
+#if defined(POLARSSL_SSL_TLS_C) && (defined(POLARSSL_SSL_PROTO_SSL3) && \
+    defined(POLARSSL_SSL_PROTO_TLS1_2) && (!defined(POLARSSL_SSL_PROTO_TLS1) || \
+    !defined(POLARSSL_SSL_PROTO_TLS1_1)))
+#error "Illegal protocol selection"
+#endif
+
+#if defined(POLARSSL_SSL_SESSION_TICKETS) && defined(POLARSSL_SSL_TLS_C) && \
+    ( !defined(POLARSSL_AES_C) || !defined(POLARSSL_SHA256_C) ||            \
+      !defined(POLARSSL_CIPHER_MODE_CBC) )
+#error "POLARSSL_SSL_SESSION_TICKETS_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) && \
+        !defined(POLARSSL_X509_CRT_PARSE_C)
+#error "POLARSSL_SSL_SERVER_NAME_INDICATION defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_THREADING_PTHREAD)
+#if !defined(POLARSSL_THREADING_C) || defined(POLARSSL_THREADING_IMPL)
+#error "POLARSSL_THREADING_PTHREAD defined, but not all prerequisites"
+#endif
+#define POLARSSL_THREADING_IMPL
+#endif
+
+#if defined(POLARSSL_THREADING_ALT)
+#if !defined(POLARSSL_THREADING_C) || defined(POLARSSL_THREADING_IMPL)
+#error "POLARSSL_THREADING_ALT defined, but not all prerequisites"
+#endif
+#define POLARSSL_THREADING_IMPL
+#endif
+
+#if defined(POLARSSL_THREADING_C) && !defined(POLARSSL_THREADING_IMPL)
+#error "POLARSSL_THREADING_C defined, single threading implementation required"
+#endif
+#undef POLARSSL_THREADING_IMPL
+
+#if defined(POLARSSL_X509_USE_C) && ( !defined(POLARSSL_BIGNUM_C) ||  \
+    !defined(POLARSSL_OID_C) || !defined(POLARSSL_ASN1_PARSE_C) ||      \
+    !defined(POLARSSL_PK_PARSE_C) )
+#error "POLARSSL_X509_USE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_X509_CREATE_C) && ( !defined(POLARSSL_BIGNUM_C) ||  \
+    !defined(POLARSSL_OID_C) || !defined(POLARSSL_ASN1_WRITE_C) ||       \
+    !defined(POLARSSL_PK_WRITE_C) )
+#error "POLARSSL_X509_CREATE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_X509_CRT_PARSE_C) && ( !defined(POLARSSL_X509_USE_C) )
+#error "POLARSSL_X509_CRT_PARSE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_X509_CRL_PARSE_C) && ( !defined(POLARSSL_X509_USE_C) )
+#error "POLARSSL_X509_CRL_PARSE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_X509_CSR_PARSE_C) && ( !defined(POLARSSL_X509_USE_C) )
+#error "POLARSSL_X509_CSR_PARSE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_X509_CRT_WRITE_C) && ( !defined(POLARSSL_X509_CREATE_C) )
+#error "POLARSSL_X509_CRT_WRITE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_X509_CSR_WRITE_C) && ( !defined(POLARSSL_X509_CREATE_C) )
+#error "POLARSSL_X509_CSR_WRITE_C defined, but not all prerequisites"
+#endif
+
+#endif /* config.h */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/config_orig.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,2122 @@
+/**
+ * \file config.h
+ *
+ * \brief Configuration options (set of defines)
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * This set of compile-time options may be used to enable
+ * or disable features selectively, and reduce the global
+ * memory footprint.
+ */
+#ifndef POLARSSL_CONFIG_H
+#define POLARSSL_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 POLARSSL_HAVE_INT8
+ *
+ * The system uses 8-bit wide native integers.
+ *
+ * Uncomment if native integers are 8-bit wide.
+ */
+//#define POLARSSL_HAVE_INT8
+
+/**
+ * \def POLARSSL_HAVE_INT16
+ *
+ * The system uses 16-bit wide native integers.
+ *
+ * Uncomment if native integers are 16-bit wide.
+ */
+//#define POLARSSL_HAVE_INT16
+
+/**
+ * \def POLARSSL_HAVE_LONGLONG
+ *
+ * The compiler supports the 'long long' type.
+ * (Only used on 32-bit platforms)
+ */
+#define POLARSSL_HAVE_LONGLONG
+
+/**
+ * \def POLARSSL_HAVE_ASM
+ *
+ * The compiler has support for asm().
+ *
+ * Requires support for asm() in compiler.
+ *
+ * Used in:
+ *      library/timing.c
+ *      library/padlock.c
+ *      include/polarssl/bn_mul.h
+ *
+ * Comment to disable the use of assembly code.
+ */
+#define POLARSSL_HAVE_ASM
+
+/**
+ * \def POLARSSL_HAVE_SSE2
+ *
+ * CPU supports SSE2 instruction set.
+ *
+ * Uncomment if the CPU supports SSE2 (IA-32 specific).
+ */
+//#define POLARSSL_HAVE_SSE2
+
+/**
+ * \def POLARSSL_HAVE_TIME
+ *
+ * System has time.h and time() / localtime()  / gettimeofday().
+ *
+ * Comment if your system does not support time functions
+ */
+#define POLARSSL_HAVE_TIME
+
+/**
+ * \def POLARSSL_HAVE_IPV6
+ *
+ * System supports the basic socket interface for IPv6 (RFC 3493),
+ * specifically getaddrinfo(), freeaddrinfo() and struct sockaddr_storage.
+ *
+ * Note: on Windows/MingW, XP or higher is required.
+ *
+ * Comment if your system does not support the IPv6 socket interface
+ */
+#define POLARSSL_HAVE_IPV6
+
+/**
+ * \def POLARSSL_PLATFORM_MEMORY
+ *
+ * Enable the memory allocation layer.
+ *
+ * By default PolarSSL uses the system-provided malloc() and free().
+ * This allows different allocators (self-implemented or provided) to be
+ * provided to the platform abstraction layer.
+ *
+ * Enabling POLARSSL_PLATFORM_MEMORY will provide "platform_set_malloc_free()"
+ * to allow you to set an alternative malloc() and free() function pointer.
+ *
+ * Requires: POLARSSL_PLATFORM_C
+ *
+ * Enable this layer to allow use of alternative memory allocators.
+ */
+//#define POLARSSL_PLATFORM_MEMORY
+
+/**
+ * \def POLARSSL_PLATFORM_NO_STD_FUNCTIONS
+ *
+ * Do not assign standard functions in the platform layer (e.g. malloc() to
+ * POLARSSL_PLATFORM_STD_MALLOC and printf() to POLARSSL_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 POLARSSL_PLATFORM_STD_XXX defines.
+ *
+ * Requires: POLARSSL_PLATFORM_C
+ *
+ * Uncomment to prevent default assignment of standard functions in the
+ * platform layer.
+ */
+//#define POLARSSL_PLATFORM_NO_STD_FUNCTIONS
+
+/**
+ * \def POLARSSL_PLATFORM_XXX_ALT
+ *
+ * Uncomment a macro to let PolarSSL support the function in the platform
+ * abstraction layer.
+ *
+ * Example: In case you uncomment POLARSSL_PLATFORM_PRINTF_ALT, PolarSSL will
+ * provide a function "platform_set_printf()" that allows you to set an
+ * alternative printf function pointer.
+ *
+ * All these define require POLARSSL_PLATFORM_C to be defined!
+ *
+ * Uncomment a macro to enable alternate implementation of specific base
+ * platform function
+ */
+//#define POLARSSL_PLATFORM_PRINTF_ALT
+//#define POLARSSL_PLATFORM_FPRINTF_ALT
+/* \} name SECTION: System support */
+
+/**
+ * \name SECTION: PolarSSL feature support
+ *
+ * This section sets support for features that are or are not needed
+ * within the modules that are enabled.
+ * \{
+ */
+
+/**
+ * \def POLARSSL_TIMING_ALT
+ *
+ * Uncomment to provide your own alternate implementation for hardclock(),
+ * get_timer(), set_alarm() and m_sleep().
+ *
+ * Only works if you have POLARSSL_TIMING_C enabled.
+ *
+ * You will need to provide a header "timing_alt.h" and an implementation at
+ * compile time.
+ */
+//#define POLARSSL_TIMING_ALT
+
+/**
+ * \def POLARSSL_XXX_ALT
+ *
+ * Uncomment a macro to let PolarSSL use your alternate core implementation of
+ * a symmetric or hash algorithm (e.g. platform specific assembly optimized
+ * implementations). Keep in mind that the function prototypes should remain
+ * the same.
+ *
+ * Example: In case you uncomment POLARSSL_AES_ALT, PolarSSL will no longer
+ * provide the "struct 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 for core algorithm
+ * functions
+ */
+//#define POLARSSL_AES_ALT
+//#define POLARSSL_ARC4_ALT
+//#define POLARSSL_BLOWFISH_ALT
+//#define POLARSSL_CAMELLIA_ALT
+//#define POLARSSL_DES_ALT
+//#define POLARSSL_XTEA_ALT
+//#define POLARSSL_MD2_ALT
+//#define POLARSSL_MD4_ALT
+//#define POLARSSL_MD5_ALT
+//#define POLARSSL_RIPEMD160_ALT
+//#define POLARSSL_SHA1_ALT
+//#define POLARSSL_SHA256_ALT
+//#define POLARSSL_SHA512_ALT
+
+/**
+ * \def POLARSSL_AES_ROM_TABLES
+ *
+ * Store the AES tables in ROM.
+ *
+ * Uncomment this macro to store the AES tables in ROM.
+ *
+ */
+//#define POLARSSL_AES_ROM_TABLES
+
+/**
+ * \def POLARSSL_CIPHER_MODE_CBC
+ *
+ * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers.
+ */
+#define POLARSSL_CIPHER_MODE_CBC
+
+/**
+ * \def POLARSSL_CIPHER_MODE_CFB
+ *
+ * Enable Cipher Feedback mode (CFB) for symmetric ciphers.
+ */
+#define POLARSSL_CIPHER_MODE_CFB
+
+/**
+ * \def POLARSSL_CIPHER_MODE_CTR
+ *
+ * Enable Counter Block Cipher mode (CTR) for symmetric ciphers.
+ */
+#define POLARSSL_CIPHER_MODE_CTR
+
+/**
+ * \def POLARSSL_CIPHER_NULL_CIPHER
+ *
+ * Enable NULL cipher.
+ * Warning: Only do so when you know what you are doing. This allows for
+ * encryption or channels without any security!
+ *
+ * Requires POLARSSL_ENABLE_WEAK_CIPHERSUITES as well to enable
+ * the following ciphersuites:
+ *      TLS_ECDH_ECDSA_WITH_NULL_SHA
+ *      TLS_ECDH_RSA_WITH_NULL_SHA
+ *      TLS_ECDHE_ECDSA_WITH_NULL_SHA
+ *      TLS_ECDHE_RSA_WITH_NULL_SHA
+ *      TLS_ECDHE_PSK_WITH_NULL_SHA384
+ *      TLS_ECDHE_PSK_WITH_NULL_SHA256
+ *      TLS_ECDHE_PSK_WITH_NULL_SHA
+ *      TLS_DHE_PSK_WITH_NULL_SHA384
+ *      TLS_DHE_PSK_WITH_NULL_SHA256
+ *      TLS_DHE_PSK_WITH_NULL_SHA
+ *      TLS_RSA_WITH_NULL_SHA256
+ *      TLS_RSA_WITH_NULL_SHA
+ *      TLS_RSA_WITH_NULL_MD5
+ *      TLS_RSA_PSK_WITH_NULL_SHA384
+ *      TLS_RSA_PSK_WITH_NULL_SHA256
+ *      TLS_RSA_PSK_WITH_NULL_SHA
+ *      TLS_PSK_WITH_NULL_SHA384
+ *      TLS_PSK_WITH_NULL_SHA256
+ *      TLS_PSK_WITH_NULL_SHA
+ *
+ * Uncomment this macro to enable the NULL cipher and ciphersuites
+ */
+//#define POLARSSL_CIPHER_NULL_CIPHER
+
+/**
+ * \def POLARSSL_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 POLARSSL_CIPHER_PADDING_PKCS7
+#define POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS
+#define POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN
+#define POLARSSL_CIPHER_PADDING_ZEROS
+
+/**
+ * \def POLARSSL_ENABLE_WEAK_CIPHERSUITES
+ *
+ * Enable weak ciphersuites in SSL / TLS.
+ * Warning: Only do so when you know what you are doing. This allows for
+ * channels with virtually no security at all!
+ *
+ * This enables the following ciphersuites:
+ *      TLS_RSA_WITH_DES_CBC_SHA
+ *      TLS_DHE_RSA_WITH_DES_CBC_SHA
+ *
+ * Uncomment this macro to enable weak ciphersuites
+ */
+//#define POLARSSL_ENABLE_WEAK_CIPHERSUITES
+
+/**
+ * \def POLARSSL_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 POLARSSL_ECP_DP_SECP192R1_ENABLED
+#define POLARSSL_ECP_DP_SECP224R1_ENABLED
+#define POLARSSL_ECP_DP_SECP256R1_ENABLED
+#define POLARSSL_ECP_DP_SECP384R1_ENABLED
+#define POLARSSL_ECP_DP_SECP521R1_ENABLED
+#define POLARSSL_ECP_DP_SECP192K1_ENABLED
+#define POLARSSL_ECP_DP_SECP224K1_ENABLED
+#define POLARSSL_ECP_DP_SECP256K1_ENABLED
+#define POLARSSL_ECP_DP_BP256R1_ENABLED
+#define POLARSSL_ECP_DP_BP384R1_ENABLED
+#define POLARSSL_ECP_DP_BP512R1_ENABLED
+//#define POLARSSL_ECP_DP_M221_ENABLED  // Not implemented yet!
+#define POLARSSL_ECP_DP_M255_ENABLED
+//#define POLARSSL_ECP_DP_M383_ENABLED  // Not implemented yet!
+//#define POLARSSL_ECP_DP_M511_ENABLED  // Not implemented yet!
+
+/**
+ * \def POLARSSL_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 POLARSSL_ECP_NIST_OPTIM
+
+/**
+ * \def POLARSSL_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: POLARSSL_HMAC_DRBG_C
+ *
+ * Comment this macro to disable deterministic ECDSA.
+ */
+#define POLARSSL_ECDSA_DETERMINISTIC
+
+/**
+ * \def POLARSSL_KEY_EXCHANGE_PSK_ENABLED
+ *
+ * Enable the PSK based ciphersuite modes in SSL / TLS.
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      TLS_PSK_WITH_AES_256_GCM_SHA384
+ *      TLS_PSK_WITH_AES_256_CBC_SHA384
+ *      TLS_PSK_WITH_AES_256_CBC_SHA
+ *      TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ *      TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_PSK_WITH_AES_128_GCM_SHA256
+ *      TLS_PSK_WITH_AES_128_CBC_SHA256
+ *      TLS_PSK_WITH_AES_128_CBC_SHA
+ *      TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_PSK_WITH_3DES_EDE_CBC_SHA
+ *      TLS_PSK_WITH_RC4_128_SHA
+ */
+#define POLARSSL_KEY_EXCHANGE_PSK_ENABLED
+
+/**
+ * \def POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED
+ *
+ * Enable the DHE-PSK based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: POLARSSL_DHM_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
+ *      TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
+ *      TLS_DHE_PSK_WITH_AES_256_CBC_SHA
+ *      TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ *      TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
+ *      TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
+ *      TLS_DHE_PSK_WITH_AES_128_CBC_SHA
+ *      TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA
+ *      TLS_DHE_PSK_WITH_RC4_128_SHA
+ */
+#define POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED
+
+/**
+ * \def POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED
+ *
+ * Enable the ECDHE-PSK based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: POLARSSL_ECDH_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384
+ *      TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA
+ *      TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
+ *      TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA
+ *      TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA
+ *      TLS_ECDHE_PSK_WITH_RC4_128_SHA
+ */
+#define POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED
+
+/**
+ * \def POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED
+ *
+ * Enable the RSA-PSK based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: POLARSSL_RSA_C, POLARSSL_PKCS1_V15,
+ *           POLARSSL_X509_CRT_PARSE_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      TLS_RSA_PSK_WITH_AES_256_GCM_SHA384
+ *      TLS_RSA_PSK_WITH_AES_256_CBC_SHA384
+ *      TLS_RSA_PSK_WITH_AES_256_CBC_SHA
+ *      TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ *      TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_RSA_PSK_WITH_AES_128_GCM_SHA256
+ *      TLS_RSA_PSK_WITH_AES_128_CBC_SHA256
+ *      TLS_RSA_PSK_WITH_AES_128_CBC_SHA
+ *      TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA
+ *      TLS_RSA_PSK_WITH_RC4_128_SHA
+ */
+#define POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED
+
+/**
+ * \def POLARSSL_KEY_EXCHANGE_RSA_ENABLED
+ *
+ * Enable the RSA-only based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: POLARSSL_RSA_C, POLARSSL_PKCS1_V15,
+ *           POLARSSL_X509_CRT_PARSE_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      TLS_RSA_WITH_AES_256_GCM_SHA384
+ *      TLS_RSA_WITH_AES_256_CBC_SHA256
+ *      TLS_RSA_WITH_AES_256_CBC_SHA
+ *      TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
+ *      TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
+ *      TLS_RSA_WITH_AES_128_GCM_SHA256
+ *      TLS_RSA_WITH_AES_128_CBC_SHA256
+ *      TLS_RSA_WITH_AES_128_CBC_SHA
+ *      TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
+ *      TLS_RSA_WITH_3DES_EDE_CBC_SHA
+ *      TLS_RSA_WITH_RC4_128_SHA
+ *      TLS_RSA_WITH_RC4_128_MD5
+ */
+#define POLARSSL_KEY_EXCHANGE_RSA_ENABLED
+
+/**
+ * \def POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED
+ *
+ * Enable the DHE-RSA based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: POLARSSL_DHM_C, POLARSSL_RSA_C, POLARSSL_PKCS1_V15,
+ *           POLARSSL_X509_CRT_PARSE_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
+ *      TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
+ *      TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+ *      TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
+ *      TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
+ *      TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
+ *      TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+ *      TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+ *      TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
+ *      TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
+ */
+#define POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED
+
+/**
+ * \def POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED
+ *
+ * Enable the ECDHE-RSA based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: POLARSSL_ECDH_C, POLARSSL_RSA_C, POLARSSL_PKCS1_V15,
+ *           POLARSSL_X509_CRT_PARSE_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
+ *      TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
+ *      TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
+ *      TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
+ *      TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+ *      TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
+ *      TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
+ *      TLS_ECDHE_RSA_WITH_RC4_128_SHA
+ */
+#define POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED
+
+/**
+ * \def POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+ *
+ * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: POLARSSL_ECDH_C, POLARSSL_ECDSA_C, POLARSSL_X509_CRT_PARSE_C,
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
+ *      TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
+ *      TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
+ *      TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+ *      TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
+ *      TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
+ *      TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
+ *      TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
+ */
+#define POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+
+/**
+ * \def POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
+ *
+ * Enable the ECDH-ECDSA based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: POLARSSL_ECDH_C, POLARSSL_X509_CRT_PARSE_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      TLS_ECDH_ECDSA_WITH_RC4_128_SHA
+ *      TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
+ *      TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
+ *      TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
+ *      TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
+ *      TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
+ *      TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
+ *      TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
+ *      TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
+ */
+#define POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
+
+/**
+ * \def POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED
+ *
+ * Enable the ECDH-RSA based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: POLARSSL_ECDH_C, POLARSSL_X509_CRT_PARSE_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      TLS_ECDH_RSA_WITH_RC4_128_SHA
+ *      TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
+ *      TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
+ *      TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
+ *      TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
+ *      TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
+ *      TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
+ *      TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
+ *      TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ */
+#define POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED
+
+/**
+ * \def POLARSSL_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 POLARSSL_PK_PARSE_EC_EXTENDED
+
+/**
+ * \def POLARSSL_ERROR_STRERROR_BC
+ *
+ * Make available the backward compatible error_strerror() next to the
+ * current polarssl_strerror().
+ *
+ * Disable if you run into name conflicts and want to really remove the
+ * error_strerror()
+ */
+#define POLARSSL_ERROR_STRERROR_BC
+
+/**
+ * \def POLARSSL_ERROR_STRERROR_DUMMY
+ *
+ * Enable a dummy error function to make use of polarssl_strerror() in
+ * third party libraries easier.
+ *
+ * Disable if you run into name conflicts and want to really remove the
+ * polarssl_strerror()
+ */
+#define POLARSSL_ERROR_STRERROR_DUMMY
+
+/**
+ * \def POLARSSL_GENPRIME
+ *
+ * Enable the prime-number generation code.
+ *
+ * Requires: POLARSSL_BIGNUM_C
+ */
+#define POLARSSL_GENPRIME
+
+/**
+ * \def POLARSSL_FS_IO
+ *
+ * Enable functions that use the filesystem.
+ */
+#define POLARSSL_FS_IO
+
+/**
+ * \def POLARSSL_NO_DEFAULT_ENTROPY_SOURCES
+ *
+ * Do not add default entropy sources. These are the platform specific,
+ * 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 POLARSSL_NO_DEFAULT_ENTROPY_SOURCES
+
+/**
+ * \def POLARSSL_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 POLARSSL_NO_PLATFORM_ENTROPY
+
+/**
+ * \def POLARSSL_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: POLARSSL_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 POLARSSL_SHA256_C and
+ * POLARSSL_SHA512_C are defined. Otherwise the available hash module is used.
+ */
+//#define POLARSSL_ENTROPY_FORCE_SHA256
+
+/**
+ * \def POLARSSL_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: POLARSSL_MEMORY_BUFFER_ALLOC_C
+ *
+ * Uncomment this macro to let the buffer allocator print out error messages.
+ */
+//#define POLARSSL_MEMORY_DEBUG
+
+/**
+ * \def POLARSSL_MEMORY_BACKTRACE
+ *
+ * Include backtrace information with each allocated block.
+ *
+ * Requires: POLARSSL_MEMORY_BUFFER_ALLOC_C
+ *           GLIBC-compatible backtrace() an backtrace_symbols() support
+ *
+ * Uncomment this macro to include backtrace information
+ */
+//#define POLARSSL_MEMORY_BACKTRACE
+
+/**
+ * \def POLARSSL_PKCS1_V15
+ *
+ * Enable support for PKCS#1 v1.5 encoding.
+ *
+ * Requires: POLARSSL_RSA_C
+ *
+ * This enables support for PKCS#1 v1.5 operations.
+ */
+#define POLARSSL_PKCS1_V15
+
+/**
+ * \def POLARSSL_PKCS1_V21
+ *
+ * Enable support for PKCS#1 v2.1 encoding.
+ *
+ * Requires: POLARSSL_MD_C, POLARSSL_RSA_C
+ *
+ * This enables support for RSAES-OAEP and RSASSA-PSS operations.
+ */
+#define POLARSSL_PKCS1_V21
+
+/**
+ * \def POLARSSL_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 POLARSSL_RSA_NO_CRT
+
+/**
+ * \def POLARSSL_SELF_TEST
+ *
+ * Enable the checkup functions (*_self_test).
+ */
+#define POLARSSL_SELF_TEST
+
+/**
+ * \def POLARSSL_SSL_ALL_ALERT_MESSAGES
+ *
+ * Enable sending of alert messages in case of encountered errors as per RFC.
+ * If you choose not to send the alert messages, PolarSSL can still communicate
+ * with other servers, only debugging of failures is harder.
+ *
+ * The advantage of not sending alert messages, is that no information is given
+ * about reasons for failures thus preventing adversaries of gaining intel.
+ *
+ * Enable sending of all alert messages
+ */
+#define POLARSSL_SSL_ALERT_MESSAGES
+
+/**
+ * \def POLARSSL_SSL_DEBUG_ALL
+ *
+ * Enable the debug messages in SSL module for all issues.
+ * Debug messages have been disabled in some places to prevent timing
+ * attacks due to (unbalanced) debugging function calls.
+ *
+ * If you need all error reporting you should enable this during debugging,
+ * but remove this for production servers that should log as well.
+ *
+ * Uncomment this macro to report all debug messages on errors introducing
+ * a timing side-channel.
+ *
+ */
+//#define POLARSSL_SSL_DEBUG_ALL
+
+/**
+ * \def POLARSSL_SSL_HW_RECORD_ACCEL
+ *
+ * Enable hooking functions in SSL module for hardware acceleration of
+ * individual records.
+ *
+ * Uncomment this macro to enable hooking functions.
+ */
+//#define POLARSSL_SSL_HW_RECORD_ACCEL
+
+/**
+ * \def POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO
+ *
+ * Enable support for receiving and parsing SSLv2 Client Hello messages for the
+ * SSL Server module (POLARSSL_SSL_SRV_C).
+ *
+ * Comment this macro to disable support for SSLv2 Client Hello messages.
+ */
+#define POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO
+
+/**
+ * \def POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE
+ *
+ * Pick the ciphersuite according to the client's preferences rather than ours
+ * in the SSL Server module (POLARSSL_SSL_SRV_C).
+ *
+ * Uncomment this macro to respect client's ciphersuite order
+ */
+//#define POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE
+
+/**
+ * \def POLARSSL_SSL_MAX_FRAGMENT_LENGTH
+ *
+ * Enable support for RFC 6066 max_fragment_length extension in SSL.
+ *
+ * Comment this macro to disable support for the max_fragment_length extension
+ */
+#define POLARSSL_SSL_MAX_FRAGMENT_LENGTH
+
+/**
+ * \def POLARSSL_SSL_PROTO_SSL3
+ *
+ * Enable support for SSL 3.0.
+ *
+ * Requires: POLARSSL_MD5_C
+ *           POLARSSL_SHA1_C
+ *
+ * Comment this macro to disable support for SSL 3.0
+ */
+#define POLARSSL_SSL_PROTO_SSL3
+
+/**
+ * \def POLARSSL_SSL_PROTO_TLS1
+ *
+ * Enable support for TLS 1.0.
+ *
+ * Requires: POLARSSL_MD5_C
+ *           POLARSSL_SHA1_C
+ *
+ * Comment this macro to disable support for TLS 1.0
+ */
+#define POLARSSL_SSL_PROTO_TLS1
+
+/**
+ * \def POLARSSL_SSL_PROTO_TLS1_1
+ *
+ * Enable support for TLS 1.1.
+ *
+ * Requires: POLARSSL_MD5_C
+ *           POLARSSL_SHA1_C
+ *
+ * Comment this macro to disable support for TLS 1.1
+ */
+#define POLARSSL_SSL_PROTO_TLS1_1
+
+/**
+ * \def POLARSSL_SSL_PROTO_TLS1_2
+ *
+ * Enable support for TLS 1.2.
+ *
+ * Requires: POLARSSL_SHA1_C or POLARSSL_SHA256_C or POLARSSL_SHA512_C
+ *           (Depends on ciphersuites)
+ *
+ * Comment this macro to disable support for TLS 1.2
+ */
+#define POLARSSL_SSL_PROTO_TLS1_2
+
+/**
+ * \def POLARSSL_SSL_ALPN
+ *
+ * Enable support for Application Layer Protocol Negotiation.
+ * draft-ietf-tls-applayerprotoneg-05
+ *
+ * Comment this macro to disable support for ALPN.
+ */
+#define POLARSSL_SSL_ALPN
+
+/**
+ * \def POLARSSL_SSL_SESSION_TICKETS
+ *
+ * Enable support for RFC 5077 session tickets in SSL.
+ *
+ * Requires: POLARSSL_AES_C
+ *           POLARSSL_SHA256_C
+ *           POLARSSL_CIPHER_MODE_CBC
+ *
+ * Comment this macro to disable support for SSL session tickets
+ */
+#define POLARSSL_SSL_SESSION_TICKETS
+
+/**
+ * \def POLARSSL_SSL_SERVER_NAME_INDICATION
+ *
+ * Enable support for RFC 6066 server name indication (SNI) in SSL.
+ *
+ * Comment this macro to disable support for server name indication in SSL
+ */
+#define POLARSSL_SSL_SERVER_NAME_INDICATION
+
+/**
+ * \def POLARSSL_SSL_TRUNCATED_HMAC
+ *
+ * Enable support for RFC 6066 truncated HMAC in SSL.
+ *
+ * Comment this macro to disable support for truncated HMAC in SSL
+ */
+#define POLARSSL_SSL_TRUNCATED_HMAC
+
+/**
+ * \def POLARSSL_SSL_SET_CURVES
+ *
+ * Enable ssl_set_curves().
+ *
+ * This is disabled by default since it breaks binary compatibility with the
+ * 1.3.x line. If you choose to enable it, you will need to rebuild your
+ * application against the new header files, relinking will not be enough.
+ * It will be enabled by default, or no longer an option, in the 1.4 branch.
+ *
+ * Uncomment to make ssl_set_curves() available.
+ */
+//#define POLARSSL_SSL_SET_CURVES
+
+/**
+ * \def POLARSSL_THREADING_ALT
+ *
+ * Provide your own alternate threading implementation.
+ *
+ * Requires: POLARSSL_THREADING_C
+ *
+ * Uncomment this to allow your own alternate threading implementation.
+ */
+//#define POLARSSL_THREADING_ALT
+
+/**
+ * \def POLARSSL_THREADING_PTHREAD
+ *
+ * Enable the pthread wrapper layer for the threading layer.
+ *
+ * Requires: POLARSSL_THREADING_C
+ *
+ * Uncomment this to enable pthread mutexes.
+ */
+//#define POLARSSL_THREADING_PTHREAD
+
+/**
+ * \def POLARSSL_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 version_check_feature().
+ *
+ * Requires: POLARSSL_VERSION_C
+ *
+ * Comment this to disable run-time checking and save ROM space
+ */
+#define POLARSSL_VERSION_FEATURES
+
+/**
+ * \def POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3
+ *
+ * If set, the X509 parser will not break-off when parsing an X509 certificate
+ * and encountering an extension in a v1 or v2 certificate.
+ *
+ * Uncomment to prevent an error.
+ */
+//#define POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3
+
+/**
+ * \def POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
+ *
+ * If set, the X509 parser will not break-off when parsing an X509 certificate
+ * and encountering an unknown critical extension.
+ *
+ * Uncomment to prevent an error.
+ */
+//#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
+
+/**
+ * \def POLARSSL_X509_CHECK_KEY_USAGE
+ *
+ * Enable verification of the keyUsage extension (CA and leaf certificates).
+ *
+ * Disabling this avoids problems with mis-issued and/or misused
+ * (intermediate) CA and leaf certificates.
+ *
+ * \warning Depending on your PKI use, disabling this can be a security risk!
+ *
+ * Comment to skip keyUsage checking for both CA and leaf certificates.
+ */
+#define POLARSSL_X509_CHECK_KEY_USAGE
+
+/**
+ * \def POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE
+ *
+ * Enable verification of the extendedKeyUsage extension (leaf certificates).
+ *
+ * Disabling this avoids problems with mis-issued and/or misused certificates.
+ *
+ * \warning Depending on your PKI use, disabling this can be a security risk!
+ *
+ * Comment to skip extendedKeyUsage checking for certificates.
+ */
+#define POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE
+
+/**
+ * \def POLARSSL_ZLIB_SUPPORT
+ *
+ * If set, the SSL/TLS module uses ZLIB to support compression and
+ * decompression of packet data.
+ *
+ * \warning TLS-level compression MAY REDUCE SECURITY! See for example the
+ * CRIME attack. Before enabling this option, you should examine with care if
+ * CRIME or similar exploits may be a applicable to your use case.
+ *
+ * Used in: library/ssl_tls.c
+ *          library/ssl_cli.c
+ *          library/ssl_srv.c
+ *
+ * This feature requires zlib library and headers to be present.
+ *
+ * Uncomment to enable use of ZLIB
+ */
+//#define POLARSSL_ZLIB_SUPPORT
+/* \} name SECTION: PolarSSL feature support */
+
+/**
+ * \name SECTION: PolarSSL modules
+ *
+ * This section enables or disables entire modules in PolarSSL
+ * \{
+ */
+
+/**
+ * \def POLARSSL_AESNI_C
+ *
+ * Enable AES-NI support on x86-64.
+ *
+ * Module:  library/aesni.c
+ * Caller:  library/aes.c
+ *
+ * Requires: POLARSSL_HAVE_ASM
+ *
+ * This modules adds support for the AES-NI instructions on x86-64
+ */
+#define POLARSSL_AESNI_C
+
+/**
+ * \def POLARSSL_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):
+ *      TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
+ *      TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
+ *      TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
+ *      TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
+ *      TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
+ *      TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
+ *      TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
+ *      TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
+ *      TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
+ *      TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
+ *      TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
+ *      TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
+ *      TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
+ *      TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
+ *      TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
+ *      TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
+ *      TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
+ *      TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
+ *      TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
+ *      TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
+ *      TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+ *      TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+ *      TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
+ *      TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
+ *      TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
+ *      TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+ *      TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+ *      TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
+ *      TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
+ *      TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+ *      TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
+ *      TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384
+ *      TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
+ *      TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA
+ *      TLS_DHE_PSK_WITH_AES_256_CBC_SHA
+ *      TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
+ *      TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
+ *      TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
+ *      TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA
+ *      TLS_DHE_PSK_WITH_AES_128_CBC_SHA
+ *      TLS_RSA_WITH_AES_256_GCM_SHA384
+ *      TLS_RSA_WITH_AES_256_CBC_SHA256
+ *      TLS_RSA_WITH_AES_256_CBC_SHA
+ *      TLS_RSA_WITH_AES_128_GCM_SHA256
+ *      TLS_RSA_WITH_AES_128_CBC_SHA256
+ *      TLS_RSA_WITH_AES_128_CBC_SHA
+ *      TLS_RSA_PSK_WITH_AES_256_GCM_SHA384
+ *      TLS_RSA_PSK_WITH_AES_256_CBC_SHA384
+ *      TLS_RSA_PSK_WITH_AES_256_CBC_SHA
+ *      TLS_RSA_PSK_WITH_AES_128_GCM_SHA256
+ *      TLS_RSA_PSK_WITH_AES_128_CBC_SHA256
+ *      TLS_RSA_PSK_WITH_AES_128_CBC_SHA
+ *      TLS_PSK_WITH_AES_256_GCM_SHA384
+ *      TLS_PSK_WITH_AES_256_CBC_SHA384
+ *      TLS_PSK_WITH_AES_256_CBC_SHA
+ *      TLS_PSK_WITH_AES_128_GCM_SHA256
+ *      TLS_PSK_WITH_AES_128_CBC_SHA256
+ *      TLS_PSK_WITH_AES_128_CBC_SHA
+ *
+ * PEM_PARSE uses AES for decrypting encrypted keys.
+ */
+#define POLARSSL_AES_C
+
+/**
+ * \def POLARSSL_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):
+ *      TLS_ECDH_ECDSA_WITH_RC4_128_SHA
+ *      TLS_ECDH_RSA_WITH_RC4_128_SHA
+ *      TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
+ *      TLS_ECDHE_RSA_WITH_RC4_128_SHA
+ *      TLS_ECDHE_PSK_WITH_RC4_128_SHA
+ *      TLS_DHE_PSK_WITH_RC4_128_SHA
+ *      TLS_RSA_WITH_RC4_128_SHA
+ *      TLS_RSA_WITH_RC4_128_MD5
+ *      TLS_RSA_PSK_WITH_RC4_128_SHA
+ *      TLS_PSK_WITH_RC4_128_SHA
+ */
+#define POLARSSL_ARC4_C
+
+/**
+ * \def POLARSSL_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 POLARSSL_ASN1_PARSE_C
+
+/**
+ * \def POLARSSL_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 POLARSSL_ASN1_WRITE_C
+
+/**
+ * \def POLARSSL_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 POLARSSL_BASE64_C
+
+/**
+ * \def POLARSSL_BIGNUM_C
+ *
+ * Enable the multi-precision integer library.
+ *
+ * Module:  library/bignum.c
+ * Caller:  library/dhm.c
+ *          library/ecp.c
+ *          library/rsa.c
+ *          library/ssl_tls.c
+ *
+ * This module is required for RSA and DHM support.
+ */
+#define POLARSSL_BIGNUM_C
+
+/**
+ * \def POLARSSL_BLOWFISH_C
+ *
+ * Enable the Blowfish block cipher.
+ *
+ * Module:  library/blowfish.c
+ */
+#define POLARSSL_BLOWFISH_C
+
+/**
+ * \def POLARSSL_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):
+ *      TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
+ *      TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
+ *      TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
+ *      TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ *      TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
+ *      TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
+ *      TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
+ *      TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ *      TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ *      TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ */
+#define POLARSSL_CAMELLIA_C
+
+/**
+ * \def POLARSSL_CERTS_C
+ *
+ * Enable the test certificates.
+ *
+ * Module:  library/certs.c
+ * Caller:
+ *
+ * Requires: POLARSSL_PEM_PARSE_C
+ *
+ * This module is used for testing (ssl_client/server).
+ */
+#define POLARSSL_CERTS_C
+
+/**
+ * \def POLARSSL_CIPHER_C
+ *
+ * Enable the generic cipher layer.
+ *
+ * Module:  library/cipher.c
+ * Caller:  library/ssl_tls.c
+ *
+ * Uncomment to enable generic cipher wrappers.
+ */
+#define POLARSSL_CIPHER_C
+
+/**
+ * \def POLARSSL_CTR_DRBG_C
+ *
+ * Enable the CTR_DRBG AES-256-based random generator.
+ *
+ * Module:  library/ctr_drbg.c
+ * Caller:
+ *
+ * Requires: POLARSSL_AES_C
+ *
+ * This module provides the CTR_DRBG AES-256 random number generator.
+ */
+#define POLARSSL_CTR_DRBG_C
+
+/**
+ * \def POLARSSL_DEBUG_C
+ *
+ * Enable the debug functions.
+ *
+ * Module:  library/debug.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *          library/ssl_tls.c
+ *
+ * This module provides debugging functions.
+ */
+#define POLARSSL_DEBUG_C
+
+/**
+ * \def POLARSSL_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):
+ *      TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
+ *      TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
+ *      TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
+ *      TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
+ *      TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
+ *      TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA
+ *      TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA
+ *      TLS_RSA_WITH_3DES_EDE_CBC_SHA
+ *      TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA
+ *      TLS_PSK_WITH_3DES_EDE_CBC_SHA
+ *
+ * PEM_PARSE uses DES/3DES for decrypting encrypted keys.
+ */
+#define POLARSSL_DES_C
+
+/**
+ * \def POLARSSL_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
+ */
+#define POLARSSL_DHM_C
+
+/**
+ * \def POLARSSL_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: POLARSSL_ECP_C
+ */
+#define POLARSSL_ECDH_C
+
+/**
+ * \def POLARSSL_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: POLARSSL_ECP_C, POLARSSL_ASN1_WRITE_C, POLARSSL_ASN1_PARSE_C
+ */
+#define POLARSSL_ECDSA_C
+
+/**
+ * \def POLARSSL_ECP_C
+ *
+ * Enable the elliptic curve over GF(p) library.
+ *
+ * Module:  library/ecp.c
+ * Caller:  library/ecdh.c
+ *          library/ecdsa.c
+ *
+ * Requires: POLARSSL_BIGNUM_C and at least one POLARSSL_ECP_DP_XXX_ENABLED
+ */
+#define POLARSSL_ECP_C
+
+/**
+ * \def POLARSSL_ENTROPY_C
+ *
+ * Enable the platform-specific entropy code.
+ *
+ * Module:  library/entropy.c
+ * Caller:
+ *
+ * Requires: POLARSSL_SHA512_C or POLARSSL_SHA256_C
+ *
+ * This module provides a generic entropy pool
+ */
+#define POLARSSL_ENTROPY_C
+
+/**
+ * \def POLARSSL_ERROR_C
+ *
+ * Enable error code to error string conversion.
+ *
+ * Module:  library/error.c
+ * Caller:
+ *
+ * This module enables polarssl_strerror().
+ */
+#define POLARSSL_ERROR_C
+
+/**
+ * \def POLARSSL_GCM_C
+ *
+ * Enable the Galois/Counter Mode (GCM) for AES.
+ *
+ * Module:  library/gcm.c
+ *
+ * Requires: POLARSSL_AES_C or POLARSSL_CAMELLIA_C
+ *
+ * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other
+ * requisites are enabled as well.
+ */
+#define POLARSSL_GCM_C
+
+/**
+ * \def POLARSSL_HAVEGE_C
+ *
+ * Enable the HAVEGE random generator.
+ *
+ * Warning: the HAVEGE random generator is not suitable for virtualized
+ *          environments
+ *
+ * Warning: the HAVEGE random generator is dependent on timing and specific
+ *          processor traits. It is therefore not advised to use HAVEGE as
+ *          your applications primary random generator or primary entropy pool
+ *          input. As a secondary input to your entropy pool, it IS able add
+ *          the (limited) extra entropy it provides.
+ *
+ * Module:  library/havege.c
+ * Caller:
+ *
+ * Requires: POLARSSL_TIMING_C
+ *
+ * Uncomment to enable the HAVEGE random generator.
+ */
+//#define POLARSSL_HAVEGE_C
+
+/**
+ * \def POLARSSL_HMAC_DRBG_C
+ *
+ * Enable the HMAC_DRBG random generator.
+ *
+ * Module:  library/hmac_drbg.c
+ * Caller:
+ *
+ * Requires: POLARSSL_MD_C
+ *
+ * Uncomment to enable the HMAC_DRBG random number geerator.
+ */
+#define POLARSSL_HMAC_DRBG_C
+
+/**
+ * \def POLARSSL_MD_C
+ *
+ * Enable the generic message digest layer.
+ *
+ * Module:  library/md.c
+ * Caller:
+ *
+ * Uncomment to enable generic message digest wrappers.
+ */
+#define POLARSSL_MD_C
+
+/**
+ * \def POLARSSL_MD2_C
+ *
+ * Enable the MD2 hash algorithm.
+ *
+ * Module:  library/md2.c
+ * Caller:
+ *
+ * Uncomment to enable support for (rare) MD2-signed X.509 certs.
+ */
+//#define POLARSSL_MD2_C
+
+/**
+ * \def POLARSSL_MD4_C
+ *
+ * Enable the MD4 hash algorithm.
+ *
+ * Module:  library/md4.c
+ * Caller:
+ *
+ * Uncomment to enable support for (rare) MD4-signed X.509 certs.
+ */
+//#define POLARSSL_MD4_C
+
+/**
+ * \def POLARSSL_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 and X.509.
+ * PEM_PARSE uses MD5 for decrypting encrypted keys.
+ */
+#define POLARSSL_MD5_C
+
+/**
+ * \def POLARSSL_MEMORY_C
+ * Deprecated since 1.3.5. Please use POLARSSL_PLATFORM_MEMORY instead.
+ */
+//#define POLARSSL_MEMORY_C
+
+/**
+ * \def POLARSSL_MEMORY_BUFFER_ALLOC_C
+ *
+ * Enable the buffer allocator implementation that makes use of a (stack)
+ * based buffer to 'allocate' dynamic memory. (replaces malloc() and free()
+ * calls)
+ *
+ * Module:  library/memory_buffer_alloc.c
+ *
+ * Requires: POLARSSL_PLATFORM_C
+ *           POLARSSL_PLATFORM_MEMORY (to use it within PolarSSL)
+ *
+ * Enable this module to enable the buffer memory allocator.
+ */
+//#define POLARSSL_MEMORY_BUFFER_ALLOC_C
+
+/**
+ * \def POLARSSL_NET_C
+ *
+ * Enable the TCP/IP networking routines.
+ *
+ * Module:  library/net.c
+ *
+ * This module provides TCP/IP networking routines.
+ */
+#define POLARSSL_NET_C
+
+/**
+ * \def POLARSSL_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 POLARSSL_OID_C
+
+/**
+ * \def POLARSSL_PADLOCK_C
+ *
+ * Enable VIA Padlock support on x86.
+ *
+ * Module:  library/padlock.c
+ * Caller:  library/aes.c
+ *
+ * Requires: POLARSSL_HAVE_ASM
+ *
+ * This modules adds support for the VIA PadLock on x86.
+ */
+#define POLARSSL_PADLOCK_C
+
+/**
+ * \def POLARSSL_PBKDF2_C
+ *
+ * Enable PKCS#5 PBKDF2 key derivation function.
+ * DEPRECATED: Use POLARSSL_PKCS5_C instead
+ *
+ * Module:  library/pbkdf2.c
+ *
+ * Requires: POLARSSL_PKCS5_C
+ *
+ * This module adds support for the PKCS#5 PBKDF2 key derivation function.
+ */
+#define POLARSSL_PBKDF2_C
+
+/**
+ * \def POLARSSL_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: POLARSSL_BASE64_C
+ *
+ * This modules adds support for decoding / parsing PEM files.
+ */
+#define POLARSSL_PEM_PARSE_C
+
+/**
+ * \def POLARSSL_PEM_WRITE_C
+ *
+ * Enable PEM encoding / writing.
+ *
+ * Module:  library/pem.c
+ * Caller:  library/pkwrite.c
+ *          library/x509write_crt.c
+ *          library/x509write_csr.c
+ *
+ * Requires: POLARSSL_BASE64_C
+ *
+ * This modules adds support for encoding / writing PEM files.
+ */
+#define POLARSSL_PEM_WRITE_C
+
+/**
+ * \def POLARSSL_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: POLARSSL_RSA_C or POLARSSL_ECP_C
+ *
+ * Uncomment to enable generic public key wrappers.
+ */
+#define POLARSSL_PK_C
+
+/**
+ * \def POLARSSL_PK_PARSE_C
+ *
+ * Enable the generic public (asymetric) key parser.
+ *
+ * Module:  library/pkparse.c
+ * Caller:  library/x509_crt.c
+ *          library/x509_csr.c
+ *
+ * Requires: POLARSSL_PK_C
+ *
+ * Uncomment to enable generic public key parse functions.
+ */
+#define POLARSSL_PK_PARSE_C
+
+/**
+ * \def POLARSSL_PK_WRITE_C
+ *
+ * Enable the generic public (asymetric) key writer.
+ *
+ * Module:  library/pkwrite.c
+ * Caller:  library/x509write.c
+ *
+ * Requires: POLARSSL_PK_C
+ *
+ * Uncomment to enable generic public key write functions.
+ */
+#define POLARSSL_PK_WRITE_C
+
+/**
+ * \def POLARSSL_PKCS5_C
+ *
+ * Enable PKCS#5 functions.
+ *
+ * Module:  library/pkcs5.c
+ *
+ * Requires: POLARSSL_MD_C
+ *
+ * This module adds support for the PKCS#5 functions.
+ */
+#define POLARSSL_PKCS5_C
+
+/**
+ * \def POLARSSL_PKCS11_C
+ *
+ * Enable wrapper for PKCS#11 smartcard support.
+ *
+ * Module:  library/pkcs11.c
+ * Caller:  library/pk.c
+ *
+ * Requires: POLARSSL_PK_C
+ *
+ * This module enables SSL/TLS PKCS #11 smartcard support.
+ * Requires the presence of the PKCS#11 helper library (libpkcs11-helper)
+ */
+//#define POLARSSL_PKCS11_C
+
+/**
+ * \def POLARSSL_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: POLARSSL_ASN1_PARSE_C, POLARSSL_CIPHER_C, POLARSSL_MD_C
+ * Can use:  POLARSSL_ARC4_C
+ *
+ * This module enables PKCS#12 functions.
+ */
+#define POLARSSL_PKCS12_C
+
+/**
+ * \def POLARSSL_PLATFORM_C
+ *
+ * Enable the platform abstraction layer that allows you to re-assign
+ * functions like malloc(), free(), printf(), fprintf()
+ *
+ * Module:  library/platform.c
+ * Caller:  Most other .c files
+ *
+ * This module enables abstraction of common (libc) functions.
+ */
+#define POLARSSL_PLATFORM_C
+
+/**
+ * \def POLARSSL_RIPEMD160_C
+ *
+ * Enable the RIPEMD-160 hash algorithm.
+ *
+ * Module:  library/ripemd160.c
+ * Caller:  library/md.c
+ *
+ */
+#define POLARSSL_RIPEMD160_C
+
+/**
+ * \def POLARSSL_RSA_C
+ *
+ * Enable the RSA public-key cryptosystem.
+ *
+ * Module:  library/rsa.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: POLARSSL_BIGNUM_C, POLARSSL_OID_C
+ */
+#define POLARSSL_RSA_C
+
+/**
+ * \def POLARSSL_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 and SHA1-signed certificates.
+ */
+#define POLARSSL_SHA1_C
+
+/**
+ * \def POLARSSL_SHA256_C
+ *
+ * Enable the SHA-224 and SHA-256 cryptographic hash algorithms.
+ * (Used to be POLARSSL_SHA2_C)
+ *
+ * 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 POLARSSL_SHA256_C
+
+/**
+ * \def POLARSSL_SHA512_C
+ *
+ * Enable the SHA-384 and SHA-512 cryptographic hash algorithms.
+ * (Used to be POLARSSL_SHA4_C)
+ *
+ * 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 POLARSSL_SHA512_C
+
+/**
+ * \def POLARSSL_SSL_CACHE_C
+ *
+ * Enable simple SSL cache implementation.
+ *
+ * Module:  library/ssl_cache.c
+ * Caller:
+ *
+ * Requires: POLARSSL_SSL_CACHE_C
+ */
+#define POLARSSL_SSL_CACHE_C
+
+/**
+ * \def POLARSSL_SSL_CLI_C
+ *
+ * Enable the SSL/TLS client code.
+ *
+ * Module:  library/ssl_cli.c
+ * Caller:
+ *
+ * Requires: POLARSSL_SSL_TLS_C
+ *
+ * This module is required for SSL/TLS client support.
+ */
+#define POLARSSL_SSL_CLI_C
+
+/**
+ * \def POLARSSL_SSL_SRV_C
+ *
+ * Enable the SSL/TLS server code.
+ *
+ * Module:  library/ssl_srv.c
+ * Caller:
+ *
+ * Requires: POLARSSL_SSL_TLS_C
+ *
+ * This module is required for SSL/TLS server support.
+ */
+#define POLARSSL_SSL_SRV_C
+
+/**
+ * \def POLARSSL_SSL_TLS_C
+ *
+ * Enable the generic SSL/TLS code.
+ *
+ * Module:  library/ssl_tls.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *
+ * Requires: POLARSSL_CIPHER_C, POLARSSL_MD_C
+ *           and at least one of the POLARSSL_SSL_PROTO_* defines
+ *
+ * This module is required for SSL/TLS.
+ */
+#define POLARSSL_SSL_TLS_C
+
+/**
+ * \def POLARSSL_THREADING_C
+ *
+ * Enable the threading abstraction layer.
+ * By default PolarSSL 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.
+ *
+ * Module:  library/threading.c
+ *
+ * This allows different threading implementations (self-implemented or
+ * provided).
+ *
+ * You will have to enable either POLARSSL_THREADING_ALT or
+ * POLARSSL_THREADING_PTHREAD.
+ *
+ * Enable this layer to allow use of mutexes within PolarSSL
+ */
+//#define POLARSSL_THREADING_C
+
+/**
+ * \def POLARSSL_TIMING_C
+ *
+ * Enable the portable timing interface.
+ *
+ * Module:  library/timing.c
+ * Caller:  library/havege.c
+ *
+ * This module is used by the HAVEGE random number generator.
+ */
+#define POLARSSL_TIMING_C
+
+/**
+ * \def POLARSSL_VERSION_C
+ *
+ * Enable run-time version information.
+ *
+ * Module:  library/version.c
+ *
+ * This module provides run-time version information.
+ */
+#define POLARSSL_VERSION_C
+
+/**
+ * \def POLARSSL_X509_USE_C
+ *
+ * Enable X.509 core for using certificates.
+ *
+ * Module:  library/x509.c
+ * Caller:  library/x509_crl.c
+ *          library/x509_crt.c
+ *          library/x509_csr.c
+ *
+ * Requires: POLARSSL_ASN1_PARSE_C, POLARSSL_BIGNUM_C, POLARSSL_OID_C,
+ *           POLARSSL_PK_PARSE_C
+ *
+ * This module is required for the X.509 parsing modules.
+ */
+#define POLARSSL_X509_USE_C
+
+/**
+ * \def POLARSSL_X509_CRT_PARSE_C
+ *
+ * Enable X.509 certificate parsing.
+ *
+ * Module:  library/x509_crt.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *          library/ssl_tls.c
+ *
+ * Requires: POLARSSL_X509_USE_C
+ *
+ * This module is required for X.509 certificate parsing.
+ */
+#define POLARSSL_X509_CRT_PARSE_C
+
+/**
+ * \def POLARSSL_X509_CRL_PARSE_C
+ *
+ * Enable X.509 CRL parsing.
+ *
+ * Module:  library/x509_crl.c
+ * Caller:  library/x509_crt.c
+ *
+ * Requires: POLARSSL_X509_USE_C
+ *
+ * This module is required for X.509 CRL parsing.
+ */
+#define POLARSSL_X509_CRL_PARSE_C
+
+/**
+ * \def POLARSSL_X509_CSR_PARSE_C
+ *
+ * Enable X.509 Certificate Signing Request (CSR) parsing.
+ *
+ * Module:  library/x509_csr.c
+ * Caller:  library/x509_crt_write.c
+ *
+ * Requires: POLARSSL_X509_USE_C
+ *
+ * This module is used for reading X.509 certificate request.
+ */
+#define POLARSSL_X509_CSR_PARSE_C
+
+/**
+ * \def POLARSSL_X509_CREATE_C
+ *
+ * Enable X.509 core for creating certificates.
+ *
+ * Module:  library/x509_create.c
+ *
+ * Requires: POLARSSL_BIGNUM_C, POLARSSL_OID_C, POLARSSL_PK_WRITE_C
+ *
+ * This module is the basis for creating X.509 certificates and CSRs.
+ */
+#define POLARSSL_X509_CREATE_C
+
+/**
+ * \def POLARSSL_X509_CRT_WRITE_C
+ *
+ * Enable creating X.509 certificates.
+ *
+ * Module:  library/x509_crt_write.c
+ *
+ * Requires: POLARSSL_CREATE_C
+ *
+ * This module is required for X.509 certificate creation.
+ */
+#define POLARSSL_X509_CRT_WRITE_C
+
+/**
+ * \def POLARSSL_X509_CSR_WRITE_C
+ *
+ * Enable creating X.509 Certificate Signing Requests (CSR).
+ *
+ * Module:  library/x509_csr_write.c
+ *
+ * Requires: POLARSSL_CREATE_C
+ *
+ * This module is required for X.509 certificate request writing.
+ */
+#define POLARSSL_X509_CSR_WRITE_C
+
+/**
+ * \def POLARSSL_XTEA_C
+ *
+ * Enable the XTEA block cipher.
+ *
+ * Module:  library/xtea.c
+ * Caller:
+ */
+#define POLARSSL_XTEA_C
+
+/* \} name SECTION: PolarSSL 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 POLARSSL_MPI_WINDOW_SIZE            6 /**< Maximum windows size used. */
+//#define POLARSSL_MPI_MAX_SIZE             512 /**< Maximum number of bytes for usable MPIs. */
+
+/* CTR_DRBG options */
+//#define CTR_DRBG_ENTROPY_LEN               48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */
+//#define CTR_DRBG_RESEED_INTERVAL        10000 /**< Interval before reseed is performed by default */
+//#define CTR_DRBG_MAX_INPUT                256 /**< Maximum number of additional input bytes */
+//#define CTR_DRBG_MAX_REQUEST             1024 /**< Maximum number of requested bytes per call */
+//#define CTR_DRBG_MAX_SEED_INPUT           384 /**< Maximum size of (re)seed buffer */
+
+/* HMAC_DRBG options */
+//#define POLARSSL_HMAC_DRBG_RESEED_INTERVAL   10000 /**< Interval before reseed is performed by default */
+//#define POLARSSL_HMAC_DRBG_MAX_INPUT           256 /**< Maximum number of additional input bytes */
+//#define POLARSSL_HMAC_DRBG_MAX_REQUEST        1024 /**< Maximum number of requested bytes per call */
+//#define POLARSSL_HMAC_DRBG_MAX_SEED_INPUT      384 /**< Maximum size of (re)seed buffer */
+
+/* ECP options */
+//#define POLARSSL_ECP_MAX_BITS             521 /**< Maximum bit size of groups */
+//#define POLARSSL_ECP_WINDOW_SIZE            6 /**< Maximum window size used */
+//#define POLARSSL_ECP_FIXED_POINT_OPTIM      1 /**< Enable fixed-point speed-up */
+
+/* Entropy options */
+//#define ENTROPY_MAX_SOURCES                20 /**< Maximum number of sources supported */
+//#define ENTROPY_MAX_GATHER                128 /**< Maximum amount requested from entropy sources */
+
+/* Memory buffer allocator options */
+//#define MEMORY_ALIGN_MULTIPLE               4 /**< Align on multiples of this value */
+
+/* Platform options */
+//#define POLARSSL_PLATFORM_STD_MEM_HDR <stdlib.h> /**< Header to include if POLARSSL_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */
+//#define POLARSSL_PLATFORM_STD_MALLOC   malloc /**< Default allocator to use, can be undefined */
+//#define POLARSSL_PLATFORM_STD_FREE       free /**< Default free to use, can be undefined */
+//#define POLARSSL_PLATFORM_STD_PRINTF   printf /**< Default printf to use, can be undefined */
+//#define POLARSSL_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use, can be undefined */
+
+/* SSL Cache options */
+//#define SSL_CACHE_DEFAULT_TIMEOUT       86400 /**< 1 day  */
+//#define SSL_CACHE_DEFAULT_MAX_ENTRIES      50 /**< Maximum entries in cache */
+
+/* SSL options */
+//#define SSL_MAX_CONTENT_LEN             16384 /**< Size of the input / output buffer */
+//#define SSL_DEFAULT_TICKET_LIFETIME     86400 /**< Lifetime of session tickets (if enabled) */
+
+/* Debug options */
+//#define POLARSSL_DEBUG_DFL_MODE POLARSSL_DEBUG_LOG_FULL /**< Default log: Full or Raw */
+
+/* \} name SECTION: Module configuration options */
+
+#include "check_config.h"
+
+#endif /* POLARSSL_CONFIG_H */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/ctr_drbg.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,269 @@
+/**
+ * \file ctr_drbg.h
+ *
+ * \brief CTR_DRBG based on AES-256 (NIST SP 800-90)
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_CTR_DRBG_H
+#define POLARSSL_CTR_DRBG_H
+
+#include <string.h>
+
+#include "aes.h"
+
+#define POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED        -0x0034  /**< The entropy source failed. */
+#define POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG              -0x0036  /**< Too many random requested in single call. */
+#define POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG                -0x0038  /**< Input too large (Entropy + additional). */
+#define POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR                -0x003A  /**< Read/write error in file. */
+
+#define CTR_DRBG_BLOCKSIZE          16      /**< Block size used by the cipher                  */
+#define CTR_DRBG_KEYSIZE            32      /**< Key size used by the cipher                    */
+#define CTR_DRBG_KEYBITS            ( CTR_DRBG_KEYSIZE * 8 )
+#define CTR_DRBG_SEEDLEN            ( CTR_DRBG_KEYSIZE + CTR_DRBG_BLOCKSIZE )
+                                            /**< The seed length (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 on the compiler command line.
+ * \{
+ */
+
+#if !defined(CTR_DRBG_ENTROPY_LEN)
+#if defined(POLARSSL_SHA512_C) && !defined(POLARSSL_ENTROPY_FORCE_SHA256)
+#define CTR_DRBG_ENTROPY_LEN        48      /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */
+#else
+#define CTR_DRBG_ENTROPY_LEN        32      /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */
+#endif
+#endif
+
+#if !defined(CTR_DRBG_RESEED_INTERVAL)
+#define CTR_DRBG_RESEED_INTERVAL    10000   /**< Interval before reseed is performed by default */
+#endif
+
+#if !defined(CTR_DRBG_MAX_INPUT)
+#define CTR_DRBG_MAX_INPUT          256     /**< Maximum number of additional input bytes */
+#endif
+
+#if !defined(CTR_DRBG_MAX_REQUEST)
+#define CTR_DRBG_MAX_REQUEST        1024    /**< Maximum number of requested bytes per call */
+#endif
+
+#if !defined(CTR_DRBG_MAX_SEED_INPUT)
+#define CTR_DRBG_MAX_SEED_INPUT     384     /**< Maximum size of (re)seed buffer */
+#endif
+
+/* \} name SECTION: Module settings */
+
+#define CTR_DRBG_PR_OFF             0       /**< No prediction resistance       */
+#define CTR_DRBG_PR_ON              1       /**< Prediction resistance enabled  */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          CTR_DRBG context structure
+ */
+typedef struct
+{
+    unsigned char counter[16];  /*!<  counter (V)       */
+    int reseed_counter;         /*!<  reseed counter    */
+    int prediction_resistance;  /*!<  enable prediction resistance (Automatic
+                                      reseed before every random generation)  */
+    size_t entropy_len;         /*!<  amount of entropy grabbed on each
+                                      (re)seed          */
+    int reseed_interval;        /*!<  reseed interval   */
+
+    aes_context aes_ctx;        /*!<  AES context       */
+
+    /*
+     * Callbacks (Entropy)
+     */
+    int (*f_entropy)(void *, unsigned char *, size_t);
+
+    void *p_entropy;            /*!<  context for the entropy function */
+}
+ctr_drbg_context;
+
+/**
+ * \brief               CTR_DRBG initialization
+ *
+ * Note: Personalization data can be provided in addition to the more generic
+ *       entropy source to make this instantiation as unique as possible.
+ *
+ * \param ctx           CTR_DRBG context to be initialized
+ * \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
+ *
+ * \return              0 if successful, or
+ *                      POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED
+ */
+int ctr_drbg_init( ctr_drbg_context *ctx,
+                   int (*f_entropy)(void *, unsigned char *, size_t),
+                   void *p_entropy,
+                   const unsigned char *custom,
+                   size_t 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           CTR_DRBG context
+ * \param resistance    CTR_DRBG_PR_ON or CTR_DRBG_PR_OFF
+ */
+void ctr_drbg_set_prediction_resistance( ctr_drbg_context *ctx,
+                                         int resistance );
+
+/**
+ * \brief               Set the amount of entropy grabbed on each (re)seed
+ *                      (Default: CTR_DRBG_ENTROPY_LEN)
+ *
+ * \param ctx           CTR_DRBG context
+ * \param len           Amount of entropy to grab
+ */
+void ctr_drbg_set_entropy_len( ctr_drbg_context *ctx,
+                               size_t len );
+
+/**
+ * \brief               Set the reseed interval
+ *                      (Default: CTR_DRBG_RESEED_INTERVAL)
+ *
+ * \param ctx           CTR_DRBG context
+ * \param interval      Reseed interval
+ */
+void ctr_drbg_set_reseed_interval( ctr_drbg_context *ctx,
+                                   int interval );
+
+/**
+ * \brief               CTR_DRBG reseeding (extracts data from entropy source)
+ *
+ * \param ctx           CTR_DRBG context
+ * \param additional    Additional data to add to state (Can be NULL)
+ * \param len           Length of additional data
+ *
+ * \return              0 if successful, or
+ *                      POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED
+ */
+int ctr_drbg_reseed( ctr_drbg_context *ctx,
+                     const unsigned char *additional, size_t len );
+
+/**
+ * \brief               CTR_DRBG update state
+ *
+ * \param ctx           CTR_DRBG context
+ * \param additional    Additional data to update state with
+ * \param add_len       Length of additional data
+ */
+void ctr_drbg_update( ctr_drbg_context *ctx,
+                      const unsigned char *additional, size_t add_len );
+
+/**
+ * \brief               CTR_DRBG generate random with additional update input
+ *
+ * Note: Automatically reseeds if reseed_counter is reached.
+ *
+ * \param p_rng         CTR_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
+ *
+ * \return              0 if successful, or
+ *                      POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED, or
+ *                      POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG
+ */
+int ctr_drbg_random_with_add( void *p_rng,
+                              unsigned char *output, size_t output_len,
+                              const unsigned char *additional, size_t add_len );
+
+/**
+ * \brief               CTR_DRBG generate random
+ *
+ * Note: Automatically reseeds if reseed_counter is reached.
+ *
+ * \param p_rng         CTR_DRBG context
+ * \param output        Buffer to fill
+ * \param output_len    Length of the buffer
+ *
+ * \return              0 if successful, or
+ *                      POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED, or
+ *                      POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG
+ */
+int ctr_drbg_random( void *p_rng,
+                     unsigned char *output, size_t output_len );
+
+#if defined(POLARSSL_FS_IO)
+/**
+ * \brief               Write a seed file
+ *
+ * \param ctx           CTR_DRBG context
+ * \param path          Name of the file
+ *
+ * \return              0 if successful,
+ *                      POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR on file error, or
+ *                      POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED
+ */
+int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path );
+
+/**
+ * \brief               Read and update a seed file. Seed is added to this
+ *                      instance
+ *
+ * \param ctx           CTR_DRBG context
+ * \param path          Name of the file
+ *
+ * \return              0 if successful,
+ *                      POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR on file error,
+ *                      POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or
+ *                      POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG
+ */
+int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path );
+#endif /* POLARSSL_FS_IO */
+
+/**
+ * \brief               Checkup routine
+ *
+ * \return              0 if successful, or 1 if the test failed
+ */
+int ctr_drbg_self_test( int verbose );
+
+/* Internal functions (do not call directly) */
+int ctr_drbg_init_entropy_len( ctr_drbg_context *,
+                               int (*)(void *, unsigned char *, size_t), void *,
+                               const unsigned char *, size_t, size_t );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ctr_drbg.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/debug.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,154 @@
+/**
+ * \file debug.h
+ *
+ * \brief Debug functions
+ *
+ *  Copyright (C) 2006-2011, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_DEBUG_H
+#define POLARSSL_DEBUG_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+#include "ssl.h"
+#if defined(POLARSSL_ECP_C)
+#include "ecp.h"
+#endif
+
+#if defined(POLARSSL_DEBUG_C)
+
+#define POLARSSL_DEBUG_LOG_FULL         0 /**< Include file:line in log lines */
+#define POLARSSL_DEBUG_LOG_RAW          1 /**< Only log raw debug lines */
+
+/**
+ * \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(POLARSSL_DEBUG_DFL_MODE)
+#define POLARSSL_DEBUG_DFL_MODE POLARSSL_DEBUG_LOG_FULL /**< Default log: Full or Raw */
+#endif
+
+/* \} name SECTION: Module settings */
+
+
+#define SSL_DEBUG_MSG( level, args )                    \
+    debug_print_msg( ssl, level, __FILE__, __LINE__, debug_fmt args );
+
+#define SSL_DEBUG_RET( level, text, ret )                \
+    debug_print_ret( ssl, level, __FILE__, __LINE__, text, ret );
+
+#define SSL_DEBUG_BUF( level, text, buf, len )           \
+    debug_print_buf( ssl, level, __FILE__, __LINE__, text, buf, len );
+
+#if defined(POLARSSL_BIGNUM_C)
+#define SSL_DEBUG_MPI( level, text, X )                  \
+    debug_print_mpi( ssl, level, __FILE__, __LINE__, text, X );
+#endif
+
+#if defined(POLARSSL_ECP_C)
+#define SSL_DEBUG_ECP( level, text, X )                  \
+    debug_print_ecp( ssl, level, __FILE__, __LINE__, text, X );
+#endif
+
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+#define SSL_DEBUG_CRT( level, text, crt )                \
+    debug_print_crt( ssl, level, __FILE__, __LINE__, text, crt );
+#endif
+
+#else /* POLARSSL_DEBUG_ C */
+
+#define SSL_DEBUG_MSG( level, args )            do { } while( 0 )
+#define SSL_DEBUG_RET( level, text, ret )       do { } while( 0 )
+#define SSL_DEBUG_BUF( level, text, buf, len )  do { } while( 0 )
+#define SSL_DEBUG_MPI( level, text, X )         do { } while( 0 )
+#define SSL_DEBUG_ECP( level, text, X )         do { } while( 0 )
+#define SSL_DEBUG_CRT( level, text, crt )       do { } while( 0 )
+
+#endif /* POLARSSL_DEBUG_C */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief   Set the log mode for the debug functions globally
+ *          (Default value: POLARSSL_DEBUG_DFL_MODE)
+ *
+ * \param log_mode      The log mode to use (POLARSSL_DEBUG_LOG_FULL or
+ *                                           POLARSSL_DEBUG_LOG_RAW)
+ */
+void debug_set_log_mode( int log_mode );
+
+/**
+ * \brief   Set the level threshold to handle globally. Messages that have a
+ *          level over the threshold value are ignored.
+ *          (Default value: 0 (No debug))
+ *
+ * \param threshold     maximum level of messages to pass on
+ */
+void debug_set_threshold( int threshold );
+
+char *debug_fmt( const char *format, ... );
+
+void debug_print_msg( const ssl_context *ssl, int level,
+                      const char *file, int line, const char *text );
+
+void debug_print_ret( const ssl_context *ssl, int level,
+                      const char *file, int line,
+                      const char *text, int ret );
+
+void debug_print_buf( const ssl_context *ssl, int level,
+                      const char *file, int line, const char *text,
+                      unsigned char *buf, size_t len );
+
+#if defined(POLARSSL_BIGNUM_C)
+void debug_print_mpi( const ssl_context *ssl, int level,
+                      const char *file, int line,
+                      const char *text, const mpi *X );
+#endif
+
+#if defined(POLARSSL_ECP_C)
+void debug_print_ecp( const ssl_context *ssl, int level,
+                      const char *file, int line,
+                      const char *text, const ecp_point *X );
+#endif
+
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+void debug_print_crt( const ssl_context *ssl, int level,
+                      const char *file, int line,
+                      const char *text, const x509_crt *crt );
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* debug.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/des.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,266 @@
+/**
+ * \file des.h
+ *
+ * \brief DES block cipher
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_DES_H
+#define POLARSSL_DES_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#include <string.h>
+
+#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
+#include <basetsd.h>
+typedef UINT32 uint32_t;
+#else
+#include <inttypes.h>
+#endif
+
+#define DES_ENCRYPT     1
+#define DES_DECRYPT     0
+
+#define POLARSSL_ERR_DES_INVALID_INPUT_LENGTH              -0x0032  /**< The data input has an invalid length. */
+
+#define DES_KEY_SIZE    8
+
+#if !defined(POLARSSL_DES_ALT)
+// Regular implementation
+//
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          DES context structure
+ */
+typedef struct
+{
+    int mode;                   /*!<  encrypt/decrypt   */
+    uint32_t sk[32];            /*!<  DES subkeys       */
+}
+des_context;
+
+/**
+ * \brief          Triple-DES context structure
+ */
+typedef struct
+{
+    int mode;                   /*!<  encrypt/decrypt   */
+    uint32_t sk[96];            /*!<  3DES subkeys      */
+}
+des3_context;
+
+/**
+ * \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
+ */
+void des_key_set_parity( unsigned char key[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.
+ */
+int des_key_check_key_parity( const unsigned char key[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.
+ */
+int des_key_check_weak( const unsigned char key[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
+ */
+int des_setkey_enc( des_context *ctx, const unsigned char key[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
+ */
+int des_setkey_dec( des_context *ctx, const unsigned char key[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 des3_set2key_enc( des3_context *ctx,
+                      const unsigned char key[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 des3_set2key_dec( des3_context *ctx,
+                      const unsigned char key[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 des3_set3key_enc( des3_context *ctx,
+                      const unsigned char key[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 des3_set3key_dec( des3_context *ctx,
+                      const unsigned char key[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
+ */
+int des_crypt_ecb( des_context *ctx,
+                    const unsigned char input[8],
+                    unsigned char output[8] );
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+/**
+ * \brief          DES-CBC buffer encryption/decryption
+ *
+ * \param ctx      DES context
+ * \param mode     DES_ENCRYPT or 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
+ */
+int des_crypt_cbc( des_context *ctx,
+                    int mode,
+                    size_t length,
+                    unsigned char iv[8],
+                    const unsigned char *input,
+                    unsigned char *output );
+#endif /* POLARSSL_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 des3_crypt_ecb( des3_context *ctx,
+                     const unsigned char input[8],
+                     unsigned char output[8] );
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+/**
+ * \brief          3DES-CBC buffer encryption/decryption
+ *
+ * \param ctx      3DES context
+ * \param mode     DES_ENCRYPT or 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 POLARSSL_ERR_DES_INVALID_INPUT_LENGTH
+ */
+int des3_crypt_cbc( des3_context *ctx,
+                     int mode,
+                     size_t length,
+                     unsigned char iv[8],
+                     const unsigned char *input,
+                     unsigned char *output );
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+#ifdef __cplusplus
+}
+#endif
+
+#else  /* POLARSSL_DES_ALT */
+#include "des_alt.h"
+#endif /* POLARSSL_DES_ALT */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int des_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* des.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/dhm.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,290 @@
+/**
+ * \file dhm.h
+ *
+ * \brief Diffie-Hellman-Merkle key exchange
+ *
+ *  Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_DHM_H
+#define POLARSSL_DHM_H
+
+#include "bignum.h"
+
+/*
+ * DHM Error codes
+ */
+#define POLARSSL_ERR_DHM_BAD_INPUT_DATA                    -0x3080  /**< Bad input parameters to function. */
+#define POLARSSL_ERR_DHM_READ_PARAMS_FAILED                -0x3100  /**< Reading of the DHM parameters failed. */
+#define POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED                -0x3180  /**< Making of the DHM parameters failed. */
+#define POLARSSL_ERR_DHM_READ_PUBLIC_FAILED                -0x3200  /**< Reading of the public values failed. */
+#define POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED                -0x3280  /**< Making of the public value failed. */
+#define POLARSSL_ERR_DHM_CALC_SECRET_FAILED                -0x3300  /**< Calculation of the DHM secret failed. */
+#define POLARSSL_ERR_DHM_INVALID_FORMAT                    -0x3380  /**< The ASN.1 data is not formatted correctly. */
+#define POLARSSL_ERR_DHM_MALLOC_FAILED                     -0x3400  /**< Allocation of memory failed. */
+#define POLARSSL_ERR_DHM_FILE_IO_ERROR                     -0x3480  /**< Read/write of file failed. */
+
+/**
+ * RFC 3526 defines a number of standardized Diffie-Hellman groups
+ * for IKE.
+ * RFC 5114 defines a number of standardized Diffie-Hellman groups
+ * that can be used.
+ *
+ * Some are included here for convenience.
+ *
+ * Included are:
+ *  RFC 3526 3.    2048-bit MODP Group
+ *  RFC 3526 4.    3072-bit MODP Group
+ *  RFC 5114 2.1.  1024-bit MODP Group with 160-bit Prime Order Subgroup
+ *  RFC 5114 2.2.  2048-bit MODP Group with 224-bit Prime Order Subgroup
+ */
+#define POLARSSL_DHM_RFC3526_MODP_2048_P               \
+    "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
+    "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
+    "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
+    "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
+    "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \
+    "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \
+    "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \
+    "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \
+    "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \
+    "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \
+    "15728E5A8AACAA68FFFFFFFFFFFFFFFF"
+
+#define POLARSSL_DHM_RFC3526_MODP_2048_G          "02"
+
+#define POLARSSL_DHM_RFC3526_MODP_3072_P               \
+    "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
+    "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
+    "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
+    "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
+    "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \
+    "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \
+    "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \
+    "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \
+    "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \
+    "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \
+    "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \
+    "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \
+    "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \
+    "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \
+    "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \
+    "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF"
+
+#define POLARSSL_DHM_RFC3526_MODP_3072_G          "02"
+
+#define POLARSSL_DHM_RFC5114_MODP_1024_P               \
+    "B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C6" \
+    "9A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C0" \
+    "13ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD70" \
+    "98488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0" \
+    "A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708" \
+    "DF1FB2BC2E4A4371"
+
+#define POLARSSL_DHM_RFC5114_MODP_1024_G               \
+    "A4D1CBD5C3FD34126765A442EFB99905F8104DD258AC507F" \
+    "D6406CFF14266D31266FEA1E5C41564B777E690F5504F213" \
+    "160217B4B01B886A5E91547F9E2749F4D7FBD7D3B9A92EE1" \
+    "909D0D2263F80A76A6A24C087A091F531DBF0A0169B6A28A" \
+    "D662A4D18E73AFA32D779D5918D08BC8858F4DCEF97C2A24" \
+    "855E6EEB22B3B2E5"
+
+#define POLARSSL_DHM_RFC5114_MODP_2048_P               \
+    "AD107E1E9123A9D0D660FAA79559C51FA20D64E5683B9FD1" \
+    "B54B1597B61D0A75E6FA141DF95A56DBAF9A3C407BA1DF15" \
+    "EB3D688A309C180E1DE6B85A1274A0A66D3F8152AD6AC212" \
+    "9037C9EDEFDA4DF8D91E8FEF55B7394B7AD5B7D0B6C12207" \
+    "C9F98D11ED34DBF6C6BA0B2C8BBC27BE6A00E0A0B9C49708" \
+    "B3BF8A317091883681286130BC8985DB1602E714415D9330" \
+    "278273C7DE31EFDC7310F7121FD5A07415987D9ADC0A486D" \
+    "CDF93ACC44328387315D75E198C641A480CD86A1B9E587E8" \
+    "BE60E69CC928B2B9C52172E413042E9B23F10B0E16E79763" \
+    "C9B53DCF4BA80A29E3FB73C16B8E75B97EF363E2FFA31F71" \
+    "CF9DE5384E71B81C0AC4DFFE0C10E64F"
+
+#define POLARSSL_DHM_RFC5114_MODP_2048_G              \
+    "AC4032EF4F2D9AE39DF30B5C8FFDAC506CDEBE7B89998CAF"\
+    "74866A08CFE4FFE3A6824A4E10B9A6F0DD921F01A70C4AFA"\
+    "AB739D7700C29F52C57DB17C620A8652BE5E9001A8D66AD7"\
+    "C17669101999024AF4D027275AC1348BB8A762D0521BC98A"\
+    "E247150422EA1ED409939D54DA7460CDB5F6C6B250717CBE"\
+    "F180EB34118E98D119529A45D6F834566E3025E316A330EF"\
+    "BB77A86F0C1AB15B051AE3D428C8F8ACB70A8137150B8EEB"\
+    "10E183EDD19963DDD9E263E4770589EF6AA21E7F5F2FF381"\
+    "B539CCE3409D13CD566AFBB48D6C019181E1BCFE94B30269"\
+    "EDFE72FE9B6AA4BD7B5A0F1C71CFFF4C19C418E1F6EC0179"\
+    "81BC087F2A7065B384B890D3191F2BFA"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          DHM context structure
+ */
+typedef struct
+{
+    size_t len; /*!<  size(P) in chars  */
+    mpi P;      /*!<  prime modulus     */
+    mpi G;      /*!<  generator         */
+    mpi X;      /*!<  secret value      */
+    mpi GX;     /*!<  self = G^X mod P  */
+    mpi GY;     /*!<  peer = G^Y mod P  */
+    mpi K;      /*!<  key = GY^X mod P  */
+    mpi RP;     /*!<  cached R^2 mod P  */
+    mpi Vi;     /*!<  blinding value    */
+    mpi Vf;     /*!<  un-blinding value */
+    mpi pX;     /*!<  previous X        */
+}
+dhm_context;
+
+/**
+ * \brief          Parse the ServerKeyExchange parameters
+ *
+ * \param ctx      DHM context
+ * \param p        &(start of input buffer)
+ * \param end      end of buffer
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_DHM_XXX error code
+ */
+int dhm_read_params( dhm_context *ctx,
+                     unsigned char **p,
+                     const unsigned char *end );
+
+/**
+ * \brief          Setup and write the ServerKeyExchange parameters
+ *
+ * \param ctx      DHM context
+ * \param x_size   private value size in bytes
+ * \param output   destination buffer
+ * \param olen     number of chars written
+ * \param f_rng    RNG function
+ * \param p_rng    RNG parameter
+ *
+ * \note           This function assumes that ctx->P and ctx->G
+ *                 have already been properly set (for example
+ *                 using mpi_read_string or mpi_read_binary).
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_DHM_XXX error code
+ */
+int dhm_make_params( dhm_context *ctx, int x_size,
+                     unsigned char *output, size_t *olen,
+                     int (*f_rng)(void *, unsigned char *, size_t),
+                     void *p_rng );
+
+/**
+ * \brief          Import the peer's public value G^Y
+ *
+ * \param ctx      DHM context
+ * \param input    input buffer
+ * \param ilen     size of buffer
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_DHM_XXX error code
+ */
+int dhm_read_public( dhm_context *ctx,
+                     const unsigned char *input, size_t ilen );
+
+/**
+ * \brief          Create own private value X and export G^X
+ *
+ * \param ctx      DHM context
+ * \param x_size   private value size in bytes
+ * \param output   destination buffer
+ * \param olen     must be equal to ctx->P.len
+ * \param f_rng    RNG function
+ * \param p_rng    RNG parameter
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_DHM_XXX error code
+ */
+int dhm_make_public( dhm_context *ctx, int x_size,
+                     unsigned char *output, size_t olen,
+                     int (*f_rng)(void *, unsigned char *, size_t),
+                     void *p_rng );
+
+/**
+ * \brief          Derive and export the shared secret (G^Y)^X mod P
+ *
+ * \param ctx      DHM context
+ * \param output   destination buffer
+ * \param olen     number of chars written
+ * \param f_rng    RNG function, for blinding purposes
+ * \param p_rng    RNG parameter
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_DHM_XXX error code
+ *
+ * \note           If non-NULL, f_rng is used to blind the input as
+ *                 countermeasure against timing attacks. Blinding is
+ *                 automatically used if and only if our secret value X is
+ *                 re-used and costs nothing otherwise, so it is recommended
+ *                 to always pass a non-NULL f_rng argument.
+ */
+int dhm_calc_secret( dhm_context *ctx,
+                     unsigned char *output, size_t *olen,
+                     int (*f_rng)(void *, unsigned char *, size_t),
+                     void *p_rng );
+
+/**
+ * \brief          Free the components of a DHM key
+ */
+void dhm_free( dhm_context *ctx );
+
+#if defined(POLARSSL_ASN1_PARSE_C)
+/** \ingroup x509_module */
+/**
+ * \brief          Parse DHM parameters
+ *
+ * \param dhm      DHM context to be initialized
+ * \param dhmin    input buffer
+ * \param dhminlen size of the buffer
+ *
+ * \return         0 if successful, or a specific DHM or PEM error code
+ */
+int dhm_parse_dhm( dhm_context *dhm, const unsigned char *dhmin,
+                   size_t dhminlen );
+
+#if defined(POLARSSL_FS_IO)
+/** \ingroup x509_module */
+/**
+ * \brief          Load and parse DHM parameters
+ *
+ * \param dhm      DHM context to be initialized
+ * \param path     filename to read the DHM Parameters from
+ *
+ * \return         0 if successful, or a specific DHM or PEM error code
+ */
+int dhm_parse_dhmfile( dhm_context *dhm, const char *path );
+#endif /* POLARSSL_FS_IO */
+#endif /* POLARSSL_ASN1_PARSE_C */
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int dhm_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* dhm.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/ecdh.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,217 @@
+/**
+ * \file ecdh.h
+ *
+ * \brief Elliptic curve Diffie-Hellman
+ *
+ *  Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_ECDH_H
+#define POLARSSL_ECDH_H
+
+#include "ecp.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * When importing from an EC key, select if it is our key or the peer's key
+ */
+typedef enum
+{
+    POLARSSL_ECDH_OURS,
+    POLARSSL_ECDH_THEIRS,
+} ecdh_side;
+
+/**
+ * \brief           ECDH context structure
+ */
+typedef struct
+{
+    ecp_group grp;      /*!<  ellipitic curve used      */
+    mpi d;              /*!<  our secret value          */
+    ecp_point Q;        /*!<  our public value          */
+    ecp_point Qp;       /*!<  peer's public value       */
+    mpi z;              /*!<  shared secret             */
+    int point_format;   /*!<  format for point export   */
+    ecp_point Vi;       /*!<  blinding value (for later)    */
+    ecp_point Vf;       /*!<  un-blinding value (for later) */
+    mpi _d;             /*!<  previous d                    */
+}
+ecdh_context;
+
+/**
+ * \brief           Generate a public key
+ *
+ * \param grp       ECP group
+ * \param d         Destination MPI (secret exponent)
+ * \param Q         Destination point (public key)
+ * \param f_rng     RNG function
+ * \param p_rng     RNG parameter
+ *
+ * \return          0 if successful,
+ *                  or a POLARSSL_ERR_ECP_XXX or POLARSSL_MPI_XXX error code
+ */
+int ecdh_gen_public( ecp_group *grp, mpi *d, ecp_point *Q,
+                     int (*f_rng)(void *, unsigned char *, size_t),
+                     void *p_rng );
+
+/**
+ * \brief           Compute shared secret
+ *
+ * \param grp       ECP group
+ * \param z         Destination MPI (shared secret)
+ * \param Q         Public key from other party
+ * \param d         Our secret exponent
+ * \param f_rng     RNG function (see notes)
+ * \param p_rng     RNG parameter
+ *
+ * \return          0 if successful,
+ *                  or a POLARSSL_ERR_ECP_XXX or POLARSSL_MPI_XXX error code
+ *
+ * \note            If f_rng is not NULL, it is used to implement
+ *                  countermeasures against potential elaborate timing
+ *                  attacks, see \c ecp_mul() for details.
+ */
+int ecdh_compute_shared( ecp_group *grp, mpi *z,
+                         const ecp_point *Q, const mpi *d,
+                         int (*f_rng)(void *, unsigned char *, size_t),
+                         void *p_rng );
+
+/**
+ * \brief           Initialize context
+ *
+ * \param ctx       Context to initialize
+ */
+void ecdh_init( ecdh_context *ctx );
+
+/**
+ * \brief           Free context
+ *
+ * \param ctx       Context to free
+ */
+void ecdh_free( ecdh_context *ctx );
+
+/**
+ * \brief           Setup and write the ServerKeyExhange parameters
+ *
+ * \param ctx       ECDH context
+ * \param olen      number of chars written
+ * \param buf       destination buffer
+ * \param blen      length of buffer
+ * \param f_rng     RNG function
+ * \param p_rng     RNG parameter
+ *
+ * \note            This function assumes that ctx->grp has already been
+ *                  properly set (for example using ecp_use_known_dp).
+ *
+ * \return          0 if successful, or an POLARSSL_ERR_ECP_XXX error code
+ */
+int ecdh_make_params( ecdh_context *ctx, size_t *olen,
+                      unsigned char *buf, size_t blen,
+                      int (*f_rng)(void *, unsigned char *, size_t),
+                      void *p_rng );
+
+/**
+ * \brief           Parse the ServerKeyExhange parameters
+ *
+ * \param ctx       ECDH context
+ * \param buf       pointer to start of input buffer
+ * \param end       one past end of buffer
+ *
+ * \return          0 if successful, or an POLARSSL_ERR_ECP_XXX error code
+ */
+int ecdh_read_params( ecdh_context *ctx,
+                      const unsigned char **buf, const unsigned char *end );
+
+/**
+ * \brief           Setup an ECDH context from an EC key
+ *
+ * \param ctx       ECDH constext to set
+ * \param key       EC key to use
+ * \param side      Is it our key (1) or the peer's key (0) ?
+ *
+ * \return          0 if successful, or an POLARSSL_ERR_ECP_XXX error code
+ */
+int ecdh_get_params( ecdh_context *ctx, const ecp_keypair *key,
+                     ecdh_side side );
+
+/**
+ * \brief           Setup and export the client's public value
+ *
+ * \param ctx       ECDH context
+ * \param olen      number of bytes actually written
+ * \param buf       destination buffer
+ * \param blen      size of destination buffer
+ * \param f_rng     RNG function
+ * \param p_rng     RNG parameter
+ *
+ * \return          0 if successful, or an POLARSSL_ERR_ECP_XXX error code
+ */
+int ecdh_make_public( ecdh_context *ctx, size_t *olen,
+                      unsigned char *buf, size_t blen,
+                      int (*f_rng)(void *, unsigned char *, size_t),
+                      void *p_rng );
+
+/**
+ * \brief           Parse and import the client's public value
+ *
+ * \param ctx       ECDH context
+ * \param buf       start of input buffer
+ * \param blen      length of input buffer
+ *
+ * \return          0 if successful, or an POLARSSL_ERR_ECP_XXX error code
+ */
+int ecdh_read_public( ecdh_context *ctx,
+                      const unsigned char *buf, size_t blen );
+
+/**
+ * \brief           Derive and export the shared secret
+ *
+ * \param ctx       ECDH context
+ * \param olen      number of bytes written
+ * \param buf       destination buffer
+ * \param blen      buffer length
+ * \param f_rng     RNG function, see notes for \c ecdh_compute_shared()
+ * \param p_rng     RNG parameter
+ *
+ * \return          0 if successful, or an POLARSSL_ERR_ECP_XXX error code
+ */
+int ecdh_calc_secret( ecdh_context *ctx, size_t *olen,
+                      unsigned char *buf, size_t blen,
+                      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 ecdh_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ecdh.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/ecdsa.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,238 @@
+/**
+ * \file ecdsa.h
+ *
+ * \brief Elliptic curve DSA
+ *
+ *  Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_ECDSA_H
+#define POLARSSL_ECDSA_H
+
+#include "ecp.h"
+
+#if defined(POLARSSL_ECDSA_DETERMINISTIC)
+#include "md.h"
+#endif
+
+/**
+ * \brief           ECDSA context structure
+ *
+ * \note Purposefully begins with the same members as struct ecp_keypair.
+ */
+typedef struct
+{
+    ecp_group grp;      /*!<  ellipitic curve used          */
+    mpi d;              /*!<  secret signature key          */
+    ecp_point Q;        /*!<  public signature key          */
+    mpi r;              /*!<  first integer from signature  */
+    mpi s;              /*!<  second integer from signature */
+}
+ecdsa_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief           Compute ECDSA signature of a previously hashed message
+ *
+ * \param grp       ECP group
+ * \param r         First output integer
+ * \param s         Second output integer
+ * \param d         Private signing key
+ * \param buf       Message hash
+ * \param blen      Length of buf
+ * \param f_rng     RNG function
+ * \param p_rng     RNG parameter
+ *
+ * \return          0 if successful,
+ *                  or a POLARSSL_ERR_ECP_XXX or POLARSSL_MPI_XXX error code
+ */
+int ecdsa_sign( ecp_group *grp, mpi *r, mpi *s,
+                const mpi *d, const unsigned char *buf, size_t blen,
+                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
+
+#if defined(POLARSSL_ECDSA_DETERMINISTIC)
+/**
+ * \brief           Compute ECDSA signature of a previously hashed message
+ *                  (deterministic version)
+ *
+ * \param grp       ECP group
+ * \param r         First output integer
+ * \param s         Second output integer
+ * \param d         Private signing key
+ * \param buf       Message hash
+ * \param blen      Length of buf
+ * \param md_alg    MD algorithm used to hash the message
+ *
+ * \return          0 if successful,
+ *                  or a POLARSSL_ERR_ECP_XXX or POLARSSL_MPI_XXX error code
+ */
+int ecdsa_sign_det( ecp_group *grp, mpi *r, mpi *s,
+                    const mpi *d, const unsigned char *buf, size_t blen,
+                    md_type_t md_alg );
+#endif /* POLARSSL_ECDSA_DETERMINISTIC */
+
+/**
+ * \brief           Verify ECDSA signature of a previously hashed message
+ *
+ * \param grp       ECP group
+ * \param buf       Message hash
+ * \param blen      Length of buf
+ * \param Q         Public key to use for verification
+ * \param r         First integer of the signature
+ * \param s         Second integer of the signature
+ *
+ * \return          0 if successful,
+ *                  POLARSSL_ERR_ECP_BAD_INPUT_DATA if signature is invalid
+ *                  or a POLARSSL_ERR_ECP_XXX or POLARSSL_MPI_XXX error code
+ */
+int ecdsa_verify( ecp_group *grp,
+                  const unsigned char *buf, size_t blen,
+                  const ecp_point *Q, const mpi *r, const mpi *s);
+
+/**
+ * \brief           Compute ECDSA signature and write it to buffer,
+ *                  serialized as defined in RFC 4492 page 20.
+ *                  (Not thread-safe to use same context in multiple threads)
+ *
+ * \param ctx       ECDSA context
+ * \param hash      Message hash
+ * \param hlen      Length of hash
+ * \param sig       Buffer that will hold the signature
+ * \param slen      Length of the signature written
+ * \param f_rng     RNG function
+ * \param p_rng     RNG parameter
+ *
+ * \note            The "sig" buffer must be at least as large as twice the
+ *                  size of the curve used, plus 7 (eg. 71 bytes if a 256-bit
+ *                  curve is used).
+ *
+ * \return          0 if successful,
+ *                  or a POLARSSL_ERR_ECP, POLARSSL_ERR_MPI or
+ *                  POLARSSL_ERR_ASN1 error code
+ */
+int ecdsa_write_signature( ecdsa_context *ctx,
+                           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(POLARSSL_ECDSA_DETERMINISTIC)
+/**
+ * \brief           Compute ECDSA signature and write it to buffer,
+ *                  serialized as defined in RFC 4492 page 20.
+ *                  Deterministic version, RFC 6979.
+ *                  (Not thread-safe to use same context in multiple threads)
+ *
+ * \param ctx       ECDSA context
+ * \param hash      Message hash
+ * \param hlen      Length of hash
+ * \param sig       Buffer that will hold the signature
+ * \param slen      Length of the signature written
+ * \param md_alg    MD algorithm used to hash the message
+ *
+ * \note            The "sig" buffer must be at least as large as twice the
+ *                  size of the curve used, plus 7 (eg. 71 bytes if a 256-bit
+ *                  curve is used).
+ *
+ * \return          0 if successful,
+ *                  or a POLARSSL_ERR_ECP, POLARSSL_ERR_MPI or
+ *                  POLARSSL_ERR_ASN1 error code
+ */
+int ecdsa_write_signature_det( ecdsa_context *ctx,
+                               const unsigned char *hash, size_t hlen,
+                               unsigned char *sig, size_t *slen,
+                               md_type_t md_alg );
+#endif /* POLARSSL_ECDSA_DETERMINISTIC */
+
+/**
+ * \brief           Read and verify an ECDSA signature
+ *
+ * \param ctx       ECDSA context
+ * \param hash      Message hash
+ * \param hlen      Size of hash
+ * \param sig       Signature to read and verify
+ * \param slen      Size of sig
+ *
+ * \return          0 if successful,
+ *                  POLARSSL_ERR_ECP_BAD_INPUT_DATA if signature is invalid,
+ *                  POLARSSL_ERR_ECP_SIG_LEN_MISTMATCH if the signature is
+ *                  valid but its actual length is less than siglen,
+ *                  or a POLARSSL_ERR_ECP or POLARSSL_ERR_MPI error code
+ */
+int ecdsa_read_signature( ecdsa_context *ctx,
+                          const unsigned char *hash, size_t hlen,
+                          const unsigned char *sig, size_t slen );
+
+/**
+ * \brief           Generate an ECDSA keypair on the given curve
+ *
+ * \param ctx       ECDSA context in which the keypair should be stored
+ * \param gid       Group (elliptic curve) to use. One of the various
+ *                  POLARSSL_ECP_DP_XXX macros depending on configuration.
+ * \param f_rng     RNG function
+ * \param p_rng     RNG parameter
+ *
+ * \return          0 on success, or a POLARSSL_ERR_ECP code.
+ */
+int ecdsa_genkey( ecdsa_context *ctx, ecp_group_id gid,
+                  int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
+
+/**
+ * \brief           Set an ECDSA context from an EC key pair
+ *
+ * \param ctx       ECDSA context to set
+ * \param key       EC key to use
+ *
+ * \return          0 on success, or a POLARSSL_ERR_ECP code.
+ */
+int ecdsa_from_keypair( ecdsa_context *ctx, const ecp_keypair *key );
+
+/**
+ * \brief           Initialize context
+ *
+ * \param ctx       Context to initialize
+ */
+void ecdsa_init( ecdsa_context *ctx );
+
+/**
+ * \brief           Free context
+ *
+ * \param ctx       Context to free
+ */
+void ecdsa_free( ecdsa_context *ctx );
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int ecdsa_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ecdsa.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/ecp.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,653 @@
+/**
+ * \file ecp.h
+ *
+ * \brief Elliptic curves over GF(p)
+ *
+ *  Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_ECP_H
+#define POLARSSL_ECP_H
+
+#include "bignum.h"
+
+/*
+ * ECP error codes
+ */
+#define POLARSSL_ERR_ECP_BAD_INPUT_DATA                    -0x4F80  /**< Bad input parameters to function. */
+#define POLARSSL_ERR_ECP_BUFFER_TOO_SMALL                  -0x4F00  /**< The buffer is too small to write to. */
+#define POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE               -0x4E80  /**< Requested curve not available. */
+#define POLARSSL_ERR_ECP_VERIFY_FAILED                     -0x4E00  /**< The signature is not valid. */
+#define POLARSSL_ERR_ECP_MALLOC_FAILED                     -0x4D80  /**< Memory allocation failed. */
+#define POLARSSL_ERR_ECP_RANDOM_FAILED                     -0x4D00  /**< Generation of random value, such as (ephemeral) key, failed. */
+#define POLARSSL_ERR_ECP_INVALID_KEY                       -0x4C80  /**< Invalid private or public key. */
+#define POLARSSL_ERR_ECP_SIG_LEN_MISMATCH                  -0x4C00  /**< Signature is valid but shorter than the user-supplied length. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Domain parameters (curve, subgroup and generator) identifiers.
+ *
+ * Only curves over prime fields are supported.
+ *
+ * \warning This library does not support validation of arbitrary domain
+ * parameters. Therefore, only well-known domain parameters from trusted
+ * sources should be used. See ecp_use_known_dp().
+ */
+typedef enum
+{
+    POLARSSL_ECP_DP_NONE = 0,
+    POLARSSL_ECP_DP_SECP192R1,      /*!< 192-bits NIST curve  */
+    POLARSSL_ECP_DP_SECP224R1,      /*!< 224-bits NIST curve  */
+    POLARSSL_ECP_DP_SECP256R1,      /*!< 256-bits NIST curve  */
+    POLARSSL_ECP_DP_SECP384R1,      /*!< 384-bits NIST curve  */
+    POLARSSL_ECP_DP_SECP521R1,      /*!< 521-bits NIST curve  */
+    POLARSSL_ECP_DP_BP256R1,        /*!< 256-bits Brainpool curve */
+    POLARSSL_ECP_DP_BP384R1,        /*!< 384-bits Brainpool curve */
+    POLARSSL_ECP_DP_BP512R1,        /*!< 512-bits Brainpool curve */
+    POLARSSL_ECP_DP_M221,           /*!< (not implemented yet)    */
+    POLARSSL_ECP_DP_M255,           /*!< Curve25519               */
+    POLARSSL_ECP_DP_M383,           /*!< (not implemented yet)    */
+    POLARSSL_ECP_DP_M511,           /*!< (not implemented yet)    */
+    POLARSSL_ECP_DP_SECP192K1,      /*!< 192-bits "Koblitz" curve */
+    POLARSSL_ECP_DP_SECP224K1,      /*!< 224-bits "Koblitz" curve */
+    POLARSSL_ECP_DP_SECP256K1,      /*!< 256-bits "Koblitz" curve */
+} ecp_group_id;
+
+/**
+ * Number of supported curves (plus one for NONE).
+ *
+ * (Montgomery curves excluded for now.)
+ */
+#define POLARSSL_ECP_DP_MAX     12
+
+/**
+ * Curve information for use by other modules
+ */
+typedef struct
+{
+    ecp_group_id grp_id;    /*!< Internal identifier        */
+    uint16_t tls_id;        /*!< TLS NamedCurve identifier  */
+    uint16_t size;          /*!< Curve size in bits         */
+    const char *name;       /*!< Human-friendly name        */
+} ecp_curve_info;
+
+/**
+ * \brief           ECP point structure (jacobian coordinates)
+ *
+ * \note            All functions expect and return points satisfying
+ *                  the following condition: Z == 0 or Z == 1. (Other
+ *                  values of Z are used by internal functions only.)
+ *                  The point is zero, or "at infinity", if Z == 0.
+ *                  Otherwise, X and Y are its standard (affine) coordinates.
+ */
+typedef struct
+{
+    mpi X;          /*!<  the point's X coordinate  */
+    mpi Y;          /*!<  the point's Y coordinate  */
+    mpi Z;          /*!<  the point's Z coordinate  */
+}
+ecp_point;
+
+/**
+ * \brief           ECP group structure
+ *
+ * We consider two types of curves equations:
+ * 1. Short Weierstrass y^2 = x^3 + A x + B     mod P   (SEC1 + RFC 4492)
+ * 2. Montgomery,       y^2 = x^3 + A x^2 + x   mod P   (M255 + draft)
+ * In both cases, a generator G for a prime-order subgroup is fixed. In the
+ * short weierstrass, this subgroup is actually the whole curve, and its
+ * cardinal is denoted by N.
+ *
+ * In the case of Short Weierstrass curves, our code requires that N is an odd
+ * prime. (Use odd in ecp_mul() and prime in ecdsa_sign() for blinding.)
+ *
+ * In the case of Montgomery curves, we don't store A but (A + 2) / 4 which is
+ * the quantity actually used in the formulas. Also, nbits is not the size of N
+ * but the required size for private keys.
+ *
+ * If modp is NULL, reduction modulo P is done using a generic algorithm.
+ * Otherwise, it must point to a function that takes an mpi in the range
+ * 0..2^(2*pbits)-1 and transforms it in-place in an integer of little more
+ * than pbits, so that the integer may be efficiently brought in the 0..P-1
+ * range by a few additions or substractions. It must return 0 on success and
+ * non-zero on failure.
+ */
+typedef struct
+{
+    ecp_group_id id;    /*!<  internal group identifier                     */
+    mpi P;              /*!<  prime modulus of the base field               */
+    mpi A;              /*!<  1. A in the equation, or 2. (A + 2) / 4       */
+    mpi B;              /*!<  1. B in the equation, or 2. unused            */
+    ecp_point G;        /*!<  generator of the (sub)group used              */
+    mpi N;              /*!<  1. the order of G, or 2. unused               */
+    size_t pbits;       /*!<  number of bits in P                           */
+    size_t nbits;       /*!<  number of bits in 1. P, or 2. private keys    */
+    unsigned int h;     /*!<  internal: 1 if the constants are static       */
+    int (*modp)(mpi *); /*!<  function for fast reduction mod P             */
+    int (*t_pre)(ecp_point *, void *);  /*!< unused                         */
+    int (*t_post)(ecp_point *, void *); /*!< unused                         */
+    void *t_data;                       /*!< unused                         */
+    ecp_point *T;       /*!<  pre-computed points for ecp_mul_comb()        */
+    size_t T_size;      /*!<  number for pre-computed points                */
+}
+ecp_group;
+
+/**
+ * \brief           ECP key pair structure
+ *
+ * A generic key pair that could be used for ECDSA, fixed ECDH, etc.
+ *
+ * \note Members purposefully in the same order as struc ecdsa_context.
+ */
+typedef struct
+{
+    ecp_group grp;      /*!<  Elliptic curve and base point     */
+    mpi d;              /*!<  our secret value                  */
+    ecp_point Q;        /*!<  our public value                  */
+}
+ecp_keypair;
+
+/**
+ * \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(POLARSSL_ECP_MAX_BITS)
+/**
+ * Maximum size of the groups (that is, of N and P)
+ */
+#define POLARSSL_ECP_MAX_BITS     521   /**< Maximum bit size of groups */
+#endif
+
+#define POLARSSL_ECP_MAX_BYTES    ( ( POLARSSL_ECP_MAX_BITS + 7 ) / 8 )
+#define POLARSSL_ECP_MAX_PT_LEN   ( 2 * POLARSSL_ECP_MAX_BYTES + 1 )
+
+#if !defined(POLARSSL_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 << ( POLARSSL_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 POLARSSL_ECP_WINDOW_SIZE    6   /**< Maximum window size used */
+#endif
+
+#if !defined(POLARSSL_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 POLARSSL_ECP_FIXED_POINT_OPTIM  1   /**< Enable fixed-point speed-up */
+#endif
+
+/* \} name SECTION: Module settings */
+
+/*
+ * Point formats, from RFC 4492's enum ECPointFormat
+ */
+#define POLARSSL_ECP_PF_UNCOMPRESSED    0   /**< Uncompressed point format */
+#define POLARSSL_ECP_PF_COMPRESSED      1   /**< Compressed point format */
+
+/*
+ * Some other constants from RFC 4492
+ */
+#define POLARSSL_ECP_TLS_NAMED_CURVE    3   /**< ECCurveType's named_curve */
+
+/**
+ * \brief           Get the list of supported curves in order of preferrence
+ *                  (full information)
+ *
+ * \return          A statically allocated array, the last entry is 0.
+ */
+const ecp_curve_info *ecp_curve_list( void );
+
+/**
+ * \brief           Get the list of supported curves in order of preferrence
+ *                  (grp_id only)
+ *
+ * \return          A statically allocated array,
+ *                  terminated with POLARSSL_ECP_DP_NONE.
+ */
+const ecp_group_id *ecp_grp_id_list( void );
+
+/**
+ * \brief           Get curve information from an internal group identifier
+ *
+ * \param grp_id    A POLARSSL_ECP_DP_XXX value
+ *
+ * \return          The associated curve information or NULL
+ */
+const ecp_curve_info *ecp_curve_info_from_grp_id( ecp_group_id grp_id );
+
+/**
+ * \brief           Get curve information from a TLS NamedCurve value
+ *
+ * \param tls_id    A POLARSSL_ECP_DP_XXX value
+ *
+ * \return          The associated curve information or NULL
+ */
+const ecp_curve_info *ecp_curve_info_from_tls_id( uint16_t tls_id );
+
+/**
+ * \brief           Get curve information from a human-readable name
+ *
+ * \param name      The name
+ *
+ * \return          The associated curve information or NULL
+ */
+const ecp_curve_info *ecp_curve_info_from_name( const char *name );
+
+/**
+ * \brief           Initialize a point (as zero)
+ */
+void ecp_point_init( ecp_point *pt );
+
+/**
+ * \brief           Initialize a group (to something meaningless)
+ */
+void ecp_group_init( ecp_group *grp );
+
+/**
+ * \brief           Initialize a key pair (as an invalid one)
+ */
+void ecp_keypair_init( ecp_keypair *key );
+
+/**
+ * \brief           Free the components of a point
+ */
+void ecp_point_free( ecp_point *pt );
+
+/**
+ * \brief           Free the components of an ECP group
+ */
+void ecp_group_free( ecp_group *grp );
+
+/**
+ * \brief           Free the components of a key pair
+ */
+void ecp_keypair_free( ecp_keypair *key );
+
+/**
+ * \brief           Copy the contents of point Q into P
+ *
+ * \param P         Destination point
+ * \param Q         Source point
+ *
+ * \return          0 if successful,
+ *                  POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int ecp_copy( ecp_point *P, const ecp_point *Q );
+
+/**
+ * \brief           Copy the contents of a group object
+ *
+ * \param dst       Destination group
+ * \param src       Source group
+ *
+ * \return          0 if successful,
+ *                  POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int ecp_group_copy( ecp_group *dst, const ecp_group *src );
+
+/**
+ * \brief           Set a point to zero
+ *
+ * \param pt        Destination point
+ *
+ * \return          0 if successful,
+ *                  POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int ecp_set_zero( ecp_point *pt );
+
+/**
+ * \brief           Tell if a point is zero
+ *
+ * \param pt        Point to test
+ *
+ * \return          1 if point is zero, 0 otherwise
+ */
+int ecp_is_zero( ecp_point *pt );
+
+/**
+ * \brief           Import a non-zero point from two ASCII strings
+ *
+ * \param P         Destination point
+ * \param radix     Input numeric base
+ * \param x         First affine coordinate as a null-terminated string
+ * \param y         Second affine coordinate as a null-terminated string
+ *
+ * \return          0 if successful, or a POLARSSL_ERR_MPI_XXX error code
+ */
+int ecp_point_read_string( ecp_point *P, int radix,
+                           const char *x, const char *y );
+
+/**
+ * \brief           Export a point into unsigned binary data
+ *
+ * \param grp       Group to which the point should belong
+ * \param P         Point to export
+ * \param format    Point format, should be a POLARSSL_ECP_PF_XXX macro
+ * \param olen      Length of the actual output
+ * \param buf       Output buffer
+ * \param buflen    Length of the output buffer
+ *
+ * \return          0 if successful,
+ *                  or POLARSSL_ERR_ECP_BAD_INPUT_DATA
+ *                  or POLARSSL_ERR_ECP_BUFFER_TOO_SMALL
+ */
+int ecp_point_write_binary( const ecp_group *grp, const ecp_point *P,
+                            int format, size_t *olen,
+                            unsigned char *buf, size_t buflen );
+
+/**
+ * \brief           Import a point from unsigned binary data
+ *
+ * \param grp       Group to which the point should belong
+ * \param P         Point to import
+ * \param buf       Input buffer
+ * \param ilen      Actual length of input
+ *
+ * \return          0 if successful,
+ *                  POLARSSL_ERR_ECP_BAD_INPUT_DATA if input is invalid,
+ *                  POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
+ *                  POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE if the point format
+ *                  is not implemented.
+ *
+ * \note            This function does NOT check that the point actually
+ *                  belongs to the given group, see ecp_check_pubkey() for
+ *                  that.
+ */
+int ecp_point_read_binary( const ecp_group *grp, ecp_point *P,
+                           const unsigned char *buf, size_t ilen );
+
+/**
+ * \brief           Import a point from a TLS ECPoint record
+ *
+ * \param grp       ECP group used
+ * \param pt        Destination point
+ * \param buf       $(Start of input buffer)
+ * \param len       Buffer length
+ *
+ * \return          O if successful,
+ *                  POLARSSL_ERR_MPI_XXX if initialization failed
+ *                  POLARSSL_ERR_ECP_BAD_INPUT_DATA if input is invalid
+ */
+int ecp_tls_read_point( const ecp_group *grp, ecp_point *pt,
+                        const unsigned char **buf, size_t len );
+
+/**
+ * \brief           Export a point as a TLS ECPoint record
+ *
+ * \param grp       ECP group used
+ * \param pt        Point to export
+ * \param format    Export format
+ * \param olen      length of data written
+ * \param buf       Buffer to write to
+ * \param blen      Buffer length
+ *
+ * \return          0 if successful,
+ *                  or POLARSSL_ERR_ECP_BAD_INPUT_DATA
+ *                  or POLARSSL_ERR_ECP_BUFFER_TOO_SMALL
+ */
+int ecp_tls_write_point( const ecp_group *grp, const ecp_point *pt,
+                         int format, size_t *olen,
+                         unsigned char *buf, size_t blen );
+
+/**
+ * \brief           Import an ECP group from null-terminated ASCII strings
+ *
+ * \param grp       Destination group
+ * \param radix     Input numeric base
+ * \param p         Prime modulus of the base field
+ * \param b         Constant term in the equation
+ * \param gx        The generator's X coordinate
+ * \param gy        The generator's Y coordinate
+ * \param n         The generator's order
+ *
+ * \return          0 if successful, or a POLARSSL_ERR_MPI_XXX error code
+ *
+ * \note            Sets all fields except modp.
+ */
+int ecp_group_read_string( ecp_group *grp, int radix,
+                           const char *p, const char *b,
+                           const char *gx, const char *gy, const char *n);
+
+/**
+ * \brief           Set a group using well-known domain parameters
+ *
+ * \param grp       Destination group
+ * \param index     Index in the list of well-known domain parameters
+ *
+ * \return          O if successful,
+ *                  POLARSSL_ERR_MPI_XXX if initialization failed
+ *                  POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE for unkownn groups
+ *
+ * \note            Index should be a value of RFC 4492's enum NamdeCurve,
+ *                  possibly in the form of a POLARSSL_ECP_DP_XXX macro.
+ */
+int ecp_use_known_dp( ecp_group *grp, ecp_group_id index );
+
+/**
+ * \brief           Set a group from a TLS ECParameters record
+ *
+ * \param grp       Destination group
+ * \param buf       &(Start of input buffer)
+ * \param len       Buffer length
+ *
+ * \return          O if successful,
+ *                  POLARSSL_ERR_MPI_XXX if initialization failed
+ *                  POLARSSL_ERR_ECP_BAD_INPUT_DATA if input is invalid
+ */
+int ecp_tls_read_group( ecp_group *grp, const unsigned char **buf, size_t len );
+
+/**
+ * \brief           Write the TLS ECParameters record for a group
+ *
+ * \param grp       ECP group used
+ * \param olen      Number of bytes actually written
+ * \param buf       Buffer to write to
+ * \param blen      Buffer length
+ *
+ * \return          0 if successful,
+ *                  or POLARSSL_ERR_ECP_BUFFER_TOO_SMALL
+ */
+int ecp_tls_write_group( const ecp_group *grp, size_t *olen,
+                         unsigned char *buf, size_t blen );
+
+/**
+ * \brief           Addition: R = P + Q
+ *
+ * \param grp       ECP group
+ * \param R         Destination point
+ * \param P         Left-hand point
+ * \param Q         Right-hand point
+ *
+ * \return          0 if successful,
+ *                  POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ *
+ * \note            This function does not support Montgomery curves, such as
+ *                  Curve25519.
+ */
+int ecp_add( const ecp_group *grp, ecp_point *R,
+             const ecp_point *P, const ecp_point *Q );
+
+/**
+ * \brief           Subtraction: R = P - Q
+ *
+ * \param grp       ECP group
+ * \param R         Destination point
+ * \param P         Left-hand point
+ * \param Q         Right-hand point
+ *
+ * \return          0 if successful,
+ *                  POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ *
+ * \note            This function does not support Montgomery curves, such as
+ *                  Curve25519.
+ */
+int ecp_sub( const ecp_group *grp, ecp_point *R,
+             const ecp_point *P, const ecp_point *Q );
+
+/**
+ * \brief           Multiplication by an integer: R = m * P
+ *                  (Not thread-safe to use same group in multiple threads)
+ *
+ * \param grp       ECP group
+ * \param R         Destination point
+ * \param m         Integer by which to multiply
+ * \param P         Point to multiply
+ * \param f_rng     RNG function (see notes)
+ * \param p_rng     RNG parameter
+ *
+ * \return          0 if successful,
+ *                  POLARSSL_ERR_ECP_INVALID_KEY if m is not a valid privkey
+ *                  or P is not a valid pubkey,
+ *                  POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ *
+ * \note            In order to prevent timing attacks, this function
+ *                  executes the exact same sequence of (base field)
+ *                  operations for any valid m. It avoids any if-branch or
+ *                  array index depending on the value of m.
+ *
+ * \note            If f_rng is not NULL, it is used to randomize intermediate
+ *                  results in order to prevent potential timing attacks
+ *                  targeting these results. It is recommended to always
+ *                  provide a non-NULL f_rng (the overhead is negligible).
+ */
+int ecp_mul( ecp_group *grp, ecp_point *R,
+             const mpi *m, const ecp_point *P,
+             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
+
+/**
+ * \brief           Check that a point is a valid public key on this curve
+ *
+ * \param grp       Curve/group the point should belong to
+ * \param pt        Point to check
+ *
+ * \return          0 if point is a valid public key,
+ *                  POLARSSL_ERR_ECP_INVALID_KEY otherwise.
+ *
+ * \note            This function only checks the point is non-zero, has valid
+ *                  coordinates and lies on the curve, but not that it is
+ *                  indeed a multiple of G. This is additional check is more
+ *                  expensive, isn't required by standards, and shouldn't 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            Uses bare components rather than an ecp_keypair structure
+ *                  in order to ease use with other structures such as
+ *                  ecdh_context of ecdsa_context.
+ */
+int ecp_check_pubkey( const ecp_group *grp, const ecp_point *pt );
+
+/**
+ * \brief           Check that an mpi is a valid private key for this curve
+ *
+ * \param grp       Group used
+ * \param d         Integer to check
+ *
+ * \return          0 if point is a valid private key,
+ *                  POLARSSL_ERR_ECP_INVALID_KEY otherwise.
+ *
+ * \note            Uses bare components rather than an ecp_keypair structure
+ *                  in order to ease use with other structures such as
+ *                  ecdh_context of ecdsa_context.
+ */
+int ecp_check_privkey( const ecp_group *grp, const mpi *d );
+
+/**
+ * \brief           Generate a keypair
+ *
+ * \param grp       ECP group
+ * \param d         Destination MPI (secret part)
+ * \param Q         Destination point (public part)
+ * \param f_rng     RNG function
+ * \param p_rng     RNG parameter
+ *
+ * \return          0 if successful,
+ *                  or a POLARSSL_ERR_ECP_XXX or POLARSSL_MPI_XXX error code
+ *
+ * \note            Uses bare components rather than an ecp_keypair structure
+ *                  in order to ease use with other structures such as
+ *                  ecdh_context of ecdsa_context.
+ */
+int ecp_gen_keypair( ecp_group *grp, mpi *d, ecp_point *Q,
+                     int (*f_rng)(void *, unsigned char *, size_t),
+                     void *p_rng );
+
+/**
+ * \brief           Generate a keypair
+ *
+ * \param grp_id    ECP group identifier
+ * \param key       Destination keypair
+ * \param f_rng     RNG function
+ * \param p_rng     RNG parameter
+ *
+ * \return          0 if successful,
+ *                  or a POLARSSL_ERR_ECP_XXX or POLARSSL_MPI_XXX error code
+ */
+int ecp_gen_key( ecp_group_id grp_id, ecp_keypair *key,
+                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
+
+#if defined(POLARSSL_SELF_TEST)
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if a test failed
+ */
+int ecp_self_test( int verbose );
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ecp.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/entropy.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,239 @@
+/**
+ * \file entropy.h
+ *
+ * \brief Entropy accumulator implementation
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_ENTROPY_H
+#define POLARSSL_ENTROPY_H
+
+#include <string.h>
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_SHA512_C) && !defined(POLARSSL_ENTROPY_FORCE_SHA256)
+#include "sha512.h"
+#define POLARSSL_ENTROPY_SHA512_ACCUMULATOR
+#else
+#if defined(POLARSSL_SHA256_C)
+#define POLARSSL_ENTROPY_SHA256_ACCUMULATOR
+#include "sha256.h"
+#endif
+#endif
+
+#if defined(POLARSSL_THREADING_C)
+#include "threading.h"
+#endif
+
+#if defined(POLARSSL_HAVEGE_C)
+#include "havege.h"
+#endif
+
+#define POLARSSL_ERR_ENTROPY_SOURCE_FAILED                 -0x003C  /**< Critical entropy source failure. */
+#define POLARSSL_ERR_ENTROPY_MAX_SOURCES                   -0x003E  /**< No more sources can be added. */
+#define POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED            -0x0040  /**< No sources have been added to poll. */
+#define POLARSSL_ERR_ENTROPY_FILE_IO_ERROR                 -0x0058  /**< 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(ENTROPY_MAX_SOURCES)
+#define ENTROPY_MAX_SOURCES     20      /**< Maximum number of sources supported */
+#endif
+
+#if !defined(ENTROPY_MAX_GATHER)
+#define ENTROPY_MAX_GATHER      128     /**< Maximum amount requested from entropy sources */
+#endif
+
+/* \} name SECTION: Module settings */
+
+#if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
+#define ENTROPY_BLOCK_SIZE      64      /**< Block size of entropy accumulator (SHA-512) */
+#else
+#define ENTROPY_BLOCK_SIZE      32      /**< Block size of entropy accumulator (SHA-256) */
+#endif
+
+#define ENTROPY_MAX_SEED_SIZE   1024    /**< Maximum size of seed we read from seed file */
+#define ENTROPY_SOURCE_MANUAL   ENTROPY_MAX_SOURCES
+
+#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,
+ *                  POLARSSL_ERR_ENTROPY_SOURCE_FAILED otherwise
+ */
+typedef int (*f_source_ptr)(void *data, unsigned char *output, size_t len,
+                            size_t *olen);
+
+/**
+ * \brief           Entropy source state
+ */
+typedef struct
+{
+    f_source_ptr    f_source;   /**< The entropy source callback */
+    void *          p_source;   /**< The callback data pointer */
+    size_t          size;       /**< Amount received */
+    size_t          threshold;  /**< Minimum level required before release */
+}
+source_state;
+
+/**
+ * \brief           Entropy context structure
+ */
+typedef struct
+{
+#if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
+    sha512_context  accumulator;
+#else
+    sha256_context  accumulator;
+#endif
+    int             source_count;
+    source_state    source[ENTROPY_MAX_SOURCES];
+#if defined(POLARSSL_HAVEGE_C)
+    havege_state    havege_data;
+#endif
+#if defined(POLARSSL_THREADING_C)
+    threading_mutex_t mutex;    /*!< mutex                  */
+#endif
+}
+entropy_context;
+
+/**
+ * \brief           Initialize the context
+ *
+ * \param ctx       Entropy context to initialize
+ */
+void entropy_init( entropy_context *ctx );
+
+/**
+ * \brief           Free the data in the context
+ *
+ * \param ctx       Entropy context to free
+ */
+void entropy_free( entropy_context *ctx );
+
+/**
+ * \brief           Adds an entropy source to poll
+ *                  (Thread-safe if POLARSSL_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 entropy_func() )
+ *
+ * \return          0 if successful or POLARSSL_ERR_ENTROPY_MAX_SOURCES
+ */
+int entropy_add_source( entropy_context *ctx,
+                        f_source_ptr f_source, void *p_source,
+                        size_t threshold );
+
+/**
+ * \brief           Trigger an extra gather poll for the accumulator
+ *                  (Thread-safe if POLARSSL_THREADING_C is enabled)
+ *
+ * \param ctx       Entropy context
+ *
+ * \return          0 if successful, or POLARSSL_ERR_ENTROPY_SOURCE_FAILED
+ */
+int entropy_gather( entropy_context *ctx );
+
+/**
+ * \brief           Retrieve entropy from the accumulator
+ *                  (Maximum length: ENTROPY_BLOCK_SIZE)
+ *                  (Thread-safe if POLARSSL_THREADING_C is enabled)
+ *
+ * \param data      Entropy context
+ * \param output    Buffer to fill
+ * \param len       Length of buffer
+ *
+ * \return          0 if successful, or POLARSSL_ERR_ENTROPY_SOURCE_FAILED
+ */
+int entropy_func( void *data, unsigned char *output, size_t len );
+
+/**
+ * \brief           Add data to the accumulator manually
+ *                  (Thread-safe if POLARSSL_THREADING_C is enabled)
+ *
+ * \param ctx       Entropy context
+ * \param data      Data to add
+ * \param len       Length of data
+ *
+ * \return          0 if successful
+ */
+int entropy_update_manual( entropy_context *ctx,
+                           const unsigned char *data, size_t len );
+
+#if defined(POLARSSL_FS_IO)
+/**
+ * \brief               Write a seed file
+ *
+ * \param ctx           Entropy context
+ * \param path          Name of the file
+ *
+ * \return              0 if successful,
+ *                      POLARSSL_ERR_ENTROPY_FILE_IO_ERROR on file error, or
+ *                      POLARSSL_ERR_ENTROPY_SOURCE_FAILED
+ */
+int entropy_write_seed_file( entropy_context *ctx, const char *path );
+
+/**
+ * \brief               Read and update a seed file. Seed is added to this
+ *                      instance. No more than 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,
+ *                      POLARSSL_ERR_ENTROPY_FILE_IO_ERROR on file error,
+ *                      POLARSSL_ERR_ENTROPY_SOURCE_FAILED
+ */
+int entropy_update_seed_file( entropy_context *ctx, const char *path );
+#endif /* POLARSSL_FS_IO */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* entropy.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/entropy_poll.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,81 @@
+/**
+ * \file entropy_poll.h
+ *
+ * \brief Platform-specific and custom entropy polling functions
+ *
+ *  Copyright (C) 2006-2011, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_ENTROPY_POLL_H
+#define POLARSSL_ENTROPY_POLL_H
+
+#include <string.h>
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Default thresholds for built-in sources
+ */
+#define ENTROPY_MIN_PLATFORM    128     /**< Minimum for platform source    */
+#define ENTROPY_MIN_HAVEGE      128     /**< Minimum for HAVEGE             */
+#define ENTROPY_MIN_HARDCLOCK    32     /**< Minimum for hardclock()        */
+
+#if !defined(POLARSSL_NO_PLATFORM_ENTROPY)
+/**
+ * \brief           Platform-specific entropy poll callback
+ */
+int platform_entropy_poll( void *data,
+                           unsigned char *output, size_t len, size_t *olen );
+#endif
+
+#if defined(POLARSSL_HAVEGE_C)
+/**
+ * \brief           HAVEGE based entropy poll callback
+ *
+ * Requires an HAVEGE state as its data pointer.
+ */
+int havege_poll( void *data,
+                 unsigned char *output, size_t len, size_t *olen );
+#endif
+
+#if defined(POLARSSL_TIMING_C)
+/**
+ * \brief           hardclock-based entropy poll callback
+ */
+int hardclock_poll( void *data,
+                    unsigned char *output, size_t len, size_t *olen );
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* entropy_poll.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/error.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,124 @@
+/**
+ * \file error.h
+ *
+ * \brief Error to string translation
+ *
+ *  Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_ERROR_H
+#define POLARSSL_ERROR_H
+
+#include <string.h>
+
+/**
+ * Error code layout.
+ *
+ * Currently we try to keep all error codes within the negative space of 16
+ * bytes signed integers to support all platforms (-0x0000 - -0x8000). 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  - 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       2  0x0012-0x0014
+ * BLOWFISH  2  0x0016-0x0018
+ * THREADING 3  0x001A-0x001E
+ * AES       2  0x0020-0x0022
+ * CAMELLIA  2  0x0024-0x0026
+ * XTEA      1  0x0028-0x0028
+ * BASE64    2  0x002A-0x002C
+ * OID       1  0x002E-0x002E   0x000B-0x000B
+ * PADLOCK   1  0x0030-0x0030
+ * DES       1  0x0032-0x0032
+ * CTR_DBRG  4  0x0034-0x003A
+ * ENTROPY   3  0x003C-0x0040
+ * NET      11  0x0042-0x0056
+ * ENTROPY   1  0x0058-0x0058
+ * ASN1      7  0x0060-0x006C
+ * MD2       1  0x0070-0x0070
+ * MD4       1  0x0072-0x0072
+ * MD5       1  0x0074-0x0074
+ * SHA1      1  0x0076-0x0076
+ * SHA256    1  0x0078-0x0078
+ * SHA512    1  0x007A-0x007A
+ * PBKDF2    1  0x007C-0x007C
+ * RIPEMD160 1  0x007E-0x007E
+ * HMAC_DRBG 4  0x0003-0x0009
+ *
+ * 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   18
+ * PK        2   14 (Started from top, plus 0x2000)
+ * DHM       3   9
+ * PKCS5     3   4 (Started from top)
+ * RSA       4   9
+ * ECP       4   8 (Started from top)
+ * MD        5   4
+ * CIPHER    6   6
+ * SSL       6   9 (Started from top)
+ * SSL       7   31
+ *
+ * Module dependent error code (5 bits 0x.00.-0x.F8.)
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Translate a PolarSSL 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 polarssl_strerror( int errnum, char *buffer, size_t buflen );
+
+#if defined(POLARSSL_ERROR_STRERROR_BC)
+void error_strerror( int errnum, char *buffer, size_t buflen );
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* error.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/gcm.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,221 @@
+/**
+ * \file gcm.h
+ *
+ * \brief Galois/Counter mode for 128-bit block ciphers
+ *
+ *  Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_GCM_H
+#define POLARSSL_GCM_H
+
+#include "cipher.h"
+
+#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
+#include <basetsd.h>
+typedef UINT32 uint32_t;
+typedef UINT64 uint64_t;
+#else
+#include <stdint.h>
+#endif
+
+#define GCM_ENCRYPT     1
+#define GCM_DECRYPT     0
+
+#define POLARSSL_ERR_GCM_AUTH_FAILED                       -0x0012  /**< Authenticated decryption failed. */
+#define POLARSSL_ERR_GCM_BAD_INPUT                         -0x0014  /**< Bad input parameters to function. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          GCM context structure
+ */
+typedef struct {
+    cipher_context_t cipher_ctx;/*!< cipher context used */
+    uint64_t HL[16];            /*!< Precalculated HTable */
+    uint64_t HH[16];            /*!< Precalculated HTable */
+    uint64_t len;               /*!< Total data length */
+    uint64_t add_len;           /*!< Total add length */
+    unsigned char base_ectr[16];/*!< First ECTR for tag */
+    unsigned char y[16];        /*!< Y working value */
+    unsigned char buf[16];      /*!< buf working value */
+    int mode;                   /*!< Encrypt or Decrypt */
+}
+gcm_context;
+
+/**
+ * \brief           GCM initialization (encryption)
+ *
+ * \param ctx       GCM context to be initialized
+ * \param cipher    cipher to use (a 128-bit block cipher)
+ * \param key       encryption key
+ * \param keysize   must be 128, 192 or 256
+ *
+ * \return          0 if successful, or a cipher specific error code
+ */
+int gcm_init( gcm_context *ctx, cipher_id_t cipher, const unsigned char *key,
+              unsigned int keysize );
+
+/**
+ * \brief           GCM buffer encryption/decryption using a block cipher
+ *
+ * \note On encryption, the output buffer can be the same as the input buffer.
+ *       On decryption, the output buffer cannot be the same as input buffer.
+ *       If buffers overlap, the output buffer must trail at least 8 bytes
+ *       behind the input buffer.
+ *
+ * \param ctx       GCM context
+ * \param mode      GCM_ENCRYPT or GCM_DECRYPT
+ * \param length    length of the input data
+ * \param iv        initialization vector
+ * \param iv_len    length of IV
+ * \param add       additional data
+ * \param add_len   length of additional data
+ * \param input     buffer holding the input data
+ * \param output    buffer for holding the output data
+ * \param tag_len   length of the tag to generate
+ * \param tag       buffer for holding the tag
+ *
+ * \return         0 if successful
+ */
+int gcm_crypt_and_tag( 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           GCM buffer authenticated decryption using a block cipher
+ *
+ * \note On decryption, the output buffer cannot be the same as input buffer.
+ *       If buffers overlap, the output buffer must trail at least 8 bytes
+ *       behind the input buffer.
+ *
+ * \param ctx       GCM context
+ * \param length    length of the input data
+ * \param iv        initialization vector
+ * \param iv_len    length of IV
+ * \param add       additional data
+ * \param add_len   length of additional data
+ * \param tag       buffer holding the tag
+ * \param tag_len   length of the tag
+ * \param input     buffer holding the input data
+ * \param output    buffer for holding the output data
+ *
+ * \return         0 if successful and authenticated,
+ *                 POLARSSL_ERR_GCM_AUTH_FAILED if tag does not match
+ */
+int gcm_auth_decrypt( 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           Generic GCM stream start function
+ *
+ * \param ctx       GCM context
+ * \param mode      GCM_ENCRYPT or GCM_DECRYPT
+ * \param iv        initialization vector
+ * \param iv_len    length of IV
+ * \param add       additional data (or NULL if length is 0)
+ * \param add_len   length of additional data
+ *
+ * \return         0 if successful
+ */
+int gcm_starts( gcm_context *ctx,
+                int mode,
+                const unsigned char *iv,
+                size_t iv_len,
+                const unsigned char *add,
+                size_t add_len );
+
+/**
+ * \brief           Generic GCM update function. Encrypts/decrypts using the
+ *                  given GCM context. Expects input to be a multiple of 16
+ *                  bytes! Only the last call before gcm_finish() can be less
+ *                  than 16 bytes!
+ *
+ * \note On decryption, the output buffer cannot be the same as input buffer.
+ *       If buffers overlap, the output buffer must trail at least 8 bytes
+ *       behind the input buffer.
+ *
+ * \param ctx       GCM context
+ * \param length    length of the input data
+ * \param input     buffer holding the input data
+ * \param output    buffer for holding the output data
+ *
+ * \return         0 if successful or POLARSSL_ERR_GCM_BAD_INPUT
+ */
+int gcm_update( gcm_context *ctx,
+                size_t length,
+                const unsigned char *input,
+                unsigned char *output );
+
+/**
+ * \brief           Generic GCM finalisation function. Wraps up the GCM stream
+ *                  and generates the tag. The tag can have a maximum length of
+ *                  16 bytes.
+ *
+ * \param ctx       GCM context
+ * \param tag       buffer for holding the tag (may be NULL if tag_len is 0)
+ * \param tag_len   length of the tag to generate
+ *
+ * \return          0 if successful or POLARSSL_ERR_GCM_BAD_INPUT
+ */
+int gcm_finish( gcm_context *ctx,
+                unsigned char *tag,
+                size_t tag_len );
+
+/**
+ * \brief           Free a GCM context and underlying cipher sub-context
+ *
+ * \param ctx       GCM context to free
+ */
+void gcm_free( gcm_context *ctx );
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int gcm_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* gcm.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/havege.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,73 @@
+/**
+ * \file havege.h
+ *
+ * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion
+ *
+ *  Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_HAVEGE_H
+#define POLARSSL_HAVEGE_H
+
+#include <string.h>
+
+#define COLLECT_SIZE 1024
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          HAVEGE state structure
+ */
+typedef struct
+{
+    int PT1, PT2, offset[2];
+    int pool[COLLECT_SIZE];
+    int WALK[8192];
+}
+havege_state;
+
+/**
+ * \brief          HAVEGE initialization
+ *
+ * \param hs       HAVEGE state to be initialized
+ */
+void havege_init( havege_state *hs );
+
+/**
+ * \brief          HAVEGE rand function
+ *
+ * \param p_rng    A HAVEGE state
+ * \param output   Buffer to fill
+ * \param len      Length of buffer
+ *
+ * \return         0
+ */
+int havege_random( void *p_rng, unsigned char *output, size_t len );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* havege.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/hmac_drbg.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,286 @@
+/**
+ * \file hmac_drbg.h
+ *
+ * \brief HMAC_DRBG (NIST SP 800-90A)
+ *
+ *  Copyright (C) 2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_HMAC_DRBG_H
+#define POLARSSL_HMAC_DRBG_H
+
+#include "md.h"
+
+/*
+ * Error codes
+ */
+#define POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG              -0x0003  /**< Too many random requested in single call. */
+#define POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG                -0x0005  /**< Input too large (Entropy + additional). */
+#define POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR                -0x0007  /**< Read/write error in file. */
+#define POLARSSL_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(POLARSSL_HMAC_DRBG_RESEED_INTERVAL)
+#define POLARSSL_HMAC_DRBG_RESEED_INTERVAL   10000   /**< Interval before reseed is performed by default */
+#endif
+
+#if !defined(POLARSSL_HMAC_DRBG_MAX_INPUT)
+#define POLARSSL_HMAC_DRBG_MAX_INPUT         256     /**< Maximum number of additional input bytes */
+#endif
+
+#if !defined(POLARSSL_HMAC_DRBG_MAX_REQUEST)
+#define POLARSSL_HMAC_DRBG_MAX_REQUEST       1024    /**< Maximum number of requested bytes per call */
+#endif
+
+#if !defined(POLARSSL_HMAC_DRBG_MAX_SEED_INPUT)
+#define POLARSSL_HMAC_DRBG_MAX_SEED_INPUT    384     /**< Maximum size of (re)seed buffer */
+#endif
+
+/* \} name SECTION: Module settings */
+
+#define POLARSSL_HMAC_DRBG_PR_OFF   0   /**< No prediction resistance       */
+#define POLARSSL_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 */
+    md_context_t md_ctx;                    /*!< HMAC context (inc. K)  */
+    unsigned char V[POLARSSL_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        */
+} hmac_drbg_context;
+
+/**
+ * \brief               HMAC_DRBG initialisation
+ *
+ * \param ctx           HMAC_DRBG context to be initialised
+ * \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
+ *                      POLARSSL_ERR_MD_BAD_INPUT_DATA, or
+ *                      POLARSSL_ERR_MD_ALLOC_FAILED, or
+ *                      POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED.
+ */
+int hmac_drbg_init( hmac_drbg_context *ctx,
+                    const 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
+ *                      POLARSSL_ERR_MD_BAD_INPUT_DATA, or
+ *                      POLARSSL_ERR_MD_ALLOC_FAILED.
+ */
+int hmac_drbg_init_buf( hmac_drbg_context *ctx,
+                        const 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    POLARSSL_HMAC_DRBG_PR_ON or POLARSSL_HMAC_DRBG_PR_OFF
+ */
+void hmac_drbg_set_prediction_resistance( 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 hmac_drbg_init() )
+ *
+ * \param ctx           HMAC_DRBG context
+ * \param len           Amount of entropy to grab, in bytes
+ */
+void hmac_drbg_set_entropy_len( hmac_drbg_context *ctx,
+                                size_t len );
+
+/**
+ * \brief               Set the reseed interval
+ *                      (Default: POLARSSL_HMAC_DRBG_RESEED_INTERVAL)
+ *
+ * \param ctx           HMAC_DRBG context
+ * \param interval      Reseed interval
+ */
+void hmac_drbg_set_reseed_interval( 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 hmac_drbg_update( 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
+ *                      POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
+ */
+int hmac_drbg_reseed( 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
+ *                      POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or
+ *                      POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG, or
+ *                      POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG.
+ */
+int 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
+ *                      POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or
+ *                      POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG
+ */
+int 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 hmac_drbg_free( hmac_drbg_context *ctx );
+
+#if defined(POLARSSL_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
+ *                      POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
+ */
+int hmac_drbg_write_seed_file( 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,
+ *                      POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED or
+ *                      POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG
+ */
+int hmac_drbg_update_seed_file( hmac_drbg_context *ctx, const char *path );
+#endif /* POLARSSL_FS_IO */
+
+
+#if defined(POLARSSL_SELF_TEST)
+/**
+ * \brief               Checkup routine
+ *
+ * \return              0 if successful, or 1 if the test failed
+ */
+int hmac_drbg_self_test( int verbose );
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* hmac_drbg.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/md.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,380 @@
+/**
+ * \file md.h
+ *
+ * \brief Generic message digest wrapper
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_MD_H
+#define POLARSSL_MD_H
+
+#include <string.h>
+
+#if defined(_MSC_VER) && !defined(inline)
+#define inline _inline
+#else
+#if defined(__ARMCC_VERSION) && !defined(inline)
+#define inline __inline
+#endif /* __ARMCC_VERSION */
+#endif /*_MSC_VER */
+
+#define POLARSSL_ERR_MD_FEATURE_UNAVAILABLE                -0x5080  /**< The selected feature is not available. */
+#define POLARSSL_ERR_MD_BAD_INPUT_DATA                     -0x5100  /**< Bad input parameters to function. */
+#define POLARSSL_ERR_MD_ALLOC_FAILED                       -0x5180  /**< Failed to allocate memory. */
+#define POLARSSL_ERR_MD_FILE_IO_ERROR                      -0x5200  /**< Opening or reading of file failed. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+    POLARSSL_MD_NONE=0,
+    POLARSSL_MD_MD2,
+    POLARSSL_MD_MD4,
+    POLARSSL_MD_MD5,
+    POLARSSL_MD_SHA1,
+    POLARSSL_MD_SHA224,
+    POLARSSL_MD_SHA256,
+    POLARSSL_MD_SHA384,
+    POLARSSL_MD_SHA512,
+    POLARSSL_MD_RIPEMD160,
+} md_type_t;
+
+#if defined(POLARSSL_SHA512_C)
+#define POLARSSL_MD_MAX_SIZE         64  /* longest known is SHA512 */
+#else
+#define POLARSSL_MD_MAX_SIZE         32  /* longest known is SHA256 or less */
+#endif
+
+/**
+ * Message digest information. Allows message digest functions to be called
+ * in a generic way.
+ */
+typedef struct {
+    /** Digest identifier */
+    md_type_t type;
+
+    /** Name of the message digest */
+    const char * name;
+
+    /** Output length of the digest function */
+    int size;
+
+    /** Digest initialisation function */
+    void (*starts_func)( void *ctx );
+
+    /** Digest update function */
+    void (*update_func)( void *ctx, const unsigned char *input, size_t ilen );
+
+    /** Digest finalisation function */
+    void (*finish_func)( void *ctx, unsigned char *output );
+
+    /** Generic digest function */
+    void (*digest_func)( const unsigned char *input, size_t ilen,
+                         unsigned char *output );
+
+    /** Generic file digest function */
+    int (*file_func)( const char *path, unsigned char *output );
+
+    /** HMAC Initialisation function */
+    void (*hmac_starts_func)( void *ctx, const unsigned char *key,
+                              size_t keylen );
+
+    /** HMAC update function */
+    void (*hmac_update_func)( void *ctx, const unsigned char *input,
+                              size_t ilen );
+
+    /** HMAC finalisation function */
+    void (*hmac_finish_func)( void *ctx, unsigned char *output);
+
+    /** HMAC context reset function */
+    void (*hmac_reset_func)( void *ctx );
+
+    /** Generic HMAC function */
+    void (*hmac_func)( const unsigned char *key, size_t keylen,
+                       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 );
+
+    /** Internal use only */
+    void (*process_func)( void *ctx, const unsigned char *input );
+} md_info_t;
+
+/**
+ * Generic message digest context.
+ */
+typedef struct {
+    /** Information about the associated message digest */
+    const md_info_t *md_info;
+
+    /** Digest-specific context */
+    void *md_ctx;
+} md_context_t;
+
+#define MD_CONTEXT_T_INIT { \
+    NULL, /* md_info */ \
+    NULL, /* md_ctx */ \
+}
+
+/**
+ * \brief Returns the list of digests supported by the generic digest module.
+ *
+ * \return          a statically allocated array of digests, the last entry
+ *                  is 0.
+ */
+const int *md_list( void );
+
+/**
+ * \brief           Returns the message digest information associated with the
+ *                  given digest name.
+ *
+ * \param md_name   Name of the digest to search for.
+ *
+ * \return          The message digest information associated with md_name or
+ *                  NULL if not found.
+ */
+const md_info_t *md_info_from_string( const char *md_name );
+
+/**
+ * \brief           Returns the message digest information associated with the
+ *                  given digest type.
+ *
+ * \param md_type   type of digest to search for.
+ *
+ * \return          The message digest information associated with md_type or
+ *                  NULL if not found.
+ */
+const md_info_t *md_info_from_type( md_type_t md_type );
+
+/**
+ * \brief          Initialises and fills the message digest context structure
+ *                 with the appropriate values.
+ *
+ * \param ctx      context to initialise. May not be NULL. The
+ *                 digest-specific context (ctx->md_ctx) must be NULL. It will
+ *                 be allocated, and must be freed using md_free_ctx() later.
+ * \param md_info  message digest to use.
+ *
+ * \returns        \c 0 on success, \c POLARSSL_ERR_MD_BAD_INPUT_DATA on
+ *                 parameter failure, \c POLARSSL_ERR_MD_ALLOC_FAILED if
+ *                 allocation of the digest-specific context failed.
+ */
+int md_init_ctx( md_context_t *ctx, const md_info_t *md_info );
+
+/**
+ * \brief          Free the message-specific context of ctx. Freeing ctx itself
+ *                 remains the responsibility of the caller.
+ *
+ * \param ctx      Free the message-specific context
+ *
+ * \returns        0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ *                 verification fails.
+ */
+int md_free_ctx( md_context_t *ctx );
+
+/**
+ * \brief           Returns the size of the message digest output.
+ *
+ * \param md_info   message digest info
+ *
+ * \return          size of the message digest output.
+ */
+static inline unsigned char md_get_size( const md_info_t *md_info )
+{
+    if( md_info == NULL )
+        return( 0 );
+
+    return md_info->size;
+}
+
+/**
+ * \brief           Returns the type of the message digest output.
+ *
+ * \param md_info   message digest info
+ *
+ * \return          type of the message digest output.
+ */
+static inline md_type_t md_get_type( const md_info_t *md_info )
+{
+    if( md_info == NULL )
+        return( POLARSSL_MD_NONE );
+
+    return md_info->type;
+}
+
+/**
+ * \brief           Returns the name of the message digest output.
+ *
+ * \param md_info   message digest info
+ *
+ * \return          name of the message digest output.
+ */
+static inline const char *md_get_name( const md_info_t *md_info )
+{
+    if( md_info == NULL )
+        return( NULL );
+
+    return md_info->name;
+}
+
+/**
+ * \brief          Set-up the given context for a new message digest
+ *
+ * \param ctx      generic message digest context.
+ *
+ * \returns        0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ *                 verification fails.
+ */
+int md_starts( md_context_t *ctx );
+
+/**
+ * \brief          Generic message digest process buffer
+ *
+ * \param ctx      Generic message digest context
+ * \param input    buffer holding the  datal
+ * \param ilen     length of the input data
+ *
+ * \returns        0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ *                 verification fails.
+ */
+int md_update( md_context_t *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief          Generic message digest final digest
+ *
+ * \param ctx      Generic message digest context
+ * \param output   Generic message digest checksum result
+ *
+ * \returns        0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ *                 verification fails.
+ */
+int md_finish( md_context_t *ctx, unsigned char *output );
+
+/**
+ * \brief          Output = message_digest( input buffer )
+ *
+ * \param md_info  message digest info
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   Generic message digest checksum result
+ *
+ * \returns        0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ *                 verification fails.
+ */
+int md( const md_info_t *md_info, const unsigned char *input, size_t ilen,
+        unsigned char *output );
+
+/**
+ * \brief          Output = message_digest( file contents )
+ *
+ * \param md_info  message digest info
+ * \param path     input file name
+ * \param output   generic message digest checksum result
+ *
+ * \return         0 if successful, POLARSSL_ERR_MD_FILE_OPEN_FAILED if fopen
+ *                 failed, POLARSSL_ERR_MD_FILE_READ_FAILED if fread failed,
+ *                 POLARSSL_ERR_MD_BAD_INPUT_DATA if md_info was NULL.
+ */
+int md_file( const md_info_t *md_info, const char *path,
+             unsigned char *output );
+
+/**
+ * \brief          Generic HMAC context setup
+ *
+ * \param ctx      HMAC context to be initialized
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ *
+ * \returns        0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ *                 verification fails.
+ */
+int md_hmac_starts( md_context_t *ctx, const unsigned char *key,
+                    size_t keylen );
+
+/**
+ * \brief          Generic HMAC process buffer
+ *
+ * \param ctx      HMAC context
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ *
+ * \returns        0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ *                 verification fails.
+ */
+int md_hmac_update( md_context_t *ctx, const unsigned char *input,
+                    size_t ilen );
+
+/**
+ * \brief          Generic HMAC final digest
+ *
+ * \param ctx      HMAC context
+ * \param output   Generic HMAC checksum result
+ *
+ * \returns        0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ *                 verification fails.
+ */
+int md_hmac_finish( md_context_t *ctx, unsigned char *output);
+
+/**
+ * \brief          Generic HMAC context reset
+ *
+ * \param ctx      HMAC context to be reset
+ *
+ * \returns        0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ *                 verification fails.
+ */
+int md_hmac_reset( md_context_t *ctx );
+
+/**
+ * \brief          Output = Generic_HMAC( hmac key, input buffer )
+ *
+ * \param md_info  message digest info
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   Generic HMAC-result
+ *
+ * \returns        0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ *                 verification fails.
+ */
+int md_hmac( const 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 md_process( md_context_t *ctx, const unsigned char *data );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* POLARSSL_MD_H */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/md2.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,182 @@
+/**
+ * \file md2.h
+ *
+ * \brief MD2 message digest algorithm (hash function)
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_MD2_H
+#define POLARSSL_MD2_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#include <string.h>
+
+#define POLARSSL_ERR_MD2_FILE_IO_ERROR                 -0x0070  /**< Read/write error in file. */
+
+#if !defined(POLARSSL_MD2_ALT)
+// Regular implementation
+//
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          MD2 context structure
+ */
+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 */
+
+    unsigned char ipad[16];     /*!< HMAC: inner padding        */
+    unsigned char opad[16];     /*!< HMAC: outer padding        */
+    size_t left;                /*!< amount of data in buffer   */
+}
+md2_context;
+
+/**
+ * \brief          MD2 context setup
+ *
+ * \param ctx      context to be initialized
+ */
+void md2_starts( md2_context *ctx );
+
+/**
+ * \brief          MD2 process buffer
+ *
+ * \param ctx      MD2 context
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ */
+void md2_update( md2_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief          MD2 final digest
+ *
+ * \param ctx      MD2 context
+ * \param output   MD2 checksum result
+ */
+void md2_finish( md2_context *ctx, unsigned char output[16] );
+
+#ifdef __cplusplus
+}
+#endif
+
+#else  /* POLARSSL_MD2_ALT */
+#include "md2_alt.h"
+#endif /* POLARSSL_MD2_ALT */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          Output = MD2( input buffer )
+ *
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   MD2 checksum result
+ */
+void md2( const unsigned char *input, size_t ilen, unsigned char output[16] );
+
+/**
+ * \brief          Output = MD2( file contents )
+ *
+ * \param path     input file name
+ * \param output   MD2 checksum result
+ *
+ * \return         0 if successful, or POLARSSL_ERR_MD2_FILE_IO_ERROR
+ */
+int md2_file( const char *path, unsigned char output[16] );
+
+/**
+ * \brief          MD2 HMAC context setup
+ *
+ * \param ctx      HMAC context to be initialized
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ */
+void md2_hmac_starts( md2_context *ctx, const unsigned char *key,
+                      size_t keylen );
+
+/**
+ * \brief          MD2 HMAC process buffer
+ *
+ * \param ctx      HMAC context
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ */
+void md2_hmac_update( md2_context *ctx, const unsigned char *input,
+                      size_t ilen );
+
+/**
+ * \brief          MD2 HMAC final digest
+ *
+ * \param ctx      HMAC context
+ * \param output   MD2 HMAC checksum result
+ */
+void md2_hmac_finish( md2_context *ctx, unsigned char output[16] );
+
+/**
+ * \brief          MD2 HMAC context reset
+ *
+ * \param ctx      HMAC context to be reset
+ */
+void md2_hmac_reset( md2_context *ctx );
+
+/**
+ * \brief          Output = HMAC-MD2( hmac key, input buffer )
+ *
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   HMAC-MD2 result
+ */
+void md2_hmac( const unsigned char *key, size_t keylen,
+               const unsigned char *input, size_t ilen,
+               unsigned char output[16] );
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int md2_self_test( int verbose );
+
+/* Internal use */
+void md2_process( md2_context *ctx );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* md2.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/md4.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,188 @@
+/**
+ * \file md4.h
+ *
+ * \brief MD4 message digest algorithm (hash function)
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_MD4_H
+#define POLARSSL_MD4_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#include <string.h>
+
+#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
+#include <basetsd.h>
+typedef UINT32 uint32_t;
+#else
+#include <inttypes.h>
+#endif
+
+#define POLARSSL_ERR_MD4_FILE_IO_ERROR                 -0x0072  /**< Read/write error in file. */
+
+#if !defined(POLARSSL_MD4_ALT)
+// Regular implementation
+//
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          MD4 context structure
+ */
+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 */
+
+    unsigned char ipad[64];     /*!< HMAC: inner padding        */
+    unsigned char opad[64];     /*!< HMAC: outer padding        */
+}
+md4_context;
+
+/**
+ * \brief          MD4 context setup
+ *
+ * \param ctx      context to be initialized
+ */
+void md4_starts( md4_context *ctx );
+
+/**
+ * \brief          MD4 process buffer
+ *
+ * \param ctx      MD4 context
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ */
+void md4_update( md4_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief          MD4 final digest
+ *
+ * \param ctx      MD4 context
+ * \param output   MD4 checksum result
+ */
+void md4_finish( md4_context *ctx, unsigned char output[16] );
+
+#ifdef __cplusplus
+}
+#endif
+
+#else  /* POLARSSL_MD4_ALT */
+#include "md4_alt.h"
+#endif /* POLARSSL_MD4_ALT */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          Output = MD4( input buffer )
+ *
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   MD4 checksum result
+ */
+void md4( const unsigned char *input, size_t ilen, unsigned char output[16] );
+
+/**
+ * \brief          Output = MD4( file contents )
+ *
+ * \param path     input file name
+ * \param output   MD4 checksum result
+ *
+ * \return         0 if successful, or POLARSSL_ERR_MD4_FILE_IO_ERROR
+ */
+int md4_file( const char *path, unsigned char output[16] );
+
+/**
+ * \brief          MD4 HMAC context setup
+ *
+ * \param ctx      HMAC context to be initialized
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ */
+void md4_hmac_starts( md4_context *ctx, const unsigned char *key,
+                      size_t keylen );
+
+/**
+ * \brief          MD4 HMAC process buffer
+ *
+ * \param ctx      HMAC context
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ */
+void md4_hmac_update( md4_context *ctx, const unsigned char *input,
+                      size_t ilen );
+
+/**
+ * \brief          MD4 HMAC final digest
+ *
+ * \param ctx      HMAC context
+ * \param output   MD4 HMAC checksum result
+ */
+void md4_hmac_finish( md4_context *ctx, unsigned char output[16] );
+
+/**
+ * \brief          MD4 HMAC context reset
+ *
+ * \param ctx      HMAC context to be reset
+ */
+void md4_hmac_reset( md4_context *ctx );
+
+/**
+ * \brief          Output = HMAC-MD4( hmac key, input buffer )
+ *
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   HMAC-MD4 result
+ */
+void md4_hmac( const unsigned char *key, size_t keylen,
+               const unsigned char *input, size_t ilen,
+               unsigned char output[16] );
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int md4_self_test( int verbose );
+
+/* Internal use */
+void md4_process( md4_context *ctx, const unsigned char data[64] );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* md4.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/md5.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,188 @@
+/**
+ * \file md5.h
+ *
+ * \brief MD5 message digest algorithm (hash function)
+ *
+ *  Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_MD5_H
+#define POLARSSL_MD5_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#include <string.h>
+
+#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
+#include <basetsd.h>
+typedef UINT32 uint32_t;
+#else
+#include <inttypes.h>
+#endif
+
+#define POLARSSL_ERR_MD5_FILE_IO_ERROR                 -0x0074  /**< Read/write error in file. */
+
+#if !defined(POLARSSL_MD5_ALT)
+// Regular implementation
+//
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          MD5 context structure
+ */
+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 */
+
+    unsigned char ipad[64];     /*!< HMAC: inner padding        */
+    unsigned char opad[64];     /*!< HMAC: outer padding        */
+}
+md5_context;
+
+/**
+ * \brief          MD5 context setup
+ *
+ * \param ctx      context to be initialized
+ */
+void md5_starts( md5_context *ctx );
+
+/**
+ * \brief          MD5 process buffer
+ *
+ * \param ctx      MD5 context
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ */
+void md5_update( md5_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief          MD5 final digest
+ *
+ * \param ctx      MD5 context
+ * \param output   MD5 checksum result
+ */
+void md5_finish( md5_context *ctx, unsigned char output[16] );
+
+/* Internal use */
+void md5_process( md5_context *ctx, const unsigned char data[64] );
+
+#ifdef __cplusplus
+}
+#endif
+
+#else  /* POLARSSL_MD5_ALT */
+#include "md5_alt.h"
+#endif /* POLARSSL_MD5_ALT */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          Output = MD5( input buffer )
+ *
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   MD5 checksum result
+ */
+void md5( const unsigned char *input, size_t ilen, unsigned char output[16] );
+
+/**
+ * \brief          Output = MD5( file contents )
+ *
+ * \param path     input file name
+ * \param output   MD5 checksum result
+ *
+ * \return         0 if successful, or POLARSSL_ERR_MD5_FILE_IO_ERROR
+ */
+int md5_file( const char *path, unsigned char output[16] );
+
+/**
+ * \brief          MD5 HMAC context setup
+ *
+ * \param ctx      HMAC context to be initialized
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ */
+void md5_hmac_starts( md5_context *ctx,
+                      const unsigned char *key, size_t keylen );
+
+/**
+ * \brief          MD5 HMAC process buffer
+ *
+ * \param ctx      HMAC context
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ */
+void md5_hmac_update( md5_context *ctx,
+                      const unsigned char *input, size_t ilen );
+
+/**
+ * \brief          MD5 HMAC final digest
+ *
+ * \param ctx      HMAC context
+ * \param output   MD5 HMAC checksum result
+ */
+void md5_hmac_finish( md5_context *ctx, unsigned char output[16] );
+
+/**
+ * \brief          MD5 HMAC context reset
+ *
+ * \param ctx      HMAC context to be reset
+ */
+void md5_hmac_reset( md5_context *ctx );
+
+/**
+ * \brief          Output = HMAC-MD5( hmac key, input buffer )
+ *
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   HMAC-MD5 result
+ */
+void md5_hmac( const unsigned char *key, size_t keylen,
+               const unsigned char *input, size_t ilen,
+               unsigned char output[16] );
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int md5_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* md5.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/md_wrap.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,73 @@
+/**
+ * \file md_wrap.h
+ *
+ * \brief Message digest wrappers.
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ *  Copyright (C) 2006-2011, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_MD_WRAP_H
+#define POLARSSL_MD_WRAP_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+#include "md.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(POLARSSL_MD2_C)
+extern const md_info_t md2_info;
+#endif
+#if defined(POLARSSL_MD4_C)
+extern const md_info_t md4_info;
+#endif
+#if defined(POLARSSL_MD5_C)
+extern const md_info_t md5_info;
+#endif
+#if defined(POLARSSL_RIPEMD160_C)
+extern const md_info_t ripemd160_info;
+#endif
+#if defined(POLARSSL_SHA1_C)
+extern const md_info_t sha1_info;
+#endif
+#if defined(POLARSSL_SHA256_C)
+extern const md_info_t sha224_info;
+extern const md_info_t sha256_info;
+#endif
+#if defined(POLARSSL_SHA512_C)
+extern const md_info_t sha384_info;
+extern const md_info_t sha512_info;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* POLARSSL_MD_WRAP_H */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/memory.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,54 @@
+/**
+ * \file memory.h
+ *
+ * \brief Memory allocation layer (Deprecated to platform layer)
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_MEMORY_H
+#define POLARSSL_MEMORY_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#include <stdlib.h>
+
+#if defined(POLARSSL_MEMORY_C) && !defined(POLARSSL_PLATFORM_MEMORY)
+#define POLARSSL_PLATFORM_MEMORY
+#endif
+
+#include "platform.h"
+#include "memory_buffer_alloc.h"
+
+int memory_set_own( void * (*malloc_func)( size_t ),
+                    void (*free_func)( void * ) )
+{
+    return platform_set_malloc_free( malloc_func, free_func );
+}
+
+
+#endif /* memory.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/memory_buffer_alloc.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,124 @@
+/**
+ * \file memory_buffer_alloc.h
+ *
+ * \brief Buffer-based memory allocator
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_MEMORY_BUFFER_ALLOC_H
+#define POLARSSL_MEMORY_BUFFER_ALLOC_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#include <stdlib.h>
+
+/**
+ * \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(POLARSSL_MEMORY_ALIGN_MULTIPLE)
+#define POLARSSL_MEMORY_ALIGN_MULTIPLE       4 /**< Align on multiples of this value */
+#endif
+
+/* \} name SECTION: Module settings */
+
+#define MEMORY_VERIFY_NONE         0
+#define MEMORY_VERIFY_ALLOC        (1 << 0)
+#define MEMORY_VERIFY_FREE         (1 << 1)
+#define MEMORY_VERIFY_ALWAYS       (MEMORY_VERIFY_ALLOC | MEMORY_VERIFY_FREE)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief   Initialize use of stack-based memory allocator.
+ *          The stack-based allocator does memory management inside the
+ *          presented buffer and does not call malloc() and free().
+ *          It sets the global polarssl_malloc() and polarssl_free() pointers
+ *          to its own functions.
+ *          (Provided polarssl_malloc() and polarssl_free() are thread-safe if
+ *           POLARSSL_THREADING_C is defined)
+ *
+ * \note    This code is not optimized and provides a straight-forward
+ *          implementation of a stack-based memory allocator.
+ *
+ * \param buf   buffer to use as heap
+ * \param len   size of the buffer
+ *
+ * \return              0 if successful
+ */
+int memory_buffer_alloc_init( unsigned char *buf, size_t len );
+
+/**
+ * \brief   Free the mutex for thread-safety and clear remaining memory
+ */
+void memory_buffer_alloc_free( void );
+
+/**
+ * \brief   Determine when the allocator should automatically verify the state
+ *          of the entire chain of headers / meta-data.
+ *          (Default: MEMORY_VERIFY_NONE)
+ *
+ * \param verify    One of MEMORY_VERIFY_NONE, MEMORY_VERIFY_ALLOC,
+ *                  MEMORY_VERIFY_FREE or MEMORY_VERIFY_ALWAYS
+ */
+void memory_buffer_set_verify( int verify );
+
+#if defined(POLARSSL_MEMORY_DEBUG)
+/**
+ * \brief   Print out the status of the allocated memory (primarily for use
+ *          after a program should have de-allocated all memory)
+ *          Prints out a list of 'still allocated' blocks and their stack
+ *          trace if POLARSSL_MEMORY_BACKTRACE is defined.
+ */
+void memory_buffer_alloc_status( void );
+#endif /* POLARSSL_MEMORY_DEBUG */
+
+/**
+ * \brief   Verifies that all headers in the memory buffer are correct
+ *          and contain sane values. Helps debug buffer-overflow errors.
+ *
+ *          Prints out first failure if POLARSSL_MEMORY_DEBUG is defined.
+ *          Prints out full header information if POLARSSL_MEMORY_DEBUG_HEADERS
+ *          is defined. (Includes stack trace information for each block if
+ *          POLARSSL_MEMORY_BACKTRACE is defined as well).
+ *
+ * \returns             0 if verified, 1 otherwise
+ */
+int memory_buffer_alloc_verify( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* memory_buffer_alloc.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/net.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,19 @@
+
+#ifndef POLARSSL_NET_H
+#define POLARSSL_NET_H
+
+#define POLARSSL_ERR_NET_UNKNOWN_HOST                      -0x0056  /**< Failed to get an IP address for the given hostname. */
+#define POLARSSL_ERR_NET_SOCKET_FAILED                     -0x0042  /**< Failed to open a socket. */
+#define POLARSSL_ERR_NET_CONNECT_FAILED                    -0x0044  /**< The connection to the given server / port failed. */
+#define POLARSSL_ERR_NET_BIND_FAILED                       -0x0046  /**< Binding of the socket failed. */
+#define POLARSSL_ERR_NET_LISTEN_FAILED                     -0x0048  /**< Could not listen on the socket. */
+#define POLARSSL_ERR_NET_ACCEPT_FAILED                     -0x004A  /**< Could not accept the incoming connection. */
+#define POLARSSL_ERR_NET_RECV_FAILED                       -0x004C  /**< Reading information from the socket failed. */
+#define POLARSSL_ERR_NET_SEND_FAILED                       -0x004E  /**< Sending information through the socket failed. */
+#define POLARSSL_ERR_NET_CONN_RESET                        -0x0050  /**< Connection was reset by peer. */
+#define POLARSSL_ERR_NET_WANT_READ                         -0x0052  /**< Connection requires a read call. */
+#define POLARSSL_ERR_NET_WANT_WRITE                        -0x0054  /**< Connection requires a write call. */
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/oid.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,568 @@
+/**
+ * \file oid.h
+ *
+ * \brief Object Identifier (OID) database
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_OID_H
+#define POLARSSL_OID_H
+
+#include <string.h>
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+#include "asn1.h"
+#include "pk.h"
+#if defined(POLARSSL_CIPHER_C)
+#include "cipher.h"
+#endif
+
+#if defined(POLARSSL_MD_C)
+#include "md.h"
+#endif
+
+#if defined(POLARSSL_X509_USE_C) || defined(POLARSSL_X509_CREATE_C)
+#include "x509.h"
+#endif
+
+#define POLARSSL_ERR_OID_NOT_FOUND                         -0x002E  /**< OID is not found. */
+#define POLARSSL_ERR_OID_BUF_TOO_SMALL                     -0x000B  /**< output buffer is too small */
+
+/*
+ * Top level OID tuples
+ */
+#define OID_ISO_MEMBER_BODIES           "\x2a"          /* {iso(1) member-body(2)} */
+#define OID_ISO_IDENTIFIED_ORG          "\x2b"          /* {iso(1) identified-organization(3)} */
+#define OID_ISO_CCITT_DS                "\x55"          /* {joint-iso-ccitt(2) ds(5)} */
+#define OID_ISO_ITU_COUNTRY             "\x60"          /* {joint-iso-itu-t(2) country(16)} */
+
+/*
+ * ISO Member bodies OID parts
+ */
+#define OID_COUNTRY_US                  "\x86\x48"      /* {us(840)} */
+#define OID_ORG_RSA_DATA_SECURITY       "\x86\xf7\x0d"  /* {rsadsi(113549)} */
+#define OID_RSA_COMPANY                 OID_ISO_MEMBER_BODIES OID_COUNTRY_US \
+                                        OID_ORG_RSA_DATA_SECURITY /* {iso(1) member-body(2) us(840) rsadsi(113549)} */
+#define OID_ORG_ANSI_X9_62              "\xce\x3d" /* ansi-X9-62(10045) */
+#define OID_ANSI_X9_62                  OID_ISO_MEMBER_BODIES OID_COUNTRY_US \
+                                        OID_ORG_ANSI_X9_62
+
+/*
+ * ISO Identified organization OID parts
+ */
+#define OID_ORG_DOD                     "\x06"          /* {dod(6)} */
+#define OID_ORG_OIW                     "\x0e"
+#define OID_OIW_SECSIG                  OID_ORG_OIW "\x03"
+#define OID_OIW_SECSIG_ALG              OID_OIW_SECSIG "\x02"
+#define OID_OIW_SECSIG_SHA1             OID_OIW_SECSIG_ALG "\x1a"
+#define OID_ORG_CERTICOM                "\x81\x04"  /* certicom(132) */
+#define OID_CERTICOM                    OID_ISO_IDENTIFIED_ORG OID_ORG_CERTICOM
+#define OID_ORG_TELETRUST               "\x24" /* teletrust(36) */
+#define OID_TELETRUST                   OID_ISO_IDENTIFIED_ORG OID_ORG_TELETRUST
+
+/*
+ * ISO ITU OID parts
+ */
+#define OID_ORGANIZATION                "\x01"          /* {organization(1)} */
+#define OID_ISO_ITU_US_ORG              OID_ISO_ITU_COUNTRY OID_COUNTRY_US OID_ORGANIZATION /* {joint-iso-itu-t(2) country(16) us(840) organization(1)} */
+
+#define OID_ORG_GOV                     "\x65"          /* {gov(101)} */
+#define OID_GOV                         OID_ISO_ITU_US_ORG OID_ORG_GOV /* {joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101)} */
+
+#define OID_ORG_NETSCAPE                "\x86\xF8\x42"  /* {netscape(113730)} */
+#define OID_NETSCAPE                    OID_ISO_ITU_US_ORG 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 OID_ID_CE                       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 OID_PKIX                        OID_ISO_IDENTIFIED_ORG OID_ORG_DOD "\x01\x05\x05\x07"
+
+/*
+ * Arc for standard naming attributes
+ */
+#define OID_AT                          OID_ISO_CCITT_DS "\x04" /**< id-at OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 4} */
+#define OID_AT_CN                       OID_AT "\x03" /**< id-at-commonName AttributeType:= {id-at 3} */
+#define OID_AT_SUR_NAME                 OID_AT "\x04" /**< id-at-surName AttributeType:= {id-at 4} */
+#define OID_AT_SERIAL_NUMBER            OID_AT "\x05" /**< id-at-serialNumber AttributeType:= {id-at 5} */
+#define OID_AT_COUNTRY                  OID_AT "\x06" /**< id-at-countryName AttributeType:= {id-at 6} */
+#define OID_AT_LOCALITY                 OID_AT "\x07" /**< id-at-locality AttributeType:= {id-at 7} */
+#define OID_AT_STATE                    OID_AT "\x08" /**< id-at-state AttributeType:= {id-at 8} */
+#define OID_AT_ORGANIZATION             OID_AT "\x0A" /**< id-at-organizationName AttributeType:= {id-at 10} */
+#define OID_AT_ORG_UNIT                 OID_AT "\x0B" /**< id-at-organizationalUnitName AttributeType:= {id-at 11} */
+#define OID_AT_TITLE                    OID_AT "\x0C" /**< id-at-title AttributeType:= {id-at 12} */
+#define OID_AT_POSTAL_ADDRESS           OID_AT "\x10" /**< id-at-postalAddress AttributeType:= {id-at 16} */
+#define OID_AT_POSTAL_CODE              OID_AT "\x11" /**< id-at-postalCode AttributeType:= {id-at 17} */
+#define OID_AT_GIVEN_NAME               OID_AT "\x2A" /**< id-at-givenName AttributeType:= {id-at 42} */
+#define OID_AT_INITIALS                 OID_AT "\x2B" /**< id-at-initials AttributeType:= {id-at 43} */
+#define OID_AT_GENERATION_QUALIFIER     OID_AT "\x2C" /**< id-at-generationQualifier AttributeType:= {id-at 44} */
+#define OID_AT_DN_QUALIFIER             OID_AT "\x2E" /**< id-at-dnQualifier AttributeType:= {id-at 46} */
+#define OID_AT_PSEUDONYM                OID_AT "\x41" /**< id-at-pseudonym AttributeType:= {id-at 65} */
+
+#define 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 OID_AUTHORITY_KEY_IDENTIFIER    OID_ID_CE "\x23" /**< id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::=  { id-ce 35 } */
+#define OID_SUBJECT_KEY_IDENTIFIER      OID_ID_CE "\x0E" /**< id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::=  { id-ce 14 } */
+#define OID_KEY_USAGE                   OID_ID_CE "\x0F" /**< id-ce-keyUsage OBJECT IDENTIFIER ::=  { id-ce 15 } */
+#define OID_CERTIFICATE_POLICIES        OID_ID_CE "\x20" /**< id-ce-certificatePolicies OBJECT IDENTIFIER ::=  { id-ce 32 } */
+#define OID_POLICY_MAPPINGS             OID_ID_CE "\x21" /**< id-ce-policyMappings OBJECT IDENTIFIER ::=  { id-ce 33 } */
+#define OID_SUBJECT_ALT_NAME            OID_ID_CE "\x11" /**< id-ce-subjectAltName OBJECT IDENTIFIER ::=  { id-ce 17 } */
+#define OID_ISSUER_ALT_NAME             OID_ID_CE "\x12" /**< id-ce-issuerAltName OBJECT IDENTIFIER ::=  { id-ce 18 } */
+#define OID_SUBJECT_DIRECTORY_ATTRS     OID_ID_CE "\x09" /**< id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::=  { id-ce 9 } */
+#define OID_BASIC_CONSTRAINTS           OID_ID_CE "\x13" /**< id-ce-basicConstraints OBJECT IDENTIFIER ::=  { id-ce 19 } */
+#define OID_NAME_CONSTRAINTS            OID_ID_CE "\x1E" /**< id-ce-nameConstraints OBJECT IDENTIFIER ::=  { id-ce 30 } */
+#define OID_POLICY_CONSTRAINTS          OID_ID_CE "\x24" /**< id-ce-policyConstraints OBJECT IDENTIFIER ::=  { id-ce 36 } */
+#define OID_EXTENDED_KEY_USAGE          OID_ID_CE "\x25" /**< id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } */
+#define OID_CRL_DISTRIBUTION_POINTS     OID_ID_CE "\x1F" /**< id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::=  { id-ce 31 } */
+#define OID_INIHIBIT_ANYPOLICY          OID_ID_CE "\x36" /**< id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::=  { id-ce 54 } */
+#define OID_FRESHEST_CRL                OID_ID_CE "\x2E" /**< id-ce-freshestCRL OBJECT IDENTIFIER ::=  { id-ce 46 } */
+
+/*
+ * Netscape certificate extensions
+ */
+#define OID_NS_CERT                 OID_NETSCAPE "\x01"
+#define OID_NS_CERT_TYPE            OID_NS_CERT  "\x01"
+#define OID_NS_BASE_URL             OID_NS_CERT  "\x02"
+#define OID_NS_REVOCATION_URL       OID_NS_CERT  "\x03"
+#define OID_NS_CA_REVOCATION_URL    OID_NS_CERT  "\x04"
+#define OID_NS_RENEWAL_URL          OID_NS_CERT  "\x07"
+#define OID_NS_CA_POLICY_URL        OID_NS_CERT  "\x08"
+#define OID_NS_SSL_SERVER_NAME      OID_NS_CERT  "\x0C"
+#define OID_NS_COMMENT              OID_NS_CERT  "\x0D"
+#define OID_NS_DATA_TYPE            OID_NETSCAPE "\x02"
+#define OID_NS_CERT_SEQUENCE        OID_NS_DATA_TYPE "\x05"
+
+/*
+ * OIDs for CRL extensions
+ */
+#define OID_PRIVATE_KEY_USAGE_PERIOD    OID_ID_CE "\x10"
+#define OID_CRL_NUMBER                  OID_ID_CE "\x14" /**< id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 } */
+
+/*
+ * X.509 v3 Extended key usage OIDs
+ */
+#define OID_ANY_EXTENDED_KEY_USAGE      OID_EXTENDED_KEY_USAGE "\x00" /**< anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 } */
+
+#define OID_KP                          OID_PKIX "\x03" /**< id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } */
+#define OID_SERVER_AUTH                 OID_KP "\x01" /**< id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } */
+#define OID_CLIENT_AUTH                 OID_KP "\x02" /**< id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } */
+#define OID_CODE_SIGNING                OID_KP "\x03" /**< id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } */
+#define OID_EMAIL_PROTECTION            OID_KP "\x04" /**< id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } */
+#define OID_TIME_STAMPING               OID_KP "\x08" /**< id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } */
+#define OID_OCSP_SIGNING                OID_KP "\x09" /**< id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } */
+
+/*
+ * PKCS definition OIDs
+ */
+
+#define OID_PKCS                OID_RSA_COMPANY "\x01" /**< pkcs OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) 1 } */
+#define OID_PKCS1               OID_PKCS "\x01" /**< pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } */
+#define OID_PKCS5               OID_PKCS "\x05" /**< pkcs-5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 } */
+#define OID_PKCS9               OID_PKCS "\x09" /**< pkcs-9 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 } */
+#define OID_PKCS12              OID_PKCS "\x0c" /**< pkcs-12 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 } */
+
+/*
+ * PKCS#1 OIDs
+ */
+#define OID_PKCS1_RSA           OID_PKCS1 "\x01" /**< rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 } */
+#define OID_PKCS1_MD2           OID_PKCS1 "\x02" /**< md2WithRSAEncryption ::= { pkcs-1 2 } */
+#define OID_PKCS1_MD4           OID_PKCS1 "\x03" /**< md4WithRSAEncryption ::= { pkcs-1 3 } */
+#define OID_PKCS1_MD5           OID_PKCS1 "\x04" /**< md5WithRSAEncryption ::= { pkcs-1 4 } */
+#define OID_PKCS1_SHA1          OID_PKCS1 "\x05" /**< sha1WithRSAEncryption ::= { pkcs-1 5 } */
+#define OID_PKCS1_SHA224        OID_PKCS1 "\x0e" /**< sha224WithRSAEncryption ::= { pkcs-1 14 } */
+#define OID_PKCS1_SHA256        OID_PKCS1 "\x0b" /**< sha256WithRSAEncryption ::= { pkcs-1 11 } */
+#define OID_PKCS1_SHA384        OID_PKCS1 "\x0c" /**< sha384WithRSAEncryption ::= { pkcs-1 12 } */
+#define OID_PKCS1_SHA512        OID_PKCS1 "\x0d" /**< sha512WithRSAEncryption ::= { pkcs-1 13 } */
+
+#define OID_RSA_SHA_OBS         "\x2B\x0E\x03\x02\x1D"
+
+#define OID_PKCS9_EMAIL         OID_PKCS9 "\x01" /**< emailAddress AttributeType ::= { pkcs-9 1 } */
+
+/*
+ * Digest algorithms
+ */
+#define OID_DIGEST_ALG_MD2              OID_RSA_COMPANY "\x02\x02" /**< id-md2 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 2 } */
+#define OID_DIGEST_ALG_MD4              OID_RSA_COMPANY "\x02\x04" /**< id-md4 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 4 } */
+#define OID_DIGEST_ALG_MD5              OID_RSA_COMPANY "\x02\x05" /**< id-md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 } */
+#define OID_DIGEST_ALG_SHA1             OID_ISO_IDENTIFIED_ORG OID_OIW_SECSIG_SHA1 /**< id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } */
+#define OID_DIGEST_ALG_SHA224           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 OID_DIGEST_ALG_SHA256           OID_GOV "\x03\x04\x02\x01" /**< id-sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */
+
+#define OID_DIGEST_ALG_SHA384           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 OID_DIGEST_ALG_SHA512           OID_GOV "\x03\x04\x02\x03" /**< id-sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */
+
+#define OID_HMAC_SHA1                   OID_RSA_COMPANY "\x02\x07" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } */
+
+/*
+ * Encryption algorithms
+ */
+#define OID_DES_CBC                     OID_ISO_IDENTIFIED_ORG OID_OIW_SECSIG_ALG "\x07" /**< desCBC OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 7 } */
+#define OID_DES_EDE3_CBC                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 OID_PKCS5_PBKDF2                OID_PKCS5 "\x0c" /**< id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12} */
+#define OID_PKCS5_PBES2                 OID_PKCS5 "\x0d" /**< id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13} */
+#define OID_PKCS5_PBMAC1                OID_PKCS5 "\x0e" /**< id-PBMAC1 OBJECT IDENTIFIER ::= {pkcs-5 14} */
+
+/*
+ * PKCS#5 PBES1 algorithms
+ */
+#define OID_PKCS5_PBE_MD2_DES_CBC       OID_PKCS5 "\x01" /**< pbeWithMD2AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 1} */
+#define OID_PKCS5_PBE_MD2_RC2_CBC       OID_PKCS5 "\x04" /**< pbeWithMD2AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 4} */
+#define OID_PKCS5_PBE_MD5_DES_CBC       OID_PKCS5 "\x03" /**< pbeWithMD5AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 3} */
+#define OID_PKCS5_PBE_MD5_RC2_CBC       OID_PKCS5 "\x06" /**< pbeWithMD5AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 6} */
+#define OID_PKCS5_PBE_SHA1_DES_CBC      OID_PKCS5 "\x0a" /**< pbeWithSHA1AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 10} */
+#define OID_PKCS5_PBE_SHA1_RC2_CBC      OID_PKCS5 "\x0b" /**< pbeWithSHA1AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 11} */
+
+/*
+ * PKCS#8 OIDs
+ */
+#define OID_PKCS9_CSR_EXT_REQ           OID_PKCS9 "\x0e" /**< extensionRequest OBJECT IDENTIFIER ::= {pkcs-9 14} */
+
+/*
+ * PKCS#12 PBE OIDs
+ */
+#define OID_PKCS12_PBE                      OID_PKCS12 "\x01" /**< pkcs-12PbeIds OBJECT IDENTIFIER ::= {pkcs-12 1} */
+
+#define OID_PKCS12_PBE_SHA1_RC4_128         OID_PKCS12_PBE "\x01" /**< pbeWithSHAAnd128BitRC4 OBJECT IDENTIFIER ::= {pkcs-12PbeIds 1} */
+#define OID_PKCS12_PBE_SHA1_RC4_40          OID_PKCS12_PBE "\x02" /**< pbeWithSHAAnd40BitRC4 OBJECT IDENTIFIER ::= {pkcs-12PbeIds 2} */
+#define OID_PKCS12_PBE_SHA1_DES3_EDE_CBC    OID_PKCS12_PBE "\x03" /**< pbeWithSHAAnd3-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 3} */
+#define OID_PKCS12_PBE_SHA1_DES2_EDE_CBC    OID_PKCS12_PBE "\x04" /**< pbeWithSHAAnd2-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 4} */
+#define OID_PKCS12_PBE_SHA1_RC2_128_CBC     OID_PKCS12_PBE "\x05" /**< pbeWithSHAAnd128BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 5} */
+#define OID_PKCS12_PBE_SHA1_RC2_40_CBC      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 OID_EC_ALG_UNRESTRICTED         OID_ANSI_X9_62 "\x02\01"
+
+/*   id-ecDH OBJECT IDENTIFIER ::= {
+ *     iso(1) identified-organization(3) certicom(132)
+ *     schemes(1) ecdh(12) } */
+#define OID_EC_ALG_ECDH                 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 OID_EC_GRP_SECP192R1        OID_ANSI_X9_62 "\x03\x01\x01"
+
+/* secp224r1 OBJECT IDENTIFIER ::= {
+ *   iso(1) identified-organization(3) certicom(132) curve(0) 33 } */
+#define OID_EC_GRP_SECP224R1        OID_CERTICOM "\x00\x21"
+
+/* secp256r1 OBJECT IDENTIFIER ::= {
+ *   iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 7 } */
+#define OID_EC_GRP_SECP256R1        OID_ANSI_X9_62 "\x03\x01\x07"
+
+/* secp384r1 OBJECT IDENTIFIER ::= {
+ *   iso(1) identified-organization(3) certicom(132) curve(0) 34 } */
+#define OID_EC_GRP_SECP384R1        OID_CERTICOM "\x00\x22"
+
+/* secp521r1 OBJECT IDENTIFIER ::= {
+ *   iso(1) identified-organization(3) certicom(132) curve(0) 35 } */
+#define OID_EC_GRP_SECP521R1        OID_CERTICOM "\x00\x23"
+
+/* secp192k1 OBJECT IDENTIFIER ::= {
+ *   iso(1) identified-organization(3) certicom(132) curve(0) 31 } */
+#define OID_EC_GRP_SECP192K1        OID_CERTICOM "\x00\x1f"
+
+/* secp224k1 OBJECT IDENTIFIER ::= {
+ *   iso(1) identified-organization(3) certicom(132) curve(0) 32 } */
+#define OID_EC_GRP_SECP224K1        OID_CERTICOM "\x00\x20"
+
+/* secp256k1 OBJECT IDENTIFIER ::= {
+ *   iso(1) identified-organization(3) certicom(132) curve(0) 10 } */
+#define OID_EC_GRP_SECP256K1        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 OID_EC_BRAINPOOL_V1         OID_TELETRUST "\x03\x03\x02\x08\x01\x01"
+
+/* brainpoolP256r1 OBJECT IDENTIFIER ::= {versionOne 7} */
+#define OID_EC_GRP_BP256R1          OID_EC_BRAINPOOL_V1 "\x07"
+
+/* brainpoolP384r1 OBJECT IDENTIFIER ::= {versionOne 11} */
+#define OID_EC_GRP_BP384R1          OID_EC_BRAINPOOL_V1 "\x0B"
+
+/* brainpoolP512r1 OBJECT IDENTIFIER ::= {versionOne 13} */
+#define OID_EC_GRP_BP512R1          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 OID_ANSI_X9_62_FIELD_TYPE   OID_ANSI_X9_62 "\x01"
+#define OID_ANSI_X9_62_PRIME_FIELD  OID_ANSI_X9_62_FIELD_TYPE "\x01"
+
+/*
+ * ECDSA signature identifiers, from RFC 5480
+ */
+#define OID_ANSI_X9_62_SIG          OID_ANSI_X9_62 "\x04" /* signatures(4) */
+#define OID_ANSI_X9_62_SIG_SHA2     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 OID_ECDSA_SHA1              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 OID_ECDSA_SHA224            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 OID_ECDSA_SHA256            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 OID_ECDSA_SHA384            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 OID_ECDSA_SHA512            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     */
+} 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
+ *                  POLARSSL_ERR_OID_BUF_TO_SMALL in case of error
+ */
+int oid_get_numeric_string( char *buf, size_t size, const asn1_buf *oid );
+
+#if defined(POLARSSL_X509_USE_C) || defined(POLARSSL_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 POLARSSL_ERR_OID_NOT_FOUND
+ */
+int oid_get_x509_ext_type( const 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 POLARSSL_ERR_OID_NOT_FOUND
+ */
+int oid_get_attr_short_name( const 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 POLARSSL_ERR_OID_NOT_FOUND
+ */
+int oid_get_pk_alg( const asn1_buf *oid, 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 POLARSSL_ERR_OID_NOT_FOUND
+ */
+int oid_get_oid_by_pk_alg( pk_type_t pk_alg,
+                           const char **oid, size_t *olen );
+
+#if defined(POLARSSL_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 POLARSSL_ERR_OID_NOT_FOUND
+ */
+int oid_get_ec_grp( const asn1_buf *oid, 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 POLARSSL_ERR_OID_NOT_FOUND
+ */
+int oid_get_oid_by_ec_grp( ecp_group_id grp_id,
+                           const char **oid, size_t *olen );
+#endif /* POLARSSL_ECP_C */
+
+#if defined(POLARSSL_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 POLARSSL_ERR_OID_NOT_FOUND
+ */
+int oid_get_sig_alg( const asn1_buf *oid,
+                     md_type_t *md_alg, 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 POLARSSL_ERR_OID_NOT_FOUND
+ */
+int oid_get_sig_alg_desc( const 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 POLARSSL_ERR_OID_NOT_FOUND
+ */
+int oid_get_oid_by_sig_alg( pk_type_t pk_alg, 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 POLARSSL_ERR_OID_NOT_FOUND
+ */
+int oid_get_md_alg( const asn1_buf *oid, md_type_t *md_alg );
+#endif /* POLARSSL_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 POLARSSL_ERR_OID_NOT_FOUND
+ */
+int oid_get_extended_key_usage( const 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 POLARSSL_ERR_OID_NOT_FOUND
+ */
+int oid_get_oid_by_md( md_type_t md_alg, const char **oid, size_t *olen );
+
+#if defined(POLARSSL_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 POLARSSL_ERR_OID_NOT_FOUND
+ */
+int oid_get_cipher_alg( const asn1_buf *oid, cipher_type_t *cipher_alg );
+#endif /* POLARSSL_CIPHER_C */
+
+#if defined(POLARSSL_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 POLARSSL_ERR_OID_NOT_FOUND
+ */
+int oid_get_pkcs12_pbe_alg( const asn1_buf *oid, md_type_t *md_alg,
+                            cipher_type_t *cipher_alg );
+#endif /* POLARSSL_PKCS12_C */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* oid.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/openssl.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,142 @@
+/**
+ * \file openssl.h
+ *
+ * \brief OpenSSL wrapper (definitions, inline functions).
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * OpenSSL wrapper contributed by David Barett
+ */
+#ifndef POLARSSL_OPENSSL_H
+#define POLARSSL_OPENSSL_H
+
+#include "aes.h"
+#include "md5.h"
+#include "rsa.h"
+#include "sha1.h"
+
+#define AES_SIZE                16
+#define AES_BLOCK_SIZE          16
+#define AES_KEY                 aes_context
+#define MD5_CTX                 md5_context
+#define SHA_CTX                 sha1_context
+
+#define SHA1_Init( CTX ) \
+        sha1_starts( (CTX) )
+#define SHA1_Update(  CTX, BUF, LEN ) \
+        sha1_update( (CTX), (unsigned char *)(BUF), (LEN) )
+#define SHA1_Final( OUT, CTX ) \
+        sha1_finish( (CTX), (OUT) )
+
+#define MD5_Init( CTX ) \
+        md5_starts( (CTX) )
+#define MD5_Update( CTX, BUF, LEN ) \
+        md5_update( (CTX), (unsigned char *)(BUF), (LEN) )
+#define MD5_Final( OUT, CTX ) \
+        md5_finish( (CTX), (OUT) )
+
+#define AES_set_encrypt_key( KEY, KEYSIZE, CTX ) \
+        aes_setkey_enc( (CTX), (KEY), (KEYSIZE) )
+#define AES_set_decrypt_key( KEY, KEYSIZE, CTX ) \
+        aes_setkey_dec( (CTX), (KEY), (KEYSIZE) )
+#define AES_cbc_encrypt( INPUT, OUTPUT, LEN, CTX, IV, MODE ) \
+        aes_crypt_cbc( (CTX), (MODE), (LEN), (IV), (INPUT), (OUTPUT) )
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * RSA stuff follows. TODO: needs cleanup
+ */
+inline int __RSA_Passthrough( void *output, void *input, int size )
+{
+    memcpy( output, input, size );
+    return size;
+}
+
+inline rsa_context* d2i_RSA_PUBKEY( void *ignore, unsigned char **bufptr,
+                                    int len )
+{
+    unsigned char *buffer = *(unsigned char **) bufptr;
+    rsa_context *rsa;
+
+    /*
+     * Not a general-purpose parser: only parses public key from *exactly*
+     *   openssl genrsa -out privkey.pem 512 (or 1024)
+     *   openssl rsa -in privkey.pem -out privatekey.der -outform der
+     *   openssl rsa -in privkey.pem -out pubkey.der -outform der -pubout
+     *
+     * TODO: make a general-purpose parse
+     */
+    if( ignore != 0 || ( len != 94 && len != 162 ) )
+        return( 0 );
+
+    rsa = (rsa_context *) malloc( sizeof( rsa_rsa ) );
+    if( rsa == NULL )
+        return( 0 );
+
+    memset( rsa, 0, sizeof( rsa_context ) );
+
+    if( ( len ==  94 &&
+          mpi_read_binary( &rsa->N, &buffer[ 25],  64 ) == 0 &&
+          mpi_read_binary( &rsa->E, &buffer[ 91],   3 ) == 0 ) ||
+        ( len == 162 &&
+          mpi_read_binary( &rsa->N, &buffer[ 29], 128 ) == 0 ) &&
+          mpi_read_binary( &rsa->E, &buffer[159],   3 ) == 0 )
+    {
+        /*
+         * key read successfully
+         */
+        rsa->len = ( mpi_msb( &rsa->N ) + 7 ) >> 3;
+        return( rsa );
+    }
+    else
+    {
+        memset( rsa, 0, sizeof( rsa_context ) );
+        free( rsa );
+        return( 0 );
+    }
+}
+
+#define RSA                     rsa_context
+#define RSA_PKCS1_PADDING       1 /* ignored; always encrypt with this */
+#define RSA_size( CTX )         (CTX)->len
+#define RSA_free( CTX )         rsa_free( CTX )
+#define ERR_get_error( )        "ERR_get_error() not supported"
+#define RSA_blinding_off( IGNORE )
+
+#define d2i_RSAPrivateKey( a, b, c ) new rsa_context /* TODO: C++ bleh */
+
+inline int RSA_public_decrypt ( int size, unsigned char* input, unsigned char* output, RSA* key, int ignore ) { int outsize=size; if( !rsa_pkcs1_decrypt( key, RSA_PUBLIC,  &outsize, input, output ) ) return outsize; else return -1; }
+inline int RSA_private_decrypt( int size, unsigned char* input, unsigned char* output, RSA* key, int ignore ) { int outsize=size; if( !rsa_pkcs1_decrypt( key, RSA_PRIVATE, &outsize, input, output ) ) return outsize; else return -1; }
+inline int RSA_public_encrypt ( int size, unsigned char* input, unsigned char* output, RSA* key, int ignore ) { if( !rsa_pkcs1_encrypt( key, RSA_PUBLIC,  size, input, output ) ) return RSA_size(key); else return -1; }
+inline int RSA_private_encrypt( int size, unsigned char* input, unsigned char* output, RSA* key, int ignore ) { if( !rsa_pkcs1_encrypt( key, RSA_PRIVATE, size, input, output ) ) return RSA_size(key); else return -1; }
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* openssl.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/padlock.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,111 @@
+/**
+ * \file padlock.h
+ *
+ * \brief VIA PadLock ACE for HW encryption/decryption supported by some
+ *        processors
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_PADLOCK_H
+#define POLARSSL_PADLOCK_H
+
+#include "aes.h"
+
+#define POLARSSL_ERR_PADLOCK_DATA_MISALIGNED               -0x0030  /**< Input data should be aligned. */
+
+#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && defined(__i386__)
+
+#ifndef POLARSSL_HAVE_X86
+#define POLARSSL_HAVE_X86
+#endif
+
+#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
+#include <basetsd.h>
+typedef INT32 int32_t;
+#else
+#include <inttypes.h>
+#endif
+
+
+#define PADLOCK_RNG 0x000C
+#define PADLOCK_ACE 0x00C0
+#define PADLOCK_PHE 0x0C00
+#define PADLOCK_PMM 0x3000
+
+#define PADLOCK_ALIGN16(x) (uint32_t *) (16 + ((int32_t) x & ~15))
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          PadLock detection routine
+ *
+ * \param feature  The feature to detect
+ *
+ * \return         1 if CPU has support for the feature, 0 otherwise
+ */
+int padlock_supports( int feature );
+
+/**
+ * \brief          PadLock AES-ECB block en(de)cryption
+ *
+ * \param ctx      AES context
+ * \param mode     AES_ENCRYPT or AES_DECRYPT
+ * \param input    16-byte input block
+ * \param output   16-byte output block
+ *
+ * \return         0 if success, 1 if operation failed
+ */
+int padlock_xcryptecb( aes_context *ctx,
+                       int mode,
+                       const unsigned char input[16],
+                       unsigned char output[16] );
+
+/**
+ * \brief          PadLock AES-CBC buffer en(de)cryption
+ *
+ * \param ctx      AES context
+ * \param mode     AES_ENCRYPT or AES_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 success, 1 if operation failed
+ */
+int padlock_xcryptcbc( aes_context *ctx,
+                       int mode,
+                       size_t length,
+                       unsigned char iv[16],
+                       const unsigned char *input,
+                       unsigned char *output );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAVE_X86  */
+
+#endif /* padlock.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/pbkdf2.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,84 @@
+/**
+ * \file pbkdf2.h
+ *
+ * \brief Password-Based Key Derivation Function 2 (from PKCS#5)
+ *        DEPRECATED: use pkcs5.h instead.
+ *
+ * \author Mathias Olsson <mathias@kompetensum.com>
+ *
+ *  Copyright (C) 2006-2012, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_PBKDF2_H
+#define POLARSSL_PBKDF2_H
+
+#include <string.h>
+
+#include "md.h"
+
+#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
+#include <basetsd.h>
+typedef UINT32 uint32_t;
+#else
+#include <inttypes.h>
+#endif
+
+#define POLARSSL_ERR_PBKDF2_BAD_INPUT_DATA                 -0x007C  /**< Bad input parameters to function. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          PKCS#5 PBKDF2 using HMAC
+ *                 DEPRECATED: Use pkcs5_pbkdf2_hmac() instead!
+ *
+ * \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
+ * \param output   Generated key. Must be at least as big as key_length
+ *
+ * \returns        0 on success, or a PolarSSL error code if verification fails.
+ */
+int pbkdf2_hmac( 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
+ *                 DEPRECATED: Use pkcs5_self_test() instead!
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int pbkdf2_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* pbkdf2.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/pem.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,135 @@
+/**
+ * \file pem.h
+ *
+ * \brief Privacy Enhanced Mail (PEM) decoding
+ *
+ *  Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_PEM_H
+#define POLARSSL_PEM_H
+
+#include <string.h>
+
+/**
+ * \name PEM Error codes
+ * These error codes are returned in case of errors reading the
+ * PEM data.
+ * \{
+ */
+#define POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT          -0x1080  /**< No PEM header or footer found. */
+#define POLARSSL_ERR_PEM_INVALID_DATA                      -0x1100  /**< PEM string is not as expected. */
+#define POLARSSL_ERR_PEM_MALLOC_FAILED                     -0x1180  /**< Failed to allocate memory. */
+#define POLARSSL_ERR_PEM_INVALID_ENC_IV                    -0x1200  /**< RSA IV is not in hex-format. */
+#define POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG                   -0x1280  /**< Unsupported key encryption algorithm. */
+#define POLARSSL_ERR_PEM_PASSWORD_REQUIRED                 -0x1300  /**< Private key password can't be empty. */
+#define POLARSSL_ERR_PEM_PASSWORD_MISMATCH                 -0x1380  /**< Given private key password does not allow for correct decryption. */
+#define POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE               -0x1400  /**< Unavailable feature, e.g. hashing/encryption combination. */
+#define POLARSSL_ERR_PEM_BAD_INPUT_DATA                    -0x1480  /**< Bad input parameters to function. */
+/* \} name */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(POLARSSL_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 */
+}
+pem_context;
+
+/**
+ * \brief       PEM context setup
+ *
+ * \param ctx   context to be initialized
+ */
+void pem_init( 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
+ * \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
+ *                  POLARSSL_ERR_PEM_BAD_INPUT_DATA or
+ *                  POLARSSL_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 pem_read_buffer( 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 pem_free( pem_context *ctx );
+#endif /* POLARSSL_PEM_PARSE_C */
+
+#if defined(POLARSSL_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
+ *                  POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL olen is the required
+ *                  size.
+ */
+int 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 /* POLARSSL_PEM_WRITE_C */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* pem.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/pk.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,576 @@
+/**
+ * \file pk.h
+ *
+ * \brief Public Key abstraction layer
+ *
+ *  Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef POLARSSL_PK_H
+#define POLARSSL_PK_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#include "md.h"
+
+#if defined(POLARSSL_RSA_C)
+#include "rsa.h"
+#endif
+
+#if defined(POLARSSL_ECP_C)
+#include "ecp.h"
+#endif
+
+#if defined(POLARSSL_ECDSA_C)
+#include "ecdsa.h"
+#endif
+
+#define POLARSSL_ERR_PK_MALLOC_FAILED       -0x2F80  /**< Memory alloation failed. */
+#define POLARSSL_ERR_PK_TYPE_MISMATCH       -0x2F00  /**< Type mismatch, eg attempt to encrypt with an ECDSA key */
+#define POLARSSL_ERR_PK_BAD_INPUT_DATA      -0x2E80  /**< Bad input parameters to function. */
+#define POLARSSL_ERR_PK_FILE_IO_ERROR       -0x2E00  /**< Read/write of file failed. */
+#define POLARSSL_ERR_PK_KEY_INVALID_VERSION -0x2D80  /**< Unsupported key version */
+#define POLARSSL_ERR_PK_KEY_INVALID_FORMAT  -0x2D00  /**< Invalid key tag or value. */
+#define POLARSSL_ERR_PK_UNKNOWN_PK_ALG      -0x2C80  /**< Key algorithm is unsupported (only RSA and EC are supported). */
+#define POLARSSL_ERR_PK_PASSWORD_REQUIRED   -0x2C00  /**< Private key password can't be empty. */
+#define POLARSSL_ERR_PK_PASSWORD_MISMATCH   -0x2B80  /**< Given private key password does not allow for correct decryption. */
+#define POLARSSL_ERR_PK_INVALID_PUBKEY      -0x2B00  /**< The pubkey tag or value is invalid (only RSA and EC are supported). */
+#define POLARSSL_ERR_PK_INVALID_ALG         -0x2A80  /**< The algorithm tag or value is invalid. */
+#define POLARSSL_ERR_PK_UNKNOWN_NAMED_CURVE -0x2A00  /**< Elliptic curve is unsupported (only NIST curves are supported). */
+#define POLARSSL_ERR_PK_FEATURE_UNAVAILABLE -0x2980  /**< Unavailable feature, e.g. RSA disabled for RSA key. */
+#define POLARSSL_ERR_PK_SIG_LEN_MISMATCH    -0x2000  /**< The signature is valid but its length is less than expected. */
+
+
+#if defined(POLARSSL_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 macro!
+ */
+#define pk_rsa( pk )        ( (rsa_context *) (pk).pk_ctx )
+#endif /* POLARSSL_RSA_C */
+
+#if defined(POLARSSL_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 macro!
+ */
+#define pk_ec( pk )         ( (ecp_keypair *) (pk).pk_ctx )
+#endif /* POLARSSL_ECP_C */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          Public key types
+ */
+typedef enum {
+    POLARSSL_PK_NONE=0,
+    POLARSSL_PK_RSA,
+    POLARSSL_PK_ECKEY,
+    POLARSSL_PK_ECKEY_DH,
+    POLARSSL_PK_ECDSA,
+    POLARSSL_PK_RSA_ALT,
+} pk_type_t;
+
+/**
+ * \brief           Types for interfacing with the debug module
+ */
+typedef enum
+{
+    POLARSSL_PK_DEBUG_NONE = 0,
+    POLARSSL_PK_DEBUG_MPI,
+    POLARSSL_PK_DEBUG_ECP,
+} pk_debug_type;
+
+/**
+ * \brief           Item to send to the debug module
+ */
+typedef struct
+{
+    pk_debug_type type;
+    const char *name;
+    void *value;
+} pk_debug_item;
+
+/** Maximum number of item send for debugging, plus 1 */
+#define POLARSSL_PK_DEBUG_MAX_ITEMS 3
+
+/**
+ * \brief           Public key information and operations
+ */
+typedef struct
+{
+    /** Public key type */
+    pk_type_t type;
+
+    /** Type name */
+    const char *name;
+
+    /** Get key size in bits */
+    size_t (*get_size)( const void * );
+
+    /** Tell if the context implements this type (e.g. ECKEY can do ECDSA) */
+    int (*can_do)( pk_type_t type );
+
+    /** Verify signature */
+    int (*verify_func)( void *ctx, 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, 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 );
+
+    /** 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, pk_debug_item *items );
+
+} pk_info_t;
+
+/**
+ * \brief           Public key container
+ */
+typedef struct
+{
+    const pk_info_t *   pk_info;    /**< Public key informations        */
+    void *              pk_ctx;     /**< Underlying public key context  */
+} pk_context;
+
+/**
+ * \brief           Types for RSA-alt abstraction
+ */
+typedef int (*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 (*pk_rsa_alt_sign_func)( void *ctx,
+                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+                    int mode, md_type_t md_alg, unsigned int hashlen,
+                    const unsigned char *hash, unsigned char *sig );
+typedef size_t (*pk_rsa_alt_key_len_func)( void *ctx );
+
+/**
+ * \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 pk_info_t *pk_info_from_type( pk_type_t pk_type );
+
+/**
+ * \brief           Initialize a pk_context (as NONE)
+ */
+void pk_init( pk_context *ctx );
+
+/**
+ * \brief           Free a pk_context
+ */
+void pk_free( 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,
+ *                  POLARSSL_ERR_PK_BAD_INPUT_DATA on invalid input,
+ *                  POLARSSL_ERR_PK_MALLOC_FAILED on allocation failure.
+ *
+ * \note            For contexts holding an RSA-alt key, use
+ *                  \c pk_init_ctx_rsa_alt() instead.
+ */
+int pk_init_ctx( pk_context *ctx, const pk_info_t *info );
+
+/**
+ * \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 POLARSSL_ERR_PK_BAD_INPUT_DATA if the
+ *                  context wasn't already initialized as RSA_ALT.
+ *
+ * \note            This function replaces \c pk_init_ctx() for RSA-alt.
+ */
+int pk_init_ctx_rsa_alt( pk_context *ctx, void * key,
+                         pk_rsa_alt_decrypt_func decrypt_func,
+                         pk_rsa_alt_sign_func sign_func,
+                         pk_rsa_alt_key_len_func key_len_func );
+
+/**
+ * \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 pk_get_size( const 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 pk_get_len( const pk_context *ctx )
+{
+    return( ( pk_get_size( 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 pk_can_do( pk_context *ctx, pk_type_t type );
+
+/**
+ * \brief           Verify signature
+ *
+ * \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),
+ *                  POLARSSL_ERR_PK_SIG_LEN_MISMATCH if the signature is
+ *                  valid but its actual length is less than sig_len,
+ *                  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 POLARSSL_MD_NONE, only if hash_len != 0
+ */
+int pk_verify( pk_context *ctx, md_type_t md_alg,
+               const unsigned char *hash, size_t hash_len,
+               const unsigned char *sig, size_t sig_len );
+
+/**
+ * \brief           Make signature
+ *
+ * \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       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            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 POLARSSL_MD_NONE, only if hash_len != 0
+ */
+int pk_sign( pk_context *ctx, 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
+ *
+ * \param ctx       PK context to use
+ * \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
+ *
+ * \return          0 on success, or a specific error code.
+ */
+int pk_decrypt( 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
+ *
+ * \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
+ *
+ * \return          0 on success, or a specific error code.
+ */
+int pk_encrypt( 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           Export debug information
+ *
+ * \param ctx       Context to use
+ * \param items     Place to write debug items
+ *
+ * \return          0 on success or POLARSSL_ERR_PK_BAD_INPUT_DATA
+ */
+int pk_debug( const pk_context *ctx, pk_debug_item *items );
+
+/**
+ * \brief           Access the type name
+ *
+ * \param ctx       Context to use
+ *
+ * \return          Type name on success, or "invalid PK"
+ */
+const char * pk_get_name( const pk_context *ctx );
+
+/**
+ * \brief           Get the key type
+ *
+ * \param ctx       Context to use
+ *
+ * \return          Type on success, or POLARSSL_PK_NONE
+ */
+pk_type_t pk_get_type( const pk_context *ctx );
+
+#if defined(POLARSSL_PK_PARSE_C)
+/** \ingroup pk_module */
+/**
+ * \brief           Parse a private key
+ *
+ * \param ctx       key to be initialized
+ * \param key       input buffer
+ * \param keylen    size of the buffer
+ * \param pwd       password for decryption (optional)
+ * \param pwdlen    size of the password
+ *
+ * \note            On entry, ctx must be empty, either freshly initialised
+ *                  with pk_init() or reset with pk_free(). If you need a
+ *                  specific key type, check the result with pk_can_do().
+ *
+ * \note            The key is also checked for correctness.
+ *
+ * \return          0 if successful, or a specific PK or PEM error code
+ */
+int pk_parse_key( 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
+ *
+ * \param ctx       key to be initialized
+ * \param key       input buffer
+ * \param keylen    size of the buffer
+ *
+ * \note            On entry, ctx must be empty, either freshly initialised
+ *                  with pk_init() or reset with pk_free(). If you need a
+ *                  specific key type, check the result with pk_can_do().
+ *
+ * \note            The key is also checked for correctness.
+ *
+ * \return          0 if successful, or a specific PK or PEM error code
+ */
+int pk_parse_public_key( pk_context *ctx,
+                         const unsigned char *key, size_t keylen );
+
+#if defined(POLARSSL_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 pk_init() or reset with pk_free(). If you need a
+ *                  specific key type, check the result with pk_can_do().
+ *
+ * \note            The key is also checked for correctness.
+ *
+ * \return          0 if successful, or a specific PK or PEM error code
+ */
+int pk_parse_keyfile( 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 private key from
+ *
+ * \note            On entry, ctx must be empty, either freshly initialised
+ *                  with pk_init() or reset with pk_free(). If you need a
+ *                  specific key type, check the result with pk_can_do().
+ *
+ * \note            The key is also checked for correctness.
+ *
+ * \return          0 if successful, or a specific PK or PEM error code
+ */
+int pk_parse_public_keyfile( pk_context *ctx, const char *path );
+#endif /* POLARSSL_FS_IO */
+#endif /* POLARSSL_PK_PARSE_C */
+
+#if defined(POLARSSL_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 pk_write_key_der( 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 pk_write_pubkey_der( pk_context *ctx, unsigned char *buf, size_t size );
+
+#if defined(POLARSSL_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 successful, or a specific error code
+ */
+int pk_write_pubkey_pem( 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 successful, or a specific error code
+ */
+int pk_write_key_pem( pk_context *ctx, unsigned char *buf, size_t size );
+#endif /* POLARSSL_PEM_WRITE_C */
+#endif /* POLARSSL_PK_WRITE_C */
+
+/*
+ * WARNING: Low-level functions. You probably do not want to use these unless
+ *          you are certain you do ;)
+ */
+
+#if defined(POLARSSL_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 pk_parse_subpubkey( unsigned char **p, const unsigned char *end,
+                        pk_context *pk );
+#endif /* POLARSSL_PK_PARSE_C */
+
+#if defined(POLARSSL_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 pk_write_pubkey( unsigned char **p, unsigned char *start,
+                     const pk_context *key );
+#endif /* POLARSSL_PK_WRITE_C */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* POLARSSL_PK_H */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/pk_wrap.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,65 @@
+/**
+ * \file pk.h
+ *
+ * \brief Public Key abstraction layer: wrapper functions
+ *
+ *  Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef POLARSSL_PK_WRAP_H
+#define POLARSSL_PK_WRAP_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#include "pk.h"
+
+/* Container for RSA-alt */
+typedef struct
+{
+    void *key;
+    pk_rsa_alt_decrypt_func decrypt_func;
+    pk_rsa_alt_sign_func sign_func;
+    pk_rsa_alt_key_len_func key_len_func;
+} rsa_alt_context;
+
+#if defined(POLARSSL_RSA_C)
+extern const pk_info_t rsa_info;
+#endif
+
+#if defined(POLARSSL_ECP_C)
+extern const pk_info_t eckey_info;
+extern const pk_info_t eckeydh_info;
+#endif
+
+#if defined(POLARSSL_ECDSA_C)
+extern const pk_info_t ecdsa_info;
+#endif
+
+extern const pk_info_t rsa_alt_info;
+
+#endif /* POLARSSL_PK_WRAP_H */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/pkcs11.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,176 @@
+/**
+ * \file pkcs11.h
+ *
+ * \brief Wrapper for PKCS#11 library libpkcs11-helper
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_PKCS11_H
+#define POLARSSL_PKCS11_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_PKCS11_C)
+
+#include "x509_crt.h"
+
+#include <pkcs11-helper-1.0/pkcs11h-certificate.h>
+
+#if defined(_MSC_VER) && !defined(inline)
+#define inline _inline
+#else
+#if defined(__ARMCC_VERSION) && !defined(inline)
+#define inline __inline
+#endif /* __ARMCC_VERSION */
+#endif /*_MSC_VER */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Context for PKCS #11 private keys.
+ */
+typedef struct {
+        pkcs11h_certificate_t pkcs11h_cert;
+        int len;
+} pkcs11_context;
+
+/**
+ * Fill in a PolarSSL 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 pkcs11_x509_cert_init( x509_crt *cert, pkcs11h_certificate_t pkcs11h_cert );
+
+/**
+ * Initialise a pkcs11_context, storing the given certificate. Note that the
+ * 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 pkcs11_priv_key_init( 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 pkcs11_priv_key_free( 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 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 POLARSSL_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 pkcs11_decrypt( 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 RSA_PRIVATE, for compatibility with rsa.c's signature
+ * \param md_alg   a POLARSSL_MD_* (use POLARSSL_MD_NONE for signing raw data)
+ * \param hashlen  message digest length (for POLARSSL_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 POLARSSL_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 pkcs11_sign( pkcs11_context *ctx,
+                    int mode,
+                    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 ssl_pkcs11_decrypt( void *ctx, int mode, size_t *olen,
+                        const unsigned char *input, unsigned char *output,
+                        size_t output_max_len )
+{
+    return pkcs11_decrypt( (pkcs11_context *) ctx, mode, olen, input, output,
+                           output_max_len );
+}
+
+static inline int ssl_pkcs11_sign( void *ctx,
+                     int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+                     int mode, md_type_t md_alg, unsigned int hashlen,
+                     const unsigned char *hash, unsigned char *sig )
+{
+    ((void) f_rng);
+    ((void) p_rng);
+    return pkcs11_sign( (pkcs11_context *) ctx, mode, md_alg,
+                        hashlen, hash, sig );
+}
+
+static inline size_t ssl_pkcs11_key_len( void *ctx )
+{
+    return ( (pkcs11_context *) ctx )->len;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* POLARSSL_PKCS11_C */
+
+#endif /* POLARSSL_PKCS11_H */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/pkcs12.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,125 @@
+/**
+ * \file pkcs12.h
+ *
+ * \brief PKCS#12 Personal Information Exchange Syntax
+ *
+ *  Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_PKCS12_H
+#define POLARSSL_PKCS12_H
+
+#include <string.h>
+
+#include "md.h"
+#include "cipher.h"
+#include "asn1.h"
+
+#define POLARSSL_ERR_PKCS12_BAD_INPUT_DATA                 -0x1F80  /**< Bad input parameters to function. */
+#define POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE            -0x1F00  /**< Feature not available, e.g. unsupported encryption scheme. */
+#define POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT             -0x1E80  /**< PBE ASN.1 data not as expected. */
+#define POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH              -0x1E00  /**< Given private key password does not allow for correct decryption. */
+
+#define PKCS12_DERIVE_KEY       1   /**< encryption/decryption key */
+#define PKCS12_DERIVE_IV        2   /**< initialization vector     */
+#define PKCS12_DERIVE_MAC_KEY   3   /**< integrity / MAC key       */
+
+#define PKCS12_PBE_DECRYPT      0
+#define 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 PKCS12_PBE_ENCRYPT or 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 PolarSSL error code
+ */
+int pkcs12_pbe_sha1_rc4_128( 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 md-based PBE's
+ *
+ * \param pbe_params an ASN1 buffer containing the pkcs-12PbeParams structure
+ * \param mode       either PKCS12_PBE_ENCRYPT or PKCS12_PBE_DECRYPT
+ * \param cipher_type the cipher used
+ * \param md_type     the 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 PolarSSL error code
+ */
+int pkcs12_pbe( asn1_buf *pbe_params, int mode,
+                cipher_type_t cipher_type, 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 md         md type to use during the derivation
+ * \param id         id that describes the purpose (can be PKCS12_DERIVE_KEY,
+ *                   PKCS12_DERIVE_IV or PKCS12_DERIVE_MAC_KEY)
+ * \param iterations number of iterations
+ *
+ * \return          0 if successful, or a MD, BIGNUM type error.
+ */
+int pkcs12_derivation( unsigned char *data, size_t datalen,
+                       const unsigned char *pwd, size_t pwdlen,
+                       const unsigned char *salt, size_t saltlen,
+                       md_type_t md, int id, int iterations );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* pkcs12.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/pkcs5.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,106 @@
+/**
+ * \file pkcs5.h
+ *
+ * \brief PKCS#5 functions
+ *
+ * \author Mathias Olsson <mathias@kompetensum.com>
+ *
+ *  Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_PKCS5_H
+#define POLARSSL_PKCS5_H
+
+#include <string.h>
+
+#include "asn1.h"
+#include "md.h"
+
+#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
+#include <basetsd.h>
+typedef UINT32 uint32_t;
+#else
+#include <inttypes.h>
+#endif
+
+#define POLARSSL_ERR_PKCS5_BAD_INPUT_DATA                  -0x3f80  /**< Bad input parameters to function. */
+#define POLARSSL_ERR_PKCS5_INVALID_FORMAT                  -0x3f00  /**< Unexpected ASN.1 data. */
+#define POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE             -0x3e80  /**< Requested encryption or digest alg not available. */
+#define POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH               -0x3e00  /**< Given private key password does not allow for correct decryption. */
+
+#define PKCS5_DECRYPT      0
+#define PKCS5_ENCRYPT      1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          PKCS#5 PBES2 function
+ *
+ * \param pbe_params the ASN.1 algorithm parameters
+ * \param mode       either PKCS5_DECRYPT or 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 PolarSSL error code if verification fails.
+ */
+int pkcs5_pbes2( 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
+ * \param output   Generated key. Must be at least as big as key_length
+ *
+ * \returns        0 on success, or a PolarSSL error code if verification fails.
+ */
+int pkcs5_pbkdf2_hmac( 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 pkcs5_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* pkcs5.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/platform.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,130 @@
+/**
+ * \file platform.h
+ *
+ * \brief PolarSSL Platform abstraction layer
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_PLATFORM_H
+#define POLARSSL_PLATFORM_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#include <stdio.h>
+
+#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(POLARSSL_PLATFORM_NO_STD_FUNCTIONS)
+#include <stdlib.h>
+#if !defined(POLARSSL_PLATFORM_STD_PRINTF)
+#define POLARSSL_PLATFORM_STD_PRINTF   printf /**< Default printf to use  */
+#endif
+#if !defined(POLARSSL_PLATFORM_STD_FPRINTF)
+#define POLARSSL_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use */
+#endif
+#if !defined(POLARSSL_PLATFORM_STD_MALLOC)
+#define POLARSSL_PLATFORM_STD_MALLOC   malloc /**< Default allocator to use */
+#endif
+#if !defined(POLARSSL_PLATFORM_STD_FREE)
+#define POLARSSL_PLATFORM_STD_FREE       free /**< Default free to use */
+#endif
+#else /* POLARSSL_PLATFORM_NO_STD_FUNCTIONS */
+#if defined(POLARSSL_PLATFORM_STD_MEM_HDR)
+#include POLARSSL_PLATFORM_STD_MEM_HDR
+#endif
+#endif /* POLARSSL_PLATFORM_NO_STD_FUNCTIONS */
+
+/* \} name SECTION: Module settings */
+
+/*
+ * The function pointers for malloc and free
+ */
+#if defined(POLARSSL_PLATFORM_MEMORY)
+extern void * (*polarssl_malloc)( size_t len );
+extern void (*polarssl_free)( void *ptr );
+
+/**
+ * \brief   Set your own memory implementation function pointers
+ *
+ * \param malloc_func   the malloc function implementation
+ * \param free_func     the free function implementation
+ *
+ * \return              0 if successful
+ */
+int platform_set_malloc_free( void * (*malloc_func)( size_t ),
+                              void (*free_func)( void * ) );
+#else /* POLARSSL_PLATFORM_ENTROPY */
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif /* POLARSSL_PLATFORM_ENTROPY */
+
+/*
+ * The function pointers for printf
+ */
+#if defined(POLARSSL_PLATFORM_PRINTF_ALT)
+extern int (*polarssl_printf)( const char *format, ... );
+
+/**
+ * \brief   Set your own printf function pointer
+ *
+ * \param printf_func   the printf function implementation
+ *
+ * \return              0
+ */
+int platform_set_printf( int (*printf_func)( const char *, ... ) );
+#else /* POLARSSL_PLATFORM_PRINTF_ALT */
+#define polarssl_printf     printf
+#endif /* POLARSSL_PLATFORM_PRINTF_ALT */
+
+/*
+ * The function pointers for fprintf
+ */
+#if defined(POLARSSL_PLATFORM_FPRINTF_ALT)
+extern int (*polarssl_fprintf)( FILE *stream, const char *format, ... );
+
+int platform_set_fprintf( int (*fprintf_func)( FILE *stream, const char *,
+                                               ... ) );
+#else
+#define polarssl_fprintf    fprintf
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* platform.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/ripemd160.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,192 @@
+/**
+ * \file ripemd160.h
+ *
+ * \brief RIPE MD-160 message digest
+ *
+ *  Copyright (C) 2014-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_RIPEMD160_H
+#define POLARSSL_RIPEMD160_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#include <string.h>
+
+#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
+#include <basetsd.h>
+typedef UINT32 uint32_t;
+#else
+#include <inttypes.h>
+#endif
+
+#define POLARSSL_ERR_RIPEMD160_FILE_IO_ERROR              -0x007E  /**< Read/write error in file. */
+
+#if !defined(POLARSSL_RIPEMD160_ALT)
+// Regular implementation
+//
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \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 */
+
+    unsigned char ipad[64];     /*!< HMAC: inner padding        */
+    unsigned char opad[64];     /*!< HMAC: outer padding        */
+}
+ripemd160_context;
+
+/**
+ * \brief          RIPEMD-160 context setup
+ *
+ * \param ctx      context to be initialized
+ */
+void ripemd160_starts( 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
+ */
+void ripemd160_update( 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
+ */
+void ripemd160_finish( ripemd160_context *ctx, unsigned char output[20] );
+
+/* Internal use */
+void ripemd160_process( ripemd160_context *ctx, const unsigned char data[64] );
+
+#ifdef __cplusplus
+}
+#endif
+
+#else  /* POLARSSL_RIPEMD160_ALT */
+#include "ripemd160.h"
+#endif /* POLARSSL_RIPEMD160_ALT */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \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
+ */
+void ripemd160( const unsigned char *input, size_t ilen,
+                unsigned char output[20] );
+
+#if defined(POLARSSL_FS_IO)
+/**
+ * \brief          Output = RIPEMD-160( file contents )
+ *
+ * \param path     input file name
+ * \param output   RIPEMD-160 checksum result
+ *
+ * \return         0 if successful, or POLARSSL_ERR_RIPEMD160_FILE_IO_ERROR
+ */
+int ripemd160_file( const char *path, unsigned char output[20] );
+#endif /* POLARSSL_FS_IO */
+
+/**
+ * \brief          RIPEMD-160 HMAC context setup
+ *
+ * \param ctx      HMAC context to be initialized
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ */
+void ripemd160_hmac_starts( ripemd160_context *ctx,
+                            const unsigned char *key, size_t keylen );
+
+/**
+ * \brief          RIPEMD-160 HMAC process buffer
+ *
+ * \param ctx      HMAC context
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ */
+void ripemd160_hmac_update( ripemd160_context *ctx,
+                            const unsigned char *input, size_t ilen );
+
+/**
+ * \brief          RIPEMD-160 HMAC final digest
+ *
+ * \param ctx      HMAC context
+ * \param output   RIPEMD-160 HMAC checksum result
+ */
+void ripemd160_hmac_finish( ripemd160_context *ctx, unsigned char output[20] );
+
+/**
+ * \brief          RIPEMD-160 HMAC context reset
+ *
+ * \param ctx      HMAC context to be reset
+ */
+void ripemd160_hmac_reset( ripemd160_context *ctx );
+
+/**
+ * \brief          Output = HMAC-RIPEMD-160( hmac key, input buffer )
+ *
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   HMAC-RIPEMD-160 result
+ */
+void ripemd160_hmac( const unsigned char *key, size_t keylen,
+                     const unsigned char *input, size_t ilen,
+                     unsigned char output[20] );
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int ripemd160_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ripemd160.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/rsa.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,612 @@
+/**
+ * \file rsa.h
+ *
+ * \brief The RSA public-key cryptosystem
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_RSA_H
+#define POLARSSL_RSA_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#include "bignum.h"
+#include "md.h"
+
+#if defined(POLARSSL_THREADING_C)
+#include "threading.h"
+#endif
+
+/*
+ * RSA Error codes
+ */
+#define POLARSSL_ERR_RSA_BAD_INPUT_DATA                    -0x4080  /**< Bad input parameters to function. */
+#define POLARSSL_ERR_RSA_INVALID_PADDING                   -0x4100  /**< Input data contains invalid padding and is rejected. */
+#define POLARSSL_ERR_RSA_KEY_GEN_FAILED                    -0x4180  /**< Something failed during generation of a key. */
+#define POLARSSL_ERR_RSA_KEY_CHECK_FAILED                  -0x4200  /**< Key failed to pass the libraries validity check. */
+#define POLARSSL_ERR_RSA_PUBLIC_FAILED                     -0x4280  /**< The public key operation failed. */
+#define POLARSSL_ERR_RSA_PRIVATE_FAILED                    -0x4300  /**< The private key operation failed. */
+#define POLARSSL_ERR_RSA_VERIFY_FAILED                     -0x4380  /**< The PKCS#1 verification failed. */
+#define POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE                  -0x4400  /**< The output buffer for decryption is not large enough. */
+#define POLARSSL_ERR_RSA_RNG_FAILED                        -0x4480  /**< The random generator failed to generate non-zeros. */
+
+/*
+ * RSA constants
+ */
+#define RSA_PUBLIC      0
+#define RSA_PRIVATE     1
+
+#define RSA_PKCS_V15    0
+#define RSA_PKCS_V21    1
+
+#define RSA_SIGN        1
+#define RSA_CRYPT       2
+
+/*
+ * 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.
+ */
+#if defined(POLARSSL_RSA_C)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          RSA context structure
+ */
+typedef struct
+{
+    int ver;                    /*!<  always 0          */
+    size_t len;                 /*!<  size(N) in chars  */
+
+    mpi N;                      /*!<  public modulus    */
+    mpi E;                      /*!<  public exponent   */
+
+    mpi D;                      /*!<  private exponent  */
+    mpi P;                      /*!<  1st prime factor  */
+    mpi Q;                      /*!<  2nd prime factor  */
+    mpi DP;                     /*!<  D % (P - 1)       */
+    mpi DQ;                     /*!<  D % (Q - 1)       */
+    mpi QP;                     /*!<  1 / (Q % P)       */
+
+    mpi RN;                     /*!<  cached R^2 mod N  */
+    mpi RP;                     /*!<  cached R^2 mod P  */
+    mpi RQ;                     /*!<  cached R^2 mod Q  */
+
+#if !defined(POLARSSL_RSA_NO_CRT)
+    mpi Vi;                     /*!<  cached blinding value     */
+    mpi Vf;                     /*!<  cached un-blinding value  */
+#endif
+
+    int padding;                /*!<  RSA_PKCS_V15 for 1.5 padding and
+                                      RSA_PKCS_v21 for OAEP/PSS         */
+    int hash_id;                /*!<  Hash identifier of md_type_t as
+                                      specified in the md.h header file
+                                      for the EME-OAEP and EMSA-PSS
+                                      encoding                          */
+#if defined(POLARSSL_THREADING_C)
+    threading_mutex_t mutex;    /*!<  Thread-safety mutex       */
+#endif
+}
+rsa_context;
+
+/**
+ * \brief          Initialize an RSA context
+ *
+ *                 Note: Set padding to RSA_PKCS_V21 for the RSAES-OAEP
+ *                 encryption scheme and the RSASSA-PSS signature scheme.
+ *
+ * \param ctx      RSA context to be initialized
+ * \param padding  RSA_PKCS_V15 or RSA_PKCS_V21
+ * \param hash_id  RSA_PKCS_V21 hash identifier
+ *
+ * \note           The hash_id parameter is actually ignored
+ *                 when using RSA_PKCS_V15 padding.
+ */
+void rsa_init( rsa_context *ctx,
+               int padding,
+               int hash_id);
+
+/**
+ * \brief          Set padding for an already initialized RSA context
+ *
+ *                 Note: Set padding to RSA_PKCS_V21 for the RSAES-OAEP
+ *                 encryption scheme and the RSASSA-PSS signature scheme.
+ *
+ * \param ctx      RSA context to be set
+ * \param padding  RSA_PKCS_V15 or RSA_PKCS_V21
+ * \param hash_id  RSA_PKCS_V21 hash identifier
+ *
+ * \note           The hash_id parameter is actually ignored
+ *                 when using RSA_PKCS_V15 padding.
+ */
+void rsa_set_padding( rsa_context *ctx, int padding, int hash_id);
+
+/**
+ * \brief          Generate an RSA keypair
+ *
+ * \param ctx      RSA context that will hold the key
+ * \param f_rng    RNG function
+ * \param p_rng    RNG parameter
+ * \param nbits    size of the public key in bits
+ * \param exponent public exponent (e.g., 65537)
+ *
+ * \note           rsa_init() must be called beforehand to setup
+ *                 the RSA context.
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ */
+int rsa_gen_key( rsa_context *ctx,
+                 int (*f_rng)(void *, unsigned char *, size_t),
+                 void *p_rng,
+                 unsigned int nbits, int exponent );
+
+/**
+ * \brief          Check a public RSA key
+ *
+ * \param ctx      RSA context to be checked
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ */
+int rsa_check_pubkey( const rsa_context *ctx );
+
+/**
+ * \brief          Check a private RSA key
+ *
+ * \param ctx      RSA context to be checked
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ */
+int rsa_check_privkey( const rsa_context *ctx );
+
+/**
+ * \brief          Do an RSA public key operation
+ *
+ * \param ctx      RSA context
+ * \param input    input buffer
+ * \param output   output buffer
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note           This function does NOT take care of message
+ *                 padding. Also, be sure to set input[0] = 0 or assure that
+ *                 input is smaller than N.
+ *
+ * \note           The input and output buffers must be large
+ *                 enough (eg. 128 bytes if RSA-1024 is used).
+ */
+int rsa_public( rsa_context *ctx,
+                const unsigned char *input,
+                unsigned char *output );
+
+/**
+ * \brief          Do an RSA private key operation
+ *
+ * \param ctx      RSA context
+ * \param f_rng    RNG function (Needed for blinding)
+ * \param p_rng    RNG parameter
+ * \param input    input buffer
+ * \param output   output buffer
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note           The input and output buffers must be large
+ *                 enough (eg. 128 bytes if RSA-1024 is used).
+ */
+int rsa_private( rsa_context *ctx,
+                 int (*f_rng)(void *, unsigned char *, size_t),
+                 void *p_rng,
+                 const unsigned char *input,
+                 unsigned char *output );
+
+/**
+ * \brief          Generic wrapper to perform a PKCS#1 encryption using the
+ *                 mode from the context. Add the message padding, then do an
+ *                 RSA operation.
+ *
+ * \param ctx      RSA context
+ * \param f_rng    RNG function (Needed for padding and PKCS#1 v2.1 encoding
+ *                               and RSA_PRIVATE)
+ * \param p_rng    RNG parameter
+ * \param mode     RSA_PUBLIC or RSA_PRIVATE
+ * \param ilen     contains the plaintext length
+ * \param input    buffer holding the data to be encrypted
+ * \param output   buffer that will hold the ciphertext
+ *
+ * \return         0 if successful, or an POLARSSL_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).
+ */
+int rsa_pkcs1_encrypt( 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          Perform a PKCS#1 v1.5 encryption (RSAES-PKCS1-v1_5-ENCRYPT)
+ *
+ * \param ctx      RSA context
+ * \param f_rng    RNG function (Needed for padding and RSA_PRIVATE)
+ * \param p_rng    RNG parameter
+ * \param mode     RSA_PUBLIC or RSA_PRIVATE
+ * \param ilen     contains the plaintext length
+ * \param input    buffer holding the data to be encrypted
+ * \param output   buffer that will hold the ciphertext
+ *
+ * \return         0 if successful, or an POLARSSL_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).
+ */
+int rsa_rsaes_pkcs1_v15_encrypt( 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          Perform a PKCS#1 v2.1 OAEP encryption (RSAES-OAEP-ENCRYPT)
+ *
+ * \param ctx      RSA context
+ * \param f_rng    RNG function (Needed for padding and PKCS#1 v2.1 encoding
+ *                               and RSA_PRIVATE)
+ * \param p_rng    RNG parameter
+ * \param mode     RSA_PUBLIC or RSA_PRIVATE
+ * \param label    buffer holding the custom label to use
+ * \param label_len contains the label length
+ * \param ilen     contains the plaintext length
+ * \param input    buffer holding the data to be encrypted
+ * \param output   buffer that will hold the ciphertext
+ *
+ * \return         0 if successful, or an POLARSSL_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).
+ */
+int rsa_rsaes_oaep_encrypt( 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          Generic wrapper to perform a PKCS#1 decryption using the
+ *                 mode from the context. Do an RSA operation, then remove
+ *                 the message padding
+ *
+ * \param ctx      RSA context
+ * \param f_rng    RNG function (Only needed for RSA_PRIVATE)
+ * \param p_rng    RNG parameter
+ * \param mode     RSA_PUBLIC or RSA_PRIVATE
+ * \param olen     will contain the plaintext length
+ * \param input    buffer holding the encrypted data
+ * \param output   buffer that will hold the plaintext
+ * \param output_max_len    maximum length of the output buffer
+ *
+ * \return         0 if successful, or an POLARSSL_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 rsa_pkcs1_decrypt( 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          Perform a PKCS#1 v1.5 decryption (RSAES-PKCS1-v1_5-DECRYPT)
+ *
+ * \param ctx      RSA context
+ * \param f_rng    RNG function (Only needed for RSA_PRIVATE)
+ * \param p_rng    RNG parameter
+ * \param mode     RSA_PUBLIC or RSA_PRIVATE
+ * \param olen     will contain the plaintext length
+ * \param input    buffer holding the encrypted data
+ * \param output   buffer that will hold the plaintext
+ * \param output_max_len    maximum length of the output buffer
+ *
+ * \return         0 if successful, or an POLARSSL_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 rsa_rsaes_pkcs1_v15_decrypt( 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          Perform a PKCS#1 v2.1 OAEP decryption (RSAES-OAEP-DECRYPT)
+ *
+ * \param ctx      RSA context
+ * \param f_rng    RNG function (Only needed for RSA_PRIVATE)
+ * \param p_rng    RNG parameter
+ * \param mode     RSA_PUBLIC or RSA_PRIVATE
+ * \param label    buffer holding the custom label to use
+ * \param label_len contains the label length
+ * \param olen     will contain the plaintext length
+ * \param input    buffer holding the encrypted data
+ * \param output   buffer that will hold the plaintext
+ * \param output_max_len    maximum length of the output buffer
+ *
+ * \return         0 if successful, or an POLARSSL_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 rsa_rsaes_oaep_decrypt( 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          Generic wrapper to perform a PKCS#1 signature using the
+ *                 mode from the context. Do a private RSA operation to sign
+ *                 a message digest
+ *
+ * \param ctx      RSA context
+ * \param f_rng    RNG function (Needed for PKCS#1 v2.1 encoding and for
+ *                               RSA_PRIVATE)
+ * \param p_rng    RNG parameter
+ * \param mode     RSA_PUBLIC or RSA_PRIVATE
+ * \param md_alg   a POLARSSL_MD_* (use POLARSSL_MD_NONE for signing raw data)
+ * \param hashlen  message digest length (for POLARSSL_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 POLARSSL_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).
+ *
+ * \note           In case of PKCS#1 v2.1 encoding keep in mind that
+ *                 the hash_id in the RSA context is the one used for the
+ *                 encoding. hash_id in the function call is the type of hash
+ *                 that is encoded. According to RFC 3447 it is advised to
+ *                 keep both hashes the same.
+ */
+int rsa_pkcs1_sign( rsa_context *ctx,
+                    int (*f_rng)(void *, unsigned char *, size_t),
+                    void *p_rng,
+                    int mode,
+                    md_type_t md_alg,
+                    unsigned int hashlen,
+                    const unsigned char *hash,
+                    unsigned char *sig );
+
+/**
+ * \brief          Perform a PKCS#1 v1.5 signature (RSASSA-PKCS1-v1_5-SIGN)
+ *
+ * \param ctx      RSA context
+ * \param f_rng    RNG function (Only needed for RSA_PRIVATE)
+ * \param p_rng    RNG parameter
+ * \param mode     RSA_PUBLIC or RSA_PRIVATE
+ * \param md_alg   a POLARSSL_MD_* (use POLARSSL_MD_NONE for signing raw data)
+ * \param hashlen  message digest length (for POLARSSL_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 POLARSSL_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 rsa_rsassa_pkcs1_v15_sign( rsa_context *ctx,
+                               int (*f_rng)(void *, unsigned char *, size_t),
+                               void *p_rng,
+                               int mode,
+                               md_type_t md_alg,
+                               unsigned int hashlen,
+                               const unsigned char *hash,
+                               unsigned char *sig );
+
+/**
+ * \brief          Perform a PKCS#1 v2.1 PSS signature (RSASSA-PSS-SIGN)
+ *
+ * \param ctx      RSA context
+ * \param f_rng    RNG function (Needed for PKCS#1 v2.1 encoding and for
+ *                               RSA_PRIVATE)
+ * \param p_rng    RNG parameter
+ * \param mode     RSA_PUBLIC or RSA_PRIVATE
+ * \param md_alg   a POLARSSL_MD_* (use POLARSSL_MD_NONE for signing raw data)
+ * \param hashlen  message digest length (for POLARSSL_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 POLARSSL_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).
+ *
+ * \note           In case of PKCS#1 v2.1 encoding keep in mind that
+ *                 the hash_id in the RSA context is the one used for the
+ *                 encoding. hash_id in the function call is the type of hash
+ *                 that is encoded. According to RFC 3447 it is advised to
+ *                 keep both hashes the same.
+ */
+int rsa_rsassa_pss_sign( rsa_context *ctx,
+                         int (*f_rng)(void *, unsigned char *, size_t),
+                         void *p_rng,
+                         int mode,
+                         md_type_t md_alg,
+                         unsigned int hashlen,
+                         const unsigned char *hash,
+                         unsigned char *sig );
+
+/**
+ * \brief          Generic wrapper to perform a PKCS#1 verification using the
+ *                 mode from the context. Do a public RSA operation and check
+ *                 the message digest
+ *
+ * \param ctx      points to an RSA public key
+ * \param f_rng    RNG function (Only needed for RSA_PRIVATE)
+ * \param p_rng    RNG parameter
+ * \param mode     RSA_PUBLIC or RSA_PRIVATE
+ * \param md_alg   a POLARSSL_MD_* (use POLARSSL_MD_NONE for signing raw data)
+ * \param hashlen  message digest length (for POLARSSL_MD_NONE only)
+ * \param hash     buffer holding the message digest
+ * \param sig      buffer holding the ciphertext
+ *
+ * \return         0 if the verify operation was successful,
+ *                 or an POLARSSL_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).
+ *
+ * \note           In case of PKCS#1 v2.1 encoding keep in mind that
+ *                 the hash_id in the RSA context is the one used for the
+ *                 verification. hash_id in the function call is the type of
+ *                 hash that is verified. According to RFC 3447 it is advised to
+ *                 keep both hashes the same.
+ */
+int rsa_pkcs1_verify( rsa_context *ctx,
+                      int (*f_rng)(void *, unsigned char *, size_t),
+                      void *p_rng,
+                      int mode,
+                      md_type_t md_alg,
+                      unsigned int hashlen,
+                      const unsigned char *hash,
+                      const unsigned char *sig );
+
+/**
+ * \brief          Perform a PKCS#1 v1.5 verification (RSASSA-PKCS1-v1_5-VERIFY)
+ *
+ * \param ctx      points to an RSA public key
+ * \param f_rng    RNG function (Only needed for RSA_PRIVATE)
+ * \param p_rng    RNG parameter
+ * \param mode     RSA_PUBLIC or RSA_PRIVATE
+ * \param md_alg   a POLARSSL_MD_* (use POLARSSL_MD_NONE for signing raw data)
+ * \param hashlen  message digest length (for POLARSSL_MD_NONE only)
+ * \param hash     buffer holding the message digest
+ * \param sig      buffer holding the ciphertext
+ *
+ * \return         0 if the verify operation was successful,
+ *                 or an POLARSSL_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 rsa_rsassa_pkcs1_v15_verify( rsa_context *ctx,
+                                 int (*f_rng)(void *, unsigned char *, size_t),
+                                 void *p_rng,
+                                 int mode,
+                                 md_type_t md_alg,
+                                 unsigned int hashlen,
+                                 const unsigned char *hash,
+                                 const unsigned char *sig );
+
+/**
+ * \brief          Perform a PKCS#1 v2.1 PSS verification (RSASSA-PSS-VERIFY)
+ *
+ * \param ctx      points to an RSA public key
+ * \param f_rng    RNG function (Only needed for RSA_PRIVATE)
+ * \param p_rng    RNG parameter
+ * \param mode     RSA_PUBLIC or RSA_PRIVATE
+ * \param md_alg   a POLARSSL_MD_* (use POLARSSL_MD_NONE for signing raw data)
+ * \param hashlen  message digest length (for POLARSSL_MD_NONE only)
+ * \param hash     buffer holding the message digest
+ * \param sig      buffer holding the ciphertext
+ *
+ * \return         0 if the verify operation was successful,
+ *                 or an POLARSSL_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).
+ *
+ * \note           In case of PKCS#1 v2.1 encoding keep in mind that
+ *                 the hash_id in the RSA context is the one used for the
+ *                 verification. hash_id in the function call is the type of
+ *                 hash that is verified. According to RFC 3447 it is advised to
+ *                 keep both hashes the same.
+ */
+int rsa_rsassa_pss_verify( rsa_context *ctx,
+                           int (*f_rng)(void *, unsigned char *, size_t),
+                           void *p_rng,
+                           int mode,
+                           md_type_t md_alg,
+                           unsigned int hashlen,
+                           const unsigned char *hash,
+                           const unsigned char *sig );
+
+/**
+ * \brief          Copy the components of an RSA context
+ *
+ * \param dst      Destination context
+ * \param src      Source context
+ *
+ * \return         O on success,
+ *                 POLARSSL_ERR_MPI_MALLOC_FAILED on memory allocation failure
+ */
+int rsa_copy( rsa_context *dst, const rsa_context *src );
+
+/**
+ * \brief          Free the components of an RSA key
+ *
+ * \param ctx      RSA Context to free
+ */
+void rsa_free( rsa_context *ctx );
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int rsa_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* POLARSSL_RSA_C */
+
+#endif /* rsa.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/sha1.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,188 @@
+/**
+ * \file sha1.h
+ *
+ * \brief SHA-1 cryptographic hash function
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_SHA1_H
+#define POLARSSL_SHA1_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#include <string.h>
+
+#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
+#include <basetsd.h>
+typedef UINT32 uint32_t;
+#else
+#include <inttypes.h>
+#endif
+
+#define POLARSSL_ERR_SHA1_FILE_IO_ERROR                -0x0076  /**< Read/write error in file. */
+
+#if !defined(POLARSSL_SHA1_ALT)
+// Regular implementation
+//
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          SHA-1 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 */
+
+    unsigned char ipad[64];     /*!< HMAC: inner padding        */
+    unsigned char opad[64];     /*!< HMAC: outer padding        */
+}
+sha1_context;
+
+/**
+ * \brief          SHA-1 context setup
+ *
+ * \param ctx      context to be initialized
+ */
+void sha1_starts( sha1_context *ctx );
+
+/**
+ * \brief          SHA-1 process buffer
+ *
+ * \param ctx      SHA-1 context
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ */
+void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief          SHA-1 final digest
+ *
+ * \param ctx      SHA-1 context
+ * \param output   SHA-1 checksum result
+ */
+void sha1_finish( sha1_context *ctx, unsigned char output[20] );
+
+/* Internal use */
+void sha1_process( sha1_context *ctx, const unsigned char data[64] );
+
+#ifdef __cplusplus
+}
+#endif
+
+#else  /* POLARSSL_SHA1_ALT */
+#include "sha1_alt.h"
+#endif /* POLARSSL_SHA1_ALT */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          Output = SHA-1( input buffer )
+ *
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   SHA-1 checksum result
+ */
+void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] );
+
+/**
+ * \brief          Output = SHA-1( file contents )
+ *
+ * \param path     input file name
+ * \param output   SHA-1 checksum result
+ *
+ * \return         0 if successful, or POLARSSL_ERR_SHA1_FILE_IO_ERROR
+ */
+int sha1_file( const char *path, unsigned char output[20] );
+
+/**
+ * \brief          SHA-1 HMAC context setup
+ *
+ * \param ctx      HMAC context to be initialized
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ */
+void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key,
+                       size_t keylen );
+
+/**
+ * \brief          SHA-1 HMAC process buffer
+ *
+ * \param ctx      HMAC context
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ */
+void sha1_hmac_update( sha1_context *ctx, const unsigned char *input,
+                       size_t ilen );
+
+/**
+ * \brief          SHA-1 HMAC final digest
+ *
+ * \param ctx      HMAC context
+ * \param output   SHA-1 HMAC checksum result
+ */
+void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] );
+
+/**
+ * \brief          SHA-1 HMAC context reset
+ *
+ * \param ctx      HMAC context to be reset
+ */
+void sha1_hmac_reset( sha1_context *ctx );
+
+/**
+ * \brief          Output = HMAC-SHA-1( hmac key, input buffer )
+ *
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   HMAC-SHA-1 result
+ */
+void sha1_hmac( const unsigned char *key, size_t keylen,
+                const unsigned char *input, size_t ilen,
+                unsigned char output[20] );
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int sha1_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* sha1.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/sha256.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,196 @@
+/**
+ * \file sha256.h
+ *
+ * \brief SHA-224 and SHA-256 cryptographic hash function
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_SHA256_H
+#define POLARSSL_SHA256_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#include <string.h>
+
+#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
+#include <basetsd.h>
+typedef UINT32 uint32_t;
+#else
+#include <inttypes.h>
+#endif
+
+#define POLARSSL_ERR_SHA256_FILE_IO_ERROR              -0x0078  /**< Read/write error in file. */
+
+#if !defined(POLARSSL_SHA256_ALT)
+// Regular implementation
+//
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          SHA-256 context structure
+ */
+typedef struct
+{
+    uint32_t total[2];          /*!< number of bytes processed  */
+    uint32_t state[8];          /*!< intermediate digest state  */
+    unsigned char buffer[64];   /*!< data block being processed */
+
+    unsigned char ipad[64];     /*!< HMAC: inner padding        */
+    unsigned char opad[64];     /*!< HMAC: outer padding        */
+    int is224;                  /*!< 0 => SHA-256, else SHA-224 */
+}
+sha256_context;
+
+/**
+ * \brief          SHA-256 context setup
+ *
+ * \param ctx      context to be initialized
+ * \param is224    0 = use SHA256, 1 = use SHA224
+ */
+void sha256_starts( sha256_context *ctx, int is224 );
+
+/**
+ * \brief          SHA-256 process buffer
+ *
+ * \param ctx      SHA-256 context
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ */
+void sha256_update( sha256_context *ctx, const unsigned char *input,
+                    size_t ilen );
+
+/**
+ * \brief          SHA-256 final digest
+ *
+ * \param ctx      SHA-256 context
+ * \param output   SHA-224/256 checksum result
+ */
+void sha256_finish( sha256_context *ctx, unsigned char output[32] );
+
+/* Internal use */
+void sha256_process( sha256_context *ctx, const unsigned char data[64] );
+
+#ifdef __cplusplus
+}
+#endif
+
+#else  /* POLARSSL_SHA256_ALT */
+#include "sha256_alt.h"
+#endif /* POLARSSL_SHA256_ALT */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          Output = SHA-256( input buffer )
+ *
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   SHA-224/256 checksum result
+ * \param is224    0 = use SHA256, 1 = use SHA224
+ */
+void sha256( const unsigned char *input, size_t ilen,
+           unsigned char output[32], int is224 );
+
+/**
+ * \brief          Output = SHA-256( file contents )
+ *
+ * \param path     input file name
+ * \param output   SHA-224/256 checksum result
+ * \param is224    0 = use SHA256, 1 = use SHA224
+ *
+ * \return         0 if successful, or POLARSSL_ERR_SHA256_FILE_IO_ERROR
+ */
+int sha256_file( const char *path, unsigned char output[32], int is224 );
+
+/**
+ * \brief          SHA-256 HMAC context setup
+ *
+ * \param ctx      HMAC context to be initialized
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ * \param is224    0 = use SHA256, 1 = use SHA224
+ */
+void sha256_hmac_starts( sha256_context *ctx, const unsigned char *key,
+                         size_t keylen, int is224 );
+
+/**
+ * \brief          SHA-256 HMAC process buffer
+ *
+ * \param ctx      HMAC context
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ */
+void sha256_hmac_update( sha256_context *ctx, const unsigned char *input,
+                         size_t ilen );
+
+/**
+ * \brief          SHA-256 HMAC final digest
+ *
+ * \param ctx      HMAC context
+ * \param output   SHA-224/256 HMAC checksum result
+ */
+void sha256_hmac_finish( sha256_context *ctx, unsigned char output[32] );
+
+/**
+ * \brief          SHA-256 HMAC context reset
+ *
+ * \param ctx      HMAC context to be reset
+ */
+void sha256_hmac_reset( sha256_context *ctx );
+
+/**
+ * \brief          Output = HMAC-SHA-256( hmac key, input buffer )
+ *
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   HMAC-SHA-224/256 result
+ * \param is224    0 = use SHA256, 1 = use SHA224
+ */
+void sha256_hmac( const unsigned char *key, size_t keylen,
+                  const unsigned char *input, size_t ilen,
+                  unsigned char output[32], int is224 );
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int sha256_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* sha256.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/sha512.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,197 @@
+/**
+ * \file sha512.h
+ *
+ * \brief SHA-384 and SHA-512 cryptographic hash function
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_SHA512_H
+#define POLARSSL_SHA512_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#include <string.h>
+
+#if defined(_MSC_VER) || defined(__WATCOMC__)
+  #define UL64(x) x##ui64
+  typedef unsigned __int64 uint64_t;
+#else
+  #include <inttypes.h>
+  #define UL64(x) x##ULL
+#endif
+
+#define POLARSSL_ERR_SHA512_FILE_IO_ERROR              -0x007A  /**< Read/write error in file. */
+
+#if !defined(POLARSSL_SHA512_ALT)
+// Regular implementation
+//
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          SHA-512 context structure
+ */
+typedef struct
+{
+    uint64_t total[2];          /*!< number of bytes processed  */
+    uint64_t state[8];          /*!< intermediate digest state  */
+    unsigned char buffer[128];  /*!< data block being processed */
+
+    unsigned char ipad[128];    /*!< HMAC: inner padding        */
+    unsigned char opad[128];    /*!< HMAC: outer padding        */
+    int is384;                  /*!< 0 => SHA-512, else SHA-384 */
+}
+sha512_context;
+
+/**
+ * \brief          SHA-512 context setup
+ *
+ * \param ctx      context to be initialized
+ * \param is384    0 = use SHA512, 1 = use SHA384
+ */
+void sha512_starts( sha512_context *ctx, int is384 );
+
+/**
+ * \brief          SHA-512 process buffer
+ *
+ * \param ctx      SHA-512 context
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ */
+void sha512_update( sha512_context *ctx, const unsigned char *input,
+                    size_t ilen );
+
+/**
+ * \brief          SHA-512 final digest
+ *
+ * \param ctx      SHA-512 context
+ * \param output   SHA-384/512 checksum result
+ */
+void sha512_finish( sha512_context *ctx, unsigned char output[64] );
+
+#ifdef __cplusplus
+}
+#endif
+
+#else  /* POLARSSL_SHA512_ALT */
+#include "sha512_alt.h"
+#endif /* POLARSSL_SHA512_ALT */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          Output = SHA-512( input buffer )
+ *
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   SHA-384/512 checksum result
+ * \param is384    0 = use SHA512, 1 = use SHA384
+ */
+void sha512( const unsigned char *input, size_t ilen,
+             unsigned char output[64], int is384 );
+
+/**
+ * \brief          Output = SHA-512( file contents )
+ *
+ * \param path     input file name
+ * \param output   SHA-384/512 checksum result
+ * \param is384    0 = use SHA512, 1 = use SHA384
+ *
+ * \return         0 if successful, or POLARSSL_ERR_SHA512_FILE_IO_ERROR
+ */
+int sha512_file( const char *path, unsigned char output[64], int is384 );
+
+/**
+ * \brief          SHA-512 HMAC context setup
+ *
+ * \param ctx      HMAC context to be initialized
+ * \param is384    0 = use SHA512, 1 = use SHA384
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ */
+void sha512_hmac_starts( sha512_context *ctx, const unsigned char *key,
+                         size_t keylen, int is384 );
+
+/**
+ * \brief          SHA-512 HMAC process buffer
+ *
+ * \param ctx      HMAC context
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ */
+void sha512_hmac_update( sha512_context *ctx, const unsigned char *input,
+                         size_t ilen );
+
+/**
+ * \brief          SHA-512 HMAC final digest
+ *
+ * \param ctx      HMAC context
+ * \param output   SHA-384/512 HMAC checksum result
+ */
+void sha512_hmac_finish( sha512_context *ctx, unsigned char output[64] );
+
+/**
+ * \brief          SHA-512 HMAC context reset
+ *
+ * \param ctx      HMAC context to be reset
+ */
+void sha512_hmac_reset( sha512_context *ctx );
+
+/**
+ * \brief          Output = HMAC-SHA-512( hmac key, input buffer )
+ *
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   HMAC-SHA-384/512 result
+ * \param is384    0 = use SHA512, 1 = use SHA384
+ */
+void sha512_hmac( const unsigned char *key, size_t keylen,
+                const unsigned char *input, size_t ilen,
+                unsigned char output[64], int is384 );
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int sha512_self_test( int verbose );
+
+/* Internal use */
+void sha512_process( sha512_context *ctx, const unsigned char data[128] );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* sha512.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/ssl.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,1710 @@
+/**
+ * \file ssl.h
+ *
+ * \brief SSL/TLS functions.
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_SSL_H
+#define POLARSSL_SSL_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+#include "net.h"
+#include "bignum.h"
+
+#include "ssl_ciphersuites.h"
+
+#if defined(POLARSSL_MD5_C)
+#include "md5.h"
+#endif
+
+#if defined(POLARSSL_SHA1_C)
+#include "sha1.h"
+#endif
+
+#if defined(POLARSSL_SHA256_C)
+#include "sha256.h"
+#endif
+
+#if defined(POLARSSL_SHA512_C)
+#include "sha512.h"
+#endif
+
+// for session tickets
+#if defined(POLARSSL_AES_C)
+#include "aes.h"
+#endif
+
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+#include "x509_crt.h"
+#include "x509_crl.h"
+#endif
+
+#if defined(POLARSSL_DHM_C)
+#include "dhm.h"
+#endif
+
+#if defined(POLARSSL_ECDH_C)
+#include "ecdh.h"
+#endif
+
+#if defined(POLARSSL_ZLIB_SUPPORT)
+#include "zlib.h"
+#endif
+
+#if defined(POLARSSL_HAVE_TIME)
+#include <time.h>
+#endif
+
+/* For convenience below and in programs */
+#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) ||                           \
+    defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) ||                       \
+    defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) ||                       \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
+#define POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ||                   \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
+#define POLARSSL_KEY_EXCHANGE__SOME__ECDHE_ENABLED
+#endif
+
+#if defined(_MSC_VER) && !defined(inline)
+#define inline _inline
+#else
+#if defined(__ARMCC_VERSION) && !defined(inline)
+#define inline __inline
+#endif /* __ARMCC_VERSION */
+#endif /*_MSC_VER */
+
+/*
+ * SSL Error codes
+ */
+#define POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE               -0x7080  /**< The requested feature is not available. */
+#define POLARSSL_ERR_SSL_BAD_INPUT_DATA                    -0x7100  /**< Bad input parameters to function. */
+#define POLARSSL_ERR_SSL_INVALID_MAC                       -0x7180  /**< Verification of the message MAC failed. */
+#define POLARSSL_ERR_SSL_INVALID_RECORD                    -0x7200  /**< An invalid SSL record was received. */
+#define POLARSSL_ERR_SSL_CONN_EOF                          -0x7280  /**< The connection indicated an EOF. */
+#define POLARSSL_ERR_SSL_UNKNOWN_CIPHER                    -0x7300  /**< An unknown cipher was received. */
+#define POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN                  -0x7380  /**< The server has no ciphersuites in common with the client. */
+#define POLARSSL_ERR_SSL_NO_RNG                            -0x7400  /**< No RNG was provided to the SSL module. */
+#define POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE             -0x7480  /**< No client certification received from the client, but required by the authentication mode. */
+#define POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE             -0x7500  /**< Our own certificate(s) is/are too large to send in an SSL message.*/
+#define POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED              -0x7580  /**< The own certificate is not set, but needed by the server. */
+#define POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED              -0x7600  /**< The own private key or pre-shared key is not set, but needed. */
+#define POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED                 -0x7680  /**< No CA Chain is set, but required to operate. */
+#define POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE                -0x7700  /**< An unexpected message was received from our peer. */
+#define POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE               -0x7780  /**< A fatal alert message was received from our peer. */
+#define POLARSSL_ERR_SSL_PEER_VERIFY_FAILED                -0x7800  /**< Verification of our peer failed. */
+#define POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY                 -0x7880  /**< The peer notified us that the connection is going to be closed. */
+#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO               -0x7900  /**< Processing of the ClientHello handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO               -0x7980  /**< Processing of the ServerHello handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE                -0x7A00  /**< Processing of the Certificate handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST        -0x7A80  /**< Processing of the CertificateRequest handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE        -0x7B00  /**< Processing of the ServerKeyExchange handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE          -0x7B80  /**< Processing of the ServerHelloDone handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE        -0x7C00  /**< Processing of the ClientKeyExchange handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP     -0x7C80  /**< Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public. */
+#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS     -0x7D00  /**< Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret. */
+#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY         -0x7D80  /**< Processing of the CertificateVerify handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC         -0x7E00  /**< Processing of the ChangeCipherSpec handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_FINISHED                   -0x7E80  /**< Processing of the Finished handshake message failed. */
+#define POLARSSL_ERR_SSL_MALLOC_FAILED                     -0x7F00  /**< Memory allocation failed */
+#define POLARSSL_ERR_SSL_HW_ACCEL_FAILED                   -0x7F80  /**< Hardware acceleration function returned with error */
+#define POLARSSL_ERR_SSL_HW_ACCEL_FALLTHROUGH              -0x6F80  /**< Hardware acceleration function skipped / left alone data */
+#define POLARSSL_ERR_SSL_COMPRESSION_FAILED                -0x6F00  /**< Processing of the compression / decompression failed */
+#define POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION           -0x6E80  /**< Handshake protocol not within min/max boundaries */
+#define POLARSSL_ERR_SSL_BAD_HS_NEW_SESSION_TICKET         -0x6E00  /**< Processing of the NewSessionTicket handshake message failed. */
+#define POLARSSL_ERR_SSL_SESSION_TICKET_EXPIRED            -0x6D80  /**< Session ticket has expired. */
+#define POLARSSL_ERR_SSL_PK_TYPE_MISMATCH                  -0x6D00  /**< Public key type mismatch (eg, asked for RSA key exchange and presented EC key) */
+#define POLARSSL_ERR_SSL_UNKNOWN_IDENTITY                  -0x6C80  /**< Unknown identity received (eg, PSK identity) */
+#define POLARSSL_ERR_SSL_INTERNAL_ERROR                    -0x6C00  /**< Internal error (eg, unexpected failure in lower-level module) */
+#define POLARSSL_ERR_SSL_COUNTER_WRAPPING                  -0x6B80  /**< A counter would wrap (eg, too many messages exchanged). */
+
+/*
+ * Various constants
+ */
+#define SSL_MAJOR_VERSION_3             3
+#define SSL_MINOR_VERSION_0             0   /*!< SSL v3.0 */
+#define SSL_MINOR_VERSION_1             1   /*!< TLS v1.0 */
+#define SSL_MINOR_VERSION_2             2   /*!< TLS v1.1 */
+#define SSL_MINOR_VERSION_3             3   /*!< TLS v1.2 */
+
+/* Determine minimum supported version */
+#define SSL_MIN_MAJOR_VERSION           SSL_MAJOR_VERSION_3
+
+#if defined(POLARSSL_SSL_PROTO_SSL3)
+#define SSL_MIN_MINOR_VERSION           SSL_MINOR_VERSION_0
+#else
+#if defined(POLARSSL_SSL_PROTO_TLS1)
+#define SSL_MIN_MINOR_VERSION           SSL_MINOR_VERSION_1
+#else
+#if defined(POLARSSL_SSL_PROTO_TLS1_1)
+#define SSL_MIN_MINOR_VERSION           SSL_MINOR_VERSION_2
+#else
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+#define SSL_MIN_MINOR_VERSION           SSL_MINOR_VERSION_3
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
+#endif /* POLARSSL_SSL_PROTO_TLS1_1 */
+#endif /* POLARSSL_SSL_PROTO_TLS1   */
+#endif /* POLARSSL_SSL_PROTO_SSL3   */
+
+/* Determine maximum supported version */
+#define SSL_MAX_MAJOR_VERSION           SSL_MAJOR_VERSION_3
+
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+#define SSL_MAX_MINOR_VERSION           SSL_MINOR_VERSION_3
+#else
+#if defined(POLARSSL_SSL_PROTO_TLS1_1)
+#define SSL_MAX_MINOR_VERSION           SSL_MINOR_VERSION_2
+#else
+#if defined(POLARSSL_SSL_PROTO_TLS1)
+#define SSL_MAX_MINOR_VERSION           SSL_MINOR_VERSION_1
+#else
+#if defined(POLARSSL_SSL_PROTO_SSL3)
+#define SSL_MAX_MINOR_VERSION           SSL_MINOR_VERSION_0
+#endif /* POLARSSL_SSL_PROTO_SSL3   */
+#endif /* POLARSSL_SSL_PROTO_TLS1   */
+#endif /* POLARSSL_SSL_PROTO_TLS1_1 */
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
+
+/* RFC 6066 section 4, see also mfl_code_to_length in ssl_tls.c
+ * NONE must be zero so that memset()ing structure to zero works */
+#define SSL_MAX_FRAG_LEN_NONE           0   /*!< don't use this extension   */
+#define SSL_MAX_FRAG_LEN_512            1   /*!< MaxFragmentLength 2^9      */
+#define SSL_MAX_FRAG_LEN_1024           2   /*!< MaxFragmentLength 2^10     */
+#define SSL_MAX_FRAG_LEN_2048           3   /*!< MaxFragmentLength 2^11     */
+#define SSL_MAX_FRAG_LEN_4096           4   /*!< MaxFragmentLength 2^12     */
+#define SSL_MAX_FRAG_LEN_INVALID        5   /*!< first invalid value        */
+
+#define SSL_IS_CLIENT                   0
+#define SSL_IS_SERVER                   1
+#define SSL_COMPRESS_NULL               0
+#define SSL_COMPRESS_DEFLATE            1
+
+#define SSL_VERIFY_NONE                 0
+#define SSL_VERIFY_OPTIONAL             1
+#define SSL_VERIFY_REQUIRED             2
+
+#define SSL_INITIAL_HANDSHAKE           0
+#define SSL_RENEGOTIATION               1   /* In progress */
+#define SSL_RENEGOTIATION_DONE          2   /* Done */
+#define SSL_RENEGOTIATION_PENDING       3   /* Requested (server only) */
+
+#define SSL_LEGACY_RENEGOTIATION        0
+#define SSL_SECURE_RENEGOTIATION        1
+
+#define SSL_RENEGOTIATION_DISABLED      0
+#define SSL_RENEGOTIATION_ENABLED       1
+
+#define SSL_LEGACY_NO_RENEGOTIATION     0
+#define SSL_LEGACY_ALLOW_RENEGOTIATION  1
+#define SSL_LEGACY_BREAK_HANDSHAKE      2
+
+#define SSL_TRUNC_HMAC_DISABLED         0
+#define SSL_TRUNC_HMAC_ENABLED          1
+#define SSL_TRUNCATED_HMAC_LEN          10  /* 80 bits, rfc 6066 section 7 */
+
+#define SSL_SESSION_TICKETS_DISABLED     0
+#define SSL_SESSION_TICKETS_ENABLED      1
+
+/**
+ * \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(SSL_DEFAULT_TICKET_LIFETIME)
+#define SSL_DEFAULT_TICKET_LIFETIME     86400 /**< Lifetime of session tickets (if enabled) */
+#endif
+
+/*
+ * Size of the input / output buffer.
+ * Note: the RFC defines the default size of SSL / TLS messages. If you
+ * change the value here, other clients / servers may not be able to
+ * communicate with you anymore. Only change this value if you control
+ * both sides of the connection and have it reduced at both sides!
+ */
+#if !defined(SSL_MAX_CONTENT_LEN)
+#define SSL_MAX_CONTENT_LEN         16384   /**< Size of the input / output buffer */
+#endif
+
+/* \} name SECTION: Module settings */
+
+/*
+ * Allow an extra 301 bytes for the record header
+ * and encryption overhead: counter (8) + header (5) + MAC (32) + padding (256)
+ * and allow for a maximum of 1024 of compression expansion if
+ * enabled.
+ */
+#if defined(POLARSSL_ZLIB_SUPPORT)
+#define SSL_COMPRESSION_ADD          1024
+#else
+#define SSL_COMPRESSION_ADD             0
+#endif
+
+#define SSL_BUFFER_LEN (SSL_MAX_CONTENT_LEN + SSL_COMPRESSION_ADD + 301)
+
+#define SSL_EMPTY_RENEGOTIATION_INFO    0xFF   /**< renegotiation info ext */
+
+/*
+ * Supported Signature and Hash algorithms (For TLS 1.2)
+ * RFC 5246 section 7.4.1.4.1
+ */
+#define SSL_HASH_NONE                0
+#define SSL_HASH_MD5                 1
+#define SSL_HASH_SHA1                2
+#define SSL_HASH_SHA224              3
+#define SSL_HASH_SHA256              4
+#define SSL_HASH_SHA384              5
+#define SSL_HASH_SHA512              6
+
+#define SSL_SIG_ANON                 0
+#define SSL_SIG_RSA                  1
+#define SSL_SIG_ECDSA                3
+
+/*
+ * Client Certificate Types
+ * RFC 5246 section 7.4.4 plus RFC 4492 section 5.5
+ */
+#define SSL_CERT_TYPE_RSA_SIGN       1
+#define SSL_CERT_TYPE_ECDSA_SIGN    64
+
+/*
+ * Message, alert and handshake types
+ */
+#define SSL_MSG_CHANGE_CIPHER_SPEC     20
+#define SSL_MSG_ALERT                  21
+#define SSL_MSG_HANDSHAKE              22
+#define SSL_MSG_APPLICATION_DATA       23
+
+#define SSL_ALERT_LEVEL_WARNING         1
+#define SSL_ALERT_LEVEL_FATAL           2
+
+#define SSL_ALERT_MSG_CLOSE_NOTIFY           0  /* 0x00 */
+#define SSL_ALERT_MSG_UNEXPECTED_MESSAGE    10  /* 0x0A */
+#define SSL_ALERT_MSG_BAD_RECORD_MAC        20  /* 0x14 */
+#define SSL_ALERT_MSG_DECRYPTION_FAILED     21  /* 0x15 */
+#define SSL_ALERT_MSG_RECORD_OVERFLOW       22  /* 0x16 */
+#define SSL_ALERT_MSG_DECOMPRESSION_FAILURE 30  /* 0x1E */
+#define SSL_ALERT_MSG_HANDSHAKE_FAILURE     40  /* 0x28 */
+#define SSL_ALERT_MSG_NO_CERT               41  /* 0x29 */
+#define SSL_ALERT_MSG_BAD_CERT              42  /* 0x2A */
+#define SSL_ALERT_MSG_UNSUPPORTED_CERT      43  /* 0x2B */
+#define SSL_ALERT_MSG_CERT_REVOKED          44  /* 0x2C */
+#define SSL_ALERT_MSG_CERT_EXPIRED          45  /* 0x2D */
+#define SSL_ALERT_MSG_CERT_UNKNOWN          46  /* 0x2E */
+#define SSL_ALERT_MSG_ILLEGAL_PARAMETER     47  /* 0x2F */
+#define SSL_ALERT_MSG_UNKNOWN_CA            48  /* 0x30 */
+#define SSL_ALERT_MSG_ACCESS_DENIED         49  /* 0x31 */
+#define SSL_ALERT_MSG_DECODE_ERROR          50  /* 0x32 */
+#define SSL_ALERT_MSG_DECRYPT_ERROR         51  /* 0x33 */
+#define SSL_ALERT_MSG_EXPORT_RESTRICTION    60  /* 0x3C */
+#define SSL_ALERT_MSG_PROTOCOL_VERSION      70  /* 0x46 */
+#define SSL_ALERT_MSG_INSUFFICIENT_SECURITY 71  /* 0x47 */
+#define SSL_ALERT_MSG_INTERNAL_ERROR        80  /* 0x50 */
+#define SSL_ALERT_MSG_USER_CANCELED         90  /* 0x5A */
+#define SSL_ALERT_MSG_NO_RENEGOTIATION     100  /* 0x64 */
+#define SSL_ALERT_MSG_UNSUPPORTED_EXT      110  /* 0x6E */
+#define SSL_ALERT_MSG_UNRECOGNIZED_NAME    112  /* 0x70 */
+#define SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY 115  /* 0x73 */
+#define SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL 120 /* 0x78 */
+
+#define SSL_HS_HELLO_REQUEST            0
+#define SSL_HS_CLIENT_HELLO             1
+#define SSL_HS_SERVER_HELLO             2
+#define SSL_HS_NEW_SESSION_TICKET       4
+#define SSL_HS_CERTIFICATE             11
+#define SSL_HS_SERVER_KEY_EXCHANGE     12
+#define SSL_HS_CERTIFICATE_REQUEST     13
+#define SSL_HS_SERVER_HELLO_DONE       14
+#define SSL_HS_CERTIFICATE_VERIFY      15
+#define SSL_HS_CLIENT_KEY_EXCHANGE     16
+#define SSL_HS_FINISHED                20
+
+/*
+ * TLS extensions
+ */
+#define TLS_EXT_SERVERNAME                   0
+#define TLS_EXT_SERVERNAME_HOSTNAME          0
+
+#define TLS_EXT_MAX_FRAGMENT_LENGTH          1
+
+#define TLS_EXT_TRUNCATED_HMAC               4
+
+#define TLS_EXT_SUPPORTED_ELLIPTIC_CURVES   10
+#define TLS_EXT_SUPPORTED_POINT_FORMATS     11
+
+#define TLS_EXT_SIG_ALG                     13
+
+#define TLS_EXT_ALPN                        16
+
+#define TLS_EXT_SESSION_TICKET              35
+
+#define TLS_EXT_RENEGOTIATION_INFO      0xFF01
+
+/*
+ * TLS extension flags (for extensions with outgoing ServerHello content
+ * that need it (e.g. for RENEGOTIATION_INFO the server already knows because
+ * of state of the renegotiation flag, so no indicator is required)
+ */
+#define TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT (1 << 0)
+
+/*
+ * Size defines
+ */
+#if !defined(POLARSSL_MPI_MAX_SIZE)
+#define POLARSSL_PREMASTER_SIZE             512
+#else
+#define POLARSSL_PREMASTER_SIZE             POLARSSL_MPI_MAX_SIZE
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Generic function pointers for allowing external RSA private key
+ * implementations.
+ */
+typedef int (*rsa_decrypt_func)( void *ctx, int mode, size_t *olen,
+                        const unsigned char *input, unsigned char *output,
+                        size_t output_max_len );
+typedef int (*rsa_sign_func)( void *ctx,
+                     int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+                     int mode, md_type_t md_alg, unsigned int hashlen,
+                     const unsigned char *hash, unsigned char *sig );
+typedef size_t (*rsa_key_len_func)( void *ctx );
+
+/*
+ * SSL state machine
+ */
+typedef enum
+{
+    SSL_HELLO_REQUEST,
+    SSL_CLIENT_HELLO,
+    SSL_SERVER_HELLO,
+    SSL_SERVER_CERTIFICATE,
+    SSL_SERVER_KEY_EXCHANGE,
+    SSL_CERTIFICATE_REQUEST,
+    SSL_SERVER_HELLO_DONE,
+    SSL_CLIENT_CERTIFICATE,
+    SSL_CLIENT_KEY_EXCHANGE,
+    SSL_CERTIFICATE_VERIFY,
+    SSL_CLIENT_CHANGE_CIPHER_SPEC,
+    SSL_CLIENT_FINISHED,
+    SSL_SERVER_CHANGE_CIPHER_SPEC,
+    SSL_SERVER_FINISHED,
+    SSL_FLUSH_BUFFERS,
+    SSL_HANDSHAKE_WRAPUP,
+    SSL_HANDSHAKE_OVER,
+    SSL_SERVER_NEW_SESSION_TICKET,
+}
+ssl_states;
+
+typedef struct _ssl_session ssl_session;
+typedef struct _ssl_context ssl_context;
+typedef struct _ssl_transform ssl_transform;
+typedef struct _ssl_handshake_params ssl_handshake_params;
+#if defined(POLARSSL_SSL_SESSION_TICKETS)
+typedef struct _ssl_ticket_keys ssl_ticket_keys;
+#endif
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+typedef struct _ssl_key_cert ssl_key_cert;
+#endif
+
+/*
+ * This structure is used for storing current session data.
+ */
+struct _ssl_session
+{
+#if defined(POLARSSL_HAVE_TIME)
+    time_t start;               /*!< starting time      */
+#endif
+    int ciphersuite;            /*!< chosen ciphersuite */
+    int compression;            /*!< chosen compression */
+    size_t length;              /*!< session id length  */
+    unsigned char id[32];       /*!< session identifier */
+    unsigned char master[48];   /*!< the master secret  */
+
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+    x509_crt *peer_cert;        /*!< peer X.509 cert chain */
+#endif /* POLARSSL_X509_CRT_PARSE_C */
+    int verify_result;          /*!<  verification result     */
+
+#if defined(POLARSSL_SSL_SESSION_TICKETS)
+    unsigned char *ticket;      /*!< RFC 5077 session ticket */
+    size_t ticket_len;          /*!< session ticket length   */
+    uint32_t ticket_lifetime;   /*!< ticket lifetime hint    */
+#endif /* POLARSSL_SSL_SESSION_TICKETS */
+
+#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH)
+    unsigned char mfl_code;     /*!< MaxFragmentLength negotiated by peer */
+#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */
+
+#if defined(POLARSSL_SSL_TRUNCATED_HMAC)
+    int trunc_hmac;             /*!< flag for truncated hmac activation   */
+#endif /* POLARSSL_SSL_TRUNCATED_HMAC */
+};
+
+/*
+ * This structure contains a full set of runtime transform parameters
+ * either in negotiation or active.
+ */
+struct _ssl_transform
+{
+    /*
+     * Session specific crypto layer
+     */
+    const ssl_ciphersuite_t *ciphersuite_info;
+                                        /*!<  Chosen cipersuite_info  */
+    unsigned int keylen;                /*!<  symmetric key length    */
+    size_t minlen;                      /*!<  min. ciphertext length  */
+    size_t ivlen;                       /*!<  IV length               */
+    size_t fixed_ivlen;                 /*!<  Fixed part of IV (AEAD) */
+    size_t maclen;                      /*!<  MAC length              */
+
+    unsigned char iv_enc[16];           /*!<  IV (encryption)         */
+    unsigned char iv_dec[16];           /*!<  IV (decryption)         */
+
+#if defined(POLARSSL_SSL_PROTO_SSL3)
+    /* Needed only for SSL v3.0 secret */
+    unsigned char mac_enc[48];          /*!<  SSL v3.0 secret (enc)   */
+    unsigned char mac_dec[48];          /*!<  SSL v3.0 secret (dec)   */
+#endif /* POLARSSL_SSL_PROTO_SSL3 */
+
+    md_context_t md_ctx_enc;            /*!<  MAC (encryption)        */
+    md_context_t md_ctx_dec;            /*!<  MAC (decryption)        */
+
+    cipher_context_t cipher_ctx_enc;    /*!<  encryption context      */
+    cipher_context_t cipher_ctx_dec;    /*!<  decryption context      */
+
+    /*
+     * Session specific compression layer
+     */
+#if defined(POLARSSL_ZLIB_SUPPORT)
+    z_stream ctx_deflate;               /*!<  compression context     */
+    z_stream ctx_inflate;               /*!<  decompression context   */
+#endif
+};
+
+/*
+ * This structure contains the parameters only needed during handshake.
+ */
+struct _ssl_handshake_params
+{
+    /*
+     * Handshake specific crypto variables
+     */
+    int sig_alg;                        /*!<  Signature algorithm     */
+    int cert_type;                      /*!<  Requested cert type     */
+    int verify_sig_alg;                 /*!<  Signature algorithm for verify */
+#if defined(POLARSSL_DHM_C)
+    dhm_context dhm_ctx;                /*!<  DHM key exchange        */
+#endif
+#if defined(POLARSSL_ECDH_C)
+    ecdh_context ecdh_ctx;              /*!<  ECDH key exchange       */
+#endif
+#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C)
+    const ecp_curve_info **curves;      /*!<  Supported elliptic curves */
+#endif
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+    /**
+     * Current key/cert or key/cert list.
+     * On client: pointer to ssl->key_cert, only the first entry used.
+     * On server: starts as a pointer to ssl->key_cert, then becomes
+     * a pointer to the chosen key from this list or the SNI list.
+     */
+    ssl_key_cert *key_cert;
+#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
+    ssl_key_cert *sni_key_cert;         /*!<  key/cert list from SNI  */
+#endif
+#endif /* POLARSSL_X509_CRT_PARSE_C */
+
+    /*
+     * Checksum contexts
+     */
+#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_1)
+       md5_context fin_md5;
+      sha1_context fin_sha1;
+#endif
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+#if defined(POLARSSL_SHA256_C)
+    sha256_context fin_sha256;
+#endif
+#if defined(POLARSSL_SHA512_C)
+    sha512_context fin_sha512;
+#endif
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
+
+    void (*update_checksum)(ssl_context *, const unsigned char *, size_t);
+    void (*calc_verify)(ssl_context *, unsigned char *);
+    void (*calc_finished)(ssl_context *, unsigned char *, int);
+    int  (*tls_prf)(const unsigned char *, size_t, const char *,
+                    const unsigned char *, size_t,
+                    unsigned char *, size_t);
+
+    size_t pmslen;                      /*!<  premaster length        */
+
+    unsigned char randbytes[64];        /*!<  random bytes            */
+    unsigned char premaster[POLARSSL_PREMASTER_SIZE];
+                                        /*!<  premaster secret        */
+
+    int resume;                         /*!<  session resume indicator*/
+    int max_major_ver;                  /*!< max. major version client*/
+    int max_minor_ver;                  /*!< max. minor version client*/
+    int cli_exts;                       /*!< client extension presence*/
+
+#if defined(POLARSSL_SSL_SESSION_TICKETS)
+    int new_session_ticket;             /*!< use NewSessionTicket?    */
+#endif /* POLARSSL_SSL_SESSION_TICKETS */
+};
+
+#if defined(POLARSSL_SSL_SESSION_TICKETS)
+/*
+ * Parameters needed to secure session tickets
+ */
+struct _ssl_ticket_keys
+{
+    unsigned char key_name[16];     /*!< name to quickly discard bad tickets */
+    aes_context enc;                /*!< encryption context                  */
+    aes_context dec;                /*!< decryption context                  */
+    unsigned char mac_key[16];      /*!< authentication key                  */
+};
+#endif /* POLARSSL_SSL_SESSION_TICKETS */
+
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+/*
+ * List of certificate + private key pairs
+ */
+struct _ssl_key_cert
+{
+    x509_crt *cert;                 /*!< cert                       */
+    pk_context *key;                /*!< private key                */
+    int key_own_alloc;              /*!< did we allocate key?       */
+    ssl_key_cert *next;             /*!< next key/cert pair         */
+};
+#endif /* POLARSSL_X509_CRT_PARSE_C */
+
+struct _ssl_context
+{
+    /*
+     * Miscellaneous
+     */
+    int state;                  /*!< SSL handshake: current state     */
+    int renegotiation;          /*!< Initial or renegotiation         */
+
+    int major_ver;              /*!< equal to  SSL_MAJOR_VERSION_3    */
+    int minor_ver;              /*!< either 0 (SSL3) or 1 (TLS1.0)    */
+
+    int max_major_ver;          /*!< max. major version used          */
+    int max_minor_ver;          /*!< max. minor version used          */
+    int min_major_ver;          /*!< min. major version used          */
+    int min_minor_ver;          /*!< min. minor version used          */
+
+    /*
+     * Callbacks (RNG, debug, I/O, verification)
+     */
+    int  (*f_rng)(void *, unsigned char *, size_t);
+    void (*f_dbg)(void *, int, const char *);
+    int (*f_recv)(void *, unsigned char *, size_t);
+    int (*f_send)(void *, const unsigned char *, size_t);
+    int (*f_get_cache)(void *, ssl_session *);
+    int (*f_set_cache)(void *, const ssl_session *);
+
+    void *p_rng;                /*!< context for the RNG function     */
+    void *p_dbg;                /*!< context for the debug function   */
+    void *p_recv;               /*!< context for reading operations   */
+    void *p_send;               /*!< context for writing operations   */
+    void *p_get_cache;          /*!< context for cache retrieval      */
+    void *p_set_cache;          /*!< context for cache store          */
+    void *p_hw_data;            /*!< context for HW acceleration      */
+
+#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
+    int (*f_sni)(void *, ssl_context *, const unsigned char *, size_t);
+    void *p_sni;                /*!< context for SNI extension        */
+#endif
+
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+    int (*f_vrfy)(void *, x509_crt *, int, int *);
+    void *p_vrfy;               /*!< context for verification         */
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
+    int (*f_psk)(void *, ssl_context *, const unsigned char *, size_t);
+    void *p_psk;               /*!< context for PSK retrieval         */
+#endif
+
+    /*
+     * Session layer
+     */
+    ssl_session *session_in;            /*!<  current session data (in)   */
+    ssl_session *session_out;           /*!<  current session data (out)  */
+    ssl_session *session;               /*!<  negotiated session data     */
+    ssl_session *session_negotiate;     /*!<  session data in negotiation */
+
+    ssl_handshake_params *handshake;    /*!<  params required only during
+                                              the handshake process        */
+
+    /*
+     * Record layer transformations
+     */
+    ssl_transform *transform_in;        /*!<  current transform params (in)   */
+    ssl_transform *transform_out;       /*!<  current transform params (in)   */
+    ssl_transform *transform;           /*!<  negotiated transform params     */
+    ssl_transform *transform_negotiate; /*!<  transform params in negotiation */
+
+    /*
+     * Record layer (incoming data)
+     */
+    unsigned char *in_ctr;      /*!< 64-bit incoming message counter  */
+    unsigned char *in_hdr;      /*!< 5-byte record header (in_ctr+8)  */
+    unsigned char *in_iv;       /*!< ivlen-byte IV (in_hdr+5)         */
+    unsigned char *in_msg;      /*!< message contents (in_iv+ivlen)   */
+    unsigned char *in_offt;     /*!< read offset in application data  */
+
+    int in_msgtype;             /*!< record header: message type      */
+    size_t in_msglen;           /*!< record header: message length    */
+    size_t in_left;             /*!< amount of data read so far       */
+
+    size_t in_hslen;            /*!< current handshake message length */
+    int nb_zero;                /*!< # of 0-length encrypted messages */
+    int record_read;            /*!< record is already present        */
+
+    /*
+     * Record layer (outgoing data)
+     */
+    unsigned char *out_ctr;     /*!< 64-bit outgoing message counter  */
+    unsigned char *out_hdr;     /*!< 5-byte record header (out_ctr+8) */
+    unsigned char *out_iv;      /*!< ivlen-byte IV (out_hdr+5)        */
+    unsigned char *out_msg;     /*!< message contents (out_iv+ivlen)  */
+
+    int out_msgtype;            /*!< record header: message type      */
+    size_t out_msglen;          /*!< record header: message length    */
+    size_t out_left;            /*!< amount of data not yet written   */
+
+#if defined(POLARSSL_ZLIB_SUPPORT)
+    unsigned char *compress_buf;        /*!<  zlib data buffer        */
+#endif
+#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH)
+    unsigned char mfl_code;     /*!< MaxFragmentLength chosen by us   */
+#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */
+
+    /*
+     * PKI layer
+     */
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+    ssl_key_cert *key_cert;             /*!<  own certificate(s)/key(s) */
+
+    x509_crt *ca_chain;                 /*!<  own trusted CA chain      */
+    x509_crl *ca_crl;                   /*!<  trusted CA CRLs           */
+    const char *peer_cn;                /*!<  expected peer CN          */
+#endif /* POLARSSL_X509_CRT_PARSE_C */
+
+    /*
+     * Support for generating and checking session tickets
+     */
+#if defined(POLARSSL_SSL_SESSION_TICKETS)
+    ssl_ticket_keys *ticket_keys;       /*!<  keys for ticket encryption */
+#endif /* POLARSSL_SSL_SESSION_TICKETS */
+
+    /*
+     * User settings
+     */
+    int endpoint;                       /*!<  0: client, 1: server    */
+    int authmode;                       /*!<  verification mode       */
+    int client_auth;                    /*!<  flag for client auth.   */
+    int verify_result;                  /*!<  verification result     */
+    int disable_renegotiation;          /*!<  enable/disable renegotiation   */
+    int allow_legacy_renegotiation;     /*!<  allow legacy renegotiation     */
+    const int *ciphersuite_list[4];     /*!<  allowed ciphersuites / version */
+#if defined(POLARSSL_SSL_SET_CURVES)
+    const ecp_group_id *curve_list;     /*!<  allowed curves                 */
+#endif
+#if defined(POLARSSL_SSL_TRUNCATED_HMAC)
+    int trunc_hmac;                     /*!<  negotiate truncated hmac?      */
+#endif
+#if defined(POLARSSL_SSL_SESSION_TICKETS)
+    int session_tickets;                /*!<  use session tickets?    */
+    int ticket_lifetime;                /*!<  session ticket lifetime */
+#endif
+
+#if defined(POLARSSL_DHM_C)
+    mpi dhm_P;                          /*!<  prime modulus for DHM   */
+    mpi dhm_G;                          /*!<  generator for DHM       */
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
+    /*
+     * PSK values
+     */
+    unsigned char *psk;
+    size_t         psk_len;
+    unsigned char *psk_identity;
+    size_t         psk_identity_len;
+#endif
+
+#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
+    /*
+     * SNI extension
+     */
+    unsigned char *hostname;
+    size_t         hostname_len;
+#endif
+
+#if defined(POLARSSL_SSL_ALPN)
+    /*
+     * ALPN extension
+     */
+    const char **alpn_list;     /*!<  ordered list of supported protocols   */
+    const char *alpn_chosen;    /*!<  negotiated protocol                   */
+#endif
+
+    /*
+     * Secure renegotiation
+     */
+    int secure_renegotiation;           /*!<  does peer support legacy or
+                                              secure renegotiation           */
+    size_t verify_data_len;             /*!<  length of verify data stored   */
+    char own_verify_data[36];           /*!<  previous handshake verify data */
+    char peer_verify_data[36];          /*!<  previous handshake verify data */
+};
+
+#if defined(POLARSSL_SSL_HW_RECORD_ACCEL)
+
+#define SSL_CHANNEL_OUTBOUND    0
+#define SSL_CHANNEL_INBOUND     1
+
+extern int (*ssl_hw_record_init)(ssl_context *ssl,
+                const unsigned char *key_enc, const unsigned char *key_dec,
+                size_t keylen,
+                const unsigned char *iv_enc,  const unsigned char *iv_dec,
+                size_t ivlen,
+                const unsigned char *mac_enc, const unsigned char *mac_dec,
+                size_t maclen);
+extern int (*ssl_hw_record_activate)(ssl_context *ssl, int direction);
+extern int (*ssl_hw_record_reset)(ssl_context *ssl);
+extern int (*ssl_hw_record_write)(ssl_context *ssl);
+extern int (*ssl_hw_record_read)(ssl_context *ssl);
+extern int (*ssl_hw_record_finish)(ssl_context *ssl);
+#endif /* POLARSSL_SSL_HW_RECORD_ACCEL */
+
+/**
+ * \brief Returns the list of ciphersuites supported by the SSL/TLS module.
+ *
+ * \return              a statically allocated array of ciphersuites, the last
+ *                      entry is 0.
+ */
+const int *ssl_list_ciphersuites( void );
+
+/**
+ * \brief               Return the name of the ciphersuite associated with the
+ *                      given ID
+ *
+ * \param ciphersuite_id SSL ciphersuite ID
+ *
+ * \return              a string containing the ciphersuite name
+ */
+const char *ssl_get_ciphersuite_name( const int ciphersuite_id );
+
+/**
+ * \brief               Return the ID of the ciphersuite associated with the
+ *                      given name
+ *
+ * \param ciphersuite_name SSL ciphersuite name
+ *
+ * \return              the ID with the ciphersuite or 0 if not found
+ */
+int ssl_get_ciphersuite_id( const char *ciphersuite_name );
+
+/**
+ * \brief          Initialize an SSL context
+ *                 (An individual SSL context is not thread-safe)
+ *
+ * \param ssl      SSL context
+ *
+ * \return         0 if successful, or POLARSSL_ERR_SSL_MALLOC_FAILED if
+ *                 memory allocation failed
+ */
+int ssl_init( ssl_context *ssl );
+
+/**
+ * \brief          Reset an already initialized SSL context for re-use
+ *                 while retaining application-set variables, function
+ *                 pointers and data.
+ *
+ * \param ssl      SSL context
+ * \return         0 if successful, or POLASSL_ERR_SSL_MALLOC_FAILED,
+                   POLARSSL_ERR_SSL_HW_ACCEL_FAILED or
+ *                 POLARSSL_ERR_SSL_COMPRESSION_FAILED
+ */
+int ssl_session_reset( ssl_context *ssl );
+
+/**
+ * \brief          Set the current endpoint type
+ *
+ * \param ssl      SSL context
+ * \param endpoint must be SSL_IS_CLIENT or SSL_IS_SERVER
+ *
+ * \note           This function should be called right after ssl_init() since
+ *                 some other ssl_set_foo() functions depend on it.
+ */
+void ssl_set_endpoint( ssl_context *ssl, int endpoint );
+
+/**
+ * \brief          Set the certificate verification mode
+ *
+ * \param ssl      SSL context
+ * \param authmode can be:
+ *
+ *  SSL_VERIFY_NONE:      peer certificate is not checked (default),
+ *                        this is insecure and SHOULD be avoided.
+ *
+ *  SSL_VERIFY_OPTIONAL:  peer certificate is checked, however the
+ *                        handshake continues even if verification failed;
+ *                        ssl_get_verify_result() can be called after the
+ *                        handshake is complete.
+ *
+ *  SSL_VERIFY_REQUIRED:  peer *must* present a valid certificate,
+ *                        handshake is aborted if verification failed.
+ *
+ * \note On client, SSL_VERIFY_REQUIRED is the recommended mode.
+ * With SSL_VERIFY_OPTIONAL, the user needs to call ssl_get_verify_result() at
+ * the right time(s), which may not be obvious, while REQUIRED always perform
+ * the verification as soon as possible. For example, REQUIRED was protecting
+ * against the "triple handshake" attack even before it was found.
+ */
+void ssl_set_authmode( ssl_context *ssl, int authmode );
+
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+/**
+ * \brief          Set the verification callback (Optional).
+ *
+ *                 If set, the verify callback is called for each
+ *                 certificate in the chain. For implementation
+ *                 information, please see \c x509parse_verify()
+ *
+ * \param ssl      SSL context
+ * \param f_vrfy   verification function
+ * \param p_vrfy   verification parameter
+ */
+void ssl_set_verify( ssl_context *ssl,
+                     int (*f_vrfy)(void *, x509_crt *, int, int *),
+                     void *p_vrfy );
+#endif /* POLARSSL_X509_CRT_PARSE_C */
+
+/**
+ * \brief          Set the random number generator callback
+ *
+ * \param ssl      SSL context
+ * \param f_rng    RNG function
+ * \param p_rng    RNG parameter
+ */
+void ssl_set_rng( ssl_context *ssl,
+                  int (*f_rng)(void *, unsigned char *, size_t),
+                  void *p_rng );
+
+/**
+ * \brief          Set the debug callback
+ *
+ * \param ssl      SSL context
+ * \param f_dbg    debug function
+ * \param p_dbg    debug parameter
+ */
+void ssl_set_dbg( ssl_context *ssl,
+                  void (*f_dbg)(void *, int, const char *),
+                  void  *p_dbg );
+
+/**
+ * \brief          Set the underlying BIO read and write callbacks
+ *
+ * \param ssl      SSL context
+ * \param f_recv   read callback
+ * \param p_recv   read parameter
+ * \param f_send   write callback
+ * \param p_send   write parameter
+ */
+void ssl_set_bio( ssl_context *ssl,
+        int (*f_recv)(void *, unsigned char *, size_t), void *p_recv,
+        int (*f_send)(void *, const unsigned char *, size_t), void *p_send );
+
+/**
+ * \brief          Set the session cache callbacks (server-side only)
+ *                 If not set, no session resuming is done.
+ *
+ *                 The session cache has the responsibility to check for stale
+ *                 entries based on timeout. See RFC 5246 for recommendations.
+ *
+ *                 Warning: session.peer_cert is cleared by the SSL/TLS layer on
+ *                 connection shutdown, so do not cache the pointer! Either set
+ *                 it to NULL or make a full copy of the certificate.
+ *
+ *                 The get callback is called once during the initial handshake
+ *                 to enable session resuming. The get function has the
+ *                 following parameters: (void *parameter, ssl_session *session)
+ *                 If a valid entry is found, it should fill the master of
+ *                 the session object with the cached values and return 0,
+ *                 return 1 otherwise. Optionally peer_cert can be set as well
+ *                 if it is properly present in cache entry.
+ *
+ *                 The set callback is called once during the initial handshake
+ *                 to enable session resuming after the entire handshake has
+ *                 been finished. The set function has the following parameters:
+ *                 (void *parameter, const ssl_session *session). The function
+ *                 should create a cache entry for future retrieval based on
+ *                 the data in the session structure and should keep in mind
+ *                 that the ssl_session object presented (and all its referenced
+ *                 data) is cleared by the SSL/TLS layer when the connection is
+ *                 terminated. It is recommended to add metadata to determine if
+ *                 an entry is still valid in the future. Return 0 if
+ *                 successfully cached, return 1 otherwise.
+ *
+ * \param ssl            SSL context
+ * \param f_get_cache    session get callback
+ * \param p_get_cache    session get parameter
+ * \param f_set_cache    session set callback
+ * \param p_set_cache    session set parameter
+ */
+void ssl_set_session_cache( ssl_context *ssl,
+        int (*f_get_cache)(void *, ssl_session *), void *p_get_cache,
+        int (*f_set_cache)(void *, const ssl_session *), void *p_set_cache );
+
+/**
+ * \brief          Request resumption of session (client-side only)
+ *                 Session data is copied from presented session structure.
+ *
+ * \param ssl      SSL context
+ * \param session  session context
+ *
+ * \return         0 if successful,
+ *                 POLARSSL_ERR_SSL_MALLOC_FAILED if memory allocation failed,
+ *                 POLARSSL_ERR_SSL_BAD_INPUT_DATA if used server-side or
+ *                 arguments are otherwise invalid
+ *
+ * \sa             ssl_get_session()
+ */
+int ssl_set_session( ssl_context *ssl, const ssl_session *session );
+
+/**
+ * \brief               Set the list of allowed ciphersuites and the preference
+ *                      order. First in the list has the highest preference.
+ *                      (Overrides all version specific lists)
+ *
+ *                      Note: The PolarSSL SSL server uses its own preferences
+ *                      over the preference of the connection SSL client unless
+ *                      POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE is defined!
+ *
+ * \param ssl           SSL context
+ * \param ciphersuites  0-terminated list of allowed ciphersuites
+ */
+void ssl_set_ciphersuites( ssl_context *ssl, const int *ciphersuites );
+
+/**
+ * \brief               Set the list of allowed ciphersuites and the
+ *                      preference order for a specific version of the protocol.
+ *                      (Only useful on the server side)
+ *
+ * \param ssl           SSL context
+ * \param ciphersuites  0-terminated list of allowed ciphersuites
+ * \param major         Major version number (only SSL_MAJOR_VERSION_3
+ *                      supported)
+ * \param minor         Minor version number (SSL_MINOR_VERSION_0,
+ *                      SSL_MINOR_VERSION_1 and SSL_MINOR_VERSION_2,
+ *                      SSL_MINOR_VERSION_3 supported)
+ */
+void ssl_set_ciphersuites_for_version( ssl_context *ssl,
+                                       const int *ciphersuites,
+                                       int major, int minor );
+
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+/**
+ * \brief          Set the data required to verify peer certificate
+ *
+ * \param ssl      SSL context
+ * \param ca_chain trusted CA chain (meaning all fully trusted top-level CAs)
+ * \param ca_crl   trusted CA CRLs
+ * \param peer_cn  expected peer CommonName (or NULL)
+ */
+void ssl_set_ca_chain( ssl_context *ssl, x509_crt *ca_chain,
+                       x509_crl *ca_crl, const char *peer_cn );
+
+/**
+ * \brief          Set own certificate chain and private key
+ *
+ * \note           own_cert should contain in order from the bottom up your
+ *                 certificate chain. The top certificate (self-signed)
+ *                 can be omitted.
+ *
+ * \note           This function may be called more than once if you want to
+ *                 support multiple certificates (eg, one using RSA and one
+ *                 using ECDSA). However, on client, currently only the first
+ *                 certificate is used (subsequent calls have no effect).
+ *
+ * \param ssl      SSL context
+ * \param own_cert own public certificate chain
+ * \param pk_key   own private key
+ *
+ * \return         0 on success or POLARSSL_ERR_SSL_MALLOC_FAILED
+ */
+int ssl_set_own_cert( ssl_context *ssl, x509_crt *own_cert,
+                       pk_context *pk_key );
+
+#if defined(POLARSSL_RSA_C)
+/**
+ * \brief          Set own certificate chain and private RSA key
+ *
+ *                 Note: own_cert should contain IN order from the bottom
+ *                 up your certificate chain. The top certificate (self-signed)
+ *                 can be omitted.
+ *
+ * \warning        This backwards-compatibility function is deprecated!
+ *                 Please use \c ssl_set_own_cert() instead.
+ *
+ * \param ssl      SSL context
+ * \param own_cert own public certificate chain
+ * \param rsa_key  own private RSA key
+ *
+ * \return          0 on success, or a specific error code.
+ */
+int ssl_set_own_cert_rsa( ssl_context *ssl, x509_crt *own_cert,
+                          rsa_context *rsa_key );
+#endif /* POLARSSL_RSA_C */
+
+/**
+ * \brief          Set own certificate and alternate non-PolarSSL RSA private
+ *                 key and handling callbacks, such as the PKCS#11 wrappers
+ *                 or any other external private key handler.
+ *                 (see the respective RSA functions in rsa.h for documentation
+ *                 of the callback parameters, with the only change being
+ *                 that the rsa_context * is a void * in the callbacks)
+ *
+ *                 Note: own_cert should contain IN order from the bottom
+ *                 up your certificate chain. The top certificate (self-signed)
+ *                 can be omitted.
+ *
+ * \warning        This backwards-compatibility function is deprecated!
+ *                 Please use \c pk_init_ctx_rsa_alt()
+ *                 and \c ssl_set_own_cert() instead.
+ *
+ * \param ssl      SSL context
+ * \param own_cert own public certificate chain
+ * \param rsa_key  alternate implementation private RSA key
+ * \param rsa_decrypt  alternate implementation of \c rsa_pkcs1_decrypt()
+ * \param rsa_sign     alternate implementation of \c rsa_pkcs1_sign()
+ * \param rsa_key_len  function returning length of RSA key in bytes
+ *
+ * \return          0 on success, or a specific error code.
+ */
+int ssl_set_own_cert_alt( ssl_context *ssl, x509_crt *own_cert,
+                          void *rsa_key,
+                          rsa_decrypt_func rsa_decrypt,
+                          rsa_sign_func rsa_sign,
+                          rsa_key_len_func rsa_key_len );
+#endif /* POLARSSL_X509_CRT_PARSE_C */
+
+#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
+/**
+ * \brief          Set the Pre Shared Key (PSK) and the identity name connected
+ *                 to it.
+ *
+ * \param ssl      SSL context
+ * \param psk      pointer to the pre-shared key
+ * \param psk_len  pre-shared key length
+ * \param psk_identity      pointer to the pre-shared key identity
+ * \param psk_identity_len  identity key length
+ *
+ * \return         0 if successful or POLARSSL_ERR_SSL_MALLOC_FAILED
+ */
+int ssl_set_psk( ssl_context *ssl, const unsigned char *psk, size_t psk_len,
+                 const unsigned char *psk_identity, size_t psk_identity_len );
+
+/**
+ * \brief          Set the PSK callback (server-side only) (Optional).
+ *
+ *                 If set, the PSK callback is called for each
+ *                 handshake where a PSK ciphersuite was negotiated.
+ *                 The caller provides the identity received and wants to
+ *                 receive the actual PSK data and length.
+ *
+ *                 The callback has the following parameters: (void *parameter,
+ *                 ssl_context *ssl, const unsigned char *psk_identity,
+ *                 size_t identity_len)
+ *                 If a valid PSK identity is found, the callback should use
+ *                 ssl_set_psk() on the ssl context to set the correct PSK and
+ *                 identity and return 0.
+ *                 Any other return value will result in a denied PSK identity.
+ *
+ * \param ssl      SSL context
+ * \param f_psk    PSK identity function
+ * \param p_psk    PSK identity parameter
+ */
+void ssl_set_psk_cb( ssl_context *ssl,
+                     int (*f_psk)(void *, ssl_context *, const unsigned char *,
+                                  size_t),
+                     void *p_psk );
+#endif /* POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED */
+
+#if defined(POLARSSL_DHM_C)
+/**
+ * \brief          Set the Diffie-Hellman public P and G values,
+ *                 read as hexadecimal strings (server-side only)
+ *                 (Default: POLARSSL_DHM_RFC5114_MODP_1024_[PG])
+ *
+ * \param ssl      SSL context
+ * \param dhm_P    Diffie-Hellman-Merkle modulus
+ * \param dhm_G    Diffie-Hellman-Merkle generator
+ *
+ * \return         0 if successful
+ */
+int ssl_set_dh_param( ssl_context *ssl, const char *dhm_P, const char *dhm_G );
+
+/**
+ * \brief          Set the Diffie-Hellman public P and G values,
+ *                 read from existing context (server-side only)
+ *
+ * \param ssl      SSL context
+ * \param dhm_ctx  Diffie-Hellman-Merkle context
+ *
+ * \return         0 if successful
+ */
+int ssl_set_dh_param_ctx( ssl_context *ssl, dhm_context *dhm_ctx );
+#endif /* POLARSSL_DHM_C */
+
+#if defined(POLARSSL_SSL_SET_CURVES)
+/**
+ * \brief          Set the allowed curves in order of preference.
+ *                 (Default: all defined curves.)
+ *
+ *                 On server: this only affects selection of the ECDHE curve;
+ *                 the curves used for ECDH and ECDSA are determined by the
+ *                 list of available certificates instead.
+ *
+ *                 On client: this affects the list of curves offered for any
+ *                 use. The server can override our preference order.
+ *
+ *                 Both sides: limits the set of curves used by peer to the
+ *                 listed curves for any use (ECDH(E), certificates).
+ *
+ * \param ssl      SSL context
+ * \param curves   Ordered list of allowed curves,
+ *                 terminated by POLARSSL_ECP_DP_NONE.
+ */
+void ssl_set_curves( ssl_context *ssl, const ecp_group_id *curves );
+#endif /* POLARSSL_SSL_SET_CURVES */
+
+#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
+/**
+ * \brief          Set hostname for ServerName TLS extension
+ *                 (client-side only)
+ *
+ *
+ * \param ssl      SSL context
+ * \param hostname the server hostname
+ *
+ * \return         0 if successful or POLARSSL_ERR_SSL_MALLOC_FAILED
+ */
+int ssl_set_hostname( ssl_context *ssl, const char *hostname );
+
+/**
+ * \brief          Set server side ServerName TLS extension callback
+ *                 (optional, server-side only).
+ *
+ *                 If set, the ServerName callback is called whenever the
+ *                 server receives a ServerName TLS extension from the client
+ *                 during a handshake. The ServerName callback has the
+ *                 following parameters: (void *parameter, ssl_context *ssl,
+ *                 const unsigned char *hostname, size_t len). If a suitable
+ *                 certificate is found, the callback should set the
+ *                 certificate and key to use with ssl_set_own_cert() (and
+ *                 possibly adjust the CA chain as well) and return 0. The
+ *                 callback should return -1 to abort the handshake at this
+ *                 point.
+ *
+ * \param ssl      SSL context
+ * \param f_sni    verification function
+ * \param p_sni    verification parameter
+ */
+void ssl_set_sni( ssl_context *ssl,
+                  int (*f_sni)(void *, ssl_context *, const unsigned char *,
+                               size_t),
+                  void *p_sni );
+#endif /* POLARSSL_SSL_SERVER_NAME_INDICATION */
+
+#if defined(POLARSSL_SSL_ALPN)
+/**
+ * \brief          Set the supported Application Layer Protocols.
+ *
+ * \param ssl      SSL context
+ * \param protos   NULL-terminated list of supported protocols,
+ *                 in decreasing preference order.
+ *
+ * \return         0 on success, or POLARSSL_ERR_SSL_BAD_INPUT_DATA.
+ */
+int ssl_set_alpn_protocols( ssl_context *ssl, const char **protos );
+
+/**
+ * \brief          Get the name of the negotiated Application Layer Protocol.
+ *                 This function should be called after the handshake is
+ *                 completed.
+ *
+ * \param ssl      SSL context
+ *
+ * \return         Protcol name, or NULL if no protocol was negotiated.
+ */
+const char *ssl_get_alpn_protocol( const ssl_context *ssl );
+#endif /* POLARSSL_SSL_ALPN */
+
+/**
+ * \brief          Set the maximum supported version sent from the client side
+ *                 and/or accepted at the server side
+ *                 (Default: SSL_MAX_MAJOR_VERSION, SSL_MAX_MINOR_VERSION)
+ *
+ *                 Note: This ignores ciphersuites from 'higher' versions.
+ *                 Note: Input outside of the SSL_MAX_XXXXX_VERSION and
+ *                       SSL_MIN_XXXXX_VERSION range is ignored.
+ *
+ * \param ssl      SSL context
+ * \param major    Major version number (only SSL_MAJOR_VERSION_3 supported)
+ * \param minor    Minor version number (SSL_MINOR_VERSION_0,
+ *                 SSL_MINOR_VERSION_1 and SSL_MINOR_VERSION_2,
+ *                 SSL_MINOR_VERSION_3 supported)
+ */
+void ssl_set_max_version( ssl_context *ssl, int major, int minor );
+
+
+/**
+ * \brief          Set the minimum accepted SSL/TLS protocol version
+ *                 (Default: SSL_MIN_MAJOR_VERSION, SSL_MIN_MINOR_VERSION)
+ *
+ *                 Note: Input outside of the SSL_MAX_XXXXX_VERSION and
+ *                       SSL_MIN_XXXXX_VERSION range is ignored.
+ *
+ * \param ssl      SSL context
+ * \param major    Major version number (only SSL_MAJOR_VERSION_3 supported)
+ * \param minor    Minor version number (SSL_MINOR_VERSION_0,
+ *                 SSL_MINOR_VERSION_1 and SSL_MINOR_VERSION_2,
+ *                 SSL_MINOR_VERSION_3 supported)
+ */
+void ssl_set_min_version( ssl_context *ssl, int major, int minor );
+
+#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH)
+/**
+ * \brief          Set the maximum fragment length to emit and/or negotiate
+ *                 (Default: SSL_MAX_CONTENT_LEN, usually 2^14 bytes)
+ *                 (Server: set maximum fragment length to emit,
+ *                 usually negotiated by the client during handshake
+ *                 (Client: set maximum fragment length to emit *and*
+ *                 negotiate with the server during handshake)
+ *
+ * \param ssl      SSL context
+ * \param mfl_code Code for maximum fragment length (allowed values:
+ *                 SSL_MAX_FRAG_LEN_512,  SSL_MAX_FRAG_LEN_1024,
+ *                 SSL_MAX_FRAG_LEN_2048, SSL_MAX_FRAG_LEN_4096)
+ *
+ * \return         O if successful or POLARSSL_ERR_SSL_BAD_INPUT_DATA
+ */
+int ssl_set_max_frag_len( ssl_context *ssl, unsigned char mfl_code );
+#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */
+
+#if defined(POLARSSL_SSL_TRUNCATED_HMAC)
+/**
+ * \brief          Activate negotiation of truncated HMAC (Client only)
+ *                 (Default: SSL_TRUNC_HMAC_ENABLED)
+ *
+ * \param ssl      SSL context
+ * \param truncate Enable or disable (SSL_TRUNC_HMAC_ENABLED or
+ *                                    SSL_TRUNC_HMAC_DISABLED)
+ *
+ * \return         O if successful,
+ *                 POLARSSL_ERR_SSL_BAD_INPUT_DATA if used server-side
+ */
+int ssl_set_truncated_hmac( ssl_context *ssl, int truncate );
+#endif /* POLARSSL_SSL_TRUNCATED_HMAC */
+
+#if defined(POLARSSL_SSL_SESSION_TICKETS)
+/**
+ * \brief          Enable / Disable session tickets
+ *                 (Default: SSL_SESSION_TICKETS_ENABLED on client,
+ *                           SSL_SESSION_TICKETS_DISABLED on server)
+ *
+ * \note           On server, ssl_set_rng() must be called before this function
+ *                 to allow generating the ticket encryption and
+ *                 authentication keys.
+ *
+ * \param ssl      SSL context
+ * \param use_tickets   Enable or disable (SSL_SESSION_TICKETS_ENABLED or
+ *                                         SSL_SESSION_TICKETS_DISABLED)
+ *
+ * \return         O if successful,
+ *                 or a specific error code (server only).
+ */
+int ssl_set_session_tickets( ssl_context *ssl, int use_tickets );
+
+/**
+ * \brief          Set session ticket lifetime (server only)
+ *                 (Default: SSL_DEFAULT_TICKET_LIFETIME (86400 secs / 1 day))
+ *
+ * \param ssl      SSL context
+ * \param lifetime session ticket lifetime
+ */
+void ssl_set_session_ticket_lifetime( ssl_context *ssl, int lifetime );
+#endif /* POLARSSL_SSL_SESSION_TICKETS */
+
+/**
+ * \brief          Enable / Disable renegotiation support for connection when
+ *                 initiated by peer
+ *                 (Default: SSL_RENEGOTIATION_DISABLED)
+ *
+ *                 Note: A server with support enabled is more vulnerable for a
+ *                 resource DoS by a malicious client. You should enable this on
+ *                 a client to enable server-initiated renegotiation.
+ *
+ * \param ssl      SSL context
+ * \param renegotiation     Enable or disable (SSL_RENEGOTIATION_ENABLED or
+ *                                             SSL_RENEGOTIATION_DISABLED)
+ */
+void ssl_set_renegotiation( ssl_context *ssl, int renegotiation );
+
+/**
+ * \brief          Prevent or allow legacy renegotiation.
+ *                 (Default: SSL_LEGACY_NO_RENEGOTIATION)
+ *
+ *                 SSL_LEGACY_NO_RENEGOTIATION allows connections to
+ *                 be established even if the peer does not support
+ *                 secure renegotiation, but does not allow renegotiation
+ *                 to take place if not secure.
+ *                 (Interoperable and secure option)
+ *
+ *                 SSL_LEGACY_ALLOW_RENEGOTIATION allows renegotiations
+ *                 with non-upgraded peers. Allowing legacy renegotiation
+ *                 makes the connection vulnerable to specific man in the
+ *                 middle attacks. (See RFC 5746)
+ *                 (Most interoperable and least secure option)
+ *
+ *                 SSL_LEGACY_BREAK_HANDSHAKE breaks off connections
+ *                 if peer does not support secure renegotiation. Results
+ *                 in interoperability issues with non-upgraded peers
+ *                 that do not support renegotiation altogether.
+ *                 (Most secure option, interoperability issues)
+ *
+ * \param ssl      SSL context
+ * \param allow_legacy  Prevent or allow (SSL_NO_LEGACY_RENEGOTIATION,
+ *                                        SSL_ALLOW_LEGACY_RENEGOTIATION or
+ *                                        SSL_LEGACY_BREAK_HANDSHAKE)
+ */
+void ssl_legacy_renegotiation( ssl_context *ssl, int allow_legacy );
+
+/**
+ * \brief          Return the number of data bytes available to read
+ *
+ * \param ssl      SSL context
+ *
+ * \return         how many bytes are available in the read buffer
+ */
+size_t ssl_get_bytes_avail( const ssl_context *ssl );
+
+/**
+ * \brief          Return the result of the certificate verification
+ *
+ * \param ssl      SSL context
+ *
+ * \return         0 if successful, or a combination of:
+ *                      BADCERT_EXPIRED
+ *                      BADCERT_REVOKED
+ *                      BADCERT_CN_MISMATCH
+ *                      BADCERT_NOT_TRUSTED
+ */
+int ssl_get_verify_result( const ssl_context *ssl );
+
+/**
+ * \brief          Return the name of the current ciphersuite
+ *
+ * \param ssl      SSL context
+ *
+ * \return         a string containing the ciphersuite name
+ */
+const char *ssl_get_ciphersuite( const ssl_context *ssl );
+
+/**
+ * \brief          Return the current SSL version (SSLv3/TLSv1/etc)
+ *
+ * \param ssl      SSL context
+ *
+ * \return         a string containing the SSL version
+ */
+const char *ssl_get_version( const ssl_context *ssl );
+
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+/**
+ * \brief          Return the peer certificate from the current connection
+ *
+ *                 Note: Can be NULL in case no certificate was sent during
+ *                 the handshake. Different calls for the same connection can
+ *                 return the same or different pointers for the same
+ *                 certificate and even a different certificate altogether.
+ *                 The peer cert CAN change in a single connection if
+ *                 renegotiation is performed.
+ *
+ * \param ssl      SSL context
+ *
+ * \return         the current peer certificate
+ */
+const x509_crt *ssl_get_peer_cert( const ssl_context *ssl );
+#endif /* POLARSSL_X509_CRT_PARSE_C */
+
+/**
+ * \brief          Save session in order to resume it later (client-side only)
+ *                 Session data is copied to presented session structure.
+ *
+ * \warning        Currently, peer certificate is lost in the operation.
+ *
+ * \param ssl      SSL context
+ * \param session  session context
+ *
+ * \return         0 if successful,
+ *                 POLARSSL_ERR_SSL_MALLOC_FAILED if memory allocation failed,
+ *                 POLARSSL_ERR_SSL_BAD_INPUT_DATA if used server-side or
+ *                 arguments are otherwise invalid
+ *
+ * \sa             ssl_set_session()
+ */
+int ssl_get_session( const ssl_context *ssl, ssl_session *session );
+
+/**
+ * \brief          Perform the SSL handshake
+ *
+ * \param ssl      SSL context
+ *
+ * \return         0 if successful, POLARSSL_ERR_NET_WANT_READ,
+ *                 POLARSSL_ERR_NET_WANT_WRITE, or a specific SSL error code.
+ */
+int ssl_handshake( ssl_context *ssl );
+
+/**
+ * \brief          Perform a single step of the SSL handshake
+ *
+ *                 Note: the state of the context (ssl->state) will be at
+ *                 the following state after execution of this function.
+ *                 Do not call this function if state is SSL_HANDSHAKE_OVER.
+ *
+ * \param ssl      SSL context
+ *
+ * \return         0 if successful, POLARSSL_ERR_NET_WANT_READ,
+ *                 POLARSSL_ERR_NET_WANT_WRITE, or a specific SSL error code.
+ */
+int ssl_handshake_step( ssl_context *ssl );
+
+/**
+ * \brief          Initiate an SSL renegotiation on the running connection.
+ *                 Client: perform the renegotiation right now.
+ *                 Server: request renegotiation, which will be performed
+ *                 during the next call to ssl_read() if honored by client.
+ *
+ * \param ssl      SSL context
+ *
+ * \return         0 if successful, or any ssl_handshake() return value.
+ */
+int ssl_renegotiate( ssl_context *ssl );
+
+/**
+ * \brief          Read at most 'len' application data bytes
+ *
+ * \param ssl      SSL context
+ * \param buf      buffer that will hold the data
+ * \param len      how many bytes must be read
+ *
+ * \return         This function returns the number of bytes read, 0 for EOF,
+ *                 or a negative error code.
+ */
+int ssl_read( ssl_context *ssl, unsigned char *buf, size_t len );
+
+/**
+ * \brief          Write exactly 'len' application data bytes
+ *
+ * \param ssl      SSL context
+ * \param buf      buffer holding the data
+ * \param len      how many bytes must be written
+ *
+ * \return         This function returns the number of bytes written,
+ *                 or a negative error code.
+ *
+ * \note           When this function returns POLARSSL_ERR_NET_WANT_WRITE,
+ *                 it must be called later with the *same* arguments,
+ *                 until it returns a positive value.
+ */
+int ssl_write( ssl_context *ssl, const unsigned char *buf, size_t len );
+
+/**
+ * \brief           Send an alert message
+ *
+ * \param ssl       SSL context
+ * \param level     The alert level of the message
+ *                  (SSL_ALERT_LEVEL_WARNING or SSL_ALERT_LEVEL_FATAL)
+ * \param message   The alert message (SSL_ALERT_MSG_*)
+ *
+ * \return          0 if successful, or a specific SSL error code.
+ */
+int ssl_send_alert_message( ssl_context *ssl,
+                            unsigned char level,
+                            unsigned char message );
+/**
+ * \brief          Notify the peer that the connection is being closed
+ *
+ * \param ssl      SSL context
+ */
+int ssl_close_notify( ssl_context *ssl );
+
+/**
+ * \brief          Free referenced items in an SSL context and clear memory
+ *
+ * \param ssl      SSL context
+ */
+void ssl_free( ssl_context *ssl );
+
+/**
+ * \brief          Free referenced items in an SSL session including the
+ *                 peer certificate and clear memory
+ *
+ * \param session  SSL session
+ */
+void ssl_session_free( ssl_session *session );
+
+/**
+ * \brief           Free referenced items in an SSL transform context and clear
+ *                  memory
+ *
+ * \param transform SSL transform context
+ */
+void ssl_transform_free( ssl_transform *transform );
+
+/**
+ * \brief           Free referenced items in an SSL handshake context and clear
+ *                  memory
+ *
+ * \param handshake SSL handshake context
+ */
+void ssl_handshake_free( ssl_handshake_params *handshake );
+
+/*
+ * Internal functions (do not call directly)
+ */
+int ssl_handshake_client_step( ssl_context *ssl );
+int ssl_handshake_server_step( ssl_context *ssl );
+void ssl_handshake_wrapup( ssl_context *ssl );
+
+int ssl_send_fatal_handshake_failure( ssl_context *ssl );
+
+int ssl_derive_keys( ssl_context *ssl );
+
+int ssl_read_record( ssl_context *ssl );
+/**
+ * \return         0 if successful, POLARSSL_ERR_SSL_CONN_EOF on EOF or
+ *                 another negative error code.
+ */
+int ssl_fetch_input( ssl_context *ssl, size_t nb_want );
+
+int ssl_write_record( ssl_context *ssl );
+int ssl_flush_output( ssl_context *ssl );
+
+int ssl_parse_certificate( ssl_context *ssl );
+int ssl_write_certificate( ssl_context *ssl );
+
+int ssl_parse_change_cipher_spec( ssl_context *ssl );
+int ssl_write_change_cipher_spec( ssl_context *ssl );
+
+int ssl_parse_finished( ssl_context *ssl );
+int ssl_write_finished( ssl_context *ssl );
+
+void ssl_optimize_checksum( ssl_context *ssl,
+                            const ssl_ciphersuite_t *ciphersuite_info );
+
+#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
+int ssl_psk_derive_premaster( ssl_context *ssl, key_exchange_type_t key_ex );
+#endif
+
+#if defined(POLARSSL_PK_C)
+unsigned char ssl_sig_from_pk( pk_context *pk );
+pk_type_t ssl_pk_alg_from_sig( unsigned char sig );
+#endif
+
+md_type_t ssl_md_alg_from_hash( unsigned char hash );
+
+#if defined(POLARSSL_SSL_SET_CURVES)
+int ssl_curve_is_acceptable( const ssl_context *ssl, ecp_group_id grp_id );
+#endif
+
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+static inline pk_context *ssl_own_key( ssl_context *ssl )
+{
+    return( ssl->handshake->key_cert == NULL ? NULL
+            : ssl->handshake->key_cert->key );
+}
+
+static inline x509_crt *ssl_own_cert( ssl_context *ssl )
+{
+    return( ssl->handshake->key_cert == NULL ? NULL
+            : ssl->handshake->key_cert->cert );
+}
+
+/*
+ * Check usage of a certificate wrt extensions:
+ * keyUsage, extendedKeyUsage (later), and nSCertType (later).
+ *
+ * Warning: cert_endpoint is the endpoint of the cert (ie, of our peer when we
+ * check a cert we received from them)!
+ *
+ * Return 0 if everything is OK, -1 if not.
+ */
+int ssl_check_cert_usage( const x509_crt *cert,
+                          const ssl_ciphersuite_t *ciphersuite,
+                          int cert_endpoint );
+#endif /* POLARSSL_X509_CRT_PARSE_C */
+
+/* constant-time buffer comparison */
+static inline int safer_memcmp( const void *a, const void *b, size_t n )
+{
+    size_t i;
+    const unsigned char *A = (const unsigned char *) a;
+    const unsigned char *B = (const unsigned char *) b;
+    unsigned char diff = 0;
+
+    for( i = 0; i < n; i++ )
+        diff |= A[i] ^ B[i];
+
+    return( diff );
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ssl.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/ssl_cache.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,149 @@
+/**
+ * \file ssl_cache.h
+ *
+ * \brief SSL session cache implementation
+ *
+ *  Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_SSL_CACHE_H
+#define POLARSSL_SSL_CACHE_H
+
+#include "ssl.h"
+
+#if defined(POLARSSL_THREADING_C)
+#include "threading.h"
+#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(SSL_CACHE_DEFAULT_TIMEOUT)
+#define SSL_CACHE_DEFAULT_TIMEOUT       86400   /*!< 1 day  */
+#endif
+
+#if !defined(SSL_CACHE_DEFAULT_MAX_ENTRIES)
+#define SSL_CACHE_DEFAULT_MAX_ENTRIES      50   /*!< Maximum entries in cache */
+#endif
+
+/* \} name SECTION: Module settings */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct _ssl_cache_context ssl_cache_context;
+typedef struct _ssl_cache_entry ssl_cache_entry;
+
+/**
+ * \brief   This structure is used for storing cache entries
+ */
+struct _ssl_cache_entry
+{
+#if defined(POLARSSL_HAVE_TIME)
+    time_t timestamp;           /*!< entry timestamp    */
+#endif
+    ssl_session session;        /*!< entry session      */
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+    x509_buf peer_cert;         /*!< entry peer_cert    */
+#endif
+    ssl_cache_entry *next;      /*!< chain pointer      */
+};
+
+/**
+ * \brief Cache context
+ */
+struct _ssl_cache_context
+{
+    ssl_cache_entry *chain;     /*!< start of the chain     */
+    int timeout;                /*!< cache entry timeout    */
+    int max_entries;            /*!< maximum entries        */
+#if defined(POLARSSL_THREADING_C)
+    threading_mutex_t mutex;    /*!< mutex                  */
+#endif
+};
+
+/**
+ * \brief          Initialize an SSL cache context
+ *
+ * \param cache    SSL cache context
+ */
+void ssl_cache_init( ssl_cache_context *cache );
+
+/**
+ * \brief          Cache get callback implementation
+ *                 (Thread-safe if POLARSSL_THREADING_C is enabled)
+ *
+ * \param data     SSL cache context
+ * \param session  session to retrieve entry for
+ */
+int ssl_cache_get( void *data, ssl_session *session );
+
+/**
+ * \brief          Cache set callback implementation
+ *                 (Thread-safe if POLARSSL_THREADING_C is enabled)
+ *
+ * \param data     SSL cache context
+ * \param session  session to store entry for
+ */
+int ssl_cache_set( void *data, const ssl_session *session );
+
+#if defined(POLARSSL_HAVE_TIME)
+/**
+ * \brief          Set the cache timeout
+ *                 (Default: SSL_CACHE_DEFAULT_TIMEOUT (1 day))
+ *
+ *                 A timeout of 0 indicates no timeout.
+ *
+ * \param cache    SSL cache context
+ * \param timeout  cache entry timeout in seconds
+ */
+void ssl_cache_set_timeout( ssl_cache_context *cache, int timeout );
+#endif /* POLARSSL_HAVE_TIME */
+
+/**
+ * \brief          Set the cache timeout
+ *                 (Default: SSL_CACHE_DEFAULT_MAX_ENTRIES (50))
+ *
+ * \param cache    SSL cache context
+ * \param max      cache entry maximum
+ */
+void ssl_cache_set_max_entries( ssl_cache_context *cache, int max );
+
+/**
+ * \brief          Free referenced items in a cache context and clear memory
+ *
+ * \param cache    SSL cache context
+ */
+void ssl_cache_free( ssl_cache_context *cache );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ssl_cache.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/ssl_ciphersuites.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,269 @@
+/**
+ * \file ssl_ciphersuites.h
+ *
+ * \brief SSL Ciphersuites for PolarSSL
+ *
+ *  Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_SSL_CIPHERSUITES_H
+#define POLARSSL_SSL_CIPHERSUITES_H
+
+#include "pk.h"
+#include "cipher.h"
+#include "md.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Supported ciphersuites (Official IANA names)
+ */
+#define TLS_RSA_WITH_NULL_MD5                    0x01   /**< Weak! */
+#define TLS_RSA_WITH_NULL_SHA                    0x02   /**< Weak! */
+
+#define TLS_RSA_WITH_RC4_128_MD5                 0x04
+#define TLS_RSA_WITH_RC4_128_SHA                 0x05
+#define TLS_RSA_WITH_DES_CBC_SHA                 0x09   /**< Weak! Not in TLS 1.2 */
+
+#define TLS_RSA_WITH_3DES_EDE_CBC_SHA            0x0A
+
+#define TLS_DHE_RSA_WITH_DES_CBC_SHA             0x15   /**< Weak! Not in TLS 1.2 */
+#define TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA        0x16
+
+#define TLS_PSK_WITH_NULL_SHA                    0x2C   /**< Weak! */
+#define TLS_DHE_PSK_WITH_NULL_SHA                0x2D   /**< Weak! */
+#define TLS_RSA_PSK_WITH_NULL_SHA                0x2E   /**< Weak! */
+#define TLS_RSA_WITH_AES_128_CBC_SHA             0x2F
+
+#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA         0x33
+#define TLS_RSA_WITH_AES_256_CBC_SHA             0x35
+#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA         0x39
+
+#define TLS_RSA_WITH_NULL_SHA256                 0x3B   /**< Weak! */
+#define TLS_RSA_WITH_AES_128_CBC_SHA256          0x3C   /**< TLS 1.2 */
+#define TLS_RSA_WITH_AES_256_CBC_SHA256          0x3D   /**< TLS 1.2 */
+
+#define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA        0x41
+#define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA    0x45
+
+#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256      0x67   /**< TLS 1.2 */
+#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256      0x6B   /**< TLS 1.2 */
+
+#define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA        0x84
+#define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA    0x88
+
+#define TLS_PSK_WITH_RC4_128_SHA                 0x8A
+#define TLS_PSK_WITH_3DES_EDE_CBC_SHA            0x8B
+#define TLS_PSK_WITH_AES_128_CBC_SHA             0x8C
+#define TLS_PSK_WITH_AES_256_CBC_SHA             0x8D
+
+#define TLS_DHE_PSK_WITH_RC4_128_SHA             0x8E
+#define TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA        0x8F
+#define TLS_DHE_PSK_WITH_AES_128_CBC_SHA         0x90
+#define TLS_DHE_PSK_WITH_AES_256_CBC_SHA         0x91
+
+#define TLS_RSA_PSK_WITH_RC4_128_SHA             0x92
+#define TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA        0x93
+#define TLS_RSA_PSK_WITH_AES_128_CBC_SHA         0x94
+#define TLS_RSA_PSK_WITH_AES_256_CBC_SHA         0x95
+
+#define TLS_RSA_WITH_AES_128_GCM_SHA256          0x9C   /**< TLS 1.2 */
+#define TLS_RSA_WITH_AES_256_GCM_SHA384          0x9D   /**< TLS 1.2 */
+#define TLS_DHE_RSA_WITH_AES_128_GCM_SHA256      0x9E   /**< TLS 1.2 */
+#define TLS_DHE_RSA_WITH_AES_256_GCM_SHA384      0x9F   /**< TLS 1.2 */
+
+#define TLS_PSK_WITH_AES_128_GCM_SHA256          0xA8   /**< TLS 1.2 */
+#define TLS_PSK_WITH_AES_256_GCM_SHA384          0xA9   /**< TLS 1.2 */
+#define TLS_DHE_PSK_WITH_AES_128_GCM_SHA256      0xAA   /**< TLS 1.2 */
+#define TLS_DHE_PSK_WITH_AES_256_GCM_SHA384      0xAB   /**< TLS 1.2 */
+#define TLS_RSA_PSK_WITH_AES_128_GCM_SHA256      0xAC   /**< TLS 1.2 */
+#define TLS_RSA_PSK_WITH_AES_256_GCM_SHA384      0xAD   /**< TLS 1.2 */
+
+#define TLS_PSK_WITH_AES_128_CBC_SHA256          0xAE
+#define TLS_PSK_WITH_AES_256_CBC_SHA384          0xAF
+#define TLS_PSK_WITH_NULL_SHA256                 0xB0   /**< Weak! */
+#define TLS_PSK_WITH_NULL_SHA384                 0xB1   /**< Weak! */
+
+#define TLS_DHE_PSK_WITH_AES_128_CBC_SHA256      0xB2
+#define TLS_DHE_PSK_WITH_AES_256_CBC_SHA384      0xB3
+#define TLS_DHE_PSK_WITH_NULL_SHA256             0xB4   /**< Weak! */
+#define TLS_DHE_PSK_WITH_NULL_SHA384             0xB5   /**< Weak! */
+
+#define TLS_RSA_PSK_WITH_AES_128_CBC_SHA256      0xB6
+#define TLS_RSA_PSK_WITH_AES_256_CBC_SHA384      0xB7
+#define TLS_RSA_PSK_WITH_NULL_SHA256             0xB8   /**< Weak! */
+#define TLS_RSA_PSK_WITH_NULL_SHA384             0xB9   /**< Weak! */
+
+#define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256     0xBA   /**< TLS 1.2 */
+#define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBE   /**< TLS 1.2 */
+
+#define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256     0xC0   /**< TLS 1.2 */
+#define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC4   /**< TLS 1.2 */
+
+#define TLS_ECDH_ECDSA_WITH_NULL_SHA             0xC001 /**< Weak! */
+#define TLS_ECDH_ECDSA_WITH_RC4_128_SHA          0xC002 /**< Not in SSL3! */
+#define TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA     0xC003 /**< Not in SSL3! */
+#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA      0xC004 /**< Not in SSL3! */
+#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA      0xC005 /**< Not in SSL3! */
+
+#define TLS_ECDHE_ECDSA_WITH_NULL_SHA            0xC006 /**< Weak! */
+#define TLS_ECDHE_ECDSA_WITH_RC4_128_SHA         0xC007 /**< Not in SSL3! */
+#define TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA    0xC008 /**< Not in SSL3! */
+#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA     0xC009 /**< Not in SSL3! */
+#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA     0xC00A /**< Not in SSL3! */
+
+#define TLS_ECDH_RSA_WITH_NULL_SHA               0xC00B /**< Weak! */
+#define TLS_ECDH_RSA_WITH_RC4_128_SHA            0xC00C /**< Not in SSL3! */
+#define TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA       0xC00D /**< Not in SSL3! */
+#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA        0xC00E /**< Not in SSL3! */
+#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA        0xC00F /**< Not in SSL3! */
+
+#define TLS_ECDHE_RSA_WITH_NULL_SHA              0xC010 /**< Weak! */
+#define TLS_ECDHE_RSA_WITH_RC4_128_SHA           0xC011 /**< Not in SSL3! */
+#define TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA      0xC012 /**< Not in SSL3! */
+#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA       0xC013 /**< Not in SSL3! */
+#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA       0xC014 /**< Not in SSL3! */
+
+#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256  0xC023 /**< TLS 1.2 */
+#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384  0xC024 /**< TLS 1.2 */
+#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256   0xC025 /**< TLS 1.2 */
+#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384   0xC026 /**< TLS 1.2 */
+#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256    0xC027 /**< TLS 1.2 */
+#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384    0xC028 /**< TLS 1.2 */
+#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256     0xC029 /**< TLS 1.2 */
+#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384     0xC02A /**< TLS 1.2 */
+
+#define TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256  0xC02B /**< TLS 1.2 */
+#define TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384  0xC02C /**< TLS 1.2 */
+#define TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256   0xC02D /**< TLS 1.2 */
+#define TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384   0xC02E /**< TLS 1.2 */
+#define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256    0xC02F /**< TLS 1.2 */
+#define TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384    0xC030 /**< TLS 1.2 */
+#define TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256     0xC031 /**< TLS 1.2 */
+#define TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384     0xC032 /**< TLS 1.2 */
+
+#define TLS_ECDHE_PSK_WITH_RC4_128_SHA           0xC033 /**< Not in SSL3! */
+#define TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA      0xC034 /**< Not in SSL3! */
+#define TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA       0xC035 /**< Not in SSL3! */
+#define TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA       0xC036 /**< Not in SSL3! */
+#define TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256    0xC037 /**< Not in SSL3! */
+#define TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384    0xC038 /**< Not in SSL3! */
+#define TLS_ECDHE_PSK_WITH_NULL_SHA              0xC039 /**< Weak! No SSL3! */
+#define TLS_ECDHE_PSK_WITH_NULL_SHA256           0xC03A /**< Weak! No SSL3! */
+#define TLS_ECDHE_PSK_WITH_NULL_SHA384           0xC03B /**< Weak! No SSL3! */
+
+#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC072 /**< Not in SSL3! */
+#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC073 /**< Not in SSL3! */
+#define TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256  0xC074 /**< Not in SSL3! */
+#define TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384  0xC075 /**< Not in SSL3! */
+#define TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256   0xC076 /**< Not in SSL3! */
+#define TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384   0xC077 /**< Not in SSL3! */
+#define TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256    0xC078 /**< Not in SSL3! */
+#define TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384    0xC079 /**< Not in SSL3! */
+
+#define TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256         0xC07A /**< TLS 1.2 */
+#define TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384         0xC07B /**< TLS 1.2 */
+#define TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256     0xC07C /**< TLS 1.2 */
+#define TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384     0xC07D /**< TLS 1.2 */
+#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 0xC086 /**< TLS 1.2 */
+#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 0xC087 /**< TLS 1.2 */
+#define TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256  0xC088 /**< TLS 1.2 */
+#define TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384  0xC089 /**< TLS 1.2 */
+#define TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256   0xC08A /**< TLS 1.2 */
+#define TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384   0xC08B /**< TLS 1.2 */
+#define TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256    0xC08C /**< TLS 1.2 */
+#define TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384    0xC08D /**< TLS 1.2 */
+
+#define TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256       0xC08E /**< TLS 1.2 */
+#define TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384       0xC08F /**< TLS 1.2 */
+#define TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256   0xC090 /**< TLS 1.2 */
+#define TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384   0xC091 /**< TLS 1.2 */
+#define TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256   0xC092 /**< TLS 1.2 */
+#define TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384   0xC093 /**< TLS 1.2 */
+
+#define TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256       0xC094
+#define TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384       0xC095
+#define TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256   0xC096
+#define TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384   0xC097
+#define TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256   0xC098
+#define TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384   0xC099
+#define TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC09A /**< Not in SSL3! */
+#define TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC09B /**< Not in SSL3! */
+
+typedef enum {
+    POLARSSL_KEY_EXCHANGE_NONE = 0,
+    POLARSSL_KEY_EXCHANGE_RSA,
+    POLARSSL_KEY_EXCHANGE_DHE_RSA,
+    POLARSSL_KEY_EXCHANGE_ECDHE_RSA,
+    POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA,
+    POLARSSL_KEY_EXCHANGE_PSK,
+    POLARSSL_KEY_EXCHANGE_DHE_PSK,
+    POLARSSL_KEY_EXCHANGE_RSA_PSK,
+    POLARSSL_KEY_EXCHANGE_ECDHE_PSK,
+    POLARSSL_KEY_EXCHANGE_ECDH_RSA,
+    POLARSSL_KEY_EXCHANGE_ECDH_ECDSA,
+} key_exchange_type_t;
+
+typedef struct _ssl_ciphersuite_t ssl_ciphersuite_t;
+
+#define POLARSSL_CIPHERSUITE_WEAK   0x01    /**< Weak ciphersuite flag      */
+
+/**
+ * \brief   This structure is used for storing ciphersuite information
+ */
+struct _ssl_ciphersuite_t
+{
+    int id;
+    const char * name;
+
+    cipher_type_t cipher;
+    md_type_t mac;
+    key_exchange_type_t key_exchange;
+
+    int min_major_ver;
+    int min_minor_ver;
+    int max_major_ver;
+    int max_minor_ver;
+
+    unsigned char flags;
+};
+
+const int *ssl_list_ciphersuites( void );
+
+const ssl_ciphersuite_t *ssl_ciphersuite_from_string( const char *ciphersuite_name );
+const ssl_ciphersuite_t *ssl_ciphersuite_from_id( int ciphersuite_id );
+
+#if defined(POLARSSL_PK_C)
+pk_type_t ssl_get_ciphersuite_sig_pk_alg( const ssl_ciphersuite_t *info );
+#endif
+
+int ssl_ciphersuite_uses_ec( const ssl_ciphersuite_t *info );
+int ssl_ciphersuite_uses_psk( const ssl_ciphersuite_t *info );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ssl_ciphersuites.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/threading.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,88 @@
+/**
+ * \file threading.h
+ *
+ * \brief Threading abstraction layer
+ *
+ *  Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_THREADING_H
+#define POLARSSL_THREADING_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define POLARSSL_ERR_THREADING_FEATURE_UNAVAILABLE         -0x001A  /**< The selected feature is not available. */
+#define POLARSSL_ERR_THREADING_BAD_INPUT_DATA              -0x001C  /**< Bad input parameters to function. */
+#define POLARSSL_ERR_THREADING_MUTEX_ERROR                 -0x001E  /**< Locking / unlocking / free failed with error code. */
+
+#if defined(POLARSSL_THREADING_PTHREAD)
+#include <pthread.h>
+typedef pthread_mutex_t threading_mutex_t;
+#endif
+
+#if defined(POLARSSL_THREADING_ALT)
+/* You should define the threading_mutex_t type in your header */
+#include "threading_alt.h"
+
+/**
+ * \brief           Set your alternate threading implementation function
+ *                  pointers
+ *
+ * \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
+ *
+ * \return              0 if successful
+ */
+int threading_set_alt( int (*mutex_init)( threading_mutex_t * ),
+                       int (*mutex_free)( threading_mutex_t * ),
+                       int (*mutex_lock)( threading_mutex_t * ),
+                       int (*mutex_unlock)( threading_mutex_t * ) );
+#endif /* POLARSSL_THREADING_ALT_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 int (*polarssl_mutex_init)( threading_mutex_t *mutex );
+extern int (*polarssl_mutex_free)( threading_mutex_t *mutex );
+extern int (*polarssl_mutex_lock)( threading_mutex_t *mutex );
+extern int (*polarssl_mutex_unlock)( threading_mutex_t *mutex );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* threading.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/timing.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,100 @@
+/**
+ * \file timing.h
+ *
+ * \brief Portable interface to the CPU cycle counter
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_TIMING_H
+#define POLARSSL_TIMING_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if !defined(POLARSSL_TIMING_ALT)
+// Regular implementation
+//
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          timer structure
+ */
+struct hr_time
+{
+    unsigned char opaque[32];
+};
+
+extern volatile int alarmed;
+
+/**
+ * \brief          Return the CPU cycle counter value
+ */
+unsigned long hardclock( void );
+
+/**
+ * \brief          Return the elapsed time in milliseconds
+ *
+ * \param val      points to a timer structure
+ * \param reset    if set to 1, the timer is restarted
+ */
+unsigned long get_timer( struct hr_time *val, int reset );
+
+/**
+ * \brief          Setup an alarm clock
+ *
+ * \param seconds  delay before the "alarmed" flag is set
+ */
+void set_alarm( int seconds );
+
+/**
+ * \brief          Sleep for a certain amount of time
+ *
+ * \param milliseconds  delay in milliseconds
+ */
+void m_sleep( int milliseconds );
+
+#if defined(POLARSSL_SELF_TEST)
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if a test failed
+ */
+int timing_self_test( int verbose );
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#else  /* POLARSSL_TIMING_ALT */
+#include "timing_alt.h"
+#endif /* POLARSSL_TIMING_ALT */
+
+#endif /* timing.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/version.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,116 @@
+/**
+ * \file version.h
+ *
+ * \brief Run-time version information
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * This set of compile-time defines and run-time variables can be used to
+ * determine the version number of the PolarSSL library used.
+ */
+#ifndef POLARSSL_VERSION_H
+#define POLARSSL_VERSION_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+/**
+ * The version number x.y.z is split into three parts.
+ * Major, Minor, Patchlevel
+ */
+#define POLARSSL_VERSION_MAJOR  1
+#define POLARSSL_VERSION_MINOR  3
+#define POLARSSL_VERSION_PATCH  7
+
+/**
+ * The single version number has the following structure:
+ *    MMNNPP00
+ *    Major version | Minor version | Patch version
+ */
+#define POLARSSL_VERSION_NUMBER         0x01030700
+#define POLARSSL_VERSION_STRING         "1.3.7"
+#define POLARSSL_VERSION_STRING_FULL    "PolarSSL 1.3.7"
+
+#if defined(POLARSSL_VERSION_C)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Get the version number.
+ *
+ * \return          The constructed version number in the format
+ *                  MMNNPP00 (Major, Minor, Patch).
+ */
+unsigned int version_get_number( void );
+
+/**
+ * Get the version string ("x.y.z").
+ *
+ * \param string    The string that will receive the value.
+ *                  (Should be at least 9 bytes in size)
+ */
+void version_get_string( char *string );
+
+/**
+ * Get the full version string ("PolarSSL x.y.z").
+ *
+ * \param string    The string that will receive the value. The PolarSSL version
+ *                  string will use 18 bytes AT MOST including a terminating
+ *                  null byte.
+ *                  (So the buffer should be at least 18 bytes to receive this
+ *                  version string).
+ */
+void version_get_string_full( char *string );
+
+/**
+ * \brief           Check if support for a feature was compiled into this
+ *                  PolarSSL binary. This allows you to see at runtime if the
+ *                  library was for instance compiled with or without
+ *                  Multi-threading support.
+ *
+ *                  Note: only checks against defines in the sections "System
+ *                        support", "PolarSSL modules" and "PolarSSL feature
+ *                        support" in config.h
+ *
+ * \param feature   The string for the define to check (e.g. "POLARSSL_AES_C")
+ *
+ * \return          0 if the feature is present, -1 if the feature is not
+ *                  present and -2 if support for feature checking as a whole
+ *                  was not compiled in.
+ */
+int version_check_feature( const char *feature );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* POLARSSL_VERSION_C */
+
+#endif /* version.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/x509.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,308 @@
+/**
+ * \file x509.h
+ *
+ * \brief X.509 generic defines and structures
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_X509_H
+#define POLARSSL_X509_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#include "asn1.h"
+#include "pk.h"
+
+#if defined(POLARSSL_RSA_C)
+#include "rsa.h"
+#endif
+
+/**
+ * \addtogroup x509_module
+ * \{
+ */
+
+/**
+ * \name X509 Error codes
+ * \{
+ */
+#define POLARSSL_ERR_X509_FEATURE_UNAVAILABLE              -0x2080  /**< Unavailable feature, e.g. RSA hashing/encryption combination. */
+#define POLARSSL_ERR_X509_UNKNOWN_OID                      -0x2100  /**< Requested OID is unknown. */
+#define POLARSSL_ERR_X509_INVALID_FORMAT                   -0x2180  /**< The CRT/CRL/CSR format is invalid, e.g. different type expected. */
+#define POLARSSL_ERR_X509_INVALID_VERSION                  -0x2200  /**< The CRT/CRL/CSR version element is invalid. */
+#define POLARSSL_ERR_X509_INVALID_SERIAL                   -0x2280  /**< The serial tag or value is invalid. */
+#define POLARSSL_ERR_X509_INVALID_ALG                      -0x2300  /**< The algorithm tag or value is invalid. */
+#define POLARSSL_ERR_X509_INVALID_NAME                     -0x2380  /**< The name tag or value is invalid. */
+#define POLARSSL_ERR_X509_INVALID_DATE                     -0x2400  /**< The date tag or value is invalid. */
+#define POLARSSL_ERR_X509_INVALID_SIGNATURE                -0x2480  /**< The signature tag or value invalid. */
+#define POLARSSL_ERR_X509_INVALID_EXTENSIONS               -0x2500  /**< The extension tag or value is invalid. */
+#define POLARSSL_ERR_X509_UNKNOWN_VERSION                  -0x2580  /**< CRT/CRL/CSR has an unsupported version number. */
+#define POLARSSL_ERR_X509_UNKNOWN_SIG_ALG                  -0x2600  /**< Signature algorithm (oid) is unsupported. */
+#define POLARSSL_ERR_X509_SIG_MISMATCH                     -0x2680  /**< Signature algorithms do not match. (see \c ::x509_crt sig_oid) */
+#define POLARSSL_ERR_X509_CERT_VERIFY_FAILED               -0x2700  /**< Certificate verification failed, e.g. CRL, CA or signature check failed. */
+#define POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT              -0x2780  /**< Format not recognized as DER or PEM. */
+#define POLARSSL_ERR_X509_BAD_INPUT_DATA                   -0x2800  /**< Input invalid. */
+#define POLARSSL_ERR_X509_MALLOC_FAILED                    -0x2880  /**< Allocation of memory failed. */
+#define POLARSSL_ERR_X509_FILE_IO_ERROR                    -0x2900  /**< Read/write of file failed. */
+/* \} name */
+
+/**
+ * \name X509 Verify codes
+ * \{
+ */
+#define BADCERT_EXPIRED             0x01  /**< The certificate validity has expired. */
+#define BADCERT_REVOKED             0x02  /**< The certificate has been revoked (is on a CRL). */
+#define BADCERT_CN_MISMATCH         0x04  /**< The certificate Common Name (CN) does not match with the expected CN. */
+#define BADCERT_NOT_TRUSTED         0x08  /**< The certificate is not correctly signed by the trusted CA. */
+#define BADCRL_NOT_TRUSTED          0x10  /**< CRL is not correctly signed by the trusted CA. */
+#define BADCRL_EXPIRED              0x20  /**< CRL is expired. */
+#define BADCERT_MISSING             0x40  /**< Certificate was missing. */
+#define BADCERT_SKIP_VERIFY         0x80  /**< Certificate verification was skipped. */
+#define BADCERT_OTHER             0x0100  /**< Other reason (can be used by verify callback) */
+#define BADCERT_FUTURE            0x0200  /**< The certificate validity starts in the future. */
+#define BADCRL_FUTURE             0x0400  /**< The CRL is from the future */
+/* \} name */
+/* \} addtogroup x509_module */
+
+/*
+ * X.509 v3 Key Usage Extension flags
+ */
+#define KU_DIGITAL_SIGNATURE            (0x80)  /* bit 0 */
+#define KU_NON_REPUDIATION              (0x40)  /* bit 1 */
+#define KU_KEY_ENCIPHERMENT             (0x20)  /* bit 2 */
+#define KU_DATA_ENCIPHERMENT            (0x10)  /* bit 3 */
+#define KU_KEY_AGREEMENT                (0x08)  /* bit 4 */
+#define KU_KEY_CERT_SIGN                (0x04)  /* bit 5 */
+#define KU_CRL_SIGN                     (0x02)  /* bit 6 */
+
+/*
+ * Netscape certificate types
+ * (http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn3.html)
+ */
+
+#define NS_CERT_TYPE_SSL_CLIENT         (0x80)  /* bit 0 */
+#define NS_CERT_TYPE_SSL_SERVER         (0x40)  /* bit 1 */
+#define NS_CERT_TYPE_EMAIL              (0x20)  /* bit 2 */
+#define NS_CERT_TYPE_OBJECT_SIGNING     (0x10)  /* bit 3 */
+#define NS_CERT_TYPE_RESERVED           (0x08)  /* bit 4 */
+#define NS_CERT_TYPE_SSL_CA             (0x04)  /* bit 5 */
+#define NS_CERT_TYPE_EMAIL_CA           (0x02)  /* bit 6 */
+#define NS_CERT_TYPE_OBJECT_SIGNING_CA  (0x01)  /* bit 7 */
+
+/*
+ * X.509 extension types
+ *
+ * Comments refer to the status for using certificates. Status can be
+ * different for writing certificates or reading CRLs or CSRs.
+ */
+#define EXT_AUTHORITY_KEY_IDENTIFIER    (1 << 0)
+#define EXT_SUBJECT_KEY_IDENTIFIER      (1 << 1)
+#define EXT_KEY_USAGE                   (1 << 2)    /* Parsed but not used */
+#define EXT_CERTIFICATE_POLICIES        (1 << 3)
+#define EXT_POLICY_MAPPINGS             (1 << 4)
+#define EXT_SUBJECT_ALT_NAME            (1 << 5)    /* Supported (DNS) */
+#define EXT_ISSUER_ALT_NAME             (1 << 6)
+#define EXT_SUBJECT_DIRECTORY_ATTRS     (1 << 7)
+#define EXT_BASIC_CONSTRAINTS           (1 << 8)    /* Supported */
+#define EXT_NAME_CONSTRAINTS            (1 << 9)
+#define EXT_POLICY_CONSTRAINTS          (1 << 10)
+#define EXT_EXTENDED_KEY_USAGE          (1 << 11)   /* Parsed but not used */
+#define EXT_CRL_DISTRIBUTION_POINTS     (1 << 12)
+#define EXT_INIHIBIT_ANYPOLICY          (1 << 13)
+#define EXT_FRESHEST_CRL                (1 << 14)
+
+#define EXT_NS_CERT_TYPE                (1 << 16)   /* Parsed (and then ?) */
+
+/*
+ * Storage format identifiers
+ * Recognized formats: PEM and DER
+ */
+#define X509_FORMAT_DER                 1
+#define X509_FORMAT_PEM                 2
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \addtogroup x509_module
+ * \{ */
+
+/**
+ * \name Structures for parsing X.509 certificates, CRLs and CSRs
+ * \{
+ */
+
+/**
+ * Type-length-value structure that allows for ASN1 using DER.
+ */
+typedef asn1_buf x509_buf;
+
+/**
+ * Container for ASN1 bit strings.
+ */
+typedef asn1_bitstring x509_bitstring;
+
+/**
+ * Container for ASN1 named information objects.
+ * It allows for Relative Distinguished Names (e.g. cn=polarssl,ou=code,etc.).
+ */
+typedef asn1_named_data x509_name;
+
+/**
+ * Container for a sequence of ASN.1 items
+ */
+typedef asn1_sequence x509_sequence;
+
+/** Container for date and time (precision in seconds). */
+typedef struct _x509_time
+{
+    int year, mon, day;         /**< Date. */
+    int hour, min, sec;         /**< Time. */
+}
+x509_time;
+
+/** \} name Structures for parsing X.509 certificates, CRLs and CSRs */
+/** \} addtogroup x509_module */
+
+/**
+ * \brief          Store the certificate DN in printable form into buf;
+ *                 no more than size characters will be written.
+ *
+ * \param buf      Buffer to write to
+ * \param size     Maximum size of buffer
+ * \param dn       The X509 name to represent
+ *
+ * \return         The amount of data written to the buffer, or -1 in
+ *                 case of an error.
+ */
+int x509_dn_gets( char *buf, size_t size, const x509_name *dn );
+
+/**
+ * \brief          Store the certificate serial in printable form into buf;
+ *                 no more than size characters will be written.
+ *
+ * \param buf      Buffer to write to
+ * \param size     Maximum size of buffer
+ * \param serial   The X509 serial to represent
+ *
+ * \return         The amount of data written to the buffer, or -1 in
+ *                 case of an error.
+ */
+int x509_serial_gets( char *buf, size_t size, const x509_buf *serial );
+
+/**
+ * \brief          Give an known OID, return its descriptive string.
+ *                 (Deprecated. Use oid_get_extended_key_usage() instead.)
+ *                 Warning: only works for extended_key_usage OIDs!
+ *
+ * \param oid      buffer containing the oid
+ *
+ * \return         Return a string if the OID is known,
+ *                 or NULL otherwise.
+ */
+const char *x509_oid_get_description( x509_buf *oid );
+
+/**
+ * \brief          Give an OID, return a string version of its OID number.
+ *                 (Deprecated. Use oid_get_numeric_string() instead)
+ *
+ * \param buf      Buffer to write to
+ * \param size     Maximum size of buffer
+ * \param oid      Buffer containing the OID
+ *
+ * \return         Length of the string written (excluding final NULL) or
+ *                 POLARSSL_ERR_OID_BUF_TO_SMALL in case of error
+ */
+int x509_oid_get_numeric_string( char *buf, size_t size, x509_buf *oid );
+
+/**
+ * \brief          Check a given x509_time against the system time and check
+ *                 if it is not expired.
+ *
+ * \param time     x509_time to check
+ *
+ * \return         0 if the x509_time is still valid,
+ *                 1 otherwise.
+ */
+int x509_time_expired( const x509_time *time );
+
+/**
+ * \brief          Check a given x509_time against the system time and check
+ *                 if it is not from the future.
+ *
+ * \param time     x509_time to check
+ *
+ * \return         0 if the x509_time is already valid,
+ *                 1 otherwise.
+ */
+int x509_time_future( const x509_time *time );
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int x509_self_test( int verbose );
+
+/*
+ * Internal module functions. You probably do not want to use these unless you
+ * know you do.
+ */
+int x509_get_name( unsigned char **p, const unsigned char *end,
+                   x509_name *cur );
+int x509_get_alg_null( unsigned char **p, const unsigned char *end,
+                       x509_buf *alg );
+int x509_get_sig( unsigned char **p, const unsigned char *end, x509_buf *sig );
+int x509_get_sig_alg( const x509_buf *sig_oid, md_type_t *md_alg,
+                      pk_type_t *pk_alg );
+int x509_get_time( unsigned char **p, const unsigned char *end,
+                   x509_time *time );
+int x509_get_serial( unsigned char **p, const unsigned char *end,
+                     x509_buf *serial );
+int x509_get_ext( unsigned char **p, const unsigned char *end,
+                  x509_buf *ext, int tag );
+int x509_load_file( const char *path, unsigned char **buf, size_t *n );
+int x509_key_size_helper( char *buf, size_t size, const char *name );
+int x509_string_to_names( asn1_named_data **head, const char *name );
+int x509_set_extension( asn1_named_data **head, const char *oid, size_t oid_len,
+                        int critical, const unsigned char *val,
+                        size_t val_len );
+int x509_write_extensions( unsigned char **p, unsigned char *start,
+                           asn1_named_data *first );
+int x509_write_names( unsigned char **p, unsigned char *start,
+                      asn1_named_data *first );
+int x509_write_sig( unsigned char **p, unsigned char *start,
+                    const char *oid, size_t oid_len,
+                    unsigned char *sig, size_t size );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* x509.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/x509_crl.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,163 @@
+/**
+ * \file x509_crl.h
+ *
+ * \brief X.509 certificate revocation list parsing
+ *
+ *  Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_X509_CRL_H
+#define POLARSSL_X509_CRL_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#include "x509.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \addtogroup x509_module
+ * \{ */
+
+/**
+ * \name Structures and functions for parsing CRLs
+ * \{
+ */
+
+/**
+ * Certificate revocation list entry.
+ * Contains the CA-specific serial numbers and revocation dates.
+ */
+typedef struct _x509_crl_entry
+{
+    x509_buf raw;
+
+    x509_buf serial;
+
+    x509_time revocation_date;
+
+    x509_buf entry_ext;
+
+    struct _x509_crl_entry *next;
+}
+x509_crl_entry;
+
+/**
+ * Certificate revocation list structure.
+ * Every CRL may have multiple entries.
+ */
+typedef struct _x509_crl
+{
+    x509_buf raw;           /**< The raw certificate data (DER). */
+    x509_buf tbs;           /**< The raw certificate body (DER). The part that is To Be Signed. */
+
+    int version;
+    x509_buf sig_oid1;
+
+    x509_buf issuer_raw;    /**< The raw issuer data (DER). */
+
+    x509_name issuer;       /**< The parsed issuer data (named information object). */
+
+    x509_time this_update;
+    x509_time next_update;
+
+    x509_crl_entry entry;   /**< The CRL entries containing the certificate revocation times for this CA. */
+
+    x509_buf crl_ext;
+
+    x509_buf sig_oid2;
+    x509_buf sig;
+    md_type_t sig_md;           /**< Internal representation of the MD algorithm of the signature algorithm, e.g. POLARSSL_MD_SHA256 */
+    pk_type_t sig_pk            /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. POLARSSL_PK_RSA */;
+
+    struct _x509_crl *next;
+}
+x509_crl;
+
+/**
+ * \brief          Parse one or more CRLs and add them
+ *                 to the chained list
+ *
+ * \param chain    points to the start of the chain
+ * \param buf      buffer holding the CRL data
+ * \param buflen   size of the buffer
+ *
+ * \return         0 if successful, or a specific X509 or PEM error code
+ */
+int x509_crl_parse( x509_crl *chain, const unsigned char *buf, size_t buflen );
+
+#if defined(POLARSSL_FS_IO)
+/**
+ * \brief          Load one or more CRLs and add them
+ *                 to the chained list
+ *
+ * \param chain    points to the start of the chain
+ * \param path     filename to read the CRLs from
+ *
+ * \return         0 if successful, or a specific X509 or PEM error code
+ */
+int x509_crl_parse_file( x509_crl *chain, const char *path );
+#endif /* POLARSSL_FS_IO */
+
+/**
+ * \brief          Returns an informational string about the CRL.
+ *
+ * \param buf      Buffer to write to
+ * \param size     Maximum size of buffer
+ * \param prefix   A line prefix
+ * \param crl      The X509 CRL to represent
+ *
+ * \return         The amount of data written to the buffer, or -1 in
+ *                 case of an error.
+ */
+int x509_crl_info( char *buf, size_t size, const char *prefix,
+                   const x509_crl *crl );
+
+/**
+ * \brief          Initialize a CRL (chain)
+ *
+ * \param crl      CRL chain to initialize
+ */
+void x509_crl_init( x509_crl *crl );
+
+/**
+ * \brief          Unallocate all CRL data
+ *
+ * \param crl      CRL chain to free
+ */
+void x509_crl_free( x509_crl *crl );
+
+/* \} name */
+/* \} addtogroup x509_module */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* x509_crl.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/x509_crt.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,559 @@
+/**
+ * \file x509_crt.h
+ *
+ * \brief X.509 certificate parsing and writing
+ *
+ *  Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_X509_CRT_H
+#define POLARSSL_X509_CRT_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#include "x509.h"
+
+#include "x509_crl.h"
+
+/**
+ * \addtogroup x509_module
+ * \{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \name Structures and functions for parsing and writing X.509 certificates
+ * \{
+ */
+
+/**
+ * Container for an X.509 certificate. The certificate may be chained.
+ */
+typedef struct _x509_crt
+{
+    x509_buf raw;               /**< The raw certificate data (DER). */
+    x509_buf tbs;               /**< The raw certificate body (DER). The part that is To Be Signed. */
+
+    int version;                /**< The X.509 version. (0=v1, 1=v2, 2=v3) */
+    x509_buf serial;            /**< Unique id for certificate issued by a specific CA. */
+    x509_buf sig_oid1;          /**< Signature algorithm, e.g. sha1RSA */
+
+    x509_buf issuer_raw;        /**< The raw issuer data (DER). Used for quick comparison. */
+    x509_buf subject_raw;       /**< The raw subject data (DER). Used for quick comparison. */
+
+    x509_name issuer;           /**< The parsed issuer data (named information object). */
+    x509_name subject;          /**< The parsed subject data (named information object). */
+
+    x509_time valid_from;       /**< Start time of certificate validity. */
+    x509_time valid_to;         /**< End time of certificate validity. */
+
+    pk_context pk;              /**< Container for the public key context. */
+
+    x509_buf issuer_id;         /**< Optional X.509 v2/v3 issuer unique identifier. */
+    x509_buf subject_id;        /**< Optional X.509 v2/v3 subject unique identifier. */
+    x509_buf v3_ext;            /**< Optional X.509 v3 extensions.  */
+    x509_sequence subject_alt_names;    /**< Optional list of Subject Alternative Names (Only dNSName supported). */
+
+    int ext_types;              /**< Bit string containing detected and parsed extensions */
+    int ca_istrue;              /**< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. */
+    int max_pathlen;            /**< Optional Basic Constraint extension value: The maximum path length to the root certificate. Path length is 1 higher than RFC 5280 'meaning', so 1+ */
+
+    unsigned char key_usage;    /**< Optional key usage extension value: See the values in x509.h */
+
+    x509_sequence ext_key_usage; /**< Optional list of extended key usage OIDs. */
+
+    unsigned char ns_cert_type; /**< Optional Netscape certificate type extension value: See the values in x509.h */
+
+    x509_buf sig_oid2;          /**< Signature algorithm. Must match sig_oid1. */
+    x509_buf sig;               /**< Signature: hash of the tbs part signed with the private key. */
+    md_type_t sig_md;           /**< Internal representation of the MD algorithm of the signature algorithm, e.g. POLARSSL_MD_SHA256 */
+    pk_type_t sig_pk            /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. POLARSSL_PK_RSA */;
+
+    struct _x509_crt *next;     /**< Next certificate in the CA-chain. */
+}
+x509_crt;
+
+#define X509_CRT_VERSION_1              0
+#define X509_CRT_VERSION_2              1
+#define X509_CRT_VERSION_3              2
+
+#define X509_RFC5280_MAX_SERIAL_LEN 32
+#define X509_RFC5280_UTC_TIME_LEN   15
+
+/**
+ * Container for writing a certificate (CRT)
+ */
+typedef struct _x509write_cert
+{
+    int version;
+    mpi serial;
+    pk_context *subject_key;
+    pk_context *issuer_key;
+    asn1_named_data *subject;
+    asn1_named_data *issuer;
+    md_type_t md_alg;
+    char not_before[X509_RFC5280_UTC_TIME_LEN + 1];
+    char not_after[X509_RFC5280_UTC_TIME_LEN + 1];
+    asn1_named_data *extensions;
+}
+x509write_cert;
+
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+/**
+ * \brief          Parse a single DER formatted certificate and add it
+ *                 to the chained list.
+ *
+ * \param chain    points to the start of the chain
+ * \param buf      buffer holding the certificate DER data
+ * \param buflen   size of the buffer
+ *
+ * \return         0 if successful, or a specific X509 or PEM error code
+ */
+int x509_crt_parse_der( x509_crt *chain, const unsigned char *buf,
+                        size_t buflen );
+
+/**
+ * \brief          Parse one or more certificates and add them
+ *                 to the chained list. Parses permissively. If some
+ *                 certificates can be parsed, the result is the number
+ *                 of failed certificates it encountered. If none complete
+ *                 correctly, the first error is returned.
+ *
+ * \param chain    points to the start of the chain
+ * \param buf      buffer holding the certificate data
+ * \param buflen   size of the buffer
+ *
+ * \return         0 if all certificates parsed successfully, a positive number
+ *                 if partly successful or a specific X509 or PEM error code
+ */
+int x509_crt_parse( x509_crt *chain, const unsigned char *buf, size_t buflen );
+
+#if defined(POLARSSL_FS_IO)
+/**
+ * \brief          Load one or more certificates and add them
+ *                 to the chained list. Parses permissively. If some
+ *                 certificates can be parsed, the result is the number
+ *                 of failed certificates it encountered. If none complete
+ *                 correctly, the first error is returned.
+ *
+ * \param chain    points to the start of the chain
+ * \param path     filename to read the certificates from
+ *
+ * \return         0 if all certificates parsed successfully, a positive number
+ *                 if partly successful or a specific X509 or PEM error code
+ */
+int x509_crt_parse_file( x509_crt *chain, const char *path );
+
+/**
+ * \brief          Load one or more certificate files from a path and add them
+ *                 to the chained list. Parses permissively. If some
+ *                 certificates can be parsed, the result is the number
+ *                 of failed certificates it encountered. If none complete
+ *                 correctly, the first error is returned.
+ *
+ * \warning        This function is NOT thread-safe unless
+ *                 POLARSSL_THREADING_PTHREADS is defined. If you're using an
+ *                 alternative threading implementation, you should either use
+ *                 this function only in the main thread, or mutex it.
+ *
+ * \param chain    points to the start of the chain
+ * \param path     directory / folder to read the certificate files from
+ *
+ * \return         0 if all certificates parsed successfully, a positive number
+ *                 if partly successful or a specific X509 or PEM error code
+ */
+int x509_crt_parse_path( x509_crt *chain, const char *path );
+#endif /* POLARSSL_FS_IO */
+
+/**
+ * \brief          Returns an informational string about the
+ *                 certificate.
+ *
+ * \param buf      Buffer to write to
+ * \param size     Maximum size of buffer
+ * \param prefix   A line prefix
+ * \param crt      The X509 certificate to represent
+ *
+ * \return         The amount of data written to the buffer, or -1 in
+ *                 case of an error.
+ */
+int x509_crt_info( char *buf, size_t size, const char *prefix,
+                   const x509_crt *crt );
+
+/**
+ * \brief          Verify the certificate signature
+ *
+ *                 The verify callback is a user-supplied callback that
+ *                 can clear / modify / add flags for a certificate. If set,
+ *                 the verification callback is called for each
+ *                 certificate in the chain (from the trust-ca down to the
+ *                 presented crt). The parameters for the callback are:
+ *                 (void *parameter, x509_crt *crt, int certificate_depth,
+ *                 int *flags). With the flags representing current flags for
+ *                 that specific certificate and the certificate depth from
+ *                 the bottom (Peer cert depth = 0).
+ *
+ *                 All flags left after returning from the callback
+ *                 are also returned to the application. The function should
+ *                 return 0 for anything but a fatal error.
+ *
+ * \param crt      a certificate to be verified
+ * \param trust_ca the trusted CA chain
+ * \param ca_crl   the CRL chain for trusted CA's
+ * \param cn       expected Common Name (can be set to
+ *                 NULL if the CN must not be verified)
+ * \param flags    result of the verification
+ * \param f_vrfy   verification function
+ * \param p_vrfy   verification parameter
+ *
+ * \return         0 if successful or POLARSSL_ERR_X509_SIG_VERIFY_FAILED,
+ *                 in which case *flags will have one or more of
+ *                 the following values set:
+ *                      BADCERT_EXPIRED --
+ *                      BADCERT_REVOKED --
+ *                      BADCERT_CN_MISMATCH --
+ *                      BADCERT_NOT_TRUSTED
+ *                 or another error in case of a fatal error encountered
+ *                 during the verification process.
+ */
+int x509_crt_verify( x509_crt *crt,
+                     x509_crt *trust_ca,
+                     x509_crl *ca_crl,
+                     const char *cn, int *flags,
+                     int (*f_vrfy)(void *, x509_crt *, int, int *),
+                     void *p_vrfy );
+
+#if defined(POLARSSL_X509_CHECK_KEY_USAGE)
+/**
+ * \brief          Check usage of certificate against keyUsage extension.
+ *
+ * \param crt      Leaf certificate used.
+ * \param usage    Intended usage(s) (eg KU_KEY_ENCIPHERMENT before using the
+ *                 certificate to perform an RSA key exchange).
+ *
+ * \return         0 is these uses of the certificate are allowed,
+ *                 POLARSSL_ERR_X509_BAD_INPUT_DATA if the keyUsage extension
+ *                 is present but does not contain all the bits set in the
+ *                 usage argument.
+ *
+ * \note           You should only call this function on leaf certificates, on
+ *                 (intermediate) CAs the keyUsage extension is automatically
+ *                 checked by \c x509_crt_verify().
+ */
+int x509_crt_check_key_usage( const x509_crt *crt, int usage );
+#endif /* POLARSSL_X509_CHECK_KEY_USAGE) */
+
+#if defined(POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE)
+/**
+ * \brief          Check usage of certificate against extentedJeyUsage.
+ *
+ * \param crt      Leaf certificate used.
+ * \param usage_oid Intended usage (eg OID_SERVER_AUTH or OID_CLIENT_AUTH).
+ * \param usage_len Length of usage_oid (eg given by OID_SIZE()).
+ *
+ * \return         0 is this use of the certificate is allowed,
+ *                 POLARSSL_ERR_X509_BAD_INPUT_DATA if not.
+ *
+ * \note           Usually only makes sense on leaf certificates.
+ */
+int x509_crt_check_extended_key_usage( const x509_crt *crt,
+                                       const char *usage_oid,
+                                       size_t usage_len );
+#endif /* POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE) */
+
+#if defined(POLARSSL_X509_CRL_PARSE_C)
+/**
+ * \brief          Verify the certificate revocation status
+ *
+ * \param crt      a certificate to be verified
+ * \param crl      the CRL to verify against
+ *
+ * \return         1 if the certificate is revoked, 0 otherwise
+ *
+ */
+int x509_crt_revoked( const x509_crt *crt, const x509_crl *crl );
+#endif /* POLARSSL_X509_CRL_PARSE_C */
+
+/**
+ * \brief          Initialize a certificate (chain)
+ *
+ * \param crt      Certificate chain to initialize
+ */
+void x509_crt_init( x509_crt *crt );
+
+/**
+ * \brief          Unallocate all certificate data
+ *
+ * \param crt      Certificate chain to free
+ */
+void x509_crt_free( x509_crt *crt );
+#endif /* POLARSSL_X509_CRT_PARSE_C */
+
+/* \} name */
+/* \} addtogroup x509_module */
+
+#if defined(POLARSSL_X509_CRT_WRITE_C)
+/**
+ * \brief           Initialize a CRT writing context
+ *
+ * \param ctx       CRT context to initialize
+ */
+void x509write_crt_init( x509write_cert *ctx );
+
+/**
+ * \brief           Set the verion for a Certificate
+ *                  Default: X509_CRT_VERSION_3
+ *
+ * \param ctx       CRT context to use
+ * \param version   version to set (X509_CRT_VERSION_1, X509_CRT_VERSION_2 or
+ *                                  X509_CRT_VERSION_3)
+ */
+void x509write_crt_set_version( x509write_cert *ctx, int version );
+
+/**
+ * \brief           Set the serial number for a Certificate.
+ *
+ * \param ctx       CRT context to use
+ * \param serial    serial number to set
+ *
+ * \return          0 if successful
+ */
+int x509write_crt_set_serial( x509write_cert *ctx, const mpi *serial );
+
+/**
+ * \brief           Set the validity period for a Certificate
+ *                  Timestamps should be in string format for UTC timezone
+ *                  i.e. "YYYYMMDDhhmmss"
+ *                  e.g. "20131231235959" for December 31st 2013
+ *                       at 23:59:59
+ *
+ * \param ctx       CRT context to use
+ * \param not_before    not_before timestamp
+ * \param not_after     not_after timestamp
+ *
+ * \return          0 if timestamp was parsed successfully, or
+ *                  a specific error code
+ */
+int x509write_crt_set_validity( x509write_cert *ctx, const char *not_before,
+                                const char *not_after );
+
+/**
+ * \brief           Set the issuer name for a Certificate
+ *                  Issuer names should contain a comma-separated list
+ *                  of OID types and values:
+ *                  e.g. "C=NL,O=Offspark,CN=PolarSSL CA"
+ *
+ * \param ctx           CRT context to use
+ * \param issuer_name   issuer name to set
+ *
+ * \return          0 if issuer name was parsed successfully, or
+ *                  a specific error code
+ */
+int x509write_crt_set_issuer_name( x509write_cert *ctx,
+                                   const char *issuer_name );
+
+/**
+ * \brief           Set the subject name for a Certificate
+ *                  Subject names should contain a comma-separated list
+ *                  of OID types and values:
+ *                  e.g. "C=NL,O=Offspark,CN=PolarSSL Server 1"
+ *
+ * \param ctx           CRT context to use
+ * \param subject_name  subject name to set
+ *
+ * \return          0 if subject name was parsed successfully, or
+ *                  a specific error code
+ */
+int x509write_crt_set_subject_name( x509write_cert *ctx,
+                                    const char *subject_name );
+
+/**
+ * \brief           Set the subject public key for the certificate
+ *
+ * \param ctx       CRT context to use
+ * \param key       public key to include
+ */
+void x509write_crt_set_subject_key( x509write_cert *ctx, pk_context *key );
+
+/**
+ * \brief           Set the issuer key used for signing the certificate
+ *
+ * \param ctx       CRT context to use
+ * \param key       private key to sign with
+ */
+void x509write_crt_set_issuer_key( x509write_cert *ctx, pk_context *key );
+
+/**
+ * \brief           Set the MD algorithm to use for the signature
+ *                  (e.g. POLARSSL_MD_SHA1)
+ *
+ * \param ctx       CRT context to use
+ * \param md_alg    MD algorithm to use
+ */
+void x509write_crt_set_md_alg( x509write_cert *ctx, md_type_t md_alg );
+
+/**
+ * \brief           Generic function to add to or replace an extension in the
+ *                  CRT
+ *
+ * \param ctx       CRT context to use
+ * \param oid       OID of the extension
+ * \param oid_len   length of the OID
+ * \param critical  if the extension is critical (per the RFC's definition)
+ * \param val       value of the extension OCTET STRING
+ * \param val_len   length of the value data
+ *
+ * \return          0 if successful, or a POLARSSL_ERR_X509WRITE_MALLOC_FAILED
+ */
+int x509write_crt_set_extension( x509write_cert *ctx,
+                                 const char *oid, size_t oid_len,
+                                 int critical,
+                                 const unsigned char *val, size_t val_len );
+
+/**
+ * \brief           Set the basicConstraints extension for a CRT
+ *
+ * \param ctx       CRT context to use
+ * \param is_ca     is this a CA certificate
+ * \param max_pathlen   maximum length of certificate chains below this
+ *                      certificate (only for CA certificates, -1 is
+ *                      inlimited)
+ *
+ * \return          0 if successful, or a POLARSSL_ERR_X509WRITE_MALLOC_FAILED
+ */
+int x509write_crt_set_basic_constraints( x509write_cert *ctx,
+                                         int is_ca, int max_pathlen );
+
+#if defined(POLARSSL_SHA1_C)
+/**
+ * \brief           Set the subjectKeyIdentifier extension for a CRT
+ *                  Requires that x509write_crt_set_subject_key() has been
+ *                  called before
+ *
+ * \param ctx       CRT context to use
+ *
+ * \return          0 if successful, or a POLARSSL_ERR_X509WRITE_MALLOC_FAILED
+ */
+int x509write_crt_set_subject_key_identifier( x509write_cert *ctx );
+
+/**
+ * \brief           Set the authorityKeyIdentifier extension for a CRT
+ *                  Requires that x509write_crt_set_issuer_key() has been
+ *                  called before
+ *
+ * \param ctx       CRT context to use
+ *
+ * \return          0 if successful, or a POLARSSL_ERR_X509WRITE_MALLOC_FAILED
+ */
+int x509write_crt_set_authority_key_identifier( x509write_cert *ctx );
+#endif /* POLARSSL_SHA1_C */
+
+/**
+ * \brief           Set the Key Usage Extension flags
+ *                  (e.g. KU_DIGITAL_SIGNATURE | KU_KEY_CERT_SIGN)
+ *
+ * \param ctx       CRT context to use
+ * \param key_usage key usage flags to set
+ *
+ * \return          0 if successful, or POLARSSL_ERR_X509WRITE_MALLOC_FAILED
+ */
+int x509write_crt_set_key_usage( x509write_cert *ctx, unsigned char key_usage );
+
+/**
+ * \brief           Set the Netscape Cert Type flags
+ *                  (e.g. NS_CERT_TYPE_SSL_CLIENT | NS_CERT_TYPE_EMAIL)
+ *
+ * \param ctx           CRT context to use
+ * \param ns_cert_type  Netscape Cert Type flags to set
+ *
+ * \return          0 if successful, or POLARSSL_ERR_X509WRITE_MALLOC_FAILED
+ */
+int x509write_crt_set_ns_cert_type( x509write_cert *ctx,
+                                    unsigned char ns_cert_type );
+
+/**
+ * \brief           Free the contents of a CRT write context
+ *
+ * \param ctx       CRT context to free
+ */
+void x509write_crt_free( x509write_cert *ctx );
+
+/**
+ * \brief           Write a built up certificate to a X509 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       certificate to write away
+ * \param buf       buffer to write to
+ * \param size      size of the buffer
+ * \param f_rng     RNG function (for signature, see note)
+ * \param p_rng     RNG parameter
+ *
+ * \return          length of data written if successful, or a specific
+ *                  error code
+ *
+ * \note            f_rng may be NULL if RSA is used for signature and the
+ *                  signature is made offline (otherwise f_rng is desirable
+ *                  for countermeasures against timing attacks).
+ *                  ECDSA signatures always require a non-NULL f_rng.
+ */
+int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size,
+                       int (*f_rng)(void *, unsigned char *, size_t),
+                       void *p_rng );
+
+#if defined(POLARSSL_PEM_WRITE_C)
+/**
+ * \brief           Write a built up certificate to a X509 PEM string
+ *
+ * \param ctx       certificate to write away
+ * \param buf       buffer to write to
+ * \param size      size of the buffer
+ * \param f_rng     RNG function (for signature, see note)
+ * \param p_rng     RNG parameter
+ *
+ * \return          0 successful, or a specific error code
+ *
+ * \note            f_rng may be NULL if RSA is used for signature and the
+ *                  signature is made offline (otherwise f_rng is desirable
+ *                  for countermeasures against timing attacks).
+ *                  ECDSA signatures always require a non-NULL f_rng.
+ */
+int x509write_crt_pem( x509write_cert *ctx, unsigned char *buf, size_t size,
+                       int (*f_rng)(void *, unsigned char *, size_t),
+                       void *p_rng );
+#endif /* POLARSSL_PEM_WRITE_C */
+#endif /* POLARSSL_X509_CRT_WRITE_C */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* x509_crt.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/x509_csr.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,284 @@
+/**
+ * \file x509_csr.h
+ *
+ * \brief X.509 certificate signing request parsing and writing
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_X509_CSR_H
+#define POLARSSL_X509_CSR_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#include "x509.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \addtogroup x509_module
+ * \{ */
+
+/**
+ * \name Structures and functions for X.509 Certificate Signing Requests (CSR)
+ * \{
+ */
+
+/**
+ * Certificate Signing Request (CSR) structure.
+ */
+typedef struct _x509_csr
+{
+    x509_buf raw;           /**< The raw CSR data (DER). */
+    x509_buf cri;           /**< The raw CertificateRequestInfo body (DER). */
+
+    int version;
+
+    x509_buf  subject_raw;  /**< The raw subject data (DER). */
+    x509_name subject;      /**< The parsed subject data (named information object). */
+
+    pk_context pk;          /**< Container for the public key context. */
+
+    x509_buf sig_oid;
+    x509_buf sig;
+    md_type_t sig_md;       /**< Internal representation of the MD algorithm of the signature algorithm, e.g. POLARSSL_MD_SHA256 */
+    pk_type_t sig_pk        /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. POLARSSL_PK_RSA */;
+}
+x509_csr;
+
+/**
+ * Container for writing a CSR
+ */
+typedef struct _x509write_csr
+{
+    pk_context *key;
+    asn1_named_data *subject;
+    md_type_t md_alg;
+    asn1_named_data *extensions;
+}
+x509write_csr;
+
+#if defined(POLARSSL_X509_CSR_PARSE_C)
+/**
+ * \brief          Load a Certificate Signing Request (CSR)
+ *
+ * \param csr      CSR context to fill
+ * \param buf      buffer holding the CRL data
+ * \param buflen   size of the buffer
+ *
+ * \return         0 if successful, or a specific X509 or PEM error code
+ */
+int x509_csr_parse( x509_csr *csr, const unsigned char *buf, size_t buflen );
+
+#if defined(POLARSSL_FS_IO)
+/**
+ * \brief          Load a Certificate Signing Request (CSR)
+ *
+ * \param csr      CSR context to fill
+ * \param path     filename to read the CSR from
+ *
+ * \return         0 if successful, or a specific X509 or PEM error code
+ */
+int x509_csr_parse_file( x509_csr *csr, const char *path );
+#endif /* POLARSSL_FS_IO */
+
+/**
+ * \brief          Returns an informational string about the
+ *                 CSR.
+ *
+ * \param buf      Buffer to write to
+ * \param size     Maximum size of buffer
+ * \param prefix   A line prefix
+ * \param csr      The X509 CSR to represent
+ *
+ * \return         The amount of data written to the buffer, or -1 in
+ *                 case of an error.
+ */
+int x509_csr_info( char *buf, size_t size, const char *prefix,
+                   const x509_csr *csr );
+
+/**
+ * \brief          Initialize a CSR
+ *
+ * \param csr      CSR to initialize
+ */
+void x509_csr_init( x509_csr *csr );
+
+/**
+ * \brief          Unallocate all CSR data
+ *
+ * \param csr      CSR to free
+ */
+void x509_csr_free( x509_csr *csr );
+#endif /* POLARSSL_X509_CSR_PARSE_C */
+
+/* \} name */
+/* \} addtogroup x509_module */
+
+#if defined(POLARSSL_X509_CSR_WRITE_C)
+/**
+ * \brief           Initialize a CSR context
+ *
+ * \param ctx       CSR context to initialize
+ */
+void x509write_csr_init( x509write_csr *ctx );
+
+/**
+ * \brief           Set the subject name for a CSR
+ *                  Subject names should contain a comma-separated list
+ *                  of OID types and values:
+ *                  e.g. "C=NL,O=Offspark,CN=PolarSSL Server 1"
+ *
+ * \param ctx           CSR context to use
+ * \param subject_name  subject name to set
+ *
+ * \return          0 if subject name was parsed successfully, or
+ *                  a specific error code
+ */
+int x509write_csr_set_subject_name( x509write_csr *ctx,
+                                    const char *subject_name );
+
+/**
+ * \brief           Set the key for a CSR (public key will be included,
+ *                  private key used to sign the CSR when writing it)
+ *
+ * \param ctx       CSR context to use
+ * \param key       Asymetric key to include
+ */
+void x509write_csr_set_key( x509write_csr *ctx, pk_context *key );
+
+/**
+ * \brief           Set the MD algorithm to use for the signature
+ *                  (e.g. POLARSSL_MD_SHA1)
+ *
+ * \param ctx       CSR context to use
+ * \param md_alg    MD algorithm to use
+ */
+void x509write_csr_set_md_alg( x509write_csr *ctx, md_type_t md_alg );
+
+/**
+ * \brief           Set the Key Usage Extension flags
+ *                  (e.g. KU_DIGITAL_SIGNATURE | KU_KEY_CERT_SIGN)
+ *
+ * \param ctx       CSR context to use
+ * \param key_usage key usage flags to set
+ *
+ * \return          0 if successful, or POLARSSL_ERR_X509WRITE_MALLOC_FAILED
+ */
+int x509write_csr_set_key_usage( x509write_csr *ctx, unsigned char key_usage );
+
+/**
+ * \brief           Set the Netscape Cert Type flags
+ *                  (e.g. NS_CERT_TYPE_SSL_CLIENT | NS_CERT_TYPE_EMAIL)
+ *
+ * \param ctx           CSR context to use
+ * \param ns_cert_type  Netscape Cert Type flags to set
+ *
+ * \return          0 if successful, or POLARSSL_ERR_X509WRITE_MALLOC_FAILED
+ */
+int x509write_csr_set_ns_cert_type( x509write_csr *ctx,
+                                    unsigned char ns_cert_type );
+
+/**
+ * \brief           Generic function to add to or replace an extension in the
+ *                  CSR
+ *
+ * \param ctx       CSR context to use
+ * \param oid       OID of the extension
+ * \param oid_len   length of the OID
+ * \param val       value of the extension OCTET STRING
+ * \param val_len   length of the value data
+ *
+ * \return          0 if successful, or a POLARSSL_ERR_X509WRITE_MALLOC_FAILED
+ */
+int x509write_csr_set_extension( x509write_csr *ctx,
+                                 const char *oid, size_t oid_len,
+                                 const unsigned char *val, size_t val_len );
+
+/**
+ * \brief           Free the contents of a CSR context
+ *
+ * \param ctx       CSR context to free
+ */
+void x509write_csr_free( x509write_csr *ctx );
+
+/**
+ * \brief           Write a CSR (Certificate Signing Request) to a
+ *                  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       CSR to write away
+ * \param buf       buffer to write to
+ * \param size      size of the buffer
+ * \param f_rng     RNG function (for signature, see note)
+ * \param p_rng     RNG parameter
+ *
+ * \return          length of data written if successful, or a specific
+ *                  error code
+ *
+ * \note            f_rng may be NULL if RSA is used for signature and the
+ *                  signature is made offline (otherwise f_rng is desirable
+ *                  for countermeasures against timing attacks).
+ *                  ECDSA signatures always require a non-NULL f_rng.
+ */
+int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size,
+                       int (*f_rng)(void *, unsigned char *, size_t),
+                       void *p_rng );
+
+#if defined(POLARSSL_PEM_WRITE_C)
+/**
+ * \brief           Write a CSR (Certificate Signing Request) to a
+ *                  PEM string
+ *
+ * \param ctx       CSR to write away
+ * \param buf       buffer to write to
+ * \param size      size of the buffer
+ * \param f_rng     RNG function (for signature, see note)
+ * \param p_rng     RNG parameter
+ *
+ * \return          0 successful, or a specific error code
+ *
+ * \note            f_rng may be NULL if RSA is used for signature and the
+ *                  signature is made offline (otherwise f_rng is desirable
+ *                  for couermeasures against timing attacks).
+ *                  ECDSA signatures always require a non-NULL f_rng.
+ */
+int x509write_csr_pem( x509write_csr *ctx, unsigned char *buf, size_t size,
+                       int (*f_rng)(void *, unsigned char *, size_t),
+                       void *p_rng );
+#endif /* POLARSSL_PEM_WRITE_C */
+#endif /* POLARSSL_X509_CSR_WRITE_C */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* x509_csr.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/include/polarssl/xtea.h	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,137 @@
+/**
+ * \file xtea.h
+ *
+ * \brief XTEA block cipher (32-bit)
+ *
+ *  Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_XTEA_H
+#define POLARSSL_XTEA_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#include <string.h>
+
+#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
+#include <basetsd.h>
+typedef UINT32 uint32_t;
+#else
+#include <inttypes.h>
+#endif
+
+#define XTEA_ENCRYPT     1
+#define XTEA_DECRYPT     0
+
+#define POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH             -0x0028  /**< The data input has an invalid length. */
+
+#if !defined(POLARSSL_XTEA_ALT)
+// Regular implementation
+//
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          XTEA context structure
+ */
+typedef struct
+{
+    uint32_t k[4];       /*!< key */
+}
+xtea_context;
+
+/**
+ * \brief          XTEA key schedule
+ *
+ * \param ctx      XTEA context to be initialized
+ * \param key      the secret key
+ */
+void xtea_setup( xtea_context *ctx, const unsigned char key[16] );
+
+/**
+ * \brief          XTEA cipher function
+ *
+ * \param ctx      XTEA context
+ * \param mode     XTEA_ENCRYPT or XTEA_DECRYPT
+ * \param input    8-byte input block
+ * \param output   8-byte output block
+ *
+ * \return         0 if successful
+ */
+int xtea_crypt_ecb( xtea_context *ctx,
+                    int mode,
+                    const unsigned char input[8],
+                    unsigned char output[8] );
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+/**
+ * \brief          XTEA CBC cipher function
+ *
+ * \param ctx      XTEA context
+ * \param mode     XTEA_ENCRYPT or 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,
+ *                 POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH if the length % 8 != 0
+ */
+int xtea_crypt_cbc( xtea_context *ctx,
+                    int mode,
+                    size_t length,
+                    unsigned char iv[8],
+                    const unsigned char *input,
+                    unsigned char *output);
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+#ifdef __cplusplus
+}
+#endif
+
+#else  /* POLARSSL_XTEA_ALT */
+#include "xtea_alt.h"
+#endif /* POLARSSL_XTEA_ALT */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int xtea_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* xtea.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/aes.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,1435 @@
+/*
+ *  FIPS-197 compliant AES implementation
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  The AES block cipher was designed by Vincent Rijmen and Joan Daemen.
+ *
+ *  http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf
+ *  http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_AES_C)
+
+#include "polarssl/aes.h"
+#if defined(POLARSSL_PADLOCK_C)
+#include "polarssl/padlock.h"
+#endif
+#if defined(POLARSSL_AESNI_C)
+#include "polarssl/aesni.h"
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
+#if !defined(POLARSSL_AES_ALT)
+
+/*
+ * 32-bit integer manipulation macros (little endian)
+ */
+#ifndef GET_UINT32_LE
+#define GET_UINT32_LE(n,b,i)                            \
+{                                                       \
+    (n) = ( (uint32_t) (b)[(i)    ]       )             \
+        | ( (uint32_t) (b)[(i) + 1] <<  8 )             \
+        | ( (uint32_t) (b)[(i) + 2] << 16 )             \
+        | ( (uint32_t) (b)[(i) + 3] << 24 );            \
+}
+#endif
+
+#ifndef PUT_UINT32_LE
+#define PUT_UINT32_LE(n,b,i)                            \
+{                                                       \
+    (b)[(i)    ] = (unsigned char) ( (n)       );       \
+    (b)[(i) + 1] = (unsigned char) ( (n) >>  8 );       \
+    (b)[(i) + 2] = (unsigned char) ( (n) >> 16 );       \
+    (b)[(i) + 3] = (unsigned char) ( (n) >> 24 );       \
+}
+#endif
+
+#if defined(POLARSSL_PADLOCK_C) &&                      \
+    ( defined(POLARSSL_HAVE_X86) || defined(PADLOCK_ALIGN16) )
+static int aes_padlock_ace = -1;
+#endif
+
+#if defined(POLARSSL_AES_ROM_TABLES)
+/*
+ * Forward S-box
+ */
+static const unsigned char FSb[256] =
+{
+    0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,
+    0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
+    0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
+    0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
+    0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC,
+    0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
+    0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A,
+    0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
+    0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,
+    0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
+    0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B,
+    0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
+    0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85,
+    0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
+    0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
+    0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
+    0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17,
+    0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
+    0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88,
+    0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
+    0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,
+    0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
+    0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9,
+    0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
+    0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6,
+    0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
+    0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
+    0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
+    0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94,
+    0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
+    0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68,
+    0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
+};
+
+/*
+ * Forward tables
+ */
+#define FT \
+\
+    V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \
+    V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \
+    V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \
+    V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \
+    V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \
+    V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \
+    V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \
+    V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \
+    V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \
+    V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \
+    V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \
+    V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \
+    V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \
+    V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \
+    V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \
+    V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \
+    V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \
+    V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \
+    V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \
+    V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \
+    V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \
+    V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \
+    V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \
+    V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \
+    V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \
+    V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \
+    V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \
+    V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \
+    V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \
+    V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \
+    V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \
+    V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \
+    V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \
+    V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \
+    V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \
+    V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \
+    V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \
+    V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \
+    V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \
+    V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \
+    V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \
+    V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \
+    V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \
+    V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \
+    V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \
+    V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \
+    V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \
+    V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \
+    V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \
+    V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \
+    V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \
+    V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \
+    V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \
+    V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \
+    V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \
+    V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \
+    V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \
+    V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \
+    V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \
+    V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \
+    V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \
+    V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \
+    V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \
+    V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C)
+
+#define V(a,b,c,d) 0x##a##b##c##d
+static const uint32_t FT0[256] = { FT };
+#undef V
+
+#define V(a,b,c,d) 0x##b##c##d##a
+static const uint32_t FT1[256] = { FT };
+#undef V
+
+#define V(a,b,c,d) 0x##c##d##a##b
+static const uint32_t FT2[256] = { FT };
+#undef V
+
+#define V(a,b,c,d) 0x##d##a##b##c
+static const uint32_t FT3[256] = { FT };
+#undef V
+
+#undef FT
+
+/*
+ * Reverse S-box
+ */
+static const unsigned char RSb[256] =
+{
+    0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38,
+    0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
+    0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,
+    0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
+    0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D,
+    0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
+    0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2,
+    0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
+    0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,
+    0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
+    0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA,
+    0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
+    0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A,
+    0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
+    0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,
+    0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
+    0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA,
+    0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
+    0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85,
+    0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
+    0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,
+    0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
+    0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20,
+    0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
+    0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31,
+    0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
+    0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,
+    0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
+    0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0,
+    0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
+    0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26,
+    0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
+};
+
+/*
+ * Reverse tables
+ */
+#define RT \
+\
+    V(50,A7,F4,51), V(53,65,41,7E), V(C3,A4,17,1A), V(96,5E,27,3A), \
+    V(CB,6B,AB,3B), V(F1,45,9D,1F), V(AB,58,FA,AC), V(93,03,E3,4B), \
+    V(55,FA,30,20), V(F6,6D,76,AD), V(91,76,CC,88), V(25,4C,02,F5), \
+    V(FC,D7,E5,4F), V(D7,CB,2A,C5), V(80,44,35,26), V(8F,A3,62,B5), \
+    V(49,5A,B1,DE), V(67,1B,BA,25), V(98,0E,EA,45), V(E1,C0,FE,5D), \
+    V(02,75,2F,C3), V(12,F0,4C,81), V(A3,97,46,8D), V(C6,F9,D3,6B), \
+    V(E7,5F,8F,03), V(95,9C,92,15), V(EB,7A,6D,BF), V(DA,59,52,95), \
+    V(2D,83,BE,D4), V(D3,21,74,58), V(29,69,E0,49), V(44,C8,C9,8E), \
+    V(6A,89,C2,75), V(78,79,8E,F4), V(6B,3E,58,99), V(DD,71,B9,27), \
+    V(B6,4F,E1,BE), V(17,AD,88,F0), V(66,AC,20,C9), V(B4,3A,CE,7D), \
+    V(18,4A,DF,63), V(82,31,1A,E5), V(60,33,51,97), V(45,7F,53,62), \
+    V(E0,77,64,B1), V(84,AE,6B,BB), V(1C,A0,81,FE), V(94,2B,08,F9), \
+    V(58,68,48,70), V(19,FD,45,8F), V(87,6C,DE,94), V(B7,F8,7B,52), \
+    V(23,D3,73,AB), V(E2,02,4B,72), V(57,8F,1F,E3), V(2A,AB,55,66), \
+    V(07,28,EB,B2), V(03,C2,B5,2F), V(9A,7B,C5,86), V(A5,08,37,D3), \
+    V(F2,87,28,30), V(B2,A5,BF,23), V(BA,6A,03,02), V(5C,82,16,ED), \
+    V(2B,1C,CF,8A), V(92,B4,79,A7), V(F0,F2,07,F3), V(A1,E2,69,4E), \
+    V(CD,F4,DA,65), V(D5,BE,05,06), V(1F,62,34,D1), V(8A,FE,A6,C4), \
+    V(9D,53,2E,34), V(A0,55,F3,A2), V(32,E1,8A,05), V(75,EB,F6,A4), \
+    V(39,EC,83,0B), V(AA,EF,60,40), V(06,9F,71,5E), V(51,10,6E,BD), \
+    V(F9,8A,21,3E), V(3D,06,DD,96), V(AE,05,3E,DD), V(46,BD,E6,4D), \
+    V(B5,8D,54,91), V(05,5D,C4,71), V(6F,D4,06,04), V(FF,15,50,60), \
+    V(24,FB,98,19), V(97,E9,BD,D6), V(CC,43,40,89), V(77,9E,D9,67), \
+    V(BD,42,E8,B0), V(88,8B,89,07), V(38,5B,19,E7), V(DB,EE,C8,79), \
+    V(47,0A,7C,A1), V(E9,0F,42,7C), V(C9,1E,84,F8), V(00,00,00,00), \
+    V(83,86,80,09), V(48,ED,2B,32), V(AC,70,11,1E), V(4E,72,5A,6C), \
+    V(FB,FF,0E,FD), V(56,38,85,0F), V(1E,D5,AE,3D), V(27,39,2D,36), \
+    V(64,D9,0F,0A), V(21,A6,5C,68), V(D1,54,5B,9B), V(3A,2E,36,24), \
+    V(B1,67,0A,0C), V(0F,E7,57,93), V(D2,96,EE,B4), V(9E,91,9B,1B), \
+    V(4F,C5,C0,80), V(A2,20,DC,61), V(69,4B,77,5A), V(16,1A,12,1C), \
+    V(0A,BA,93,E2), V(E5,2A,A0,C0), V(43,E0,22,3C), V(1D,17,1B,12), \
+    V(0B,0D,09,0E), V(AD,C7,8B,F2), V(B9,A8,B6,2D), V(C8,A9,1E,14), \
+    V(85,19,F1,57), V(4C,07,75,AF), V(BB,DD,99,EE), V(FD,60,7F,A3), \
+    V(9F,26,01,F7), V(BC,F5,72,5C), V(C5,3B,66,44), V(34,7E,FB,5B), \
+    V(76,29,43,8B), V(DC,C6,23,CB), V(68,FC,ED,B6), V(63,F1,E4,B8), \
+    V(CA,DC,31,D7), V(10,85,63,42), V(40,22,97,13), V(20,11,C6,84), \
+    V(7D,24,4A,85), V(F8,3D,BB,D2), V(11,32,F9,AE), V(6D,A1,29,C7), \
+    V(4B,2F,9E,1D), V(F3,30,B2,DC), V(EC,52,86,0D), V(D0,E3,C1,77), \
+    V(6C,16,B3,2B), V(99,B9,70,A9), V(FA,48,94,11), V(22,64,E9,47), \
+    V(C4,8C,FC,A8), V(1A,3F,F0,A0), V(D8,2C,7D,56), V(EF,90,33,22), \
+    V(C7,4E,49,87), V(C1,D1,38,D9), V(FE,A2,CA,8C), V(36,0B,D4,98), \
+    V(CF,81,F5,A6), V(28,DE,7A,A5), V(26,8E,B7,DA), V(A4,BF,AD,3F), \
+    V(E4,9D,3A,2C), V(0D,92,78,50), V(9B,CC,5F,6A), V(62,46,7E,54), \
+    V(C2,13,8D,F6), V(E8,B8,D8,90), V(5E,F7,39,2E), V(F5,AF,C3,82), \
+    V(BE,80,5D,9F), V(7C,93,D0,69), V(A9,2D,D5,6F), V(B3,12,25,CF), \
+    V(3B,99,AC,C8), V(A7,7D,18,10), V(6E,63,9C,E8), V(7B,BB,3B,DB), \
+    V(09,78,26,CD), V(F4,18,59,6E), V(01,B7,9A,EC), V(A8,9A,4F,83), \
+    V(65,6E,95,E6), V(7E,E6,FF,AA), V(08,CF,BC,21), V(E6,E8,15,EF), \
+    V(D9,9B,E7,BA), V(CE,36,6F,4A), V(D4,09,9F,EA), V(D6,7C,B0,29), \
+    V(AF,B2,A4,31), V(31,23,3F,2A), V(30,94,A5,C6), V(C0,66,A2,35), \
+    V(37,BC,4E,74), V(A6,CA,82,FC), V(B0,D0,90,E0), V(15,D8,A7,33), \
+    V(4A,98,04,F1), V(F7,DA,EC,41), V(0E,50,CD,7F), V(2F,F6,91,17), \
+    V(8D,D6,4D,76), V(4D,B0,EF,43), V(54,4D,AA,CC), V(DF,04,96,E4), \
+    V(E3,B5,D1,9E), V(1B,88,6A,4C), V(B8,1F,2C,C1), V(7F,51,65,46), \
+    V(04,EA,5E,9D), V(5D,35,8C,01), V(73,74,87,FA), V(2E,41,0B,FB), \
+    V(5A,1D,67,B3), V(52,D2,DB,92), V(33,56,10,E9), V(13,47,D6,6D), \
+    V(8C,61,D7,9A), V(7A,0C,A1,37), V(8E,14,F8,59), V(89,3C,13,EB), \
+    V(EE,27,A9,CE), V(35,C9,61,B7), V(ED,E5,1C,E1), V(3C,B1,47,7A), \
+    V(59,DF,D2,9C), V(3F,73,F2,55), V(79,CE,14,18), V(BF,37,C7,73), \
+    V(EA,CD,F7,53), V(5B,AA,FD,5F), V(14,6F,3D,DF), V(86,DB,44,78), \
+    V(81,F3,AF,CA), V(3E,C4,68,B9), V(2C,34,24,38), V(5F,40,A3,C2), \
+    V(72,C3,1D,16), V(0C,25,E2,BC), V(8B,49,3C,28), V(41,95,0D,FF), \
+    V(71,01,A8,39), V(DE,B3,0C,08), V(9C,E4,B4,D8), V(90,C1,56,64), \
+    V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0)
+
+#define V(a,b,c,d) 0x##a##b##c##d
+static const uint32_t RT0[256] = { RT };
+#undef V
+
+#define V(a,b,c,d) 0x##b##c##d##a
+static const uint32_t RT1[256] = { RT };
+#undef V
+
+#define V(a,b,c,d) 0x##c##d##a##b
+static const uint32_t RT2[256] = { RT };
+#undef V
+
+#define V(a,b,c,d) 0x##d##a##b##c
+static const uint32_t RT3[256] = { RT };
+#undef V
+
+#undef RT
+
+/*
+ * Round constants
+ */
+static const uint32_t RCON[10] =
+{
+    0x00000001, 0x00000002, 0x00000004, 0x00000008,
+    0x00000010, 0x00000020, 0x00000040, 0x00000080,
+    0x0000001B, 0x00000036
+};
+
+#else /* POLARSSL_AES_ROM_TABLES */
+
+/*
+ * Forward S-box & tables
+ */
+static unsigned char FSb[256];
+static uint32_t FT0[256];
+static uint32_t FT1[256];
+static uint32_t FT2[256];
+static uint32_t FT3[256];
+
+/*
+ * Reverse S-box & tables
+ */
+static unsigned char RSb[256];
+static uint32_t RT0[256];
+static uint32_t RT1[256];
+static uint32_t RT2[256];
+static uint32_t RT3[256];
+
+/*
+ * Round constants
+ */
+static uint32_t RCON[10];
+
+/*
+ * Tables generation code
+ */
+#define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 )
+#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) )
+#define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 )
+
+static int aes_init_done = 0;
+
+static void aes_gen_tables( void )
+{
+    int i, x, y, z;
+    int pow[256];
+    int log[256];
+
+    /*
+     * compute pow and log tables over GF(2^8)
+     */
+    for( i = 0, x = 1; i < 256; i++ )
+    {
+        pow[i] = x;
+        log[x] = i;
+        x = ( x ^ XTIME( x ) ) & 0xFF;
+    }
+
+    /*
+     * calculate the round constants
+     */
+    for( i = 0, x = 1; i < 10; i++ )
+    {
+        RCON[i] = (uint32_t) x;
+        x = XTIME( x ) & 0xFF;
+    }
+
+    /*
+     * generate the forward and reverse S-boxes
+     */
+    FSb[0x00] = 0x63;
+    RSb[0x63] = 0x00;
+
+    for( i = 1; i < 256; i++ )
+    {
+        x = pow[255 - log[i]];
+
+        y  = x; y = ( (y << 1) | (y >> 7) ) & 0xFF;
+        x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF;
+        x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF;
+        x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF;
+        x ^= y ^ 0x63;
+
+        FSb[i] = (unsigned char) x;
+        RSb[x] = (unsigned char) i;
+    }
+
+    /*
+     * generate the forward and reverse tables
+     */
+    for( i = 0; i < 256; i++ )
+    {
+        x = FSb[i];
+        y = XTIME( x ) & 0xFF;
+        z =  ( y ^ x ) & 0xFF;
+
+        FT0[i] = ( (uint32_t) y       ) ^
+                 ( (uint32_t) x <<  8 ) ^
+                 ( (uint32_t) x << 16 ) ^
+                 ( (uint32_t) z << 24 );
+
+        FT1[i] = ROTL8( FT0[i] );
+        FT2[i] = ROTL8( FT1[i] );
+        FT3[i] = ROTL8( FT2[i] );
+
+        x = RSb[i];
+
+        RT0[i] = ( (uint32_t) MUL( 0x0E, x )       ) ^
+                 ( (uint32_t) MUL( 0x09, x ) <<  8 ) ^
+                 ( (uint32_t) MUL( 0x0D, x ) << 16 ) ^
+                 ( (uint32_t) MUL( 0x0B, x ) << 24 );
+
+        RT1[i] = ROTL8( RT0[i] );
+        RT2[i] = ROTL8( RT1[i] );
+        RT3[i] = ROTL8( RT2[i] );
+    }
+}
+
+#endif /* POLARSSL_AES_ROM_TABLES */
+
+/*
+ * AES key schedule (encryption)
+ */
+int aes_setkey_enc( aes_context *ctx, const unsigned char *key,
+                    unsigned int keysize )
+{
+    unsigned int i;
+    uint32_t *RK;
+
+#if !defined(POLARSSL_AES_ROM_TABLES)
+    if( aes_init_done == 0 )
+    {
+        aes_gen_tables();
+        aes_init_done = 1;
+
+    }
+#endif
+
+    switch( keysize )
+    {
+        case 128: ctx->nr = 10; break;
+        case 192: ctx->nr = 12; break;
+        case 256: ctx->nr = 14; break;
+        default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH );
+    }
+
+#if defined(POLARSSL_PADLOCK_C) && defined(PADLOCK_ALIGN16)
+    if( aes_padlock_ace == -1 )
+        aes_padlock_ace = padlock_supports( PADLOCK_ACE );
+
+    if( aes_padlock_ace )
+        ctx->rk = RK = PADLOCK_ALIGN16( ctx->buf );
+    else
+#endif
+    ctx->rk = RK = ctx->buf;
+
+#if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64)
+    if( aesni_supports( POLARSSL_AESNI_AES ) )
+        return( aesni_setkey_enc( (unsigned char *) ctx->rk, key, keysize ) );
+#endif
+
+    for( i = 0; i < (keysize >> 5); i++ )
+    {
+        GET_UINT32_LE( RK[i], key, i << 2 );
+    }
+
+    switch( ctx->nr )
+    {
+        case 10:
+
+            for( i = 0; i < 10; i++, RK += 4 )
+            {
+                RK[4]  = RK[0] ^ RCON[i] ^
+                ( (uint32_t) FSb[ ( RK[3] >>  8 ) & 0xFF ]       ) ^
+                ( (uint32_t) FSb[ ( RK[3] >> 16 ) & 0xFF ] <<  8 ) ^
+                ( (uint32_t) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^
+                ( (uint32_t) FSb[ ( RK[3]       ) & 0xFF ] << 24 );
+
+                RK[5]  = RK[1] ^ RK[4];
+                RK[6]  = RK[2] ^ RK[5];
+                RK[7]  = RK[3] ^ RK[6];
+            }
+            break;
+
+        case 12:
+
+            for( i = 0; i < 8; i++, RK += 6 )
+            {
+                RK[6]  = RK[0] ^ RCON[i] ^
+                ( (uint32_t) FSb[ ( RK[5] >>  8 ) & 0xFF ]       ) ^
+                ( (uint32_t) FSb[ ( RK[5] >> 16 ) & 0xFF ] <<  8 ) ^
+                ( (uint32_t) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^
+                ( (uint32_t) FSb[ ( RK[5]       ) & 0xFF ] << 24 );
+
+                RK[7]  = RK[1] ^ RK[6];
+                RK[8]  = RK[2] ^ RK[7];
+                RK[9]  = RK[3] ^ RK[8];
+                RK[10] = RK[4] ^ RK[9];
+                RK[11] = RK[5] ^ RK[10];
+            }
+            break;
+
+        case 14:
+
+            for( i = 0; i < 7; i++, RK += 8 )
+            {
+                RK[8]  = RK[0] ^ RCON[i] ^
+                ( (uint32_t) FSb[ ( RK[7] >>  8 ) & 0xFF ]       ) ^
+                ( (uint32_t) FSb[ ( RK[7] >> 16 ) & 0xFF ] <<  8 ) ^
+                ( (uint32_t) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^
+                ( (uint32_t) FSb[ ( RK[7]       ) & 0xFF ] << 24 );
+
+                RK[9]  = RK[1] ^ RK[8];
+                RK[10] = RK[2] ^ RK[9];
+                RK[11] = RK[3] ^ RK[10];
+
+                RK[12] = RK[4] ^
+                ( (uint32_t) FSb[ ( RK[11]       ) & 0xFF ]       ) ^
+                ( (uint32_t) FSb[ ( RK[11] >>  8 ) & 0xFF ] <<  8 ) ^
+                ( (uint32_t) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^
+                ( (uint32_t) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 );
+
+                RK[13] = RK[5] ^ RK[12];
+                RK[14] = RK[6] ^ RK[13];
+                RK[15] = RK[7] ^ RK[14];
+            }
+            break;
+
+        default:
+
+            break;
+    }
+
+    return( 0 );
+}
+
+/*
+ * AES key schedule (decryption)
+ */
+int aes_setkey_dec( aes_context *ctx, const unsigned char *key,
+                    unsigned int keysize )
+{
+    int i, j;
+    aes_context cty;
+    uint32_t *RK;
+    uint32_t *SK;
+    int ret;
+
+    switch( keysize )
+    {
+        case 128: ctx->nr = 10; break;
+        case 192: ctx->nr = 12; break;
+        case 256: ctx->nr = 14; break;
+        default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH );
+    }
+
+#if defined(POLARSSL_PADLOCK_C) && defined(PADLOCK_ALIGN16)
+    if( aes_padlock_ace == -1 )
+        aes_padlock_ace = padlock_supports( PADLOCK_ACE );
+
+    if( aes_padlock_ace )
+        ctx->rk = RK = PADLOCK_ALIGN16( ctx->buf );
+    else
+#endif
+    ctx->rk = RK = ctx->buf;
+
+    ret = aes_setkey_enc( &cty, key, keysize );
+    if( ret != 0 )
+        return( ret );
+
+#if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64)
+    if( aesni_supports( POLARSSL_AESNI_AES ) )
+    {
+        aesni_inverse_key( (unsigned char *) ctx->rk,
+                           (const unsigned char *) cty.rk, ctx->nr );
+        goto done;
+    }
+#endif
+
+    SK = cty.rk + cty.nr * 4;
+
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+
+    for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 )
+    {
+        for( j = 0; j < 4; j++, SK++ )
+        {
+            *RK++ = RT0[ FSb[ ( *SK       ) & 0xFF ] ] ^
+                    RT1[ FSb[ ( *SK >>  8 ) & 0xFF ] ] ^
+                    RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^
+                    RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ];
+        }
+    }
+
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+
+#if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64)
+done:
+#endif
+    memset( &cty, 0, sizeof( aes_context ) );
+
+    return( 0 );
+}
+
+#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3)     \
+{                                               \
+    X0 = *RK++ ^ FT0[ ( Y0       ) & 0xFF ] ^   \
+                 FT1[ ( Y1 >>  8 ) & 0xFF ] ^   \
+                 FT2[ ( Y2 >> 16 ) & 0xFF ] ^   \
+                 FT3[ ( Y3 >> 24 ) & 0xFF ];    \
+                                                \
+    X1 = *RK++ ^ FT0[ ( Y1       ) & 0xFF ] ^   \
+                 FT1[ ( Y2 >>  8 ) & 0xFF ] ^   \
+                 FT2[ ( Y3 >> 16 ) & 0xFF ] ^   \
+                 FT3[ ( Y0 >> 24 ) & 0xFF ];    \
+                                                \
+    X2 = *RK++ ^ FT0[ ( Y2       ) & 0xFF ] ^   \
+                 FT1[ ( Y3 >>  8 ) & 0xFF ] ^   \
+                 FT2[ ( Y0 >> 16 ) & 0xFF ] ^   \
+                 FT3[ ( Y1 >> 24 ) & 0xFF ];    \
+                                                \
+    X3 = *RK++ ^ FT0[ ( Y3       ) & 0xFF ] ^   \
+                 FT1[ ( Y0 >>  8 ) & 0xFF ] ^   \
+                 FT2[ ( Y1 >> 16 ) & 0xFF ] ^   \
+                 FT3[ ( Y2 >> 24 ) & 0xFF ];    \
+}
+
+#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3)     \
+{                                               \
+    X0 = *RK++ ^ RT0[ ( Y0       ) & 0xFF ] ^   \
+                 RT1[ ( Y3 >>  8 ) & 0xFF ] ^   \
+                 RT2[ ( Y2 >> 16 ) & 0xFF ] ^   \
+                 RT3[ ( Y1 >> 24 ) & 0xFF ];    \
+                                                \
+    X1 = *RK++ ^ RT0[ ( Y1       ) & 0xFF ] ^   \
+                 RT1[ ( Y0 >>  8 ) & 0xFF ] ^   \
+                 RT2[ ( Y3 >> 16 ) & 0xFF ] ^   \
+                 RT3[ ( Y2 >> 24 ) & 0xFF ];    \
+                                                \
+    X2 = *RK++ ^ RT0[ ( Y2       ) & 0xFF ] ^   \
+                 RT1[ ( Y1 >>  8 ) & 0xFF ] ^   \
+                 RT2[ ( Y0 >> 16 ) & 0xFF ] ^   \
+                 RT3[ ( Y3 >> 24 ) & 0xFF ];    \
+                                                \
+    X3 = *RK++ ^ RT0[ ( Y3       ) & 0xFF ] ^   \
+                 RT1[ ( Y2 >>  8 ) & 0xFF ] ^   \
+                 RT2[ ( Y1 >> 16 ) & 0xFF ] ^   \
+                 RT3[ ( Y0 >> 24 ) & 0xFF ];    \
+}
+
+/*
+ * AES-ECB block encryption/decryption
+ */
+int aes_crypt_ecb( aes_context *ctx,
+                    int mode,
+                    const unsigned char input[16],
+                    unsigned char output[16] )
+{
+    int i;
+    uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;
+
+#if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64)
+    if( aesni_supports( POLARSSL_AESNI_AES ) )
+        return( aesni_crypt_ecb( ctx, mode, input, output ) );
+#endif
+
+#if defined(POLARSSL_PADLOCK_C) && defined(POLARSSL_HAVE_X86)
+    if( aes_padlock_ace )
+    {
+        if( padlock_xcryptecb( ctx, mode, input, output ) == 0 )
+            return( 0 );
+
+        // If padlock data misaligned, we just fall back to
+        // unaccelerated mode
+        //
+    }
+#endif
+
+    RK = ctx->rk;
+
+    GET_UINT32_LE( X0, input,  0 ); X0 ^= *RK++;
+    GET_UINT32_LE( X1, input,  4 ); X1 ^= *RK++;
+    GET_UINT32_LE( X2, input,  8 ); X2 ^= *RK++;
+    GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++;
+
+    if( mode == AES_DECRYPT )
+    {
+        for( i = (ctx->nr >> 1) - 1; i > 0; i-- )
+        {
+            AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+            AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
+        }
+
+        AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+
+        X0 = *RK++ ^ \
+                ( (uint32_t) RSb[ ( Y0       ) & 0xFF ]       ) ^
+                ( (uint32_t) RSb[ ( Y3 >>  8 ) & 0xFF ] <<  8 ) ^
+                ( (uint32_t) RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
+                ( (uint32_t) RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
+
+        X1 = *RK++ ^ \
+                ( (uint32_t) RSb[ ( Y1       ) & 0xFF ]       ) ^
+                ( (uint32_t) RSb[ ( Y0 >>  8 ) & 0xFF ] <<  8 ) ^
+                ( (uint32_t) RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
+                ( (uint32_t) RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
+
+        X2 = *RK++ ^ \
+                ( (uint32_t) RSb[ ( Y2       ) & 0xFF ]       ) ^
+                ( (uint32_t) RSb[ ( Y1 >>  8 ) & 0xFF ] <<  8 ) ^
+                ( (uint32_t) RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
+                ( (uint32_t) RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
+
+        X3 = *RK++ ^ \
+                ( (uint32_t) RSb[ ( Y3       ) & 0xFF ]       ) ^
+                ( (uint32_t) RSb[ ( Y2 >>  8 ) & 0xFF ] <<  8 ) ^
+                ( (uint32_t) RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
+                ( (uint32_t) RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
+    }
+    else /* AES_ENCRYPT */
+    {
+        for( i = (ctx->nr >> 1) - 1; i > 0; i-- )
+        {
+            AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+            AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
+        }
+
+        AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+
+        X0 = *RK++ ^ \
+                ( (uint32_t) FSb[ ( Y0       ) & 0xFF ]       ) ^
+                ( (uint32_t) FSb[ ( Y1 >>  8 ) & 0xFF ] <<  8 ) ^
+                ( (uint32_t) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
+                ( (uint32_t) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
+
+        X1 = *RK++ ^ \
+                ( (uint32_t) FSb[ ( Y1       ) & 0xFF ]       ) ^
+                ( (uint32_t) FSb[ ( Y2 >>  8 ) & 0xFF ] <<  8 ) ^
+                ( (uint32_t) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
+                ( (uint32_t) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
+
+        X2 = *RK++ ^ \
+                ( (uint32_t) FSb[ ( Y2       ) & 0xFF ]       ) ^
+                ( (uint32_t) FSb[ ( Y3 >>  8 ) & 0xFF ] <<  8 ) ^
+                ( (uint32_t) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
+                ( (uint32_t) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
+
+        X3 = *RK++ ^ \
+                ( (uint32_t) FSb[ ( Y3       ) & 0xFF ]       ) ^
+                ( (uint32_t) FSb[ ( Y0 >>  8 ) & 0xFF ] <<  8 ) ^
+                ( (uint32_t) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
+                ( (uint32_t) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
+    }
+
+    PUT_UINT32_LE( X0, output,  0 );
+    PUT_UINT32_LE( X1, output,  4 );
+    PUT_UINT32_LE( X2, output,  8 );
+    PUT_UINT32_LE( X3, output, 12 );
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+/*
+ * AES-CBC buffer encryption/decryption
+ */
+int aes_crypt_cbc( aes_context *ctx,
+                    int mode,
+                    size_t length,
+                    unsigned char iv[16],
+                    const unsigned char *input,
+                    unsigned char *output )
+{
+    int i;
+    unsigned char temp[16];
+
+    if( length % 16 )
+        return( POLARSSL_ERR_AES_INVALID_INPUT_LENGTH );
+
+#if defined(POLARSSL_PADLOCK_C) && defined(POLARSSL_HAVE_X86)
+    if( aes_padlock_ace )
+    {
+        if( padlock_xcryptcbc( ctx, mode, length, iv, input, output ) == 0 )
+            return( 0 );
+
+        // If padlock data misaligned, we just fall back to
+        // unaccelerated mode
+        //
+    }
+#endif
+
+    if( mode == AES_DECRYPT )
+    {
+        while( length > 0 )
+        {
+            memcpy( temp, input, 16 );
+            aes_crypt_ecb( ctx, mode, input, output );
+
+            for( i = 0; i < 16; i++ )
+                output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+            memcpy( iv, temp, 16 );
+
+            input  += 16;
+            output += 16;
+            length -= 16;
+        }
+    }
+    else
+    {
+        while( length > 0 )
+        {
+            for( i = 0; i < 16; i++ )
+                output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+            aes_crypt_ecb( ctx, mode, output, output );
+            memcpy( iv, output, 16 );
+
+            input  += 16;
+            output += 16;
+            length -= 16;
+        }
+    }
+
+    return( 0 );
+}
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+/*
+ * AES-CFB128 buffer encryption/decryption
+ */
+int aes_crypt_cfb128( aes_context *ctx,
+                       int mode,
+                       size_t length,
+                       size_t *iv_off,
+                       unsigned char iv[16],
+                       const unsigned char *input,
+                       unsigned char *output )
+{
+    int c;
+    size_t n = *iv_off;
+
+    if( mode == AES_DECRYPT )
+    {
+        while( length-- )
+        {
+            if( n == 0 )
+                aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv );
+
+            c = *input++;
+            *output++ = (unsigned char)( c ^ iv[n] );
+            iv[n] = (unsigned char) c;
+
+            n = (n + 1) & 0x0F;
+        }
+    }
+    else
+    {
+        while( length-- )
+        {
+            if( n == 0 )
+                aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv );
+
+            iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
+
+            n = (n + 1) & 0x0F;
+        }
+    }
+
+    *iv_off = n;
+
+    return( 0 );
+}
+
+/*
+ * AES-CFB8 buffer encryption/decryption
+ */
+#include <stdio.h>
+int aes_crypt_cfb8( aes_context *ctx,
+                       int mode,
+                       size_t length,
+                       unsigned char iv[16],
+                       const unsigned char *input,
+                       unsigned char *output )
+{
+    unsigned char c;
+    unsigned char ov[17];
+
+    while( length-- )
+    {
+        memcpy(ov, iv, 16);
+        aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv );
+
+        if( mode == AES_DECRYPT )
+            ov[16] = *input;
+
+        c = *output++ = (unsigned char)( iv[0] ^ *input++ );
+
+        if( mode == AES_ENCRYPT )
+            ov[16] = c;
+
+        memcpy(iv, ov + 1, 16);
+    }
+
+    return( 0 );
+}
+#endif /*POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+/*
+ * AES-CTR buffer encryption/decryption
+ */
+int aes_crypt_ctr( 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 )
+{
+    int c, i;
+    size_t n = *nc_off;
+
+    while( length-- )
+    {
+        if( n == 0 ) {
+            aes_crypt_ecb( ctx, AES_ENCRYPT, nonce_counter, stream_block );
+
+            for( i = 16; i > 0; i-- )
+                if( ++nonce_counter[i - 1] != 0 )
+                    break;
+        }
+        c = *input++;
+        *output++ = (unsigned char)( c ^ stream_block[n] );
+
+        n = (n + 1) & 0x0F;
+    }
+
+    *nc_off = n;
+
+    return( 0 );
+}
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+#endif /* !POLARSSL_AES_ALT */
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include <stdio.h>
+
+/*
+ * AES test vectors from:
+ *
+ * http://csrc.nist.gov/archive/aes/rijndael/rijndael-vals.zip
+ */
+static const unsigned char aes_test_ecb_dec[3][16] =
+{
+    { 0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, 0x58,
+      0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, 0xEB, 0xE0 },
+    { 0x48, 0xE3, 0x1E, 0x9E, 0x25, 0x67, 0x18, 0xF2,
+      0x92, 0x29, 0x31, 0x9C, 0x19, 0xF1, 0x5B, 0xA4 },
+    { 0x05, 0x8C, 0xCF, 0xFD, 0xBB, 0xCB, 0x38, 0x2D,
+      0x1F, 0x6F, 0x56, 0x58, 0x5D, 0x8A, 0x4A, 0xDE }
+};
+
+static const unsigned char aes_test_ecb_enc[3][16] =
+{
+    { 0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, 0x73,
+      0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, 0x29, 0x7F },
+    { 0xF3, 0xF6, 0x75, 0x2A, 0xE8, 0xD7, 0x83, 0x11,
+      0x38, 0xF0, 0x41, 0x56, 0x06, 0x31, 0xB1, 0x14 },
+    { 0x8B, 0x79, 0xEE, 0xCC, 0x93, 0xA0, 0xEE, 0x5D,
+      0xFF, 0x30, 0xB4, 0xEA, 0x21, 0x63, 0x6D, 0xA4 }
+};
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+static const unsigned char aes_test_cbc_dec[3][16] =
+{
+    { 0xFA, 0xCA, 0x37, 0xE0, 0xB0, 0xC8, 0x53, 0x73,
+      0xDF, 0x70, 0x6E, 0x73, 0xF7, 0xC9, 0xAF, 0x86 },
+    { 0x5D, 0xF6, 0x78, 0xDD, 0x17, 0xBA, 0x4E, 0x75,
+      0xB6, 0x17, 0x68, 0xC6, 0xAD, 0xEF, 0x7C, 0x7B },
+    { 0x48, 0x04, 0xE1, 0x81, 0x8F, 0xE6, 0x29, 0x75,
+      0x19, 0xA3, 0xE8, 0x8C, 0x57, 0x31, 0x04, 0x13 }
+};
+
+static const unsigned char aes_test_cbc_enc[3][16] =
+{
+    { 0x8A, 0x05, 0xFC, 0x5E, 0x09, 0x5A, 0xF4, 0x84,
+      0x8A, 0x08, 0xD3, 0x28, 0xD3, 0x68, 0x8E, 0x3D },
+    { 0x7B, 0xD9, 0x66, 0xD5, 0x3A, 0xD8, 0xC1, 0xBB,
+      0x85, 0xD2, 0xAD, 0xFA, 0xE8, 0x7B, 0xB1, 0x04 },
+    { 0xFE, 0x3C, 0x53, 0x65, 0x3E, 0x2F, 0x45, 0xB5,
+      0x6F, 0xCD, 0x88, 0xB2, 0xCC, 0x89, 0x8F, 0xF0 }
+};
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+/*
+ * AES-CFB128 test vectors from:
+ *
+ * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+ */
+static const unsigned char aes_test_cfb128_key[3][32] =
+{
+    { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+      0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C },
+    { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52,
+      0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5,
+      0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B },
+    { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE,
+      0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,
+      0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,
+      0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 }
+};
+
+static const unsigned char aes_test_cfb128_iv[16] =
+{
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+    0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+};
+
+static const unsigned char aes_test_cfb128_pt[64] =
+{
+    0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,
+    0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A,
+    0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,
+    0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51,
+    0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11,
+    0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF,
+    0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17,
+    0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10
+};
+
+static const unsigned char aes_test_cfb128_ct[3][64] =
+{
+    { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20,
+      0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A,
+      0xC8, 0xA6, 0x45, 0x37, 0xA0, 0xB3, 0xA9, 0x3F,
+      0xCD, 0xE3, 0xCD, 0xAD, 0x9F, 0x1C, 0xE5, 0x8B,
+      0x26, 0x75, 0x1F, 0x67, 0xA3, 0xCB, 0xB1, 0x40,
+      0xB1, 0x80, 0x8C, 0xF1, 0x87, 0xA4, 0xF4, 0xDF,
+      0xC0, 0x4B, 0x05, 0x35, 0x7C, 0x5D, 0x1C, 0x0E,
+      0xEA, 0xC4, 0xC6, 0x6F, 0x9F, 0xF7, 0xF2, 0xE6 },
+    { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB,
+      0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74,
+      0x67, 0xCE, 0x7F, 0x7F, 0x81, 0x17, 0x36, 0x21,
+      0x96, 0x1A, 0x2B, 0x70, 0x17, 0x1D, 0x3D, 0x7A,
+      0x2E, 0x1E, 0x8A, 0x1D, 0xD5, 0x9B, 0x88, 0xB1,
+      0xC8, 0xE6, 0x0F, 0xED, 0x1E, 0xFA, 0xC4, 0xC9,
+      0xC0, 0x5F, 0x9F, 0x9C, 0xA9, 0x83, 0x4F, 0xA0,
+      0x42, 0xAE, 0x8F, 0xBA, 0x58, 0x4B, 0x09, 0xFF },
+    { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B,
+      0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60,
+      0x39, 0xFF, 0xED, 0x14, 0x3B, 0x28, 0xB1, 0xC8,
+      0x32, 0x11, 0x3C, 0x63, 0x31, 0xE5, 0x40, 0x7B,
+      0xDF, 0x10, 0x13, 0x24, 0x15, 0xE5, 0x4B, 0x92,
+      0xA1, 0x3E, 0xD0, 0xA8, 0x26, 0x7A, 0xE2, 0xF9,
+      0x75, 0xA3, 0x85, 0x74, 0x1A, 0xB9, 0xCE, 0xF8,
+      0x20, 0x31, 0x62, 0x3D, 0x55, 0xB1, 0xE4, 0x71 }
+};
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+/*
+ * AES-CTR test vectors from:
+ *
+ * http://www.faqs.org/rfcs/rfc3686.html
+ */
+
+static const unsigned char aes_test_ctr_key[3][16] =
+{
+    { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC,
+      0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E },
+    { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7,
+      0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 },
+    { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8,
+      0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC }
+};
+
+static const unsigned char aes_test_ctr_nonce_counter[3][16] =
+{
+    { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+    { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59,
+      0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 },
+    { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F,
+      0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 }
+};
+
+static const unsigned char aes_test_ctr_pt[3][48] =
+{
+    { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62,
+      0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 },
+
+    { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+      0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+      0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F },
+
+    { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+      0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+      0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+      0x20, 0x21, 0x22, 0x23 }
+};
+
+static const unsigned char aes_test_ctr_ct[3][48] =
+{
+    { 0xE4, 0x09, 0x5D, 0x4F, 0xB7, 0xA7, 0xB3, 0x79,
+      0x2D, 0x61, 0x75, 0xA3, 0x26, 0x13, 0x11, 0xB8 },
+    { 0x51, 0x04, 0xA1, 0x06, 0x16, 0x8A, 0x72, 0xD9,
+      0x79, 0x0D, 0x41, 0xEE, 0x8E, 0xDA, 0xD3, 0x88,
+      0xEB, 0x2E, 0x1E, 0xFC, 0x46, 0xDA, 0x57, 0xC8,
+      0xFC, 0xE6, 0x30, 0xDF, 0x91, 0x41, 0xBE, 0x28 },
+    { 0xC1, 0xCF, 0x48, 0xA8, 0x9F, 0x2F, 0xFD, 0xD9,
+      0xCF, 0x46, 0x52, 0xE9, 0xEF, 0xDB, 0x72, 0xD7,
+      0x45, 0x40, 0xA4, 0x2B, 0xDE, 0x6D, 0x78, 0x36,
+      0xD5, 0x9A, 0x5C, 0xEA, 0xAE, 0xF3, 0x10, 0x53,
+      0x25, 0xB2, 0x07, 0x2F }
+};
+
+static const int aes_test_ctr_len[3] =
+    { 16, 32, 36 };
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+/*
+ * Checkup routine
+ */
+int aes_self_test( int verbose )
+{
+    int i, j, u, v;
+    unsigned char key[32];
+    unsigned char buf[64];
+    unsigned char iv[16];
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    unsigned char prv[16];
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CTR) || defined(POLARSSL_CIPHER_MODE_CFB)
+    size_t offset;
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+    int len;
+    unsigned char nonce_counter[16];
+    unsigned char stream_block[16];
+#endif
+    aes_context ctx;
+
+    memset( key, 0, 32 );
+
+    /*
+     * ECB mode
+     */
+    for( i = 0; i < 6; i++ )
+    {
+        u = i >> 1;
+        v = i  & 1;
+
+        if( verbose != 0 )
+            polarssl_printf( "  AES-ECB-%3d (%s): ", 128 + u * 64,
+                             ( v == AES_DECRYPT ) ? "dec" : "enc" );
+
+        memset( buf, 0, 16 );
+
+        if( v == AES_DECRYPT )
+        {
+            aes_setkey_dec( &ctx, key, 128 + u * 64 );
+
+            for( j = 0; j < 10000; j++ )
+                aes_crypt_ecb( &ctx, v, buf, buf );
+
+            if( memcmp( buf, aes_test_ecb_dec[u], 16 ) != 0 )
+            {
+                if( verbose != 0 )
+                    polarssl_printf( "failed\n" );
+
+                return( 1 );
+            }
+        }
+        else
+        {
+            aes_setkey_enc( &ctx, key, 128 + u * 64 );
+
+            for( j = 0; j < 10000; j++ )
+                aes_crypt_ecb( &ctx, v, buf, buf );
+
+            if( memcmp( buf, aes_test_ecb_enc[u], 16 ) != 0 )
+            {
+                if( verbose != 0 )
+                    polarssl_printf( "failed\n" );
+
+                return( 1 );
+            }
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    /*
+     * CBC mode
+     */
+    for( i = 0; i < 6; i++ )
+    {
+        u = i >> 1;
+        v = i  & 1;
+
+        if( verbose != 0 )
+            polarssl_printf( "  AES-CBC-%3d (%s): ", 128 + u * 64,
+                             ( v == AES_DECRYPT ) ? "dec" : "enc" );
+
+        memset( iv , 0, 16 );
+        memset( prv, 0, 16 );
+        memset( buf, 0, 16 );
+
+        if( v == AES_DECRYPT )
+        {
+            aes_setkey_dec( &ctx, key, 128 + u * 64 );
+
+            for( j = 0; j < 10000; j++ )
+                aes_crypt_cbc( &ctx, v, 16, iv, buf, buf );
+
+            if( memcmp( buf, aes_test_cbc_dec[u], 16 ) != 0 )
+            {
+                if( verbose != 0 )
+                    polarssl_printf( "failed\n" );
+
+                return( 1 );
+            }
+        }
+        else
+        {
+            aes_setkey_enc( &ctx, key, 128 + u * 64 );
+
+            for( j = 0; j < 10000; j++ )
+            {
+                unsigned char tmp[16];
+
+                aes_crypt_cbc( &ctx, v, 16, iv, buf, buf );
+
+                memcpy( tmp, prv, 16 );
+                memcpy( prv, buf, 16 );
+                memcpy( buf, tmp, 16 );
+            }
+
+            if( memcmp( prv, aes_test_cbc_enc[u], 16 ) != 0 )
+            {
+                if( verbose != 0 )
+                    polarssl_printf( "failed\n" );
+
+                return( 1 );
+            }
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+    /*
+     * CFB128 mode
+     */
+    for( i = 0; i < 6; i++ )
+    {
+        u = i >> 1;
+        v = i  & 1;
+
+        if( verbose != 0 )
+            polarssl_printf( "  AES-CFB128-%3d (%s): ", 128 + u * 64,
+                             ( v == AES_DECRYPT ) ? "dec" : "enc" );
+
+        memcpy( iv,  aes_test_cfb128_iv, 16 );
+        memcpy( key, aes_test_cfb128_key[u], 16 + u * 8 );
+
+        offset = 0;
+        aes_setkey_enc( &ctx, key, 128 + u * 64 );
+
+        if( v == AES_DECRYPT )
+        {
+            memcpy( buf, aes_test_cfb128_ct[u], 64 );
+            aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf );
+
+            if( memcmp( buf, aes_test_cfb128_pt, 64 ) != 0 )
+            {
+                if( verbose != 0 )
+                    polarssl_printf( "failed\n" );
+
+                return( 1 );
+            }
+        }
+        else
+        {
+            memcpy( buf, aes_test_cfb128_pt, 64 );
+            aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf );
+
+            if( memcmp( buf, aes_test_cfb128_ct[u], 64 ) != 0 )
+            {
+                if( verbose != 0 )
+                    polarssl_printf( "failed\n" );
+
+                return( 1 );
+            }
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+    /*
+     * CTR mode
+     */
+    for( i = 0; i < 6; i++ )
+    {
+        u = i >> 1;
+        v = i  & 1;
+
+        if( verbose != 0 )
+            polarssl_printf( "  AES-CTR-128 (%s): ",
+                             ( v == AES_DECRYPT ) ? "dec" : "enc" );
+
+        memcpy( nonce_counter, aes_test_ctr_nonce_counter[u], 16 );
+        memcpy( key, aes_test_ctr_key[u], 16 );
+
+        offset = 0;
+        aes_setkey_enc( &ctx, key, 128 );
+
+        if( v == AES_DECRYPT )
+        {
+            len = aes_test_ctr_len[u];
+            memcpy( buf, aes_test_ctr_ct[u], len );
+
+            aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block,
+                           buf, buf );
+
+            if( memcmp( buf, aes_test_ctr_pt[u], len ) != 0 )
+            {
+                if( verbose != 0 )
+                    polarssl_printf( "failed\n" );
+
+                return( 1 );
+            }
+        }
+        else
+        {
+            len = aes_test_ctr_len[u];
+            memcpy( buf, aes_test_ctr_pt[u], len );
+
+            aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block,
+                           buf, buf );
+
+            if( memcmp( buf, aes_test_ctr_ct[u], len ) != 0 )
+            {
+                if( verbose != 0 )
+                    polarssl_printf( "failed\n" );
+
+                return( 1 );
+            }
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+    return( 0 );
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_AES_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/aesni.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,465 @@
+/*
+ *  AES-NI support functions
+ *
+ *  Copyright (C) 2013, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*
+ * [AES-WP] http://software.intel.com/en-us/articles/intel-advanced-encryption-standard-aes-instructions-set
+ * [CLMUL-WP] http://software.intel.com/en-us/articles/intel-carry-less-multiplication-instruction-and-its-usage-for-computing-the-gcm-mode/
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_AESNI_C)
+
+#include "polarssl/aesni.h"
+#include <stdio.h>
+
+#if defined(POLARSSL_HAVE_X86_64)
+
+/*
+ * AES-NI support detection routine
+ */
+int aesni_supports( unsigned int what )
+{
+    static int done = 0;
+    static unsigned int c = 0;
+
+    if( ! done )
+    {
+        asm( "movl  $1, %%eax   \n"
+             "cpuid             \n"
+             : "=c" (c)
+             :
+             : "eax", "ebx", "edx" );
+        done = 1;
+    }
+
+    return( ( c & what ) != 0 );
+}
+
+/*
+ * Binutils needs to be at least 2.19 to support AES-NI instructions.
+ * Unfortunately, a lot of users have a lower version now (2014-04).
+ * Emit bytecode directly in order to support "old" version of gas.
+ *
+ * Opcodes from the Intel architecture reference manual, vol. 3.
+ * We always use registers, so we don't need prefixes for memory operands.
+ * Operand macros are in gas order (src, dst) as opposed to Intel order
+ * (dst, src) in order to blend better into the surrounding assembly code.
+ */
+#define AESDEC      ".byte 0x66,0x0F,0x38,0xDE,"
+#define AESDECLAST  ".byte 0x66,0x0F,0x38,0xDF,"
+#define AESENC      ".byte 0x66,0x0F,0x38,0xDC,"
+#define AESENCLAST  ".byte 0x66,0x0F,0x38,0xDD,"
+#define AESIMC      ".byte 0x66,0x0F,0x38,0xDB,"
+#define AESKEYGENA  ".byte 0x66,0x0F,0x3A,0xDF,"
+#define PCLMULQDQ   ".byte 0x66,0x0F,0x3A,0x44,"
+
+#define xmm0_xmm0   "0xC0"
+#define xmm0_xmm1   "0xC8"
+#define xmm0_xmm2   "0xD0"
+#define xmm0_xmm3   "0xD8"
+#define xmm0_xmm4   "0xE0"
+#define xmm1_xmm0   "0xC1"
+#define xmm1_xmm2   "0xD1"
+
+/*
+ * AES-NI AES-ECB block en(de)cryption
+ */
+int aesni_crypt_ecb( aes_context *ctx,
+                     int mode,
+                     const unsigned char input[16],
+                     unsigned char output[16] )
+{
+    asm( "movdqu    (%3), %%xmm0    \n" // load input
+         "movdqu    (%1), %%xmm1    \n" // load round key 0
+         "pxor      %%xmm1, %%xmm0  \n" // round 0
+         "addq      $16, %1         \n" // point to next round key
+         "subl      $1, %0          \n" // normal rounds = nr - 1
+         "test      %2, %2          \n" // mode?
+         "jz        2f              \n" // 0 = decrypt
+
+         "1:                        \n" // encryption loop
+         "movdqu    (%1), %%xmm1    \n" // load round key
+         AESENC     xmm1_xmm0      "\n" // do round
+         "addq      $16, %1         \n" // point to next round key
+         "subl      $1, %0          \n" // loop
+         "jnz       1b              \n"
+         "movdqu    (%1), %%xmm1    \n" // load round key
+         AESENCLAST xmm1_xmm0      "\n" // last round
+         "jmp       3f              \n"
+
+         "2:                        \n" // decryption loop
+         "movdqu    (%1), %%xmm1    \n"
+         AESDEC     xmm1_xmm0      "\n" // do round
+         "addq      $16, %1         \n"
+         "subl      $1, %0          \n"
+         "jnz       2b              \n"
+         "movdqu    (%1), %%xmm1    \n" // load round key
+         AESDECLAST xmm1_xmm0      "\n" // last round
+
+         "3:                        \n"
+         "movdqu    %%xmm0, (%4)    \n" // export output
+         :
+         : "r" (ctx->nr), "r" (ctx->rk), "r" (mode), "r" (input), "r" (output)
+         : "memory", "cc", "xmm0", "xmm1" );
+
+
+    return( 0 );
+}
+
+/*
+ * GCM multiplication: c = a times b in GF(2^128)
+ * Based on [CLMUL-WP] algorithms 1 (with equation 27) and 5.
+ */
+void aesni_gcm_mult( unsigned char c[16],
+                     const unsigned char a[16],
+                     const unsigned char b[16] )
+{
+    unsigned char aa[16], bb[16], cc[16];
+    size_t i;
+
+    /* The inputs are in big-endian order, so byte-reverse them */
+    for( i = 0; i < 16; i++ )
+    {
+        aa[i] = a[15 - i];
+        bb[i] = b[15 - i];
+    }
+
+    asm( "movdqu (%0), %%xmm0               \n" // a1:a0
+         "movdqu (%1), %%xmm1               \n" // b1:b0
+
+         /*
+          * Caryless multiplication xmm2:xmm1 = xmm0 * xmm1
+          * using [CLMUL-WP] algorithm 1 (p. 13).
+          */
+         "movdqa %%xmm1, %%xmm2             \n" // copy of b1:b0
+         "movdqa %%xmm1, %%xmm3             \n" // same
+         "movdqa %%xmm1, %%xmm4             \n" // same
+         PCLMULQDQ xmm0_xmm1 ",0x00         \n" // a0*b0 = c1:c0
+         PCLMULQDQ xmm0_xmm2 ",0x11         \n" // a1*b1 = d1:d0
+         PCLMULQDQ xmm0_xmm3 ",0x10         \n" // a0*b1 = e1:e0
+         PCLMULQDQ xmm0_xmm4 ",0x01         \n" // a1*b0 = f1:f0
+         "pxor %%xmm3, %%xmm4               \n" // e1+f1:e0+f0
+         "movdqa %%xmm4, %%xmm3             \n" // same
+         "psrldq $8, %%xmm4                 \n" // 0:e1+f1
+         "pslldq $8, %%xmm3                 \n" // e0+f0:0
+         "pxor %%xmm4, %%xmm2               \n" // d1:d0+e1+f1
+         "pxor %%xmm3, %%xmm1               \n" // c1+e0+f1:c0
+
+         /*
+          * Now shift the result one bit to the left,
+          * taking advantage of [CLMUL-WP] eq 27 (p. 20)
+          */
+         "movdqa %%xmm1, %%xmm3             \n" // r1:r0
+         "movdqa %%xmm2, %%xmm4             \n" // r3:r2
+         "psllq $1, %%xmm1                  \n" // r1<<1:r0<<1
+         "psllq $1, %%xmm2                  \n" // r3<<1:r2<<1
+         "psrlq $63, %%xmm3                 \n" // r1>>63:r0>>63
+         "psrlq $63, %%xmm4                 \n" // r3>>63:r2>>63
+         "movdqa %%xmm3, %%xmm5             \n" // r1>>63:r0>>63
+         "pslldq $8, %%xmm3                 \n" // r0>>63:0
+         "pslldq $8, %%xmm4                 \n" // r2>>63:0
+         "psrldq $8, %%xmm5                 \n" // 0:r1>>63
+         "por %%xmm3, %%xmm1                \n" // r1<<1|r0>>63:r0<<1
+         "por %%xmm4, %%xmm2                \n" // r3<<1|r2>>62:r2<<1
+         "por %%xmm5, %%xmm2                \n" // r3<<1|r2>>62:r2<<1|r1>>63
+
+         /*
+          * Now reduce modulo the GCM polynomial x^128 + x^7 + x^2 + x + 1
+          * using [CLMUL-WP] algorithm 5 (p. 20).
+          * Currently xmm2:xmm1 holds x3:x2:x1:x0 (already shifted).
+          */
+         /* Step 2 (1) */
+         "movdqa %%xmm1, %%xmm3             \n" // x1:x0
+         "movdqa %%xmm1, %%xmm4             \n" // same
+         "movdqa %%xmm1, %%xmm5             \n" // same
+         "psllq $63, %%xmm3                 \n" // x1<<63:x0<<63 = stuff:a
+         "psllq $62, %%xmm4                 \n" // x1<<62:x0<<62 = stuff:b
+         "psllq $57, %%xmm5                 \n" // x1<<57:x0<<57 = stuff:c
+
+         /* Step 2 (2) */
+         "pxor %%xmm4, %%xmm3               \n" // stuff:a+b
+         "pxor %%xmm5, %%xmm3               \n" // stuff:a+b+c
+         "pslldq $8, %%xmm3                 \n" // a+b+c:0
+         "pxor %%xmm3, %%xmm1               \n" // x1+a+b+c:x0 = d:x0
+
+         /* Steps 3 and 4 */
+         "movdqa %%xmm1,%%xmm0              \n" // d:x0
+         "movdqa %%xmm1,%%xmm4              \n" // same
+         "movdqa %%xmm1,%%xmm5              \n" // same
+         "psrlq $1, %%xmm0                  \n" // e1:x0>>1 = e1:e0'
+         "psrlq $2, %%xmm4                  \n" // f1:x0>>2 = f1:f0'
+         "psrlq $7, %%xmm5                  \n" // g1:x0>>7 = g1:g0'
+         "pxor %%xmm4, %%xmm0               \n" // e1+f1:e0'+f0'
+         "pxor %%xmm5, %%xmm0               \n" // e1+f1+g1:e0'+f0'+g0'
+         // e0'+f0'+g0' is almost e0+f0+g0, except for some missing
+         // bits carried from d. Now get those bits back in.
+         "movdqa %%xmm1,%%xmm3              \n" // d:x0
+         "movdqa %%xmm1,%%xmm4              \n" // same
+         "movdqa %%xmm1,%%xmm5              \n" // same
+         "psllq $63, %%xmm3                 \n" // d<<63:stuff
+         "psllq $62, %%xmm4                 \n" // d<<62:stuff
+         "psllq $57, %%xmm5                 \n" // d<<57:stuff
+         "pxor %%xmm4, %%xmm3               \n" // d<<63+d<<62:stuff
+         "pxor %%xmm5, %%xmm3               \n" // missing bits of d:stuff
+         "psrldq $8, %%xmm3                 \n" // 0:missing bits of d
+         "pxor %%xmm3, %%xmm0               \n" // e1+f1+g1:e0+f0+g0
+         "pxor %%xmm1, %%xmm0               \n" // h1:h0
+         "pxor %%xmm2, %%xmm0               \n" // x3+h1:x2+h0
+
+         "movdqu %%xmm0, (%2)               \n" // done
+         :
+         : "r" (aa), "r" (bb), "r" (cc)
+         : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" );
+
+    /* Now byte-reverse the outputs */
+    for( i = 0; i < 16; i++ )
+        c[i] = cc[15 - i];
+
+    return;
+}
+
+/*
+ * Compute decryption round keys from encryption round keys
+ */
+void aesni_inverse_key( unsigned char *invkey,
+                        const unsigned char *fwdkey, int nr )
+{
+    unsigned char *ik = invkey;
+    const unsigned char *fk = fwdkey + 16 * nr;
+
+    memcpy( ik, fk, 16 );
+
+    for( fk -= 16, ik += 16; fk > fwdkey; fk -= 16, ik += 16 )
+        asm( "movdqu (%0), %%xmm0       \n"
+             AESIMC  xmm0_xmm0         "\n"
+             "movdqu %%xmm0, (%1)       \n"
+             :
+             : "r" (fk), "r" (ik)
+             : "memory", "xmm0" );
+
+    memcpy( ik, fk, 16 );
+}
+
+/*
+ * Key expansion, 128-bit case
+ */
+static void aesni_setkey_enc_128( unsigned char *rk,
+                                  const unsigned char *key )
+{
+    asm( "movdqu (%1), %%xmm0               \n" // copy the original key
+         "movdqu %%xmm0, (%0)               \n" // as round key 0
+         "jmp 2f                            \n" // skip auxiliary routine
+
+         /*
+          * Finish generating the next round key.
+          *
+          * On entry xmm0 is r3:r2:r1:r0 and xmm1 is X:stuff:stuff:stuff
+          * with X = rot( sub( r3 ) ) ^ RCON.
+          *
+          * On exit, xmm0 is r7:r6:r5:r4
+          * with r4 = X + r0, r5 = r4 + r1, r6 = r5 + r2, r7 = r6 + r3
+          * and those are written to the round key buffer.
+          */
+         "1:                                \n"
+         "pshufd $0xff, %%xmm1, %%xmm1      \n" // X:X:X:X
+         "pxor %%xmm0, %%xmm1               \n" // X+r3:X+r2:X+r1:r4
+         "pslldq $4, %%xmm0                 \n" // r2:r1:r0:0
+         "pxor %%xmm0, %%xmm1               \n" // X+r3+r2:X+r2+r1:r5:r4
+         "pslldq $4, %%xmm0                 \n" // etc
+         "pxor %%xmm0, %%xmm1               \n"
+         "pslldq $4, %%xmm0                 \n"
+         "pxor %%xmm1, %%xmm0               \n" // update xmm0 for next time!
+         "add $16, %0                       \n" // point to next round key
+         "movdqu %%xmm0, (%0)               \n" // write it
+         "ret                               \n"
+
+         /* Main "loop" */
+         "2:                                \n"
+         AESKEYGENA xmm0_xmm1 ",0x01        \ncall 1b   \n"
+         AESKEYGENA xmm0_xmm1 ",0x02        \ncall 1b   \n"
+         AESKEYGENA xmm0_xmm1 ",0x04        \ncall 1b   \n"
+         AESKEYGENA xmm0_xmm1 ",0x08        \ncall 1b   \n"
+         AESKEYGENA xmm0_xmm1 ",0x10        \ncall 1b   \n"
+         AESKEYGENA xmm0_xmm1 ",0x20        \ncall 1b   \n"
+         AESKEYGENA xmm0_xmm1 ",0x40        \ncall 1b   \n"
+         AESKEYGENA xmm0_xmm1 ",0x80        \ncall 1b   \n"
+         AESKEYGENA xmm0_xmm1 ",0x1B        \ncall 1b   \n"
+         AESKEYGENA xmm0_xmm1 ",0x36        \ncall 1b   \n"
+         :
+         : "r" (rk), "r" (key)
+         : "memory", "cc", "0" );
+}
+
+/*
+ * Key expansion, 192-bit case
+ */
+static void aesni_setkey_enc_192( unsigned char *rk,
+                                  const unsigned char *key )
+{
+    asm( "movdqu (%1), %%xmm0   \n" // copy original round key
+         "movdqu %%xmm0, (%0)   \n"
+         "add $16, %0           \n"
+         "movq 16(%1), %%xmm1   \n"
+         "movq %%xmm1, (%0)     \n"
+         "add $8, %0            \n"
+         "jmp 2f                \n" // skip auxiliary routine
+
+         /*
+          * Finish generating the next 6 quarter-keys.
+          *
+          * On entry xmm0 is r3:r2:r1:r0, xmm1 is stuff:stuff:r5:r4
+          * and xmm2 is stuff:stuff:X:stuff with X = rot( sub( r3 ) ) ^ RCON.
+          *
+          * On exit, xmm0 is r9:r8:r7:r6 and xmm1 is stuff:stuff:r11:r10
+          * and those are written to the round key buffer.
+          */
+         "1:                            \n"
+         "pshufd $0x55, %%xmm2, %%xmm2  \n" // X:X:X:X
+         "pxor %%xmm0, %%xmm2           \n" // X+r3:X+r2:X+r1:r4
+         "pslldq $4, %%xmm0             \n" // etc
+         "pxor %%xmm0, %%xmm2           \n"
+         "pslldq $4, %%xmm0             \n"
+         "pxor %%xmm0, %%xmm2           \n"
+         "pslldq $4, %%xmm0             \n"
+         "pxor %%xmm2, %%xmm0           \n" // update xmm0 = r9:r8:r7:r6
+         "movdqu %%xmm0, (%0)           \n"
+         "add $16, %0                   \n"
+         "pshufd $0xff, %%xmm0, %%xmm2  \n" // r9:r9:r9:r9
+         "pxor %%xmm1, %%xmm2           \n" // stuff:stuff:r9+r5:r10
+         "pslldq $4, %%xmm1             \n" // r2:r1:r0:0
+         "pxor %%xmm2, %%xmm1           \n" // update xmm1 = stuff:stuff:r11:r10
+         "movq %%xmm1, (%0)             \n"
+         "add $8, %0                    \n"
+         "ret                           \n"
+
+         "2:                            \n"
+         AESKEYGENA xmm1_xmm2 ",0x01    \ncall 1b   \n"
+         AESKEYGENA xmm1_xmm2 ",0x02    \ncall 1b   \n"
+         AESKEYGENA xmm1_xmm2 ",0x04    \ncall 1b   \n"
+         AESKEYGENA xmm1_xmm2 ",0x08    \ncall 1b   \n"
+         AESKEYGENA xmm1_xmm2 ",0x10    \ncall 1b   \n"
+         AESKEYGENA xmm1_xmm2 ",0x20    \ncall 1b   \n"
+         AESKEYGENA xmm1_xmm2 ",0x40    \ncall 1b   \n"
+         AESKEYGENA xmm1_xmm2 ",0x80    \ncall 1b   \n"
+
+         :
+         : "r" (rk), "r" (key)
+         : "memory", "cc", "0" );
+}
+
+/*
+ * Key expansion, 256-bit case
+ */
+static void aesni_setkey_enc_256( unsigned char *rk,
+                                  const unsigned char *key )
+{
+    asm( "movdqu (%1), %%xmm0           \n"
+         "movdqu %%xmm0, (%0)           \n"
+         "add $16, %0                   \n"
+         "movdqu 16(%1), %%xmm1         \n"
+         "movdqu %%xmm1, (%0)           \n"
+         "jmp 2f                        \n" // skip auxiliary routine
+
+         /*
+          * Finish generating the next two round keys.
+          *
+          * On entry xmm0 is r3:r2:r1:r0, xmm1 is r7:r6:r5:r4 and
+          * xmm2 is X:stuff:stuff:stuff with X = rot( sub( r7 )) ^ RCON
+          *
+          * On exit, xmm0 is r11:r10:r9:r8 and xmm1 is r15:r14:r13:r12
+          * and those have been written to the output buffer.
+          */
+         "1:                                \n"
+         "pshufd $0xff, %%xmm2, %%xmm2      \n"
+         "pxor %%xmm0, %%xmm2               \n"
+         "pslldq $4, %%xmm0                 \n"
+         "pxor %%xmm0, %%xmm2               \n"
+         "pslldq $4, %%xmm0                 \n"
+         "pxor %%xmm0, %%xmm2               \n"
+         "pslldq $4, %%xmm0                 \n"
+         "pxor %%xmm2, %%xmm0               \n"
+         "add $16, %0                       \n"
+         "movdqu %%xmm0, (%0)               \n"
+
+         /* Set xmm2 to stuff:Y:stuff:stuff with Y = subword( r11 )
+          * and proceed to generate next round key from there */
+         AESKEYGENA xmm0_xmm2 ",0x00        \n"
+         "pshufd $0xaa, %%xmm2, %%xmm2      \n"
+         "pxor %%xmm1, %%xmm2               \n"
+         "pslldq $4, %%xmm1                 \n"
+         "pxor %%xmm1, %%xmm2               \n"
+         "pslldq $4, %%xmm1                 \n"
+         "pxor %%xmm1, %%xmm2               \n"
+         "pslldq $4, %%xmm1                 \n"
+         "pxor %%xmm2, %%xmm1               \n"
+         "add $16, %0                       \n"
+         "movdqu %%xmm1, (%0)               \n"
+         "ret                               \n"
+
+         /*
+          * Main "loop" - Generating one more key than necessary,
+          * see definition of aes_context.buf
+          */
+         "2:                                \n"
+         AESKEYGENA xmm1_xmm2 ",0x01        \ncall 1b   \n"
+         AESKEYGENA xmm1_xmm2 ",0x02        \ncall 1b   \n"
+         AESKEYGENA xmm1_xmm2 ",0x04        \ncall 1b   \n"
+         AESKEYGENA xmm1_xmm2 ",0x08        \ncall 1b   \n"
+         AESKEYGENA xmm1_xmm2 ",0x10        \ncall 1b   \n"
+         AESKEYGENA xmm1_xmm2 ",0x20        \ncall 1b   \n"
+         AESKEYGENA xmm1_xmm2 ",0x40        \ncall 1b   \n"
+         :
+         : "r" (rk), "r" (key)
+         : "memory", "cc", "0" );
+}
+
+/*
+ * Key expansion, wrapper
+ */
+int aesni_setkey_enc( unsigned char *rk,
+                      const unsigned char *key,
+                      size_t bits )
+{
+    switch( bits )
+    {
+        case 128: aesni_setkey_enc_128( rk, key ); break;
+        case 192: aesni_setkey_enc_192( rk, key ); break;
+        case 256: aesni_setkey_enc_256( rk, key ); break;
+        default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH );
+    }
+
+    return( 0 );
+}
+
+#endif /* POLARSSL_HAVE_X86_64 */
+
+#endif /* POLARSSL_AESNI_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/arc4.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,186 @@
+/*
+ *  An implementation of the ARCFOUR algorithm
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  The ARCFOUR algorithm was publicly disclosed on 94/09.
+ *
+ *  http://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_ARC4_C)
+
+#include "polarssl/arc4.h"
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
+#if !defined(POLARSSL_ARC4_ALT)
+
+/*
+ * ARC4 key schedule
+ */
+void arc4_setup( arc4_context *ctx, const unsigned char *key,
+                 unsigned int keylen )
+{
+    int i, j, a;
+    unsigned int k;
+    unsigned char *m;
+
+    ctx->x = 0;
+    ctx->y = 0;
+    m = ctx->m;
+
+    for( i = 0; i < 256; i++ )
+        m[i] = (unsigned char) i;
+
+    j = k = 0;
+
+    for( i = 0; i < 256; i++, k++ )
+    {
+        if( k >= keylen ) k = 0;
+
+        a = m[i];
+        j = ( j + a + key[k] ) & 0xFF;
+        m[i] = m[j];
+        m[j] = (unsigned char) a;
+    }
+}
+
+/*
+ * ARC4 cipher function
+ */
+int arc4_crypt( arc4_context *ctx, size_t length, const unsigned char *input,
+                unsigned char *output )
+{
+    int x, y, a, b;
+    size_t i;
+    unsigned char *m;
+
+    x = ctx->x;
+    y = ctx->y;
+    m = ctx->m;
+
+    for( i = 0; i < length; i++ )
+    {
+        x = ( x + 1 ) & 0xFF; a = m[x];
+        y = ( y + a ) & 0xFF; b = m[y];
+
+        m[x] = (unsigned char) b;
+        m[y] = (unsigned char) a;
+
+        output[i] = (unsigned char)
+            ( input[i] ^ m[(unsigned char)( a + b )] );
+    }
+
+    ctx->x = x;
+    ctx->y = y;
+
+    return( 0 );
+}
+
+#endif /* !POLARSSL_ARC4_ALT */
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include <string.h>
+#include <stdio.h>
+
+/*
+ * ARC4 tests vectors as posted by Eric Rescorla in sep. 1994:
+ *
+ * http://groups.google.com/group/comp.security.misc/msg/10a300c9d21afca0
+ */
+static const unsigned char arc4_test_key[3][8] =
+{
+    { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
+    { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+};
+
+static const unsigned char arc4_test_pt[3][8] =
+{
+    { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+};
+
+static const unsigned char arc4_test_ct[3][8] =
+{
+    { 0x75, 0xB7, 0x87, 0x80, 0x99, 0xE0, 0xC5, 0x96 },
+    { 0x74, 0x94, 0xC2, 0xE7, 0x10, 0x4B, 0x08, 0x79 },
+    { 0xDE, 0x18, 0x89, 0x41, 0xA3, 0x37, 0x5D, 0x3A }
+};
+
+/*
+ * Checkup routine
+ */
+int arc4_self_test( int verbose )
+{
+    int i;
+    unsigned char ibuf[8];
+    unsigned char obuf[8];
+    arc4_context ctx;
+
+    for( i = 0; i < 3; i++ )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "  ARC4 test #%d: ", i + 1 );
+
+        memcpy( ibuf, arc4_test_pt[i], 8 );
+
+        arc4_setup( &ctx, arc4_test_key[i], 8 );
+        arc4_crypt( &ctx, 8, ibuf, obuf );
+
+        if( memcmp( obuf, arc4_test_ct[i], 8 ) != 0 )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+    return( 0 );
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_ARC4_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/asn1parse.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,393 @@
+/*
+ *  Generic ASN.1 parsing
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_ASN1_PARSE_C)
+
+#include "polarssl/asn1.h"
+
+#if defined(POLARSSL_BIGNUM_C)
+#include "polarssl/bignum.h"
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+
+/*
+ * ASN.1 DER decoding routines
+ */
+int asn1_get_len( unsigned char **p,
+                  const unsigned char *end,
+                  size_t *len )
+{
+    if( ( end - *p ) < 1 )
+        return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+    if( ( **p & 0x80 ) == 0 )
+        *len = *(*p)++;
+    else
+    {
+        switch( **p & 0x7F )
+        {
+        case 1:
+            if( ( end - *p ) < 2 )
+                return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+            *len = (*p)[1];
+            (*p) += 2;
+            break;
+
+        case 2:
+            if( ( end - *p ) < 3 )
+                return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+            *len = ( (*p)[1] << 8 ) | (*p)[2];
+            (*p) += 3;
+            break;
+
+        case 3:
+            if( ( end - *p ) < 4 )
+                return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+            *len = ( (*p)[1] << 16 ) | ( (*p)[2] << 8 ) | (*p)[3];
+            (*p) += 4;
+            break;
+
+        case 4:
+            if( ( end - *p ) < 5 )
+                return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+            *len = ( (*p)[1] << 24 ) | ( (*p)[2] << 16 ) | ( (*p)[3] << 8 ) |
+                   (*p)[4];
+            (*p) += 5;
+            break;
+
+        default:
+            return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
+        }
+    }
+
+    if( *len > (size_t) ( end - *p ) )
+        return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+    return( 0 );
+}
+
+int asn1_get_tag( unsigned char **p,
+                  const unsigned char *end,
+                  size_t *len, int tag )
+{
+    if( ( end - *p ) < 1 )
+        return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+    if( **p != tag )
+        return( POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
+
+    (*p)++;
+
+    return( asn1_get_len( p, end, len ) );
+}
+
+int asn1_get_bool( unsigned char **p,
+                   const unsigned char *end,
+                   int *val )
+{
+    int ret;
+    size_t len;
+
+    if( ( ret = asn1_get_tag( p, end, &len, ASN1_BOOLEAN ) ) != 0 )
+        return( ret );
+
+    if( len != 1 )
+        return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
+
+    *val = ( **p != 0 ) ? 1 : 0;
+    (*p)++;
+
+    return( 0 );
+}
+
+int asn1_get_int( unsigned char **p,
+                  const unsigned char *end,
+                  int *val )
+{
+    int ret;
+    size_t len;
+
+    if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
+        return( ret );
+
+    if( len > sizeof( int ) || ( **p & 0x80 ) != 0 )
+        return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
+
+    *val = 0;
+
+    while( len-- > 0 )
+    {
+        *val = ( *val << 8 ) | **p;
+        (*p)++;
+    }
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_BIGNUM_C)
+int asn1_get_mpi( unsigned char **p,
+                  const unsigned char *end,
+                  mpi *X )
+{
+    int ret;
+    size_t len;
+
+    if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
+        return( ret );
+
+    ret = mpi_read_binary( X, *p, len );
+
+    *p += len;
+
+    return( ret );
+}
+#endif /* POLARSSL_BIGNUM_C */
+
+int asn1_get_bitstring( unsigned char **p, const unsigned char *end,
+                        asn1_bitstring *bs)
+{
+    int ret;
+
+    /* Certificate type is a single byte bitstring */
+    if( ( ret = asn1_get_tag( p, end, &bs->len, ASN1_BIT_STRING ) ) != 0 )
+        return( ret );
+
+    /* Check length, subtract one for actual bit string length */
+    if ( bs->len < 1 )
+        return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
+    bs->len -= 1;
+
+    /* Get number of unused bits, ensure unused bits <= 7 */
+    bs->unused_bits = **p;
+    if( bs->unused_bits > 7 )
+        return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
+    (*p)++;
+
+    /* Get actual bitstring */
+    bs->p = *p;
+    *p += bs->len;
+
+    if( *p != end )
+        return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    return 0;
+}
+
+/*
+ * Get a bit string without unused bits
+ */
+int asn1_get_bitstring_null( unsigned char **p, const unsigned char *end,
+                             size_t *len )
+{
+    int ret;
+
+    if( ( ret = asn1_get_tag( p, end, len, ASN1_BIT_STRING ) ) != 0 )
+        return( ret );
+
+    if( (*len)-- < 2 || *(*p)++ != 0 )
+        return( POLARSSL_ERR_ASN1_INVALID_DATA );
+
+    return( 0 );
+}
+
+
+
+/*
+ *  Parses and splits an ASN.1 "SEQUENCE OF <tag>"
+ */
+int asn1_get_sequence_of( unsigned char **p,
+                          const unsigned char *end,
+                          asn1_sequence *cur,
+                          int tag)
+{
+    int ret;
+    size_t len;
+    asn1_buf *buf;
+
+    /* Get main sequence tag */
+    if( ( ret = asn1_get_tag( p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+        return( ret );
+
+    if( *p + len != end )
+        return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    while( *p < end )
+    {
+        buf = &(cur->buf);
+        buf->tag = **p;
+
+        if( ( ret = asn1_get_tag( p, end, &buf->len, tag ) ) != 0 )
+            return( ret );
+
+        buf->p = *p;
+        *p += buf->len;
+
+        /* Allocate and assign next pointer */
+        if (*p < end)
+        {
+            cur->next = (asn1_sequence *) polarssl_malloc(
+                 sizeof( asn1_sequence ) );
+
+            if( cur->next == NULL )
+                return( POLARSSL_ERR_ASN1_MALLOC_FAILED );
+
+            cur = cur->next;
+        }
+    }
+
+    /* Set final sequence entry's next pointer to NULL */
+    cur->next = NULL;
+
+    if( *p != end )
+        return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    return( 0 );
+}
+
+int asn1_get_alg( unsigned char **p,
+                  const unsigned char *end,
+                  asn1_buf *alg, asn1_buf *params )
+{
+    int ret;
+    size_t len;
+
+    if( ( ret = asn1_get_tag( p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+        return( ret );
+
+    if( ( end - *p ) < 1 )
+        return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+    alg->tag = **p;
+    end = *p + len;
+
+    if( ( ret = asn1_get_tag( p, end, &alg->len, ASN1_OID ) ) != 0 )
+        return( ret );
+
+    alg->p = *p;
+    *p += alg->len;
+
+    if( *p == end )
+    {
+        memset( params, 0, sizeof(asn1_buf) );
+        return( 0 );
+    }
+
+    params->tag = **p;
+    (*p)++;
+
+    if( ( ret = asn1_get_len( p, end, &params->len ) ) != 0 )
+        return( ret );
+
+    params->p = *p;
+    *p += params->len;
+
+    if( *p != end )
+        return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    return( 0 );
+}
+
+int asn1_get_alg_null( unsigned char **p,
+                       const unsigned char *end,
+                       asn1_buf *alg )
+{
+    int ret;
+    asn1_buf params;
+
+    memset( &params, 0, sizeof(asn1_buf) );
+
+    if( ( ret = asn1_get_alg( p, end, alg, &params ) ) != 0 )
+        return( ret );
+
+    if( ( params.tag != ASN1_NULL && params.tag != 0 ) || params.len != 0 )
+        return( POLARSSL_ERR_ASN1_INVALID_DATA );
+
+    return( 0 );
+}
+
+void asn1_free_named_data( asn1_named_data *cur )
+{
+    if( cur == NULL )
+        return;
+
+    polarssl_free( cur->oid.p );
+    polarssl_free( cur->val.p );
+
+    memset( cur, 0, sizeof( asn1_named_data ) );
+}
+
+void asn1_free_named_data_list( asn1_named_data **head )
+{
+    asn1_named_data *cur;
+
+    while( ( cur = *head ) != NULL )
+    {
+        *head = cur->next;
+        asn1_free_named_data( cur );
+        polarssl_free( cur );
+    }
+}
+
+asn1_named_data *asn1_find_named_data( asn1_named_data *list,
+                                       const char *oid, size_t len )
+{
+    while( list != NULL )
+    {
+        if( list->oid.len == len &&
+            memcmp( list->oid.p, oid, len ) == 0 )
+        {
+            break;
+        }
+
+        list = list->next;
+    }
+
+    return( list );
+}
+
+#endif /* POLARSSL_ASN1_PARSE_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/asn1write.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,368 @@
+/*
+ * ASN.1 buffer writing functionality
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_ASN1_WRITE_C)
+
+#include "polarssl/asn1write.h"
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdlib.h>
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+int asn1_write_len( unsigned char **p, unsigned char *start, size_t len )
+{
+    if( len < 0x80 )
+    {
+        if( *p - start < 1 )
+            return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+        *--(*p) = (unsigned char) len;
+        return( 1 );
+    }
+
+    if( len <= 0xFF )
+    {
+        if( *p - start < 2 )
+            return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+        *--(*p) = (unsigned char) len;
+        *--(*p) = 0x81;
+        return( 2 );
+    }
+
+    if( *p - start < 3 )
+        return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+    // We assume we never have lengths larger than 65535 bytes
+    //
+    *--(*p) = len % 256;
+    *--(*p) = ( len / 256 ) % 256;
+    *--(*p) = 0x82;
+
+    return( 3 );
+}
+
+int asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag )
+{
+    if( *p - start < 1 )
+        return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+    *--(*p) = tag;
+
+    return( 1 );
+}
+
+int asn1_write_raw_buffer( unsigned char **p, unsigned char *start,
+                           const unsigned char *buf, size_t size )
+{
+    size_t len = 0;
+
+    if( *p - start < (int) size )
+        return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+    len = size;
+    (*p) -= len;
+    memcpy( *p, buf, len );
+
+    return( (int) len );
+}
+
+#if defined(POLARSSL_BIGNUM_C)
+int asn1_write_mpi( unsigned char **p, unsigned char *start, mpi *X )
+{
+    int ret;
+    size_t len = 0;
+
+    // Write the MPI
+    //
+    len = mpi_size( X );
+
+    if( *p - start < (int) len )
+        return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+    (*p) -= len;
+    MPI_CHK( mpi_write_binary( X, *p, len ) );
+
+    // DER format assumes 2s complement for numbers, so the leftmost bit
+    // should be 0 for positive numbers and 1 for negative numbers.
+    //
+    if ( X->s ==1 && **p & 0x80 )
+    {
+        if( *p - start < 1 )
+            return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+        *--(*p) = 0x00;
+        len += 1;
+    }
+
+    ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_INTEGER ) );
+
+    ret = (int) len;
+
+cleanup:
+    return( ret );
+}
+#endif /* POLARSSL_BIGNUM_C */
+
+int asn1_write_null( unsigned char **p, unsigned char *start )
+{
+    int ret;
+    size_t len = 0;
+
+    // Write NULL
+    //
+    ASN1_CHK_ADD( len, asn1_write_len( p, start, 0) );
+    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_NULL ) );
+
+    return( (int) len );
+}
+
+int asn1_write_oid( unsigned char **p, unsigned char *start,
+                    const char *oid, size_t oid_len )
+{
+    int ret;
+    size_t len = 0;
+
+    ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
+                                  (const unsigned char *) oid, oid_len ) );
+    ASN1_CHK_ADD( len , asn1_write_len( p, start, len ) );
+    ASN1_CHK_ADD( len , asn1_write_tag( p, start, ASN1_OID ) );
+
+    return( (int) len );
+}
+
+int asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start,
+                                     const char *oid, size_t oid_len,
+                                     size_t par_len )
+{
+    int ret;
+    size_t len = 0;
+
+    if( par_len == 0 )
+        ASN1_CHK_ADD( len, asn1_write_null( p, start ) );
+    else
+        len += par_len;
+
+    ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) );
+
+    ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( p, start,
+                                       ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+
+    return( (int) len );
+}
+
+int asn1_write_bool( unsigned char **p, unsigned char *start, int boolean )
+{
+    int ret;
+    size_t len = 0;
+
+    if( *p - start < 1 )
+        return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+    *--(*p) = (boolean) ? 1 : 0;
+    len++;
+
+    ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BOOLEAN ) );
+
+    return( (int) len );
+}
+
+int asn1_write_int( unsigned char **p, unsigned char *start, int val )
+{
+    int ret;
+    size_t len = 0;
+
+    // TODO negative values and values larger than 128
+    // DER format assumes 2s complement for numbers, so the leftmost bit
+    // should be 0 for positive numbers and 1 for negative numbers.
+    //
+    if( *p - start < 1 )
+        return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+    len += 1;
+    *--(*p) = val;
+
+    if ( val > 0 && **p & 0x80 )
+    {
+        if( *p - start < 1 )
+            return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+        *--(*p) = 0x00;
+        len += 1;
+    }
+
+    ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_INTEGER ) );
+
+    return( (int) len );
+}
+
+int asn1_write_printable_string( unsigned char **p, unsigned char *start,
+                                 const char *text, size_t text_len )
+{
+    int ret;
+    size_t len = 0;
+
+    ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
+                  (const unsigned char *) text, text_len ) );
+
+    ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_PRINTABLE_STRING ) );
+
+    return( (int) len );
+}
+
+int asn1_write_ia5_string( unsigned char **p, unsigned char *start,
+                           const char *text, size_t text_len )
+{
+    int ret;
+    size_t len = 0;
+
+    ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
+                  (const unsigned char *) text, text_len ) );
+
+    ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_IA5_STRING ) );
+
+    return( (int) len );
+}
+
+int asn1_write_bitstring( unsigned char **p, unsigned char *start,
+                          const unsigned char *buf, size_t bits )
+{
+    int ret;
+    size_t len = 0, size;
+
+    size = ( bits / 8 ) + ( ( bits % 8 ) ? 1 : 0 );
+
+    // Calculate byte length
+    //
+    if( *p - start < (int) size + 1 )
+        return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+    len = size + 1;
+    (*p) -= size;
+    memcpy( *p, buf, size );
+
+    // Write unused bits
+    //
+    *--(*p) = (unsigned char) (size * 8 - bits);
+
+    ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BIT_STRING ) );
+
+    return( (int) len );
+}
+
+int asn1_write_octet_string( unsigned char **p, unsigned char *start,
+                             const unsigned char *buf, size_t size )
+{
+    int ret;
+    size_t len = 0;
+
+    ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, buf, size ) );
+
+    ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OCTET_STRING ) );
+
+    return( (int) len );
+}
+
+asn1_named_data *asn1_store_named_data( asn1_named_data **head,
+                                        const char *oid, size_t oid_len,
+                                        const unsigned char *val,
+                                        size_t val_len )
+{
+    asn1_named_data *cur;
+
+    if( ( cur = asn1_find_named_data( *head, oid, oid_len ) ) == NULL )
+    {
+        // Add new entry if not present yet based on OID
+        //
+        if( ( cur = polarssl_malloc( sizeof(asn1_named_data) ) ) == NULL )
+            return( NULL );
+
+        memset( cur, 0, sizeof(asn1_named_data) );
+
+        cur->oid.len = oid_len;
+        cur->oid.p = polarssl_malloc( oid_len );
+        if( cur->oid.p == NULL )
+        {
+            polarssl_free( cur );
+            return( NULL );
+        }
+
+        cur->val.len = val_len;
+        cur->val.p = polarssl_malloc( val_len );
+        if( cur->val.p == NULL )
+        {
+            polarssl_free( cur->oid.p );
+            polarssl_free( cur );
+            return( NULL );
+        }
+
+        memcpy( cur->oid.p, oid, oid_len );
+
+        cur->next = *head;
+        *head = cur;
+    }
+    else if( cur->val.len < val_len )
+    {
+        // Enlarge existing value buffer if needed
+        //
+        polarssl_free( cur->val.p );
+        cur->val.p = NULL;
+
+        cur->val.len = val_len;
+        cur->val.p = polarssl_malloc( val_len );
+        if( cur->val.p == NULL )
+        {
+            polarssl_free( cur->oid.p );
+            polarssl_free( cur );
+            return( NULL );
+        }
+    }
+
+    if( val != NULL )
+        memcpy( cur->val.p, val, val_len );
+
+    return( cur );
+}
+#endif /* POLARSSL_ASN1_WRITE_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/base64.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,274 @@
+/*
+ *  RFC 1521 base64 encoding/decoding
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_BASE64_C)
+
+#include "polarssl/base64.h"
+
+#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
+#include <basetsd.h>
+typedef UINT32 uint32_t;
+#else
+#include <inttypes.h>
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
+static const unsigned char base64_enc_map[64] =
+{
+    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
+    'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+    'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
+    'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+    'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
+    'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
+    '8', '9', '+', '/'
+};
+
+static const unsigned char base64_dec_map[128] =
+{
+    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+    127, 127, 127,  62, 127, 127, 127,  63,  52,  53,
+     54,  55,  56,  57,  58,  59,  60,  61, 127, 127,
+    127,  64, 127, 127, 127,   0,   1,   2,   3,   4,
+      5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
+     15,  16,  17,  18,  19,  20,  21,  22,  23,  24,
+     25, 127, 127, 127, 127, 127, 127,  26,  27,  28,
+     29,  30,  31,  32,  33,  34,  35,  36,  37,  38,
+     39,  40,  41,  42,  43,  44,  45,  46,  47,  48,
+     49,  50,  51, 127, 127, 127, 127, 127
+};
+
+/*
+ * Encode a buffer into base64 format
+ */
+int base64_encode( unsigned char *dst, size_t *dlen,
+                   const unsigned char *src, size_t slen )
+{
+    size_t i, n;
+    int C1, C2, C3;
+    unsigned char *p;
+
+    if( slen == 0 )
+        return( 0 );
+
+    n = (slen << 3) / 6;
+
+    switch( (slen << 3) - (n * 6) )
+    {
+        case  2: n += 3; break;
+        case  4: n += 2; break;
+        default: break;
+    }
+
+    if( *dlen < n + 1 )
+    {
+        *dlen = n + 1;
+        return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
+    }
+
+    n = (slen / 3) * 3;
+
+    for( i = 0, p = dst; i < n; i += 3 )
+    {
+        C1 = *src++;
+        C2 = *src++;
+        C3 = *src++;
+
+        *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
+        *p++ = base64_enc_map[(((C1 &  3) << 4) + (C2 >> 4)) & 0x3F];
+        *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
+        *p++ = base64_enc_map[C3 & 0x3F];
+    }
+
+    if( i < slen )
+    {
+        C1 = *src++;
+        C2 = ((i + 1) < slen) ? *src++ : 0;
+
+        *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
+        *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
+
+        if( (i + 1) < slen )
+             *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
+        else *p++ = '=';
+
+        *p++ = '=';
+    }
+
+    *dlen = p - dst;
+    *p = 0;
+
+    return( 0 );
+}
+
+/*
+ * Decode a base64-formatted buffer
+ */
+int base64_decode( unsigned char *dst, size_t *dlen,
+                   const unsigned char *src, size_t slen )
+{
+    size_t i, n;
+    uint32_t j, x;
+    unsigned char *p;
+
+    for( i = n = j = 0; i < slen; i++ )
+    {
+        if( ( slen - i ) >= 2 &&
+            src[i] == '\r' && src[i + 1] == '\n' )
+            continue;
+
+        if( src[i] == '\n' )
+            continue;
+
+        if( src[i] == '=' && ++j > 2 )
+            return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
+
+        if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
+            return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
+
+        if( base64_dec_map[src[i]] < 64 && j != 0 )
+            return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
+
+        n++;
+    }
+
+    if( n == 0 )
+        return( 0 );
+
+    n = ((n * 6) + 7) >> 3;
+
+    if( dst == NULL || *dlen < n )
+    {
+        *dlen = n;
+        return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
+    }
+
+   for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
+   {
+        if( *src == '\r' || *src == '\n' )
+            continue;
+
+        j -= ( base64_dec_map[*src] == 64 );
+        x  = (x << 6) | ( base64_dec_map[*src] & 0x3F );
+
+        if( ++n == 4 )
+        {
+            n = 0;
+            if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
+            if( j > 1 ) *p++ = (unsigned char)( x >>  8 );
+            if( j > 2 ) *p++ = (unsigned char)( x       );
+        }
+    }
+
+    *dlen = p - dst;
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include <string.h>
+#include <stdio.h>
+
+static const unsigned char base64_test_dec[64] =
+{
+    0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
+    0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
+    0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
+    0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
+    0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
+    0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
+    0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
+    0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
+};
+
+static const unsigned char base64_test_enc[] =
+    "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
+    "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
+
+/*
+ * Checkup routine
+ */
+int base64_self_test( int verbose )
+{
+    size_t len;
+    const unsigned char *src;
+    unsigned char buffer[128];
+
+    if( verbose != 0 )
+        polarssl_printf( "  Base64 encoding test: " );
+
+    len = sizeof( buffer );
+    src = base64_test_dec;
+
+    if( base64_encode( buffer, &len, src, 64 ) != 0 ||
+         memcmp( base64_test_enc, buffer, 88 ) != 0 )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "failed\n" );
+
+        return( 1 );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n  Base64 decoding test: " );
+
+    len = sizeof( buffer );
+    src = base64_test_enc;
+
+    if( base64_decode( buffer, &len, src, 88 ) != 0 ||
+         memcmp( base64_test_dec, buffer, 64 ) != 0 )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "failed\n" );
+
+        return( 1 );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n\n" );
+
+    return( 0 );
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_BASE64_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/bignum.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,2341 @@
+/*
+ *  Multi-precision integer library
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  This MPI implementation is based on:
+ *
+ *  http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
+ *  http://www.stillhq.com/extracted/gnupg-api/mpi/
+ *  http://math.libtomcrypt.com/files/tommath.pdf
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_BIGNUM_C)
+
+#include "polarssl/bignum.h"
+#include "polarssl/bn_mul.h"
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf     printf
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+#include <stdlib.h>
+
+#define ciL    (sizeof(t_uint))         /* chars in limb  */
+#define biL    (ciL << 3)               /* bits  in limb  */
+#define biH    (ciL << 2)               /* half limb size */
+
+/*
+ * Convert between bits/chars and number of limbs
+ */
+#define BITS_TO_LIMBS(i)  (((i) + biL - 1) / biL)
+#define CHARS_TO_LIMBS(i) (((i) + ciL - 1) / ciL)
+
+/*
+ * Initialize one MPI
+ */
+void mpi_init( mpi *X )
+{
+    if( X == NULL )
+        return;
+
+    X->s = 1;
+    X->n = 0;
+    X->p = NULL;
+}
+
+/*
+ * Unallocate one MPI
+ */
+void mpi_free( mpi *X )
+{
+    if( X == NULL )
+        return;
+
+    if( X->p != NULL )
+    {
+        memset( X->p, 0, X->n * ciL );
+        polarssl_free( X->p );
+    }
+
+    X->s = 1;
+    X->n = 0;
+    X->p = NULL;
+}
+
+/*
+ * Enlarge to the specified number of limbs
+ */
+int mpi_grow( mpi *X, size_t nblimbs )
+{
+    t_uint *p;
+
+    if( nblimbs > POLARSSL_MPI_MAX_LIMBS )
+        return( POLARSSL_ERR_MPI_MALLOC_FAILED );
+
+    if( X->n < nblimbs )
+    {
+        if( ( p = (t_uint *) polarssl_malloc( nblimbs * ciL ) ) == NULL )
+            return( POLARSSL_ERR_MPI_MALLOC_FAILED );
+
+        memset( p, 0, nblimbs * ciL );
+
+        if( X->p != NULL )
+        {
+            memcpy( p, X->p, X->n * ciL );
+            memset( X->p, 0, X->n * ciL );
+            polarssl_free( X->p );
+        }
+
+        X->n = nblimbs;
+        X->p = p;
+    }
+
+    return( 0 );
+}
+
+/*
+ * Resize down as much as possible,
+ * while keeping at least the specified number of limbs
+ */
+int mpi_shrink( mpi *X, size_t nblimbs )
+{
+    t_uint *p;
+    size_t i;
+
+    /* Actually resize up in this case */
+    if( X->n <= nblimbs )
+        return( mpi_grow( X, nblimbs ) );
+
+    for( i = X->n - 1; i > 0; i-- )
+        if( X->p[i] != 0 )
+            break;
+    i++;
+
+    if( i < nblimbs )
+        i = nblimbs;
+
+    if( ( p = (t_uint *) polarssl_malloc( i * ciL ) ) == NULL )
+        return( POLARSSL_ERR_MPI_MALLOC_FAILED );
+
+    memset( p, 0, i * ciL );
+
+    if( X->p != NULL )
+    {
+        memcpy( p, X->p, i * ciL );
+        memset( X->p, 0, X->n * ciL );
+        polarssl_free( X->p );
+    }
+
+    X->n = i;
+    X->p = p;
+
+    return( 0 );
+}
+
+/*
+ * Copy the contents of Y into X
+ */
+int mpi_copy( mpi *X, const mpi *Y )
+{
+    int ret;
+    size_t i;
+
+    if( X == Y )
+        return( 0 );
+
+    if( Y->p == NULL )
+    {
+        mpi_free( X );
+        return( 0 );
+    }
+
+    for( i = Y->n - 1; i > 0; i-- )
+        if( Y->p[i] != 0 )
+            break;
+    i++;
+
+    X->s = Y->s;
+
+    MPI_CHK( mpi_grow( X, i ) );
+
+    memset( X->p, 0, X->n * ciL );
+    memcpy( X->p, Y->p, i * ciL );
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Swap the contents of X and Y
+ */
+void mpi_swap( mpi *X, mpi *Y )
+{
+    mpi T;
+
+    memcpy( &T,  X, sizeof( mpi ) );
+    memcpy(  X,  Y, sizeof( mpi ) );
+    memcpy(  Y, &T, sizeof( mpi ) );
+}
+
+/*
+ * Conditionally assign X = Y, without leaking information
+ * about whether the assignment was made or not.
+ * (Leaking information about the respective sizes of X and Y is ok however.)
+ */
+int mpi_safe_cond_assign( mpi *X, const mpi *Y, unsigned char assign )
+{
+    int ret = 0;
+    size_t i;
+
+    /* make sure assign is 0 or 1 */
+    assign = ( assign != 0 );
+
+    MPI_CHK( mpi_grow( X, Y->n ) );
+
+    X->s = X->s * (1 - assign) + Y->s * assign;
+
+    for( i = 0; i < Y->n; i++ )
+        X->p[i] = X->p[i] * (1 - assign) + Y->p[i] * assign;
+
+    for( ; i < X->n; i++ )
+        X->p[i] *= (1 - assign);
+
+cleanup:
+    return( ret );
+}
+
+/*
+ * Conditionally swap X and Y, without leaking information
+ * about whether the swap was made or not.
+ * Here it is not ok to simply swap the pointers, which whould lead to
+ * different memory access patterns when X and Y are used afterwards.
+ */
+int mpi_safe_cond_swap( mpi *X, mpi *Y, unsigned char swap )
+{
+    int ret, s;
+    size_t i;
+    t_uint tmp;
+
+    if( X == Y )
+        return( 0 );
+
+    /* make sure swap is 0 or 1 */
+    swap = ( swap != 0 );
+
+    MPI_CHK( mpi_grow( X, Y->n ) );
+    MPI_CHK( mpi_grow( Y, X->n ) );
+
+    s = X->s;
+    X->s = X->s * (1 - swap) + Y->s * swap;
+    Y->s = Y->s * (1 - swap) +    s * swap;
+
+
+    for( i = 0; i < X->n; i++ )
+    {
+        tmp = X->p[i];
+        X->p[i] = X->p[i] * (1 - swap) + Y->p[i] * swap;
+        Y->p[i] = Y->p[i] * (1 - swap) +     tmp * swap;
+    }
+
+cleanup:
+    return( ret );
+}
+
+/*
+ * Set value from integer
+ */
+int mpi_lset( mpi *X, t_sint z )
+{
+    int ret;
+
+    MPI_CHK( mpi_grow( X, 1 ) );
+    memset( X->p, 0, X->n * ciL );
+
+    X->p[0] = ( z < 0 ) ? -z : z;
+    X->s    = ( z < 0 ) ? -1 : 1;
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Get a specific bit
+ */
+int mpi_get_bit( const mpi *X, size_t pos )
+{
+    if( X->n * biL <= pos )
+        return( 0 );
+
+    return ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01;
+}
+
+/*
+ * Set a bit to a specific value of 0 or 1
+ */
+int mpi_set_bit( mpi *X, size_t pos, unsigned char val )
+{
+    int ret = 0;
+    size_t off = pos / biL;
+    size_t idx = pos % biL;
+
+    if( val != 0 && val != 1 )
+        return POLARSSL_ERR_MPI_BAD_INPUT_DATA;
+
+    if( X->n * biL <= pos )
+    {
+        if( val == 0 )
+            return ( 0 );
+
+        MPI_CHK( mpi_grow( X, off + 1 ) );
+    }
+
+    X->p[off] &= ~( (t_uint) 0x01 << idx );
+    X->p[off] |= (t_uint) val << idx;
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Return the number of least significant bits
+ */
+size_t mpi_lsb( const mpi *X )
+{
+    size_t i, j, count = 0;
+
+    for( i = 0; i < X->n; i++ )
+        for( j = 0; j < biL; j++, count++ )
+            if( ( ( X->p[i] >> j ) & 1 ) != 0 )
+                return( count );
+
+    return( 0 );
+}
+
+/*
+ * Return the number of most significant bits
+ */
+size_t mpi_msb( const mpi *X )
+{
+    size_t i, j;
+
+    for( i = X->n - 1; i > 0; i-- )
+        if( X->p[i] != 0 )
+            break;
+
+    for( j = biL; j > 0; j-- )
+        if( ( ( X->p[i] >> ( j - 1 ) ) & 1 ) != 0 )
+            break;
+
+    return( ( i * biL ) + j );
+}
+
+/*
+ * Return the total size in bytes
+ */
+size_t mpi_size( const mpi *X )
+{
+    return( ( mpi_msb( X ) + 7 ) >> 3 );
+}
+
+/*
+ * Convert an ASCII character to digit value
+ */
+static int mpi_get_digit( t_uint *d, int radix, char c )
+{
+    *d = 255;
+
+    if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
+    if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
+    if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
+
+    if( *d >= (t_uint) radix )
+        return( POLARSSL_ERR_MPI_INVALID_CHARACTER );
+
+    return( 0 );
+}
+
+/*
+ * Import from an ASCII string
+ */
+int mpi_read_string( mpi *X, int radix, const char *s )
+{
+    int ret;
+    size_t i, j, slen, n;
+    t_uint d;
+    mpi T;
+
+    if( radix < 2 || radix > 16 )
+        return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+    mpi_init( &T );
+
+    slen = strlen( s );
+
+    if( radix == 16 )
+    {
+        n = BITS_TO_LIMBS( slen << 2 );
+
+        MPI_CHK( mpi_grow( X, n ) );
+        MPI_CHK( mpi_lset( X, 0 ) );
+
+        for( i = slen, j = 0; i > 0; i--, j++ )
+        {
+            if( i == 1 && s[i - 1] == '-' )
+            {
+                X->s = -1;
+                break;
+            }
+
+            MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
+            X->p[j / (2 * ciL)] |= d << ( (j % (2 * ciL)) << 2 );
+        }
+    }
+    else
+    {
+        MPI_CHK( mpi_lset( X, 0 ) );
+
+        for( i = 0; i < slen; i++ )
+        {
+            if( i == 0 && s[i] == '-' )
+            {
+                X->s = -1;
+                continue;
+            }
+
+            MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
+            MPI_CHK( mpi_mul_int( &T, X, radix ) );
+
+            if( X->s == 1 )
+            {
+                MPI_CHK( mpi_add_int( X, &T, d ) );
+            }
+            else
+            {
+                MPI_CHK( mpi_sub_int( X, &T, d ) );
+            }
+        }
+    }
+
+cleanup:
+
+    mpi_free( &T );
+
+    return( ret );
+}
+
+/*
+ * Helper to write the digits high-order first
+ */
+static int mpi_write_hlp( mpi *X, int radix, char **p )
+{
+    int ret;
+    t_uint r;
+
+    if( radix < 2 || radix > 16 )
+        return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+    MPI_CHK( mpi_mod_int( &r, X, radix ) );
+    MPI_CHK( mpi_div_int( X, NULL, X, radix ) );
+
+    if( mpi_cmp_int( X, 0 ) != 0 )
+        MPI_CHK( mpi_write_hlp( X, radix, p ) );
+
+    if( r < 10 )
+        *(*p)++ = (char)( r + 0x30 );
+    else
+        *(*p)++ = (char)( r + 0x37 );
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Export into an ASCII string
+ */
+int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen )
+{
+    int ret = 0;
+    size_t n;
+    char *p;
+    mpi T;
+
+    if( radix < 2 || radix > 16 )
+        return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+    n = mpi_msb( X );
+    if( radix >=  4 ) n >>= 1;
+    if( radix >= 16 ) n >>= 1;
+    n += 3;
+
+    if( *slen < n )
+    {
+        *slen = n;
+        return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
+    }
+
+    p = s;
+    mpi_init( &T );
+
+    if( X->s == -1 )
+        *p++ = '-';
+
+    if( radix == 16 )
+    {
+        int c;
+        size_t i, j, k;
+
+        for( i = X->n, k = 0; i > 0; i-- )
+        {
+            for( j = ciL; j > 0; j-- )
+            {
+                c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
+
+                if( c == 0 && k == 0 && ( i + j + 3 ) != 0 )
+                    continue;
+
+                *(p++) = "0123456789ABCDEF" [c / 16];
+                *(p++) = "0123456789ABCDEF" [c % 16];
+                k = 1;
+            }
+        }
+    }
+    else
+    {
+        MPI_CHK( mpi_copy( &T, X ) );
+
+        if( T.s == -1 )
+            T.s = 1;
+
+        MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
+    }
+
+    *p++ = '\0';
+    *slen = p - s;
+
+cleanup:
+
+    mpi_free( &T );
+
+    return( ret );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * Read X from an opened file
+ */
+int mpi_read_file( mpi *X, int radix, FILE *fin )
+{
+    t_uint d;
+    size_t slen;
+    char *p;
+    /*
+     * Buffer should have space for (short) label and decimal formatted MPI,
+     * newline characters and '\0'
+     */
+    char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
+
+    memset( s, 0, sizeof( s ) );
+    if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
+        return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
+
+    slen = strlen( s );
+    if( slen == sizeof( s ) - 2 )
+        return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
+
+    if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
+    if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
+
+    p = s + slen;
+    while( --p >= s )
+        if( mpi_get_digit( &d, radix, *p ) != 0 )
+            break;
+
+    return( mpi_read_string( X, radix, p + 1 ) );
+}
+
+/*
+ * Write X into an opened file (or stdout if fout == NULL)
+ */
+int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout )
+{
+    int ret;
+    size_t n, slen, plen;
+    /*
+     * Buffer should have space for (short) label and decimal formatted MPI,
+     * newline characters and '\0'
+     */
+    char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
+
+    n = sizeof( s );
+    memset( s, 0, n );
+    n -= 2;
+
+    MPI_CHK( mpi_write_string( X, radix, s, (size_t *) &n ) );
+
+    if( p == NULL ) p = "";
+
+    plen = strlen( p );
+    slen = strlen( s );
+    s[slen++] = '\r';
+    s[slen++] = '\n';
+
+    if( fout != NULL )
+    {
+        if( fwrite( p, 1, plen, fout ) != plen ||
+            fwrite( s, 1, slen, fout ) != slen )
+            return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
+    }
+    else
+        polarssl_printf( "%s%s", p, s );
+
+cleanup:
+
+    return( ret );
+}
+#endif /* POLARSSL_FS_IO */
+
+/*
+ * Import X from unsigned binary data, big endian
+ */
+int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen )
+{
+    int ret;
+    size_t i, j, n;
+
+    for( n = 0; n < buflen; n++ )
+        if( buf[n] != 0 )
+            break;
+
+    MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
+    MPI_CHK( mpi_lset( X, 0 ) );
+
+    for( i = buflen, j = 0; i > n; i--, j++ )
+        X->p[j / ciL] |= ((t_uint) buf[i - 1]) << ((j % ciL) << 3);
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Export X into unsigned binary data, big endian
+ */
+int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen )
+{
+    size_t i, j, n;
+
+    n = mpi_size( X );
+
+    if( buflen < n )
+        return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
+
+    memset( buf, 0, buflen );
+
+    for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
+        buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
+
+    return( 0 );
+}
+
+/*
+ * Left-shift: X <<= count
+ */
+int mpi_shift_l( mpi *X, size_t count )
+{
+    int ret;
+    size_t i, v0, t1;
+    t_uint r0 = 0, r1;
+
+    v0 = count / (biL    );
+    t1 = count & (biL - 1);
+
+    i = mpi_msb( X ) + count;
+
+    if( X->n * biL < i )
+        MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) );
+
+    ret = 0;
+
+    /*
+     * shift by count / limb_size
+     */
+    if( v0 > 0 )
+    {
+        for( i = X->n; i > v0; i-- )
+            X->p[i - 1] = X->p[i - v0 - 1];
+
+        for( ; i > 0; i-- )
+            X->p[i - 1] = 0;
+    }
+
+    /*
+     * shift by count % limb_size
+     */
+    if( t1 > 0 )
+    {
+        for( i = v0; i < X->n; i++ )
+        {
+            r1 = X->p[i] >> (biL - t1);
+            X->p[i] <<= t1;
+            X->p[i] |= r0;
+            r0 = r1;
+        }
+    }
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Right-shift: X >>= count
+ */
+int mpi_shift_r( mpi *X, size_t count )
+{
+    size_t i, v0, v1;
+    t_uint r0 = 0, r1;
+
+    v0 = count /  biL;
+    v1 = count & (biL - 1);
+
+    if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
+        return mpi_lset( X, 0 );
+
+    /*
+     * shift by count / limb_size
+     */
+    if( v0 > 0 )
+    {
+        for( i = 0; i < X->n - v0; i++ )
+            X->p[i] = X->p[i + v0];
+
+        for( ; i < X->n; i++ )
+            X->p[i] = 0;
+    }
+
+    /*
+     * shift by count % limb_size
+     */
+    if( v1 > 0 )
+    {
+        for( i = X->n; i > 0; i-- )
+        {
+            r1 = X->p[i - 1] << (biL - v1);
+            X->p[i - 1] >>= v1;
+            X->p[i - 1] |= r0;
+            r0 = r1;
+        }
+    }
+
+    return( 0 );
+}
+
+/*
+ * Compare unsigned values
+ */
+int mpi_cmp_abs( const mpi *X, const mpi *Y )
+{
+    size_t i, j;
+
+    for( i = X->n; i > 0; i-- )
+        if( X->p[i - 1] != 0 )
+            break;
+
+    for( j = Y->n; j > 0; j-- )
+        if( Y->p[j - 1] != 0 )
+            break;
+
+    if( i == 0 && j == 0 )
+        return( 0 );
+
+    if( i > j ) return(  1 );
+    if( j > i ) return( -1 );
+
+    for( ; i > 0; i-- )
+    {
+        if( X->p[i - 1] > Y->p[i - 1] ) return(  1 );
+        if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
+    }
+
+    return( 0 );
+}
+
+/*
+ * Compare signed values
+ */
+int mpi_cmp_mpi( const mpi *X, const mpi *Y )
+{
+    size_t i, j;
+
+    for( i = X->n; i > 0; i-- )
+        if( X->p[i - 1] != 0 )
+            break;
+
+    for( j = Y->n; j > 0; j-- )
+        if( Y->p[j - 1] != 0 )
+            break;
+
+    if( i == 0 && j == 0 )
+        return( 0 );
+
+    if( i > j ) return(  X->s );
+    if( j > i ) return( -Y->s );
+
+    if( X->s > 0 && Y->s < 0 ) return(  1 );
+    if( Y->s > 0 && X->s < 0 ) return( -1 );
+
+    for( ; i > 0; i-- )
+    {
+        if( X->p[i - 1] > Y->p[i - 1] ) return(  X->s );
+        if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
+    }
+
+    return( 0 );
+}
+
+/*
+ * Compare signed values
+ */
+int mpi_cmp_int( const mpi *X, t_sint z )
+{
+    mpi Y;
+    t_uint p[1];
+
+    *p  = ( z < 0 ) ? -z : z;
+    Y.s = ( z < 0 ) ? -1 : 1;
+    Y.n = 1;
+    Y.p = p;
+
+    return( mpi_cmp_mpi( X, &Y ) );
+}
+
+/*
+ * Unsigned addition: X = |A| + |B|  (HAC 14.7)
+ */
+int mpi_add_abs( mpi *X, const mpi *A, const mpi *B )
+{
+    int ret;
+    size_t i, j;
+    t_uint *o, *p, c;
+
+    if( X == B )
+    {
+        const mpi *T = A; A = X; B = T;
+    }
+
+    if( X != A )
+        MPI_CHK( mpi_copy( X, A ) );
+
+    /*
+     * X should always be positive as a result of unsigned additions.
+     */
+    X->s = 1;
+
+    for( j = B->n; j > 0; j-- )
+        if( B->p[j - 1] != 0 )
+            break;
+
+    MPI_CHK( mpi_grow( X, j ) );
+
+    o = B->p; p = X->p; c = 0;
+
+    for( i = 0; i < j; i++, o++, p++ )
+    {
+        *p +=  c; c  = ( *p <  c );
+        *p += *o; c += ( *p < *o );
+    }
+
+    while( c != 0 )
+    {
+        if( i >= X->n )
+        {
+            MPI_CHK( mpi_grow( X, i + 1 ) );
+            p = X->p + i;
+        }
+
+        *p += c; c = ( *p < c ); i++; p++;
+    }
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Helper for mpi subtraction
+ */
+static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d )
+{
+    size_t i;
+    t_uint c, z;
+
+    for( i = c = 0; i < n; i++, s++, d++ )
+    {
+        z = ( *d <  c );     *d -=  c;
+        c = ( *d < *s ) + z; *d -= *s;
+    }
+
+    while( c != 0 )
+    {
+        z = ( *d < c ); *d -= c;
+        c = z; i++; d++;
+    }
+}
+
+/*
+ * Unsigned subtraction: X = |A| - |B|  (HAC 14.9)
+ */
+int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B )
+{
+    mpi TB;
+    int ret;
+    size_t n;
+
+    if( mpi_cmp_abs( A, B ) < 0 )
+        return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
+
+    mpi_init( &TB );
+
+    if( X == B )
+    {
+        MPI_CHK( mpi_copy( &TB, B ) );
+        B = &TB;
+    }
+
+    if( X != A )
+        MPI_CHK( mpi_copy( X, A ) );
+
+    /*
+     * X should always be positive as a result of unsigned subtractions.
+     */
+    X->s = 1;
+
+    ret = 0;
+
+    for( n = B->n; n > 0; n-- )
+        if( B->p[n - 1] != 0 )
+            break;
+
+    mpi_sub_hlp( n, B->p, X->p );
+
+cleanup:
+
+    mpi_free( &TB );
+
+    return( ret );
+}
+
+/*
+ * Signed addition: X = A + B
+ */
+int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B )
+{
+    int ret, s = A->s;
+
+    if( A->s * B->s < 0 )
+    {
+        if( mpi_cmp_abs( A, B ) >= 0 )
+        {
+            MPI_CHK( mpi_sub_abs( X, A, B ) );
+            X->s =  s;
+        }
+        else
+        {
+            MPI_CHK( mpi_sub_abs( X, B, A ) );
+            X->s = -s;
+        }
+    }
+    else
+    {
+        MPI_CHK( mpi_add_abs( X, A, B ) );
+        X->s = s;
+    }
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Signed subtraction: X = A - B
+ */
+int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B )
+{
+    int ret, s = A->s;
+
+    if( A->s * B->s > 0 )
+    {
+        if( mpi_cmp_abs( A, B ) >= 0 )
+        {
+            MPI_CHK( mpi_sub_abs( X, A, B ) );
+            X->s =  s;
+        }
+        else
+        {
+            MPI_CHK( mpi_sub_abs( X, B, A ) );
+            X->s = -s;
+        }
+    }
+    else
+    {
+        MPI_CHK( mpi_add_abs( X, A, B ) );
+        X->s = s;
+    }
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Signed addition: X = A + b
+ */
+int mpi_add_int( mpi *X, const mpi *A, t_sint b )
+{
+    mpi _B;
+    t_uint p[1];
+
+    p[0] = ( b < 0 ) ? -b : b;
+    _B.s = ( b < 0 ) ? -1 : 1;
+    _B.n = 1;
+    _B.p = p;
+
+    return( mpi_add_mpi( X, A, &_B ) );
+}
+
+/*
+ * Signed subtraction: X = A - b
+ */
+int mpi_sub_int( mpi *X, const mpi *A, t_sint b )
+{
+    mpi _B;
+    t_uint p[1];
+
+    p[0] = ( b < 0 ) ? -b : b;
+    _B.s = ( b < 0 ) ? -1 : 1;
+    _B.n = 1;
+    _B.p = p;
+
+    return( mpi_sub_mpi( X, A, &_B ) );
+}
+
+/*
+ * Helper for mpi multiplication
+ */
+static
+#if defined(__APPLE__) && defined(__arm__)
+/*
+ * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
+ * appears to need this to prevent bad ARM code generation at -O3.
+ */
+__attribute__ ((noinline))
+#endif
+void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b )
+{
+    t_uint c = 0, t = 0;
+
+#if defined(MULADDC_HUIT)
+    for( ; i >= 8; i -= 8 )
+    {
+        MULADDC_INIT
+        MULADDC_HUIT
+        MULADDC_STOP
+    }
+
+    for( ; i > 0; i-- )
+    {
+        MULADDC_INIT
+        MULADDC_CORE
+        MULADDC_STOP
+    }
+#else /* MULADDC_HUIT */
+    for( ; i >= 16; i -= 16 )
+    {
+        MULADDC_INIT
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_CORE   MULADDC_CORE
+
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_STOP
+    }
+
+    for( ; i >= 8; i -= 8 )
+    {
+        MULADDC_INIT
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_CORE   MULADDC_CORE
+
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_STOP
+    }
+
+    for( ; i > 0; i-- )
+    {
+        MULADDC_INIT
+        MULADDC_CORE
+        MULADDC_STOP
+    }
+#endif /* MULADDC_HUIT */
+
+    t++;
+
+    do {
+        *d += c; c = ( *d < c ); d++;
+    }
+    while( c != 0 );
+}
+
+/*
+ * Baseline multiplication: X = A * B  (HAC 14.12)
+ */
+int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B )
+{
+    int ret;
+    size_t i, j;
+    mpi TA, TB;
+
+    mpi_init( &TA ); mpi_init( &TB );
+
+    if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; }
+    if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; }
+
+    for( i = A->n; i > 0; i-- )
+        if( A->p[i - 1] != 0 )
+            break;
+
+    for( j = B->n; j > 0; j-- )
+        if( B->p[j - 1] != 0 )
+            break;
+
+    MPI_CHK( mpi_grow( X, i + j ) );
+    MPI_CHK( mpi_lset( X, 0 ) );
+
+    for( i++; j > 0; j-- )
+        mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
+
+    X->s = A->s * B->s;
+
+cleanup:
+
+    mpi_free( &TB ); mpi_free( &TA );
+
+    return( ret );
+}
+
+/*
+ * Baseline multiplication: X = A * b
+ */
+int mpi_mul_int( mpi *X, const mpi *A, t_sint b )
+{
+    mpi _B;
+    t_uint p[1];
+
+    _B.s = 1;
+    _B.n = 1;
+    _B.p = p;
+    p[0] = b;
+
+    return( mpi_mul_mpi( X, A, &_B ) );
+}
+
+/*
+ * Division by mpi: A = Q * B + R  (HAC 14.20)
+ */
+int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
+{
+    int ret;
+    size_t i, n, t, k;
+    mpi X, Y, Z, T1, T2;
+
+    if( mpi_cmp_int( B, 0 ) == 0 )
+        return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
+
+    mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
+    mpi_init( &T1 ); mpi_init( &T2 );
+
+    if( mpi_cmp_abs( A, B ) < 0 )
+    {
+        if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
+        if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
+        return( 0 );
+    }
+
+    MPI_CHK( mpi_copy( &X, A ) );
+    MPI_CHK( mpi_copy( &Y, B ) );
+    X.s = Y.s = 1;
+
+    MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
+    MPI_CHK( mpi_lset( &Z,  0 ) );
+    MPI_CHK( mpi_grow( &T1, 2 ) );
+    MPI_CHK( mpi_grow( &T2, 3 ) );
+
+    k = mpi_msb( &Y ) % biL;
+    if( k < biL - 1 )
+    {
+        k = biL - 1 - k;
+        MPI_CHK( mpi_shift_l( &X, k ) );
+        MPI_CHK( mpi_shift_l( &Y, k ) );
+    }
+    else k = 0;
+
+    n = X.n - 1;
+    t = Y.n - 1;
+    MPI_CHK( mpi_shift_l( &Y, biL * (n - t) ) );
+
+    while( mpi_cmp_mpi( &X, &Y ) >= 0 )
+    {
+        Z.p[n - t]++;
+        MPI_CHK( mpi_sub_mpi( &X, &X, &Y ) );
+    }
+    MPI_CHK( mpi_shift_r( &Y, biL * (n - t) ) );
+
+    for( i = n; i > t ; i-- )
+    {
+        if( X.p[i] >= Y.p[t] )
+            Z.p[i - t - 1] = ~0;
+        else
+        {
+            /*
+             * The version of Clang shipped by Apple with Mavericks around
+             * 2014-03 can't handle 128-bit division properly. Disable
+             * 128-bits division for this version. Let's be optimistic and
+             * assume it'll be fixed in the next minor version (next
+             * patchlevel is probably a bit too optimistic).
+             */
+#if defined(POLARSSL_HAVE_UDBL) &&                          \
+    ! ( defined(__x86_64__) && defined(__APPLE__) &&        \
+        defined(__clang_major__) && __clang_major__ == 5 && \
+        defined(__clang_minor__) && __clang_minor__ == 0 )
+            t_udbl r;
+
+            r  = (t_udbl) X.p[i] << biL;
+            r |= (t_udbl) X.p[i - 1];
+            r /= Y.p[t];
+            if( r > ((t_udbl) 1 << biL) - 1)
+                r = ((t_udbl) 1 << biL) - 1;
+
+            Z.p[i - t - 1] = (t_uint) r;
+#else
+            /*
+             * __udiv_qrnnd_c, from gmp/longlong.h
+             */
+            t_uint q0, q1, r0, r1;
+            t_uint d0, d1, d, m;
+
+            d  = Y.p[t];
+            d0 = ( d << biH ) >> biH;
+            d1 = ( d >> biH );
+
+            q1 = X.p[i] / d1;
+            r1 = X.p[i] - d1 * q1;
+            r1 <<= biH;
+            r1 |= ( X.p[i - 1] >> biH );
+
+            m = q1 * d0;
+            if( r1 < m )
+            {
+                q1--, r1 += d;
+                while( r1 >= d && r1 < m )
+                    q1--, r1 += d;
+            }
+            r1 -= m;
+
+            q0 = r1 / d1;
+            r0 = r1 - d1 * q0;
+            r0 <<= biH;
+            r0 |= ( X.p[i - 1] << biH ) >> biH;
+
+            m = q0 * d0;
+            if( r0 < m )
+            {
+                q0--, r0 += d;
+                while( r0 >= d && r0 < m )
+                    q0--, r0 += d;
+            }
+            r0 -= m;
+
+            Z.p[i - t - 1] = ( q1 << biH ) | q0;
+#endif
+        }
+
+        Z.p[i - t - 1]++;
+        do
+        {
+            Z.p[i - t - 1]--;
+
+            MPI_CHK( mpi_lset( &T1, 0 ) );
+            T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
+            T1.p[1] = Y.p[t];
+            MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
+
+            MPI_CHK( mpi_lset( &T2, 0 ) );
+            T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
+            T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
+            T2.p[2] = X.p[i];
+        }
+        while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
+
+        MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
+        MPI_CHK( mpi_shift_l( &T1,  biL * (i - t - 1) ) );
+        MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
+
+        if( mpi_cmp_int( &X, 0 ) < 0 )
+        {
+            MPI_CHK( mpi_copy( &T1, &Y ) );
+            MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
+            MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
+            Z.p[i - t - 1]--;
+        }
+    }
+
+    if( Q != NULL )
+    {
+        MPI_CHK( mpi_copy( Q, &Z ) );
+        Q->s = A->s * B->s;
+    }
+
+    if( R != NULL )
+    {
+        MPI_CHK( mpi_shift_r( &X, k ) );
+        X.s = A->s;
+        MPI_CHK( mpi_copy( R, &X ) );
+
+        if( mpi_cmp_int( R, 0 ) == 0 )
+            R->s = 1;
+    }
+
+cleanup:
+
+    mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z );
+    mpi_free( &T1 ); mpi_free( &T2 );
+
+    return( ret );
+}
+
+/*
+ * Division by int: A = Q * b + R
+ */
+int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b )
+{
+    mpi _B;
+    t_uint p[1];
+
+    p[0] = ( b < 0 ) ? -b : b;
+    _B.s = ( b < 0 ) ? -1 : 1;
+    _B.n = 1;
+    _B.p = p;
+
+    return( mpi_div_mpi( Q, R, A, &_B ) );
+}
+
+/*
+ * Modulo: R = A mod B
+ */
+int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
+{
+    int ret;
+
+    if( mpi_cmp_int( B, 0 ) < 0 )
+        return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
+
+    MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
+
+    while( mpi_cmp_int( R, 0 ) < 0 )
+      MPI_CHK( mpi_add_mpi( R, R, B ) );
+
+    while( mpi_cmp_mpi( R, B ) >= 0 )
+      MPI_CHK( mpi_sub_mpi( R, R, B ) );
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Modulo: r = A mod b
+ */
+int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
+{
+    size_t i;
+    t_uint x, y, z;
+
+    if( b == 0 )
+        return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
+
+    if( b < 0 )
+        return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
+
+    /*
+     * handle trivial cases
+     */
+    if( b == 1 )
+    {
+        *r = 0;
+        return( 0 );
+    }
+
+    if( b == 2 )
+    {
+        *r = A->p[0] & 1;
+        return( 0 );
+    }
+
+    /*
+     * general case
+     */
+    for( i = A->n, y = 0; i > 0; i-- )
+    {
+        x  = A->p[i - 1];
+        y  = ( y << biH ) | ( x >> biH );
+        z  = y / b;
+        y -= z * b;
+
+        x <<= biH;
+        y  = ( y << biH ) | ( x >> biH );
+        z  = y / b;
+        y -= z * b;
+    }
+
+    /*
+     * If A is negative, then the current y represents a negative value.
+     * Flipping it to the positive side.
+     */
+    if( A->s < 0 && y != 0 )
+        y = b - y;
+
+    *r = y;
+
+    return( 0 );
+}
+
+/*
+ * Fast Montgomery initialization (thanks to Tom St Denis)
+ */
+static void mpi_montg_init( t_uint *mm, const mpi *N )
+{
+    t_uint x, m0 = N->p[0];
+    unsigned int i;
+
+    x  = m0;
+    x += ( ( m0 + 2 ) & 4 ) << 1;
+
+    for( i = biL; i >= 8; i /= 2 )
+        x *= ( 2 - ( m0 * x ) );
+
+    *mm = ~x + 1;
+}
+
+/*
+ * Montgomery multiplication: A = A * B * R^-1 mod N  (HAC 14.36)
+ */
+static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm,
+                         const mpi *T )
+{
+    size_t i, n, m;
+    t_uint u0, u1, *d;
+
+    memset( T->p, 0, T->n * ciL );
+
+    d = T->p;
+    n = N->n;
+    m = ( B->n < n ) ? B->n : n;
+
+    for( i = 0; i < n; i++ )
+    {
+        /*
+         * T = (T + u0*B + u1*N) / 2^biL
+         */
+        u0 = A->p[i];
+        u1 = ( d[0] + u0 * B->p[0] ) * mm;
+
+        mpi_mul_hlp( m, B->p, d, u0 );
+        mpi_mul_hlp( n, N->p, d, u1 );
+
+        *d++ = u0; d[n + 1] = 0;
+    }
+
+    memcpy( A->p, d, (n + 1) * ciL );
+
+    if( mpi_cmp_abs( A, N ) >= 0 )
+        mpi_sub_hlp( n, N->p, A->p );
+    else
+        /* prevent timing attacks */
+        mpi_sub_hlp( n, A->p, T->p );
+}
+
+/*
+ * Montgomery reduction: A = A * R^-1 mod N
+ */
+static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T )
+{
+    t_uint z = 1;
+    mpi U;
+
+    U.n = U.s = (int) z;
+    U.p = &z;
+
+    mpi_montmul( A, &U, N, mm, T );
+}
+
+/*
+ * Sliding-window exponentiation: X = A^E mod N  (HAC 14.85)
+ */
+int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
+{
+    int ret;
+    size_t wbits, wsize, one = 1;
+    size_t i, j, nblimbs;
+    size_t bufsize, nbits;
+    t_uint ei, mm, state;
+    mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ], Apos;
+    int neg;
+
+    if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
+        return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+    if( mpi_cmp_int( E, 0 ) < 0 )
+        return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+    /*
+     * Init temps and window size
+     */
+    mpi_montg_init( &mm, N );
+    mpi_init( &RR ); mpi_init( &T );
+    mpi_init( &Apos );
+    memset( W, 0, sizeof( W ) );
+
+    i = mpi_msb( E );
+
+    wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
+            ( i >  79 ) ? 4 : ( i >  23 ) ? 3 : 1;
+
+    if( wsize > POLARSSL_MPI_WINDOW_SIZE )
+        wsize = POLARSSL_MPI_WINDOW_SIZE;
+
+    j = N->n + 1;
+    MPI_CHK( mpi_grow( X, j ) );
+    MPI_CHK( mpi_grow( &W[1],  j ) );
+    MPI_CHK( mpi_grow( &T, j * 2 ) );
+
+    /*
+     * Compensate for negative A (and correct at the end)
+     */
+    neg = ( A->s == -1 );
+    if( neg )
+    {
+        MPI_CHK( mpi_copy( &Apos, A ) );
+        Apos.s = 1;
+        A = &Apos;
+    }
+
+    /*
+     * If 1st call, pre-compute R^2 mod N
+     */
+    if( _RR == NULL || _RR->p == NULL )
+    {
+        MPI_CHK( mpi_lset( &RR, 1 ) );
+        MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
+        MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
+
+        if( _RR != NULL )
+            memcpy( _RR, &RR, sizeof( mpi ) );
+    }
+    else
+        memcpy( &RR, _RR, sizeof( mpi ) );
+
+    /*
+     * W[1] = A * R^2 * R^-1 mod N = A * R mod N
+     */
+    if( mpi_cmp_mpi( A, N ) >= 0 )
+        MPI_CHK( mpi_mod_mpi( &W[1], A, N ) );
+    else
+        MPI_CHK( mpi_copy( &W[1], A ) );
+
+    mpi_montmul( &W[1], &RR, N, mm, &T );
+
+    /*
+     * X = R^2 * R^-1 mod N = R mod N
+     */
+    MPI_CHK( mpi_copy( X, &RR ) );
+    mpi_montred( X, N, mm, &T );
+
+    if( wsize > 1 )
+    {
+        /*
+         * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
+         */
+        j =  one << (wsize - 1);
+
+        MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
+        MPI_CHK( mpi_copy( &W[j], &W[1]    ) );
+
+        for( i = 0; i < wsize - 1; i++ )
+            mpi_montmul( &W[j], &W[j], N, mm, &T );
+
+        /*
+         * W[i] = W[i - 1] * W[1]
+         */
+        for( i = j + 1; i < (one << wsize); i++ )
+        {
+            MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
+            MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
+
+            mpi_montmul( &W[i], &W[1], N, mm, &T );
+        }
+    }
+
+    nblimbs = E->n;
+    bufsize = 0;
+    nbits   = 0;
+    wbits   = 0;
+    state   = 0;
+
+    while( 1 )
+    {
+        if( bufsize == 0 )
+        {
+            if( nblimbs == 0 )
+                break;
+
+            nblimbs--;
+
+            bufsize = sizeof( t_uint ) << 3;
+        }
+
+        bufsize--;
+
+        ei = (E->p[nblimbs] >> bufsize) & 1;
+
+        /*
+         * skip leading 0s
+         */
+        if( ei == 0 && state == 0 )
+            continue;
+
+        if( ei == 0 && state == 1 )
+        {
+            /*
+             * out of window, square X
+             */
+            mpi_montmul( X, X, N, mm, &T );
+            continue;
+        }
+
+        /*
+         * add ei to current window
+         */
+        state = 2;
+
+        nbits++;
+        wbits |= (ei << (wsize - nbits));
+
+        if( nbits == wsize )
+        {
+            /*
+             * X = X^wsize R^-1 mod N
+             */
+            for( i = 0; i < wsize; i++ )
+                mpi_montmul( X, X, N, mm, &T );
+
+            /*
+             * X = X * W[wbits] R^-1 mod N
+             */
+            mpi_montmul( X, &W[wbits], N, mm, &T );
+
+            state--;
+            nbits = 0;
+            wbits = 0;
+        }
+    }
+
+    /*
+     * process the remaining bits
+     */
+    for( i = 0; i < nbits; i++ )
+    {
+        mpi_montmul( X, X, N, mm, &T );
+
+        wbits <<= 1;
+
+        if( (wbits & (one << wsize)) != 0 )
+            mpi_montmul( X, &W[1], N, mm, &T );
+    }
+
+    /*
+     * X = A^E * R * R^-1 mod N = A^E mod N
+     */
+    mpi_montred( X, N, mm, &T );
+
+    if( neg )
+    {
+        X->s = -1;
+        MPI_CHK( mpi_add_mpi( X, N, X ) );
+    }
+
+cleanup:
+
+    for( i = (one << (wsize - 1)); i < (one << wsize); i++ )
+        mpi_free( &W[i] );
+
+    mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos );
+
+    if( _RR == NULL || _RR->p == NULL )
+        mpi_free( &RR );
+
+    return( ret );
+}
+
+/*
+ * Greatest common divisor: G = gcd(A, B)  (HAC 14.54)
+ */
+int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
+{
+    int ret;
+    size_t lz, lzt;
+    mpi TG, TA, TB;
+
+    mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB );
+
+    MPI_CHK( mpi_copy( &TA, A ) );
+    MPI_CHK( mpi_copy( &TB, B ) );
+
+    lz = mpi_lsb( &TA );
+    lzt = mpi_lsb( &TB );
+
+    if ( lzt < lz )
+        lz = lzt;
+
+    MPI_CHK( mpi_shift_r( &TA, lz ) );
+    MPI_CHK( mpi_shift_r( &TB, lz ) );
+
+    TA.s = TB.s = 1;
+
+    while( mpi_cmp_int( &TA, 0 ) != 0 )
+    {
+        MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
+        MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
+
+        if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
+        {
+            MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
+            MPI_CHK( mpi_shift_r( &TA, 1 ) );
+        }
+        else
+        {
+            MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
+            MPI_CHK( mpi_shift_r( &TB, 1 ) );
+        }
+    }
+
+    MPI_CHK( mpi_shift_l( &TB, lz ) );
+    MPI_CHK( mpi_copy( G, &TB ) );
+
+cleanup:
+
+    mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB );
+
+    return( ret );
+}
+
+/*
+ * Fill X with size bytes of random.
+ *
+ * Use a temporary bytes representation to make sure the result is the same
+ * regardless of the platform endianness (useful when f_rng is actually
+ * deterministic, eg for tests).
+ */
+int mpi_fill_random( mpi *X, size_t size,
+                     int (*f_rng)(void *, unsigned char *, size_t),
+                     void *p_rng )
+{
+    int ret;
+    unsigned char buf[POLARSSL_MPI_MAX_SIZE];
+
+    if( size > POLARSSL_MPI_MAX_SIZE )
+        return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+    MPI_CHK( f_rng( p_rng, buf, size ) );
+    MPI_CHK( mpi_read_binary( X, buf, size ) );
+
+cleanup:
+    return( ret );
+}
+
+/*
+ * Modular inverse: X = A^-1 mod N  (HAC 14.61 / 14.64)
+ */
+int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N )
+{
+    int ret;
+    mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
+
+    if( mpi_cmp_int( N, 0 ) <= 0 )
+        return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+    mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 );
+    mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV );
+    mpi_init( &V1 ); mpi_init( &V2 );
+
+    MPI_CHK( mpi_gcd( &G, A, N ) );
+
+    if( mpi_cmp_int( &G, 1 ) != 0 )
+    {
+        ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
+        goto cleanup;
+    }
+
+    MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
+    MPI_CHK( mpi_copy( &TU, &TA ) );
+    MPI_CHK( mpi_copy( &TB, N ) );
+    MPI_CHK( mpi_copy( &TV, N ) );
+
+    MPI_CHK( mpi_lset( &U1, 1 ) );
+    MPI_CHK( mpi_lset( &U2, 0 ) );
+    MPI_CHK( mpi_lset( &V1, 0 ) );
+    MPI_CHK( mpi_lset( &V2, 1 ) );
+
+    do
+    {
+        while( ( TU.p[0] & 1 ) == 0 )
+        {
+            MPI_CHK( mpi_shift_r( &TU, 1 ) );
+
+            if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
+            {
+                MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
+                MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
+            }
+
+            MPI_CHK( mpi_shift_r( &U1, 1 ) );
+            MPI_CHK( mpi_shift_r( &U2, 1 ) );
+        }
+
+        while( ( TV.p[0] & 1 ) == 0 )
+        {
+            MPI_CHK( mpi_shift_r( &TV, 1 ) );
+
+            if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
+            {
+                MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
+                MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
+            }
+
+            MPI_CHK( mpi_shift_r( &V1, 1 ) );
+            MPI_CHK( mpi_shift_r( &V2, 1 ) );
+        }
+
+        if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
+        {
+            MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
+            MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
+            MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
+        }
+        else
+        {
+            MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
+            MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
+            MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
+        }
+    }
+    while( mpi_cmp_int( &TU, 0 ) != 0 );
+
+    while( mpi_cmp_int( &V1, 0 ) < 0 )
+        MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
+
+    while( mpi_cmp_mpi( &V1, N ) >= 0 )
+        MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
+
+    MPI_CHK( mpi_copy( X, &V1 ) );
+
+cleanup:
+
+    mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 );
+    mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV );
+    mpi_free( &V1 ); mpi_free( &V2 );
+
+    return( ret );
+}
+
+#if defined(POLARSSL_GENPRIME)
+
+static const int small_prime[] =
+{
+        3,    5,    7,   11,   13,   17,   19,   23,
+       29,   31,   37,   41,   43,   47,   53,   59,
+       61,   67,   71,   73,   79,   83,   89,   97,
+      101,  103,  107,  109,  113,  127,  131,  137,
+      139,  149,  151,  157,  163,  167,  173,  179,
+      181,  191,  193,  197,  199,  211,  223,  227,
+      229,  233,  239,  241,  251,  257,  263,  269,
+      271,  277,  281,  283,  293,  307,  311,  313,
+      317,  331,  337,  347,  349,  353,  359,  367,
+      373,  379,  383,  389,  397,  401,  409,  419,
+      421,  431,  433,  439,  443,  449,  457,  461,
+      463,  467,  479,  487,  491,  499,  503,  509,
+      521,  523,  541,  547,  557,  563,  569,  571,
+      577,  587,  593,  599,  601,  607,  613,  617,
+      619,  631,  641,  643,  647,  653,  659,  661,
+      673,  677,  683,  691,  701,  709,  719,  727,
+      733,  739,  743,  751,  757,  761,  769,  773,
+      787,  797,  809,  811,  821,  823,  827,  829,
+      839,  853,  857,  859,  863,  877,  881,  883,
+      887,  907,  911,  919,  929,  937,  941,  947,
+      953,  967,  971,  977,  983,  991,  997, -103
+};
+
+/*
+ * Small divisors test (X must be positive)
+ *
+ * Return values:
+ * 0: no small factor (possible prime, more tests needed)
+ * 1: certain prime
+ * POLARSSL_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
+ * other negative: error
+ */
+static int mpi_check_small_factors( const mpi *X )
+{
+    int ret = 0;
+    size_t i;
+    t_uint r;
+
+    if( ( X->p[0] & 1 ) == 0 )
+        return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
+
+    for( i = 0; small_prime[i] > 0; i++ )
+    {
+        if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
+            return( 1 );
+
+        MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
+
+        if( r == 0 )
+            return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
+    }
+
+cleanup:
+    return( ret );
+}
+
+/*
+ * Miller-Rabin pseudo-primality test  (HAC 4.24)
+ */
+static int mpi_miller_rabin( const mpi *X,
+                             int (*f_rng)(void *, unsigned char *, size_t),
+                             void *p_rng )
+{
+    int ret;
+    size_t i, j, n, s;
+    mpi W, R, T, A, RR;
+
+    mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A );
+    mpi_init( &RR );
+
+    /*
+     * W = |X| - 1
+     * R = W >> lsb( W )
+     */
+    MPI_CHK( mpi_sub_int( &W, X, 1 ) );
+    s = mpi_lsb( &W );
+    MPI_CHK( mpi_copy( &R, &W ) );
+    MPI_CHK( mpi_shift_r( &R, s ) );
+
+    i = mpi_msb( X );
+    /*
+     * HAC, table 4.4
+     */
+    n = ( ( i >= 1300 ) ?  2 : ( i >=  850 ) ?  3 :
+          ( i >=  650 ) ?  4 : ( i >=  350 ) ?  8 :
+          ( i >=  250 ) ? 12 : ( i >=  150 ) ? 18 : 27 );
+
+    for( i = 0; i < n; i++ )
+    {
+        /*
+         * pick a random A, 1 < A < |X| - 1
+         */
+        MPI_CHK( mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
+
+        if( mpi_cmp_mpi( &A, &W ) >= 0 )
+        {
+            j = mpi_msb( &A ) - mpi_msb( &W );
+            MPI_CHK( mpi_shift_r( &A, j + 1 ) );
+        }
+        A.p[0] |= 3;
+
+        /*
+         * A = A^R mod |X|
+         */
+        MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
+
+        if( mpi_cmp_mpi( &A, &W ) == 0 ||
+            mpi_cmp_int( &A,  1 ) == 0 )
+            continue;
+
+        j = 1;
+        while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
+        {
+            /*
+             * A = A * A mod |X|
+             */
+            MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
+            MPI_CHK( mpi_mod_mpi( &A, &T, X  ) );
+
+            if( mpi_cmp_int( &A, 1 ) == 0 )
+                break;
+
+            j++;
+        }
+
+        /*
+         * not prime if A != |X| - 1 or A == 1
+         */
+        if( mpi_cmp_mpi( &A, &W ) != 0 ||
+            mpi_cmp_int( &A,  1 ) == 0 )
+        {
+            ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
+            break;
+        }
+    }
+
+cleanup:
+    mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A );
+    mpi_free( &RR );
+
+    return( ret );
+}
+
+/*
+ * Pseudo-primality test: small factors, then Miller-Rabin
+ */
+int mpi_is_prime( mpi *X,
+                  int (*f_rng)(void *, unsigned char *, size_t),
+                  void *p_rng )
+{
+    int ret;
+    const mpi XX = { 1, X->n, X->p }; /* Abs(X) */
+
+    if( mpi_cmp_int( &XX, 0 ) == 0 ||
+        mpi_cmp_int( &XX, 1 ) == 0 )
+        return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
+
+    if( mpi_cmp_int( &XX, 2 ) == 0 )
+        return( 0 );
+
+    if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
+    {
+        if( ret == 1 )
+            return( 0 );
+
+        return( ret );
+    }
+
+    return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
+}
+
+/*
+ * Prime number generation
+ */
+int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
+                   int (*f_rng)(void *, unsigned char *, size_t),
+                   void *p_rng )
+{
+    int ret;
+    size_t k, n;
+    t_uint r;
+    mpi Y;
+
+    if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS )
+        return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+    mpi_init( &Y );
+
+    n = BITS_TO_LIMBS( nbits );
+
+    MPI_CHK( mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
+
+    k = mpi_msb( X );
+    if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) );
+    if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) );
+
+    X->p[0] |= 3;
+
+    if( dh_flag == 0 )
+    {
+        while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
+        {
+            if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
+                goto cleanup;
+
+            MPI_CHK( mpi_add_int( X, X, 2 ) );
+        }
+    }
+    else
+    {
+        /*
+         * An necessary condition for Y and X = 2Y + 1 to be prime
+         * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
+         * Make sure it is satisfied, while keeping X = 3 mod 4
+         */
+        MPI_CHK( mpi_mod_int( &r, X, 3 ) );
+        if( r == 0 )
+            MPI_CHK( mpi_add_int( X, X, 8 ) );
+        else if( r == 1 )
+            MPI_CHK( mpi_add_int( X, X, 4 ) );
+
+        /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
+        MPI_CHK( mpi_copy( &Y, X ) );
+        MPI_CHK( mpi_shift_r( &Y, 1 ) );
+
+        while( 1 )
+        {
+            /*
+             * First, check small factors for X and Y
+             * before doing Miller-Rabin on any of them
+             */
+            if( ( ret = mpi_check_small_factors(  X         ) ) == 0 &&
+                ( ret = mpi_check_small_factors( &Y         ) ) == 0 &&
+                ( ret = mpi_miller_rabin(  X, f_rng, p_rng  ) ) == 0 &&
+                ( ret = mpi_miller_rabin( &Y, f_rng, p_rng  ) ) == 0 )
+            {
+                break;
+            }
+
+            if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
+                goto cleanup;
+
+            /*
+             * Next candidates. We want to preserve Y = (X-1) / 2 and
+             * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
+             * so up Y by 6 and X by 12.
+             */
+            MPI_CHK( mpi_add_int(  X,  X, 12 ) );
+            MPI_CHK( mpi_add_int( &Y, &Y, 6  ) );
+        }
+    }
+
+cleanup:
+
+    mpi_free( &Y );
+
+    return( ret );
+}
+
+#endif /* POLARSSL_GENPRIME */
+
+#if defined(POLARSSL_SELF_TEST)
+
+#define GCD_PAIR_COUNT  3
+
+static const int gcd_pairs[GCD_PAIR_COUNT][3] =
+{
+    { 693, 609, 21 },
+    { 1764, 868, 28 },
+    { 768454923, 542167814, 1 }
+};
+
+/*
+ * Checkup routine
+ */
+int mpi_self_test( int verbose )
+{
+    int ret, i;
+    mpi A, E, N, X, Y, U, V;
+
+    mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X );
+    mpi_init( &Y ); mpi_init( &U ); mpi_init( &V );
+
+    MPI_CHK( mpi_read_string( &A, 16,
+        "EFE021C2645FD1DC586E69184AF4A31E" \
+        "D5F53E93B5F123FA41680867BA110131" \
+        "944FE7952E2517337780CB0DB80E61AA" \
+        "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
+
+    MPI_CHK( mpi_read_string( &E, 16,
+        "B2E7EFD37075B9F03FF989C7C5051C20" \
+        "34D2A323810251127E7BF8625A4F49A5" \
+        "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
+        "5B5C25763222FEFCCFC38B832366C29E" ) );
+
+    MPI_CHK( mpi_read_string( &N, 16,
+        "0066A198186C18C10B2F5ED9B522752A" \
+        "9830B69916E535C8F047518A889A43A5" \
+        "94B6BED27A168D31D4A52F88925AA8F5" ) );
+
+    MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
+
+    MPI_CHK( mpi_read_string( &U, 16,
+        "602AB7ECA597A3D6B56FF9829A5E8B85" \
+        "9E857EA95A03512E2BAE7391688D264A" \
+        "A5663B0341DB9CCFD2C4C5F421FEC814" \
+        "8001B72E848A38CAE1C65F78E56ABDEF" \
+        "E12D3C039B8A02D6BE593F0BBBDA56F1" \
+        "ECF677152EF804370C1A305CAF3B5BF1" \
+        "30879B56C61DE584A0F53A2447A51E" ) );
+
+    if( verbose != 0 )
+        polarssl_printf( "  MPI test #1 (mul_mpi): " );
+
+    if( mpi_cmp_mpi( &X, &U ) != 0 )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "failed\n" );
+
+        ret = 1;
+        goto cleanup;
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n" );
+
+    MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
+
+    MPI_CHK( mpi_read_string( &U, 16,
+        "256567336059E52CAE22925474705F39A94" ) );
+
+    MPI_CHK( mpi_read_string( &V, 16,
+        "6613F26162223DF488E9CD48CC132C7A" \
+        "0AC93C701B001B092E4E5B9F73BCD27B" \
+        "9EE50D0657C77F374E903CDFA4C642" ) );
+
+    if( verbose != 0 )
+        polarssl_printf( "  MPI test #2 (div_mpi): " );
+
+    if( mpi_cmp_mpi( &X, &U ) != 0 ||
+        mpi_cmp_mpi( &Y, &V ) != 0 )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "failed\n" );
+
+        ret = 1;
+        goto cleanup;
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n" );
+
+    MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
+
+    MPI_CHK( mpi_read_string( &U, 16,
+        "36E139AEA55215609D2816998ED020BB" \
+        "BD96C37890F65171D948E9BC7CBAA4D9" \
+        "325D24D6A3C12710F10A09FA08AB87" ) );
+
+    if( verbose != 0 )
+        polarssl_printf( "  MPI test #3 (exp_mod): " );
+
+    if( mpi_cmp_mpi( &X, &U ) != 0 )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "failed\n" );
+
+        ret = 1;
+        goto cleanup;
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n" );
+
+    MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
+
+    MPI_CHK( mpi_read_string( &U, 16,
+        "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
+        "C3DBA76456363A10869622EAC2DD84EC" \
+        "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
+
+    if( verbose != 0 )
+        polarssl_printf( "  MPI test #4 (inv_mod): " );
+
+    if( mpi_cmp_mpi( &X, &U ) != 0 )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "failed\n" );
+
+        ret = 1;
+        goto cleanup;
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n" );
+
+    if( verbose != 0 )
+        polarssl_printf( "  MPI test #5 (simple gcd): " );
+
+    for ( i = 0; i < GCD_PAIR_COUNT; i++)
+    {
+        MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
+        MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
+
+        MPI_CHK( mpi_gcd( &A, &X, &Y ) );
+
+        if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed at %d\n", i );
+
+            ret = 1;
+            goto cleanup;
+        }
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n" );
+
+cleanup:
+
+    if( ret != 0 && verbose != 0 )
+        polarssl_printf( "Unexpected error, return code = %08X\n", ret );
+
+    mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X );
+    mpi_free( &Y ); mpi_free( &U ); mpi_free( &V );
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+    return( ret );
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_BIGNUM_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/blowfish.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,642 @@
+/*
+ *  Blowfish implementation
+ *
+ *  Copyright (C) 2012-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  The Blowfish block cipher was designed by Bruce Schneier in 1993.
+ *  http://www.schneier.com/blowfish.html
+ *  http://en.wikipedia.org/wiki/Blowfish_%28cipher%29
+ *
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_BLOWFISH_C)
+
+#include "polarssl/blowfish.h"
+
+#if !defined(POLARSSL_BLOWFISH_ALT)
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i)                            \
+{                                                       \
+    (n) = ( (uint32_t) (b)[(i)    ] << 24 )             \
+        | ( (uint32_t) (b)[(i) + 1] << 16 )             \
+        | ( (uint32_t) (b)[(i) + 2] <<  8 )             \
+        | ( (uint32_t) (b)[(i) + 3]       );            \
+}
+#endif
+
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i)                            \
+{                                                       \
+    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
+    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
+    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
+    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
+}
+#endif
+
+static const uint32_t P[BLOWFISH_ROUNDS + 2] = {
+        0x243F6A88L, 0x85A308D3L, 0x13198A2EL, 0x03707344L,
+        0xA4093822L, 0x299F31D0L, 0x082EFA98L, 0xEC4E6C89L,
+        0x452821E6L, 0x38D01377L, 0xBE5466CFL, 0x34E90C6CL,
+        0xC0AC29B7L, 0xC97C50DDL, 0x3F84D5B5L, 0xB5470917L,
+        0x9216D5D9L, 0x8979FB1BL
+};
+
+/* declarations of data at the end of this file */
+static const uint32_t S[4][256];
+
+static uint32_t F(blowfish_context *ctx, uint32_t x)
+{
+   unsigned short a, b, c, d;
+   uint32_t  y;
+
+   d = (unsigned short)(x & 0xFF);
+   x >>= 8;
+   c = (unsigned short)(x & 0xFF);
+   x >>= 8;
+   b = (unsigned short)(x & 0xFF);
+   x >>= 8;
+   a = (unsigned short)(x & 0xFF);
+   y = ctx->S[0][a] + ctx->S[1][b];
+   y = y ^ ctx->S[2][c];
+   y = y + ctx->S[3][d];
+
+   return y;
+}
+
+static void blowfish_enc(blowfish_context *ctx, uint32_t *xl, uint32_t *xr)
+{
+    uint32_t  Xl, Xr, temp;
+    short i;
+
+    Xl = *xl;
+    Xr = *xr;
+
+    for (i = 0; i < BLOWFISH_ROUNDS; ++i)
+    {
+        Xl = Xl ^ ctx->P[i];
+        Xr = F(ctx, Xl) ^ Xr;
+
+        temp = Xl;
+        Xl = Xr;
+        Xr = temp;
+    }
+
+    temp = Xl;
+    Xl = Xr;
+    Xr = temp;
+
+    Xr = Xr ^ ctx->P[BLOWFISH_ROUNDS];
+    Xl = Xl ^ ctx->P[BLOWFISH_ROUNDS + 1];
+
+    *xl = Xl;
+    *xr = Xr;
+}
+
+static void blowfish_dec(blowfish_context *ctx, uint32_t *xl, uint32_t *xr)
+{
+    uint32_t  Xl, Xr, temp;
+    short i;
+
+    Xl = *xl;
+    Xr = *xr;
+
+    for (i = BLOWFISH_ROUNDS + 1; i > 1; --i)
+    {
+        Xl = Xl ^ ctx->P[i];
+        Xr = F(ctx, Xl) ^ Xr;
+
+        temp = Xl;
+        Xl = Xr;
+        Xr = temp;
+    }
+
+    temp = Xl;
+    Xl = Xr;
+    Xr = temp;
+
+    Xr = Xr ^ ctx->P[1];
+    Xl = Xl ^ ctx->P[0];
+
+    *xl = Xl;
+    *xr = Xr;
+}
+
+/*
+ * Blowfish key schedule
+ */
+int blowfish_setkey( blowfish_context *ctx, const unsigned char *key,
+                     unsigned int keysize )
+{
+    unsigned int i, j, k;
+    uint32_t data, datal, datar;
+
+    if( keysize < BLOWFISH_MIN_KEY || keysize > BLOWFISH_MAX_KEY ||
+        ( keysize % 8 ) )
+    {
+        return POLARSSL_ERR_BLOWFISH_INVALID_KEY_LENGTH;
+    }
+
+    keysize >>= 3;
+
+    for( i = 0; i < 4; i++ )
+    {
+        for( j = 0; j < 256; j++ )
+            ctx->S[i][j] = S[i][j];
+    }
+
+    j = 0;
+    for( i = 0; i < BLOWFISH_ROUNDS + 2; ++i )
+    {
+        data = 0x00000000;
+        for( k = 0; k < 4; ++k )
+        {
+            data = ( data << 8 ) | key[j++];
+            if( j >= keysize )
+                j = 0;
+        }
+        ctx->P[i] = P[i] ^ data;
+    }
+
+    datal = 0x00000000;
+    datar = 0x00000000;
+
+    for( i = 0; i < BLOWFISH_ROUNDS + 2; i += 2 )
+    {
+        blowfish_enc( ctx, &datal, &datar );
+        ctx->P[i] = datal;
+        ctx->P[i + 1] = datar;
+    }
+
+    for( i = 0; i < 4; i++ )
+    {
+       for( j = 0; j < 256; j += 2 )
+       {
+            blowfish_enc( ctx, &datal, &datar );
+            ctx->S[i][j] = datal;
+            ctx->S[i][j + 1] = datar;
+        }
+    }
+    return( 0 );
+}
+
+/*
+ * Blowfish-ECB block encryption/decryption
+ */
+int blowfish_crypt_ecb( blowfish_context *ctx,
+                    int mode,
+                    const unsigned char input[BLOWFISH_BLOCKSIZE],
+                    unsigned char output[BLOWFISH_BLOCKSIZE] )
+{
+    uint32_t X0, X1;
+
+    GET_UINT32_BE( X0, input,  0 );
+    GET_UINT32_BE( X1, input,  4 );
+
+    if( mode == BLOWFISH_DECRYPT )
+    {
+        blowfish_dec(ctx, &X0, &X1);
+    }
+    else /* BLOWFISH_ENCRYPT */
+    {
+        blowfish_enc(ctx, &X0, &X1);
+    }
+
+    PUT_UINT32_BE( X0, output,  0 );
+    PUT_UINT32_BE( X1, output,  4 );
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+/*
+ * Blowfish-CBC buffer encryption/decryption
+ */
+int blowfish_crypt_cbc( blowfish_context *ctx,
+                    int mode,
+                    size_t length,
+                    unsigned char iv[BLOWFISH_BLOCKSIZE],
+                    const unsigned char *input,
+                    unsigned char *output )
+{
+    int i;
+    unsigned char temp[BLOWFISH_BLOCKSIZE];
+
+    if( length % BLOWFISH_BLOCKSIZE )
+        return( POLARSSL_ERR_BLOWFISH_INVALID_INPUT_LENGTH );
+
+    if( mode == BLOWFISH_DECRYPT )
+    {
+        while( length > 0 )
+        {
+            memcpy( temp, input, BLOWFISH_BLOCKSIZE );
+            blowfish_crypt_ecb( ctx, mode, input, output );
+
+            for( i = 0; i < BLOWFISH_BLOCKSIZE;i++ )
+                output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+            memcpy( iv, temp, BLOWFISH_BLOCKSIZE );
+
+            input  += BLOWFISH_BLOCKSIZE;
+            output += BLOWFISH_BLOCKSIZE;
+            length -= BLOWFISH_BLOCKSIZE;
+        }
+    }
+    else
+    {
+        while( length > 0 )
+        {
+            for( i = 0; i < BLOWFISH_BLOCKSIZE; i++ )
+                output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+            blowfish_crypt_ecb( ctx, mode, output, output );
+            memcpy( iv, output, BLOWFISH_BLOCKSIZE );
+
+            input  += BLOWFISH_BLOCKSIZE;
+            output += BLOWFISH_BLOCKSIZE;
+            length -= BLOWFISH_BLOCKSIZE;
+        }
+    }
+
+    return( 0 );
+}
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+/*
+ * Blowfish CFB buffer encryption/decryption
+ */
+int blowfish_crypt_cfb64( blowfish_context *ctx,
+                       int mode,
+                       size_t length,
+                       size_t *iv_off,
+                       unsigned char iv[BLOWFISH_BLOCKSIZE],
+                       const unsigned char *input,
+                       unsigned char *output )
+{
+    int c;
+    size_t n = *iv_off;
+
+    if( mode == BLOWFISH_DECRYPT )
+    {
+        while( length-- )
+        {
+            if( n == 0 )
+                blowfish_crypt_ecb( ctx, BLOWFISH_ENCRYPT, iv, iv );
+
+            c = *input++;
+            *output++ = (unsigned char)( c ^ iv[n] );
+            iv[n] = (unsigned char) c;
+
+            n = (n + 1) % BLOWFISH_BLOCKSIZE;
+        }
+    }
+    else
+    {
+        while( length-- )
+        {
+            if( n == 0 )
+                blowfish_crypt_ecb( ctx, BLOWFISH_ENCRYPT, iv, iv );
+
+            iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
+
+            n = (n + 1) % BLOWFISH_BLOCKSIZE;
+        }
+    }
+
+    *iv_off = n;
+
+    return( 0 );
+}
+#endif /*POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+/*
+ * Blowfish CTR buffer encryption/decryption
+ */
+int blowfish_crypt_ctr( blowfish_context *ctx,
+                       size_t length,
+                       size_t *nc_off,
+                       unsigned char nonce_counter[BLOWFISH_BLOCKSIZE],
+                       unsigned char stream_block[BLOWFISH_BLOCKSIZE],
+                       const unsigned char *input,
+                       unsigned char *output )
+{
+    int c, i;
+    size_t n = *nc_off;
+
+    while( length-- )
+    {
+        if( n == 0 ) {
+            blowfish_crypt_ecb( ctx, BLOWFISH_ENCRYPT, nonce_counter,
+                                stream_block );
+
+            for( i = BLOWFISH_BLOCKSIZE; i > 0; i-- )
+                if( ++nonce_counter[i - 1] != 0 )
+                    break;
+        }
+        c = *input++;
+        *output++ = (unsigned char)( c ^ stream_block[n] );
+
+        n = (n + 1) % BLOWFISH_BLOCKSIZE;
+    }
+
+    *nc_off = n;
+
+    return( 0 );
+}
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+static const uint32_t S[4][256] = {
+    {   0xD1310BA6L, 0x98DFB5ACL, 0x2FFD72DBL, 0xD01ADFB7L,
+        0xB8E1AFEDL, 0x6A267E96L, 0xBA7C9045L, 0xF12C7F99L,
+        0x24A19947L, 0xB3916CF7L, 0x0801F2E2L, 0x858EFC16L,
+        0x636920D8L, 0x71574E69L, 0xA458FEA3L, 0xF4933D7EL,
+        0x0D95748FL, 0x728EB658L, 0x718BCD58L, 0x82154AEEL,
+        0x7B54A41DL, 0xC25A59B5L, 0x9C30D539L, 0x2AF26013L,
+        0xC5D1B023L, 0x286085F0L, 0xCA417918L, 0xB8DB38EFL,
+        0x8E79DCB0L, 0x603A180EL, 0x6C9E0E8BL, 0xB01E8A3EL,
+        0xD71577C1L, 0xBD314B27L, 0x78AF2FDAL, 0x55605C60L,
+        0xE65525F3L, 0xAA55AB94L, 0x57489862L, 0x63E81440L,
+        0x55CA396AL, 0x2AAB10B6L, 0xB4CC5C34L, 0x1141E8CEL,
+        0xA15486AFL, 0x7C72E993L, 0xB3EE1411L, 0x636FBC2AL,
+        0x2BA9C55DL, 0x741831F6L, 0xCE5C3E16L, 0x9B87931EL,
+        0xAFD6BA33L, 0x6C24CF5CL, 0x7A325381L, 0x28958677L,
+        0x3B8F4898L, 0x6B4BB9AFL, 0xC4BFE81BL, 0x66282193L,
+        0x61D809CCL, 0xFB21A991L, 0x487CAC60L, 0x5DEC8032L,
+        0xEF845D5DL, 0xE98575B1L, 0xDC262302L, 0xEB651B88L,
+        0x23893E81L, 0xD396ACC5L, 0x0F6D6FF3L, 0x83F44239L,
+        0x2E0B4482L, 0xA4842004L, 0x69C8F04AL, 0x9E1F9B5EL,
+        0x21C66842L, 0xF6E96C9AL, 0x670C9C61L, 0xABD388F0L,
+        0x6A51A0D2L, 0xD8542F68L, 0x960FA728L, 0xAB5133A3L,
+        0x6EEF0B6CL, 0x137A3BE4L, 0xBA3BF050L, 0x7EFB2A98L,
+        0xA1F1651DL, 0x39AF0176L, 0x66CA593EL, 0x82430E88L,
+        0x8CEE8619L, 0x456F9FB4L, 0x7D84A5C3L, 0x3B8B5EBEL,
+        0xE06F75D8L, 0x85C12073L, 0x401A449FL, 0x56C16AA6L,
+        0x4ED3AA62L, 0x363F7706L, 0x1BFEDF72L, 0x429B023DL,
+        0x37D0D724L, 0xD00A1248L, 0xDB0FEAD3L, 0x49F1C09BL,
+        0x075372C9L, 0x80991B7BL, 0x25D479D8L, 0xF6E8DEF7L,
+        0xE3FE501AL, 0xB6794C3BL, 0x976CE0BDL, 0x04C006BAL,
+        0xC1A94FB6L, 0x409F60C4L, 0x5E5C9EC2L, 0x196A2463L,
+        0x68FB6FAFL, 0x3E6C53B5L, 0x1339B2EBL, 0x3B52EC6FL,
+        0x6DFC511FL, 0x9B30952CL, 0xCC814544L, 0xAF5EBD09L,
+        0xBEE3D004L, 0xDE334AFDL, 0x660F2807L, 0x192E4BB3L,
+        0xC0CBA857L, 0x45C8740FL, 0xD20B5F39L, 0xB9D3FBDBL,
+        0x5579C0BDL, 0x1A60320AL, 0xD6A100C6L, 0x402C7279L,
+        0x679F25FEL, 0xFB1FA3CCL, 0x8EA5E9F8L, 0xDB3222F8L,
+        0x3C7516DFL, 0xFD616B15L, 0x2F501EC8L, 0xAD0552ABL,
+        0x323DB5FAL, 0xFD238760L, 0x53317B48L, 0x3E00DF82L,
+        0x9E5C57BBL, 0xCA6F8CA0L, 0x1A87562EL, 0xDF1769DBL,
+        0xD542A8F6L, 0x287EFFC3L, 0xAC6732C6L, 0x8C4F5573L,
+        0x695B27B0L, 0xBBCA58C8L, 0xE1FFA35DL, 0xB8F011A0L,
+        0x10FA3D98L, 0xFD2183B8L, 0x4AFCB56CL, 0x2DD1D35BL,
+        0x9A53E479L, 0xB6F84565L, 0xD28E49BCL, 0x4BFB9790L,
+        0xE1DDF2DAL, 0xA4CB7E33L, 0x62FB1341L, 0xCEE4C6E8L,
+        0xEF20CADAL, 0x36774C01L, 0xD07E9EFEL, 0x2BF11FB4L,
+        0x95DBDA4DL, 0xAE909198L, 0xEAAD8E71L, 0x6B93D5A0L,
+        0xD08ED1D0L, 0xAFC725E0L, 0x8E3C5B2FL, 0x8E7594B7L,
+        0x8FF6E2FBL, 0xF2122B64L, 0x8888B812L, 0x900DF01CL,
+        0x4FAD5EA0L, 0x688FC31CL, 0xD1CFF191L, 0xB3A8C1ADL,
+        0x2F2F2218L, 0xBE0E1777L, 0xEA752DFEL, 0x8B021FA1L,
+        0xE5A0CC0FL, 0xB56F74E8L, 0x18ACF3D6L, 0xCE89E299L,
+        0xB4A84FE0L, 0xFD13E0B7L, 0x7CC43B81L, 0xD2ADA8D9L,
+        0x165FA266L, 0x80957705L, 0x93CC7314L, 0x211A1477L,
+        0xE6AD2065L, 0x77B5FA86L, 0xC75442F5L, 0xFB9D35CFL,
+        0xEBCDAF0CL, 0x7B3E89A0L, 0xD6411BD3L, 0xAE1E7E49L,
+        0x00250E2DL, 0x2071B35EL, 0x226800BBL, 0x57B8E0AFL,
+        0x2464369BL, 0xF009B91EL, 0x5563911DL, 0x59DFA6AAL,
+        0x78C14389L, 0xD95A537FL, 0x207D5BA2L, 0x02E5B9C5L,
+        0x83260376L, 0x6295CFA9L, 0x11C81968L, 0x4E734A41L,
+        0xB3472DCAL, 0x7B14A94AL, 0x1B510052L, 0x9A532915L,
+        0xD60F573FL, 0xBC9BC6E4L, 0x2B60A476L, 0x81E67400L,
+        0x08BA6FB5L, 0x571BE91FL, 0xF296EC6BL, 0x2A0DD915L,
+        0xB6636521L, 0xE7B9F9B6L, 0xFF34052EL, 0xC5855664L,
+        0x53B02D5DL, 0xA99F8FA1L, 0x08BA4799L, 0x6E85076AL   },
+    {   0x4B7A70E9L, 0xB5B32944L, 0xDB75092EL, 0xC4192623L,
+        0xAD6EA6B0L, 0x49A7DF7DL, 0x9CEE60B8L, 0x8FEDB266L,
+        0xECAA8C71L, 0x699A17FFL, 0x5664526CL, 0xC2B19EE1L,
+        0x193602A5L, 0x75094C29L, 0xA0591340L, 0xE4183A3EL,
+        0x3F54989AL, 0x5B429D65L, 0x6B8FE4D6L, 0x99F73FD6L,
+        0xA1D29C07L, 0xEFE830F5L, 0x4D2D38E6L, 0xF0255DC1L,
+        0x4CDD2086L, 0x8470EB26L, 0x6382E9C6L, 0x021ECC5EL,
+        0x09686B3FL, 0x3EBAEFC9L, 0x3C971814L, 0x6B6A70A1L,
+        0x687F3584L, 0x52A0E286L, 0xB79C5305L, 0xAA500737L,
+        0x3E07841CL, 0x7FDEAE5CL, 0x8E7D44ECL, 0x5716F2B8L,
+        0xB03ADA37L, 0xF0500C0DL, 0xF01C1F04L, 0x0200B3FFL,
+        0xAE0CF51AL, 0x3CB574B2L, 0x25837A58L, 0xDC0921BDL,
+        0xD19113F9L, 0x7CA92FF6L, 0x94324773L, 0x22F54701L,
+        0x3AE5E581L, 0x37C2DADCL, 0xC8B57634L, 0x9AF3DDA7L,
+        0xA9446146L, 0x0FD0030EL, 0xECC8C73EL, 0xA4751E41L,
+        0xE238CD99L, 0x3BEA0E2FL, 0x3280BBA1L, 0x183EB331L,
+        0x4E548B38L, 0x4F6DB908L, 0x6F420D03L, 0xF60A04BFL,
+        0x2CB81290L, 0x24977C79L, 0x5679B072L, 0xBCAF89AFL,
+        0xDE9A771FL, 0xD9930810L, 0xB38BAE12L, 0xDCCF3F2EL,
+        0x5512721FL, 0x2E6B7124L, 0x501ADDE6L, 0x9F84CD87L,
+        0x7A584718L, 0x7408DA17L, 0xBC9F9ABCL, 0xE94B7D8CL,
+        0xEC7AEC3AL, 0xDB851DFAL, 0x63094366L, 0xC464C3D2L,
+        0xEF1C1847L, 0x3215D908L, 0xDD433B37L, 0x24C2BA16L,
+        0x12A14D43L, 0x2A65C451L, 0x50940002L, 0x133AE4DDL,
+        0x71DFF89EL, 0x10314E55L, 0x81AC77D6L, 0x5F11199BL,
+        0x043556F1L, 0xD7A3C76BL, 0x3C11183BL, 0x5924A509L,
+        0xF28FE6EDL, 0x97F1FBFAL, 0x9EBABF2CL, 0x1E153C6EL,
+        0x86E34570L, 0xEAE96FB1L, 0x860E5E0AL, 0x5A3E2AB3L,
+        0x771FE71CL, 0x4E3D06FAL, 0x2965DCB9L, 0x99E71D0FL,
+        0x803E89D6L, 0x5266C825L, 0x2E4CC978L, 0x9C10B36AL,
+        0xC6150EBAL, 0x94E2EA78L, 0xA5FC3C53L, 0x1E0A2DF4L,
+        0xF2F74EA7L, 0x361D2B3DL, 0x1939260FL, 0x19C27960L,
+        0x5223A708L, 0xF71312B6L, 0xEBADFE6EL, 0xEAC31F66L,
+        0xE3BC4595L, 0xA67BC883L, 0xB17F37D1L, 0x018CFF28L,
+        0xC332DDEFL, 0xBE6C5AA5L, 0x65582185L, 0x68AB9802L,
+        0xEECEA50FL, 0xDB2F953BL, 0x2AEF7DADL, 0x5B6E2F84L,
+        0x1521B628L, 0x29076170L, 0xECDD4775L, 0x619F1510L,
+        0x13CCA830L, 0xEB61BD96L, 0x0334FE1EL, 0xAA0363CFL,
+        0xB5735C90L, 0x4C70A239L, 0xD59E9E0BL, 0xCBAADE14L,
+        0xEECC86BCL, 0x60622CA7L, 0x9CAB5CABL, 0xB2F3846EL,
+        0x648B1EAFL, 0x19BDF0CAL, 0xA02369B9L, 0x655ABB50L,
+        0x40685A32L, 0x3C2AB4B3L, 0x319EE9D5L, 0xC021B8F7L,
+        0x9B540B19L, 0x875FA099L, 0x95F7997EL, 0x623D7DA8L,
+        0xF837889AL, 0x97E32D77L, 0x11ED935FL, 0x16681281L,
+        0x0E358829L, 0xC7E61FD6L, 0x96DEDFA1L, 0x7858BA99L,
+        0x57F584A5L, 0x1B227263L, 0x9B83C3FFL, 0x1AC24696L,
+        0xCDB30AEBL, 0x532E3054L, 0x8FD948E4L, 0x6DBC3128L,
+        0x58EBF2EFL, 0x34C6FFEAL, 0xFE28ED61L, 0xEE7C3C73L,
+        0x5D4A14D9L, 0xE864B7E3L, 0x42105D14L, 0x203E13E0L,
+        0x45EEE2B6L, 0xA3AAABEAL, 0xDB6C4F15L, 0xFACB4FD0L,
+        0xC742F442L, 0xEF6ABBB5L, 0x654F3B1DL, 0x41CD2105L,
+        0xD81E799EL, 0x86854DC7L, 0xE44B476AL, 0x3D816250L,
+        0xCF62A1F2L, 0x5B8D2646L, 0xFC8883A0L, 0xC1C7B6A3L,
+        0x7F1524C3L, 0x69CB7492L, 0x47848A0BL, 0x5692B285L,
+        0x095BBF00L, 0xAD19489DL, 0x1462B174L, 0x23820E00L,
+        0x58428D2AL, 0x0C55F5EAL, 0x1DADF43EL, 0x233F7061L,
+        0x3372F092L, 0x8D937E41L, 0xD65FECF1L, 0x6C223BDBL,
+        0x7CDE3759L, 0xCBEE7460L, 0x4085F2A7L, 0xCE77326EL,
+        0xA6078084L, 0x19F8509EL, 0xE8EFD855L, 0x61D99735L,
+        0xA969A7AAL, 0xC50C06C2L, 0x5A04ABFCL, 0x800BCADCL,
+        0x9E447A2EL, 0xC3453484L, 0xFDD56705L, 0x0E1E9EC9L,
+        0xDB73DBD3L, 0x105588CDL, 0x675FDA79L, 0xE3674340L,
+        0xC5C43465L, 0x713E38D8L, 0x3D28F89EL, 0xF16DFF20L,
+        0x153E21E7L, 0x8FB03D4AL, 0xE6E39F2BL, 0xDB83ADF7L   },
+    {   0xE93D5A68L, 0x948140F7L, 0xF64C261CL, 0x94692934L,
+        0x411520F7L, 0x7602D4F7L, 0xBCF46B2EL, 0xD4A20068L,
+        0xD4082471L, 0x3320F46AL, 0x43B7D4B7L, 0x500061AFL,
+        0x1E39F62EL, 0x97244546L, 0x14214F74L, 0xBF8B8840L,
+        0x4D95FC1DL, 0x96B591AFL, 0x70F4DDD3L, 0x66A02F45L,
+        0xBFBC09ECL, 0x03BD9785L, 0x7FAC6DD0L, 0x31CB8504L,
+        0x96EB27B3L, 0x55FD3941L, 0xDA2547E6L, 0xABCA0A9AL,
+        0x28507825L, 0x530429F4L, 0x0A2C86DAL, 0xE9B66DFBL,
+        0x68DC1462L, 0xD7486900L, 0x680EC0A4L, 0x27A18DEEL,
+        0x4F3FFEA2L, 0xE887AD8CL, 0xB58CE006L, 0x7AF4D6B6L,
+        0xAACE1E7CL, 0xD3375FECL, 0xCE78A399L, 0x406B2A42L,
+        0x20FE9E35L, 0xD9F385B9L, 0xEE39D7ABL, 0x3B124E8BL,
+        0x1DC9FAF7L, 0x4B6D1856L, 0x26A36631L, 0xEAE397B2L,
+        0x3A6EFA74L, 0xDD5B4332L, 0x6841E7F7L, 0xCA7820FBL,
+        0xFB0AF54EL, 0xD8FEB397L, 0x454056ACL, 0xBA489527L,
+        0x55533A3AL, 0x20838D87L, 0xFE6BA9B7L, 0xD096954BL,
+        0x55A867BCL, 0xA1159A58L, 0xCCA92963L, 0x99E1DB33L,
+        0xA62A4A56L, 0x3F3125F9L, 0x5EF47E1CL, 0x9029317CL,
+        0xFDF8E802L, 0x04272F70L, 0x80BB155CL, 0x05282CE3L,
+        0x95C11548L, 0xE4C66D22L, 0x48C1133FL, 0xC70F86DCL,
+        0x07F9C9EEL, 0x41041F0FL, 0x404779A4L, 0x5D886E17L,
+        0x325F51EBL, 0xD59BC0D1L, 0xF2BCC18FL, 0x41113564L,
+        0x257B7834L, 0x602A9C60L, 0xDFF8E8A3L, 0x1F636C1BL,
+        0x0E12B4C2L, 0x02E1329EL, 0xAF664FD1L, 0xCAD18115L,
+        0x6B2395E0L, 0x333E92E1L, 0x3B240B62L, 0xEEBEB922L,
+        0x85B2A20EL, 0xE6BA0D99L, 0xDE720C8CL, 0x2DA2F728L,
+        0xD0127845L, 0x95B794FDL, 0x647D0862L, 0xE7CCF5F0L,
+        0x5449A36FL, 0x877D48FAL, 0xC39DFD27L, 0xF33E8D1EL,
+        0x0A476341L, 0x992EFF74L, 0x3A6F6EABL, 0xF4F8FD37L,
+        0xA812DC60L, 0xA1EBDDF8L, 0x991BE14CL, 0xDB6E6B0DL,
+        0xC67B5510L, 0x6D672C37L, 0x2765D43BL, 0xDCD0E804L,
+        0xF1290DC7L, 0xCC00FFA3L, 0xB5390F92L, 0x690FED0BL,
+        0x667B9FFBL, 0xCEDB7D9CL, 0xA091CF0BL, 0xD9155EA3L,
+        0xBB132F88L, 0x515BAD24L, 0x7B9479BFL, 0x763BD6EBL,
+        0x37392EB3L, 0xCC115979L, 0x8026E297L, 0xF42E312DL,
+        0x6842ADA7L, 0xC66A2B3BL, 0x12754CCCL, 0x782EF11CL,
+        0x6A124237L, 0xB79251E7L, 0x06A1BBE6L, 0x4BFB6350L,
+        0x1A6B1018L, 0x11CAEDFAL, 0x3D25BDD8L, 0xE2E1C3C9L,
+        0x44421659L, 0x0A121386L, 0xD90CEC6EL, 0xD5ABEA2AL,
+        0x64AF674EL, 0xDA86A85FL, 0xBEBFE988L, 0x64E4C3FEL,
+        0x9DBC8057L, 0xF0F7C086L, 0x60787BF8L, 0x6003604DL,
+        0xD1FD8346L, 0xF6381FB0L, 0x7745AE04L, 0xD736FCCCL,
+        0x83426B33L, 0xF01EAB71L, 0xB0804187L, 0x3C005E5FL,
+        0x77A057BEL, 0xBDE8AE24L, 0x55464299L, 0xBF582E61L,
+        0x4E58F48FL, 0xF2DDFDA2L, 0xF474EF38L, 0x8789BDC2L,
+        0x5366F9C3L, 0xC8B38E74L, 0xB475F255L, 0x46FCD9B9L,
+        0x7AEB2661L, 0x8B1DDF84L, 0x846A0E79L, 0x915F95E2L,
+        0x466E598EL, 0x20B45770L, 0x8CD55591L, 0xC902DE4CL,
+        0xB90BACE1L, 0xBB8205D0L, 0x11A86248L, 0x7574A99EL,
+        0xB77F19B6L, 0xE0A9DC09L, 0x662D09A1L, 0xC4324633L,
+        0xE85A1F02L, 0x09F0BE8CL, 0x4A99A025L, 0x1D6EFE10L,
+        0x1AB93D1DL, 0x0BA5A4DFL, 0xA186F20FL, 0x2868F169L,
+        0xDCB7DA83L, 0x573906FEL, 0xA1E2CE9BL, 0x4FCD7F52L,
+        0x50115E01L, 0xA70683FAL, 0xA002B5C4L, 0x0DE6D027L,
+        0x9AF88C27L, 0x773F8641L, 0xC3604C06L, 0x61A806B5L,
+        0xF0177A28L, 0xC0F586E0L, 0x006058AAL, 0x30DC7D62L,
+        0x11E69ED7L, 0x2338EA63L, 0x53C2DD94L, 0xC2C21634L,
+        0xBBCBEE56L, 0x90BCB6DEL, 0xEBFC7DA1L, 0xCE591D76L,
+        0x6F05E409L, 0x4B7C0188L, 0x39720A3DL, 0x7C927C24L,
+        0x86E3725FL, 0x724D9DB9L, 0x1AC15BB4L, 0xD39EB8FCL,
+        0xED545578L, 0x08FCA5B5L, 0xD83D7CD3L, 0x4DAD0FC4L,
+        0x1E50EF5EL, 0xB161E6F8L, 0xA28514D9L, 0x6C51133CL,
+        0x6FD5C7E7L, 0x56E14EC4L, 0x362ABFCEL, 0xDDC6C837L,
+        0xD79A3234L, 0x92638212L, 0x670EFA8EL, 0x406000E0L  },
+    {   0x3A39CE37L, 0xD3FAF5CFL, 0xABC27737L, 0x5AC52D1BL,
+        0x5CB0679EL, 0x4FA33742L, 0xD3822740L, 0x99BC9BBEL,
+        0xD5118E9DL, 0xBF0F7315L, 0xD62D1C7EL, 0xC700C47BL,
+        0xB78C1B6BL, 0x21A19045L, 0xB26EB1BEL, 0x6A366EB4L,
+        0x5748AB2FL, 0xBC946E79L, 0xC6A376D2L, 0x6549C2C8L,
+        0x530FF8EEL, 0x468DDE7DL, 0xD5730A1DL, 0x4CD04DC6L,
+        0x2939BBDBL, 0xA9BA4650L, 0xAC9526E8L, 0xBE5EE304L,
+        0xA1FAD5F0L, 0x6A2D519AL, 0x63EF8CE2L, 0x9A86EE22L,
+        0xC089C2B8L, 0x43242EF6L, 0xA51E03AAL, 0x9CF2D0A4L,
+        0x83C061BAL, 0x9BE96A4DL, 0x8FE51550L, 0xBA645BD6L,
+        0x2826A2F9L, 0xA73A3AE1L, 0x4BA99586L, 0xEF5562E9L,
+        0xC72FEFD3L, 0xF752F7DAL, 0x3F046F69L, 0x77FA0A59L,
+        0x80E4A915L, 0x87B08601L, 0x9B09E6ADL, 0x3B3EE593L,
+        0xE990FD5AL, 0x9E34D797L, 0x2CF0B7D9L, 0x022B8B51L,
+        0x96D5AC3AL, 0x017DA67DL, 0xD1CF3ED6L, 0x7C7D2D28L,
+        0x1F9F25CFL, 0xADF2B89BL, 0x5AD6B472L, 0x5A88F54CL,
+        0xE029AC71L, 0xE019A5E6L, 0x47B0ACFDL, 0xED93FA9BL,
+        0xE8D3C48DL, 0x283B57CCL, 0xF8D56629L, 0x79132E28L,
+        0x785F0191L, 0xED756055L, 0xF7960E44L, 0xE3D35E8CL,
+        0x15056DD4L, 0x88F46DBAL, 0x03A16125L, 0x0564F0BDL,
+        0xC3EB9E15L, 0x3C9057A2L, 0x97271AECL, 0xA93A072AL,
+        0x1B3F6D9BL, 0x1E6321F5L, 0xF59C66FBL, 0x26DCF319L,
+        0x7533D928L, 0xB155FDF5L, 0x03563482L, 0x8ABA3CBBL,
+        0x28517711L, 0xC20AD9F8L, 0xABCC5167L, 0xCCAD925FL,
+        0x4DE81751L, 0x3830DC8EL, 0x379D5862L, 0x9320F991L,
+        0xEA7A90C2L, 0xFB3E7BCEL, 0x5121CE64L, 0x774FBE32L,
+        0xA8B6E37EL, 0xC3293D46L, 0x48DE5369L, 0x6413E680L,
+        0xA2AE0810L, 0xDD6DB224L, 0x69852DFDL, 0x09072166L,
+        0xB39A460AL, 0x6445C0DDL, 0x586CDECFL, 0x1C20C8AEL,
+        0x5BBEF7DDL, 0x1B588D40L, 0xCCD2017FL, 0x6BB4E3BBL,
+        0xDDA26A7EL, 0x3A59FF45L, 0x3E350A44L, 0xBCB4CDD5L,
+        0x72EACEA8L, 0xFA6484BBL, 0x8D6612AEL, 0xBF3C6F47L,
+        0xD29BE463L, 0x542F5D9EL, 0xAEC2771BL, 0xF64E6370L,
+        0x740E0D8DL, 0xE75B1357L, 0xF8721671L, 0xAF537D5DL,
+        0x4040CB08L, 0x4EB4E2CCL, 0x34D2466AL, 0x0115AF84L,
+        0xE1B00428L, 0x95983A1DL, 0x06B89FB4L, 0xCE6EA048L,
+        0x6F3F3B82L, 0x3520AB82L, 0x011A1D4BL, 0x277227F8L,
+        0x611560B1L, 0xE7933FDCL, 0xBB3A792BL, 0x344525BDL,
+        0xA08839E1L, 0x51CE794BL, 0x2F32C9B7L, 0xA01FBAC9L,
+        0xE01CC87EL, 0xBCC7D1F6L, 0xCF0111C3L, 0xA1E8AAC7L,
+        0x1A908749L, 0xD44FBD9AL, 0xD0DADECBL, 0xD50ADA38L,
+        0x0339C32AL, 0xC6913667L, 0x8DF9317CL, 0xE0B12B4FL,
+        0xF79E59B7L, 0x43F5BB3AL, 0xF2D519FFL, 0x27D9459CL,
+        0xBF97222CL, 0x15E6FC2AL, 0x0F91FC71L, 0x9B941525L,
+        0xFAE59361L, 0xCEB69CEBL, 0xC2A86459L, 0x12BAA8D1L,
+        0xB6C1075EL, 0xE3056A0CL, 0x10D25065L, 0xCB03A442L,
+        0xE0EC6E0EL, 0x1698DB3BL, 0x4C98A0BEL, 0x3278E964L,
+        0x9F1F9532L, 0xE0D392DFL, 0xD3A0342BL, 0x8971F21EL,
+        0x1B0A7441L, 0x4BA3348CL, 0xC5BE7120L, 0xC37632D8L,
+        0xDF359F8DL, 0x9B992F2EL, 0xE60B6F47L, 0x0FE3F11DL,
+        0xE54CDA54L, 0x1EDAD891L, 0xCE6279CFL, 0xCD3E7E6FL,
+        0x1618B166L, 0xFD2C1D05L, 0x848FD2C5L, 0xF6FB2299L,
+        0xF523F357L, 0xA6327623L, 0x93A83531L, 0x56CCCD02L,
+        0xACF08162L, 0x5A75EBB5L, 0x6E163697L, 0x88D273CCL,
+        0xDE966292L, 0x81B949D0L, 0x4C50901BL, 0x71C65614L,
+        0xE6C6C7BDL, 0x327A140AL, 0x45E1D006L, 0xC3F27B9AL,
+        0xC9AA53FDL, 0x62A80F00L, 0xBB25BFE2L, 0x35BDD2F6L,
+        0x71126905L, 0xB2040222L, 0xB6CBCF7CL, 0xCD769C2BL,
+        0x53113EC0L, 0x1640E3D3L, 0x38ABBD60L, 0x2547ADF0L,
+        0xBA38209CL, 0xF746CE76L, 0x77AFA1C5L, 0x20756060L,
+        0x85CBFE4EL, 0x8AE88DD8L, 0x7AAAF9B0L, 0x4CF9AA7EL,
+        0x1948C25CL, 0x02FB8A8CL, 0x01C36AE4L, 0xD6EBE1F9L,
+        0x90D4F869L, 0xA65CDEA0L, 0x3F09252DL, 0xC208E69FL,
+        0xB74E6132L, 0xCE77E25BL, 0x578FDFE3L, 0x3AC372E6L  }
+};
+
+#endif /* !POLARSSL_BLOWFISH_ALT */
+#endif /* POLARSSL_BLOWFISH_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/camellia.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,1061 @@
+/*
+ *  Camellia implementation
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  The Camellia block cipher was designed by NTT and Mitsubishi Electric
+ *  Corporation.
+ *
+ *  http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/01espec.pdf
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_CAMELLIA_C)
+
+#include "polarssl/camellia.h"
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
+#if !defined(POLARSSL_CAMELLIA_ALT)
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i)                            \
+{                                                       \
+    (n) = ( (uint32_t) (b)[(i)    ] << 24 )             \
+        | ( (uint32_t) (b)[(i) + 1] << 16 )             \
+        | ( (uint32_t) (b)[(i) + 2] <<  8 )             \
+        | ( (uint32_t) (b)[(i) + 3]       );            \
+}
+#endif
+
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i)                            \
+{                                                       \
+    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
+    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
+    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
+    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
+}
+#endif
+
+static const unsigned char SIGMA_CHARS[6][8] =
+{
+    { 0xa0, 0x9e, 0x66, 0x7f, 0x3b, 0xcc, 0x90, 0x8b },
+    { 0xb6, 0x7a, 0xe8, 0x58, 0x4c, 0xaa, 0x73, 0xb2 },
+    { 0xc6, 0xef, 0x37, 0x2f, 0xe9, 0x4f, 0x82, 0xbe },
+    { 0x54, 0xff, 0x53, 0xa5, 0xf1, 0xd3, 0x6f, 0x1c },
+    { 0x10, 0xe5, 0x27, 0xfa, 0xde, 0x68, 0x2d, 0x1d },
+    { 0xb0, 0x56, 0x88, 0xc2, 0xb3, 0xe6, 0xc1, 0xfd }
+};
+
+#if defined(POLARSSL_CAMELLIA_SMALL_MEMORY)
+
+static const unsigned char FSb[256] =
+{
+    112,130, 44,236,179, 39,192,229,228,133, 87, 53,234, 12,174, 65,
+     35,239,107,147, 69, 25,165, 33,237, 14, 79, 78, 29,101,146,189,
+    134,184,175,143,124,235, 31,206, 62, 48,220, 95, 94,197, 11, 26,
+    166,225, 57,202,213, 71, 93, 61,217,  1, 90,214, 81, 86,108, 77,
+    139, 13,154,102,251,204,176, 45,116, 18, 43, 32,240,177,132,153,
+    223, 76,203,194, 52,126,118,  5,109,183,169, 49,209, 23,  4,215,
+     20, 88, 58, 97,222, 27, 17, 28, 50, 15,156, 22, 83, 24,242, 34,
+    254, 68,207,178,195,181,122,145, 36,  8,232,168, 96,252,105, 80,
+    170,208,160,125,161,137, 98,151, 84, 91, 30,149,224,255,100,210,
+     16,196,  0, 72,163,247,117,219,138,  3,230,218,  9, 63,221,148,
+    135, 92,131,  2,205, 74,144, 51,115,103,246,243,157,127,191,226,
+     82,155,216, 38,200, 55,198, 59,129,150,111, 75, 19,190, 99, 46,
+    233,121,167,140,159,110,188,142, 41,245,249,182, 47,253,180, 89,
+    120,152,  6,106,231, 70,113,186,212, 37,171, 66,136,162,141,250,
+    114,  7,185, 85,248,238,172, 10, 54, 73, 42,104, 60, 56,241,164,
+     64, 40,211,123,187,201, 67,193, 21,227,173,244,119,199,128,158
+};
+
+#define SBOX1(n) FSb[(n)]
+#define SBOX2(n) (unsigned char)((FSb[(n)] >> 7 ^ FSb[(n)] << 1) & 0xff)
+#define SBOX3(n) (unsigned char)((FSb[(n)] >> 1 ^ FSb[(n)] << 7) & 0xff)
+#define SBOX4(n) FSb[((n) << 1 ^ (n) >> 7) &0xff]
+
+#else /* POLARSSL_CAMELLIA_SMALL_MEMORY */
+
+static const unsigned char FSb[256] =
+{
+ 112, 130,  44, 236, 179,  39, 192, 229, 228, 133,  87,  53, 234,  12, 174,  65,
+  35, 239, 107, 147,  69,  25, 165,  33, 237,  14,  79,  78,  29, 101, 146, 189,
+ 134, 184, 175, 143, 124, 235,  31, 206,  62,  48, 220,  95,  94, 197,  11,  26,
+ 166, 225,  57, 202, 213,  71,  93,  61, 217,   1,  90, 214,  81,  86, 108,  77,
+ 139,  13, 154, 102, 251, 204, 176,  45, 116,  18,  43,  32, 240, 177, 132, 153,
+ 223,  76, 203, 194,  52, 126, 118,   5, 109, 183, 169,  49, 209,  23,   4, 215,
+  20,  88,  58,  97, 222,  27,  17,  28,  50,  15, 156,  22,  83,  24, 242,  34,
+ 254,  68, 207, 178, 195, 181, 122, 145,  36,   8, 232, 168,  96, 252, 105,  80,
+ 170, 208, 160, 125, 161, 137,  98, 151,  84,  91,  30, 149, 224, 255, 100, 210,
+  16, 196,   0,  72, 163, 247, 117, 219, 138,   3, 230, 218,   9,  63, 221, 148,
+ 135,  92, 131,   2, 205,  74, 144,  51, 115, 103, 246, 243, 157, 127, 191, 226,
+  82, 155, 216,  38, 200,  55, 198,  59, 129, 150, 111,  75,  19, 190,  99,  46,
+ 233, 121, 167, 140, 159, 110, 188, 142,  41, 245, 249, 182,  47, 253, 180,  89,
+ 120, 152,   6, 106, 231,  70, 113, 186, 212,  37, 171,  66, 136, 162, 141, 250,
+ 114,   7, 185,  85, 248, 238, 172,  10,  54,  73,  42, 104,  60,  56, 241, 164,
+ 64,  40, 211, 123, 187, 201,  67, 193,  21, 227, 173, 244, 119, 199, 128, 158
+};
+
+static const unsigned char FSb2[256] =
+{
+ 224,   5,  88, 217, 103,  78, 129, 203, 201,  11, 174, 106, 213,  24,  93, 130,
+  70, 223, 214,  39, 138,  50,  75,  66, 219,  28, 158, 156,  58, 202,  37, 123,
+  13, 113,  95,  31, 248, 215,  62, 157, 124,  96, 185, 190, 188, 139,  22,  52,
+  77, 195, 114, 149, 171, 142, 186, 122, 179,   2, 180, 173, 162, 172, 216, 154,
+  23,  26,  53, 204, 247, 153,  97,  90, 232,  36,  86,  64, 225,  99,   9,  51,
+ 191, 152, 151, 133, 104, 252, 236,  10, 218, 111,  83,  98, 163,  46,   8, 175,
+  40, 176, 116, 194, 189,  54,  34,  56, 100,  30,  57,  44, 166,  48, 229,  68,
+ 253, 136, 159, 101, 135, 107, 244,  35,  72,  16, 209,  81, 192, 249, 210, 160,
+  85, 161,  65, 250,  67,  19, 196,  47, 168, 182,  60,  43, 193, 255, 200, 165,
+  32, 137,   0, 144,  71, 239, 234, 183,  21,   6, 205, 181,  18, 126, 187,  41,
+  15, 184,   7,   4, 155, 148,  33, 102, 230, 206, 237, 231,  59, 254, 127, 197,
+ 164,  55, 177,  76, 145, 110, 141, 118,   3,  45, 222, 150,  38, 125, 198,  92,
+ 211, 242,  79,  25,  63, 220, 121,  29,  82, 235, 243, 109,  94, 251, 105, 178,
+ 240,  49,  12, 212, 207, 140, 226, 117, 169,  74,  87, 132,  17,  69,  27, 245,
+ 228,  14, 115, 170, 241, 221,  89,  20, 108, 146,  84, 208, 120, 112, 227,  73,
+ 128,  80, 167, 246, 119, 147, 134, 131,  42, 199,  91, 233, 238, 143,   1,  61
+};
+
+static const unsigned char FSb3[256] =
+{
+  56,  65,  22, 118, 217, 147,  96, 242, 114, 194, 171, 154, 117,   6,  87, 160,
+ 145, 247, 181, 201, 162, 140, 210, 144, 246,   7, 167,  39, 142, 178,  73, 222,
+  67,  92, 215, 199,  62, 245, 143, 103,  31,  24, 110, 175,  47, 226, 133,  13,
+  83, 240, 156, 101, 234, 163, 174, 158, 236, 128,  45, 107, 168,  43,  54, 166,
+ 197, 134,  77,  51, 253, 102,  88, 150,  58,   9, 149,  16, 120, 216,  66, 204,
+ 239,  38, 229,  97,  26,  63,  59, 130, 182, 219, 212, 152, 232, 139,   2, 235,
+  10,  44,  29, 176, 111, 141, 136,  14,  25, 135,  78,  11, 169,  12, 121,  17,
+ 127,  34, 231,  89, 225, 218,  61, 200,  18,   4, 116,  84,  48, 126, 180,  40,
+  85, 104,  80, 190, 208, 196,  49, 203,  42, 173,  15, 202, 112, 255,  50, 105,
+   8,  98,   0,  36, 209, 251, 186, 237,  69, 129, 115, 109, 132, 159, 238,  74,
+ 195,  46, 193,   1, 230,  37,  72, 153, 185, 179, 123, 249, 206, 191, 223, 113,
+  41, 205, 108,  19, 100, 155,  99, 157, 192,  75, 183, 165, 137,  95, 177,  23,
+ 244, 188, 211,  70, 207,  55,  94,  71, 148, 250, 252,  91, 151, 254,  90, 172,
+  60,  76,   3,  53, 243,  35, 184,  93, 106, 146, 213,  33,  68,  81, 198, 125,
+  57, 131, 220, 170, 124, 119,  86,   5,  27, 164,  21,  52,  30,  28, 248,  82,
+  32,  20, 233, 189, 221, 228, 161, 224, 138, 241, 214, 122, 187, 227,  64,  79
+};
+
+static const unsigned char FSb4[256] =
+{
+ 112,  44, 179, 192, 228,  87, 234, 174,  35, 107,  69, 165, 237,  79,  29, 146,
+ 134, 175, 124,  31,  62, 220,  94,  11, 166,  57, 213,  93, 217,  90,  81, 108,
+ 139, 154, 251, 176, 116,  43, 240, 132, 223, 203,  52, 118, 109, 169, 209,   4,
+  20,  58, 222,  17,  50, 156,  83, 242, 254, 207, 195, 122,  36, 232,  96, 105,
+ 170, 160, 161,  98,  84,  30, 224, 100,  16,   0, 163, 117, 138, 230,   9, 221,
+ 135, 131, 205, 144, 115, 246, 157, 191,  82, 216, 200, 198, 129, 111,  19,  99,
+ 233, 167, 159, 188,  41, 249,  47, 180, 120,   6, 231, 113, 212, 171, 136, 141,
+ 114, 185, 248, 172,  54,  42,  60, 241,  64, 211, 187,  67,  21, 173, 119, 128,
+ 130, 236,  39, 229, 133,  53,  12,  65, 239, 147,  25,  33,  14,  78, 101, 189,
+ 184, 143, 235, 206,  48,  95, 197,  26, 225, 202,  71,  61,   1, 214,  86,  77,
+  13, 102, 204,  45,  18,  32, 177, 153,  76, 194, 126,   5, 183,  49,  23, 215,
+  88,  97,  27,  28,  15,  22,  24,  34,  68, 178, 181, 145,   8, 168, 252,  80,
+ 208, 125, 137, 151,  91, 149, 255, 210, 196,  72, 247, 219,   3, 218,  63, 148,
+  92,   2,  74,  51, 103, 243, 127, 226, 155,  38,  55,  59, 150,  75, 190,  46,
+ 121, 140, 110, 142, 245, 182, 253,  89, 152, 106,  70, 186,  37,  66, 162, 250,
+  7,  85, 238,  10,  73, 104,  56, 164,  40, 123, 201, 193, 227, 244, 199, 158
+};
+
+#define SBOX1(n) FSb[(n)]
+#define SBOX2(n) FSb2[(n)]
+#define SBOX3(n) FSb3[(n)]
+#define SBOX4(n) FSb4[(n)]
+
+#endif /* POLARSSL_CAMELLIA_SMALL_MEMORY */
+
+static const unsigned char shifts[2][4][4] =
+{
+    {
+        { 1, 1, 1, 1 }, /* KL */
+        { 0, 0, 0, 0 }, /* KR */
+        { 1, 1, 1, 1 }, /* KA */
+        { 0, 0, 0, 0 }  /* KB */
+    },
+    {
+        { 1, 0, 1, 1 }, /* KL */
+        { 1, 1, 0, 1 }, /* KR */
+        { 1, 1, 1, 0 }, /* KA */
+        { 1, 1, 0, 1 }  /* KB */
+    }
+};
+
+static const signed char indexes[2][4][20] =
+{
+    {
+        {  0,  1,  2,  3,  8,  9, 10, 11, 38, 39,
+          36, 37, 23, 20, 21, 22, 27, -1, -1, 26 }, /* KL -> RK */
+        { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+          -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* KR -> RK */
+        {  4,  5,  6,  7, 12, 13, 14, 15, 16, 17,
+          18, 19, -1, 24, 25, -1, 31, 28, 29, 30 }, /* KA -> RK */
+        { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+          -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }  /* KB -> RK */
+    },
+    {
+        {  0,  1,  2,  3, 61, 62, 63, 60, -1, -1,
+          -1, -1, 27, 24, 25, 26, 35, 32, 33, 34 }, /* KL -> RK */
+        { -1, -1, -1, -1,  8,  9, 10, 11, 16, 17,
+          18, 19, -1, -1, -1, -1, 39, 36, 37, 38 }, /* KR -> RK */
+        { -1, -1, -1, -1, 12, 13, 14, 15, 58, 59,
+          56, 57, 31, 28, 29, 30, -1, -1, -1, -1 }, /* KA -> RK */
+        {  4,  5,  6,  7, 65, 66, 67, 64, 20, 21,
+          22, 23, -1, -1, -1, -1, 43, 40, 41, 42 }  /* KB -> RK */
+    }
+};
+
+static const signed char transposes[2][20] =
+{
+    {
+        21, 22, 23, 20,
+        -1, -1, -1, -1,
+        18, 19, 16, 17,
+        11,  8,  9, 10,
+        15, 12, 13, 14
+    },
+    {
+        25, 26, 27, 24,
+        29, 30, 31, 28,
+        18, 19, 16, 17,
+        -1, -1, -1, -1,
+        -1, -1, -1, -1
+    }
+};
+
+/* Shift macro for 128 bit strings with rotation smaller than 32 bits (!) */
+#define ROTL(DEST, SRC, SHIFT)                                      \
+{                                                                   \
+    (DEST)[0] = (SRC)[0] << (SHIFT) ^ (SRC)[1] >> (32 - (SHIFT));   \
+    (DEST)[1] = (SRC)[1] << (SHIFT) ^ (SRC)[2] >> (32 - (SHIFT));   \
+    (DEST)[2] = (SRC)[2] << (SHIFT) ^ (SRC)[3] >> (32 - (SHIFT));   \
+    (DEST)[3] = (SRC)[3] << (SHIFT) ^ (SRC)[0] >> (32 - (SHIFT));   \
+}
+
+#define FL(XL, XR, KL, KR)                                          \
+{                                                                   \
+    (XR) = ((((XL) & (KL)) << 1) | (((XL) & (KL)) >> 31)) ^ (XR);   \
+    (XL) = ((XR) | (KR)) ^ (XL);                                    \
+}
+
+#define FLInv(YL, YR, KL, KR)                                       \
+{                                                                   \
+    (YL) = ((YR) | (KR)) ^ (YL);                                    \
+    (YR) = ((((YL) & (KL)) << 1) | (((YL) & (KL)) >> 31)) ^ (YR);   \
+}
+
+#define SHIFT_AND_PLACE(INDEX, OFFSET)                      \
+{                                                           \
+    TK[0] = KC[(OFFSET) * 4 + 0];                           \
+    TK[1] = KC[(OFFSET) * 4 + 1];                           \
+    TK[2] = KC[(OFFSET) * 4 + 2];                           \
+    TK[3] = KC[(OFFSET) * 4 + 3];                           \
+                                                            \
+    for ( i = 1; i <= 4; i++ )                              \
+        if (shifts[(INDEX)][(OFFSET)][i -1])                \
+            ROTL(TK + i * 4, TK, (15 * i) % 32);            \
+                                                            \
+    for ( i = 0; i < 20; i++ )                              \
+        if (indexes[(INDEX)][(OFFSET)][i] != -1) {          \
+        RK[indexes[(INDEX)][(OFFSET)][i]] = TK[ i ];        \
+    }                                                       \
+}
+
+static void camellia_feistel( const uint32_t x[2], const uint32_t k[2],
+                              uint32_t z[2])
+{
+    uint32_t I0, I1;
+    I0 = x[0] ^ k[0];
+    I1 = x[1] ^ k[1];
+
+    I0 = (SBOX1((I0 >> 24) & 0xFF) << 24) |
+         (SBOX2((I0 >> 16) & 0xFF) << 16) |
+         (SBOX3((I0 >>  8) & 0xFF) <<  8) |
+         (SBOX4((I0      ) & 0xFF)      );
+    I1 = (SBOX2((I1 >> 24) & 0xFF) << 24) |
+         (SBOX3((I1 >> 16) & 0xFF) << 16) |
+         (SBOX4((I1 >>  8) & 0xFF) <<  8) |
+         (SBOX1((I1      ) & 0xFF)      );
+
+    I0 ^= (I1 << 8) | (I1 >> 24);
+    I1 ^= (I0 << 16) | (I0 >> 16);
+    I0 ^= (I1 >> 8) | (I1 << 24);
+    I1 ^= (I0 >> 8) | (I0 << 24);
+
+    z[0] ^= I1;
+    z[1] ^= I0;
+}
+
+/*
+ * Camellia key schedule (encryption)
+ */
+int camellia_setkey_enc( camellia_context *ctx, const unsigned char *key,
+                         unsigned int keysize )
+{
+    int idx;
+    size_t i;
+    uint32_t *RK;
+    unsigned char t[64];
+    uint32_t SIGMA[6][2];
+    uint32_t KC[16];
+    uint32_t TK[20];
+
+    RK = ctx->rk;
+
+    memset(t, 0, 64);
+    memset(RK, 0, sizeof(ctx->rk));
+
+    switch( keysize )
+    {
+        case 128: ctx->nr = 3; idx = 0; break;
+        case 192:
+        case 256: ctx->nr = 4; idx = 1; break;
+        default : return( POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH );
+    }
+
+    for( i = 0; i < keysize / 8; ++i)
+        t[i] = key[i];
+
+    if (keysize == 192) {
+        for (i = 0; i < 8; i++)
+            t[24 + i] = ~t[16 + i];
+    }
+
+    /*
+     * Prepare SIGMA values
+     */
+    for (i = 0; i < 6; i++) {
+        GET_UINT32_BE(SIGMA[i][0], SIGMA_CHARS[i], 0);
+        GET_UINT32_BE(SIGMA[i][1], SIGMA_CHARS[i], 4);
+    }
+
+    /*
+     * Key storage in KC
+     * Order: KL, KR, KA, KB
+     */
+    memset(KC, 0, sizeof(KC));
+
+    /* Store KL, KR */
+    for (i = 0; i < 8; i++)
+        GET_UINT32_BE(KC[i], t, i * 4);
+
+    /* Generate KA */
+    for( i = 0; i < 4; ++i)
+        KC[8 + i] = KC[i] ^ KC[4 + i];
+
+    camellia_feistel(KC + 8, SIGMA[0], KC + 10);
+    camellia_feistel(KC + 10, SIGMA[1], KC + 8);
+
+    for( i = 0; i < 4; ++i)
+        KC[8 + i] ^= KC[i];
+
+    camellia_feistel(KC + 8, SIGMA[2], KC + 10);
+    camellia_feistel(KC + 10, SIGMA[3], KC + 8);
+
+    if (keysize > 128) {
+        /* Generate KB */
+        for( i = 0; i < 4; ++i)
+            KC[12 + i] = KC[4 + i] ^ KC[8 + i];
+
+        camellia_feistel(KC + 12, SIGMA[4], KC + 14);
+        camellia_feistel(KC + 14, SIGMA[5], KC + 12);
+    }
+
+    /*
+     * Generating subkeys
+     */
+
+    /* Manipulating KL */
+    SHIFT_AND_PLACE(idx, 0);
+
+    /* Manipulating KR */
+    if (keysize > 128) {
+        SHIFT_AND_PLACE(idx, 1);
+    }
+
+    /* Manipulating KA */
+    SHIFT_AND_PLACE(idx, 2);
+
+    /* Manipulating KB */
+    if (keysize > 128) {
+        SHIFT_AND_PLACE(idx, 3);
+    }
+
+    /* Do transpositions */
+    for ( i = 0; i < 20; i++ ) {
+        if (transposes[idx][i] != -1) {
+            RK[32 + 12 * idx + i] = RK[transposes[idx][i]];
+        }
+    }
+
+    return( 0 );
+}
+
+/*
+ * Camellia key schedule (decryption)
+ */
+int camellia_setkey_dec( camellia_context *ctx, const unsigned char *key,
+                         unsigned int keysize )
+{
+    int idx;
+    size_t i;
+    camellia_context cty;
+    uint32_t *RK;
+    uint32_t *SK;
+    int ret;
+
+    switch( keysize )
+    {
+        case 128: ctx->nr = 3; idx = 0; break;
+        case 192:
+        case 256: ctx->nr = 4; idx = 1; break;
+        default : return( POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH );
+    }
+
+    RK = ctx->rk;
+
+    ret = camellia_setkey_enc(&cty, key, keysize);
+    if( ret != 0 )
+        return( ret );
+
+    SK = cty.rk + 24 * 2 + 8 * idx * 2;
+
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+
+    for (i = 22 + 8 * idx, SK -= 6; i > 0; i--, SK -= 4)
+    {
+        *RK++ = *SK++;
+        *RK++ = *SK++;
+    }
+
+    SK -= 2;
+
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+
+    memset( &cty, 0, sizeof( camellia_context ) );
+
+    return( 0 );
+}
+
+/*
+ * Camellia-ECB block encryption/decryption
+ */
+int camellia_crypt_ecb( camellia_context *ctx,
+                    int mode,
+                    const unsigned char input[16],
+                    unsigned char output[16] )
+{
+    int NR;
+    uint32_t *RK, X[4];
+
+    ( (void) mode );
+
+    NR = ctx->nr;
+    RK = ctx->rk;
+
+    GET_UINT32_BE( X[0], input,  0 );
+    GET_UINT32_BE( X[1], input,  4 );
+    GET_UINT32_BE( X[2], input,  8 );
+    GET_UINT32_BE( X[3], input, 12 );
+
+    X[0] ^= *RK++;
+    X[1] ^= *RK++;
+    X[2] ^= *RK++;
+    X[3] ^= *RK++;
+
+    while (NR) {
+        --NR;
+        camellia_feistel(X, RK, X + 2);
+        RK += 2;
+        camellia_feistel(X + 2, RK, X);
+        RK += 2;
+        camellia_feistel(X, RK, X + 2);
+        RK += 2;
+        camellia_feistel(X + 2, RK, X);
+        RK += 2;
+        camellia_feistel(X, RK, X + 2);
+        RK += 2;
+        camellia_feistel(X + 2, RK, X);
+        RK += 2;
+
+        if (NR) {
+            FL(X[0], X[1], RK[0], RK[1]);
+            RK += 2;
+            FLInv(X[2], X[3], RK[0], RK[1]);
+            RK += 2;
+        }
+    }
+
+    X[2] ^= *RK++;
+    X[3] ^= *RK++;
+    X[0] ^= *RK++;
+    X[1] ^= *RK++;
+
+    PUT_UINT32_BE( X[2], output,  0 );
+    PUT_UINT32_BE( X[3], output,  4 );
+    PUT_UINT32_BE( X[0], output,  8 );
+    PUT_UINT32_BE( X[1], output, 12 );
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+/*
+ * Camellia-CBC buffer encryption/decryption
+ */
+int camellia_crypt_cbc( camellia_context *ctx,
+                    int mode,
+                    size_t length,
+                    unsigned char iv[16],
+                    const unsigned char *input,
+                    unsigned char *output )
+{
+    int i;
+    unsigned char temp[16];
+
+    if( length % 16 )
+        return( POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH );
+
+    if( mode == CAMELLIA_DECRYPT )
+    {
+        while( length > 0 )
+        {
+            memcpy( temp, input, 16 );
+            camellia_crypt_ecb( ctx, mode, input, output );
+
+            for( i = 0; i < 16; i++ )
+                output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+            memcpy( iv, temp, 16 );
+
+            input  += 16;
+            output += 16;
+            length -= 16;
+        }
+    }
+    else
+    {
+        while( length > 0 )
+        {
+            for( i = 0; i < 16; i++ )
+                output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+            camellia_crypt_ecb( ctx, mode, output, output );
+            memcpy( iv, output, 16 );
+
+            input  += 16;
+            output += 16;
+            length -= 16;
+        }
+    }
+
+    return( 0 );
+}
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+/*
+ * Camellia-CFB128 buffer encryption/decryption
+ */
+int camellia_crypt_cfb128( camellia_context *ctx,
+                       int mode,
+                       size_t length,
+                       size_t *iv_off,
+                       unsigned char iv[16],
+                       const unsigned char *input,
+                       unsigned char *output )
+{
+    int c;
+    size_t n = *iv_off;
+
+    if( mode == CAMELLIA_DECRYPT )
+    {
+        while( length-- )
+        {
+            if( n == 0 )
+                camellia_crypt_ecb( ctx, CAMELLIA_ENCRYPT, iv, iv );
+
+            c = *input++;
+            *output++ = (unsigned char)( c ^ iv[n] );
+            iv[n] = (unsigned char) c;
+
+            n = (n + 1) & 0x0F;
+        }
+    }
+    else
+    {
+        while( length-- )
+        {
+            if( n == 0 )
+                camellia_crypt_ecb( ctx, CAMELLIA_ENCRYPT, iv, iv );
+
+            iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
+
+            n = (n + 1) & 0x0F;
+        }
+    }
+
+    *iv_off = n;
+
+    return( 0 );
+}
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+/*
+ * Camellia-CTR buffer encryption/decryption
+ */
+int camellia_crypt_ctr( 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 )
+{
+    int c, i;
+    size_t n = *nc_off;
+
+    while( length-- )
+    {
+        if( n == 0 ) {
+            camellia_crypt_ecb( ctx, CAMELLIA_ENCRYPT, nonce_counter,
+                                stream_block );
+
+            for( i = 16; i > 0; i-- )
+                if( ++nonce_counter[i - 1] != 0 )
+                    break;
+        }
+        c = *input++;
+        *output++ = (unsigned char)( c ^ stream_block[n] );
+
+        n = (n + 1) & 0x0F;
+    }
+
+    *nc_off = n;
+
+    return( 0 );
+}
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+#endif /* !POLARSSL_CAMELLIA_ALT */
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include <stdio.h>
+
+/*
+ * Camellia test vectors from:
+ *
+ * http://info.isl.ntt.co.jp/crypt/eng/camellia/technology.html:
+ *   http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/intermediate.txt
+ *   http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/t_camellia.txt
+ *                      (For each bitlength: Key 0, Nr 39)
+ */
+#define CAMELLIA_TESTS_ECB  2
+
+static const unsigned char camellia_test_ecb_key[3][CAMELLIA_TESTS_ECB][32] =
+{
+    {
+        { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+          0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+    },
+    {
+        { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+          0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+          0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 },
+        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+    },
+    {
+        { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+          0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+          0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+          0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+    },
+};
+
+static const unsigned char camellia_test_ecb_plain[CAMELLIA_TESTS_ECB][16] =
+{
+    { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+      0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+    { 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+};
+
+static const unsigned char camellia_test_ecb_cipher[3][CAMELLIA_TESTS_ECB][16] =
+{
+    {
+        { 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73,
+          0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 },
+        { 0x38, 0x3C, 0x6C, 0x2A, 0xAB, 0xEF, 0x7F, 0xDE,
+          0x25, 0xCD, 0x47, 0x0B, 0xF7, 0x74, 0xA3, 0x31 }
+    },
+    {
+        { 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8,
+          0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 },
+        { 0xD1, 0x76, 0x3F, 0xC0, 0x19, 0xD7, 0x7C, 0xC9,
+          0x30, 0xBF, 0xF2, 0xA5, 0x6F, 0x7C, 0x93, 0x64 }
+    },
+    {
+        { 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c,
+          0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 },
+        { 0x05, 0x03, 0xFB, 0x10, 0xAB, 0x24, 0x1E, 0x7C,
+          0xF4, 0x5D, 0x8C, 0xDE, 0xEE, 0x47, 0x43, 0x35 }
+    }
+};
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+#define CAMELLIA_TESTS_CBC  3
+
+static const unsigned char camellia_test_cbc_key[3][32] =
+{
+        { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+          0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }
+    ,
+        { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52,
+          0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5,
+          0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }
+    ,
+        { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE,
+          0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,
+          0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,
+          0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 }
+};
+
+static const unsigned char camellia_test_cbc_iv[16] =
+
+    { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+      0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }
+;
+
+static const unsigned char camellia_test_cbc_plain[CAMELLIA_TESTS_CBC][16] =
+{
+    { 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,
+      0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A },
+    { 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,
+      0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51 },
+    { 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11,
+      0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF }
+
+};
+
+static const unsigned char camellia_test_cbc_cipher[3][CAMELLIA_TESTS_CBC][16] =
+{
+    {
+        { 0x16, 0x07, 0xCF, 0x49, 0x4B, 0x36, 0xBB, 0xF0,
+          0x0D, 0xAE, 0xB0, 0xB5, 0x03, 0xC8, 0x31, 0xAB },
+        { 0xA2, 0xF2, 0xCF, 0x67, 0x16, 0x29, 0xEF, 0x78,
+          0x40, 0xC5, 0xA5, 0xDF, 0xB5, 0x07, 0x48, 0x87 },
+        { 0x0F, 0x06, 0x16, 0x50, 0x08, 0xCF, 0x8B, 0x8B,
+          0x5A, 0x63, 0x58, 0x63, 0x62, 0x54, 0x3E, 0x54 }
+    },
+    {
+        { 0x2A, 0x48, 0x30, 0xAB, 0x5A, 0xC4, 0xA1, 0xA2,
+          0x40, 0x59, 0x55, 0xFD, 0x21, 0x95, 0xCF, 0x93 },
+        { 0x5D, 0x5A, 0x86, 0x9B, 0xD1, 0x4C, 0xE5, 0x42,
+          0x64, 0xF8, 0x92, 0xA6, 0xDD, 0x2E, 0xC3, 0xD5 },
+        { 0x37, 0xD3, 0x59, 0xC3, 0x34, 0x98, 0x36, 0xD8,
+          0x84, 0xE3, 0x10, 0xAD, 0xDF, 0x68, 0xC4, 0x49 }
+    },
+    {
+        { 0xE6, 0xCF, 0xA3, 0x5F, 0xC0, 0x2B, 0x13, 0x4A,
+          0x4D, 0x2C, 0x0B, 0x67, 0x37, 0xAC, 0x3E, 0xDA },
+        { 0x36, 0xCB, 0xEB, 0x73, 0xBD, 0x50, 0x4B, 0x40,
+          0x70, 0xB1, 0xB7, 0xDE, 0x2B, 0x21, 0xEB, 0x50 },
+        { 0xE3, 0x1A, 0x60, 0x55, 0x29, 0x7D, 0x96, 0xCA,
+          0x33, 0x30, 0xCD, 0xF1, 0xB1, 0x86, 0x0A, 0x83 }
+    }
+};
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+/*
+ * Camellia-CTR test vectors from:
+ *
+ * http://www.faqs.org/rfcs/rfc5528.html
+ */
+
+static const unsigned char camellia_test_ctr_key[3][16] =
+{
+    { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC,
+      0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E },
+    { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7,
+      0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 },
+    { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8,
+      0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC }
+};
+
+static const unsigned char camellia_test_ctr_nonce_counter[3][16] =
+{
+    { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+    { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59,
+      0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 },
+    { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F,
+      0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 }
+};
+
+static const unsigned char camellia_test_ctr_pt[3][48] =
+{
+    { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62,
+      0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 },
+
+    { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+      0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+      0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F },
+
+    { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+      0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+      0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+      0x20, 0x21, 0x22, 0x23 }
+};
+
+static const unsigned char camellia_test_ctr_ct[3][48] =
+{
+    { 0xD0, 0x9D, 0xC2, 0x9A, 0x82, 0x14, 0x61, 0x9A,
+      0x20, 0x87, 0x7C, 0x76, 0xDB, 0x1F, 0x0B, 0x3F },
+    { 0xDB, 0xF3, 0xC7, 0x8D, 0xC0, 0x83, 0x96, 0xD4,
+      0xDA, 0x7C, 0x90, 0x77, 0x65, 0xBB, 0xCB, 0x44,
+      0x2B, 0x8E, 0x8E, 0x0F, 0x31, 0xF0, 0xDC, 0xA7,
+      0x2C, 0x74, 0x17, 0xE3, 0x53, 0x60, 0xE0, 0x48 },
+    { 0xB1, 0x9D, 0x1F, 0xCD, 0xCB, 0x75, 0xEB, 0x88,
+      0x2F, 0x84, 0x9C, 0xE2, 0x4D, 0x85, 0xCF, 0x73,
+      0x9C, 0xE6, 0x4B, 0x2B, 0x5C, 0x9D, 0x73, 0xF1,
+      0x4F, 0x2D, 0x5D, 0x9D, 0xCE, 0x98, 0x89, 0xCD,
+      0xDF, 0x50, 0x86, 0x96 }
+};
+
+static const int camellia_test_ctr_len[3] =
+    { 16, 32, 36 };
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+/*
+ * Checkup routine
+ */
+int camellia_self_test( int verbose )
+{
+    int i, j, u, v;
+    unsigned char key[32];
+    unsigned char buf[64];
+    unsigned char src[16];
+    unsigned char dst[16];
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    unsigned char iv[16];
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+    size_t offset, len;
+    unsigned char nonce_counter[16];
+    unsigned char stream_block[16];
+#endif
+
+    camellia_context ctx;
+
+    memset( key, 0, 32 );
+
+    for (j = 0; j < 6; j++) {
+        u = j >> 1;
+    v = j & 1;
+
+    if( verbose != 0 )
+        polarssl_printf( "  CAMELLIA-ECB-%3d (%s): ", 128 + u * 64,
+                         (v == CAMELLIA_DECRYPT) ? "dec" : "enc");
+
+    for (i = 0; i < CAMELLIA_TESTS_ECB; i++ ) {
+        memcpy( key, camellia_test_ecb_key[u][i], 16 + 8 * u);
+
+        if (v == CAMELLIA_DECRYPT) {
+            camellia_setkey_dec(&ctx, key, 128 + u * 64);
+            memcpy(src, camellia_test_ecb_cipher[u][i], 16);
+            memcpy(dst, camellia_test_ecb_plain[i], 16);
+        } else { /* CAMELLIA_ENCRYPT */
+            camellia_setkey_enc(&ctx, key, 128 + u * 64);
+            memcpy(src, camellia_test_ecb_plain[i], 16);
+            memcpy(dst, camellia_test_ecb_cipher[u][i], 16);
+        }
+
+        camellia_crypt_ecb(&ctx, v, src, buf);
+
+        if( memcmp( buf, dst, 16 ) != 0 )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed\n" );
+
+            return( 1 );
+        }
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    /*
+     * CBC mode
+     */
+    for( j = 0; j < 6; j++ )
+    {
+        u = j >> 1;
+        v = j  & 1;
+
+        if( verbose != 0 )
+            polarssl_printf( "  CAMELLIA-CBC-%3d (%s): ", 128 + u * 64,
+                             ( v == CAMELLIA_DECRYPT ) ? "dec" : "enc" );
+
+    memcpy( src, camellia_test_cbc_iv, 16);
+    memcpy( dst, camellia_test_cbc_iv, 16);
+    memcpy( key, camellia_test_cbc_key[u], 16 + 8 * u);
+
+    if (v == CAMELLIA_DECRYPT) {
+        camellia_setkey_dec(&ctx, key, 128 + u * 64);
+    } else {
+        camellia_setkey_enc(&ctx, key, 128 + u * 64);
+    }
+
+    for (i = 0; i < CAMELLIA_TESTS_CBC; i++ ) {
+
+        if (v == CAMELLIA_DECRYPT) {
+            memcpy( iv , src, 16 );
+            memcpy(src, camellia_test_cbc_cipher[u][i], 16);
+            memcpy(dst, camellia_test_cbc_plain[i], 16);
+        } else { /* CAMELLIA_ENCRYPT */
+            memcpy( iv , dst, 16 );
+            memcpy(src, camellia_test_cbc_plain[i], 16);
+            memcpy(dst, camellia_test_cbc_cipher[u][i], 16);
+        }
+
+        camellia_crypt_cbc(&ctx, v, 16, iv, src, buf);
+
+        if( memcmp( buf, dst, 16 ) != 0 )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed\n" );
+
+            return( 1 );
+        }
+    }
+
+        if( verbose != 0 )
+            polarssl_printf( "passed\n" );
+    }
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+    /*
+     * CTR mode
+     */
+    for( i = 0; i < 6; i++ )
+    {
+        u = i >> 1;
+        v = i  & 1;
+
+        if( verbose != 0 )
+            polarssl_printf( "  CAMELLIA-CTR-128 (%s): ",
+                             ( v == CAMELLIA_DECRYPT ) ? "dec" : "enc" );
+
+        memcpy( nonce_counter, camellia_test_ctr_nonce_counter[u], 16 );
+        memcpy( key, camellia_test_ctr_key[u], 16 );
+
+        offset = 0;
+        camellia_setkey_enc( &ctx, key, 128 );
+
+        if( v == CAMELLIA_DECRYPT )
+        {
+            len = camellia_test_ctr_len[u];
+            memcpy( buf, camellia_test_ctr_ct[u], len );
+
+            camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block,
+                                buf, buf );
+
+            if( memcmp( buf, camellia_test_ctr_pt[u], len ) != 0 )
+            {
+                if( verbose != 0 )
+                    polarssl_printf( "failed\n" );
+
+                return( 1 );
+            }
+        }
+        else
+        {
+            len = camellia_test_ctr_len[u];
+            memcpy( buf, camellia_test_ctr_pt[u], len );
+
+            camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block,
+                                buf, buf );
+
+            if( memcmp( buf, camellia_test_ctr_ct[u], len ) != 0 )
+            {
+                if( verbose != 0 )
+                    polarssl_printf( "failed\n" );
+
+                return( 1 );
+            }
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+    return ( 0 );
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_CAMELLIA_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/certs.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,312 @@
+/*
+ *  X.509 test certificates
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_CERTS_C)
+
+#if defined(POLARSSL_ECDSA_C)
+#define TEST_CA_CRT_EC                                                  \
+"-----BEGIN CERTIFICATE-----\r\n"                                       \
+"MIICUjCCAdegAwIBAgIJAMFD4n5iQ8zoMAoGCCqGSM49BAMCMD4xCzAJBgNVBAYT\r\n"  \
+"Ak5MMREwDwYDVQQKEwhQb2xhclNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBF\r\n"  \
+"QyBDQTAeFw0xMzA5MjQxNTQ5NDhaFw0yMzA5MjIxNTQ5NDhaMD4xCzAJBgNVBAYT\r\n"  \
+"Ak5MMREwDwYDVQQKEwhQb2xhclNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBF\r\n"  \
+"QyBDQTB2MBAGByqGSM49AgEGBSuBBAAiA2IABMPaKzRBN1gvh1b+/Im6KUNLTuBu\r\n"  \
+"ww5XUzM5WNRStJGVOQsj318XJGJI/BqVKc4sLYfCiFKAr9ZqqyHduNMcbli4yuiy\r\n"  \
+"aY7zQa0pw7RfdadHb9UZKVVpmlM7ILRmFmAzHqOBoDCBnTAdBgNVHQ4EFgQUnW0g\r\n"  \
+"JEkBPyvLeLUZvH4kydv7NnwwbgYDVR0jBGcwZYAUnW0gJEkBPyvLeLUZvH4kydv7\r\n"  \
+"NnyhQqRAMD4xCzAJBgNVBAYTAk5MMREwDwYDVQQKEwhQb2xhclNTTDEcMBoGA1UE\r\n"  \
+"AxMTUG9sYXJzc2wgVGVzdCBFQyBDQYIJAMFD4n5iQ8zoMAwGA1UdEwQFMAMBAf8w\r\n"  \
+"CgYIKoZIzj0EAwIDaQAwZgIxAMO0YnNWKJUAfXgSJtJxexn4ipg+kv4znuR50v56\r\n"  \
+"t4d0PCu412mUC6Nnd7izvtE2MgIxAP1nnJQjZ8BWukszFQDG48wxCCyci9qpdSMv\r\n"  \
+"uCjn8pwUOkABXK8Mss90fzCfCEOtIA==\r\n"                                  \
+"-----END CERTIFICATE-----\r\n"
+const char test_ca_crt_ec[] = TEST_CA_CRT_EC;
+
+const char test_ca_key_ec[] =
+"-----BEGIN EC PRIVATE KEY-----\r\n"
+"Proc-Type: 4,ENCRYPTED\r\n"
+"DEK-Info: DES-EDE3-CBC,307EAB469933D64E\r\n"
+"\r\n"
+"IxbrRmKcAzctJqPdTQLA4SWyBYYGYJVkYEna+F7Pa5t5Yg/gKADrFKcm6B72e7DG\r\n"
+"ihExtZI648s0zdYw6qSJ74vrPSuWDe5qm93BqsfVH9svtCzWHW0pm1p0KTBCFfUq\r\n"
+"UsuWTITwJImcnlAs1gaRZ3sAWm7cOUidL0fo2G0fYUFNcYoCSLffCFTEHBuPnagb\r\n"
+"a77x/sY1Bvii8S9/XhDTb6pTMx06wzrm\r\n"
+"-----END EC PRIVATE KEY-----\r\n";
+
+const char test_ca_pwd_ec[] = "PolarSSLTest";
+
+const char test_srv_crt_ec[] =
+"-----BEGIN CERTIFICATE-----\r\n"
+"MIICHzCCAaWgAwIBAgIBCTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJOTDERMA8G\r\n"
+"A1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1BvbGFyc3NsIFRlc3QgRUMgQ0EwHhcN\r\n"
+"MTMwOTI0MTU1MjA0WhcNMjMwOTIyMTU1MjA0WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n"
+"A1UEChMIUG9sYXJTU0wxEjAQBgNVBAMTCWxvY2FsaG9zdDBZMBMGByqGSM49AgEG\r\n"
+"CCqGSM49AwEHA0IABDfMVtl2CR5acj7HWS3/IG7ufPkGkXTQrRS192giWWKSTuUA\r\n"
+"2CMR/+ov0jRdXRa9iojCa3cNVc2KKg76Aci07f+jgZ0wgZowCQYDVR0TBAIwADAd\r\n"
+"BgNVHQ4EFgQUUGGlj9QH2deCAQzlZX+MY0anE74wbgYDVR0jBGcwZYAUnW0gJEkB\r\n"
+"PyvLeLUZvH4kydv7NnyhQqRAMD4xCzAJBgNVBAYTAk5MMREwDwYDVQQKEwhQb2xh\r\n"
+"clNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBFQyBDQYIJAMFD4n5iQ8zoMAoG\r\n"
+"CCqGSM49BAMCA2gAMGUCMQCaLFzXptui5WQN8LlO3ddh1hMxx6tzgLvT03MTVK2S\r\n"
+"C12r0Lz3ri/moSEpNZWqPjkCMCE2f53GXcYLqyfyJR078c/xNSUU5+Xxl7VZ414V\r\n"
+"fGa5kHvHARBPc8YAIVIqDvHH1Q==\r\n"
+"-----END CERTIFICATE-----\r\n";
+
+const char test_srv_key_ec[] =
+"-----BEGIN EC PRIVATE KEY-----\r\n"
+"MHcCAQEEIPEqEyB2AnCoPL/9U/YDHvdqXYbIogTywwyp6/UfDw6noAoGCCqGSM49\r\n"
+"AwEHoUQDQgAEN8xW2XYJHlpyPsdZLf8gbu58+QaRdNCtFLX3aCJZYpJO5QDYIxH/\r\n"
+"6i/SNF1dFr2KiMJrdw1VzYoqDvoByLTt/w==\r\n"
+"-----END EC PRIVATE KEY-----\r\n";
+
+const char test_cli_crt_ec[] =
+"-----BEGIN CERTIFICATE-----\r\n"
+"MIICLDCCAbKgAwIBAgIBDTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJOTDERMA8G\r\n"
+"A1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1BvbGFyc3NsIFRlc3QgRUMgQ0EwHhcN\r\n"
+"MTMwOTI0MTU1MjA0WhcNMjMwOTIyMTU1MjA0WjBBMQswCQYDVQQGEwJOTDERMA8G\r\n"
+"A1UEChMIUG9sYXJTU0wxHzAdBgNVBAMTFlBvbGFyU1NMIFRlc3QgQ2xpZW50IDIw\r\n"
+"WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARX5a6xc9/TrLuTuIH/Eq7u5lOszlVT\r\n"
+"9jQOzC7jYyUL35ji81xgNpbA1RgUcOV/n9VLRRjlsGzVXPiWj4dwo+THo4GdMIGa\r\n"
+"MAkGA1UdEwQCMAAwHQYDVR0OBBYEFHoAX4Zk/OBd5REQO7LmO8QmP8/iMG4GA1Ud\r\n"
+"IwRnMGWAFJ1tICRJAT8ry3i1Gbx+JMnb+zZ8oUKkQDA+MQswCQYDVQQGEwJOTDER\r\n"
+"MA8GA1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1BvbGFyc3NsIFRlc3QgRUMgQ0GC\r\n"
+"CQDBQ+J+YkPM6DAKBggqhkjOPQQDAgNoADBlAjBKZQ17IIOimbmoD/yN7o89u3BM\r\n"
+"lgOsjnhw3fIOoLIWy2WOGsk/LGF++DzvrRzuNiACMQCd8iem1XS4JK7haj8xocpU\r\n"
+"LwjQje5PDGHfd3h9tP38Qknu5bJqws0md2KOKHyeV0U=\r\n"
+"-----END CERTIFICATE-----\r\n";
+
+const char test_cli_key_ec[] =
+"-----BEGIN EC PRIVATE KEY-----\r\n"
+"MHcCAQEEIPb3hmTxZ3/mZI3vyk7p3U3wBf+WIop6hDhkFzJhmLcqoAoGCCqGSM49\r\n"
+"AwEHoUQDQgAEV+WusXPf06y7k7iB/xKu7uZTrM5VU/Y0Dswu42MlC9+Y4vNcYDaW\r\n"
+"wNUYFHDlf5/VS0UY5bBs1Vz4lo+HcKPkxw==\r\n"
+"-----END EC PRIVATE KEY-----\r\n";
+#else
+#define TEST_CA_CRT_EC
+#endif /* POLARSSL_ECDSA_C */
+
+#if defined(POLARSSL_RSA_C)
+#define TEST_CA_CRT_RSA                                                 \
+"-----BEGIN CERTIFICATE-----\r\n"                                       \
+"MIIDhzCCAm+gAwIBAgIBADANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n"  \
+"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n"  \
+"MTEwMjEyMTQ0NDAwWhcNMjEwMjEyMTQ0NDAwWjA7MQswCQYDVQQGEwJOTDERMA8G\r\n"  \
+"A1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G\r\n"  \
+"CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx\r\n"  \
+"mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny\r\n"  \
+"50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n\r\n"  \
+"YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL\r\n"  \
+"R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu\r\n"  \
+"KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj\r\n"  \
+"gZUwgZIwDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQUtFrkpbPe0lL2udWmlQ/rPrzH\r\n"  \
+"/f8wYwYDVR0jBFwwWoAUtFrkpbPe0lL2udWmlQ/rPrzH/f+hP6Q9MDsxCzAJBgNV\r\n"  \
+"BAYTAk5MMREwDwYDVQQKEwhQb2xhclNTTDEZMBcGA1UEAxMQUG9sYXJTU0wgVGVz\r\n"  \
+"dCBDQYIBADANBgkqhkiG9w0BAQUFAAOCAQEAuP1U2ABUkIslsCfdlc2i94QHHYeJ\r\n"  \
+"SsR4EdgHtdciUI5I62J6Mom+Y0dT/7a+8S6MVMCZP6C5NyNyXw1GWY/YR82XTJ8H\r\n"  \
+"DBJiCTok5DbZ6SzaONBzdWHXwWwmi5vg1dxn7YxrM9d0IjxM27WNKs4sDQhZBQkF\r\n"  \
+"pjmfs2cb4oPl4Y9T9meTx/lvdkRYEug61Jfn6cA+qHpyPYdTH+UshITnmp5/Ztkf\r\n"  \
+"m/UTSLBNFNHesiTZeH31NcxYGdHSme9Nc/gfidRa0FLOCfWxRlFqAI47zG9jAQCZ\r\n"  \
+"7Z2mCGDNMhjQc+BYcdnl0lPXjdDK6V0qCg1dVewhUBcW5gZKzV7e9+DpVA==\r\n"      \
+"-----END CERTIFICATE-----\r\n"
+const char test_ca_crt_rsa[] = TEST_CA_CRT_RSA;
+
+const char test_ca_key_rsa[] =
+"-----BEGIN RSA PRIVATE KEY-----\r\n"
+"Proc-Type: 4,ENCRYPTED\r\n"
+"DEK-Info: DES-EDE3-CBC,A8A95B05D5B7206B\r\n"
+"\r\n"
+"9Qd9GeArejl1GDVh2lLV1bHt0cPtfbh5h/5zVpAVaFpqtSPMrElp50Rntn9et+JA\r\n"
+"7VOyboR+Iy2t/HU4WvA687k3Bppe9GwKHjHhtl//8xFKwZr3Xb5yO5JUP8AUctQq\r\n"
+"Nb8CLlZyuUC+52REAAthdWgsX+7dJO4yabzUcQ22Tp9JSD0hiL43BlkWYUNK3dAo\r\n"
+"PZlmiptjnzVTjg1MxsBSydZinWOLBV8/JQgxSPo2yD4uEfig28qbvQ2wNIn0pnAb\r\n"
+"GxnSAOazkongEGfvcjIIs+LZN9gXFhxcOh6kc4Q/c99B7QWETwLLkYgZ+z1a9VY9\r\n"
+"gEU7CwCxYCD+h9hY6FPmsK0/lC4O7aeRKpYq00rPPxs6i7phiexg6ax6yTMmArQq\r\n"
+"QmK3TAsJm8V/J5AWpLEV6jAFgRGymGGHnof0DXzVWZidrcZJWTNuGEX90nB3ee2w\r\n"
+"PXJEFWKoD3K3aFcSLdHYr3mLGxP7H9ThQai9VsycxZKS5kwvBKQ//YMrmFfwPk8x\r\n"
+"vTeY4KZMaUrveEel5tWZC94RSMKgxR6cyE1nBXyTQnDOGbfpNNgBKxyKbINWoOJU\r\n"
+"WJZAwlsQn+QzCDwpri7+sV1mS3gBE6UY7aQmnmiiaC2V3Hbphxct/en5QsfDOt1X\r\n"
+"JczSfpRWLlbPznZg8OQh/VgCMA58N5DjOzTIK7sJJ5r+94ZBTCpgAMbF588f0NTR\r\n"
+"KCe4yrxGJR7X02M4nvD4IwOlpsQ8xQxZtOSgXv4LkxvdU9XJJKWZ/XNKJeWztxSe\r\n"
+"Z1vdTc2YfsDBA2SEv33vxHx2g1vqtw8SjDRT2RaQSS0QuSaMJimdOX6mTOCBKk1J\r\n"
+"9Q5mXTrER+/LnK0jEmXsBXWA5bqqVZIyahXSx4VYZ7l7w/PHiUDtDgyRhMMKi4n2\r\n"
+"iQvQcWSQTjrpnlJbca1/DkpRt3YwrvJwdqb8asZU2VrNETh5x0QVefDRLFiVpif/\r\n"
+"tUaeAe/P1F8OkS7OIZDs1SUbv/sD2vMbhNkUoCms3/PvNtdnvgL4F0zhaDpKCmlT\r\n"
+"P8vx49E7v5CyRNmED9zZg4o3wmMqrQO93PtTug3Eu9oVx1zPQM1NVMyBa2+f29DL\r\n"
+"1nuTCeXdo9+ni45xx+jAI4DCwrRdhJ9uzZyC6962H37H6D+5naNvClFR1s6li1Gb\r\n"
+"nqPoiy/OBsEx9CaDGcqQBp5Wme/3XW+6z1ISOx+igwNTVCT14mHdBMbya0eIKft5\r\n"
+"X+GnwtgEMyCYyyWuUct8g4RzErcY9+yW9Om5Hzpx4zOuW4NPZgPDTgK+t2RSL/Yq\r\n"
+"rE1njrgeGYcVeG3f+OftH4s6fPbq7t1A5ZgUscbLMBqr9tK+OqygR4EgKBPsH6Cz\r\n"
+"L6zlv/2RV0qAHvVuDJcIDIgwY5rJtINEm32rhOeFNJwZS5MNIC1czXZx5//ugX7l\r\n"
+"I4sy5nbVhwSjtAk8Xg5dZbdTZ6mIrb7xqH+fdakZor1khG7bC2uIwibD3cSl2XkR\r\n"
+"wN48lslbHnqqagr6Xm1nNOSVl8C/6kbJEsMpLhAezfRtGwvOucoaE+WbeUNolGde\r\n"
+"P/eQiddSf0brnpiLJRh7qZrl9XuqYdpUqnoEdMAfotDOID8OtV7gt8a48ad8VPW2\r\n"
+"-----END RSA PRIVATE KEY-----\r\n";
+
+const char test_ca_pwd_rsa[] = "PolarSSLTest";
+
+const char test_srv_crt_rsa[] =
+"-----BEGIN CERTIFICATE-----\r\n"
+"MIIDNzCCAh+gAwIBAgIBAjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n"
+"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n"
+"MTEwMjEyMTQ0NDA2WhcNMjEwMjEyMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n"
+"A1UEChMIUG9sYXJTU0wxEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n"
+"AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN\r\n"
+"owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz\r\n"
+"NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM\r\n"
+"tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P\r\n"
+"hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya\r\n"
+"HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNNMEswCQYD\r\n"
+"VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw\r\n"
+"FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQEFBQADggEBAJxnXClY\r\n"
+"oHkbp70cqBrsGXLybA74czbO5RdLEgFs7rHVS9r+c293luS/KdliLScZqAzYVylw\r\n"
+"UfRWvKMoWhHYKp3dEIS4xTXk6/5zXxhv9Rw8SGc8qn6vITHk1S1mPevtekgasY5Y\r\n"
+"iWQuM3h4YVlRH3HHEMAD1TnAexfXHHDFQGe+Bd1iAbz1/sH9H8l4StwX6egvTK3M\r\n"
+"wXRwkKkvjKaEDA9ATbZx0mI8LGsxSuCqe9r9dyjmttd47J1p1Rulz3CLzaRcVIuS\r\n"
+"RRQfaD8neM9c1S/iJ/amTVqJxA1KOdOS5780WhPfSArA+g4qAmSjelc3p4wWpha8\r\n"
+"zhuYwjVuX6JHG0c=\r\n"
+"-----END CERTIFICATE-----\r\n";
+
+const char test_srv_key_rsa[] =
+"-----BEGIN RSA PRIVATE KEY-----\r\n"
+"MIIEpAIBAAKCAQEAwU2j3efNHdEE10lyuJmsDnjkOjxKzzoTFtBa5M2jAIin7h5r\r\n"
+"lqdStJDvLXJ6PiSa/LY0rCT1d+AmZIycsCh9odrqjObJHJa8/sEEUrM21KP64bF2\r\n"
+"2JDBYbRmUjaiJlOqq3ReB30Zgtsq2B+g2Q0cLUlm91slc0boC4pPaQy1AJDh2oIQ\r\n"
+"Zn2uVCuLZXmRoeJhw81ASQjuaAzxi4bSRr/QuKoRAx5/VqgaHkQYDw+Fi9qLRF7i\r\n"
+"GMZiL8dmjfpd2H3zJ4kpAcWQDj8n8TDISg7v1t7HxydrxwU9esQCPJodPg/oNJhb\r\n"
+"y3NLUpbYEaIsgIhpOVrTD7DeWS8Rx/fqEgEwlwIDAQABAoIBAQCXR0S8EIHFGORZ\r\n"
+"++AtOg6eENxD+xVs0f1IeGz57Tjo3QnXX7VBZNdj+p1ECvhCE/G7XnkgU5hLZX+G\r\n"
+"Z0jkz/tqJOI0vRSdLBbipHnWouyBQ4e/A1yIJdlBtqXxJ1KE/ituHRbNc4j4kL8Z\r\n"
+"/r6pvwnTI0PSx2Eqs048YdS92LT6qAv4flbNDxMn2uY7s4ycS4Q8w1JXnCeaAnYm\r\n"
+"WYI5wxO+bvRELR2Mcz5DmVnL8jRyml6l6582bSv5oufReFIbyPZbQWlXgYnpu6He\r\n"
+"GTc7E1zKYQGG/9+DQUl/1vQuCPqQwny0tQoX2w5tdYpdMdVm+zkLtbajzdTviJJa\r\n"
+"TWzL6lt5AoGBAN86+SVeJDcmQJcv4Eq6UhtRr4QGMiQMz0Sod6ettYxYzMgxtw28\r\n"
+"CIrgpozCc+UaZJLo7UxvC6an85r1b2nKPCLQFaggJ0H4Q0J/sZOhBIXaoBzWxveK\r\n"
+"nupceKdVxGsFi8CDy86DBfiyFivfBj+47BbaQzPBj7C4rK7UlLjab2rDAoGBAN2u\r\n"
+"AM2gchoFiu4v1HFL8D7lweEpi6ZnMJjnEu/dEgGQJFjwdpLnPbsj4c75odQ4Gz8g\r\n"
+"sw9lao9VVzbusoRE/JGI4aTdO0pATXyG7eG1Qu+5Yc1YGXcCrliA2xM9xx+d7f+s\r\n"
+"mPzN+WIEg5GJDYZDjAzHG5BNvi/FfM1C9dOtjv2dAoGAF0t5KmwbjWHBhcVqO4Ic\r\n"
+"BVvN3BIlc1ue2YRXEDlxY5b0r8N4XceMgKmW18OHApZxfl8uPDauWZLXOgl4uepv\r\n"
+"whZC3EuWrSyyICNhLY21Ah7hbIEBPF3L3ZsOwC+UErL+dXWLdB56Jgy3gZaBeW7b\r\n"
+"vDrEnocJbqCm7IukhXHOBK8CgYEAwqdHB0hqyNSzIOGY7v9abzB6pUdA3BZiQvEs\r\n"
+"3LjHVd4HPJ2x0N8CgrBIWOE0q8+0hSMmeE96WW/7jD3fPWwCR5zlXknxBQsfv0gP\r\n"
+"3BC5PR0Qdypz+d+9zfMf625kyit4T/hzwhDveZUzHnk1Cf+IG7Q+TOEnLnWAWBED\r\n"
+"ISOWmrUCgYAFEmRxgwAc/u+D6t0syCwAYh6POtscq9Y0i9GyWk89NzgC4NdwwbBH\r\n"
+"4AgahOxIxXx2gxJnq3yfkJfIjwf0s2DyP0kY2y6Ua1OeomPeY9mrIS4tCuDQ6LrE\r\n"
+"TB6l9VGoxJL4fyHnZb8L5gGvnB1bbD8cL6YPaDiOhcRseC9vBiEuVg==\r\n"
+"-----END RSA PRIVATE KEY-----\r\n";
+
+
+const char test_cli_crt_rsa[] =
+"-----BEGIN CERTIFICATE-----\r\n"
+"MIIDPzCCAiegAwIBAgIBBDANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n"
+"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n"
+"MTEwMjEyMTQ0NDA3WhcNMjEwMjEyMTQ0NDA3WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n"
+"A1UEChMIUG9sYXJTU0wxGjAYBgNVBAMTEVBvbGFyU1NMIENsaWVudCAyMIIBIjAN\r\n"
+"BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6f\r\n"
+"M60Nj4o8VmXl3ETZzGaFB9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu\r\n"
+"1C93KYRhTYJQj6eVSHD1bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEw\r\n"
+"MjDV0/YI0FZPRo7yX/k9Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v\r\n"
+"4Jv4EFbMs44TFeY0BGbH7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx/\r\n"
+"/DZrtenNLQNiTrM9AM+vdqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQAB\r\n"
+"o00wSzAJBgNVHRMEAjAAMB0GA1UdDgQWBBRxoQBzckAvVHZeM/xSj7zx3WtGITAf\r\n"
+"BgNVHSMEGDAWgBS0WuSls97SUva51aaVD+s+vMf9/zANBgkqhkiG9w0BAQUFAAOC\r\n"
+"AQEAAn86isAM8X+mVwJqeItt6E9slhEQbAofyk+diH1Lh8Y9iLlWQSKbw/UXYjx5\r\n"
+"LLPZcniovxIcARC/BjyZR9g3UwTHNGNm+rwrqa15viuNOFBchykX/Orsk02EH7NR\r\n"
+"Alw5WLPorYjED6cdVQgBl9ot93HdJogRiXCxErM7NC8/eP511mjq+uLDjLKH8ZPQ\r\n"
+"8I4ekHJnroLsDkIwXKGIsvIBHQy2ac/NwHLCQOK6mfum1pRx52V4Utu5dLLjD5bM\r\n"
+"xOBC7KU4xZKuMXXZM6/93Yb51K/J4ahf1TxJlTWXtnzDr9saEYdNy2SKY/6ZiDNH\r\n"
+"D+stpAKiQLAWaAusIWKYEyw9MQ==\r\n"
+"-----END CERTIFICATE-----\r\n";
+
+const char test_cli_key_rsa[] =
+"-----BEGIN RSA PRIVATE KEY-----\r\n"
+"MIIEpAIBAAKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6fM60Nj4o8VmXl3ETZzGaF\r\n"
+"B9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu1C93KYRhTYJQj6eVSHD1\r\n"
+"bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEwMjDV0/YI0FZPRo7yX/k9\r\n"
+"Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v4Jv4EFbMs44TFeY0BGbH\r\n"
+"7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx//DZrtenNLQNiTrM9AM+v\r\n"
+"dqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQABAoIBAGdNtfYDiap6bzst\r\n"
+"yhCiI8m9TtrhZw4MisaEaN/ll3XSjaOG2dvV6xMZCMV+5TeXDHOAZnY18Yi18vzz\r\n"
+"4Ut2TnNFzizCECYNaA2fST3WgInnxUkV3YXAyP6CNxJaCmv2aA0yFr2kFVSeaKGt\r\n"
+"ymvljNp2NVkvm7Th8fBQBO7I7AXhz43k0mR7XmPgewe8ApZOG3hstkOaMvbWAvWA\r\n"
+"zCZupdDjZYjOJqlA4eEA4H8/w7F83r5CugeBE8LgEREjLPiyejrU5H1fubEY+h0d\r\n"
+"l5HZBJ68ybTXfQ5U9o/QKA3dd0toBEhhdRUDGzWtjvwkEQfqF1reGWj/tod/gCpf\r\n"
+"DFi6X0ECgYEA4wOv/pjSC3ty6TuOvKX2rOUiBrLXXv2JSxZnMoMiWI5ipLQt+RYT\r\n"
+"VPafL/m7Dn6MbwjayOkcZhBwk5CNz5A6Q4lJ64Mq/lqHznRCQQ2Mc1G8eyDF/fYL\r\n"
+"Ze2pLvwP9VD5jTc2miDfw+MnvJhywRRLcemDFP8k4hQVtm8PMp3ZmNECgYEA4gz7\r\n"
+"wzObR4gn8ibe617uQPZjWzUj9dUHYd+in1gwBCIrtNnaRn9I9U/Q6tegRYpii4ys\r\n"
+"c176NmU+umy6XmuSKV5qD9bSpZWG2nLFnslrN15Lm3fhZxoeMNhBaEDTnLT26yoi\r\n"
+"33gp0mSSWy94ZEqipms+ULF6sY1ZtFW6tpGFoy8CgYAQHhnnvJflIs2ky4q10B60\r\n"
+"ZcxFp3rtDpkp0JxhFLhiizFrujMtZSjYNm5U7KkgPVHhLELEUvCmOnKTt4ap/vZ0\r\n"
+"BxJNe1GZH3pW6SAvGDQpl9sG7uu/vTFP+lCxukmzxB0DrrDcvorEkKMom7ZCCRvW\r\n"
+"KZsZ6YeH2Z81BauRj218kQKBgQCUV/DgKP2985xDTT79N08jUo3hTP5MVYCCuj/+\r\n"
+"UeEw1TvZcx3LJby7P6Xad6a1/BqveaGyFKIfEFIaBUBItk801sDDpDaYc4gL00Xc\r\n"
+"7lFuBHOZkxJYlss5QrGpuOEl9ZwUt5IrFLBdYaKqNHzNVC1pCPfb/JyH6Dr2HUxq\r\n"
+"gxUwAQKBgQCcU6G2L8AG9d9c0UpOyL1tMvFe5Ttw0KjlQVdsh1MP6yigYo9DYuwu\r\n"
+"bHFVW2r0dBTqegP2/KTOxKzaHfC1qf0RGDsUoJCNJrd1cwoCLG8P2EF4w3OBrKqv\r\n"
+"8u4ytY0F+Vlanj5lm3TaoHSVF1+NWPyOTiwevIECGKwSxvlki4fDAA==\r\n"
+"-----END RSA PRIVATE KEY-----\r\n";
+#else
+#define TEST_CA_CRT_RSA
+#endif /* POLARSSL_RSA_C */
+
+#if defined(POLARSSL_DHM_C)
+const char test_dhm_params[] =
+"-----BEGIN DH PARAMETERS-----\r\n"
+"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
+"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
+"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
+"-----END DH PARAMETERS-----\r\n";
+#endif
+
+/* Concatenation of all available CA certificates */
+const char test_ca_list[] = TEST_CA_CRT_RSA TEST_CA_CRT_EC;
+
+#if defined(POLARSSL_RSA_C)
+const char *test_ca_crt = test_ca_crt_rsa;
+const char *test_ca_key = test_ca_key_rsa;
+const char *test_ca_pwd = test_ca_pwd_rsa;
+const char *test_srv_crt = test_srv_crt_rsa;
+const char *test_srv_key = test_srv_key_rsa;
+const char *test_cli_crt = test_cli_crt_rsa;
+const char *test_cli_key = test_cli_key_rsa;
+#else /* ! POLARSSL_RSA_C, so POLARSSL_ECDSA_C */
+const char *test_ca_crt = test_ca_crt_ec;
+const char *test_ca_key = test_ca_key_ec;
+const char *test_ca_pwd = test_ca_pwd_ec;
+const char *test_srv_crt = test_srv_crt_ec;
+const char *test_srv_key = test_srv_key_ec;
+const char *test_cli_crt = test_cli_crt_ec;
+const char *test_cli_key = test_cli_key_ec;
+#endif /* POLARSSL_RSA_C */
+
+#endif /* POLARSSL_CERTS_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/cipher.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,790 @@
+/**
+ * \file cipher.c
+ *
+ * \brief Generic cipher wrapper for PolarSSL
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_CIPHER_C)
+
+#include "polarssl/cipher.h"
+#include "polarssl/cipher_wrap.h"
+
+#if defined(POLARSSL_GCM_C)
+#include "polarssl/gcm.h"
+#endif
+
+#include <stdlib.h>
+
+#if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER)
+#define POLARSSL_CIPHER_MODE_STREAM
+#endif
+
+#if defined(_MSC_VER) && !defined strcasecmp && !defined(EFIX64) && \
+    !defined(EFI32)
+#define strcasecmp _stricmp
+#endif
+
+static int supported_init = 0;
+
+const int *cipher_list( void )
+{
+    const cipher_definition_t *def;
+    int *type;
+
+    if( ! supported_init )
+    {
+        def = cipher_definitions;
+        type = supported_ciphers;
+
+        while( def->type != 0 )
+            *type++ = (*def++).type;
+
+        *type = 0;
+
+        supported_init = 1;
+    }
+
+    return supported_ciphers;
+}
+
+const cipher_info_t *cipher_info_from_type( const cipher_type_t cipher_type )
+{
+    const cipher_definition_t *def;
+
+    for( def = cipher_definitions; def->info != NULL; def++ )
+        if( def->type == cipher_type )
+            return( def->info );
+
+    return NULL;
+}
+
+const cipher_info_t *cipher_info_from_string( const char *cipher_name )
+{
+    const cipher_definition_t *def;
+
+    if( NULL == cipher_name )
+        return NULL;
+
+    for( def = cipher_definitions; def->info != NULL; def++ )
+        if( !  strcasecmp( def->info->name, cipher_name ) )
+            return( def->info );
+
+    return NULL;
+}
+
+const cipher_info_t *cipher_info_from_values( const cipher_id_t cipher_id,
+                                              int key_length,
+                                              const cipher_mode_t mode )
+{
+    const cipher_definition_t *def;
+
+    for( def = cipher_definitions; def->info != NULL; def++ )
+        if( def->info->base->cipher == cipher_id &&
+            def->info->key_length == (unsigned) key_length &&
+            def->info->mode == mode )
+            return( def->info );
+
+    return NULL;
+}
+
+int cipher_init_ctx( cipher_context_t *ctx, const cipher_info_t *cipher_info )
+{
+    if( NULL == cipher_info || NULL == ctx )
+        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+    memset( ctx, 0, sizeof( cipher_context_t ) );
+
+    if( NULL == ( ctx->cipher_ctx = cipher_info->base->ctx_alloc_func() ) )
+        return POLARSSL_ERR_CIPHER_ALLOC_FAILED;
+
+    ctx->cipher_info = cipher_info;
+
+#if defined(POLARSSL_CIPHER_MODE_WITH_PADDING)
+    /*
+     * Ignore possible errors caused by a cipher mode that doesn't use padding
+     */
+#if defined(POLARSSL_CIPHER_PADDING_PKCS7)
+    (void) cipher_set_padding_mode( ctx, POLARSSL_PADDING_PKCS7 );
+#else
+    (void) cipher_set_padding_mode( ctx, POLARSSL_PADDING_NONE );
+#endif
+#endif /* POLARSSL_CIPHER_MODE_WITH_PADDING */
+
+    return 0;
+}
+
+int cipher_free_ctx( cipher_context_t *ctx )
+{
+    if( ctx == NULL || ctx->cipher_info == NULL )
+        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+    ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx );
+
+    return 0;
+}
+
+int cipher_setkey( cipher_context_t *ctx, const unsigned char *key,
+        int key_length, const operation_t operation )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info )
+        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+    if( (int) ctx->cipher_info->key_length != key_length )
+        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+    ctx->key_length = key_length;
+    ctx->operation = operation;
+
+    /*
+     * For CFB and CTR mode always use the encryption key schedule
+     */
+    if( POLARSSL_ENCRYPT == operation ||
+        POLARSSL_MODE_CFB == ctx->cipher_info->mode ||
+        POLARSSL_MODE_CTR == ctx->cipher_info->mode )
+    {
+        return ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key,
+                ctx->key_length );
+    }
+
+    if( POLARSSL_DECRYPT == operation )
+        return ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key,
+                ctx->key_length );
+
+    return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+}
+
+int cipher_set_iv( cipher_context_t *ctx,
+                   const unsigned char *iv, size_t iv_len )
+{
+    size_t actual_iv_size;
+
+    if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv )
+        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+    /* avoid buffer overflow in ctx->iv */
+    if( iv_len > POLARSSL_MAX_IV_LENGTH )
+        return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+
+    if( ctx->cipher_info->accepts_variable_iv_size )
+        actual_iv_size = iv_len;
+    else
+    {
+        actual_iv_size = ctx->cipher_info->iv_size;
+
+        /* avoid reading past the end of input buffer */
+        if( actual_iv_size > iv_len )
+            return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+    }
+
+    memcpy( ctx->iv, iv, actual_iv_size );
+    ctx->iv_size = actual_iv_size;
+
+    return 0;
+}
+
+int cipher_reset( cipher_context_t *ctx )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info )
+        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+    ctx->unprocessed_len = 0;
+
+    return 0;
+}
+
+#if defined(POLARSSL_CIPHER_MODE_AEAD)
+int cipher_update_ad( cipher_context_t *ctx,
+                      const unsigned char *ad, size_t ad_len )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info )
+        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+#if defined(POLARSSL_GCM_C)
+    if( POLARSSL_MODE_GCM == ctx->cipher_info->mode )
+    {
+        return gcm_starts( (gcm_context *) ctx->cipher_ctx, ctx->operation,
+                           ctx->iv, ctx->iv_size, ad, ad_len );
+    }
+#endif
+
+    return 0;
+}
+#endif /* POLARSSL_CIPHER_MODE_AEAD */
+
+int cipher_update( cipher_context_t *ctx, const unsigned char *input,
+                   size_t ilen, unsigned char *output, size_t *olen )
+{
+    int ret;
+
+    if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen )
+    {
+        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+    }
+
+    *olen = 0;
+
+    if( ctx->cipher_info->mode == POLARSSL_MODE_ECB )
+    {
+        if( ilen != cipher_get_block_size( ctx ) )
+            return POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED;
+
+        *olen = ilen;
+
+        if( 0 != ( ret = ctx->cipher_info->base->ecb_func( ctx->cipher_ctx,
+                    ctx->operation, input, output ) ) )
+        {
+            return ret;
+        }
+
+        return 0;
+    }
+
+#if defined(POLARSSL_GCM_C)
+    if( ctx->cipher_info->mode == POLARSSL_MODE_GCM )
+    {
+        *olen = ilen;
+        return gcm_update( (gcm_context *) ctx->cipher_ctx, ilen, input,
+                           output );
+    }
+#endif
+
+    if( input == output &&
+       ( ctx->unprocessed_len != 0 || ilen % cipher_get_block_size( ctx ) ) )
+    {
+        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+    }
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    if( ctx->cipher_info->mode == POLARSSL_MODE_CBC )
+    {
+        size_t copy_len = 0;
+
+        /*
+         * If there is not enough data for a full block, cache it.
+         */
+        if( ( ctx->operation == POLARSSL_DECRYPT &&
+                ilen + ctx->unprocessed_len <= cipher_get_block_size( ctx ) ) ||
+             ( ctx->operation == POLARSSL_ENCRYPT &&
+                ilen + ctx->unprocessed_len < cipher_get_block_size( ctx ) ) )
+        {
+            memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input,
+                    ilen );
+
+            ctx->unprocessed_len += ilen;
+            return 0;
+        }
+
+        /*
+         * Process cached data first
+         */
+        if( ctx->unprocessed_len != 0 )
+        {
+            copy_len = cipher_get_block_size( ctx ) - ctx->unprocessed_len;
+
+            memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input,
+                    copy_len );
+
+            if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
+                    ctx->operation, cipher_get_block_size( ctx ), ctx->iv,
+                    ctx->unprocessed_data, output ) ) )
+            {
+                return ret;
+            }
+
+            *olen += cipher_get_block_size( ctx );
+            output += cipher_get_block_size( ctx );
+            ctx->unprocessed_len = 0;
+
+            input += copy_len;
+            ilen -= copy_len;
+        }
+
+        /*
+         * Cache final, incomplete block
+         */
+        if( 0 != ilen )
+        {
+            copy_len = ilen % cipher_get_block_size( ctx );
+            if( copy_len == 0 && ctx->operation == POLARSSL_DECRYPT )
+                copy_len = cipher_get_block_size(ctx);
+
+            memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ),
+                    copy_len );
+
+            ctx->unprocessed_len += copy_len;
+            ilen -= copy_len;
+        }
+
+        /*
+         * Process remaining full blocks
+         */
+        if( ilen )
+        {
+            if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
+                    ctx->operation, ilen, ctx->iv, input, output ) ) )
+            {
+                return ret;
+            }
+
+            *olen += ilen;
+        }
+
+        return 0;
+    }
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+    if( ctx->cipher_info->mode == POLARSSL_MODE_CFB )
+    {
+        if( 0 != ( ret = ctx->cipher_info->base->cfb_func( ctx->cipher_ctx,
+                ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv,
+                input, output ) ) )
+        {
+            return ret;
+        }
+
+        *olen = ilen;
+
+        return 0;
+    }
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+    if( ctx->cipher_info->mode == POLARSSL_MODE_CTR )
+    {
+        if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx,
+                ilen, &ctx->unprocessed_len, ctx->iv,
+                ctx->unprocessed_data, input, output ) ) )
+        {
+            return ret;
+        }
+
+        *olen = ilen;
+
+        return 0;
+    }
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+#if defined(POLARSSL_CIPHER_MODE_STREAM)
+    if( ctx->cipher_info->mode == POLARSSL_MODE_STREAM )
+    {
+        if( 0 != ( ret = ctx->cipher_info->base->stream_func( ctx->cipher_ctx,
+                                                    ilen, input, output ) ) )
+        {
+            return ret;
+        }
+
+        *olen = ilen;
+
+        return 0;
+    }
+#endif /* POLARSSL_CIPHER_MODE_STREAM */
+
+    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+}
+
+#if defined(POLARSSL_CIPHER_MODE_WITH_PADDING)
+#if defined(POLARSSL_CIPHER_PADDING_PKCS7)
+/*
+ * PKCS7 (and PKCS5) padding: fill with ll bytes, with ll = padding_len
+ */
+static void add_pkcs_padding( unsigned char *output, size_t output_len,
+        size_t data_len )
+{
+    size_t padding_len = output_len - data_len;
+    unsigned char i;
+
+    for( i = 0; i < padding_len; i++ )
+        output[data_len + i] = (unsigned char) padding_len;
+}
+
+static int get_pkcs_padding( unsigned char *input, size_t input_len,
+        size_t *data_len )
+{
+    size_t i, pad_idx;
+    unsigned char padding_len, bad = 0;
+
+    if( NULL == input || NULL == data_len )
+        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+    padding_len = input[input_len - 1];
+    *data_len = input_len - padding_len;
+
+    /* Avoid logical || since it results in a branch */
+    bad |= padding_len > input_len;
+    bad |= padding_len == 0;
+
+    /* The number of bytes checked must be independent of padding_len,
+     * so pick input_len, which is usually 8 or 16 (one block) */
+    pad_idx = input_len - padding_len;
+    for( i = 0; i < input_len; i++ )
+        bad |= ( input[i] ^ padding_len ) * ( i >= pad_idx );
+
+    return POLARSSL_ERR_CIPHER_INVALID_PADDING * (bad != 0);
+}
+#endif /* POLARSSL_CIPHER_PADDING_PKCS7 */
+
+#if defined(POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS)
+/*
+ * One and zeros padding: fill with 80 00 ... 00
+ */
+static void add_one_and_zeros_padding( unsigned char *output,
+                                       size_t output_len, size_t data_len )
+{
+    size_t padding_len = output_len - data_len;
+    unsigned char i = 0;
+
+    output[data_len] = 0x80;
+    for( i = 1; i < padding_len; i++ )
+        output[data_len + i] = 0x00;
+}
+
+static int get_one_and_zeros_padding( unsigned char *input, size_t input_len,
+                                      size_t *data_len )
+{
+    size_t i;
+    unsigned char done = 0, prev_done, bad;
+
+    if( NULL == input || NULL == data_len )
+        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+    bad = 0xFF;
+    *data_len = 0;
+    for( i = input_len; i > 0; i-- )
+    {
+        prev_done = done;
+        done |= ( input[i-1] != 0 );
+        *data_len |= ( i - 1 ) * ( done != prev_done );
+        bad &= ( input[i-1] ^ 0x80 ) | ( done == prev_done );
+    }
+
+    return POLARSSL_ERR_CIPHER_INVALID_PADDING * (bad != 0);
+
+}
+#endif /* POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS */
+
+#if defined(POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN)
+/*
+ * Zeros and len padding: fill with 00 ... 00 ll, where ll is padding length
+ */
+static void add_zeros_and_len_padding( unsigned char *output,
+                                       size_t output_len, size_t data_len )
+{
+    size_t padding_len = output_len - data_len;
+    unsigned char i = 0;
+
+    for( i = 1; i < padding_len; i++ )
+        output[data_len + i - 1] = 0x00;
+    output[output_len - 1] = (unsigned char) padding_len;
+}
+
+static int get_zeros_and_len_padding( unsigned char *input, size_t input_len,
+                                      size_t *data_len )
+{
+    size_t i, pad_idx;
+    unsigned char padding_len, bad = 0;
+
+    if( NULL == input || NULL == data_len )
+        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+    padding_len = input[input_len - 1];
+    *data_len = input_len - padding_len;
+
+    /* Avoid logical || since it results in a branch */
+    bad |= padding_len > input_len;
+    bad |= padding_len == 0;
+
+    /* The number of bytes checked must be independent of padding_len */
+    pad_idx = input_len - padding_len;
+    for( i = 0; i < input_len - 1; i++ )
+        bad |= input[i] * ( i >= pad_idx );
+
+    return POLARSSL_ERR_CIPHER_INVALID_PADDING * (bad != 0);
+}
+#endif /* POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN */
+
+#if defined(POLARSSL_CIPHER_PADDING_ZEROS)
+/*
+ * Zero padding: fill with 00 ... 00
+ */
+static void add_zeros_padding( unsigned char *output,
+                               size_t output_len, size_t data_len )
+{
+    size_t i;
+
+    for( i = data_len; i < output_len; i++ )
+        output[i] = 0x00;
+}
+
+static int get_zeros_padding( unsigned char *input, size_t input_len,
+                              size_t *data_len )
+{
+    size_t i;
+    unsigned char done = 0, prev_done;
+
+    if( NULL == input || NULL == data_len )
+        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+    *data_len = 0;
+    for( i = input_len; i > 0; i-- )
+    {
+        prev_done = done;
+        done |= ( input[i-1] != 0 );
+        *data_len |= i * ( done != prev_done );
+    }
+
+    return 0;
+}
+#endif /* POLARSSL_CIPHER_PADDING_ZEROS */
+
+/*
+ * No padding: don't pad :)
+ *
+ * There is no add_padding function (check for NULL in cipher_finish)
+ * but a trivial get_padding function
+ */
+static int get_no_padding( unsigned char *input, size_t input_len,
+                              size_t *data_len )
+{
+    if( NULL == input || NULL == data_len )
+        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+    *data_len = input_len;
+
+    return 0;
+}
+#endif /* POLARSSL_CIPHER_MODE_WITH_PADDING */
+
+int cipher_finish( cipher_context_t *ctx,
+                   unsigned char *output, size_t *olen )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen )
+        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+    *olen = 0;
+
+    if( POLARSSL_MODE_CFB == ctx->cipher_info->mode ||
+        POLARSSL_MODE_CTR == ctx->cipher_info->mode ||
+        POLARSSL_MODE_GCM == ctx->cipher_info->mode ||
+        POLARSSL_MODE_STREAM == ctx->cipher_info->mode )
+    {
+        return 0;
+    }
+
+    if( POLARSSL_MODE_ECB == ctx->cipher_info->mode )
+    {
+        if( ctx->unprocessed_len != 0 )
+            return POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED;
+
+        return 0;
+    }
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    if( POLARSSL_MODE_CBC == ctx->cipher_info->mode )
+    {
+        int ret = 0;
+
+        if( POLARSSL_ENCRYPT == ctx->operation )
+        {
+            /* check for 'no padding' mode */
+            if( NULL == ctx->add_padding )
+            {
+                if( 0 != ctx->unprocessed_len )
+                    return POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED;
+
+                return 0;
+            }
+
+            ctx->add_padding( ctx->unprocessed_data, cipher_get_iv_size( ctx ),
+                    ctx->unprocessed_len );
+        }
+        else if ( cipher_get_block_size( ctx ) != ctx->unprocessed_len )
+        {
+            /*
+             * For decrypt operations, expect a full block,
+             * or an empty block if no padding
+             */
+            if( NULL == ctx->add_padding && 0 == ctx->unprocessed_len )
+                return 0;
+
+            return POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED;
+        }
+
+        /* cipher block */
+        if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
+                ctx->operation, cipher_get_block_size( ctx ), ctx->iv,
+                ctx->unprocessed_data, output ) ) )
+        {
+            return ret;
+        }
+
+        /* Set output size for decryption */
+        if( POLARSSL_DECRYPT == ctx->operation )
+            return ctx->get_padding( output, cipher_get_block_size( ctx ),
+                                     olen );
+
+        /* Set output size for encryption */
+        *olen = cipher_get_block_size( ctx );
+        return 0;
+    }
+#else
+    ((void) output);
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+}
+
+#if defined(POLARSSL_CIPHER_MODE_WITH_PADDING)
+int cipher_set_padding_mode( cipher_context_t *ctx, cipher_padding_t mode )
+{
+    if( NULL == ctx ||
+        POLARSSL_MODE_CBC != ctx->cipher_info->mode )
+    {
+        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+    }
+
+    switch( mode )
+    {
+#if defined(POLARSSL_CIPHER_PADDING_PKCS7)
+    case POLARSSL_PADDING_PKCS7:
+        ctx->add_padding = add_pkcs_padding;
+        ctx->get_padding = get_pkcs_padding;
+        break;
+#endif
+#if defined(POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS)
+    case POLARSSL_PADDING_ONE_AND_ZEROS:
+        ctx->add_padding = add_one_and_zeros_padding;
+        ctx->get_padding = get_one_and_zeros_padding;
+        break;
+#endif
+#if defined(POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN)
+    case POLARSSL_PADDING_ZEROS_AND_LEN:
+        ctx->add_padding = add_zeros_and_len_padding;
+        ctx->get_padding = get_zeros_and_len_padding;
+        break;
+#endif
+#if defined(POLARSSL_CIPHER_PADDING_ZEROS)
+    case POLARSSL_PADDING_ZEROS:
+        ctx->add_padding = add_zeros_padding;
+        ctx->get_padding = get_zeros_padding;
+        break;
+#endif
+    case POLARSSL_PADDING_NONE:
+        ctx->add_padding = NULL;
+        ctx->get_padding = get_no_padding;
+        break;
+
+    default:
+        return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+    }
+
+    return 0;
+}
+#endif /* POLARSSL_CIPHER_MODE_WITH_PADDING */
+
+#if defined(POLARSSL_CIPHER_MODE_AEAD)
+int cipher_write_tag( cipher_context_t *ctx,
+                      unsigned char *tag, size_t tag_len )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info || NULL == tag )
+        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+    if( POLARSSL_ENCRYPT != ctx->operation )
+        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+#if defined(POLARSSL_GCM_C)
+    if( POLARSSL_MODE_GCM == ctx->cipher_info->mode )
+        return gcm_finish( (gcm_context *) ctx->cipher_ctx, tag, tag_len );
+#endif
+
+    return 0;
+}
+
+int cipher_check_tag( cipher_context_t *ctx,
+                      const unsigned char *tag, size_t tag_len )
+{
+    int ret;
+
+    if( NULL == ctx || NULL == ctx->cipher_info ||
+        POLARSSL_DECRYPT != ctx->operation )
+    {
+        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+    }
+
+#if defined(POLARSSL_GCM_C)
+    if( POLARSSL_MODE_GCM == ctx->cipher_info->mode )
+    {
+        unsigned char check_tag[16];
+        size_t i;
+        int diff;
+
+        if( tag_len > sizeof( check_tag ) )
+            return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+        if( 0 != ( ret = gcm_finish( (gcm_context *) ctx->cipher_ctx,
+                                     check_tag, tag_len ) ) )
+        {
+            return( ret );
+        }
+
+        /* Check the tag in "constant-time" */
+        for( diff = 0, i = 0; i < tag_len; i++ )
+            diff |= tag[i] ^ check_tag[i];
+
+        if( diff != 0 )
+            return( POLARSSL_ERR_CIPHER_AUTH_FAILED );
+
+        return( 0 );
+    }
+#endif /* POLARSSL_GCM_C */
+
+    return( 0 );
+}
+#endif /* POLARSSL_CIPHER_MODE_AEAD */
+
+#if defined(POLARSSL_SELF_TEST)
+
+/*
+ * Checkup routine
+ */
+int cipher_self_test( int verbose )
+{
+    ((void) verbose);
+
+    return( 0 );
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_CIPHER_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/cipher_wrap.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,1288 @@
+/**
+ * \file cipher_wrap.c
+ *
+ * \brief Generic cipher wrapper for PolarSSL
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_CIPHER_C)
+
+#include "polarssl/cipher_wrap.h"
+
+#if defined(POLARSSL_AES_C)
+#include "polarssl/aes.h"
+#endif
+
+#if defined(POLARSSL_ARC4_C)
+#include "polarssl/arc4.h"
+#endif
+
+#if defined(POLARSSL_CAMELLIA_C)
+#include "polarssl/camellia.h"
+#endif
+
+#if defined(POLARSSL_DES_C)
+#include "polarssl/des.h"
+#endif
+
+#if defined(POLARSSL_BLOWFISH_C)
+#include "polarssl/blowfish.h"
+#endif
+
+#if defined(POLARSSL_GCM_C)
+#include "polarssl/gcm.h"
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+#include <stdlib.h>
+
+#if defined(POLARSSL_GCM_C)
+/* shared by all GCM ciphers */
+static void *gcm_ctx_alloc( void )
+{
+    return polarssl_malloc( sizeof( gcm_context ) );
+}
+
+static void gcm_ctx_free( void *ctx )
+{
+    gcm_free( ctx );
+    polarssl_free( ctx );
+}
+#endif /* POLARSSL_GCM_C */
+
+#if defined(POLARSSL_AES_C)
+
+static int aes_crypt_ecb_wrap( void *ctx, operation_t operation,
+        const unsigned char *input, unsigned char *output )
+{
+    return aes_crypt_ecb( (aes_context *) ctx, operation, input, output );
+}
+
+static int aes_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length,
+        unsigned char *iv, const unsigned char *input, unsigned char *output )
+{
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    return aes_crypt_cbc( (aes_context *) ctx, operation, length, iv, input,
+                          output );
+#else
+    ((void) ctx);
+    ((void) operation);
+    ((void) length);
+    ((void) iv);
+    ((void) input);
+    ((void) output);
+
+    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+}
+
+static int aes_crypt_cfb128_wrap( void *ctx, operation_t operation,
+        size_t length, size_t *iv_off, unsigned char *iv,
+        const unsigned char *input, unsigned char *output )
+{
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+    return aes_crypt_cfb128( (aes_context *) ctx, operation, length, iv_off, iv,
+                             input, output );
+#else
+    ((void) ctx);
+    ((void) operation);
+    ((void) length);
+    ((void) iv_off);
+    ((void) iv);
+    ((void) input);
+    ((void) output);
+
+    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+}
+
+static int aes_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off,
+        unsigned char *nonce_counter, unsigned char *stream_block,
+        const unsigned char *input, unsigned char *output )
+{
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+    return aes_crypt_ctr( (aes_context *) ctx, length, nc_off, nonce_counter,
+                          stream_block, input, output );
+#else
+    ((void) ctx);
+    ((void) length);
+    ((void) nc_off);
+    ((void) nonce_counter);
+    ((void) stream_block);
+    ((void) input);
+    ((void) output);
+
+    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+}
+
+static int aes_setkey_dec_wrap( void *ctx, const unsigned char *key,
+                                unsigned int key_length )
+{
+    return aes_setkey_dec( (aes_context *) ctx, key, key_length );
+}
+
+static int aes_setkey_enc_wrap( void *ctx, const unsigned char *key,
+                                unsigned int key_length )
+{
+    return aes_setkey_enc( (aes_context *) ctx, key, key_length );
+}
+
+static void * aes_ctx_alloc( void )
+{
+    return polarssl_malloc( sizeof( aes_context ) );
+}
+
+static void aes_ctx_free( void *ctx )
+{
+    polarssl_free( ctx );
+}
+
+const cipher_base_t aes_info = {
+    POLARSSL_CIPHER_ID_AES,
+    aes_crypt_ecb_wrap,
+    aes_crypt_cbc_wrap,
+    aes_crypt_cfb128_wrap,
+    aes_crypt_ctr_wrap,
+    NULL,
+    aes_setkey_enc_wrap,
+    aes_setkey_dec_wrap,
+    aes_ctx_alloc,
+    aes_ctx_free
+};
+
+const cipher_info_t aes_128_ecb_info = {
+    POLARSSL_CIPHER_AES_128_ECB,
+    POLARSSL_MODE_ECB,
+    128,
+    "AES-128-ECB",
+    16,
+    0,
+    16,
+    &aes_info
+};
+
+const cipher_info_t aes_192_ecb_info = {
+    POLARSSL_CIPHER_AES_192_ECB,
+    POLARSSL_MODE_ECB,
+    192,
+    "AES-192-ECB",
+    16,
+    0,
+    16,
+    &aes_info
+};
+
+const cipher_info_t aes_256_ecb_info = {
+    POLARSSL_CIPHER_AES_256_ECB,
+    POLARSSL_MODE_ECB,
+    256,
+    "AES-256-ECB",
+    16,
+    0,
+    16,
+    &aes_info
+};
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+const cipher_info_t aes_128_cbc_info = {
+    POLARSSL_CIPHER_AES_128_CBC,
+    POLARSSL_MODE_CBC,
+    128,
+    "AES-128-CBC",
+    16,
+    0,
+    16,
+    &aes_info
+};
+
+const cipher_info_t aes_192_cbc_info = {
+    POLARSSL_CIPHER_AES_192_CBC,
+    POLARSSL_MODE_CBC,
+    192,
+    "AES-192-CBC",
+    16,
+    0,
+    16,
+    &aes_info
+};
+
+const cipher_info_t aes_256_cbc_info = {
+    POLARSSL_CIPHER_AES_256_CBC,
+    POLARSSL_MODE_CBC,
+    256,
+    "AES-256-CBC",
+    16,
+    0,
+    16,
+    &aes_info
+};
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+const cipher_info_t aes_128_cfb128_info = {
+    POLARSSL_CIPHER_AES_128_CFB128,
+    POLARSSL_MODE_CFB,
+    128,
+    "AES-128-CFB128",
+    16,
+    0,
+    16,
+    &aes_info
+};
+
+const cipher_info_t aes_192_cfb128_info = {
+    POLARSSL_CIPHER_AES_192_CFB128,
+    POLARSSL_MODE_CFB,
+    192,
+    "AES-192-CFB128",
+    16,
+    0,
+    16,
+    &aes_info
+};
+
+const cipher_info_t aes_256_cfb128_info = {
+    POLARSSL_CIPHER_AES_256_CFB128,
+    POLARSSL_MODE_CFB,
+    256,
+    "AES-256-CFB128",
+    16,
+    0,
+    16,
+    &aes_info
+};
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+const cipher_info_t aes_128_ctr_info = {
+    POLARSSL_CIPHER_AES_128_CTR,
+    POLARSSL_MODE_CTR,
+    128,
+    "AES-128-CTR",
+    16,
+    0,
+    16,
+    &aes_info
+};
+
+const cipher_info_t aes_192_ctr_info = {
+    POLARSSL_CIPHER_AES_192_CTR,
+    POLARSSL_MODE_CTR,
+    192,
+    "AES-192-CTR",
+    16,
+    0,
+    16,
+    &aes_info
+};
+
+const cipher_info_t aes_256_ctr_info = {
+    POLARSSL_CIPHER_AES_256_CTR,
+    POLARSSL_MODE_CTR,
+    256,
+    "AES-256-CTR",
+    16,
+    0,
+    16,
+    &aes_info
+};
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+#if defined(POLARSSL_GCM_C)
+static int gcm_aes_setkey_wrap( void *ctx, const unsigned char *key,
+                                unsigned int key_length )
+{
+    return gcm_init( (gcm_context *) ctx, POLARSSL_CIPHER_ID_AES,
+                     key, key_length );
+}
+
+const cipher_base_t gcm_aes_info = {
+    POLARSSL_CIPHER_ID_AES,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    gcm_aes_setkey_wrap,
+    gcm_aes_setkey_wrap,
+    gcm_ctx_alloc,
+    gcm_ctx_free,
+};
+
+const cipher_info_t aes_128_gcm_info = {
+    POLARSSL_CIPHER_AES_128_GCM,
+    POLARSSL_MODE_GCM,
+    128,
+    "AES-128-GCM",
+    12,
+    1,
+    16,
+    &gcm_aes_info
+};
+
+const cipher_info_t aes_192_gcm_info = {
+    POLARSSL_CIPHER_AES_192_GCM,
+    POLARSSL_MODE_GCM,
+    192,
+    "AES-192-GCM",
+    12,
+    1,
+    16,
+    &gcm_aes_info
+};
+
+const cipher_info_t aes_256_gcm_info = {
+    POLARSSL_CIPHER_AES_256_GCM,
+    POLARSSL_MODE_GCM,
+    256,
+    "AES-256-GCM",
+    12,
+    1,
+    16,
+    &gcm_aes_info
+};
+#endif /* POLARSSL_GCM_C */
+
+#endif /* POLARSSL_AES_C */
+
+#if defined(POLARSSL_CAMELLIA_C)
+
+static int camellia_crypt_ecb_wrap( void *ctx, operation_t operation,
+        const unsigned char *input, unsigned char *output )
+{
+    return camellia_crypt_ecb( (camellia_context *) ctx, operation, input,
+                               output );
+}
+
+static int camellia_crypt_cbc_wrap( void *ctx, operation_t operation,
+        size_t length, unsigned char *iv,
+        const unsigned char *input, unsigned char *output )
+{
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    return camellia_crypt_cbc( (camellia_context *) ctx, operation, length, iv,
+                               input, output );
+#else
+    ((void) ctx);
+    ((void) operation);
+    ((void) length);
+    ((void) iv);
+    ((void) input);
+    ((void) output);
+
+    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+}
+
+static int camellia_crypt_cfb128_wrap( void *ctx, operation_t operation,
+        size_t length, size_t *iv_off, unsigned char *iv,
+        const unsigned char *input, unsigned char *output )
+{
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+    return camellia_crypt_cfb128( (camellia_context *) ctx, operation, length,
+                                  iv_off, iv, input, output );
+#else
+    ((void) ctx);
+    ((void) operation);
+    ((void) length);
+    ((void) iv_off);
+    ((void) iv);
+    ((void) input);
+    ((void) output);
+
+    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+}
+
+static int camellia_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off,
+        unsigned char *nonce_counter, unsigned char *stream_block,
+        const unsigned char *input, unsigned char *output )
+{
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+    return camellia_crypt_ctr( (camellia_context *) ctx, length, nc_off,
+                               nonce_counter, stream_block, input, output );
+#else
+    ((void) ctx);
+    ((void) length);
+    ((void) nc_off);
+    ((void) nonce_counter);
+    ((void) stream_block);
+    ((void) input);
+    ((void) output);
+
+    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+}
+
+static int camellia_setkey_dec_wrap( void *ctx, const unsigned char *key,
+                                     unsigned int key_length )
+{
+    return camellia_setkey_dec( (camellia_context *) ctx, key, key_length );
+}
+
+static int camellia_setkey_enc_wrap( void *ctx, const unsigned char *key,
+                                     unsigned int key_length )
+{
+    return camellia_setkey_enc( (camellia_context *) ctx, key, key_length );
+}
+
+static void * camellia_ctx_alloc( void )
+{
+    return polarssl_malloc( sizeof( camellia_context ) );
+}
+
+static void camellia_ctx_free( void *ctx )
+{
+    polarssl_free( ctx );
+}
+
+const cipher_base_t camellia_info = {
+    POLARSSL_CIPHER_ID_CAMELLIA,
+    camellia_crypt_ecb_wrap,
+    camellia_crypt_cbc_wrap,
+    camellia_crypt_cfb128_wrap,
+    camellia_crypt_ctr_wrap,
+    NULL,
+    camellia_setkey_enc_wrap,
+    camellia_setkey_dec_wrap,
+    camellia_ctx_alloc,
+    camellia_ctx_free
+};
+
+const cipher_info_t camellia_128_ecb_info = {
+    POLARSSL_CIPHER_CAMELLIA_128_ECB,
+    POLARSSL_MODE_ECB,
+    128,
+    "CAMELLIA-128-ECB",
+    16,
+    0,
+    16,
+    &camellia_info
+};
+
+const cipher_info_t camellia_192_ecb_info = {
+    POLARSSL_CIPHER_CAMELLIA_192_ECB,
+    POLARSSL_MODE_ECB,
+    192,
+    "CAMELLIA-192-ECB",
+    16,
+    0,
+    16,
+    &camellia_info
+};
+
+const cipher_info_t camellia_256_ecb_info = {
+    POLARSSL_CIPHER_CAMELLIA_256_ECB,
+    POLARSSL_MODE_ECB,
+    256,
+    "CAMELLIA-256-ECB",
+    16,
+    0,
+    16,
+    &camellia_info
+};
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+const cipher_info_t camellia_128_cbc_info = {
+    POLARSSL_CIPHER_CAMELLIA_128_CBC,
+    POLARSSL_MODE_CBC,
+    128,
+    "CAMELLIA-128-CBC",
+    16,
+    0,
+    16,
+    &camellia_info
+};
+
+const cipher_info_t camellia_192_cbc_info = {
+    POLARSSL_CIPHER_CAMELLIA_192_CBC,
+    POLARSSL_MODE_CBC,
+    192,
+    "CAMELLIA-192-CBC",
+    16,
+    0,
+    16,
+    &camellia_info
+};
+
+const cipher_info_t camellia_256_cbc_info = {
+    POLARSSL_CIPHER_CAMELLIA_256_CBC,
+    POLARSSL_MODE_CBC,
+    256,
+    "CAMELLIA-256-CBC",
+    16,
+    0,
+    16,
+    &camellia_info
+};
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+const cipher_info_t camellia_128_cfb128_info = {
+    POLARSSL_CIPHER_CAMELLIA_128_CFB128,
+    POLARSSL_MODE_CFB,
+    128,
+    "CAMELLIA-128-CFB128",
+    16,
+    0,
+    16,
+    &camellia_info
+};
+
+const cipher_info_t camellia_192_cfb128_info = {
+    POLARSSL_CIPHER_CAMELLIA_192_CFB128,
+    POLARSSL_MODE_CFB,
+    192,
+    "CAMELLIA-192-CFB128",
+    16,
+    0,
+    16,
+    &camellia_info
+};
+
+const cipher_info_t camellia_256_cfb128_info = {
+    POLARSSL_CIPHER_CAMELLIA_256_CFB128,
+    POLARSSL_MODE_CFB,
+    256,
+    "CAMELLIA-256-CFB128",
+    16,
+    0,
+    16,
+    &camellia_info
+};
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+const cipher_info_t camellia_128_ctr_info = {
+    POLARSSL_CIPHER_CAMELLIA_128_CTR,
+    POLARSSL_MODE_CTR,
+    128,
+    "CAMELLIA-128-CTR",
+    16,
+    0,
+    16,
+    &camellia_info
+};
+
+const cipher_info_t camellia_192_ctr_info = {
+    POLARSSL_CIPHER_CAMELLIA_192_CTR,
+    POLARSSL_MODE_CTR,
+    192,
+    "CAMELLIA-192-CTR",
+    16,
+    0,
+    16,
+    &camellia_info
+};
+
+const cipher_info_t camellia_256_ctr_info = {
+    POLARSSL_CIPHER_CAMELLIA_256_CTR,
+    POLARSSL_MODE_CTR,
+    256,
+    "CAMELLIA-256-CTR",
+    16,
+    0,
+    16,
+    &camellia_info
+};
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+#if defined(POLARSSL_GCM_C)
+static int gcm_camellia_setkey_wrap( void *ctx, const unsigned char *key,
+                                     unsigned int key_length )
+{
+    return gcm_init( (gcm_context *) ctx, POLARSSL_CIPHER_ID_CAMELLIA,
+                     key, key_length );
+}
+
+const cipher_base_t gcm_camellia_info = {
+    POLARSSL_CIPHER_ID_CAMELLIA,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    gcm_camellia_setkey_wrap,
+    gcm_camellia_setkey_wrap,
+    gcm_ctx_alloc,
+    gcm_ctx_free,
+};
+
+const cipher_info_t camellia_128_gcm_info = {
+    POLARSSL_CIPHER_CAMELLIA_128_GCM,
+    POLARSSL_MODE_GCM,
+    128,
+    "CAMELLIA-128-GCM",
+    12,
+    1,
+    16,
+    &gcm_camellia_info
+};
+
+const cipher_info_t camellia_192_gcm_info = {
+    POLARSSL_CIPHER_CAMELLIA_192_GCM,
+    POLARSSL_MODE_GCM,
+    192,
+    "CAMELLIA-192-GCM",
+    12,
+    1,
+    16,
+    &gcm_camellia_info
+};
+
+const cipher_info_t camellia_256_gcm_info = {
+    POLARSSL_CIPHER_CAMELLIA_256_GCM,
+    POLARSSL_MODE_GCM,
+    256,
+    "CAMELLIA-256-GCM",
+    12,
+    1,
+    16,
+    &gcm_camellia_info
+};
+#endif /* POLARSSL_GCM_C */
+
+#endif /* POLARSSL_CAMELLIA_C */
+
+#if defined(POLARSSL_DES_C)
+
+static int des_crypt_ecb_wrap( void *ctx, operation_t operation,
+        const unsigned char *input, unsigned char *output )
+{
+    ((void) operation);
+    return des_crypt_ecb( (des_context *) ctx, input, output );
+}
+
+static int des3_crypt_ecb_wrap( void *ctx, operation_t operation,
+        const unsigned char *input, unsigned char *output )
+{
+    ((void) operation);
+    return des3_crypt_ecb( (des3_context *) ctx, input, output );
+}
+
+static int des_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length,
+        unsigned char *iv, const unsigned char *input, unsigned char *output )
+{
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    return des_crypt_cbc( (des_context *) ctx, operation, length, iv, input,
+                          output );
+#else
+    ((void) ctx);
+    ((void) operation);
+    ((void) length);
+    ((void) iv);
+    ((void) input);
+    ((void) output);
+
+    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+}
+
+static int des3_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length,
+        unsigned char *iv, const unsigned char *input, unsigned char *output )
+{
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    return des3_crypt_cbc( (des3_context *) ctx, operation, length, iv, input,
+                           output );
+#else
+    ((void) ctx);
+    ((void) operation);
+    ((void) length);
+    ((void) iv);
+    ((void) input);
+    ((void) output);
+
+    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+}
+
+static int des_crypt_cfb128_wrap( void *ctx, operation_t operation,
+        size_t length, size_t *iv_off, unsigned char *iv,
+        const unsigned char *input, unsigned char *output )
+{
+    ((void) ctx);
+    ((void) operation);
+    ((void) length);
+    ((void) iv_off);
+    ((void) iv);
+    ((void) input);
+    ((void) output);
+
+    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+}
+
+static int des_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off,
+        unsigned char *nonce_counter, unsigned char *stream_block,
+        const unsigned char *input, unsigned char *output )
+{
+    ((void) ctx);
+    ((void) length);
+    ((void) nc_off);
+    ((void) nonce_counter);
+    ((void) stream_block);
+    ((void) input);
+    ((void) output);
+
+    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+}
+
+static int des_setkey_dec_wrap( void *ctx, const unsigned char *key,
+                                unsigned int key_length )
+{
+    ((void) key_length);
+
+    return des_setkey_dec( (des_context *) ctx, key );
+}
+
+static int des_setkey_enc_wrap( void *ctx, const unsigned char *key,
+                                unsigned int key_length )
+{
+    ((void) key_length);
+
+    return des_setkey_enc( (des_context *) ctx, key );
+}
+
+static int des3_set2key_dec_wrap( void *ctx, const unsigned char *key,
+                                  unsigned int key_length )
+{
+    ((void) key_length);
+
+    return des3_set2key_dec( (des3_context *) ctx, key );
+}
+
+static int des3_set2key_enc_wrap( void *ctx, const unsigned char *key,
+                                  unsigned int key_length )
+{
+    ((void) key_length);
+
+    return des3_set2key_enc( (des3_context *) ctx, key );
+}
+
+static int des3_set3key_dec_wrap( void *ctx, const unsigned char *key,
+                                  unsigned int key_length )
+{
+    ((void) key_length);
+
+    return des3_set3key_dec( (des3_context *) ctx, key );
+}
+
+static int des3_set3key_enc_wrap( void *ctx, const unsigned char *key,
+                                  unsigned int key_length )
+{
+    ((void) key_length);
+
+    return des3_set3key_enc( (des3_context *) ctx, key );
+}
+
+static void * des_ctx_alloc( void )
+{
+    return polarssl_malloc( sizeof( des_context ) );
+}
+
+static void * des3_ctx_alloc( void )
+{
+    return polarssl_malloc( sizeof( des3_context ) );
+}
+
+static void des_ctx_free( void *ctx )
+{
+    polarssl_free( ctx );
+}
+
+const cipher_base_t des_info = {
+    POLARSSL_CIPHER_ID_DES,
+    des_crypt_ecb_wrap,
+    des_crypt_cbc_wrap,
+    des_crypt_cfb128_wrap,
+    des_crypt_ctr_wrap,
+    NULL,
+    des_setkey_enc_wrap,
+    des_setkey_dec_wrap,
+    des_ctx_alloc,
+    des_ctx_free
+};
+
+const cipher_info_t des_ecb_info = {
+    POLARSSL_CIPHER_DES_ECB,
+    POLARSSL_MODE_ECB,
+    POLARSSL_KEY_LENGTH_DES,
+    "DES-ECB",
+    8,
+    0,
+    8,
+    &des_info
+};
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+const cipher_info_t des_cbc_info = {
+    POLARSSL_CIPHER_DES_CBC,
+    POLARSSL_MODE_CBC,
+    POLARSSL_KEY_LENGTH_DES,
+    "DES-CBC",
+    8,
+    0,
+    8,
+    &des_info
+};
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+const cipher_base_t des_ede_info = {
+    POLARSSL_CIPHER_ID_DES,
+    des3_crypt_ecb_wrap,
+    des3_crypt_cbc_wrap,
+    des_crypt_cfb128_wrap,
+    des_crypt_ctr_wrap,
+    NULL,
+    des3_set2key_enc_wrap,
+    des3_set2key_dec_wrap,
+    des3_ctx_alloc,
+    des_ctx_free
+};
+
+const cipher_info_t des_ede_ecb_info = {
+    POLARSSL_CIPHER_DES_EDE_ECB,
+    POLARSSL_MODE_ECB,
+    POLARSSL_KEY_LENGTH_DES_EDE,
+    "DES-EDE-ECB",
+    8,
+    0,
+    8,
+    &des_ede_info
+};
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+const cipher_info_t des_ede_cbc_info = {
+    POLARSSL_CIPHER_DES_EDE_CBC,
+    POLARSSL_MODE_CBC,
+    POLARSSL_KEY_LENGTH_DES_EDE,
+    "DES-EDE-CBC",
+    8,
+    0,
+    8,
+    &des_ede_info
+};
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+const cipher_base_t des_ede3_info = {
+    POLARSSL_CIPHER_ID_DES,
+    des3_crypt_ecb_wrap,
+    des3_crypt_cbc_wrap,
+    des_crypt_cfb128_wrap,
+    des_crypt_ctr_wrap,
+    NULL,
+    des3_set3key_enc_wrap,
+    des3_set3key_dec_wrap,
+    des3_ctx_alloc,
+    des_ctx_free
+};
+
+const cipher_info_t des_ede3_ecb_info = {
+    POLARSSL_CIPHER_DES_EDE3_ECB,
+    POLARSSL_MODE_ECB,
+    POLARSSL_KEY_LENGTH_DES_EDE3,
+    "DES-EDE3-ECB",
+    8,
+    0,
+    8,
+    &des_ede3_info
+};
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+const cipher_info_t des_ede3_cbc_info = {
+    POLARSSL_CIPHER_DES_EDE3_CBC,
+    POLARSSL_MODE_CBC,
+    POLARSSL_KEY_LENGTH_DES_EDE3,
+    "DES-EDE3-CBC",
+    8,
+    0,
+    8,
+    &des_ede3_info
+};
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#endif /* POLARSSL_DES_C */
+
+#if defined(POLARSSL_BLOWFISH_C)
+
+static int blowfish_crypt_ecb_wrap( void *ctx, operation_t operation,
+        const unsigned char *input, unsigned char *output )
+{
+    return blowfish_crypt_ecb( (blowfish_context *) ctx, operation, input,
+                               output );
+}
+
+static int blowfish_crypt_cbc_wrap( void *ctx, operation_t operation,
+        size_t length, unsigned char *iv, const unsigned char *input,
+        unsigned char *output )
+{
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    return blowfish_crypt_cbc( (blowfish_context *) ctx, operation, length, iv,
+                               input, output );
+#else
+    ((void) ctx);
+    ((void) operation);
+    ((void) length);
+    ((void) iv);
+    ((void) input);
+    ((void) output);
+
+    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+}
+
+static int blowfish_crypt_cfb64_wrap( void *ctx, operation_t operation,
+        size_t length, size_t *iv_off, unsigned char *iv,
+        const unsigned char *input, unsigned char *output )
+{
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+    return blowfish_crypt_cfb64( (blowfish_context *) ctx, operation, length,
+                                 iv_off, iv, input, output );
+#else
+    ((void) ctx);
+    ((void) operation);
+    ((void) length);
+    ((void) iv_off);
+    ((void) iv);
+    ((void) input);
+    ((void) output);
+
+    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+}
+
+static int blowfish_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off,
+        unsigned char *nonce_counter, unsigned char *stream_block,
+        const unsigned char *input, unsigned char *output )
+{
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+    return blowfish_crypt_ctr( (blowfish_context *) ctx, length, nc_off,
+                               nonce_counter, stream_block, input, output );
+#else
+    ((void) ctx);
+    ((void) length);
+    ((void) nc_off);
+    ((void) nonce_counter);
+    ((void) stream_block);
+    ((void) input);
+    ((void) output);
+
+    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+}
+
+static int blowfish_setkey_wrap( void *ctx, const unsigned char *key,
+                                 unsigned int key_length )
+{
+    return blowfish_setkey( (blowfish_context *) ctx, key, key_length );
+}
+
+static void * blowfish_ctx_alloc( void )
+{
+    return polarssl_malloc( sizeof( blowfish_context ) );
+}
+
+static void blowfish_ctx_free( void *ctx )
+{
+    polarssl_free( ctx );
+}
+
+const cipher_base_t blowfish_info = {
+    POLARSSL_CIPHER_ID_BLOWFISH,
+    blowfish_crypt_ecb_wrap,
+    blowfish_crypt_cbc_wrap,
+    blowfish_crypt_cfb64_wrap,
+    blowfish_crypt_ctr_wrap,
+    NULL,
+    blowfish_setkey_wrap,
+    blowfish_setkey_wrap,
+    blowfish_ctx_alloc,
+    blowfish_ctx_free
+};
+
+const cipher_info_t blowfish_ecb_info = {
+    POLARSSL_CIPHER_BLOWFISH_ECB,
+    POLARSSL_MODE_ECB,
+    128,
+    "BLOWFISH-ECB",
+    8,
+    0,
+    8,
+    &blowfish_info
+};
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+const cipher_info_t blowfish_cbc_info = {
+    POLARSSL_CIPHER_BLOWFISH_CBC,
+    POLARSSL_MODE_CBC,
+    128,
+    "BLOWFISH-CBC",
+    8,
+    0,
+    8,
+    &blowfish_info
+};
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+const cipher_info_t blowfish_cfb64_info = {
+    POLARSSL_CIPHER_BLOWFISH_CFB64,
+    POLARSSL_MODE_CFB,
+    128,
+    "BLOWFISH-CFB64",
+    8,
+    0,
+    8,
+    &blowfish_info
+};
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+const cipher_info_t blowfish_ctr_info = {
+    POLARSSL_CIPHER_BLOWFISH_CTR,
+    POLARSSL_MODE_CTR,
+    128,
+    "BLOWFISH-CTR",
+    8,
+    0,
+    8,
+    &blowfish_info
+};
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+#endif /* POLARSSL_BLOWFISH_C */
+
+#if defined(POLARSSL_ARC4_C)
+static int arc4_crypt_stream_wrap( void *ctx, size_t length,
+                                   const unsigned char *input,
+                                   unsigned char *output )
+{
+    return( arc4_crypt( (arc4_context *) ctx, length, input, output ) );
+}
+
+static int arc4_setkey_wrap( void *ctx, const unsigned char *key,
+                             unsigned int key_length )
+{
+    /* we get key_length in bits, arc4 expects it in bytes */
+    if( key_length % 8 != 0)
+        return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA );
+
+    arc4_setup( (arc4_context *) ctx, key, key_length / 8 );
+    return( 0 );
+}
+
+static void * arc4_ctx_alloc( void )
+{
+    return polarssl_malloc( sizeof( arc4_context ) );
+}
+
+static void arc4_ctx_free( void *ctx )
+{
+    polarssl_free( ctx );
+}
+
+const cipher_base_t arc4_base_info = {
+    POLARSSL_CIPHER_ID_ARC4,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    arc4_crypt_stream_wrap,
+    arc4_setkey_wrap,
+    arc4_setkey_wrap,
+    arc4_ctx_alloc,
+    arc4_ctx_free
+};
+
+const cipher_info_t arc4_128_info = {
+    POLARSSL_CIPHER_ARC4_128,
+    POLARSSL_MODE_STREAM,
+    128,
+    "ARC4-128",
+    0,
+    0,
+    1,
+    &arc4_base_info
+};
+#endif /* POLARSSL_ARC4_C */
+
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+static int null_crypt_stream( void *ctx, size_t length,
+                              const unsigned char *input,
+                              unsigned char *output )
+{
+    ((void) ctx);
+    memmove( output, input, length );
+    return( 0 );
+}
+
+static int null_setkey( void *ctx, const unsigned char *key,
+                        unsigned int key_length )
+{
+    ((void) ctx);
+    ((void) key);
+    ((void) key_length);
+
+    return( 0 );
+}
+
+static void * null_ctx_alloc( void )
+{
+    return (void *) 1;
+}
+
+static void null_ctx_free( void *ctx )
+{
+    ((void) ctx);
+}
+
+const cipher_base_t null_base_info = {
+    POLARSSL_CIPHER_ID_NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    null_crypt_stream,
+    null_setkey,
+    null_setkey,
+    null_ctx_alloc,
+    null_ctx_free
+};
+
+const cipher_info_t null_cipher_info = {
+    POLARSSL_CIPHER_NULL,
+    POLARSSL_MODE_STREAM,
+    0,
+    "NULL",
+    0,
+    0,
+    1,
+    &null_base_info
+};
+#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
+
+const cipher_definition_t cipher_definitions[] =
+{
+#if defined(POLARSSL_AES_C)
+    { POLARSSL_CIPHER_AES_128_ECB,          &aes_128_ecb_info },
+    { POLARSSL_CIPHER_AES_192_ECB,          &aes_192_ecb_info },
+    { POLARSSL_CIPHER_AES_256_ECB,          &aes_256_ecb_info },
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    { POLARSSL_CIPHER_AES_128_CBC,          &aes_128_cbc_info },
+    { POLARSSL_CIPHER_AES_192_CBC,          &aes_192_cbc_info },
+    { POLARSSL_CIPHER_AES_256_CBC,          &aes_256_cbc_info },
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+    { POLARSSL_CIPHER_AES_128_CFB128,       &aes_128_cfb128_info },
+    { POLARSSL_CIPHER_AES_192_CFB128,       &aes_192_cfb128_info },
+    { POLARSSL_CIPHER_AES_256_CFB128,       &aes_256_cfb128_info },
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+    { POLARSSL_CIPHER_AES_128_CTR,          &aes_128_ctr_info },
+    { POLARSSL_CIPHER_AES_192_CTR,          &aes_192_ctr_info },
+    { POLARSSL_CIPHER_AES_256_CTR,          &aes_256_ctr_info },
+#endif
+#if defined(POLARSSL_GCM_C)
+    { POLARSSL_CIPHER_AES_128_GCM,          &aes_128_gcm_info },
+    { POLARSSL_CIPHER_AES_192_GCM,          &aes_192_gcm_info },
+    { POLARSSL_CIPHER_AES_256_GCM,          &aes_256_gcm_info },
+#endif
+#endif /* POLARSSL_AES_C */
+
+#if defined(POLARSSL_ARC4_C)
+    { POLARSSL_CIPHER_ARC4_128,             &arc4_128_info },
+#endif
+
+#if defined(POLARSSL_BLOWFISH_C)
+    { POLARSSL_CIPHER_BLOWFISH_ECB,         &blowfish_ecb_info },
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    { POLARSSL_CIPHER_BLOWFISH_CBC,         &blowfish_cbc_info },
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+    { POLARSSL_CIPHER_BLOWFISH_CFB64,       &blowfish_cfb64_info },
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+    { POLARSSL_CIPHER_BLOWFISH_CTR,         &blowfish_ctr_info },
+#endif
+#endif /* POLARSSL_BLOWFISH_C */
+
+#if defined(POLARSSL_CAMELLIA_C)
+    { POLARSSL_CIPHER_CAMELLIA_128_ECB,     &camellia_128_ecb_info },
+    { POLARSSL_CIPHER_CAMELLIA_192_ECB,     &camellia_192_ecb_info },
+    { POLARSSL_CIPHER_CAMELLIA_256_ECB,     &camellia_256_ecb_info },
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    { POLARSSL_CIPHER_CAMELLIA_128_CBC,     &camellia_128_cbc_info },
+    { POLARSSL_CIPHER_CAMELLIA_192_CBC,     &camellia_192_cbc_info },
+    { POLARSSL_CIPHER_CAMELLIA_256_CBC,     &camellia_256_cbc_info },
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+    { POLARSSL_CIPHER_CAMELLIA_128_CFB128,  &camellia_128_cfb128_info },
+    { POLARSSL_CIPHER_CAMELLIA_192_CFB128,  &camellia_192_cfb128_info },
+    { POLARSSL_CIPHER_CAMELLIA_256_CFB128,  &camellia_256_cfb128_info },
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+    { POLARSSL_CIPHER_CAMELLIA_128_CTR,     &camellia_128_ctr_info },
+    { POLARSSL_CIPHER_CAMELLIA_192_CTR,     &camellia_192_ctr_info },
+    { POLARSSL_CIPHER_CAMELLIA_256_CTR,     &camellia_256_ctr_info },
+#endif
+#if defined(POLARSSL_GCM_C)
+    { POLARSSL_CIPHER_CAMELLIA_128_GCM,     &camellia_128_gcm_info },
+    { POLARSSL_CIPHER_CAMELLIA_192_GCM,     &camellia_192_gcm_info },
+    { POLARSSL_CIPHER_CAMELLIA_256_GCM,     &camellia_256_gcm_info },
+#endif
+#endif /* POLARSSL_CAMELLIA_C */
+
+#if defined(POLARSSL_DES_C)
+    { POLARSSL_CIPHER_DES_ECB,              &des_ecb_info },
+    { POLARSSL_CIPHER_DES_EDE_ECB,          &des_ede_ecb_info },
+    { POLARSSL_CIPHER_DES_EDE3_ECB,         &des_ede3_ecb_info },
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    { POLARSSL_CIPHER_DES_CBC,              &des_cbc_info },
+    { POLARSSL_CIPHER_DES_EDE_CBC,          &des_ede_cbc_info },
+    { POLARSSL_CIPHER_DES_EDE3_CBC,         &des_ede3_cbc_info },
+#endif
+#endif /* POLARSSL_DES_C */
+
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+    { POLARSSL_CIPHER_NULL,                 &null_cipher_info },
+#endif /* POLARSSL_CIPHER_NULL_CIPHER */
+
+    { 0, NULL }
+};
+
+#define NUM_CIPHERS sizeof cipher_definitions / sizeof cipher_definitions[0]
+int supported_ciphers[NUM_CIPHERS];
+
+#endif /* POLARSSL_CIPHER_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/ctr_drbg.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,532 @@
+/*
+ *  CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  The NIST SP 800-90 DRBGs are described in the following publucation.
+ *
+ *  http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_CTR_DRBG_C)
+
+#include "polarssl/ctr_drbg.h"
+
+#if defined(POLARSSL_FS_IO)
+#include <stdio.h>
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
+/*
+ * Non-public function wrapped by ctr_crbg_init(). Necessary to allow NIST
+ * tests to succeed (which require known length fixed entropy)
+ */
+int ctr_drbg_init_entropy_len(
+                   ctr_drbg_context *ctx,
+                   int (*f_entropy)(void *, unsigned char *, size_t),
+                   void *p_entropy,
+                   const unsigned char *custom,
+                   size_t len,
+                   size_t entropy_len )
+{
+    int ret;
+    unsigned char key[CTR_DRBG_KEYSIZE];
+
+    memset( ctx, 0, sizeof(ctr_drbg_context) );
+    memset( key, 0, CTR_DRBG_KEYSIZE );
+
+    ctx->f_entropy = f_entropy;
+    ctx->p_entropy = p_entropy;
+
+    ctx->entropy_len = entropy_len;
+    ctx->reseed_interval = CTR_DRBG_RESEED_INTERVAL;
+
+    /*
+     * Initialize with an empty key
+     */
+    aes_setkey_enc( &ctx->aes_ctx, key, CTR_DRBG_KEYBITS );
+
+    if( ( ret = ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
+        return( ret );
+
+    return( 0 );
+}
+
+int ctr_drbg_init( ctr_drbg_context *ctx,
+                   int (*f_entropy)(void *, unsigned char *, size_t),
+                   void *p_entropy,
+                   const unsigned char *custom,
+                   size_t len )
+{
+    return( ctr_drbg_init_entropy_len( ctx, f_entropy, p_entropy, custom, len,
+                                       CTR_DRBG_ENTROPY_LEN ) );
+}
+
+void ctr_drbg_set_prediction_resistance( ctr_drbg_context *ctx, int resistance )
+{
+    ctx->prediction_resistance = resistance;
+}
+
+void ctr_drbg_set_entropy_len( ctr_drbg_context *ctx, size_t len )
+{
+    ctx->entropy_len = len;
+}
+
+void ctr_drbg_set_reseed_interval( ctr_drbg_context *ctx, int interval )
+{
+    ctx->reseed_interval = interval;
+}
+
+static int block_cipher_df( unsigned char *output,
+                            const unsigned char *data, size_t data_len )
+{
+    unsigned char buf[CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16];
+    unsigned char tmp[CTR_DRBG_SEEDLEN];
+    unsigned char key[CTR_DRBG_KEYSIZE];
+    unsigned char chain[CTR_DRBG_BLOCKSIZE];
+    unsigned char *p, *iv;
+    aes_context aes_ctx;
+
+    int i, j;
+    size_t buf_len, use_len;
+
+    memset( buf, 0, CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16 );
+
+    /*
+     * Construct IV (16 bytes) and S in buffer
+     * IV = Counter (in 32-bits) padded to 16 with zeroes
+     * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
+     *     data || 0x80
+     *     (Total is padded to a multiple of 16-bytes with zeroes)
+     */
+    p = buf + CTR_DRBG_BLOCKSIZE;
+    *p++ = ( data_len >> 24 ) & 0xff;
+    *p++ = ( data_len >> 16 ) & 0xff;
+    *p++ = ( data_len >> 8  ) & 0xff;
+    *p++ = ( data_len       ) & 0xff;
+    p += 3;
+    *p++ = CTR_DRBG_SEEDLEN;
+    memcpy( p, data, data_len );
+    p[data_len] = 0x80;
+
+    buf_len = CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
+
+    for( i = 0; i < CTR_DRBG_KEYSIZE; i++ )
+        key[i] = i;
+
+    aes_setkey_enc( &aes_ctx, key, CTR_DRBG_KEYBITS );
+
+    /*
+     * Reduce data to POLARSSL_CTR_DRBG_SEEDLEN bytes of data
+     */
+    for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
+    {
+        p = buf;
+        memset( chain, 0, CTR_DRBG_BLOCKSIZE );
+        use_len = buf_len;
+
+        while( use_len > 0 )
+        {
+            for( i = 0; i < CTR_DRBG_BLOCKSIZE; i++ )
+                chain[i] ^= p[i];
+            p += CTR_DRBG_BLOCKSIZE;
+            use_len -= ( use_len >= CTR_DRBG_BLOCKSIZE ) ?
+                       CTR_DRBG_BLOCKSIZE : use_len;
+
+            aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, chain, chain );
+        }
+
+        memcpy( tmp + j, chain, CTR_DRBG_BLOCKSIZE );
+
+        /*
+         * Update IV
+         */
+        buf[3]++;
+    }
+
+    /*
+     * Do final encryption with reduced data
+     */
+    aes_setkey_enc( &aes_ctx, tmp, CTR_DRBG_KEYBITS );
+    iv = tmp + CTR_DRBG_KEYSIZE;
+    p = output;
+
+    for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
+    {
+        aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, iv, iv );
+        memcpy( p, iv, CTR_DRBG_BLOCKSIZE );
+        p += CTR_DRBG_BLOCKSIZE;
+    }
+
+    return( 0 );
+}
+
+static int ctr_drbg_update_internal( ctr_drbg_context *ctx,
+                              const unsigned char data[CTR_DRBG_SEEDLEN] )
+{
+    unsigned char tmp[CTR_DRBG_SEEDLEN];
+    unsigned char *p = tmp;
+    int i, j;
+
+    memset( tmp, 0, CTR_DRBG_SEEDLEN );
+
+    for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
+    {
+        /*
+         * Increase counter
+         */
+        for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
+            if( ++ctx->counter[i - 1] != 0 )
+                break;
+
+        /*
+         * Crypt counter block
+         */
+        aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, p );
+
+        p += CTR_DRBG_BLOCKSIZE;
+    }
+
+    for( i = 0; i < CTR_DRBG_SEEDLEN; i++ )
+        tmp[i] ^= data[i];
+
+    /*
+     * Update key and counter
+     */
+    aes_setkey_enc( &ctx->aes_ctx, tmp, CTR_DRBG_KEYBITS );
+    memcpy( ctx->counter, tmp + CTR_DRBG_KEYSIZE, CTR_DRBG_BLOCKSIZE );
+
+    return( 0 );
+}
+
+void ctr_drbg_update( ctr_drbg_context *ctx,
+                      const unsigned char *additional, size_t add_len )
+{
+    unsigned char add_input[CTR_DRBG_SEEDLEN];
+
+    if( add_len > 0 )
+    {
+        block_cipher_df( add_input, additional, add_len );
+        ctr_drbg_update_internal( ctx, add_input );
+    }
+}
+
+int ctr_drbg_reseed( ctr_drbg_context *ctx,
+                     const unsigned char *additional, size_t len )
+{
+    unsigned char seed[CTR_DRBG_MAX_SEED_INPUT];
+    size_t seedlen = 0;
+
+    if( ctx->entropy_len + len > CTR_DRBG_MAX_SEED_INPUT )
+        return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
+
+    memset( seed, 0, CTR_DRBG_MAX_SEED_INPUT );
+
+    /*
+     * Gather entropy_len bytes of entropy to seed state
+     */
+    if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
+                             ctx->entropy_len ) )
+    {
+        return( POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
+    }
+
+    seedlen += ctx->entropy_len;
+
+    /*
+     * Add additional data
+     */
+    if( additional && len )
+    {
+        memcpy( seed + seedlen, additional, len );
+        seedlen += len;
+    }
+
+    /*
+     * Reduce to 384 bits
+     */
+    block_cipher_df( seed, seed, seedlen );
+
+    /*
+     * Update state
+     */
+    ctr_drbg_update_internal( ctx, seed );
+    ctx->reseed_counter = 1;
+
+    return( 0 );
+}
+
+int ctr_drbg_random_with_add( void *p_rng,
+                              unsigned char *output, size_t output_len,
+                              const unsigned char *additional, size_t add_len )
+{
+    int ret = 0;
+    ctr_drbg_context *ctx = (ctr_drbg_context *) p_rng;
+    unsigned char add_input[CTR_DRBG_SEEDLEN];
+    unsigned char *p = output;
+    unsigned char tmp[CTR_DRBG_BLOCKSIZE];
+    int i;
+    size_t use_len;
+
+    if( output_len > CTR_DRBG_MAX_REQUEST )
+        return( POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG );
+
+    if( add_len > CTR_DRBG_MAX_INPUT )
+        return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
+
+    memset( add_input, 0, CTR_DRBG_SEEDLEN );
+
+    if( ctx->reseed_counter > ctx->reseed_interval ||
+        ctx->prediction_resistance )
+    {
+        if( ( ret = ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
+            return( ret );
+
+        add_len = 0;
+    }
+
+    if( add_len > 0 )
+    {
+        block_cipher_df( add_input, additional, add_len );
+        ctr_drbg_update_internal( ctx, add_input );
+    }
+
+    while( output_len > 0 )
+    {
+        /*
+         * Increase counter
+         */
+        for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
+            if( ++ctx->counter[i - 1] != 0 )
+                break;
+
+        /*
+         * Crypt counter block
+         */
+        aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, tmp );
+
+        use_len = (output_len > CTR_DRBG_BLOCKSIZE ) ? CTR_DRBG_BLOCKSIZE :
+                                                       output_len;
+        /*
+         * Copy random block to destination
+         */
+        memcpy( p, tmp, use_len );
+        p += use_len;
+        output_len -= use_len;
+    }
+
+    ctr_drbg_update_internal( ctx, add_input );
+
+    ctx->reseed_counter++;
+
+    return( 0 );
+}
+
+int ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
+{
+    return ctr_drbg_random_with_add( p_rng, output, output_len, NULL, 0 );
+}
+
+#if defined(POLARSSL_FS_IO)
+int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path )
+{
+    int ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR;
+    FILE *f;
+    unsigned char buf[ CTR_DRBG_MAX_INPUT ];
+
+    if( ( f = fopen( path, "wb" ) ) == NULL )
+        return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
+
+    if( ( ret = ctr_drbg_random( ctx, buf, CTR_DRBG_MAX_INPUT ) ) != 0 )
+        goto exit;
+
+    if( fwrite( buf, 1, CTR_DRBG_MAX_INPUT, f ) != CTR_DRBG_MAX_INPUT )
+    {
+        ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR;
+        goto exit;
+    }
+
+    ret = 0;
+
+exit:
+    fclose( f );
+    return( ret );
+}
+
+int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path )
+{
+    FILE *f;
+    size_t n;
+    unsigned char buf[ CTR_DRBG_MAX_INPUT ];
+
+    if( ( f = fopen( path, "rb" ) ) == NULL )
+        return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
+
+    fseek( f, 0, SEEK_END );
+    n = (size_t) ftell( f );
+    fseek( f, 0, SEEK_SET );
+
+    if( n > CTR_DRBG_MAX_INPUT )
+    {
+        fclose( f );
+        return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
+    }
+
+    if( fread( buf, 1, n, f ) != n )
+    {
+        fclose( f );
+        return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
+    }
+
+    fclose( f );
+
+    ctr_drbg_update( ctx, buf, n );
+
+    return( ctr_drbg_write_seed_file( ctx, path ) );
+}
+#endif /* POLARSSL_FS_IO */
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include <stdio.h>
+
+static unsigned char entropy_source_pr[96] =
+    { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
+      0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
+      0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
+      0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
+      0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
+      0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
+      0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
+      0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
+      0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
+      0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
+      0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
+      0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
+
+static unsigned char entropy_source_nopr[64] =
+    { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
+      0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
+      0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
+      0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
+      0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
+      0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
+      0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
+      0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
+
+static const unsigned char nonce_pers_pr[16] =
+    { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
+      0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
+
+static const unsigned char nonce_pers_nopr[16] =
+    { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
+      0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
+
+static const unsigned char result_pr[16] =
+    { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
+      0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
+
+static const unsigned char result_nopr[16] =
+    { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
+      0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
+
+static size_t test_offset;
+static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
+                                       size_t len )
+{
+    const unsigned char *p = data;
+    memcpy( buf, p + test_offset, len );
+    test_offset += len;
+    return( 0 );
+}
+
+#define CHK( c )    if( (c) != 0 )                          \
+                    {                                       \
+                        if( verbose != 0 )                  \
+                            polarssl_printf( "failed\n" );  \
+                        return( 1 );                        \
+                    }
+
+/*
+ * Checkup routine
+ */
+int ctr_drbg_self_test( int verbose )
+{
+    ctr_drbg_context ctx;
+    unsigned char buf[16];
+
+    /*
+     * Based on a NIST CTR_DRBG test vector (PR = True)
+     */
+    if( verbose != 0 )
+        polarssl_printf( "  CTR_DRBG (PR = TRUE) : " );
+
+    test_offset = 0;
+    CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
+                                entropy_source_pr, nonce_pers_pr, 16, 32 ) );
+    ctr_drbg_set_prediction_resistance( &ctx, CTR_DRBG_PR_ON );
+    CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) );
+    CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) );
+    CHK( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) );
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n" );
+
+    /*
+     * Based on a NIST CTR_DRBG test vector (PR = FALSE)
+     */
+    if( verbose != 0 )
+        polarssl_printf( "  CTR_DRBG (PR = FALSE): " );
+
+    test_offset = 0;
+    CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
+                            entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
+    CHK( ctr_drbg_random( &ctx, buf, 16 ) );
+    CHK( ctr_drbg_reseed( &ctx, NULL, 0 ) );
+    CHK( ctr_drbg_random( &ctx, buf, 16 ) );
+    CHK( memcmp( buf, result_nopr, 16 ) );
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n" );
+
+    if( verbose != 0 )
+            polarssl_printf( "\n" );
+
+    return( 0 );
+}
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_CTR_DRBG_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/debug.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,353 @@
+/*
+ *  Debugging routines
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_DEBUG_C)
+
+#include "polarssl/debug.h"
+
+#include <stdarg.h>
+#include <stdlib.h>
+
+#if defined(EFIX64) || defined(EFI32)
+#include <stdio.h>
+#endif
+
+#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
+#if !defined  snprintf
+#define  snprintf  _snprintf
+#endif
+
+#if !defined vsnprintf
+#define vsnprintf _vsnprintf
+#endif
+#endif /* _MSC_VER */
+
+static int debug_log_mode = POLARSSL_DEBUG_DFL_MODE;
+static int debug_threshold = 0;
+
+void debug_set_log_mode( int log_mode )
+{
+    debug_log_mode = log_mode;
+}
+
+void debug_set_threshold( int threshold )
+{
+    debug_threshold = threshold;
+}
+
+char *debug_fmt( const char *format, ... )
+{
+    va_list argp;
+    static char str[512];
+    int maxlen = sizeof( str ) - 1;
+
+    va_start( argp, format );
+    vsnprintf( str, maxlen, format, argp );
+    va_end( argp );
+
+    str[maxlen] = '\0';
+    return( str );
+}
+
+void debug_print_msg( const ssl_context *ssl, int level,
+                      const char *file, int line, const char *text )
+{
+    char str[512];
+    int maxlen = sizeof( str ) - 1;
+
+    if( ssl->f_dbg == NULL || level > debug_threshold )
+        return;
+
+    if( debug_log_mode == POLARSSL_DEBUG_LOG_RAW )
+    {
+        ssl->f_dbg( ssl->p_dbg, level, str );
+        return;
+    }
+
+    snprintf( str, maxlen, "%s(%04d): %s\n", file, line, text );
+    str[maxlen] = '\0';
+    ssl->f_dbg( ssl->p_dbg, level, str );
+}
+
+void debug_print_ret( const ssl_context *ssl, int level,
+                      const char *file, int line,
+                      const char *text, int ret )
+{
+    char str[512];
+    int maxlen = sizeof( str ) - 1;
+    size_t idx = 0;
+
+    if( ssl->f_dbg == NULL || level > debug_threshold )
+        return;
+
+    if( debug_log_mode == POLARSSL_DEBUG_LOG_FULL )
+        idx = snprintf( str, maxlen, "%s(%04d): ", file, line );
+
+    snprintf( str + idx, maxlen - idx, "%s() returned %d (-0x%04x)\n",
+              text, ret, -ret );
+
+    str[maxlen] = '\0';
+    ssl->f_dbg( ssl->p_dbg, level, str );
+}
+
+void debug_print_buf( const ssl_context *ssl, int level,
+                      const char *file, int line, const char *text,
+                      unsigned char *buf, size_t len )
+{
+    char str[512];
+    size_t i, maxlen = sizeof( str ) - 1, idx = 0;
+
+    if( ssl->f_dbg == NULL || level > debug_threshold )
+        return;
+
+    if( debug_log_mode == POLARSSL_DEBUG_LOG_FULL )
+        idx = snprintf( str, maxlen, "%s(%04d): ", file, line );
+
+    snprintf( str + idx, maxlen - idx, "dumping '%s' (%d bytes)\n",
+              text, (unsigned int) len );
+
+    str[maxlen] = '\0';
+    ssl->f_dbg( ssl->p_dbg, level, str );
+
+    idx = 0;
+    for( i = 0; i < len; i++ )
+    {
+        if( i >= 4096 )
+            break;
+
+        if( i % 16 == 0 )
+        {
+            if( i > 0 )
+            {
+                snprintf( str + idx, maxlen - idx, "\n" );
+                ssl->f_dbg( ssl->p_dbg, level, str );
+                idx = 0;
+            }
+
+            if( debug_log_mode == POLARSSL_DEBUG_LOG_FULL )
+                idx = snprintf( str, maxlen, "%s(%04d): ", file, line );
+
+            idx += snprintf( str + idx, maxlen - idx, "%04x: ",
+                             (unsigned int) i );
+
+        }
+
+        idx += snprintf( str + idx, maxlen - idx, " %02x",
+                         (unsigned int) buf[i] );
+    }
+
+    if( len > 0 )
+    {
+        snprintf( str + idx, maxlen - idx, "\n" );
+        ssl->f_dbg( ssl->p_dbg, level, str );
+    }
+}
+
+#if defined(POLARSSL_ECP_C)
+void debug_print_ecp( const ssl_context *ssl, int level,
+                      const char *file, int line,
+                      const char *text, const ecp_point *X )
+{
+    char str[512];
+    int maxlen = sizeof( str ) - 1;
+
+    if( ssl->f_dbg == NULL || level > debug_threshold )
+        return;
+
+    snprintf( str, maxlen, "%s(X)", text );
+    str[maxlen] = '\0';
+    debug_print_mpi( ssl, level, file, line, str, &X->X );
+
+    snprintf( str, maxlen, "%s(Y)", text );
+    str[maxlen] = '\0';
+    debug_print_mpi( ssl, level, file, line, str, &X->Y );
+}
+#endif /* POLARSSL_ECP_C */
+
+#if defined(POLARSSL_BIGNUM_C)
+void debug_print_mpi( const ssl_context *ssl, int level,
+                      const char *file, int line,
+                      const char *text, const mpi *X )
+{
+    char str[512];
+    int j, k, maxlen = sizeof( str ) - 1, zeros = 1;
+    size_t i, n, idx = 0;
+
+    if( ssl->f_dbg == NULL || X == NULL || level > debug_threshold )
+        return;
+
+    for( n = X->n - 1; n > 0; n-- )
+        if( X->p[n] != 0 )
+            break;
+
+    for( j = ( sizeof(t_uint) << 3 ) - 1; j >= 0; j-- )
+        if( ( ( X->p[n] >> j ) & 1 ) != 0 )
+            break;
+
+    if( debug_log_mode == POLARSSL_DEBUG_LOG_FULL )
+        idx = snprintf( str, maxlen, "%s(%04d): ", file, line );
+
+    snprintf( str + idx, maxlen - idx, "value of '%s' (%d bits) is:\n",
+              text, (int) ( ( n * ( sizeof(t_uint) << 3 ) ) + j + 1 ) );
+
+    str[maxlen] = '\0';
+    ssl->f_dbg( ssl->p_dbg, level, str );
+
+    idx = 0;
+    for( i = n + 1, j = 0; i > 0; i-- )
+    {
+        if( zeros && X->p[i - 1] == 0 )
+            continue;
+
+        for( k = sizeof( t_uint ) - 1; k >= 0; k-- )
+        {
+            if( zeros && ( ( X->p[i - 1] >> (k << 3) ) & 0xFF ) == 0 )
+                continue;
+            else
+                zeros = 0;
+
+            if( j % 16 == 0 )
+            {
+                if( j > 0 )
+                {
+                    snprintf( str + idx, maxlen - idx, "\n" );
+                    ssl->f_dbg( ssl->p_dbg, level, str );
+                    idx = 0;
+                }
+
+                if( debug_log_mode == POLARSSL_DEBUG_LOG_FULL )
+                    idx = snprintf( str, maxlen, "%s(%04d): ", file, line );
+            }
+
+            idx += snprintf( str + idx, maxlen - idx, " %02x", (unsigned int)
+                             ( X->p[i - 1] >> (k << 3) ) & 0xFF );
+
+            j++;
+        }
+
+    }
+
+    if( zeros == 1 )
+    {
+        if( debug_log_mode == POLARSSL_DEBUG_LOG_FULL )
+        {
+            idx = snprintf( str, maxlen, "%s(%04d): ", file, line );
+
+        }
+        idx += snprintf( str + idx, maxlen - idx, " 00" );
+    }
+
+    snprintf( str + idx, maxlen - idx, "\n" );
+    ssl->f_dbg( ssl->p_dbg, level, str );
+}
+#endif /* POLARSSL_BIGNUM_C */
+
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+static void debug_print_pk( const ssl_context *ssl, int level,
+                            const char *file, int line,
+                            const char *text, const pk_context *pk )
+{
+    size_t i;
+    pk_debug_item items[POLARSSL_PK_DEBUG_MAX_ITEMS];
+    char name[16];
+
+    memset( items, 0, sizeof( items ) );
+
+    if( pk_debug( pk, items ) != 0 )
+    {
+        debug_print_msg( ssl, level, file, line, "invalid PK context" );
+        return;
+    }
+
+    for( i = 0; i < POLARSSL_PK_DEBUG_MAX_ITEMS; i++ )
+    {
+        if( items[i].type == POLARSSL_PK_DEBUG_NONE )
+            return;
+
+        snprintf( name, sizeof( name ), "%s%s", text, items[i].name );
+        name[sizeof( name ) - 1] = '\0';
+
+        if( items[i].type == POLARSSL_PK_DEBUG_MPI )
+            debug_print_mpi( ssl, level, file, line, name, items[i].value );
+        else
+#if defined(POLARSSL_ECP_C)
+        if( items[i].type == POLARSSL_PK_DEBUG_ECP )
+            debug_print_ecp( ssl, level, file, line, name, items[i].value );
+        else
+#endif
+            debug_print_msg( ssl, level, file, line, "should not happen" );
+    }
+}
+
+void debug_print_crt( const ssl_context *ssl, int level,
+                      const char *file, int line,
+                      const char *text, const x509_crt *crt )
+{
+    char str[1024], prefix[64];
+    int i = 0, maxlen = sizeof( prefix ) - 1, idx = 0;
+
+    if( ssl->f_dbg == NULL || crt == NULL || level > debug_threshold )
+        return;
+
+    if( debug_log_mode == POLARSSL_DEBUG_LOG_FULL )
+    {
+        snprintf( prefix, maxlen, "%s(%04d): ", file, line );
+        prefix[maxlen] = '\0';
+    }
+    else
+        prefix[0] = '\0';
+
+    maxlen = sizeof( str ) - 1;
+
+    while( crt != NULL )
+    {
+        char buf[1024];
+        x509_crt_info( buf, sizeof( buf ) - 1, prefix, crt );
+
+        if( debug_log_mode == POLARSSL_DEBUG_LOG_FULL )
+            idx = snprintf( str, maxlen, "%s(%04d): ", file, line );
+
+        snprintf( str + idx, maxlen - idx, "%s #%d:\n%s",
+                  text, ++i, buf );
+
+        str[maxlen] = '\0';
+        ssl->f_dbg( ssl->p_dbg, level, str );
+
+        debug_print_pk( ssl, level, file, line, "crt->", &crt->pk );
+
+        crt = crt->next;
+    }
+}
+#endif /* POLARSSL_X509_CRT_PARSE_C */
+
+#endif /* POLARSSL_DEBUG_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/des.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,1023 @@
+/*
+ *  FIPS-46-3 compliant Triple-DES implementation
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  DES, on which TDES is based, was originally designed by Horst Feistel
+ *  at IBM in 1974, and was adopted as a standard by NIST (formerly NBS).
+ *
+ *  http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_DES_C)
+
+#include "polarssl/des.h"
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
+#if !defined(POLARSSL_DES_ALT)
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i)                            \
+{                                                       \
+    (n) = ( (uint32_t) (b)[(i)    ] << 24 )             \
+        | ( (uint32_t) (b)[(i) + 1] << 16 )             \
+        | ( (uint32_t) (b)[(i) + 2] <<  8 )             \
+        | ( (uint32_t) (b)[(i) + 3]       );            \
+}
+#endif
+
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i)                            \
+{                                                       \
+    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
+    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
+    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
+    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
+}
+#endif
+
+/*
+ * Expanded DES S-boxes
+ */
+static const uint32_t SB1[64] =
+{
+    0x01010400, 0x00000000, 0x00010000, 0x01010404,
+    0x01010004, 0x00010404, 0x00000004, 0x00010000,
+    0x00000400, 0x01010400, 0x01010404, 0x00000400,
+    0x01000404, 0x01010004, 0x01000000, 0x00000004,
+    0x00000404, 0x01000400, 0x01000400, 0x00010400,
+    0x00010400, 0x01010000, 0x01010000, 0x01000404,
+    0x00010004, 0x01000004, 0x01000004, 0x00010004,
+    0x00000000, 0x00000404, 0x00010404, 0x01000000,
+    0x00010000, 0x01010404, 0x00000004, 0x01010000,
+    0x01010400, 0x01000000, 0x01000000, 0x00000400,
+    0x01010004, 0x00010000, 0x00010400, 0x01000004,
+    0x00000400, 0x00000004, 0x01000404, 0x00010404,
+    0x01010404, 0x00010004, 0x01010000, 0x01000404,
+    0x01000004, 0x00000404, 0x00010404, 0x01010400,
+    0x00000404, 0x01000400, 0x01000400, 0x00000000,
+    0x00010004, 0x00010400, 0x00000000, 0x01010004
+};
+
+static const uint32_t SB2[64] =
+{
+    0x80108020, 0x80008000, 0x00008000, 0x00108020,
+    0x00100000, 0x00000020, 0x80100020, 0x80008020,
+    0x80000020, 0x80108020, 0x80108000, 0x80000000,
+    0x80008000, 0x00100000, 0x00000020, 0x80100020,
+    0x00108000, 0x00100020, 0x80008020, 0x00000000,
+    0x80000000, 0x00008000, 0x00108020, 0x80100000,
+    0x00100020, 0x80000020, 0x00000000, 0x00108000,
+    0x00008020, 0x80108000, 0x80100000, 0x00008020,
+    0x00000000, 0x00108020, 0x80100020, 0x00100000,
+    0x80008020, 0x80100000, 0x80108000, 0x00008000,
+    0x80100000, 0x80008000, 0x00000020, 0x80108020,
+    0x00108020, 0x00000020, 0x00008000, 0x80000000,
+    0x00008020, 0x80108000, 0x00100000, 0x80000020,
+    0x00100020, 0x80008020, 0x80000020, 0x00100020,
+    0x00108000, 0x00000000, 0x80008000, 0x00008020,
+    0x80000000, 0x80100020, 0x80108020, 0x00108000
+};
+
+static const uint32_t SB3[64] =
+{
+    0x00000208, 0x08020200, 0x00000000, 0x08020008,
+    0x08000200, 0x00000000, 0x00020208, 0x08000200,
+    0x00020008, 0x08000008, 0x08000008, 0x00020000,
+    0x08020208, 0x00020008, 0x08020000, 0x00000208,
+    0x08000000, 0x00000008, 0x08020200, 0x00000200,
+    0x00020200, 0x08020000, 0x08020008, 0x00020208,
+    0x08000208, 0x00020200, 0x00020000, 0x08000208,
+    0x00000008, 0x08020208, 0x00000200, 0x08000000,
+    0x08020200, 0x08000000, 0x00020008, 0x00000208,
+    0x00020000, 0x08020200, 0x08000200, 0x00000000,
+    0x00000200, 0x00020008, 0x08020208, 0x08000200,
+    0x08000008, 0x00000200, 0x00000000, 0x08020008,
+    0x08000208, 0x00020000, 0x08000000, 0x08020208,
+    0x00000008, 0x00020208, 0x00020200, 0x08000008,
+    0x08020000, 0x08000208, 0x00000208, 0x08020000,
+    0x00020208, 0x00000008, 0x08020008, 0x00020200
+};
+
+static const uint32_t SB4[64] =
+{
+    0x00802001, 0x00002081, 0x00002081, 0x00000080,
+    0x00802080, 0x00800081, 0x00800001, 0x00002001,
+    0x00000000, 0x00802000, 0x00802000, 0x00802081,
+    0x00000081, 0x00000000, 0x00800080, 0x00800001,
+    0x00000001, 0x00002000, 0x00800000, 0x00802001,
+    0x00000080, 0x00800000, 0x00002001, 0x00002080,
+    0x00800081, 0x00000001, 0x00002080, 0x00800080,
+    0x00002000, 0x00802080, 0x00802081, 0x00000081,
+    0x00800080, 0x00800001, 0x00802000, 0x00802081,
+    0x00000081, 0x00000000, 0x00000000, 0x00802000,
+    0x00002080, 0x00800080, 0x00800081, 0x00000001,
+    0x00802001, 0x00002081, 0x00002081, 0x00000080,
+    0x00802081, 0x00000081, 0x00000001, 0x00002000,
+    0x00800001, 0x00002001, 0x00802080, 0x00800081,
+    0x00002001, 0x00002080, 0x00800000, 0x00802001,
+    0x00000080, 0x00800000, 0x00002000, 0x00802080
+};
+
+static const uint32_t SB5[64] =
+{
+    0x00000100, 0x02080100, 0x02080000, 0x42000100,
+    0x00080000, 0x00000100, 0x40000000, 0x02080000,
+    0x40080100, 0x00080000, 0x02000100, 0x40080100,
+    0x42000100, 0x42080000, 0x00080100, 0x40000000,
+    0x02000000, 0x40080000, 0x40080000, 0x00000000,
+    0x40000100, 0x42080100, 0x42080100, 0x02000100,
+    0x42080000, 0x40000100, 0x00000000, 0x42000000,
+    0x02080100, 0x02000000, 0x42000000, 0x00080100,
+    0x00080000, 0x42000100, 0x00000100, 0x02000000,
+    0x40000000, 0x02080000, 0x42000100, 0x40080100,
+    0x02000100, 0x40000000, 0x42080000, 0x02080100,
+    0x40080100, 0x00000100, 0x02000000, 0x42080000,
+    0x42080100, 0x00080100, 0x42000000, 0x42080100,
+    0x02080000, 0x00000000, 0x40080000, 0x42000000,
+    0x00080100, 0x02000100, 0x40000100, 0x00080000,
+    0x00000000, 0x40080000, 0x02080100, 0x40000100
+};
+
+static const uint32_t SB6[64] =
+{
+    0x20000010, 0x20400000, 0x00004000, 0x20404010,
+    0x20400000, 0x00000010, 0x20404010, 0x00400000,
+    0x20004000, 0x00404010, 0x00400000, 0x20000010,
+    0x00400010, 0x20004000, 0x20000000, 0x00004010,
+    0x00000000, 0x00400010, 0x20004010, 0x00004000,
+    0x00404000, 0x20004010, 0x00000010, 0x20400010,
+    0x20400010, 0x00000000, 0x00404010, 0x20404000,
+    0x00004010, 0x00404000, 0x20404000, 0x20000000,
+    0x20004000, 0x00000010, 0x20400010, 0x00404000,
+    0x20404010, 0x00400000, 0x00004010, 0x20000010,
+    0x00400000, 0x20004000, 0x20000000, 0x00004010,
+    0x20000010, 0x20404010, 0x00404000, 0x20400000,
+    0x00404010, 0x20404000, 0x00000000, 0x20400010,
+    0x00000010, 0x00004000, 0x20400000, 0x00404010,
+    0x00004000, 0x00400010, 0x20004010, 0x00000000,
+    0x20404000, 0x20000000, 0x00400010, 0x20004010
+};
+
+static const uint32_t SB7[64] =
+{
+    0x00200000, 0x04200002, 0x04000802, 0x00000000,
+    0x00000800, 0x04000802, 0x00200802, 0x04200800,
+    0x04200802, 0x00200000, 0x00000000, 0x04000002,
+    0x00000002, 0x04000000, 0x04200002, 0x00000802,
+    0x04000800, 0x00200802, 0x00200002, 0x04000800,
+    0x04000002, 0x04200000, 0x04200800, 0x00200002,
+    0x04200000, 0x00000800, 0x00000802, 0x04200802,
+    0x00200800, 0x00000002, 0x04000000, 0x00200800,
+    0x04000000, 0x00200800, 0x00200000, 0x04000802,
+    0x04000802, 0x04200002, 0x04200002, 0x00000002,
+    0x00200002, 0x04000000, 0x04000800, 0x00200000,
+    0x04200800, 0x00000802, 0x00200802, 0x04200800,
+    0x00000802, 0x04000002, 0x04200802, 0x04200000,
+    0x00200800, 0x00000000, 0x00000002, 0x04200802,
+    0x00000000, 0x00200802, 0x04200000, 0x00000800,
+    0x04000002, 0x04000800, 0x00000800, 0x00200002
+};
+
+static const uint32_t SB8[64] =
+{
+    0x10001040, 0x00001000, 0x00040000, 0x10041040,
+    0x10000000, 0x10001040, 0x00000040, 0x10000000,
+    0x00040040, 0x10040000, 0x10041040, 0x00041000,
+    0x10041000, 0x00041040, 0x00001000, 0x00000040,
+    0x10040000, 0x10000040, 0x10001000, 0x00001040,
+    0x00041000, 0x00040040, 0x10040040, 0x10041000,
+    0x00001040, 0x00000000, 0x00000000, 0x10040040,
+    0x10000040, 0x10001000, 0x00041040, 0x00040000,
+    0x00041040, 0x00040000, 0x10041000, 0x00001000,
+    0x00000040, 0x10040040, 0x00001000, 0x00041040,
+    0x10001000, 0x00000040, 0x10000040, 0x10040000,
+    0x10040040, 0x10000000, 0x00040000, 0x10001040,
+    0x00000000, 0x10041040, 0x00040040, 0x10000040,
+    0x10040000, 0x10001000, 0x10001040, 0x00000000,
+    0x10041040, 0x00041000, 0x00041000, 0x00001040,
+    0x00001040, 0x00040040, 0x10000000, 0x10041000
+};
+
+/*
+ * PC1: left and right halves bit-swap
+ */
+static const uint32_t LHs[16] =
+{
+    0x00000000, 0x00000001, 0x00000100, 0x00000101,
+    0x00010000, 0x00010001, 0x00010100, 0x00010101,
+    0x01000000, 0x01000001, 0x01000100, 0x01000101,
+    0x01010000, 0x01010001, 0x01010100, 0x01010101
+};
+
+static const uint32_t RHs[16] =
+{
+    0x00000000, 0x01000000, 0x00010000, 0x01010000,
+    0x00000100, 0x01000100, 0x00010100, 0x01010100,
+    0x00000001, 0x01000001, 0x00010001, 0x01010001,
+    0x00000101, 0x01000101, 0x00010101, 0x01010101,
+};
+
+/*
+ * Initial Permutation macro
+ */
+#define DES_IP(X,Y)                                             \
+{                                                               \
+    T = ((X >>  4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T <<  4);   \
+    T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16);   \
+    T = ((Y >>  2) ^ X) & 0x33333333; X ^= T; Y ^= (T <<  2);   \
+    T = ((Y >>  8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T <<  8);   \
+    Y = ((Y << 1) | (Y >> 31)) & 0xFFFFFFFF;                    \
+    T = (X ^ Y) & 0xAAAAAAAA; Y ^= T; X ^= T;                   \
+    X = ((X << 1) | (X >> 31)) & 0xFFFFFFFF;                    \
+}
+
+/*
+ * Final Permutation macro
+ */
+#define DES_FP(X,Y)                                             \
+{                                                               \
+    X = ((X << 31) | (X >> 1)) & 0xFFFFFFFF;                    \
+    T = (X ^ Y) & 0xAAAAAAAA; X ^= T; Y ^= T;                   \
+    Y = ((Y << 31) | (Y >> 1)) & 0xFFFFFFFF;                    \
+    T = ((Y >>  8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T <<  8);   \
+    T = ((Y >>  2) ^ X) & 0x33333333; X ^= T; Y ^= (T <<  2);   \
+    T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16);   \
+    T = ((X >>  4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T <<  4);   \
+}
+
+/*
+ * DES round macro
+ */
+#define DES_ROUND(X,Y)                          \
+{                                               \
+    T = *SK++ ^ X;                              \
+    Y ^= SB8[ (T      ) & 0x3F ] ^              \
+         SB6[ (T >>  8) & 0x3F ] ^              \
+         SB4[ (T >> 16) & 0x3F ] ^              \
+         SB2[ (T >> 24) & 0x3F ];               \
+                                                \
+    T = *SK++ ^ ((X << 28) | (X >> 4));         \
+    Y ^= SB7[ (T      ) & 0x3F ] ^              \
+         SB5[ (T >>  8) & 0x3F ] ^              \
+         SB3[ (T >> 16) & 0x3F ] ^              \
+         SB1[ (T >> 24) & 0x3F ];               \
+}
+
+#define SWAP(a,b) { uint32_t t = a; a = b; b = t; t = 0; }
+
+static const unsigned char odd_parity_table[128] = { 1,  2,  4,  7,  8,
+        11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44,
+        47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81,
+        82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112,
+        115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140,
+        143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168,
+        171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196,
+        199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224,
+        227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253,
+        254 };
+
+void des_key_set_parity( unsigned char key[DES_KEY_SIZE] )
+{
+    int i;
+
+    for( i = 0; i < DES_KEY_SIZE; i++ )
+        key[i] = odd_parity_table[key[i] / 2];
+}
+
+/*
+ * Check the given key's parity, returns 1 on failure, 0 on SUCCESS
+ */
+int des_key_check_key_parity( const unsigned char key[DES_KEY_SIZE] )
+{
+    int i;
+
+    for( i = 0; i < DES_KEY_SIZE; i++ )
+        if ( key[i] != odd_parity_table[key[i] / 2] )
+            return( 1 );
+
+    return( 0 );
+}
+
+/*
+ * Table of weak and semi-weak keys
+ *
+ * Source: http://en.wikipedia.org/wiki/Weak_key
+ *
+ * Weak:
+ * Alternating ones + zeros (0x0101010101010101)
+ * Alternating 'F' + 'E' (0xFEFEFEFEFEFEFEFE)
+ * '0xE0E0E0E0F1F1F1F1'
+ * '0x1F1F1F1F0E0E0E0E'
+ *
+ * Semi-weak:
+ * 0x011F011F010E010E and 0x1F011F010E010E01
+ * 0x01E001E001F101F1 and 0xE001E001F101F101
+ * 0x01FE01FE01FE01FE and 0xFE01FE01FE01FE01
+ * 0x1FE01FE00EF10EF1 and 0xE01FE01FF10EF10E
+ * 0x1FFE1FFE0EFE0EFE and 0xFE1FFE1FFE0EFE0E
+ * 0xE0FEE0FEF1FEF1FE and 0xFEE0FEE0FEF1FEF1
+ *
+ */
+
+#define WEAK_KEY_COUNT 16
+
+static const unsigned char weak_key_table[WEAK_KEY_COUNT][DES_KEY_SIZE] =
+{
+    { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+    { 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE },
+    { 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E },
+    { 0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1 },
+
+    { 0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E },
+    { 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01 },
+    { 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1 },
+    { 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01 },
+    { 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE },
+    { 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01 },
+    { 0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1 },
+    { 0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E },
+    { 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE },
+    { 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E },
+    { 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE },
+    { 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1 }
+};
+
+int des_key_check_weak( const unsigned char key[DES_KEY_SIZE] )
+{
+    int i;
+
+    for( i = 0; i < WEAK_KEY_COUNT; i++ )
+        if( memcmp( weak_key_table[i], key, DES_KEY_SIZE) == 0)
+            return( 1 );
+
+    return( 0 );
+}
+
+static void des_setkey( uint32_t SK[32], const unsigned char key[DES_KEY_SIZE] )
+{
+    int i;
+    uint32_t X, Y, T;
+
+    GET_UINT32_BE( X, key, 0 );
+    GET_UINT32_BE( Y, key, 4 );
+
+    /*
+     * Permuted Choice 1
+     */
+    T =  ((Y >>  4) ^ X) & 0x0F0F0F0F;  X ^= T; Y ^= (T <<  4);
+    T =  ((Y      ) ^ X) & 0x10101010;  X ^= T; Y ^= (T      );
+
+    X =   (LHs[ (X      ) & 0xF] << 3) | (LHs[ (X >>  8) & 0xF ] << 2)
+        | (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ]     )
+        | (LHs[ (X >>  5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6)
+        | (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4);
+
+    Y =   (RHs[ (Y >>  1) & 0xF] << 3) | (RHs[ (Y >>  9) & 0xF ] << 2)
+        | (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ]     )
+        | (RHs[ (Y >>  4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6)
+        | (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4);
+
+    X &= 0x0FFFFFFF;
+    Y &= 0x0FFFFFFF;
+
+    /*
+     * calculate subkeys
+     */
+    for( i = 0; i < 16; i++ )
+    {
+        if( i < 2 || i == 8 || i == 15 )
+        {
+            X = ((X <<  1) | (X >> 27)) & 0x0FFFFFFF;
+            Y = ((Y <<  1) | (Y >> 27)) & 0x0FFFFFFF;
+        }
+        else
+        {
+            X = ((X <<  2) | (X >> 26)) & 0x0FFFFFFF;
+            Y = ((Y <<  2) | (Y >> 26)) & 0x0FFFFFFF;
+        }
+
+        *SK++ =   ((X <<  4) & 0x24000000) | ((X << 28) & 0x10000000)
+                | ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000)
+                | ((X <<  6) & 0x01000000) | ((X <<  9) & 0x00200000)
+                | ((X >>  1) & 0x00100000) | ((X << 10) & 0x00040000)
+                | ((X <<  2) & 0x00020000) | ((X >> 10) & 0x00010000)
+                | ((Y >> 13) & 0x00002000) | ((Y >>  4) & 0x00001000)
+                | ((Y <<  6) & 0x00000800) | ((Y >>  1) & 0x00000400)
+                | ((Y >> 14) & 0x00000200) | ((Y      ) & 0x00000100)
+                | ((Y >>  5) & 0x00000020) | ((Y >> 10) & 0x00000010)
+                | ((Y >>  3) & 0x00000008) | ((Y >> 18) & 0x00000004)
+                | ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001);
+
+        *SK++ =   ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000)
+                | ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000)
+                | ((X >>  2) & 0x02000000) | ((X <<  1) & 0x01000000)
+                | ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000)
+                | ((X <<  3) & 0x00080000) | ((X >>  6) & 0x00040000)
+                | ((X << 15) & 0x00020000) | ((X >>  4) & 0x00010000)
+                | ((Y >>  2) & 0x00002000) | ((Y <<  8) & 0x00001000)
+                | ((Y >> 14) & 0x00000808) | ((Y >>  9) & 0x00000400)
+                | ((Y      ) & 0x00000200) | ((Y <<  7) & 0x00000100)
+                | ((Y >>  7) & 0x00000020) | ((Y >>  3) & 0x00000011)
+                | ((Y <<  2) & 0x00000004) | ((Y >> 21) & 0x00000002);
+    }
+}
+
+/*
+ * DES key schedule (56-bit, encryption)
+ */
+int des_setkey_enc( des_context *ctx, const unsigned char key[DES_KEY_SIZE] )
+{
+    des_setkey( ctx->sk, key );
+
+    return( 0 );
+}
+
+/*
+ * DES key schedule (56-bit, decryption)
+ */
+int des_setkey_dec( des_context *ctx, const unsigned char key[DES_KEY_SIZE] )
+{
+    int i;
+
+    des_setkey( ctx->sk, key );
+
+    for( i = 0; i < 16; i += 2 )
+    {
+        SWAP( ctx->sk[i    ], ctx->sk[30 - i] );
+        SWAP( ctx->sk[i + 1], ctx->sk[31 - i] );
+    }
+
+    return( 0 );
+}
+
+static void des3_set2key( uint32_t esk[96],
+                          uint32_t dsk[96],
+                          const unsigned char key[DES_KEY_SIZE*2] )
+{
+    int i;
+
+    des_setkey( esk, key );
+    des_setkey( dsk + 32, key + 8 );
+
+    for( i = 0; i < 32; i += 2 )
+    {
+        dsk[i     ] = esk[30 - i];
+        dsk[i +  1] = esk[31 - i];
+
+        esk[i + 32] = dsk[62 - i];
+        esk[i + 33] = dsk[63 - i];
+
+        esk[i + 64] = esk[i    ];
+        esk[i + 65] = esk[i + 1];
+
+        dsk[i + 64] = dsk[i    ];
+        dsk[i + 65] = dsk[i + 1];
+    }
+}
+
+/*
+ * Triple-DES key schedule (112-bit, encryption)
+ */
+int des3_set2key_enc( des3_context *ctx,
+                      const unsigned char key[DES_KEY_SIZE * 2] )
+{
+    uint32_t sk[96];
+
+    des3_set2key( ctx->sk, sk, key );
+    memset( sk,  0, sizeof( sk ) );
+
+    return( 0 );
+}
+
+/*
+ * Triple-DES key schedule (112-bit, decryption)
+ */
+int des3_set2key_dec( des3_context *ctx,
+                      const unsigned char key[DES_KEY_SIZE * 2] )
+{
+    uint32_t sk[96];
+
+    des3_set2key( sk, ctx->sk, key );
+    memset( sk,  0, sizeof( sk ) );
+
+    return( 0 );
+}
+
+static void des3_set3key( uint32_t esk[96],
+                          uint32_t dsk[96],
+                          const unsigned char key[24] )
+{
+    int i;
+
+    des_setkey( esk, key );
+    des_setkey( dsk + 32, key +  8 );
+    des_setkey( esk + 64, key + 16 );
+
+    for( i = 0; i < 32; i += 2 )
+    {
+        dsk[i     ] = esk[94 - i];
+        dsk[i +  1] = esk[95 - i];
+
+        esk[i + 32] = dsk[62 - i];
+        esk[i + 33] = dsk[63 - i];
+
+        dsk[i + 64] = esk[30 - i];
+        dsk[i + 65] = esk[31 - i];
+    }
+}
+
+/*
+ * Triple-DES key schedule (168-bit, encryption)
+ */
+int des3_set3key_enc( des3_context *ctx,
+                      const unsigned char key[DES_KEY_SIZE * 3] )
+{
+    uint32_t sk[96];
+
+    des3_set3key( ctx->sk, sk, key );
+    memset( sk, 0, sizeof( sk ) );
+
+    return( 0 );
+}
+
+/*
+ * Triple-DES key schedule (168-bit, decryption)
+ */
+int des3_set3key_dec( des3_context *ctx,
+                      const unsigned char key[DES_KEY_SIZE * 3] )
+{
+    uint32_t sk[96];
+
+    des3_set3key( sk, ctx->sk, key );
+    memset( sk, 0, sizeof( sk ) );
+
+    return( 0 );
+}
+
+/*
+ * DES-ECB block encryption/decryption
+ */
+int des_crypt_ecb( des_context *ctx,
+                    const unsigned char input[8],
+                    unsigned char output[8] )
+{
+    int i;
+    uint32_t X, Y, T, *SK;
+
+    SK = ctx->sk;
+
+    GET_UINT32_BE( X, input, 0 );
+    GET_UINT32_BE( Y, input, 4 );
+
+    DES_IP( X, Y );
+
+    for( i = 0; i < 8; i++ )
+    {
+        DES_ROUND( Y, X );
+        DES_ROUND( X, Y );
+    }
+
+    DES_FP( Y, X );
+
+    PUT_UINT32_BE( Y, output, 0 );
+    PUT_UINT32_BE( X, output, 4 );
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+/*
+ * DES-CBC buffer encryption/decryption
+ */
+int des_crypt_cbc( des_context *ctx,
+                    int mode,
+                    size_t length,
+                    unsigned char iv[8],
+                    const unsigned char *input,
+                    unsigned char *output )
+{
+    int i;
+    unsigned char temp[8];
+
+    if( length % 8 )
+        return( POLARSSL_ERR_DES_INVALID_INPUT_LENGTH );
+
+    if( mode == DES_ENCRYPT )
+    {
+        while( length > 0 )
+        {
+            for( i = 0; i < 8; i++ )
+                output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+            des_crypt_ecb( ctx, output, output );
+            memcpy( iv, output, 8 );
+
+            input  += 8;
+            output += 8;
+            length -= 8;
+        }
+    }
+    else /* DES_DECRYPT */
+    {
+        while( length > 0 )
+        {
+            memcpy( temp, input, 8 );
+            des_crypt_ecb( ctx, input, output );
+
+            for( i = 0; i < 8; i++ )
+                output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+            memcpy( iv, temp, 8 );
+
+            input  += 8;
+            output += 8;
+            length -= 8;
+        }
+    }
+
+    return( 0 );
+}
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+/*
+ * 3DES-ECB block encryption/decryption
+ */
+int des3_crypt_ecb( des3_context *ctx,
+                     const unsigned char input[8],
+                     unsigned char output[8] )
+{
+    int i;
+    uint32_t X, Y, T, *SK;
+
+    SK = ctx->sk;
+
+    GET_UINT32_BE( X, input, 0 );
+    GET_UINT32_BE( Y, input, 4 );
+
+    DES_IP( X, Y );
+
+    for( i = 0; i < 8; i++ )
+    {
+        DES_ROUND( Y, X );
+        DES_ROUND( X, Y );
+    }
+
+    for( i = 0; i < 8; i++ )
+    {
+        DES_ROUND( X, Y );
+        DES_ROUND( Y, X );
+    }
+
+    for( i = 0; i < 8; i++ )
+    {
+        DES_ROUND( Y, X );
+        DES_ROUND( X, Y );
+    }
+
+    DES_FP( Y, X );
+
+    PUT_UINT32_BE( Y, output, 0 );
+    PUT_UINT32_BE( X, output, 4 );
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+/*
+ * 3DES-CBC buffer encryption/decryption
+ */
+int des3_crypt_cbc( des3_context *ctx,
+                     int mode,
+                     size_t length,
+                     unsigned char iv[8],
+                     const unsigned char *input,
+                     unsigned char *output )
+{
+    int i;
+    unsigned char temp[8];
+
+    if( length % 8 )
+        return( POLARSSL_ERR_DES_INVALID_INPUT_LENGTH );
+
+    if( mode == DES_ENCRYPT )
+    {
+        while( length > 0 )
+        {
+            for( i = 0; i < 8; i++ )
+                output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+            des3_crypt_ecb( ctx, output, output );
+            memcpy( iv, output, 8 );
+
+            input  += 8;
+            output += 8;
+            length -= 8;
+        }
+    }
+    else /* DES_DECRYPT */
+    {
+        while( length > 0 )
+        {
+            memcpy( temp, input, 8 );
+            des3_crypt_ecb( ctx, input, output );
+
+            for( i = 0; i < 8; i++ )
+                output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+            memcpy( iv, temp, 8 );
+
+            input  += 8;
+            output += 8;
+            length -= 8;
+        }
+    }
+
+    return( 0 );
+}
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+#endif /* !POLARSSL_DES_ALT */
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include <stdio.h>
+
+/*
+ * DES and 3DES test vectors from:
+ *
+ * http://csrc.nist.gov/groups/STM/cavp/documents/des/tripledes-vectors.zip
+ */
+static const unsigned char des3_test_keys[24] =
+{
+    0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
+    0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01,
+    0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23
+};
+
+static const unsigned char des3_test_buf[8] =
+{
+    0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74
+};
+
+static const unsigned char des3_test_ecb_dec[3][8] =
+{
+    { 0xCD, 0xD6, 0x4F, 0x2F, 0x94, 0x27, 0xC1, 0x5D },
+    { 0x69, 0x96, 0xC8, 0xFA, 0x47, 0xA2, 0xAB, 0xEB },
+    { 0x83, 0x25, 0x39, 0x76, 0x44, 0x09, 0x1A, 0x0A }
+};
+
+static const unsigned char des3_test_ecb_enc[3][8] =
+{
+    { 0x6A, 0x2A, 0x19, 0xF4, 0x1E, 0xCA, 0x85, 0x4B },
+    { 0x03, 0xE6, 0x9F, 0x5B, 0xFA, 0x58, 0xEB, 0x42 },
+    { 0xDD, 0x17, 0xE8, 0xB8, 0xB4, 0x37, 0xD2, 0x32 }
+};
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+static const unsigned char des3_test_iv[8] =
+{
+    0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF,
+};
+
+static const unsigned char des3_test_cbc_dec[3][8] =
+{
+    { 0x12, 0x9F, 0x40, 0xB9, 0xD2, 0x00, 0x56, 0xB3 },
+    { 0x47, 0x0E, 0xFC, 0x9A, 0x6B, 0x8E, 0xE3, 0x93 },
+    { 0xC5, 0xCE, 0xCF, 0x63, 0xEC, 0xEC, 0x51, 0x4C }
+};
+
+static const unsigned char des3_test_cbc_enc[3][8] =
+{
+    { 0x54, 0xF1, 0x5A, 0xF6, 0xEB, 0xE3, 0xA4, 0xB4 },
+    { 0x35, 0x76, 0x11, 0x56, 0x5F, 0xA1, 0x8E, 0x4D },
+    { 0xCB, 0x19, 0x1F, 0x85, 0xD1, 0xED, 0x84, 0x39 }
+};
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+/*
+ * Checkup routine
+ */
+int des_self_test( int verbose )
+{
+    int i, j, u, v;
+    des_context ctx;
+    des3_context ctx3;
+    unsigned char key[24];
+    unsigned char buf[8];
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    unsigned char prv[8];
+    unsigned char iv[8];
+#endif
+
+    memset( key, 0, 24 );
+
+    /*
+     * ECB mode
+     */
+    for( i = 0; i < 6; i++ )
+    {
+        u = i >> 1;
+        v = i  & 1;
+
+        if( verbose != 0 )
+            polarssl_printf( "  DES%c-ECB-%3d (%s): ",
+                             ( u == 0 ) ? ' ' : '3', 56 + u * 56,
+                             ( v == DES_DECRYPT ) ? "dec" : "enc" );
+
+        memcpy( buf, des3_test_buf, 8 );
+
+        switch( i )
+        {
+        case 0:
+            des_setkey_dec( &ctx, des3_test_keys );
+            break;
+
+        case 1:
+            des_setkey_enc( &ctx, des3_test_keys );
+            break;
+
+        case 2:
+            des3_set2key_dec( &ctx3, des3_test_keys );
+            break;
+
+        case 3:
+            des3_set2key_enc( &ctx3, des3_test_keys );
+            break;
+
+        case 4:
+            des3_set3key_dec( &ctx3, des3_test_keys );
+            break;
+
+        case 5:
+            des3_set3key_enc( &ctx3, des3_test_keys );
+            break;
+
+        default:
+            return( 1 );
+        }
+
+        for( j = 0; j < 10000; j++ )
+        {
+            if( u == 0 )
+                des_crypt_ecb( &ctx, buf, buf );
+            else
+                des3_crypt_ecb( &ctx3, buf, buf );
+        }
+
+        if( ( v == DES_DECRYPT &&
+                memcmp( buf, des3_test_ecb_dec[u], 8 ) != 0 ) ||
+            ( v != DES_DECRYPT &&
+                memcmp( buf, des3_test_ecb_enc[u], 8 ) != 0 ) )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    /*
+     * CBC mode
+     */
+    for( i = 0; i < 6; i++ )
+    {
+        u = i >> 1;
+        v = i  & 1;
+
+        if( verbose != 0 )
+            polarssl_printf( "  DES%c-CBC-%3d (%s): ",
+                             ( u == 0 ) ? ' ' : '3', 56 + u * 56,
+                             ( v == DES_DECRYPT ) ? "dec" : "enc" );
+
+        memcpy( iv,  des3_test_iv,  8 );
+        memcpy( prv, des3_test_iv,  8 );
+        memcpy( buf, des3_test_buf, 8 );
+
+        switch( i )
+        {
+        case 0:
+            des_setkey_dec( &ctx, des3_test_keys );
+            break;
+
+        case 1:
+            des_setkey_enc( &ctx, des3_test_keys );
+            break;
+
+        case 2:
+            des3_set2key_dec( &ctx3, des3_test_keys );
+            break;
+
+        case 3:
+            des3_set2key_enc( &ctx3, des3_test_keys );
+            break;
+
+        case 4:
+            des3_set3key_dec( &ctx3, des3_test_keys );
+            break;
+
+        case 5:
+            des3_set3key_enc( &ctx3, des3_test_keys );
+            break;
+
+        default:
+            return( 1 );
+        }
+
+        if( v == DES_DECRYPT )
+        {
+            for( j = 0; j < 10000; j++ )
+            {
+                if( u == 0 )
+                    des_crypt_cbc( &ctx, v, 8, iv, buf, buf );
+                else
+                    des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf );
+            }
+        }
+        else
+        {
+            for( j = 0; j < 10000; j++ )
+            {
+                unsigned char tmp[8];
+
+                if( u == 0 )
+                    des_crypt_cbc( &ctx, v, 8, iv, buf, buf );
+                else
+                    des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf );
+
+                memcpy( tmp, prv, 8 );
+                memcpy( prv, buf, 8 );
+                memcpy( buf, tmp, 8 );
+            }
+
+            memcpy( buf, prv, 8 );
+        }
+
+        if( ( v == DES_DECRYPT &&
+                memcmp( buf, des3_test_cbc_dec[u], 8 ) != 0 ) ||
+            ( v != DES_DECRYPT &&
+                memcmp( buf, des3_test_cbc_enc[u], 8 ) != 0 ) )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "passed\n" );
+    }
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+    return( 0 );
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_DES_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/dhm.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,589 @@
+/*
+ *  Diffie-Hellman-Merkle key exchange
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  Reference:
+ *
+ *  http://www.cacr.math.uwaterloo.ca/hac/ (chapter 12)
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_DHM_C)
+
+#include "polarssl/dhm.h"
+
+#if defined(POLARSSL_PEM_PARSE_C)
+#include "polarssl/pem.h"
+#endif
+
+#if defined(POLARSSL_ASN1_PARSE_C)
+#include "polarssl/asn1.h"
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdlib.h>
+#define polarssl_printf     printf
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+/*
+ * helper to validate the mpi size and import it
+ */
+static int dhm_read_bignum( mpi *X,
+                            unsigned char **p,
+                            const unsigned char *end )
+{
+    int ret, n;
+
+    if( end - *p < 2 )
+        return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
+
+    n = ( (*p)[0] << 8 ) | (*p)[1];
+    (*p) += 2;
+
+    if( (int)( end - *p ) < n )
+        return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
+
+    if( ( ret = mpi_read_binary( X, *p, n ) ) != 0 )
+        return( POLARSSL_ERR_DHM_READ_PARAMS_FAILED + ret );
+
+    (*p) += n;
+
+    return( 0 );
+}
+
+/*
+ * Verify sanity of parameter with regards to P
+ *
+ * Parameter should be: 2 <= public_param <= P - 2
+ *
+ * For more information on the attack, see:
+ *  http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf
+ *  http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643
+ */
+static int dhm_check_range( const mpi *param, const mpi *P )
+{
+    mpi L, U;
+    int ret = POLARSSL_ERR_DHM_BAD_INPUT_DATA;
+
+    mpi_init( &L ); mpi_init( &U );
+
+    MPI_CHK( mpi_lset( &L, 2 ) );
+    MPI_CHK( mpi_sub_int( &U, P, 2 ) );
+
+    if( mpi_cmp_mpi( param, &L ) >= 0 &&
+        mpi_cmp_mpi( param, &U ) <= 0 )
+    {
+        ret = 0;
+    }
+
+cleanup:
+    mpi_free( &L ); mpi_free( &U );
+    return( ret );
+}
+
+/*
+ * Parse the ServerKeyExchange parameters
+ */
+int dhm_read_params( dhm_context *ctx,
+                     unsigned char **p,
+                     const unsigned char *end )
+{
+    int ret;
+
+    dhm_free( ctx );
+
+    if( ( ret = dhm_read_bignum( &ctx->P,  p, end ) ) != 0 ||
+        ( ret = dhm_read_bignum( &ctx->G,  p, end ) ) != 0 ||
+        ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 )
+        return( ret );
+
+    if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
+        return( ret );
+
+    ctx->len = mpi_size( &ctx->P );
+
+    return( 0 );
+}
+
+/*
+ * Setup and write the ServerKeyExchange parameters
+ */
+int dhm_make_params( dhm_context *ctx, int x_size,
+                     unsigned char *output, size_t *olen,
+                     int (*f_rng)(void *, unsigned char *, size_t),
+                     void *p_rng )
+{
+    int ret, count = 0;
+    size_t n1, n2, n3;
+    unsigned char *p;
+
+    if( mpi_cmp_int( &ctx->P, 0 ) == 0 )
+        return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
+
+    /*
+     * Generate X as large as possible ( < P )
+     */
+    do
+    {
+        mpi_fill_random( &ctx->X, x_size, f_rng, p_rng );
+
+        while( mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
+            MPI_CHK( mpi_shift_r( &ctx->X, 1 ) );
+
+        if( count++ > 10 )
+            return( POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED );
+    }
+    while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
+
+    /*
+     * Calculate GX = G^X mod P
+     */
+    MPI_CHK( mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
+                          &ctx->P , &ctx->RP ) );
+
+    if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
+        return( ret );
+
+    /*
+     * export P, G, GX
+     */
+#define DHM_MPI_EXPORT(X,n)                     \
+    MPI_CHK( mpi_write_binary( X, p + 2, n ) ); \
+    *p++ = (unsigned char)( n >> 8 );           \
+    *p++ = (unsigned char)( n      ); p += n;
+
+    n1 = mpi_size( &ctx->P  );
+    n2 = mpi_size( &ctx->G  );
+    n3 = mpi_size( &ctx->GX );
+
+    p = output;
+    DHM_MPI_EXPORT( &ctx->P , n1 );
+    DHM_MPI_EXPORT( &ctx->G , n2 );
+    DHM_MPI_EXPORT( &ctx->GX, n3 );
+
+    *olen  = p - output;
+
+    ctx->len = n1;
+
+cleanup:
+
+    if( ret != 0 )
+        return( POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED + ret );
+
+    return( 0 );
+}
+
+/*
+ * Import the peer's public value G^Y
+ */
+int dhm_read_public( dhm_context *ctx,
+                     const unsigned char *input, size_t ilen )
+{
+    int ret;
+
+    if( ctx == NULL || ilen < 1 || ilen > ctx->len )
+        return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
+
+    if( ( ret = mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 )
+        return( POLARSSL_ERR_DHM_READ_PUBLIC_FAILED + ret );
+
+    return( 0 );
+}
+
+/*
+ * Create own private value X and export G^X
+ */
+int dhm_make_public( dhm_context *ctx, int x_size,
+                     unsigned char *output, size_t olen,
+                     int (*f_rng)(void *, unsigned char *, size_t),
+                     void *p_rng )
+{
+    int ret, count = 0;
+
+    if( ctx == NULL || olen < 1 || olen > ctx->len )
+        return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
+
+    if( mpi_cmp_int( &ctx->P, 0 ) == 0 )
+        return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
+
+    /*
+     * generate X and calculate GX = G^X mod P
+     */
+    do
+    {
+        mpi_fill_random( &ctx->X, x_size, f_rng, p_rng );
+
+        while( mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
+            MPI_CHK( mpi_shift_r( &ctx->X, 1 ) );
+
+        if( count++ > 10 )
+            return( POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED );
+    }
+    while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
+
+    MPI_CHK( mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
+                          &ctx->P , &ctx->RP ) );
+
+    if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
+        return( ret );
+
+    MPI_CHK( mpi_write_binary( &ctx->GX, output, olen ) );
+
+cleanup:
+
+    if( ret != 0 )
+        return( POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED + ret );
+
+    return( 0 );
+}
+
+/*
+ * Use the blinding method and optimisation suggested in section 10 of:
+ *  KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
+ *  DSS, and other systems. In : Advances in Cryptology—CRYPTO’96. Springer
+ *  Berlin Heidelberg, 1996. p. 104-113.
+ */
+static int dhm_update_blinding( dhm_context *ctx,
+                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+    int ret, count;
+
+    /*
+     * Don't use any blinding the first time a particular X is used,
+     * but remember it to use blinding next time.
+     */
+    if( mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 )
+    {
+        MPI_CHK( mpi_copy( &ctx->pX, &ctx->X ) );
+        MPI_CHK( mpi_lset( &ctx->Vi, 1 ) );
+        MPI_CHK( mpi_lset( &ctx->Vf, 1 ) );
+
+        return( 0 );
+    }
+
+    /*
+     * Ok, we need blinding. Can we re-use existing values?
+     * If yes, just update them by squaring them.
+     */
+    if( mpi_cmp_int( &ctx->Vi, 1 ) != 0 )
+    {
+        MPI_CHK( mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) );
+        MPI_CHK( mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) );
+
+        MPI_CHK( mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) );
+        MPI_CHK( mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
+
+        return( 0 );
+    }
+
+    /*
+     * We need to generate blinding values from scratch
+     */
+
+    /* Vi = random( 2, P-1 ) */
+    count = 0;
+    do
+    {
+        mpi_fill_random( &ctx->Vi, mpi_size( &ctx->P ), f_rng, p_rng );
+
+        while( mpi_cmp_mpi( &ctx->Vi, &ctx->P ) >= 0 )
+            MPI_CHK( mpi_shift_r( &ctx->Vi, 1 ) );
+
+        if( count++ > 10 )
+            return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
+    }
+    while( mpi_cmp_int( &ctx->Vi, 1 ) <= 0 );
+
+    /* Vf = Vi^-X mod P */
+    MPI_CHK( mpi_inv_mod( &ctx->Vf, &ctx->Vi, &ctx->P ) );
+    MPI_CHK( mpi_exp_mod( &ctx->Vf, &ctx->Vf, &ctx->X, &ctx->P, &ctx->RP ) );
+
+cleanup:
+    return( ret );
+}
+
+/*
+ * Derive and export the shared secret (G^Y)^X mod P
+ */
+int dhm_calc_secret( dhm_context *ctx,
+                     unsigned char *output, size_t *olen,
+                     int (*f_rng)(void *, unsigned char *, size_t),
+                     void *p_rng )
+{
+    int ret;
+    mpi GYb;
+
+    if( ctx == NULL || *olen < ctx->len )
+        return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
+
+    if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
+        return( ret );
+
+    mpi_init( &GYb );
+
+    /* Blind peer's value */
+    if( f_rng != NULL )
+    {
+        MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) );
+        MPI_CHK( mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) );
+        MPI_CHK( mpi_mod_mpi( &GYb, &GYb, &ctx->P ) );
+    }
+    else
+        MPI_CHK( mpi_copy( &GYb, &ctx->GY ) );
+
+    /* Do modular exponentiation */
+    MPI_CHK( mpi_exp_mod( &ctx->K, &GYb, &ctx->X,
+                          &ctx->P, &ctx->RP ) );
+
+    /* Unblind secret value */
+    if( f_rng != NULL )
+    {
+        MPI_CHK( mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) );
+        MPI_CHK( mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) );
+    }
+
+    *olen = mpi_size( &ctx->K );
+
+    MPI_CHK( mpi_write_binary( &ctx->K, output, *olen ) );
+
+cleanup:
+    mpi_free( &GYb );
+
+    if( ret != 0 )
+        return( POLARSSL_ERR_DHM_CALC_SECRET_FAILED + ret );
+
+    return( 0 );
+}
+
+/*
+ * Free the components of a DHM key
+ */
+void dhm_free( dhm_context *ctx )
+{
+    mpi_free( &ctx->pX); mpi_free( &ctx->Vf ); mpi_free( &ctx->Vi );
+    mpi_free( &ctx->RP ); mpi_free( &ctx->K ); mpi_free( &ctx->GY );
+    mpi_free( &ctx->GX ); mpi_free( &ctx->X ); mpi_free( &ctx->G );
+    mpi_free( &ctx->P );
+
+    memset( ctx, 0, sizeof( dhm_context ) );
+}
+
+#if defined(POLARSSL_ASN1_PARSE_C)
+/*
+ * Parse DHM parameters
+ */
+int dhm_parse_dhm( dhm_context *dhm, const unsigned char *dhmin,
+                   size_t dhminlen )
+{
+    int ret;
+    size_t len;
+    unsigned char *p, *end;
+#if defined(POLARSSL_PEM_PARSE_C)
+    pem_context pem;
+
+    pem_init( &pem );
+    memset( dhm, 0, sizeof( dhm_context ) );
+
+    ret = pem_read_buffer( &pem,
+                           "-----BEGIN DH PARAMETERS-----",
+                           "-----END DH PARAMETERS-----",
+                           dhmin, NULL, 0, &dhminlen );
+
+    if( ret == 0 )
+    {
+        /*
+         * Was PEM encoded
+         */
+        dhminlen = pem.buflen;
+    }
+    else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
+        goto exit;
+
+    p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin;
+#else
+    p = (unsigned char *) dhmin;
+#endif /* POLARSSL_PEM_PARSE_C */
+    end = p + dhminlen;
+
+    /*
+     *  DHParams ::= SEQUENCE {
+     *      prime            INTEGER,  -- P
+     *      generator        INTEGER,  -- g
+     *  }
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        ret = POLARSSL_ERR_DHM_INVALID_FORMAT + ret;
+        goto exit;
+    }
+
+    end = p + len;
+
+    if( ( ret = asn1_get_mpi( &p, end, &dhm->P  ) ) != 0 ||
+        ( ret = asn1_get_mpi( &p, end, &dhm->G ) ) != 0 )
+    {
+        ret = POLARSSL_ERR_DHM_INVALID_FORMAT + ret;
+        goto exit;
+    }
+
+    if( p != end )
+    {
+        ret = POLARSSL_ERR_DHM_INVALID_FORMAT +
+              POLARSSL_ERR_ASN1_LENGTH_MISMATCH;
+        goto exit;
+    }
+
+    ret = 0;
+
+    dhm->len = mpi_size( &dhm->P );
+
+exit:
+#if defined(POLARSSL_PEM_PARSE_C)
+    pem_free( &pem );
+#endif
+    if( ret != 0 )
+        dhm_free( dhm );
+
+    return( ret );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * Load all data from a file into a given buffer.
+ */
+static int load_file( const char *path, unsigned char **buf, size_t *n )
+{
+    FILE *f;
+    long size;
+
+    if( ( f = fopen( path, "rb" ) ) == NULL )
+        return( POLARSSL_ERR_DHM_FILE_IO_ERROR );
+
+    fseek( f, 0, SEEK_END );
+    if( ( size = ftell( f ) ) == -1 )
+    {
+        fclose( f );
+        return( POLARSSL_ERR_DHM_FILE_IO_ERROR );
+    }
+    fseek( f, 0, SEEK_SET );
+
+    *n = (size_t) size;
+
+    if( *n + 1 == 0 ||
+        ( *buf = (unsigned char *) polarssl_malloc( *n + 1 ) ) == NULL )
+    {
+        fclose( f );
+        return( POLARSSL_ERR_DHM_MALLOC_FAILED );
+    }
+
+    if( fread( *buf, 1, *n, f ) != *n )
+    {
+        fclose( f );
+        polarssl_free( *buf );
+        return( POLARSSL_ERR_DHM_FILE_IO_ERROR );
+    }
+
+    fclose( f );
+
+    (*buf)[*n] = '\0';
+
+    return( 0 );
+}
+
+/*
+ * Load and parse DHM parameters
+ */
+int dhm_parse_dhmfile( dhm_context *dhm, const char *path )
+{
+    int ret;
+    size_t n;
+    unsigned char *buf;
+
+    if ( ( ret = load_file( path, &buf, &n ) ) != 0 )
+        return( ret );
+
+    ret = dhm_parse_dhm( dhm, buf, n );
+
+    memset( buf, 0, n + 1 );
+    polarssl_free( buf );
+
+    return( ret );
+}
+#endif /* POLARSSL_FS_IO */
+#endif /* POLARSSL_ASN1_PARSE_C */
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include "polarssl/certs.h"
+
+/*
+ * Checkup routine
+ */
+int dhm_self_test( int verbose )
+{
+#if defined(POLARSSL_CERTS_C)
+    int ret;
+    dhm_context dhm;
+
+    if( verbose != 0 )
+        polarssl_printf( "  DHM parameter load: " );
+
+    if( ( ret = dhm_parse_dhm( &dhm, (const unsigned char *) test_dhm_params,
+                               strlen( test_dhm_params ) ) ) != 0 )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "failed\n" );
+
+        return( ret );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n\n" );
+
+    dhm_free( &dhm );
+
+    return( 0 );
+#else
+    if( verbose != 0 )
+        polarssl_printf( "  DHM parameter load: skipped\n" );
+
+    return( 0 );
+#endif /* POLARSSL_CERTS_C */
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_DHM_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/ecdh.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,282 @@
+/*
+ *  Elliptic curve Diffie-Hellman
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*
+ * References:
+ *
+ * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
+ * RFC 4492
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_ECDH_C)
+
+#include "polarssl/ecdh.h"
+
+/*
+ * Generate public key: simple wrapper around ecp_gen_keypair
+ */
+int ecdh_gen_public( ecp_group *grp, mpi *d, ecp_point *Q,
+                     int (*f_rng)(void *, unsigned char *, size_t),
+                     void *p_rng )
+{
+    return ecp_gen_keypair( grp, d, Q, f_rng, p_rng );
+}
+
+/*
+ * Compute shared secret (SEC1 3.3.1)
+ */
+int ecdh_compute_shared( ecp_group *grp, mpi *z,
+                         const ecp_point *Q, const mpi *d,
+                         int (*f_rng)(void *, unsigned char *, size_t),
+                         void *p_rng )
+{
+    int ret;
+    ecp_point P;
+
+    ecp_point_init( &P );
+
+    /*
+     * Make sure Q is a valid pubkey before using it
+     */
+    MPI_CHK( ecp_check_pubkey( grp, Q ) );
+
+    MPI_CHK( ecp_mul( grp, &P, d, Q, f_rng, p_rng ) );
+
+    if( ecp_is_zero( &P ) )
+    {
+        ret = POLARSSL_ERR_ECP_BAD_INPUT_DATA;
+        goto cleanup;
+    }
+
+    MPI_CHK( mpi_copy( z, &P.X ) );
+
+cleanup:
+    ecp_point_free( &P );
+
+    return( ret );
+}
+
+/*
+ * Initialize context
+ */
+void ecdh_init( ecdh_context *ctx )
+{
+    memset( ctx, 0, sizeof( ecdh_context ) );
+}
+
+/*
+ * Free context
+ */
+void ecdh_free( ecdh_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    ecp_group_free( &ctx->grp );
+    mpi_free      ( &ctx->d   );
+    ecp_point_free( &ctx->Q   );
+    ecp_point_free( &ctx->Qp  );
+    mpi_free      ( &ctx->z   );
+    ecp_point_free( &ctx->Vi  );
+    ecp_point_free( &ctx->Vf  );
+    mpi_free      ( &ctx->_d  );
+}
+
+/*
+ * Setup and write the ServerKeyExhange parameters (RFC 4492)
+ *      struct {
+ *          ECParameters    curve_params;
+ *          ECPoint         public;
+ *      } ServerECDHParams;
+ */
+int ecdh_make_params( ecdh_context *ctx, size_t *olen,
+                      unsigned char *buf, size_t blen,
+                      int (*f_rng)(void *, unsigned char *, size_t),
+                      void *p_rng )
+{
+    int ret;
+    size_t grp_len, pt_len;
+
+    if( ctx == NULL || ctx->grp.pbits == 0 )
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+
+    if( ( ret = ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) )
+                != 0 )
+        return( ret );
+
+    if( ( ret = ecp_tls_write_group( &ctx->grp, &grp_len, buf, blen ) )
+                != 0 )
+        return( ret );
+
+    buf += grp_len;
+    blen -= grp_len;
+
+    if( ( ret = ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format,
+                                     &pt_len, buf, blen ) ) != 0 )
+        return( ret );
+
+    *olen = grp_len + pt_len;
+    return 0;
+}
+
+/*
+ * Read the ServerKeyExhange parameters (RFC 4492)
+ *      struct {
+ *          ECParameters    curve_params;
+ *          ECPoint         public;
+ *      } ServerECDHParams;
+ */
+int ecdh_read_params( ecdh_context *ctx,
+                      const unsigned char **buf, const unsigned char *end )
+{
+    int ret;
+
+    if( ( ret = ecp_tls_read_group( &ctx->grp, buf, end - *buf ) ) != 0 )
+        return( ret );
+
+    if( ( ret = ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf, end - *buf ) )
+                != 0 )
+        return( ret );
+
+    return 0;
+}
+
+/*
+ * Get parameters from a keypair
+ */
+int ecdh_get_params( ecdh_context *ctx, const ecp_keypair *key,
+                     ecdh_side side )
+{
+    int ret;
+
+    if( ( ret = ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 )
+        return( ret );
+
+    /* If it's not our key, just import the public part as Qp */
+    if( side == POLARSSL_ECDH_THEIRS )
+        return( ecp_copy( &ctx->Qp, &key->Q ) );
+
+    /* Our key: import public (as Q) and private parts */
+    if( side != POLARSSL_ECDH_OURS )
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+
+    if( ( ret = ecp_copy( &ctx->Q, &key->Q ) ) != 0 ||
+        ( ret = mpi_copy( &ctx->d, &key->d ) ) != 0 )
+        return( ret );
+
+    return( 0 );
+}
+
+/*
+ * Setup and export the client public value
+ */
+int ecdh_make_public( ecdh_context *ctx, size_t *olen,
+                      unsigned char *buf, size_t blen,
+                      int (*f_rng)(void *, unsigned char *, size_t),
+                      void *p_rng )
+{
+    int ret;
+
+    if( ctx == NULL || ctx->grp.pbits == 0 )
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+
+    if( ( ret = ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) )
+                != 0 )
+        return( ret );
+
+    return ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format,
+                                olen, buf, blen );
+}
+
+/*
+ * Parse and import the client's public value
+ */
+int ecdh_read_public( ecdh_context *ctx,
+                      const unsigned char *buf, size_t blen )
+{
+    int ret;
+    const unsigned char *p = buf;
+
+    if( ctx == NULL )
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+
+    if( ( ret = ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p, blen ) ) != 0 )
+        return( ret );
+
+    if( (size_t)( p - buf ) != blen )
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+
+    return( 0 );
+}
+
+/*
+ * Derive and export the shared secret
+ */
+int ecdh_calc_secret( ecdh_context *ctx, size_t *olen,
+                      unsigned char *buf, size_t blen,
+                      int (*f_rng)(void *, unsigned char *, size_t),
+                      void *p_rng )
+{
+    int ret;
+
+    if( ctx == NULL )
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+
+    if( ( ret = ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp, &ctx->d,
+                                     f_rng, p_rng ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    if( mpi_size( &ctx->z ) > blen )
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+
+    *olen = ctx->grp.pbits / 8 + ( ( ctx->grp.pbits % 8 ) != 0 );
+    return mpi_write_binary( &ctx->z, buf, *olen );
+}
+
+
+#if defined(POLARSSL_SELF_TEST)
+
+/*
+ * Checkup routine
+ */
+int ecdh_self_test( int verbose )
+{
+    ((void) verbose );
+    return( 0 );
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_ECDH_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/ecdsa.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,505 @@
+/*
+ *  Elliptic curve DSA
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*
+ * References:
+ *
+ * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_ECDSA_C)
+
+#include "polarssl/ecdsa.h"
+#include "polarssl/asn1write.h"
+
+#if defined(POLARSSL_ECDSA_DETERMINISTIC)
+#include "polarssl/hmac_drbg.h"
+#endif
+
+#if defined(POLARSSL_ECDSA_DETERMINISTIC)
+/*
+ * This a hopefully temporary compatibility function.
+ *
+ * Since we can't ensure the caller will pass a valid md_alg before the next
+ * interface change, try to pick up a decent md by size.
+ *
+ * Argument is the minimum size in bytes of the MD output.
+ */
+static const md_info_t *md_info_by_size( size_t min_size )
+{
+    const md_info_t *md_cur, *md_picked = NULL;
+    const int *md_alg;
+
+    for( md_alg = md_list(); *md_alg != 0; md_alg++ )
+    {
+        if( ( md_cur = md_info_from_type( *md_alg ) ) == NULL ||
+            (size_t) md_cur->size < min_size ||
+            ( md_picked != NULL && md_cur->size > md_picked->size ) )
+            continue;
+
+        md_picked = md_cur;
+    }
+
+    return( md_picked );
+}
+#endif /* POLARSSL_ECDSA_DETERMINISTIC */
+
+/*
+ * Derive a suitable integer for group grp from a buffer of length len
+ * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3
+ */
+static int derive_mpi( const ecp_group *grp, mpi *x,
+                       const unsigned char *buf, size_t blen )
+{
+    int ret;
+    size_t n_size = (grp->nbits + 7) / 8;
+    size_t use_size = blen > n_size ? n_size : blen;
+
+    MPI_CHK( mpi_read_binary( x, buf, use_size ) );
+    if( use_size * 8 > grp->nbits )
+        MPI_CHK( mpi_shift_r( x, use_size * 8 - grp->nbits ) );
+
+    /* While at it, reduce modulo N */
+    if( mpi_cmp_mpi( x, &grp->N ) >= 0 )
+        MPI_CHK( mpi_sub_mpi( x, x, &grp->N ) );
+
+cleanup:
+    return( ret );
+}
+
+/*
+ * Compute ECDSA signature of a hashed message (SEC1 4.1.3)
+ * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message)
+ */
+int ecdsa_sign( ecp_group *grp, mpi *r, mpi *s,
+                const mpi *d, const unsigned char *buf, size_t blen,
+                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+    int ret, key_tries, sign_tries, blind_tries;
+    ecp_point R;
+    mpi k, e, t;
+
+    /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
+    if( grp->N.p == NULL )
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+
+    ecp_point_init( &R );
+    mpi_init( &k ); mpi_init( &e ); mpi_init( &t );
+
+    sign_tries = 0;
+    do
+    {
+        /*
+         * Steps 1-3: generate a suitable ephemeral keypair
+         * and set r = xR mod n
+         */
+        key_tries = 0;
+        do
+        {
+            MPI_CHK( ecp_gen_keypair( grp, &k, &R, f_rng, p_rng ) );
+            MPI_CHK( mpi_mod_mpi( r, &R.X, &grp->N ) );
+
+            if( key_tries++ > 10 )
+            {
+                ret = POLARSSL_ERR_ECP_RANDOM_FAILED;
+                goto cleanup;
+            }
+        }
+        while( mpi_cmp_int( r, 0 ) == 0 );
+
+        /*
+         * Step 5: derive MPI from hashed message
+         */
+        MPI_CHK( derive_mpi( grp, &e, buf, blen ) );
+
+        /*
+         * Generate a random value to blind inv_mod in next step,
+         * avoiding a potential timing leak.
+         */
+        blind_tries = 0;
+        do
+        {
+            size_t n_size = (grp->nbits + 7) / 8;
+            MPI_CHK( mpi_fill_random( &t, n_size, f_rng, p_rng ) );
+            MPI_CHK( mpi_shift_r( &t, 8 * n_size - grp->nbits ) );
+
+            /* See ecp_gen_keypair() */
+            if( ++blind_tries > 30 )
+                return( POLARSSL_ERR_ECP_RANDOM_FAILED );
+        }
+        while( mpi_cmp_int( &t, 1 ) < 0 ||
+               mpi_cmp_mpi( &t, &grp->N ) >= 0 );
+
+        /*
+         * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n
+         */
+        MPI_CHK( mpi_mul_mpi( s, r, d ) );
+        MPI_CHK( mpi_add_mpi( &e, &e, s ) );
+        MPI_CHK( mpi_mul_mpi( &e, &e, &t ) );
+        MPI_CHK( mpi_mul_mpi( &k, &k, &t ) );
+        MPI_CHK( mpi_inv_mod( s, &k, &grp->N ) );
+        MPI_CHK( mpi_mul_mpi( s, s, &e ) );
+        MPI_CHK( mpi_mod_mpi( s, s, &grp->N ) );
+
+        if( sign_tries++ > 10 )
+        {
+            ret = POLARSSL_ERR_ECP_RANDOM_FAILED;
+            goto cleanup;
+        }
+    }
+    while( mpi_cmp_int( s, 0 ) == 0 );
+
+cleanup:
+    ecp_point_free( &R );
+    mpi_free( &k ); mpi_free( &e ); mpi_free( &t );
+
+    return( ret );
+}
+
+#if defined(POLARSSL_ECDSA_DETERMINISTIC)
+/*
+ * Deterministic signature wrapper
+ */
+int ecdsa_sign_det( ecp_group *grp, mpi *r, mpi *s,
+                    const mpi *d, const unsigned char *buf, size_t blen,
+                    md_type_t md_alg )
+{
+    int ret;
+    hmac_drbg_context rng_ctx;
+    unsigned char data[2 * POLARSSL_ECP_MAX_BYTES];
+    size_t grp_len = ( grp->nbits + 7 ) / 8;
+    const md_info_t *md_info;
+    mpi h;
+
+    /* Temporary fallback */
+    if( md_alg == POLARSSL_MD_NONE )
+        md_info = md_info_by_size( blen );
+    else
+        md_info = md_info_from_type( md_alg );
+
+    if( md_info == NULL )
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+
+    mpi_init( &h );
+    memset( &rng_ctx, 0, sizeof( hmac_drbg_context ) );
+
+    /* Use private key and message hash (reduced) to initialize HMAC_DRBG */
+    MPI_CHK( mpi_write_binary( d, data, grp_len ) );
+    MPI_CHK( derive_mpi( grp, &h, buf, blen ) );
+    MPI_CHK( mpi_write_binary( &h, data + grp_len, grp_len ) );
+    hmac_drbg_init_buf( &rng_ctx, md_info, data, 2 * grp_len );
+
+    ret = ecdsa_sign( grp, r, s, d, buf, blen,
+                      hmac_drbg_random, &rng_ctx );
+
+cleanup:
+    hmac_drbg_free( &rng_ctx );
+    mpi_free( &h );
+
+    return( ret );
+}
+#endif /* POLARSSL_ECDSA_DETERMINISTIC */
+
+/*
+ * Verify ECDSA signature of hashed message (SEC1 4.1.4)
+ * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message)
+ */
+int ecdsa_verify( ecp_group *grp,
+                  const unsigned char *buf, size_t blen,
+                  const ecp_point *Q, const mpi *r, const mpi *s)
+{
+    int ret;
+    mpi e, s_inv, u1, u2;
+    ecp_point R, P;
+
+    ecp_point_init( &R ); ecp_point_init( &P );
+    mpi_init( &e ); mpi_init( &s_inv ); mpi_init( &u1 ); mpi_init( &u2 );
+
+    /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
+    if( grp->N.p == NULL )
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+
+    /*
+     * Step 1: make sure r and s are in range 1..n-1
+     */
+    if( mpi_cmp_int( r, 1 ) < 0 || mpi_cmp_mpi( r, &grp->N ) >= 0 ||
+        mpi_cmp_int( s, 1 ) < 0 || mpi_cmp_mpi( s, &grp->N ) >= 0 )
+    {
+        ret = POLARSSL_ERR_ECP_VERIFY_FAILED;
+        goto cleanup;
+    }
+
+    /*
+     * Additional precaution: make sure Q is valid
+     */
+    MPI_CHK( ecp_check_pubkey( grp, Q ) );
+
+    /*
+     * Step 3: derive MPI from hashed message
+     */
+    MPI_CHK( derive_mpi( grp, &e, buf, blen ) );
+
+    /*
+     * Step 4: u1 = e / s mod n, u2 = r / s mod n
+     */
+    MPI_CHK( mpi_inv_mod( &s_inv, s, &grp->N ) );
+
+    MPI_CHK( mpi_mul_mpi( &u1, &e, &s_inv ) );
+    MPI_CHK( mpi_mod_mpi( &u1, &u1, &grp->N ) );
+
+    MPI_CHK( mpi_mul_mpi( &u2, r, &s_inv ) );
+    MPI_CHK( mpi_mod_mpi( &u2, &u2, &grp->N ) );
+
+    /*
+     * Step 5: R = u1 G + u2 Q
+     *
+     * Since we're not using any secret data, no need to pass a RNG to
+     * ecp_mul() for countermesures.
+     */
+    MPI_CHK( ecp_mul( grp, &R, &u1, &grp->G, NULL, NULL ) );
+    MPI_CHK( ecp_mul( grp, &P, &u2, Q, NULL, NULL ) );
+    MPI_CHK( ecp_add( grp, &R, &R, &P ) );
+
+    if( ecp_is_zero( &R ) )
+    {
+        ret = POLARSSL_ERR_ECP_VERIFY_FAILED;
+        goto cleanup;
+    }
+
+    /*
+     * Step 6: convert xR to an integer (no-op)
+     * Step 7: reduce xR mod n (gives v)
+     */
+    MPI_CHK( mpi_mod_mpi( &R.X, &R.X, &grp->N ) );
+
+    /*
+     * Step 8: check if v (that is, R.X) is equal to r
+     */
+    if( mpi_cmp_mpi( &R.X, r ) != 0 )
+    {
+        ret = POLARSSL_ERR_ECP_VERIFY_FAILED;
+        goto cleanup;
+    }
+
+cleanup:
+    ecp_point_free( &R ); ecp_point_free( &P );
+    mpi_free( &e ); mpi_free( &s_inv ); mpi_free( &u1 ); mpi_free( &u2 );
+
+    return( ret );
+}
+
+/*
+ * 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 POLARSSL_ECP_MAX_BYTES > 124
+#error "POLARSSL_ECP_MAX_BYTES bigger than expected, please fix MAX_SIG_LEN"
+#endif
+#define MAX_SIG_LEN ( 3 + 2 * ( 2 + POLARSSL_ECP_MAX_BYTES ) )
+
+/*
+ * Convert a signature (given by context) to ASN.1
+ */
+static int ecdsa_signature_to_asn1( ecdsa_context *ctx,
+                                    unsigned char *sig, size_t *slen )
+{
+    int ret;
+    unsigned char buf[MAX_SIG_LEN];
+    unsigned char *p = buf + sizeof( buf );
+    size_t len = 0;
+
+    ASN1_CHK_ADD( len, asn1_write_mpi( &p, buf, &ctx->s ) );
+    ASN1_CHK_ADD( len, asn1_write_mpi( &p, buf, &ctx->r ) );
+
+    ASN1_CHK_ADD( len, asn1_write_len( &p, buf, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &p, buf,
+                                       ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+
+    memcpy( sig, p, len );
+    *slen = len;
+
+    return( 0 );
+}
+
+/*
+ * Compute and write signature
+ */
+int ecdsa_write_signature( ecdsa_context *ctx,
+                           const unsigned char *hash, size_t hlen,
+                           unsigned char *sig, size_t *slen,
+                           int (*f_rng)(void *, unsigned char *, size_t),
+                           void *p_rng )
+{
+    int ret;
+
+    if( ( ret = ecdsa_sign( &ctx->grp, &ctx->r, &ctx->s, &ctx->d,
+                            hash, hlen, f_rng, p_rng ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    return( ecdsa_signature_to_asn1( ctx, sig, slen ) );
+}
+
+#if defined(POLARSSL_ECDSA_DETERMINISTIC)
+/*
+ * Compute and write signature deterministically
+ */
+int ecdsa_write_signature_det( ecdsa_context *ctx,
+                               const unsigned char *hash, size_t hlen,
+                               unsigned char *sig, size_t *slen,
+                               md_type_t md_alg )
+{
+    int ret;
+
+    if( ( ret = ecdsa_sign_det( &ctx->grp, &ctx->r, &ctx->s, &ctx->d,
+                                hash, hlen, md_alg ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    return( ecdsa_signature_to_asn1( ctx, sig, slen ) );
+}
+#endif /* POLARSSL_ECDSA_DETERMINISTIC */
+
+/*
+ * Read and check signature
+ */
+int ecdsa_read_signature( ecdsa_context *ctx,
+                          const unsigned char *hash, size_t hlen,
+                          const unsigned char *sig, size_t slen )
+{
+    int ret;
+    unsigned char *p = (unsigned char *) sig;
+    const unsigned char *end = sig + slen;
+    size_t len;
+
+    if( ( ret = asn1_get_tag( &p, end, &len,
+                    ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA + ret );
+    }
+
+    if( p + len != end )
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    if( ( ret = asn1_get_mpi( &p, end, &ctx->r ) ) != 0 ||
+        ( ret = asn1_get_mpi( &p, end, &ctx->s ) ) != 0 )
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA + ret );
+
+    if( ( ret = ecdsa_verify( &ctx->grp, hash, hlen,
+                              &ctx->Q, &ctx->r, &ctx->s ) ) != 0 )
+        return( ret );
+
+    if( p != end )
+        return( POLARSSL_ERR_ECP_SIG_LEN_MISMATCH );
+
+    return( 0 );
+}
+
+/*
+ * Generate key pair
+ */
+int ecdsa_genkey( ecdsa_context *ctx, ecp_group_id gid,
+                  int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+    return( ecp_use_known_dp( &ctx->grp, gid ) ||
+            ecp_gen_keypair( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) );
+}
+
+/*
+ * Set context from an ecp_keypair
+ */
+int ecdsa_from_keypair( ecdsa_context *ctx, const ecp_keypair *key )
+{
+    int ret;
+
+    if( ( ret = ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 ||
+        ( ret = mpi_copy( &ctx->d, &key->d ) ) != 0 ||
+        ( ret = ecp_copy( &ctx->Q, &key->Q ) ) != 0 )
+    {
+        ecdsa_free( ctx );
+    }
+
+    return( ret );
+}
+
+/*
+ * Initialize context
+ */
+void ecdsa_init( ecdsa_context *ctx )
+{
+    ecp_group_init( &ctx->grp );
+    mpi_init( &ctx->d );
+    ecp_point_init( &ctx->Q );
+    mpi_init( &ctx->r );
+    mpi_init( &ctx->s );
+}
+
+/*
+ * Free context
+ */
+void ecdsa_free( ecdsa_context *ctx )
+{
+    ecp_group_free( &ctx->grp );
+    mpi_free( &ctx->d );
+    ecp_point_free( &ctx->Q );
+    mpi_free( &ctx->r );
+    mpi_free( &ctx->s );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+/*
+ * Checkup routine
+ */
+int ecdsa_self_test( int verbose )
+{
+    ((void) verbose );
+    return( 0 );
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_ECDSA_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/ecp.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,2020 @@
+/*
+ *  Elliptic curves over GF(p): generic functions
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*
+ * References:
+ *
+ * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
+ * GECC = Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone
+ * FIPS 186-3 http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf
+ * RFC 4492 for the related TLS structures and constants
+ *
+ * [M255] http://cr.yp.to/ecdh/curve25519-20060209.pdf
+ *
+ * [2] CORON, Jean-Sébastien. 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ÉNÉTEAU, 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>
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_ECP_C)
+
+#include "polarssl/ecp.h"
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf     printf
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+#include <stdlib.h>
+
+#if defined(_MSC_VER) && !defined strcasecmp && !defined(EFIX64) && \
+    !defined(EFI32)
+#define strcasecmp _stricmp
+#endif
+
+#if defined(_MSC_VER) && !defined(inline)
+#define inline _inline
+#else
+#if defined(__ARMCC_VERSION) && !defined(inline)
+#define inline __inline
+#endif /* __ARMCC_VERSION */
+#endif /*_MSC_VER */
+
+#if defined(POLARSSL_SELF_TEST)
+/*
+ * Counts of point addition and doubling, and field multiplications.
+ * Used to test resistance of point multiplication to simple timing attacks.
+ */
+static unsigned long add_count, dbl_count, mul_count;
+#endif
+
+#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED) ||   \
+    defined(POLARSSL_ECP_DP_SECP224R1_ENABLED) ||   \
+    defined(POLARSSL_ECP_DP_SECP256R1_ENABLED) ||   \
+    defined(POLARSSL_ECP_DP_SECP384R1_ENABLED) ||   \
+    defined(POLARSSL_ECP_DP_SECP521R1_ENABLED) ||   \
+    defined(POLARSSL_ECP_DP_BP256R1_ENABLED)   ||   \
+    defined(POLARSSL_ECP_DP_BP384R1_ENABLED)   ||   \
+    defined(POLARSSL_ECP_DP_BP512R1_ENABLED)   ||   \
+    defined(POLARSSL_ECP_DP_SECP192K1_ENABLED) ||   \
+    defined(POLARSSL_ECP_DP_SECP224K1_ENABLED) ||   \
+    defined(POLARSSL_ECP_DP_SECP256K1_ENABLED)
+#define POLARSSL_ECP_SHORT_WEIERSTRASS
+#endif
+
+#if defined(POLARSSL_ECP_DP_M221_ENABLED) ||   \
+    defined(POLARSSL_ECP_DP_M255_ENABLED) ||   \
+    defined(POLARSSL_ECP_DP_M383_ENABLED) ||   \
+    defined(POLARSSL_ECP_DP_M511_ENABLED)
+#define POLARSSL_ECP_MONTGOMERY
+#endif
+
+/*
+ * Curve types: internal for now, might be exposed later
+ */
+typedef enum
+{
+    POLARSSL_ECP_TYPE_NONE = 0,
+    POLARSSL_ECP_TYPE_SHORT_WEIERSTRASS,    /* y^2 = x^3 + a x + b      */
+    POLARSSL_ECP_TYPE_MONTGOMERY,           /* y^2 = x^3 + a x^2 + x    */
+} ecp_curve_type;
+
+/*
+ * List of supported curves:
+ *  - internal ID
+ *  - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2)
+ *  - size in bits
+ *  - readable name
+ *
+ * Curves are listed in order: largest curves first, and for a given size,
+ * fastest curves first. This provides the default order for the SSL module.
+ */
+static const ecp_curve_info ecp_supported_curves[POLARSSL_ECP_DP_MAX] =
+{
+#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED)
+    { POLARSSL_ECP_DP_SECP521R1,    25,     521,    "secp521r1"         },
+#endif
+#if defined(POLARSSL_ECP_DP_BP512R1_ENABLED)
+    { POLARSSL_ECP_DP_BP512R1,      28,     512,    "brainpoolP512r1"   },
+#endif
+#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED)
+    { POLARSSL_ECP_DP_SECP384R1,    24,     384,    "secp384r1"         },
+#endif
+#if defined(POLARSSL_ECP_DP_BP384R1_ENABLED)
+    { POLARSSL_ECP_DP_BP384R1,      27,     384,    "brainpoolP384r1"   },
+#endif
+#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED)
+    { POLARSSL_ECP_DP_SECP256R1,    23,     256,    "secp256r1"         },
+#endif
+#if defined(POLARSSL_ECP_DP_SECP256K1_ENABLED)
+    { POLARSSL_ECP_DP_SECP256K1,    22,     256,    "secp256k1"         },
+#endif
+#if defined(POLARSSL_ECP_DP_BP256R1_ENABLED)
+    { POLARSSL_ECP_DP_BP256R1,      26,     256,    "brainpoolP256r1"   },
+#endif
+#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED)
+    { POLARSSL_ECP_DP_SECP224R1,    21,     224,    "secp224r1"         },
+#endif
+#if defined(POLARSSL_ECP_DP_SECP224K1_ENABLED)
+    { POLARSSL_ECP_DP_SECP224K1,    20,     224,    "secp224k1"         },
+#endif
+#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED)
+    { POLARSSL_ECP_DP_SECP192R1,    19,     192,    "secp192r1"         },
+#endif
+#if defined(POLARSSL_ECP_DP_SECP192K1_ENABLED)
+    { POLARSSL_ECP_DP_SECP192K1,    18,     192,    "secp192k1"         },
+#endif
+    { POLARSSL_ECP_DP_NONE,          0,     0,      NULL                },
+};
+
+static ecp_group_id ecp_supported_grp_id[POLARSSL_ECP_DP_MAX];
+
+/*
+ * List of supported curves and associated info
+ */
+const ecp_curve_info *ecp_curve_list( void )
+{
+    return ecp_supported_curves;
+}
+
+/*
+ * List of supported curves, group ID only
+ */
+const ecp_group_id *ecp_grp_id_list( void )
+{
+    static int init_done = 0;
+
+    if( ! init_done )
+    {
+        size_t i = 0;
+        const ecp_curve_info *curve_info;
+
+        for( curve_info = ecp_curve_list();
+             curve_info->grp_id != POLARSSL_ECP_DP_NONE;
+             curve_info++ )
+        {
+            ecp_supported_grp_id[i++] = curve_info->grp_id;
+        }
+        ecp_supported_grp_id[i] = POLARSSL_ECP_DP_NONE;
+
+        init_done = 1;
+    }
+
+    return ecp_supported_grp_id;
+}
+
+/*
+ * Get the curve info for the internal identifier
+ */
+const ecp_curve_info *ecp_curve_info_from_grp_id( ecp_group_id grp_id )
+{
+    const ecp_curve_info *curve_info;
+
+    for( curve_info = ecp_curve_list();
+         curve_info->grp_id != POLARSSL_ECP_DP_NONE;
+         curve_info++ )
+    {
+        if( curve_info->grp_id == grp_id )
+            return( curve_info );
+    }
+
+    return( NULL );
+}
+
+/*
+ * Get the curve info from the TLS identifier
+ */
+const ecp_curve_info *ecp_curve_info_from_tls_id( uint16_t tls_id )
+{
+    const ecp_curve_info *curve_info;
+
+    for( curve_info = ecp_curve_list();
+         curve_info->grp_id != POLARSSL_ECP_DP_NONE;
+         curve_info++ )
+    {
+        if( curve_info->tls_id == tls_id )
+            return( curve_info );
+    }
+
+    return( NULL );
+}
+
+/*
+ * Get the curve info from the name
+ */
+const ecp_curve_info *ecp_curve_info_from_name( const char *name )
+{
+    const ecp_curve_info *curve_info;
+
+    for( curve_info = ecp_curve_list();
+         curve_info->grp_id != POLARSSL_ECP_DP_NONE;
+         curve_info++ )
+    {
+        if( strcasecmp( curve_info->name, name ) == 0 )
+            return( curve_info );
+    }
+
+    return( NULL );
+}
+
+/*
+ * Get the type of a curve
+ */
+static inline ecp_curve_type ecp_get_type( const ecp_group *grp )
+{
+    if( grp->G.X.p == NULL )
+        return( POLARSSL_ECP_TYPE_NONE );
+
+    if( grp->G.Y.p == NULL )
+        return( POLARSSL_ECP_TYPE_MONTGOMERY );
+    else
+        return( POLARSSL_ECP_TYPE_SHORT_WEIERSTRASS );
+}
+
+/*
+ * Initialize (the components of) a point
+ */
+void ecp_point_init( ecp_point *pt )
+{
+    if( pt == NULL )
+        return;
+
+    mpi_init( &pt->X );
+    mpi_init( &pt->Y );
+    mpi_init( &pt->Z );
+}
+
+/*
+ * Initialize (the components of) a group
+ */
+void ecp_group_init( ecp_group *grp )
+{
+    if( grp == NULL )
+        return;
+
+    memset( grp, 0, sizeof( ecp_group ) );
+}
+
+/*
+ * Initialize (the components of) a key pair
+ */
+void ecp_keypair_init( ecp_keypair *key )
+{
+    if ( key == NULL )
+        return;
+
+    ecp_group_init( &key->grp );
+    mpi_init( &key->d );
+    ecp_point_init( &key->Q );
+}
+
+/*
+ * Unallocate (the components of) a point
+ */
+void ecp_point_free( ecp_point *pt )
+{
+    if( pt == NULL )
+        return;
+
+    mpi_free( &( pt->X ) );
+    mpi_free( &( pt->Y ) );
+    mpi_free( &( pt->Z ) );
+}
+
+/*
+ * Unallocate (the components of) a group
+ */
+void ecp_group_free( ecp_group *grp )
+{
+    size_t i;
+
+    if( grp == NULL )
+        return;
+
+    if( grp->h != 1 )
+    {
+        mpi_free( &grp->P );
+        mpi_free( &grp->A );
+        mpi_free( &grp->B );
+        ecp_point_free( &grp->G );
+        mpi_free( &grp->N );
+    }
+
+    if( grp->T != NULL )
+    {
+        for( i = 0; i < grp->T_size; i++ )
+            ecp_point_free( &grp->T[i] );
+        polarssl_free( grp->T );
+    }
+
+    memset( grp, 0, sizeof( ecp_group ) );
+}
+
+/*
+ * Unallocate (the components of) a key pair
+ */
+void ecp_keypair_free( ecp_keypair *key )
+{
+    if ( key == NULL )
+        return;
+
+    ecp_group_free( &key->grp );
+    mpi_free( &key->d );
+    ecp_point_free( &key->Q );
+}
+
+/*
+ * Copy the contents of a point
+ */
+int ecp_copy( ecp_point *P, const ecp_point *Q )
+{
+    int ret;
+
+    MPI_CHK( mpi_copy( &P->X, &Q->X ) );
+    MPI_CHK( mpi_copy( &P->Y, &Q->Y ) );
+    MPI_CHK( mpi_copy( &P->Z, &Q->Z ) );
+
+cleanup:
+    return( ret );
+}
+
+/*
+ * Copy the contents of a group object
+ */
+int ecp_group_copy( ecp_group *dst, const ecp_group *src )
+{
+    return ecp_use_known_dp( dst, src->id );
+}
+
+/*
+ * Set point to zero
+ */
+int ecp_set_zero( ecp_point *pt )
+{
+    int ret;
+
+    MPI_CHK( mpi_lset( &pt->X , 1 ) );
+    MPI_CHK( mpi_lset( &pt->Y , 1 ) );
+    MPI_CHK( mpi_lset( &pt->Z , 0 ) );
+
+cleanup:
+    return( ret );
+}
+
+/*
+ * Tell if a point is zero
+ */
+int ecp_is_zero( ecp_point *pt )
+{
+    return( mpi_cmp_int( &pt->Z, 0 ) == 0 );
+}
+
+/*
+ * Import a non-zero point from ASCII strings
+ */
+int ecp_point_read_string( ecp_point *P, int radix,
+                           const char *x, const char *y )
+{
+    int ret;
+
+    MPI_CHK( mpi_read_string( &P->X, radix, x ) );
+    MPI_CHK( mpi_read_string( &P->Y, radix, y ) );
+    MPI_CHK( mpi_lset( &P->Z, 1 ) );
+
+cleanup:
+    return( ret );
+}
+
+/*
+ * Export a point into unsigned binary data (SEC1 2.3.3)
+ */
+int ecp_point_write_binary( const ecp_group *grp, const ecp_point *P,
+                            int format, size_t *olen,
+                            unsigned char *buf, size_t buflen )
+{
+    int ret = 0;
+    size_t plen;
+
+    if( format != POLARSSL_ECP_PF_UNCOMPRESSED &&
+        format != POLARSSL_ECP_PF_COMPRESSED )
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+
+    /*
+     * Common case: P == 0
+     */
+    if( mpi_cmp_int( &P->Z, 0 ) == 0 )
+    {
+        if( buflen < 1 )
+            return( POLARSSL_ERR_ECP_BUFFER_TOO_SMALL );
+
+        buf[0] = 0x00;
+        *olen = 1;
+
+        return( 0 );
+    }
+
+    plen = mpi_size( &grp->P );
+
+    if( format == POLARSSL_ECP_PF_UNCOMPRESSED )
+    {
+        *olen = 2 * plen + 1;
+
+        if( buflen < *olen )
+            return( POLARSSL_ERR_ECP_BUFFER_TOO_SMALL );
+
+        buf[0] = 0x04;
+        MPI_CHK( mpi_write_binary( &P->X, buf + 1, plen ) );
+        MPI_CHK( mpi_write_binary( &P->Y, buf + 1 + plen, plen ) );
+    }
+    else if( format == POLARSSL_ECP_PF_COMPRESSED )
+    {
+        *olen = plen + 1;
+
+        if( buflen < *olen )
+            return( POLARSSL_ERR_ECP_BUFFER_TOO_SMALL );
+
+        buf[0] = 0x02 + mpi_get_bit( &P->Y, 0 );
+        MPI_CHK( mpi_write_binary( &P->X, buf + 1, plen ) );
+    }
+
+cleanup:
+    return( ret );
+}
+
+/*
+ * Import a point from unsigned binary data (SEC1 2.3.4)
+ */
+int ecp_point_read_binary( const ecp_group *grp, ecp_point *pt,
+                           const unsigned char *buf, size_t ilen )
+{
+    int ret;
+    size_t plen;
+
+    if( buf[0] == 0x00 )
+    {
+        if( ilen == 1 )
+            return( ecp_set_zero( pt ) );
+        else
+            return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+    }
+
+    plen = mpi_size( &grp->P );
+
+    if( buf[0] != 0x04 )
+        return( POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE );
+
+    if( ilen != 2 * plen + 1 )
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+
+    MPI_CHK( mpi_read_binary( &pt->X, buf + 1, plen ) );
+    MPI_CHK( mpi_read_binary( &pt->Y, buf + 1 + plen, plen ) );
+    MPI_CHK( mpi_lset( &pt->Z, 1 ) );
+
+cleanup:
+    return( ret );
+}
+
+/*
+ * Import a point from a TLS ECPoint record (RFC 4492)
+ *      struct {
+ *          opaque point <1..2^8-1>;
+ *      } ECPoint;
+ */
+int ecp_tls_read_point( const ecp_group *grp, ecp_point *pt,
+                        const unsigned char **buf, size_t buf_len )
+{
+    unsigned char data_len;
+    const unsigned char *buf_start;
+
+    /*
+     * We must have at least two bytes (1 for length, at least of for data)
+     */
+    if( buf_len < 2 )
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+
+    data_len = *(*buf)++;
+    if( data_len < 1 || data_len > buf_len - 1 )
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+
+    /*
+     * Save buffer start for read_binary and update buf
+     */
+    buf_start = *buf;
+    *buf += data_len;
+
+    return ecp_point_read_binary( grp, pt, buf_start, data_len );
+}
+
+/*
+ * Export a point as a TLS ECPoint record (RFC 4492)
+ *      struct {
+ *          opaque point <1..2^8-1>;
+ *      } ECPoint;
+ */
+int ecp_tls_write_point( const ecp_group *grp, const ecp_point *pt,
+                         int format, size_t *olen,
+                         unsigned char *buf, size_t blen )
+{
+    int ret;
+
+    /*
+     * buffer length must be at least one, for our length byte
+     */
+    if( blen < 1 )
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+
+    if( ( ret = ecp_point_write_binary( grp, pt, format,
+                    olen, buf + 1, blen - 1) ) != 0 )
+        return( ret );
+
+    /*
+     * write length to the first byte and update total length
+     */
+    buf[0] = (unsigned char) *olen;
+    ++*olen;
+
+    return 0;
+}
+
+/*
+ * Import an ECP group from ASCII strings, case A == -3
+ */
+int ecp_group_read_string( ecp_group *grp, int radix,
+                           const char *p, const char *b,
+                           const char *gx, const char *gy, const char *n)
+{
+    int ret;
+
+    MPI_CHK( mpi_read_string( &grp->P, radix, p ) );
+    MPI_CHK( mpi_read_string( &grp->B, radix, b ) );
+    MPI_CHK( ecp_point_read_string( &grp->G, radix, gx, gy ) );
+    MPI_CHK( mpi_read_string( &grp->N, radix, n ) );
+
+    grp->pbits = mpi_msb( &grp->P );
+    grp->nbits = mpi_msb( &grp->N );
+
+cleanup:
+    if( ret != 0 )
+        ecp_group_free( grp );
+
+    return( ret );
+}
+
+/*
+ * Set a group from an ECParameters record (RFC 4492)
+ */
+int ecp_tls_read_group( ecp_group *grp, const unsigned char **buf, size_t len )
+{
+    uint16_t tls_id;
+    const ecp_curve_info *curve_info;
+
+    /*
+     * We expect at least three bytes (see below)
+     */
+    if( len < 3 )
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+
+    /*
+     * First byte is curve_type; only named_curve is handled
+     */
+    if( *(*buf)++ != POLARSSL_ECP_TLS_NAMED_CURVE )
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+
+    /*
+     * Next two bytes are the namedcurve value
+     */
+    tls_id = *(*buf)++;
+    tls_id <<= 8;
+    tls_id |= *(*buf)++;
+
+    if( ( curve_info = ecp_curve_info_from_tls_id( tls_id ) ) == NULL )
+        return( POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE );
+
+    return ecp_use_known_dp( grp, curve_info->grp_id );
+}
+
+/*
+ * Write the ECParameters record corresponding to a group (RFC 4492)
+ */
+int ecp_tls_write_group( const ecp_group *grp, size_t *olen,
+                         unsigned char *buf, size_t blen )
+{
+    const ecp_curve_info *curve_info;
+
+    if( ( curve_info = ecp_curve_info_from_grp_id( grp->id ) ) == NULL )
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+
+    /*
+     * We are going to write 3 bytes (see below)
+     */
+    *olen = 3;
+    if( blen < *olen )
+        return( POLARSSL_ERR_ECP_BUFFER_TOO_SMALL );
+
+    /*
+     * First byte is curve_type, always named_curve
+     */
+    *buf++ = POLARSSL_ECP_TLS_NAMED_CURVE;
+
+    /*
+     * Next two bytes are the namedcurve value
+     */
+    buf[0] = curve_info->tls_id >> 8;
+    buf[1] = curve_info->tls_id & 0xFF;
+
+    return 0;
+}
+
+/*
+ * Wrapper around fast quasi-modp functions, with fall-back to mpi_mod_mpi.
+ * See the documentation of struct ecp_group.
+ *
+ * This function is in the critial loop for ecp_mul, so pay attention to perf.
+ */
+static int ecp_modp( mpi *N, const ecp_group *grp )
+{
+    int ret;
+
+    if( grp->modp == NULL )
+        return( mpi_mod_mpi( N, N, &grp->P ) );
+
+    /* N->s < 0 is a much faster test, which fails only if N is 0 */
+    if( ( N->s < 0 && mpi_cmp_int( N, 0 ) != 0 ) ||
+        mpi_msb( N ) > 2 * grp->pbits )
+    {
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+    }
+
+    MPI_CHK( grp->modp( N ) );
+
+    /* N->s < 0 is a much faster test, which fails only if N is 0 */
+    while( N->s < 0 && mpi_cmp_int( N, 0 ) != 0 )
+        MPI_CHK( mpi_add_mpi( N, N, &grp->P ) );
+
+    while( mpi_cmp_mpi( N, &grp->P ) >= 0 )
+        /* we known P, N and the result are positive */
+        MPI_CHK( mpi_sub_abs( N, N, &grp->P ) );
+
+cleanup:
+    return( ret );
+}
+
+/*
+ * Fast mod-p functions expect their argument to be in the 0..p^2 range.
+ *
+ * In order to guarantee that, we need to ensure that operands of
+ * mpi_mul_mpi are in the 0..p range. So, after each operation we will
+ * bring the result back to this range.
+ *
+ * The following macros are shortcuts for doing that.
+ */
+
+/*
+ * Reduce a mpi mod p in-place, general case, to use after mpi_mul_mpi
+ */
+#if defined(POLARSSL_SELF_TEST)
+#define INC_MUL_COUNT   mul_count++;
+#else
+#define INC_MUL_COUNT
+#endif
+
+#define MOD_MUL( N )    do { MPI_CHK( ecp_modp( &N, grp ) ); INC_MUL_COUNT } \
+                        while( 0 )
+
+/*
+ * Reduce a mpi mod p in-place, to use after mpi_sub_mpi
+ * N->s < 0 is a very fast test, which fails only if N is 0
+ */
+#define MOD_SUB( N )                                \
+    while( N.s < 0 && mpi_cmp_int( &N, 0 ) != 0 )   \
+        MPI_CHK( mpi_add_mpi( &N, &N, &grp->P ) )
+
+/*
+ * Reduce a mpi mod p in-place, to use after mpi_add_mpi and mpi_mul_int.
+ * We known P, N and the result are positive, so sub_abs is correct, and
+ * a bit faster.
+ */
+#define MOD_ADD( N )                                \
+    while( mpi_cmp_mpi( &N, &grp->P ) >= 0 )        \
+        MPI_CHK( mpi_sub_abs( &N, &N, &grp->P ) )
+
+#if defined(POLARSSL_ECP_SHORT_WEIERSTRASS)
+/*
+ * For curves in short Weierstrass form, we do all the internal operations in
+ * Jacobian coordinates.
+ *
+ * For multiplication, we'll use a comb method with coutermeasueres against
+ * SPA, hence timing attacks.
+ */
+
+/*
+ * Normalize jacobian coordinates so that Z == 0 || Z == 1  (GECC 3.2.1)
+ * Cost: 1N := 1I + 3M + 1S
+ */
+static int ecp_normalize_jac( const ecp_group *grp, ecp_point *pt )
+{
+    int ret;
+    mpi Zi, ZZi;
+
+    if( mpi_cmp_int( &pt->Z, 0 ) == 0 )
+        return( 0 );
+
+    mpi_init( &Zi ); mpi_init( &ZZi );
+
+    /*
+     * X = X / Z^2  mod p
+     */
+    MPI_CHK( mpi_inv_mod( &Zi,      &pt->Z,     &grp->P ) );
+    MPI_CHK( mpi_mul_mpi( &ZZi,     &Zi,        &Zi     ) ); MOD_MUL( ZZi );
+    MPI_CHK( mpi_mul_mpi( &pt->X,   &pt->X,     &ZZi    ) ); MOD_MUL( pt->X );
+
+    /*
+     * Y = Y / Z^3  mod p
+     */
+    MPI_CHK( mpi_mul_mpi( &pt->Y,   &pt->Y,     &ZZi    ) ); MOD_MUL( pt->Y );
+    MPI_CHK( mpi_mul_mpi( &pt->Y,   &pt->Y,     &Zi     ) ); MOD_MUL( pt->Y );
+
+    /*
+     * Z = 1
+     */
+    MPI_CHK( mpi_lset( &pt->Z, 1 ) );
+
+cleanup:
+
+    mpi_free( &Zi ); mpi_free( &ZZi );
+
+    return( ret );
+}
+
+/*
+ * Normalize jacobian coordinates of an array of (pointers to) points,
+ * using Montgomery's trick to perform only one inversion mod P.
+ * (See for example Cohen's "A Course in Computational Algebraic Number
+ * Theory", Algorithm 10.3.4.)
+ *
+ * Warning: fails (returning an error) if one of the points is zero!
+ * This should never happen, see choice of w in ecp_mul_comb().
+ *
+ * Cost: 1N(t) := 1I + (6t - 3)M + 1S
+ */
+static int ecp_normalize_jac_many( const ecp_group *grp,
+                                   ecp_point *T[], size_t t_len )
+{
+    int ret;
+    size_t i;
+    mpi *c, u, Zi, ZZi;
+
+    if( t_len < 2 )
+        return( ecp_normalize_jac( grp, *T ) );
+
+    if( ( c = (mpi *) polarssl_malloc( t_len * sizeof( mpi ) ) ) == NULL )
+        return( POLARSSL_ERR_ECP_MALLOC_FAILED );
+
+    mpi_init( &u ); mpi_init( &Zi ); mpi_init( &ZZi );
+    for( i = 0; i < t_len; i++ )
+        mpi_init( &c[i] );
+
+    /*
+     * c[i] = Z_0 * ... * Z_i
+     */
+    MPI_CHK( mpi_copy( &c[0], &T[0]->Z ) );
+    for( i = 1; i < t_len; i++ )
+    {
+        MPI_CHK( mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) );
+        MOD_MUL( c[i] );
+    }
+
+    /*
+     * u = 1 / (Z_0 * ... * Z_n) mod P
+     */
+    MPI_CHK( mpi_inv_mod( &u, &c[t_len-1], &grp->P ) );
+
+    for( i = t_len - 1; ; i-- )
+    {
+        /*
+         * Zi = 1 / Z_i mod p
+         * u = 1 / (Z_0 * ... * Z_i) mod P
+         */
+        if( i == 0 ) {
+            MPI_CHK( mpi_copy( &Zi, &u ) );
+        }
+        else
+        {
+            MPI_CHK( mpi_mul_mpi( &Zi, &u, &c[i-1]  ) ); MOD_MUL( Zi );
+            MPI_CHK( mpi_mul_mpi( &u,  &u, &T[i]->Z ) ); MOD_MUL( u );
+        }
+
+        /*
+         * proceed as in normalize()
+         */
+        MPI_CHK( mpi_mul_mpi( &ZZi,     &Zi,      &Zi  ) ); MOD_MUL( ZZi );
+        MPI_CHK( mpi_mul_mpi( &T[i]->X, &T[i]->X, &ZZi ) ); MOD_MUL( T[i]->X );
+        MPI_CHK( mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &ZZi ) ); MOD_MUL( T[i]->Y );
+        MPI_CHK( mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &Zi  ) ); MOD_MUL( T[i]->Y );
+
+        /*
+         * Post-precessing: reclaim some memory by shrinking coordinates
+         * - not storing Z (always 1)
+         * - shrinking other coordinates, but still keeping the same number of
+         *   limbs as P, as otherwise it will too likely be regrown too fast.
+         */
+        MPI_CHK( mpi_shrink( &T[i]->X, grp->P.n ) );
+        MPI_CHK( mpi_shrink( &T[i]->Y, grp->P.n ) );
+        mpi_free( &T[i]->Z );
+
+        if( i == 0 )
+            break;
+    }
+
+cleanup:
+
+    mpi_free( &u ); mpi_free( &Zi ); mpi_free( &ZZi );
+    for( i = 0; i < t_len; i++ )
+        mpi_free( &c[i] );
+    polarssl_free( c );
+
+    return( ret );
+}
+
+/*
+ * Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak.
+ * "inv" must be 0 (don't invert) or 1 (invert) or the result will be invalid
+ */
+static int ecp_safe_invert_jac( const ecp_group *grp,
+                            ecp_point *Q,
+                            unsigned char inv )
+{
+    int ret;
+    unsigned char nonzero;
+    mpi mQY;
+
+    mpi_init( &mQY );
+
+    /* Use the fact that -Q.Y mod P = P - Q.Y unless Q.Y == 0 */
+    MPI_CHK( mpi_sub_mpi( &mQY, &grp->P, &Q->Y ) );
+    nonzero = mpi_cmp_int( &Q->Y, 0 ) != 0;
+    MPI_CHK( mpi_safe_cond_assign( &Q->Y, &mQY, inv & nonzero ) );
+
+cleanup:
+    mpi_free( &mQY );
+
+    return( ret );
+}
+
+/*
+ * Point doubling R = 2 P, Jacobian coordinates
+ *
+ * http://www.hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian/doubling/dbl-2007-bl.op3
+ * with heavy variable renaming, some reordering and one minor modification
+ * (a = 2 * b, c = d - 2a replaced with c = d, c = c - b, c = c - b)
+ * in order to use a lot less intermediate variables (6 vs 25).
+ *
+ * Cost: 1D := 2M + 8S
+ */
+static int ecp_double_jac( const ecp_group *grp, ecp_point *R,
+                           const ecp_point *P )
+{
+    int ret;
+    mpi T1, T2, T3, X3, Y3, Z3;
+
+#if defined(POLARSSL_SELF_TEST)
+    dbl_count++;
+#endif
+
+    mpi_init( &T1 ); mpi_init( &T2 ); mpi_init( &T3 );
+    mpi_init( &X3 ); mpi_init( &Y3 ); mpi_init( &Z3 );
+
+    MPI_CHK( mpi_mul_mpi( &T3,  &P->X,  &P->X   ) ); MOD_MUL( T3 );
+    MPI_CHK( mpi_mul_mpi( &T2,  &P->Y,  &P->Y   ) ); MOD_MUL( T2 );
+    MPI_CHK( mpi_mul_mpi( &Y3,  &T2,    &T2     ) ); MOD_MUL( Y3 );
+    MPI_CHK( mpi_add_mpi( &X3,  &P->X,  &T2     ) ); MOD_ADD( X3 );
+    MPI_CHK( mpi_mul_mpi( &X3,  &X3,    &X3     ) ); MOD_MUL( X3 );
+    MPI_CHK( mpi_sub_mpi( &X3,  &X3,    &Y3     ) ); MOD_SUB( X3 );
+    MPI_CHK( mpi_sub_mpi( &X3,  &X3,    &T3     ) ); MOD_SUB( X3 );
+    MPI_CHK( mpi_mul_int( &T1,  &X3,    2       ) ); MOD_ADD( T1 );
+    MPI_CHK( mpi_mul_mpi( &Z3,  &P->Z,  &P->Z   ) ); MOD_MUL( Z3 );
+    MPI_CHK( mpi_mul_mpi( &X3,  &Z3,    &Z3     ) ); MOD_MUL( X3 );
+    MPI_CHK( mpi_mul_int( &T3,  &T3,    3       ) ); MOD_ADD( T3 );
+
+    /* Special case for A = -3 */
+    if( grp->A.p == NULL )
+    {
+        MPI_CHK( mpi_mul_int( &X3, &X3, 3 ) );
+        X3.s = -1; /* mpi_mul_int doesn't handle negative numbers */
+        MOD_SUB( X3 );
+    }
+    else
+        MPI_CHK( mpi_mul_mpi( &X3,  &X3,    &grp->A ) ); MOD_MUL( X3 );
+
+    MPI_CHK( mpi_add_mpi( &T3,  &T3,    &X3     ) ); MOD_ADD( T3 );
+    MPI_CHK( mpi_mul_mpi( &X3,  &T3,    &T3     ) ); MOD_MUL( X3 );
+    MPI_CHK( mpi_sub_mpi( &X3,  &X3,    &T1     ) ); MOD_SUB( X3 );
+    MPI_CHK( mpi_sub_mpi( &X3,  &X3,    &T1     ) ); MOD_SUB( X3 );
+    MPI_CHK( mpi_sub_mpi( &T1,  &T1,    &X3     ) ); MOD_SUB( T1 );
+    MPI_CHK( mpi_mul_mpi( &T1,  &T3,    &T1     ) ); MOD_MUL( T1 );
+    MPI_CHK( mpi_mul_int( &T3,  &Y3,    8       ) ); MOD_ADD( T3 );
+    MPI_CHK( mpi_sub_mpi( &Y3,  &T1,    &T3     ) ); MOD_SUB( Y3 );
+    MPI_CHK( mpi_add_mpi( &T1,  &P->Y,  &P->Z   ) ); MOD_ADD( T1 );
+    MPI_CHK( mpi_mul_mpi( &T1,  &T1,    &T1     ) ); MOD_MUL( T1 );
+    MPI_CHK( mpi_sub_mpi( &T1,  &T1,    &T2     ) ); MOD_SUB( T1 );
+    MPI_CHK( mpi_sub_mpi( &Z3,  &T1,    &Z3     ) ); MOD_SUB( Z3 );
+
+    MPI_CHK( mpi_copy( &R->X, &X3 ) );
+    MPI_CHK( mpi_copy( &R->Y, &Y3 ) );
+    MPI_CHK( mpi_copy( &R->Z, &Z3 ) );
+
+cleanup:
+    mpi_free( &T1 ); mpi_free( &T2 ); mpi_free( &T3 );
+    mpi_free( &X3 ); mpi_free( &Y3 ); mpi_free( &Z3 );
+
+    return( ret );
+}
+
+/*
+ * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22)
+ *
+ * The coordinates of Q must be normalized (= affine),
+ * but those of P don't need to. R is not normalized.
+ *
+ * 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: 1A := 8M + 3S
+ */
+static int ecp_add_mixed( const ecp_group *grp, ecp_point *R,
+                          const ecp_point *P, const ecp_point *Q )
+{
+    int ret;
+    mpi T1, T2, T3, T4, X, Y, Z;
+
+#if defined(POLARSSL_SELF_TEST)
+    add_count++;
+#endif
+
+    /*
+     * Trivial cases: P == 0 or Q == 0 (case 1)
+     */
+    if( mpi_cmp_int( &P->Z, 0 ) == 0 )
+        return( ecp_copy( R, Q ) );
+
+    if( Q->Z.p != NULL && mpi_cmp_int( &Q->Z, 0 ) == 0 )
+        return( ecp_copy( R, P ) );
+
+    /*
+     * Make sure Q coordinates are normalized
+     */
+    if( Q->Z.p != NULL && mpi_cmp_int( &Q->Z, 1 ) != 0 )
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+
+    mpi_init( &T1 ); mpi_init( &T2 ); mpi_init( &T3 ); mpi_init( &T4 );
+    mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
+
+    MPI_CHK( mpi_mul_mpi( &T1,  &P->Z,  &P->Z ) );  MOD_MUL( T1 );
+    MPI_CHK( mpi_mul_mpi( &T2,  &T1,    &P->Z ) );  MOD_MUL( T2 );
+    MPI_CHK( mpi_mul_mpi( &T1,  &T1,    &Q->X ) );  MOD_MUL( T1 );
+    MPI_CHK( mpi_mul_mpi( &T2,  &T2,    &Q->Y ) );  MOD_MUL( T2 );
+    MPI_CHK( mpi_sub_mpi( &T1,  &T1,    &P->X ) );  MOD_SUB( T1 );
+    MPI_CHK( mpi_sub_mpi( &T2,  &T2,    &P->Y ) );  MOD_SUB( T2 );
+
+    /* Special cases (2) and (3) */
+    if( mpi_cmp_int( &T1, 0 ) == 0 )
+    {
+        if( mpi_cmp_int( &T2, 0 ) == 0 )
+        {
+            ret = ecp_double_jac( grp, R, P );
+            goto cleanup;
+        }
+        else
+        {
+            ret = ecp_set_zero( R );
+            goto cleanup;
+        }
+    }
+
+    MPI_CHK( mpi_mul_mpi( &Z,   &P->Z,  &T1   ) );  MOD_MUL( Z  );
+    MPI_CHK( mpi_mul_mpi( &T3,  &T1,    &T1   ) );  MOD_MUL( T3 );
+    MPI_CHK( mpi_mul_mpi( &T4,  &T3,    &T1   ) );  MOD_MUL( T4 );
+    MPI_CHK( mpi_mul_mpi( &T3,  &T3,    &P->X ) );  MOD_MUL( T3 );
+    MPI_CHK( mpi_mul_int( &T1,  &T3,    2     ) );  MOD_ADD( T1 );
+    MPI_CHK( mpi_mul_mpi( &X,   &T2,    &T2   ) );  MOD_MUL( X  );
+    MPI_CHK( mpi_sub_mpi( &X,   &X,     &T1   ) );  MOD_SUB( X  );
+    MPI_CHK( mpi_sub_mpi( &X,   &X,     &T4   ) );  MOD_SUB( X  );
+    MPI_CHK( mpi_sub_mpi( &T3,  &T3,    &X    ) );  MOD_SUB( T3 );
+    MPI_CHK( mpi_mul_mpi( &T3,  &T3,    &T2   ) );  MOD_MUL( T3 );
+    MPI_CHK( mpi_mul_mpi( &T4,  &T4,    &P->Y ) );  MOD_MUL( T4 );
+    MPI_CHK( mpi_sub_mpi( &Y,   &T3,    &T4   ) );  MOD_SUB( Y  );
+
+    MPI_CHK( mpi_copy( &R->X, &X ) );
+    MPI_CHK( mpi_copy( &R->Y, &Y ) );
+    MPI_CHK( mpi_copy( &R->Z, &Z ) );
+
+cleanup:
+
+    mpi_free( &T1 ); mpi_free( &T2 ); mpi_free( &T3 ); mpi_free( &T4 );
+    mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z );
+
+    return( ret );
+}
+
+/*
+ * Addition: R = P + Q, result's coordinates normalized
+ */
+int ecp_add( const ecp_group *grp, ecp_point *R,
+             const ecp_point *P, const ecp_point *Q )
+{
+    int ret;
+
+    if( ecp_get_type( grp ) != POLARSSL_ECP_TYPE_SHORT_WEIERSTRASS )
+        return( POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE );
+
+    MPI_CHK( ecp_add_mixed( grp, R, P, Q ) );
+    MPI_CHK( ecp_normalize_jac( grp, R ) );
+
+cleanup:
+    return( ret );
+}
+
+/*
+ * Subtraction: R = P - Q, result's coordinates normalized
+ */
+int ecp_sub( const ecp_group *grp, ecp_point *R,
+             const ecp_point *P, const ecp_point *Q )
+{
+    int ret;
+    ecp_point mQ;
+
+    ecp_point_init( &mQ );
+
+    if( ecp_get_type( grp ) != POLARSSL_ECP_TYPE_SHORT_WEIERSTRASS )
+        return( POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE );
+
+    /* mQ = - Q */
+    MPI_CHK( ecp_copy( &mQ, Q ) );
+    if( mpi_cmp_int( &mQ.Y, 0 ) != 0 )
+        MPI_CHK( mpi_sub_mpi( &mQ.Y, &grp->P, &mQ.Y ) );
+
+    MPI_CHK( ecp_add_mixed( grp, R, P, &mQ ) );
+    MPI_CHK( ecp_normalize_jac( grp, R ) );
+
+cleanup:
+    ecp_point_free( &mQ );
+
+    return( ret );
+}
+
+/*
+ * Randomize jacobian coordinates:
+ * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l
+ * This is sort of the reverse operation of ecp_normalize_jac().
+ *
+ * This countermeasure was first suggested in [2].
+ */
+static int ecp_randomize_jac( const ecp_group *grp, ecp_point *pt,
+                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+    int ret;
+    mpi l, ll;
+    size_t p_size = (grp->pbits + 7) / 8;
+    int count = 0;
+
+    mpi_init( &l ); mpi_init( &ll );
+
+    /* Generate l such that 1 < l < p */
+    do
+    {
+        mpi_fill_random( &l, p_size, f_rng, p_rng );
+
+        while( mpi_cmp_mpi( &l, &grp->P ) >= 0 )
+            MPI_CHK( mpi_shift_r( &l, 1 ) );
+
+        if( count++ > 10 )
+            return( POLARSSL_ERR_ECP_RANDOM_FAILED );
+    }
+    while( mpi_cmp_int( &l, 1 ) <= 0 );
+
+    /* Z = l * Z */
+    MPI_CHK( mpi_mul_mpi( &pt->Z,   &pt->Z,     &l  ) ); MOD_MUL( pt->Z );
+
+    /* X = l^2 * X */
+    MPI_CHK( mpi_mul_mpi( &ll,      &l,         &l  ) ); MOD_MUL( ll );
+    MPI_CHK( mpi_mul_mpi( &pt->X,   &pt->X,     &ll ) ); MOD_MUL( pt->X );
+
+    /* Y = l^3 * Y */
+    MPI_CHK( mpi_mul_mpi( &ll,      &ll,        &l  ) ); MOD_MUL( ll );
+    MPI_CHK( mpi_mul_mpi( &pt->Y,   &pt->Y,     &ll ) ); MOD_MUL( pt->Y );
+
+cleanup:
+    mpi_free( &l ); mpi_free( &ll );
+
+    return( ret );
+}
+
+/*
+ * Check and define parameters used by the comb method (see below for details)
+ */
+#if POLARSSL_ECP_WINDOW_SIZE < 2 || POLARSSL_ECP_WINDOW_SIZE > 7
+#error "POLARSSL_ECP_WINDOW_SIZE out of bounds"
+#endif
+
+/* d = ceil( n / w ) */
+#define COMB_MAX_D      ( POLARSSL_ECP_MAX_BITS + 1 ) / 2
+
+/* number of precomputed points */
+#define COMB_MAX_PRE    ( 1 << ( POLARSSL_ECP_WINDOW_SIZE - 1 ) )
+
+/*
+ * Compute the representation of m that will be used with our comb method.
+ *
+ * The basic comb method is described in GECC 3.44 for example. We use a
+ * modified version that provides resistance to SPA by avoiding zero
+ * digits in the representation as in [3]. We modify the method further by
+ * requiring that all K_i be odd, which has the small cost that our
+ * representation uses one more K_i, due to carries.
+ *
+ * Also, for the sake of compactness, only the seven low-order bits of x[i]
+ * are used to represent K_i, and the msb of x[i] encodes the the sign (s_i in
+ * the paper): it is set if and only if if s_i == -1;
+ *
+ * Calling conventions:
+ * - x is an array of size d + 1
+ * - w is the size, ie number of teeth, of the comb, and must be between
+ *   2 and 7 (in practice, between 2 and POLARSSL_ECP_WINDOW_SIZE)
+ * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d
+ *   (the result will be incorrect if these assumptions are not satisfied)
+ */
+static void ecp_comb_fixed( unsigned char x[], size_t d,
+                            unsigned char w, const mpi *m )
+{
+    size_t i, j;
+    unsigned char c, cc, adjust;
+
+    memset( x, 0, d+1 );
+
+    /* First get the classical comb values (except for x_d = 0) */
+    for( i = 0; i < d; i++ )
+        for( j = 0; j < w; j++ )
+            x[i] |= mpi_get_bit( m, i + d * j ) << j;
+
+    /* Now make sure x_1 .. x_d are odd */
+    c = 0;
+    for( i = 1; i <= d; i++ )
+    {
+        /* Add carry and update it */
+        cc   = x[i] & c;
+        x[i] = x[i] ^ c;
+        c = cc;
+
+        /* Adjust if needed, avoiding branches */
+        adjust = 1 - ( x[i] & 0x01 );
+        c   |= x[i] & ( x[i-1] * adjust );
+        x[i] = x[i] ^ ( x[i-1] * adjust );
+        x[i-1] |= adjust << 7;
+    }
+}
+
+/*
+ * Precompute points for the comb method
+ *
+ * If i = i_{w-1} ... i_1 is the binary representation of i, then
+ * T[i] = i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + P
+ *
+ * T must be able to hold 2^{w - 1} elements
+ *
+ * Cost: d(w-1) D + (2^{w-1} - 1) A + 1 N(w-1) + 1 N(2^{w-1} - 1)
+ */
+static int ecp_precompute_comb( const ecp_group *grp,
+                                ecp_point T[], const ecp_point *P,
+                                unsigned char w, size_t d )
+{
+    int ret;
+    unsigned char i, k;
+    size_t j;
+    ecp_point *cur, *TT[COMB_MAX_PRE - 1];
+
+    /*
+     * Set T[0] = P and
+     * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value)
+     */
+    MPI_CHK( ecp_copy( &T[0], P ) );
+
+    k = 0;
+    for( i = 1; i < ( 1U << (w-1) ); i <<= 1 )
+    {
+        cur = T + i;
+        MPI_CHK( ecp_copy( cur, T + ( i >> 1 ) ) );
+        for( j = 0; j < d; j++ )
+            MPI_CHK( ecp_double_jac( grp, cur, cur ) );
+
+        TT[k++] = cur;
+    }
+
+    MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) );
+
+    /*
+     * Compute the remaining ones using the minimal number of additions
+     * Be careful to update T[2^l] only after using it!
+     */
+    k = 0;
+    for( i = 1; i < ( 1U << (w-1) ); i <<= 1 )
+    {
+        j = i;
+        while( j-- )
+        {
+            MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) );
+            TT[k++] = &T[i + j];
+        }
+    }
+
+    MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) );
+
+cleanup:
+    return( ret );
+}
+
+/*
+ * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ]
+ */
+static int ecp_select_comb( const ecp_group *grp, ecp_point *R,
+                            const ecp_point T[], unsigned char t_len,
+                            unsigned char i )
+{
+    int ret;
+    unsigned char ii, j;
+
+    /* Ignore the "sign" bit and scale down */
+    ii =  ( i & 0x7Fu ) >> 1;
+
+    /* Read the whole table to thwart cache-based timing attacks */
+    for( j = 0; j < t_len; j++ )
+    {
+        MPI_CHK( mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) );
+        MPI_CHK( mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) );
+    }
+
+    /* Safely invert result if i is "negative" */
+    MPI_CHK( ecp_safe_invert_jac( grp, R, i >> 7 ) );
+
+cleanup:
+    return( ret );
+}
+
+/*
+ * Core multiplication algorithm for the (modified) comb method.
+ * This part is actually common with the basic comb method (GECC 3.44)
+ *
+ * Cost: d A + d D + 1 R
+ */
+static int ecp_mul_comb_core( const ecp_group *grp, ecp_point *R,
+                              const ecp_point T[], unsigned char t_len,
+                              const unsigned char x[], size_t d,
+                              int (*f_rng)(void *, unsigned char *, size_t),
+                              void *p_rng )
+{
+    int ret;
+    ecp_point Txi;
+    size_t i;
+
+    ecp_point_init( &Txi );
+
+    /* Start with a non-zero point and randomize its coordinates */
+    i = d;
+    MPI_CHK( ecp_select_comb( grp, R, T, t_len, x[i] ) );
+    MPI_CHK( mpi_lset( &R->Z, 1 ) );
+    if( f_rng != 0 )
+        MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
+
+    while( i-- != 0 )
+    {
+        MPI_CHK( ecp_double_jac( grp, R, R ) );
+        MPI_CHK( ecp_select_comb( grp, &Txi, T, t_len, x[i] ) );
+        MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) );
+    }
+
+cleanup:
+    ecp_point_free( &Txi );
+
+    return( ret );
+}
+
+/*
+ * Multiplication using the comb method,
+ * for curves in short Weierstrass form
+ */
+static int ecp_mul_comb( ecp_group *grp, ecp_point *R,
+                         const mpi *m, const ecp_point *P,
+                         int (*f_rng)(void *, unsigned char *, size_t),
+                         void *p_rng )
+{
+    int ret;
+    unsigned char w, m_is_odd, p_eq_g, pre_len, i;
+    size_t d;
+    unsigned char k[COMB_MAX_D + 1];
+    ecp_point *T;
+    mpi M, mm;
+
+    mpi_init( &M );
+    mpi_init( &mm );
+
+    /* we need N to be odd to trnaform m in an odd number, check now */
+    if( mpi_get_bit( &grp->N, 0 ) != 1 )
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+
+    /*
+     * Minimize the number of multiplications, that is minimize
+     * 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w )
+     * (see costs of the various parts, with 1S = 1M)
+     */
+    w = grp->nbits >= 384 ? 5 : 4;
+
+    /*
+     * If P == G, pre-compute a bit more, since this may be re-used later.
+     * Just adding one avoids upping the cost of the first mul too much,
+     * and the memory cost too.
+     */
+#if POLARSSL_ECP_FIXED_POINT_OPTIM == 1
+    p_eq_g = ( mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 &&
+               mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 );
+    if( p_eq_g )
+        w++;
+#else
+    p_eq_g = 0;
+#endif
+
+    /*
+     * Make sure w is within bounds.
+     * (The last test is useful only for very small curves in the test suite.)
+     */
+    if( w > POLARSSL_ECP_WINDOW_SIZE )
+        w = POLARSSL_ECP_WINDOW_SIZE;
+    if( w >= grp->nbits )
+        w = 2;
+
+    /* Other sizes that depend on w */
+    pre_len = 1U << ( w - 1 );
+    d = ( grp->nbits + w - 1 ) / w;
+
+    /*
+     * Prepare precomputed points: if P == G we want to
+     * use grp->T if already initialized, or initialize it.
+     */
+    T = p_eq_g ? grp->T : NULL;
+
+    if( T == NULL )
+    {
+        T = (ecp_point *) polarssl_malloc( pre_len * sizeof( ecp_point ) );
+        if( T == NULL )
+        {
+            ret = POLARSSL_ERR_ECP_MALLOC_FAILED;
+            goto cleanup;
+        }
+
+        for( i = 0; i < pre_len; i++ )
+            ecp_point_init( &T[i] );
+
+        MPI_CHK( ecp_precompute_comb( grp, T, P, w, d ) );
+
+        if( p_eq_g )
+        {
+            grp->T = T;
+            grp->T_size = pre_len;
+        }
+    }
+
+    /*
+     * Make sure M is odd (M = m or M = N - m, since N is odd)
+     * using the fact that m * P = - (N - m) * P
+     */
+    m_is_odd = ( mpi_get_bit( m, 0 ) == 1 );
+    MPI_CHK( mpi_copy( &M, m ) );
+    MPI_CHK( mpi_sub_mpi( &mm, &grp->N, m ) );
+    MPI_CHK( mpi_safe_cond_assign( &M, &mm, ! m_is_odd ) );
+
+    /*
+     * Go for comb multiplication, R = M * P
+     */
+    ecp_comb_fixed( k, d, w, &M );
+    MPI_CHK( ecp_mul_comb_core( grp, R, T, pre_len, k, d, f_rng, p_rng ) );
+
+    /*
+     * Now get m * P from M * P and normalize it
+     */
+    MPI_CHK( ecp_safe_invert_jac( grp, R, ! m_is_odd ) );
+    MPI_CHK( ecp_normalize_jac( grp, R ) );
+
+cleanup:
+
+    if( T != NULL && ! p_eq_g )
+    {
+        for( i = 0; i < pre_len; i++ )
+            ecp_point_free( &T[i] );
+        polarssl_free( T );
+    }
+
+    mpi_free( &M );
+    mpi_free( &mm );
+
+    if( ret != 0 )
+        ecp_point_free( R );
+
+    return( ret );
+}
+
+#endif /* POLARSSL_ECP_SHORT_WEIERSTRASS */
+
+#if defined(POLARSSL_ECP_MONTGOMERY)
+/*
+ * For Montgomery curves, we do all the internal arithmetic in projective
+ * coordinates. Import/export of points uses only the x coordinates, which is
+ * internaly represented as X / Z.
+ *
+ * For scalar multiplication, we'll use a Montgomery ladder.
+ */
+
+/*
+ * Normalize Montgomery x/z coordinates: X = X/Z, Z = 1
+ * Cost: 1M + 1I
+ */
+static int ecp_normalize_mxz( const ecp_group *grp, ecp_point *P )
+{
+    int ret;
+
+    MPI_CHK( mpi_inv_mod( &P->Z, &P->Z, &grp->P ) );
+    MPI_CHK( mpi_mul_mpi( &P->X, &P->X, &P->Z ) ); MOD_MUL( P->X );
+    MPI_CHK( mpi_lset( &P->Z, 1 ) );
+
+cleanup:
+    return( ret );
+}
+
+/*
+ * Randomize projective x/z coordinates:
+ * (X, Z) -> (l X, l Z) for random l
+ * This is sort of the reverse operation of ecp_normalize_mxz().
+ *
+ * This countermeasure was first suggested in [2].
+ * Cost: 2M
+ */
+static int ecp_randomize_mxz( const ecp_group *grp, ecp_point *P,
+                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+    int ret;
+    mpi l;
+    size_t p_size = (grp->pbits + 7) / 8;
+    int count = 0;
+
+    mpi_init( &l );
+
+    /* Generate l such that 1 < l < p */
+    do
+    {
+        mpi_fill_random( &l, p_size, f_rng, p_rng );
+
+        while( mpi_cmp_mpi( &l, &grp->P ) >= 0 )
+            MPI_CHK( mpi_shift_r( &l, 1 ) );
+
+        if( count++ > 10 )
+            return( POLARSSL_ERR_ECP_RANDOM_FAILED );
+    }
+    while( mpi_cmp_int( &l, 1 ) <= 0 );
+
+    MPI_CHK( mpi_mul_mpi( &P->X, &P->X, &l ) ); MOD_MUL( P->X );
+    MPI_CHK( mpi_mul_mpi( &P->Z, &P->Z, &l ) ); MOD_MUL( P->Z );
+
+cleanup:
+    mpi_free( &l );
+
+    return( ret );
+}
+
+/*
+ * Double-and-add: R = 2P, S = P + Q, with d = X(P - Q),
+ * for Montgomery curves in x/z coordinates.
+ *
+ * http://www.hyperelliptic.org/EFD/g1p/auto-code/montgom/xz/ladder/mladd-1987-m.op3
+ * with
+ * d =  X1
+ * P = (X2, Z2)
+ * Q = (X3, Z3)
+ * R = (X4, Z4)
+ * S = (X5, Z5)
+ * and eliminating temporary variables tO, ..., t4.
+ *
+ * Cost: 5M + 4S
+ */
+static int ecp_double_add_mxz( const ecp_group *grp,
+                               ecp_point *R, ecp_point *S,
+                               const ecp_point *P, const ecp_point *Q,
+                               const mpi *d )
+{
+    int ret;
+    mpi A, AA, B, BB, E, C, D, DA, CB;
+
+    mpi_init( &A ); mpi_init( &AA ); mpi_init( &B );
+    mpi_init( &BB ); mpi_init( &E ); mpi_init( &C );
+    mpi_init( &D ); mpi_init( &DA ); mpi_init( &CB );
+
+    MPI_CHK( mpi_add_mpi( &A,    &P->X,   &P->Z ) ); MOD_ADD( A    );
+    MPI_CHK( mpi_mul_mpi( &AA,   &A,      &A    ) ); MOD_MUL( AA   );
+    MPI_CHK( mpi_sub_mpi( &B,    &P->X,   &P->Z ) ); MOD_SUB( B    );
+    MPI_CHK( mpi_mul_mpi( &BB,   &B,      &B    ) ); MOD_MUL( BB   );
+    MPI_CHK( mpi_sub_mpi( &E,    &AA,     &BB   ) ); MOD_SUB( E    );
+    MPI_CHK( mpi_add_mpi( &C,    &Q->X,   &Q->Z ) ); MOD_ADD( C    );
+    MPI_CHK( mpi_sub_mpi( &D,    &Q->X,   &Q->Z ) ); MOD_SUB( D    );
+    MPI_CHK( mpi_mul_mpi( &DA,   &D,      &A    ) ); MOD_MUL( DA   );
+    MPI_CHK( mpi_mul_mpi( &CB,   &C,      &B    ) ); MOD_MUL( CB   );
+    MPI_CHK( mpi_add_mpi( &S->X, &DA,     &CB   ) ); MOD_MUL( S->X );
+    MPI_CHK( mpi_mul_mpi( &S->X, &S->X,   &S->X ) ); MOD_MUL( S->X );
+    MPI_CHK( mpi_sub_mpi( &S->Z, &DA,     &CB   ) ); MOD_SUB( S->Z );
+    MPI_CHK( mpi_mul_mpi( &S->Z, &S->Z,   &S->Z ) ); MOD_MUL( S->Z );
+    MPI_CHK( mpi_mul_mpi( &S->Z, d,       &S->Z ) ); MOD_MUL( S->Z );
+    MPI_CHK( mpi_mul_mpi( &R->X, &AA,     &BB   ) ); MOD_MUL( R->X );
+    MPI_CHK( mpi_mul_mpi( &R->Z, &grp->A, &E    ) ); MOD_MUL( R->Z );
+    MPI_CHK( mpi_add_mpi( &R->Z, &BB,     &R->Z ) ); MOD_ADD( R->Z );
+    MPI_CHK( mpi_mul_mpi( &R->Z, &E,      &R->Z ) ); MOD_MUL( R->Z );
+
+cleanup:
+    mpi_free( &A ); mpi_free( &AA ); mpi_free( &B );
+    mpi_free( &BB ); mpi_free( &E ); mpi_free( &C );
+    mpi_free( &D ); mpi_free( &DA ); mpi_free( &CB );
+
+    return( ret );
+}
+
+/*
+ * Multiplication with Montgomery ladder in x/z coordinates,
+ * for curves in Montgomery form
+ */
+static int ecp_mul_mxz( ecp_group *grp, ecp_point *R,
+                        const mpi *m, const ecp_point *P,
+                        int (*f_rng)(void *, unsigned char *, size_t),
+                        void *p_rng )
+{
+    int ret;
+    size_t i;
+    unsigned char b;
+    ecp_point RP;
+    mpi PX;
+
+    ecp_point_init( &RP ); mpi_init( &PX );
+
+    /* Save PX and read from P before writing to R, in case P == R */
+    MPI_CHK( mpi_copy( &PX, &P->X ) );
+    MPI_CHK( ecp_copy( &RP, P ) );
+
+    /* Set R to zero in modified x/z coordinates */
+    MPI_CHK( mpi_lset( &R->X, 1 ) );
+    MPI_CHK( mpi_lset( &R->Z, 0 ) );
+    mpi_free( &R->Y );
+
+    /* RP.X might be sligtly larger than P, so reduce it */
+    MOD_ADD( RP.X );
+
+    /* Randomize coordinates of the starting point */
+    if( f_rng != NULL )
+        MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) );
+
+    /* Loop invariant: R = result so far, RP = R + P */
+    i = mpi_msb( m ); /* one past the (zero-based) most significant bit */
+    while( i-- > 0 )
+    {
+        b = mpi_get_bit( m, i );
+        /*
+         *  if (b) R = 2R + P else R = 2R,
+         * which is:
+         *  if (b) double_add( RP, R, RP, R )
+         *  else   double_add( R, RP, R, RP )
+         * but using safe conditional swaps to avoid leaks
+         */
+        MPI_CHK( mpi_safe_cond_swap( &R->X, &RP.X, b ) );
+        MPI_CHK( mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
+        MPI_CHK( ecp_double_add_mxz( grp, R, &RP, R, &RP, &PX ) );
+        MPI_CHK( mpi_safe_cond_swap( &R->X, &RP.X, b ) );
+        MPI_CHK( mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
+    }
+
+    MPI_CHK( ecp_normalize_mxz( grp, R ) );
+
+cleanup:
+    ecp_point_free( &RP ); mpi_free( &PX );
+
+    return( ret );
+}
+
+#endif /* POLARSSL_ECP_MONTGOMERY */
+
+/*
+ * Multiplication R = m * P
+ */
+int ecp_mul( ecp_group *grp, ecp_point *R,
+             const mpi *m, const ecp_point *P,
+             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+    int ret;
+
+    /* Common sanity checks */
+    if( mpi_cmp_int( &P->Z, 1 ) != 0 )
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+
+    if( ( ret = ecp_check_privkey( grp, m ) ) != 0 ||
+        ( ret = ecp_check_pubkey( grp, P ) ) != 0 )
+        return( ret );
+
+#if defined(POLARSSL_ECP_MONTGOMERY)
+    if( ecp_get_type( grp ) == POLARSSL_ECP_TYPE_MONTGOMERY )
+        return( ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ) );
+#endif
+#if defined(POLARSSL_ECP_SHORT_WEIERSTRASS)
+    if( ecp_get_type( grp ) == POLARSSL_ECP_TYPE_SHORT_WEIERSTRASS )
+        return( ecp_mul_comb( grp, R, m, P, f_rng, p_rng ) );
+#endif
+    return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+}
+
+#if defined(POLARSSL_ECP_SHORT_WEIERSTRASS)
+/*
+ * Check that an affine point is valid as a public key,
+ * short weierstrass curves (SEC1 3.2.3.1)
+ */
+static int ecp_check_pubkey_sw( const ecp_group *grp, const ecp_point *pt )
+{
+    int ret;
+    mpi YY, RHS;
+
+    /* pt coordinates must be normalized for our checks */
+    if( mpi_cmp_int( &pt->X, 0 ) < 0 ||
+        mpi_cmp_int( &pt->Y, 0 ) < 0 ||
+        mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 ||
+        mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 )
+        return( POLARSSL_ERR_ECP_INVALID_KEY );
+
+    mpi_init( &YY ); mpi_init( &RHS );
+
+    /*
+     * YY = Y^2
+     * RHS = X (X^2 + A) + B = X^3 + A X + B
+     */
+    MPI_CHK( mpi_mul_mpi( &YY,  &pt->Y,   &pt->Y  ) );  MOD_MUL( YY  );
+    MPI_CHK( mpi_mul_mpi( &RHS, &pt->X,   &pt->X  ) );  MOD_MUL( RHS );
+
+    /* Special case for A = -3 */
+    if( grp->A.p == NULL )
+    {
+        MPI_CHK( mpi_sub_int( &RHS, &RHS, 3       ) );  MOD_SUB( RHS );
+    }
+    else
+    {
+        MPI_CHK( mpi_add_mpi( &RHS, &RHS, &grp->A ) );  MOD_ADD( RHS );
+    }
+
+    MPI_CHK( mpi_mul_mpi( &RHS, &RHS,     &pt->X  ) );  MOD_MUL( RHS );
+    MPI_CHK( mpi_add_mpi( &RHS, &RHS,     &grp->B ) );  MOD_ADD( RHS );
+
+    if( mpi_cmp_mpi( &YY, &RHS ) != 0 )
+        ret = POLARSSL_ERR_ECP_INVALID_KEY;
+
+cleanup:
+
+    mpi_free( &YY ); mpi_free( &RHS );
+
+    return( ret );
+}
+#endif /* POLARSSL_ECP_SHORT_WEIERSTRASS */
+
+
+#if defined(POLARSSL_ECP_MONTGOMERY)
+/*
+ * Check validity of a public key for Montgomery curves with x-only schemes
+ */
+static int ecp_check_pubkey_mx( const ecp_group *grp, const ecp_point *pt )
+{
+    /* [M255 p. 5] Just check X is the correct number of bytes */
+    if( mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 )
+        return( POLARSSL_ERR_ECP_INVALID_KEY );
+
+    return( 0 );
+}
+#endif /* POLARSSL_ECP_MONTGOMERY */
+
+/*
+ * Check that a point is valid as a public key
+ */
+int ecp_check_pubkey( const ecp_group *grp, const ecp_point *pt )
+{
+    /* Must use affine coordinates */
+    if( mpi_cmp_int( &pt->Z, 1 ) != 0 )
+        return( POLARSSL_ERR_ECP_INVALID_KEY );
+
+#if defined(POLARSSL_ECP_MONTGOMERY)
+    if( ecp_get_type( grp ) == POLARSSL_ECP_TYPE_MONTGOMERY )
+        return( ecp_check_pubkey_mx( grp, pt ) );
+#endif
+#if defined(POLARSSL_ECP_SHORT_WEIERSTRASS)
+    if( ecp_get_type( grp ) == POLARSSL_ECP_TYPE_SHORT_WEIERSTRASS )
+        return( ecp_check_pubkey_sw( grp, pt ) );
+#endif
+    return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+}
+
+/*
+ * Check that an mpi is valid as a private key
+ */
+int ecp_check_privkey( const ecp_group *grp, const mpi *d )
+{
+#if defined(POLARSSL_ECP_MONTGOMERY)
+    if( ecp_get_type( grp ) == POLARSSL_ECP_TYPE_MONTGOMERY )
+    {
+        /* see [M255] page 5 */
+        if( mpi_get_bit( d, 0 ) != 0 ||
+            mpi_get_bit( d, 1 ) != 0 ||
+            mpi_get_bit( d, 2 ) != 0 ||
+            mpi_msb( d ) - 1 != grp->nbits ) /* mpi_msb is one-based! */
+            return( POLARSSL_ERR_ECP_INVALID_KEY );
+        else
+            return( 0 );
+    }
+#endif /* POLARSSL_ECP_MONTGOMERY */
+#if defined(POLARSSL_ECP_SHORT_WEIERSTRASS)
+    if( ecp_get_type( grp ) == POLARSSL_ECP_TYPE_SHORT_WEIERSTRASS )
+    {
+        /* see SEC1 3.2 */
+        if( mpi_cmp_int( d, 1 ) < 0 ||
+            mpi_cmp_mpi( d, &grp->N ) >= 0 )
+            return( POLARSSL_ERR_ECP_INVALID_KEY );
+        else
+            return( 0 );
+    }
+#endif /* POLARSSL_ECP_SHORT_WEIERSTRASS */
+
+    return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+}
+
+/*
+ * Generate a keypair
+ */
+int ecp_gen_keypair( ecp_group *grp, mpi *d, ecp_point *Q,
+                     int (*f_rng)(void *, unsigned char *, size_t),
+                     void *p_rng )
+{
+    int ret;
+    size_t n_size = (grp->nbits + 7) / 8;
+
+#if defined(POLARSSL_ECP_MONTGOMERY)
+    if( ecp_get_type( grp ) == POLARSSL_ECP_TYPE_MONTGOMERY )
+    {
+        /* [M225] page 5 */
+        size_t b;
+
+        MPI_CHK( mpi_fill_random( d, n_size, f_rng, p_rng ) );
+
+        /* Make sure the most significant bit is nbits */
+        b = mpi_msb( d ) - 1; /* mpi_msb is one-based */
+        if( b > grp->nbits )
+            MPI_CHK( mpi_shift_r( d, b - grp->nbits ) );
+        else
+            MPI_CHK( mpi_set_bit( d, grp->nbits, 1 ) );
+
+        /* Make sure the last three bits are unset */
+        MPI_CHK( mpi_set_bit( d, 0, 0 ) );
+        MPI_CHK( mpi_set_bit( d, 1, 0 ) );
+        MPI_CHK( mpi_set_bit( d, 2, 0 ) );
+    }
+    else
+#endif /* POLARSSL_ECP_MONTGOMERY */
+#if defined(POLARSSL_ECP_SHORT_WEIERSTRASS)
+    if( ecp_get_type( grp ) == POLARSSL_ECP_TYPE_SHORT_WEIERSTRASS )
+    {
+        /* SEC1 3.2.1: Generate d such that 1 <= n < N */
+        int count = 0;
+        unsigned char rnd[POLARSSL_ECP_MAX_BYTES];
+
+        /*
+         * Match the procedure given in RFC 6979 (deterministic ECDSA):
+         * - use the same byte ordering;
+         * - keep the leftmost nbits bits of the generated octet string;
+         * - try until result is in the desired range.
+         * This also avoids any biais, which is especially important for ECDSA.
+         */
+        do
+        {
+            MPI_CHK( f_rng( p_rng, rnd, n_size ) );
+            MPI_CHK( mpi_read_binary( d, rnd, n_size ) );
+            MPI_CHK( mpi_shift_r( d, 8 * n_size - grp->nbits ) );
+
+            /*
+             * Each try has at worst a probability 1/2 of failing (the msb has
+             * a probability 1/2 of being 0, and then the result will be < N),
+             * so after 30 tries failure probability is a most 2**(-30).
+             *
+             * For most curves, 1 try is enough with overwhelming probability,
+             * since N starts with a lot of 1s in binary, but some curves
+             * such as secp224k1 are actually very close to the worst case.
+             */
+            if( ++count > 30 )
+                return( POLARSSL_ERR_ECP_RANDOM_FAILED );
+        }
+        while( mpi_cmp_int( d, 1 ) < 0 ||
+               mpi_cmp_mpi( d, &grp->N ) >= 0 );
+    }
+    else
+#endif /* POLARSSL_ECP_SHORT_WEIERSTRASS */
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+
+cleanup:
+    if( ret != 0 )
+        return( ret );
+
+    return( ecp_mul( grp, Q, d, &grp->G, f_rng, p_rng ) );
+}
+
+/*
+ * Generate a keypair, prettier wrapper
+ */
+int ecp_gen_key( ecp_group_id grp_id, ecp_keypair *key,
+                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+    int ret;
+
+    if( ( ret = ecp_use_known_dp( &key->grp, grp_id ) ) != 0 )
+        return( ret );
+
+    return( ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+/*
+ * Checkup routine
+ */
+int ecp_self_test( int verbose )
+{
+    int ret;
+    size_t i;
+    ecp_group grp;
+    ecp_point R, P;
+    mpi m;
+    unsigned long add_c_prev, dbl_c_prev, mul_c_prev;
+    /* exponents especially adapted for secp192r1 */
+    const char *exponents[] =
+    {
+        "000000000000000000000000000000000000000000000001", /* one */
+        "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830", /* N - 1 */
+        "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */
+        "400000000000000000000000000000000000000000000000", /* one and zeros */
+        "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* all ones */
+        "555555555555555555555555555555555555555555555555", /* 101010... */
+    };
+
+    ecp_group_init( &grp );
+    ecp_point_init( &R );
+    ecp_point_init( &P );
+    mpi_init( &m );
+
+    /* Use secp192r1 if available, or any available curve */
+#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED)
+    MPI_CHK( ecp_use_known_dp( &grp, POLARSSL_ECP_DP_SECP192R1 ) );
+#else
+    MPI_CHK( ecp_use_known_dp( &grp, ecp_curve_list()->grp_id ) );
+#endif
+
+    if( verbose != 0 )
+        polarssl_printf( "  ECP test #1 (constant op_count, base point G): " );
+
+    /* Do a dummy multiplication first to trigger precomputation */
+    MPI_CHK( mpi_lset( &m, 2 ) );
+    MPI_CHK( ecp_mul( &grp, &P, &m, &grp.G, NULL, NULL ) );
+
+    add_count = 0;
+    dbl_count = 0;
+    mul_count = 0;
+    MPI_CHK( mpi_read_string( &m, 16, exponents[0] ) );
+    MPI_CHK( ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
+
+    for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
+    {
+        add_c_prev = add_count;
+        dbl_c_prev = dbl_count;
+        mul_c_prev = mul_count;
+        add_count = 0;
+        dbl_count = 0;
+        mul_count = 0;
+
+        MPI_CHK( mpi_read_string( &m, 16, exponents[i] ) );
+        MPI_CHK( ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
+
+        if( add_count != add_c_prev ||
+            dbl_count != dbl_c_prev ||
+            mul_count != mul_c_prev )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed (%u)\n", (unsigned int) i );
+
+            ret = 1;
+            goto cleanup;
+        }
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n" );
+
+    if( verbose != 0 )
+        polarssl_printf( "  ECP test #2 (constant op_count, other point): " );
+    /* We computed P = 2G last time, use it */
+
+    add_count = 0;
+    dbl_count = 0;
+    mul_count = 0;
+    MPI_CHK( mpi_read_string( &m, 16, exponents[0] ) );
+    MPI_CHK( ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
+
+    for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
+    {
+        add_c_prev = add_count;
+        dbl_c_prev = dbl_count;
+        mul_c_prev = mul_count;
+        add_count = 0;
+        dbl_count = 0;
+        mul_count = 0;
+
+        MPI_CHK( mpi_read_string( &m, 16, exponents[i] ) );
+        MPI_CHK( ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
+
+        if( add_count != add_c_prev ||
+            dbl_count != dbl_c_prev ||
+            mul_count != mul_c_prev )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed (%u)\n", (unsigned int) i );
+
+            ret = 1;
+            goto cleanup;
+        }
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n" );
+
+cleanup:
+
+    if( ret < 0 && verbose != 0 )
+        polarssl_printf( "Unexpected error, return code = %08X\n", ret );
+
+    ecp_group_free( &grp );
+    ecp_point_free( &R );
+    ecp_point_free( &P );
+    mpi_free( &m );
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+    return( ret );
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_ECP_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/ecp_curves.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,1382 @@
+/*
+ *  Elliptic curves over GF(p): curve-specific data and functions
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_ECP_C)
+
+#include "polarssl/ecp.h"
+
+#if defined(_MSC_VER) && !defined(inline)
+#define inline _inline
+#else
+#if defined(__ARMCC_VERSION) && !defined(inline)
+#define inline __inline
+#endif /* __ARMCC_VERSION */
+#endif /*_MSC_VER */
+
+/*
+ * Conversion macros for embedded constants:
+ * build lists of t_uint's from lists of unsigned char's grouped by 8, 4 or 2
+ */
+#if defined(POLARSSL_HAVE_INT8)
+
+#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \
+    a, b, c, d, e, f, g, h
+
+#define BYTES_TO_T_UINT_4( a, b, c, d )             \
+    a, b, c, d
+
+#define BYTES_TO_T_UINT_2( a, b )                   \
+    a, b
+
+#elif defined(POLARSSL_HAVE_INT16)
+
+#define BYTES_TO_T_UINT_2( a, b )                   \
+    ( (t_uint) a << 0 ) |                           \
+    ( (t_uint) b << 8 )
+
+#define BYTES_TO_T_UINT_4( a, b, c, d )             \
+    BYTES_TO_T_UINT_2( a, b ),                      \
+    BYTES_TO_T_UINT_2( c, d )
+
+#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \
+    BYTES_TO_T_UINT_2( a, b ),                      \
+    BYTES_TO_T_UINT_2( c, d ),                      \
+    BYTES_TO_T_UINT_2( e, f ),                      \
+    BYTES_TO_T_UINT_2( g, h )
+
+#elif defined(POLARSSL_HAVE_INT32)
+
+#define BYTES_TO_T_UINT_4( a, b, c, d )             \
+    ( (t_uint) a <<  0 ) |                          \
+    ( (t_uint) b <<  8 ) |                          \
+    ( (t_uint) c << 16 ) |                          \
+    ( (t_uint) d << 24 )
+
+#define BYTES_TO_T_UINT_2( a, b )                   \
+    BYTES_TO_T_UINT_4( a, b, 0, 0 )
+
+#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \
+    BYTES_TO_T_UINT_4( a, b, c, d ),                \
+    BYTES_TO_T_UINT_4( e, f, g, h )
+
+#else /* 64-bits */
+
+#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \
+    ( (t_uint) a <<  0 ) |                          \
+    ( (t_uint) b <<  8 ) |                          \
+    ( (t_uint) c << 16 ) |                          \
+    ( (t_uint) d << 24 ) |                          \
+    ( (t_uint) e << 32 ) |                          \
+    ( (t_uint) f << 40 ) |                          \
+    ( (t_uint) g << 48 ) |                          \
+    ( (t_uint) h << 56 )
+
+#define BYTES_TO_T_UINT_4( a, b, c, d )             \
+    BYTES_TO_T_UINT_8( a, b, c, d, 0, 0, 0, 0 )
+
+#define BYTES_TO_T_UINT_2( a, b )                   \
+    BYTES_TO_T_UINT_8( a, b, 0, 0, 0, 0, 0, 0 )
+
+#endif /* bits in t_uint */
+
+/*
+ * Note: the constants are in little-endian order
+ * to be directly usable in MPIs
+ */
+
+/*
+ * Domain parameters for secp192r1
+ */
+#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED)
+static const t_uint secp192r1_p[] = {
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+static const t_uint secp192r1_b[] = {
+    BYTES_TO_T_UINT_8( 0xB1, 0xB9, 0x46, 0xC1, 0xEC, 0xDE, 0xB8, 0xFE ),
+    BYTES_TO_T_UINT_8( 0x49, 0x30, 0x24, 0x72, 0xAB, 0xE9, 0xA7, 0x0F ),
+    BYTES_TO_T_UINT_8( 0xE7, 0x80, 0x9C, 0xE5, 0x19, 0x05, 0x21, 0x64 ),
+};
+static const t_uint secp192r1_gx[] = {
+    BYTES_TO_T_UINT_8( 0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4 ),
+    BYTES_TO_T_UINT_8( 0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C ),
+    BYTES_TO_T_UINT_8( 0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18 ),
+};
+static const t_uint secp192r1_gy[] = {
+    BYTES_TO_T_UINT_8( 0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73 ),
+    BYTES_TO_T_UINT_8( 0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63 ),
+    BYTES_TO_T_UINT_8( 0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07 ),
+};
+static const t_uint secp192r1_n[] = {
+    BYTES_TO_T_UINT_8( 0x31, 0x28, 0xD2, 0xB4, 0xB1, 0xC9, 0x6B, 0x14 ),
+    BYTES_TO_T_UINT_8( 0x36, 0xF8, 0xDE, 0x99, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+#endif /* POLARSSL_ECP_DP_SECP192R1_ENABLED */
+
+/*
+ * Domain parameters for secp224r1
+ */
+#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED)
+static const t_uint secp224r1_p[] = {
+    BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ),
+    BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ),
+};
+static const t_uint secp224r1_b[] = {
+    BYTES_TO_T_UINT_8( 0xB4, 0xFF, 0x55, 0x23, 0x43, 0x39, 0x0B, 0x27 ),
+    BYTES_TO_T_UINT_8( 0xBA, 0xD8, 0xBF, 0xD7, 0xB7, 0xB0, 0x44, 0x50 ),
+    BYTES_TO_T_UINT_8( 0x56, 0x32, 0x41, 0xF5, 0xAB, 0xB3, 0x04, 0x0C ),
+    BYTES_TO_T_UINT_4( 0x85, 0x0A, 0x05, 0xB4 ),
+};
+static const t_uint secp224r1_gx[] = {
+    BYTES_TO_T_UINT_8( 0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34 ),
+    BYTES_TO_T_UINT_8( 0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A ),
+    BYTES_TO_T_UINT_8( 0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B ),
+    BYTES_TO_T_UINT_4( 0xBD, 0x0C, 0x0E, 0xB7 ),
+};
+static const t_uint secp224r1_gy[] = {
+    BYTES_TO_T_UINT_8( 0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44 ),
+    BYTES_TO_T_UINT_8( 0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD ),
+    BYTES_TO_T_UINT_8( 0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5 ),
+    BYTES_TO_T_UINT_4( 0x88, 0x63, 0x37, 0xBD ),
+};
+static const t_uint secp224r1_n[] = {
+    BYTES_TO_T_UINT_8( 0x3D, 0x2A, 0x5C, 0x5C, 0x45, 0x29, 0xDD, 0x13 ),
+    BYTES_TO_T_UINT_8( 0x3E, 0xF0, 0xB8, 0xE0, 0xA2, 0x16, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+#endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED */
+
+/*
+ * Domain parameters for secp256r1
+ */
+#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED)
+static const t_uint secp256r1_p[] = {
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ),
+    BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ),
+    BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+static const t_uint secp256r1_b[] = {
+    BYTES_TO_T_UINT_8( 0x4B, 0x60, 0xD2, 0x27, 0x3E, 0x3C, 0xCE, 0x3B ),
+    BYTES_TO_T_UINT_8( 0xF6, 0xB0, 0x53, 0xCC, 0xB0, 0x06, 0x1D, 0x65 ),
+    BYTES_TO_T_UINT_8( 0xBC, 0x86, 0x98, 0x76, 0x55, 0xBD, 0xEB, 0xB3 ),
+    BYTES_TO_T_UINT_8( 0xE7, 0x93, 0x3A, 0xAA, 0xD8, 0x35, 0xC6, 0x5A ),
+};
+static const t_uint secp256r1_gx[] = {
+    BYTES_TO_T_UINT_8( 0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4 ),
+    BYTES_TO_T_UINT_8( 0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77 ),
+    BYTES_TO_T_UINT_8( 0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8 ),
+    BYTES_TO_T_UINT_8( 0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B ),
+};
+static const t_uint secp256r1_gy[] = {
+    BYTES_TO_T_UINT_8( 0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB ),
+    BYTES_TO_T_UINT_8( 0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B ),
+    BYTES_TO_T_UINT_8( 0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E ),
+    BYTES_TO_T_UINT_8( 0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F ),
+};
+static const t_uint secp256r1_n[] = {
+    BYTES_TO_T_UINT_8( 0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3 ),
+    BYTES_TO_T_UINT_8( 0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+#endif /* POLARSSL_ECP_DP_SECP256R1_ENABLED */
+
+/*
+ * Domain parameters for secp384r1
+ */
+#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED)
+static const t_uint secp384r1_p[] = {
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ),
+    BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+static const t_uint secp384r1_b[] = {
+    BYTES_TO_T_UINT_8( 0xEF, 0x2A, 0xEC, 0xD3, 0xED, 0xC8, 0x85, 0x2A ),
+    BYTES_TO_T_UINT_8( 0x9D, 0xD1, 0x2E, 0x8A, 0x8D, 0x39, 0x56, 0xC6 ),
+    BYTES_TO_T_UINT_8( 0x5A, 0x87, 0x13, 0x50, 0x8F, 0x08, 0x14, 0x03 ),
+    BYTES_TO_T_UINT_8( 0x12, 0x41, 0x81, 0xFE, 0x6E, 0x9C, 0x1D, 0x18 ),
+    BYTES_TO_T_UINT_8( 0x19, 0x2D, 0xF8, 0xE3, 0x6B, 0x05, 0x8E, 0x98 ),
+    BYTES_TO_T_UINT_8( 0xE4, 0xE7, 0x3E, 0xE2, 0xA7, 0x2F, 0x31, 0xB3 ),
+};
+static const t_uint secp384r1_gx[] = {
+    BYTES_TO_T_UINT_8( 0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A ),
+    BYTES_TO_T_UINT_8( 0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55 ),
+    BYTES_TO_T_UINT_8( 0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59 ),
+    BYTES_TO_T_UINT_8( 0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E ),
+    BYTES_TO_T_UINT_8( 0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E ),
+    BYTES_TO_T_UINT_8( 0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA ),
+};
+static const t_uint secp384r1_gy[] = {
+    BYTES_TO_T_UINT_8( 0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A ),
+    BYTES_TO_T_UINT_8( 0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A ),
+    BYTES_TO_T_UINT_8( 0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9 ),
+    BYTES_TO_T_UINT_8( 0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8 ),
+    BYTES_TO_T_UINT_8( 0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D ),
+    BYTES_TO_T_UINT_8( 0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36 ),
+};
+static const t_uint secp384r1_n[] = {
+    BYTES_TO_T_UINT_8( 0x73, 0x29, 0xC5, 0xCC, 0x6A, 0x19, 0xEC, 0xEC ),
+    BYTES_TO_T_UINT_8( 0x7A, 0xA7, 0xB0, 0x48, 0xB2, 0x0D, 0x1A, 0x58 ),
+    BYTES_TO_T_UINT_8( 0xDF, 0x2D, 0x37, 0xF4, 0x81, 0x4D, 0x63, 0xC7 ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+#endif /* POLARSSL_ECP_DP_SECP384R1_ENABLED */
+
+/*
+ * Domain parameters for secp521r1
+ */
+#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED)
+static const t_uint secp521r1_p[] = {
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_2( 0xFF, 0x01 ),
+};
+static const t_uint secp521r1_b[] = {
+    BYTES_TO_T_UINT_8( 0x00, 0x3F, 0x50, 0x6B, 0xD4, 0x1F, 0x45, 0xEF ),
+    BYTES_TO_T_UINT_8( 0xF1, 0x34, 0x2C, 0x3D, 0x88, 0xDF, 0x73, 0x35 ),
+    BYTES_TO_T_UINT_8( 0x07, 0xBF, 0xB1, 0x3B, 0xBD, 0xC0, 0x52, 0x16 ),
+    BYTES_TO_T_UINT_8( 0x7B, 0x93, 0x7E, 0xEC, 0x51, 0x39, 0x19, 0x56 ),
+    BYTES_TO_T_UINT_8( 0xE1, 0x09, 0xF1, 0x8E, 0x91, 0x89, 0xB4, 0xB8 ),
+    BYTES_TO_T_UINT_8( 0xF3, 0x15, 0xB3, 0x99, 0x5B, 0x72, 0xDA, 0xA2 ),
+    BYTES_TO_T_UINT_8( 0xEE, 0x40, 0x85, 0xB6, 0xA0, 0x21, 0x9A, 0x92 ),
+    BYTES_TO_T_UINT_8( 0x1F, 0x9A, 0x1C, 0x8E, 0x61, 0xB9, 0x3E, 0x95 ),
+    BYTES_TO_T_UINT_2( 0x51, 0x00 ),
+};
+static const t_uint secp521r1_gx[] = {
+    BYTES_TO_T_UINT_8( 0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9 ),
+    BYTES_TO_T_UINT_8( 0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33 ),
+    BYTES_TO_T_UINT_8( 0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE ),
+    BYTES_TO_T_UINT_8( 0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1 ),
+    BYTES_TO_T_UINT_8( 0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8 ),
+    BYTES_TO_T_UINT_8( 0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C ),
+    BYTES_TO_T_UINT_8( 0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E ),
+    BYTES_TO_T_UINT_8( 0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85 ),
+    BYTES_TO_T_UINT_2( 0xC6, 0x00 ),
+};
+static const t_uint secp521r1_gy[] = {
+    BYTES_TO_T_UINT_8( 0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88 ),
+    BYTES_TO_T_UINT_8( 0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35 ),
+    BYTES_TO_T_UINT_8( 0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5 ),
+    BYTES_TO_T_UINT_8( 0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97 ),
+    BYTES_TO_T_UINT_8( 0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17 ),
+    BYTES_TO_T_UINT_8( 0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98 ),
+    BYTES_TO_T_UINT_8( 0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C ),
+    BYTES_TO_T_UINT_8( 0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39 ),
+    BYTES_TO_T_UINT_2( 0x18, 0x01 ),
+};
+static const t_uint secp521r1_n[] = {
+    BYTES_TO_T_UINT_8( 0x09, 0x64, 0x38, 0x91, 0x1E, 0xB7, 0x6F, 0xBB ),
+    BYTES_TO_T_UINT_8( 0xAE, 0x47, 0x9C, 0x89, 0xB8, 0xC9, 0xB5, 0x3B ),
+    BYTES_TO_T_UINT_8( 0xD0, 0xA5, 0x09, 0xF7, 0x48, 0x01, 0xCC, 0x7F ),
+    BYTES_TO_T_UINT_8( 0x6B, 0x96, 0x2F, 0xBF, 0x83, 0x87, 0x86, 0x51 ),
+    BYTES_TO_T_UINT_8( 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_2( 0xFF, 0x01 ),
+};
+#endif /* POLARSSL_ECP_DP_SECP521R1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_SECP192K1_ENABLED)
+static const t_uint secp192k1_p[] = {
+    BYTES_TO_T_UINT_8( 0x37, 0xEE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+static const t_uint secp192k1_a[] = {
+    BYTES_TO_T_UINT_2( 0x00, 0x00 ),
+};
+static const t_uint secp192k1_b[] = {
+    BYTES_TO_T_UINT_2( 0x03, 0x00 ),
+};
+static const t_uint secp192k1_gx[] = {
+    BYTES_TO_T_UINT_8( 0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D ),
+    BYTES_TO_T_UINT_8( 0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26 ),
+    BYTES_TO_T_UINT_8( 0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB ),
+};
+static const t_uint secp192k1_gy[] = {
+    BYTES_TO_T_UINT_8( 0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40 ),
+    BYTES_TO_T_UINT_8( 0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84 ),
+    BYTES_TO_T_UINT_8( 0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B ),
+};
+static const t_uint secp192k1_n[] = {
+    BYTES_TO_T_UINT_8( 0x8D, 0xFD, 0xDE, 0x74, 0x6A, 0x46, 0x69, 0x0F ),
+    BYTES_TO_T_UINT_8( 0x17, 0xFC, 0xF2, 0x26, 0xFE, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+#endif /* POLARSSL_ECP_DP_SECP192K1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_SECP224K1_ENABLED)
+static const t_uint secp224k1_p[] = {
+    BYTES_TO_T_UINT_8( 0x6D, 0xE5, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+static const t_uint secp224k1_a[] = {
+    BYTES_TO_T_UINT_2( 0x00, 0x00 ),
+};
+static const t_uint secp224k1_b[] = {
+    BYTES_TO_T_UINT_2( 0x05, 0x00 ),
+};
+static const t_uint secp224k1_gx[] = {
+    BYTES_TO_T_UINT_8( 0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F ),
+    BYTES_TO_T_UINT_8( 0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69 ),
+    BYTES_TO_T_UINT_8( 0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D ),
+    BYTES_TO_T_UINT_4( 0x33, 0x5B, 0x45, 0xA1 ),
+};
+static const t_uint secp224k1_gy[] = {
+    BYTES_TO_T_UINT_8( 0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2 ),
+    BYTES_TO_T_UINT_8( 0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7 ),
+    BYTES_TO_T_UINT_8( 0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F ),
+    BYTES_TO_T_UINT_4( 0xED, 0x9F, 0x08, 0x7E ),
+};
+static const t_uint secp224k1_n[] = {
+    BYTES_TO_T_UINT_8( 0xF7, 0xB1, 0x9F, 0x76, 0x71, 0xA9, 0xF0, 0xCA ),
+    BYTES_TO_T_UINT_8( 0x84, 0x61, 0xEC, 0xD2, 0xE8, 0xDC, 0x01, 0x00 ),
+    BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ),
+    BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ),
+};
+#endif /* POLARSSL_ECP_DP_SECP224K1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_SECP256K1_ENABLED)
+static const t_uint secp256k1_p[] = {
+    BYTES_TO_T_UINT_8( 0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+static const t_uint secp256k1_a[] = {
+    BYTES_TO_T_UINT_2( 0x00, 0x00 ),
+};
+static const t_uint secp256k1_b[] = {
+    BYTES_TO_T_UINT_2( 0x07, 0x00 ),
+};
+static const t_uint secp256k1_gx[] = {
+    BYTES_TO_T_UINT_8( 0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59 ),
+    BYTES_TO_T_UINT_8( 0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02 ),
+    BYTES_TO_T_UINT_8( 0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55 ),
+    BYTES_TO_T_UINT_8( 0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79 ),
+};
+static const t_uint secp256k1_gy[] = {
+    BYTES_TO_T_UINT_8( 0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C ),
+    BYTES_TO_T_UINT_8( 0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD ),
+    BYTES_TO_T_UINT_8( 0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D ),
+    BYTES_TO_T_UINT_8( 0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48 ),
+};
+static const t_uint secp256k1_n[] = {
+    BYTES_TO_T_UINT_8( 0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF ),
+    BYTES_TO_T_UINT_8( 0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA ),
+    BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+#endif /* POLARSSL_ECP_DP_SECP256K1_ENABLED */
+
+/*
+ * Domain parameters for brainpoolP256r1 (RFC 5639 3.4)
+ */
+#if defined(POLARSSL_ECP_DP_BP256R1_ENABLED)
+static const t_uint brainpoolP256r1_p[] = {
+    BYTES_TO_T_UINT_8( 0x77, 0x53, 0x6E, 0x1F, 0x1D, 0x48, 0x13, 0x20 ),
+    BYTES_TO_T_UINT_8( 0x28, 0x20, 0x26, 0xD5, 0x23, 0xF6, 0x3B, 0x6E ),
+    BYTES_TO_T_UINT_8( 0x72, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ),
+    BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ),
+};
+static const t_uint brainpoolP256r1_a[] = {
+    BYTES_TO_T_UINT_8( 0xD9, 0xB5, 0x30, 0xF3, 0x44, 0x4B, 0x4A, 0xE9 ),
+    BYTES_TO_T_UINT_8( 0x6C, 0x5C, 0xDC, 0x26, 0xC1, 0x55, 0x80, 0xFB ),
+    BYTES_TO_T_UINT_8( 0xE7, 0xFF, 0x7A, 0x41, 0x30, 0x75, 0xF6, 0xEE ),
+    BYTES_TO_T_UINT_8( 0x57, 0x30, 0x2C, 0xFC, 0x75, 0x09, 0x5A, 0x7D ),
+};
+static const t_uint brainpoolP256r1_b[] = {
+    BYTES_TO_T_UINT_8( 0xB6, 0x07, 0x8C, 0xFF, 0x18, 0xDC, 0xCC, 0x6B ),
+    BYTES_TO_T_UINT_8( 0xCE, 0xE1, 0xF7, 0x5C, 0x29, 0x16, 0x84, 0x95 ),
+    BYTES_TO_T_UINT_8( 0xBF, 0x7C, 0xD7, 0xBB, 0xD9, 0xB5, 0x30, 0xF3 ),
+    BYTES_TO_T_UINT_8( 0x44, 0x4B, 0x4A, 0xE9, 0x6C, 0x5C, 0xDC, 0x26 ),
+};
+static const t_uint brainpoolP256r1_gx[] = {
+    BYTES_TO_T_UINT_8( 0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A ),
+    BYTES_TO_T_UINT_8( 0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9 ),
+    BYTES_TO_T_UINT_8( 0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C ),
+    BYTES_TO_T_UINT_8( 0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B ),
+};
+static const t_uint brainpoolP256r1_gy[] = {
+    BYTES_TO_T_UINT_8( 0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C ),
+    BYTES_TO_T_UINT_8( 0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2 ),
+    BYTES_TO_T_UINT_8( 0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97 ),
+    BYTES_TO_T_UINT_8( 0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54 ),
+};
+static const t_uint brainpoolP256r1_n[] = {
+    BYTES_TO_T_UINT_8( 0xA7, 0x56, 0x48, 0x97, 0x82, 0x0E, 0x1E, 0x90 ),
+    BYTES_TO_T_UINT_8( 0xF7, 0xA6, 0x61, 0xB5, 0xA3, 0x7A, 0x39, 0x8C ),
+    BYTES_TO_T_UINT_8( 0x71, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ),
+    BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ),
+};
+#endif /* POLARSSL_ECP_DP_BP256R1_ENABLED */
+
+/*
+ * Domain parameters for brainpoolP384r1 (RFC 5639 3.6)
+ */
+#if defined(POLARSSL_ECP_DP_BP384R1_ENABLED)
+static const t_uint brainpoolP384r1_p[] = {
+    BYTES_TO_T_UINT_8( 0x53, 0xEC, 0x07, 0x31, 0x13, 0x00, 0x47, 0x87 ),
+    BYTES_TO_T_UINT_8( 0x71, 0x1A, 0x1D, 0x90, 0x29, 0xA7, 0xD3, 0xAC ),
+    BYTES_TO_T_UINT_8( 0x23, 0x11, 0xB7, 0x7F, 0x19, 0xDA, 0xB1, 0x12 ),
+    BYTES_TO_T_UINT_8( 0xB4, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ),
+    BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ),
+    BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ),
+};
+static const t_uint brainpoolP384r1_a[] = {
+    BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ),
+    BYTES_TO_T_UINT_8( 0xEB, 0xD4, 0x3A, 0x50, 0x4A, 0x81, 0xA5, 0x8A ),
+    BYTES_TO_T_UINT_8( 0x0F, 0xF9, 0x91, 0xBA, 0xEF, 0x65, 0x91, 0x13 ),
+    BYTES_TO_T_UINT_8( 0x87, 0x27, 0xB2, 0x4F, 0x8E, 0xA2, 0xBE, 0xC2 ),
+    BYTES_TO_T_UINT_8( 0xA0, 0xAF, 0x05, 0xCE, 0x0A, 0x08, 0x72, 0x3C ),
+    BYTES_TO_T_UINT_8( 0x0C, 0x15, 0x8C, 0x3D, 0xC6, 0x82, 0xC3, 0x7B ),
+};
+static const t_uint brainpoolP384r1_b[] = {
+    BYTES_TO_T_UINT_8( 0x11, 0x4C, 0x50, 0xFA, 0x96, 0x86, 0xB7, 0x3A ),
+    BYTES_TO_T_UINT_8( 0x94, 0xC9, 0xDB, 0x95, 0x02, 0x39, 0xB4, 0x7C ),
+    BYTES_TO_T_UINT_8( 0xD5, 0x62, 0xEB, 0x3E, 0xA5, 0x0E, 0x88, 0x2E ),
+    BYTES_TO_T_UINT_8( 0xA6, 0xD2, 0xDC, 0x07, 0xE1, 0x7D, 0xB7, 0x2F ),
+    BYTES_TO_T_UINT_8( 0x7C, 0x44, 0xF0, 0x16, 0x54, 0xB5, 0x39, 0x8B ),
+    BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ),
+};
+static const t_uint brainpoolP384r1_gx[] = {
+    BYTES_TO_T_UINT_8( 0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF ),
+    BYTES_TO_T_UINT_8( 0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8 ),
+    BYTES_TO_T_UINT_8( 0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB ),
+    BYTES_TO_T_UINT_8( 0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88 ),
+    BYTES_TO_T_UINT_8( 0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2 ),
+    BYTES_TO_T_UINT_8( 0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D ),
+};
+static const t_uint brainpoolP384r1_gy[] = {
+    BYTES_TO_T_UINT_8( 0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42 ),
+    BYTES_TO_T_UINT_8( 0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E ),
+    BYTES_TO_T_UINT_8( 0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1 ),
+    BYTES_TO_T_UINT_8( 0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62 ),
+    BYTES_TO_T_UINT_8( 0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C ),
+    BYTES_TO_T_UINT_8( 0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A ),
+};
+static const t_uint brainpoolP384r1_n[] = {
+    BYTES_TO_T_UINT_8( 0x65, 0x65, 0x04, 0xE9, 0x02, 0x32, 0x88, 0x3B ),
+    BYTES_TO_T_UINT_8( 0x10, 0xC3, 0x7F, 0x6B, 0xAF, 0xB6, 0x3A, 0xCF ),
+    BYTES_TO_T_UINT_8( 0xA7, 0x25, 0x04, 0xAC, 0x6C, 0x6E, 0x16, 0x1F ),
+    BYTES_TO_T_UINT_8( 0xB3, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ),
+    BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ),
+    BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ),
+};
+#endif /* POLARSSL_ECP_DP_BP384R1_ENABLED */
+
+/*
+ * Domain parameters for brainpoolP512r1 (RFC 5639 3.7)
+ */
+#if defined(POLARSSL_ECP_DP_BP512R1_ENABLED)
+static const t_uint brainpoolP512r1_p[] = {
+    BYTES_TO_T_UINT_8( 0xF3, 0x48, 0x3A, 0x58, 0x56, 0x60, 0xAA, 0x28 ),
+    BYTES_TO_T_UINT_8( 0x85, 0xC6, 0x82, 0x2D, 0x2F, 0xFF, 0x81, 0x28 ),
+    BYTES_TO_T_UINT_8( 0xE6, 0x80, 0xA3, 0xE6, 0x2A, 0xA1, 0xCD, 0xAE ),
+    BYTES_TO_T_UINT_8( 0x42, 0x68, 0xC6, 0x9B, 0x00, 0x9B, 0x4D, 0x7D ),
+    BYTES_TO_T_UINT_8( 0x71, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ),
+    BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ),
+    BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ),
+    BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ),
+};
+static const t_uint brainpoolP512r1_a[] = {
+    BYTES_TO_T_UINT_8( 0xCA, 0x94, 0xFC, 0x77, 0x4D, 0xAC, 0xC1, 0xE7 ),
+    BYTES_TO_T_UINT_8( 0xB9, 0xC7, 0xF2, 0x2B, 0xA7, 0x17, 0x11, 0x7F ),
+    BYTES_TO_T_UINT_8( 0xB5, 0xC8, 0x9A, 0x8B, 0xC9, 0xF1, 0x2E, 0x0A ),
+    BYTES_TO_T_UINT_8( 0xA1, 0x3A, 0x25, 0xA8, 0x5A, 0x5D, 0xED, 0x2D ),
+    BYTES_TO_T_UINT_8( 0xBC, 0x63, 0x98, 0xEA, 0xCA, 0x41, 0x34, 0xA8 ),
+    BYTES_TO_T_UINT_8( 0x10, 0x16, 0xF9, 0x3D, 0x8D, 0xDD, 0xCB, 0x94 ),
+    BYTES_TO_T_UINT_8( 0xC5, 0x4C, 0x23, 0xAC, 0x45, 0x71, 0x32, 0xE2 ),
+    BYTES_TO_T_UINT_8( 0x89, 0x3B, 0x60, 0x8B, 0x31, 0xA3, 0x30, 0x78 ),
+};
+static const t_uint brainpoolP512r1_b[] = {
+    BYTES_TO_T_UINT_8( 0x23, 0xF7, 0x16, 0x80, 0x63, 0xBD, 0x09, 0x28 ),
+    BYTES_TO_T_UINT_8( 0xDD, 0xE5, 0xBA, 0x5E, 0xB7, 0x50, 0x40, 0x98 ),
+    BYTES_TO_T_UINT_8( 0x67, 0x3E, 0x08, 0xDC, 0xCA, 0x94, 0xFC, 0x77 ),
+    BYTES_TO_T_UINT_8( 0x4D, 0xAC, 0xC1, 0xE7, 0xB9, 0xC7, 0xF2, 0x2B ),
+    BYTES_TO_T_UINT_8( 0xA7, 0x17, 0x11, 0x7F, 0xB5, 0xC8, 0x9A, 0x8B ),
+    BYTES_TO_T_UINT_8( 0xC9, 0xF1, 0x2E, 0x0A, 0xA1, 0x3A, 0x25, 0xA8 ),
+    BYTES_TO_T_UINT_8( 0x5A, 0x5D, 0xED, 0x2D, 0xBC, 0x63, 0x98, 0xEA ),
+    BYTES_TO_T_UINT_8( 0xCA, 0x41, 0x34, 0xA8, 0x10, 0x16, 0xF9, 0x3D ),
+};
+static const t_uint brainpoolP512r1_gx[] = {
+    BYTES_TO_T_UINT_8( 0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B ),
+    BYTES_TO_T_UINT_8( 0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C ),
+    BYTES_TO_T_UINT_8( 0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50 ),
+    BYTES_TO_T_UINT_8( 0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF ),
+    BYTES_TO_T_UINT_8( 0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4 ),
+    BYTES_TO_T_UINT_8( 0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85 ),
+    BYTES_TO_T_UINT_8( 0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A ),
+    BYTES_TO_T_UINT_8( 0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81 ),
+};
+static const t_uint brainpoolP512r1_gy[] = {
+    BYTES_TO_T_UINT_8( 0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78 ),
+    BYTES_TO_T_UINT_8( 0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1 ),
+    BYTES_TO_T_UINT_8( 0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B ),
+    BYTES_TO_T_UINT_8( 0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2 ),
+    BYTES_TO_T_UINT_8( 0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0 ),
+    BYTES_TO_T_UINT_8( 0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2 ),
+    BYTES_TO_T_UINT_8( 0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0 ),
+    BYTES_TO_T_UINT_8( 0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D ),
+};
+static const t_uint brainpoolP512r1_n[] = {
+    BYTES_TO_T_UINT_8( 0x69, 0x00, 0xA9, 0x9C, 0x82, 0x96, 0x87, 0xB5 ),
+    BYTES_TO_T_UINT_8( 0xDD, 0xDA, 0x5D, 0x08, 0x81, 0xD3, 0xB1, 0x1D ),
+    BYTES_TO_T_UINT_8( 0x47, 0x10, 0xAC, 0x7F, 0x19, 0x61, 0x86, 0x41 ),
+    BYTES_TO_T_UINT_8( 0x19, 0x26, 0xA9, 0x4C, 0x41, 0x5C, 0x3E, 0x55 ),
+    BYTES_TO_T_UINT_8( 0x70, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ),
+    BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ),
+    BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ),
+    BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ),
+};
+#endif /* POLARSSL_ECP_DP_BP512R1_ENABLED */
+
+/*
+ * Create an MPI from embedded constants
+ * (assumes len is an exact multiple of sizeof t_uint)
+ */
+static inline void ecp_mpi_load( mpi *X, const t_uint *p, size_t len )
+{
+    X->s = 1;
+    X->n = len / sizeof( t_uint );
+    X->p = (t_uint *) p;
+}
+
+/*
+ * Set an MPI to static value 1
+ */
+static inline void ecp_mpi_set1( mpi *X )
+{
+    static t_uint one[] = { 1 };
+    X->s = 1;
+    X->n = 1;
+    X->p = one;
+}
+
+/*
+ * Make group available from embedded constants
+ */
+static int ecp_group_load( ecp_group *grp,
+                           const t_uint *p,  size_t plen,
+                           const t_uint *a,  size_t alen,
+                           const t_uint *b,  size_t blen,
+                           const t_uint *gx, size_t gxlen,
+                           const t_uint *gy, size_t gylen,
+                           const t_uint *n,  size_t nlen)
+{
+    ecp_mpi_load( &grp->P, p, plen );
+    if( a != NULL )
+        ecp_mpi_load( &grp->A, a, alen );
+    ecp_mpi_load( &grp->B, b, blen );
+    ecp_mpi_load( &grp->N, n, nlen );
+
+    ecp_mpi_load( &grp->G.X, gx, gxlen );
+    ecp_mpi_load( &grp->G.Y, gy, gylen );
+    ecp_mpi_set1( &grp->G.Z );
+
+    grp->pbits = mpi_msb( &grp->P );
+    grp->nbits = mpi_msb( &grp->N );
+
+    grp->h = 1;
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_ECP_NIST_OPTIM)
+/* Forward declarations */
+#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED)
+static int ecp_mod_p192( mpi * );
+#endif
+#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED)
+static int ecp_mod_p224( mpi * );
+#endif
+#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED)
+static int ecp_mod_p256( mpi * );
+#endif
+#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED)
+static int ecp_mod_p384( mpi * );
+#endif
+#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED)
+static int ecp_mod_p521( mpi * );
+#endif
+
+#define NIST_MODP( P )      grp->modp = ecp_mod_ ## P;
+#else
+#define NIST_MODP( P )
+#endif /* POLARSSL_ECP_NIST_OPTIM */
+
+/* Additional forward declarations */
+#if defined(POLARSSL_ECP_DP_M255_ENABLED)
+static int ecp_mod_p255( mpi * );
+#endif
+#if defined(POLARSSL_ECP_DP_SECP192K1_ENABLED)
+static int ecp_mod_p192k1( mpi * );
+#endif
+#if defined(POLARSSL_ECP_DP_SECP224K1_ENABLED)
+static int ecp_mod_p224k1( mpi * );
+#endif
+#if defined(POLARSSL_ECP_DP_SECP256K1_ENABLED)
+static int ecp_mod_p256k1( mpi * );
+#endif
+
+#define LOAD_GROUP_A( G )   ecp_group_load( grp,            \
+                            G ## _p,  sizeof( G ## _p  ),   \
+                            G ## _a,  sizeof( G ## _a  ),   \
+                            G ## _b,  sizeof( G ## _b  ),   \
+                            G ## _gx, sizeof( G ## _gx ),   \
+                            G ## _gy, sizeof( G ## _gy ),   \
+                            G ## _n,  sizeof( G ## _n  ) )
+
+#define LOAD_GROUP( G )     ecp_group_load( grp,            \
+                            G ## _p,  sizeof( G ## _p  ),   \
+                            NULL,     0,                    \
+                            G ## _b,  sizeof( G ## _b  ),   \
+                            G ## _gx, sizeof( G ## _gx ),   \
+                            G ## _gy, sizeof( G ## _gy ),   \
+                            G ## _n,  sizeof( G ## _n  ) )
+
+#if defined(POLARSSL_ECP_DP_M255_ENABLED)
+/*
+ * Specialized function for creating the Curve25519 group
+ */
+static int ecp_use_curve25519( ecp_group *grp )
+{
+    int ret;
+
+    /* Actually ( A + 2 ) / 4 */
+    MPI_CHK( mpi_read_string( &grp->A, 16, "01DB42" ) );
+
+    /* P = 2^255 - 19 */
+    MPI_CHK( mpi_lset( &grp->P, 1 ) );
+    MPI_CHK( mpi_shift_l( &grp->P, 255 ) );
+    MPI_CHK( mpi_sub_int( &grp->P, &grp->P, 19 ) );
+    grp->pbits = mpi_msb( &grp->P );
+
+    /* Y intentionaly not set, since we use x/z coordinates.
+     * This is used as a marker to identify Montgomery curves! */
+    MPI_CHK( mpi_lset( &grp->G.X, 9 ) );
+    MPI_CHK( mpi_lset( &grp->G.Z, 1 ) );
+    mpi_free( &grp->G.Y );
+
+    /* Actually, the required msb for private keys */
+    grp->nbits = 254;
+
+cleanup:
+    if( ret != 0 )
+        ecp_group_free( grp );
+
+    return( ret );
+}
+#endif /* POLARSSL_ECP_DP_M255_ENABLED */
+
+/*
+ * Set a group using well-known domain parameters
+ */
+int ecp_use_known_dp( ecp_group *grp, ecp_group_id id )
+{
+    ecp_group_free( grp );
+
+    grp->id = id;
+
+    switch( id )
+    {
+#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED)
+        case POLARSSL_ECP_DP_SECP192R1:
+            NIST_MODP( p192 );
+            return( LOAD_GROUP( secp192r1 ) );
+#endif /* POLARSSL_ECP_DP_SECP192R1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED)
+        case POLARSSL_ECP_DP_SECP224R1:
+            NIST_MODP( p224 );
+            return( LOAD_GROUP( secp224r1 ) );
+#endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED)
+        case POLARSSL_ECP_DP_SECP256R1:
+            NIST_MODP( p256 );
+            return( LOAD_GROUP( secp256r1 ) );
+#endif /* POLARSSL_ECP_DP_SECP256R1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED)
+        case POLARSSL_ECP_DP_SECP384R1:
+            NIST_MODP( p384 );
+            return( LOAD_GROUP( secp384r1 ) );
+#endif /* POLARSSL_ECP_DP_SECP384R1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED)
+        case POLARSSL_ECP_DP_SECP521R1:
+            NIST_MODP( p521 );
+            return( LOAD_GROUP( secp521r1 ) );
+#endif /* POLARSSL_ECP_DP_SECP521R1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_SECP192K1_ENABLED)
+        case POLARSSL_ECP_DP_SECP192K1:
+            grp->modp = ecp_mod_p192k1;
+            return( LOAD_GROUP_A( secp192k1 ) );
+#endif /* POLARSSL_ECP_DP_SECP192K1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_SECP224K1_ENABLED)
+        case POLARSSL_ECP_DP_SECP224K1:
+            grp->modp = ecp_mod_p224k1;
+            return( LOAD_GROUP_A( secp224k1 ) );
+#endif /* POLARSSL_ECP_DP_SECP224K1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_SECP256K1_ENABLED)
+        case POLARSSL_ECP_DP_SECP256K1:
+            grp->modp = ecp_mod_p256k1;
+            return( LOAD_GROUP_A( secp256k1 ) );
+#endif /* POLARSSL_ECP_DP_SECP256K1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_BP256R1_ENABLED)
+        case POLARSSL_ECP_DP_BP256R1:
+            return( LOAD_GROUP_A( brainpoolP256r1 ) );
+#endif /* POLARSSL_ECP_DP_BP256R1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_BP384R1_ENABLED)
+        case POLARSSL_ECP_DP_BP384R1:
+            return( LOAD_GROUP_A( brainpoolP384r1 ) );
+#endif /* POLARSSL_ECP_DP_BP384R1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_BP512R1_ENABLED)
+        case POLARSSL_ECP_DP_BP512R1:
+            return( LOAD_GROUP_A( brainpoolP512r1 ) );
+#endif /* POLARSSL_ECP_DP_BP512R1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_M255_ENABLED)
+        case POLARSSL_ECP_DP_M255:
+            grp->modp = ecp_mod_p255;
+            return( ecp_use_curve25519( grp ) );
+#endif /* POLARSSL_ECP_DP_M255_ENABLED */
+
+        default:
+            ecp_group_free( grp );
+            return( POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE );
+    }
+}
+
+#if defined(POLARSSL_ECP_NIST_OPTIM)
+/*
+ * Fast reduction modulo the primes used by the NIST curves.
+ *
+ * These functions are critical for speed, but not needed for correct
+ * operations. So, we make the choice to heavily rely on the internals of our
+ * bignum library, which creates a tight coupling between these functions and
+ * our MPI implementation.  However, the coupling between the ECP module and
+ * MPI remains loose, since these functions can be deactivated at will.
+ */
+
+#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED)
+/*
+ * Compared to the way things are presented in FIPS 186-3 D.2,
+ * we proceed in columns, from right (least significant chunk) to left,
+ * adding chunks to N in place, and keeping a carry for the next chunk.
+ * This avoids moving things around in memory, and uselessly adding zeros,
+ * compared to the more straightforward, line-oriented approach.
+ *
+ * For this prime we need to handle data in chunks of 64 bits.
+ * Since this is always a multiple of our basic t_uint, we can
+ * use a t_uint * to designate such a chunk, and small loops to handle it.
+ */
+
+/* Add 64-bit chunks (dst += src) and update carry */
+static inline void add64( t_uint *dst, t_uint *src, t_uint *carry )
+{
+    unsigned char i;
+    t_uint c = 0;
+    for( i = 0; i < 8 / sizeof( t_uint ); i++, dst++, src++ )
+    {
+        *dst += c;      c  = ( *dst < c );
+        *dst += *src;   c += ( *dst < *src );
+    }
+    *carry += c;
+}
+
+/* Add carry to a 64-bit chunk and update carry */
+static inline void carry64( t_uint *dst, t_uint *carry )
+{
+    unsigned char i;
+    for( i = 0; i < 8 / sizeof( t_uint ); i++, dst++ )
+    {
+        *dst += *carry;
+        *carry  = ( *dst < *carry );
+    }
+}
+
+#define WIDTH       8 / sizeof( t_uint )
+#define A( i )      N->p + i * WIDTH
+#define ADD( i )    add64( p, A( i ), &c )
+#define NEXT        p += WIDTH; carry64( p, &c )
+#define LAST        p += WIDTH; *p = c; while( ++p < end ) *p = 0
+
+/*
+ * Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1)
+ */
+static int ecp_mod_p192( mpi *N )
+{
+    int ret;
+    t_uint c = 0;
+    t_uint *p, *end;
+
+    /* Make sure we have enough blocks so that A(5) is legal */
+    MPI_CHK( mpi_grow( N, 6 * WIDTH ) );
+
+    p = N->p;
+    end = p + N->n;
+
+    ADD( 3 ); ADD( 5 );             NEXT; // A0 += A3 + A5
+    ADD( 3 ); ADD( 4 ); ADD( 5 );   NEXT; // A1 += A3 + A4 + A5
+    ADD( 4 ); ADD( 5 );             LAST; // A2 += A4 + A5
+
+cleanup:
+    return( ret );
+}
+
+#undef WIDTH
+#undef A
+#undef ADD
+#undef NEXT
+#undef LAST
+#endif /* POLARSSL_ECP_DP_SECP192R1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED) ||   \
+    defined(POLARSSL_ECP_DP_SECP256R1_ENABLED) ||   \
+    defined(POLARSSL_ECP_DP_SECP384R1_ENABLED)
+/*
+ * The reader is advised to first understand ecp_mod_p192() since the same
+ * general structure is used here, but with additional complications:
+ * (1) chunks of 32 bits, and (2) subtractions.
+ */
+
+/*
+ * For these primes, we need to handle data in chunks of 32 bits.
+ * This makes it more complicated if we use 64 bits limbs in MPI,
+ * which prevents us from using a uniform access method as for p192.
+ *
+ * So, we define a mini abstraction layer to access 32 bit chunks,
+ * load them in 'cur' for work, and store them back from 'cur' when done.
+ *
+ * While at it, also define the size of N in terms of 32-bit chunks.
+ */
+#define LOAD32      cur = A( i );
+
+#if defined(POLARSSL_HAVE_INT8)     /* 8 bit */
+
+#define MAX32       N->n / 4
+#define A( j )      (uint32_t)( N->p[4*j+0]       ) |  \
+                              ( N->p[4*j+1] << 8  ) |  \
+                              ( N->p[4*j+2] << 16 ) |  \
+                              ( N->p[4*j+3] << 24 )
+#define STORE32     N->p[4*i+0] = (t_uint)( cur       );   \
+                    N->p[4*i+1] = (t_uint)( cur >> 8  );   \
+                    N->p[4*i+2] = (t_uint)( cur >> 16 );   \
+                    N->p[4*i+3] = (t_uint)( cur >> 24 );
+
+#elif defined(POLARSSL_HAVE_INT16)  /* 16 bit */
+
+#define MAX32       N->n / 2
+#define A( j )      (uint32_t)( N->p[2*j] ) | ( N->p[2*j+1] << 16 )
+#define STORE32     N->p[2*i+0] = (t_uint)( cur       );  \
+                    N->p[2*i+1] = (t_uint)( cur >> 16 );
+
+#elif defined(POLARSSL_HAVE_INT32)  /* 32 bit */
+
+#define MAX32       N->n
+#define A( j )      N->p[j]
+#define STORE32     N->p[i] = cur;
+
+#else                               /* 64-bit */
+
+#define MAX32       N->n * 2
+#define A( j ) j % 2 ? (uint32_t)( N->p[j/2] >> 32 ) : (uint32_t)( N->p[j/2] )
+#define STORE32                                   \
+    if( i % 2 ) {                                 \
+        N->p[i/2] &= 0x00000000FFFFFFFF;          \
+        N->p[i/2] |= ((t_uint) cur) << 32;        \
+    } else {                                      \
+        N->p[i/2] &= 0xFFFFFFFF00000000;          \
+        N->p[i/2] |= (t_uint) cur;                \
+    }
+
+#endif /* sizeof( t_uint ) */
+
+/*
+ * Helpers for addition and subtraction of chunks, with signed carry.
+ */
+static inline void add32( uint32_t *dst, uint32_t src, signed char *carry )
+{
+    *dst += src;
+    *carry += ( *dst < src );
+}
+
+static inline void sub32( uint32_t *dst, uint32_t src, signed char *carry )
+{
+    *carry -= ( *dst < src );
+    *dst -= src;
+}
+
+#define ADD( j )    add32( &cur, A( j ), &c );
+#define SUB( j )    sub32( &cur, A( j ), &c );
+
+/*
+ * Helpers for the main 'loop'
+ * (see fix_negative for the motivation of C)
+ */
+#define INIT( b )                                           \
+    int ret;                                                \
+    signed char c = 0, cc;                                  \
+    uint32_t cur;                                           \
+    size_t i = 0, bits = b;                                 \
+    mpi C;                                                  \
+    t_uint Cp[ b / 8 / sizeof( t_uint) + 1 ];               \
+                                                            \
+    C.s = 1;                                                \
+    C.n = b / 8 / sizeof( t_uint) + 1;                      \
+    C.p = Cp;                                               \
+    memset( Cp, 0, C.n * sizeof( t_uint ) );                \
+                                                            \
+    MPI_CHK( mpi_grow( N, b * 2 / 8 / sizeof( t_uint ) ) ); \
+    LOAD32;
+
+#define NEXT                    \
+    STORE32; i++; LOAD32;       \
+    cc = c; c = 0;              \
+    if( cc < 0 )                \
+        sub32( &cur, -cc, &c ); \
+    else                        \
+        add32( &cur, cc, &c );  \
+
+#define LAST                                    \
+    STORE32; i++;                               \
+    cur = c > 0 ? c : 0; STORE32;               \
+    cur = 0; while( ++i < MAX32 ) { STORE32; }  \
+    if( c < 0 ) fix_negative( N, c, &C, bits );
+
+/*
+ * If the result is negative, we get it in the form
+ * c * 2^(bits + 32) + N, with c negative and N positive shorter than 'bits'
+ */
+static inline int fix_negative( mpi *N, signed char c, mpi *C, size_t bits )
+{
+    int ret;
+
+    /* C = - c * 2^(bits + 32) */
+#if !defined(POLARSSL_HAVE_INT64)
+    ((void) bits);
+#else
+    if( bits == 224 )
+        C->p[ C->n - 1 ] = ((t_uint) -c) << 32;
+    else
+#endif
+        C->p[ C->n - 1 ] = (t_uint) -c;
+
+    /* N = - ( C - N ) */
+    MPI_CHK( mpi_sub_abs( N, C, N ) );
+    N->s = -1;
+
+cleanup:
+
+    return( ret );
+}
+
+#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED)
+/*
+ * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2)
+ */
+static int ecp_mod_p224( mpi *N )
+{
+    INIT( 224 );
+
+    SUB(  7 ); SUB( 11 );               NEXT; // A0 += -A7 - A11
+    SUB(  8 ); SUB( 12 );               NEXT; // A1 += -A8 - A12
+    SUB(  9 ); SUB( 13 );               NEXT; // A2 += -A9 - A13
+    SUB( 10 ); ADD(  7 ); ADD( 11 );    NEXT; // A3 += -A10 + A7 + A11
+    SUB( 11 ); ADD(  8 ); ADD( 12 );    NEXT; // A4 += -A11 + A8 + A12
+    SUB( 12 ); ADD(  9 ); ADD( 13 );    NEXT; // A5 += -A12 + A9 + A13
+    SUB( 13 ); ADD( 10 );               LAST; // A6 += -A13 + A10
+
+cleanup:
+    return( ret );
+}
+#endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED)
+/*
+ * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3)
+ */
+static int ecp_mod_p256( mpi *N )
+{
+    INIT( 256 );
+
+    ADD(  8 ); ADD(  9 );
+    SUB( 11 ); SUB( 12 ); SUB( 13 ); SUB( 14 );             NEXT; // A0
+
+    ADD(  9 ); ADD( 10 );
+    SUB( 12 ); SUB( 13 ); SUB( 14 ); SUB( 15 );             NEXT; // A1
+
+    ADD( 10 ); ADD( 11 );
+    SUB( 13 ); SUB( 14 ); SUB( 15 );                        NEXT; // A2
+
+    ADD( 11 ); ADD( 11 ); ADD( 12 ); ADD( 12 ); ADD( 13 );
+    SUB( 15 ); SUB(  8 ); SUB(  9 );                        NEXT; // A3
+
+    ADD( 12 ); ADD( 12 ); ADD( 13 ); ADD( 13 ); ADD( 14 );
+    SUB(  9 ); SUB( 10 );                                   NEXT; // A4
+
+    ADD( 13 ); ADD( 13 ); ADD( 14 ); ADD( 14 ); ADD( 15 );
+    SUB( 10 ); SUB( 11 );                                   NEXT; // A5
+
+    ADD( 14 ); ADD( 14 ); ADD( 15 ); ADD( 15 ); ADD( 14 ); ADD( 13 );
+    SUB(  8 ); SUB(  9 );                                   NEXT; // A6
+
+    ADD( 15 ); ADD( 15 ); ADD( 15 ); ADD( 8 );
+    SUB( 10 ); SUB( 11 ); SUB( 12 ); SUB( 13 );             LAST; // A7
+
+cleanup:
+    return( ret );
+}
+#endif /* POLARSSL_ECP_DP_SECP256R1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED)
+/*
+ * Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4)
+ */
+static int ecp_mod_p384( mpi *N )
+{
+    INIT( 384 );
+
+    ADD( 12 ); ADD( 21 ); ADD( 20 );
+    SUB( 23 );                                              NEXT; // A0
+
+    ADD( 13 ); ADD( 22 ); ADD( 23 );
+    SUB( 12 ); SUB( 20 );                                   NEXT; // A2
+
+    ADD( 14 ); ADD( 23 );
+    SUB( 13 ); SUB( 21 );                                   NEXT; // A2
+
+    ADD( 15 ); ADD( 12 ); ADD( 20 ); ADD( 21 );
+    SUB( 14 ); SUB( 22 ); SUB( 23 );                        NEXT; // A3
+
+    ADD( 21 ); ADD( 21 ); ADD( 16 ); ADD( 13 ); ADD( 12 ); ADD( 20 ); ADD( 22 );
+    SUB( 15 ); SUB( 23 ); SUB( 23 );                        NEXT; // A4
+
+    ADD( 22 ); ADD( 22 ); ADD( 17 ); ADD( 14 ); ADD( 13 ); ADD( 21 ); ADD( 23 );
+    SUB( 16 );                                              NEXT; // A5
+
+    ADD( 23 ); ADD( 23 ); ADD( 18 ); ADD( 15 ); ADD( 14 ); ADD( 22 );
+    SUB( 17 );                                              NEXT; // A6
+
+    ADD( 19 ); ADD( 16 ); ADD( 15 ); ADD( 23 );
+    SUB( 18 );                                              NEXT; // A7
+
+    ADD( 20 ); ADD( 17 ); ADD( 16 );
+    SUB( 19 );                                              NEXT; // A8
+
+    ADD( 21 ); ADD( 18 ); ADD( 17 );
+    SUB( 20 );                                              NEXT; // A9
+
+    ADD( 22 ); ADD( 19 ); ADD( 18 );
+    SUB( 21 );                                              NEXT; // A10
+
+    ADD( 23 ); ADD( 20 ); ADD( 19 );
+    SUB( 22 );                                              LAST; // A11
+
+cleanup:
+    return( ret );
+}
+#endif /* POLARSSL_ECP_DP_SECP384R1_ENABLED */
+
+#undef A
+#undef LOAD32
+#undef STORE32
+#undef MAX32
+#undef INIT
+#undef NEXT
+#undef LAST
+
+#endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED ||
+          POLARSSL_ECP_DP_SECP256R1_ENABLED ||
+          POLARSSL_ECP_DP_SECP384R1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED)
+/*
+ * Here we have an actual Mersenne prime, so things are more straightforward.
+ * However, chunks are aligned on a 'weird' boundary (521 bits).
+ */
+
+/* Size of p521 in terms of t_uint */
+#define P521_WIDTH      ( 521 / 8 / sizeof( t_uint ) + 1 )
+
+/* Bits to keep in the most significant t_uint */
+#if defined(POLARSSL_HAVE_INT8)
+#define P521_MASK       0x01
+#else
+#define P521_MASK       0x01FF
+#endif
+
+/*
+ * Fast quasi-reduction modulo p521 (FIPS 186-3 D.2.5)
+ * Write N as A1 + 2^521 A0, return A0 + A1
+ */
+static int ecp_mod_p521( mpi *N )
+{
+    int ret;
+    size_t i;
+    mpi M;
+    t_uint Mp[P521_WIDTH + 1];
+    /* Worst case for the size of M is when t_uint is 16 bits:
+     * we need to hold bits 513 to 1056, which is 34 limbs, that is
+     * P521_WIDTH + 1. Otherwise P521_WIDTH is enough. */
+
+    if( N->n < P521_WIDTH )
+        return( 0 );
+
+    /* M = A1 */
+    M.s = 1;
+    M.n = N->n - ( P521_WIDTH - 1 );
+    if( M.n > P521_WIDTH + 1 )
+        M.n = P521_WIDTH + 1;
+    M.p = Mp;
+    memcpy( Mp, N->p + P521_WIDTH - 1, M.n * sizeof( t_uint ) );
+    MPI_CHK( mpi_shift_r( &M, 521 % ( 8 * sizeof( t_uint ) ) ) );
+
+    /* N = A0 */
+    N->p[P521_WIDTH - 1] &= P521_MASK;
+    for( i = P521_WIDTH; i < N->n; i++ )
+        N->p[i] = 0;
+
+    /* N = A0 + A1 */
+    MPI_CHK( mpi_add_abs( N, N, &M ) );
+
+cleanup:
+    return( ret );
+}
+
+#undef P521_WIDTH
+#undef P521_MASK
+#endif /* POLARSSL_ECP_DP_SECP521R1_ENABLED */
+
+#endif /* POLARSSL_ECP_NIST_OPTIM */
+
+#if defined(POLARSSL_ECP_DP_M255_ENABLED)
+
+/* Size of p255 in terms of t_uint */
+#define P255_WIDTH      ( 255 / 8 / sizeof( t_uint ) + 1 )
+
+/*
+ * Fast quasi-reduction modulo p255 = 2^255 - 19
+ * Write N as A0 + 2^255 A1, return A0 + 19 * A1
+ */
+static int ecp_mod_p255( mpi *N )
+{
+    int ret;
+    size_t i;
+    mpi M;
+    t_uint Mp[P255_WIDTH + 2];
+
+    if( N->n < P255_WIDTH )
+        return( 0 );
+
+    /* M = A1 */
+    M.s = 1;
+    M.n = N->n - ( P255_WIDTH - 1 );
+    if( M.n > P255_WIDTH + 1 )
+        M.n = P255_WIDTH + 1;
+    M.p = Mp;
+    memset( Mp, 0, sizeof Mp );
+    memcpy( Mp, N->p + P255_WIDTH - 1, M.n * sizeof( t_uint ) );
+    MPI_CHK( mpi_shift_r( &M, 255 % ( 8 * sizeof( t_uint ) ) ) );
+    M.n++; /* Make room for multiplication by 19 */
+
+    /* N = A0 */
+    MPI_CHK( mpi_set_bit( N, 255, 0 ) );
+    for( i = P255_WIDTH; i < N->n; i++ )
+        N->p[i] = 0;
+
+    /* N = A0 + 19 * A1 */
+    MPI_CHK( mpi_mul_int( &M, &M, 19 ) );
+    MPI_CHK( mpi_add_abs( N, N, &M ) );
+
+cleanup:
+    return( ret );
+}
+#endif /* POLARSSL_ECP_DP_M255_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_SECP192K1_ENABLED) ||   \
+    defined(POLARSSL_ECP_DP_SECP224K1_ENABLED) ||   \
+    defined(POLARSSL_ECP_DP_SECP256K1_ENABLED)
+/*
+ * Fast quasi-reduction modulo P = 2^s - R,
+ * with R about 33 bits, used by the Koblitz curves.
+ *
+ * Write N as A0 + 2^224 A1, return A0 + R * A1.
+ * Actually do two passes, since R is big.
+ */
+#define P_KOBLITZ_MAX   ( 256 / 8 / sizeof( t_uint ) )  // Max limbs in P
+#define P_KOBLITZ_R     ( 8 / sizeof( t_uint ) )        // Limbs in R
+static inline int ecp_mod_koblitz( mpi *N, t_uint *Rp, size_t p_limbs,
+                                   size_t adjust, size_t shift, t_uint mask )
+{
+    int ret;
+    size_t i;
+    mpi M, R;
+    t_uint Mp[P_KOBLITZ_MAX + P_KOBLITZ_R];
+
+    if( N->n < p_limbs )
+        return( 0 );
+
+    /* Init R */
+    R.s = 1;
+    R.p = Rp;
+    R.n = P_KOBLITZ_R;
+
+    /* Common setup for M */
+    M.s = 1;
+    M.p = Mp;
+
+    /* M = A1 */
+    M.n = N->n - ( p_limbs - adjust );
+    if( M.n > p_limbs + adjust )
+        M.n = p_limbs + adjust;
+    memset( Mp, 0, sizeof Mp );
+    memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( t_uint ) );
+    if (shift != 0 )
+        MPI_CHK( mpi_shift_r( &M, shift ) );
+    M.n += R.n - adjust; /* Make room for multiplication by R */
+
+    /* N = A0 */
+    if (mask != 0 )
+        N->p[p_limbs - 1] &= mask;
+    for( i = p_limbs; i < N->n; i++ )
+        N->p[i] = 0;
+
+    /* N = A0 + R * A1 */
+    MPI_CHK( mpi_mul_mpi( &M, &M, &R ) );
+    MPI_CHK( mpi_add_abs( N, N, &M ) );
+
+    /* Second pass */
+
+    /* M = A1 */
+    M.n = N->n - ( p_limbs - adjust );
+    if( M.n > p_limbs + adjust )
+        M.n = p_limbs + adjust;
+    memset( Mp, 0, sizeof Mp );
+    memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( t_uint ) );
+    if (shift != 0 )
+        MPI_CHK( mpi_shift_r( &M, shift ) );
+    M.n += R.n - adjust; /* Make room for multiplication by R */
+
+    /* N = A0 */
+    if (mask != 0 )
+        N->p[p_limbs - 1] &= mask;
+    for( i = p_limbs; i < N->n; i++ )
+        N->p[i] = 0;
+
+    /* N = A0 + R * A1 */
+    MPI_CHK( mpi_mul_mpi( &M, &M, &R ) );
+    MPI_CHK( mpi_add_abs( N, N, &M ) );
+
+cleanup:
+    return( ret );
+}
+#endif /* POLARSSL_ECP_DP_SECP192K1_ENABLED) ||
+          POLARSSL_ECP_DP_SECP224K1_ENABLED) ||
+          POLARSSL_ECP_DP_SECP256K1_ENABLED) */
+
+#if defined(POLARSSL_ECP_DP_SECP192K1_ENABLED)
+/*
+ * Fast quasi-reduction modulo p192k1 = 2^192 - R,
+ * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x0100001119
+ */
+static int ecp_mod_p192k1( mpi *N )
+{
+    static t_uint Rp[] = {
+        BYTES_TO_T_UINT_8( 0xC9, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) };
+
+    return( ecp_mod_koblitz( N, Rp, 192 / 8 / sizeof( t_uint ), 0, 0, 0 ) );
+}
+#endif /* POLARSSL_ECP_DP_SECP192K1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_SECP224K1_ENABLED)
+/*
+ * Fast quasi-reduction modulo p224k1 = 2^224 - R,
+ * with R = 2^32 + 2^12 + 2^11 + 2^9 + 2^7 + 2^4 + 2 + 1 = 0x0100001A93
+ */
+static int ecp_mod_p224k1( mpi *N )
+{
+    static t_uint Rp[] = {
+        BYTES_TO_T_UINT_8( 0x93, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) };
+
+#if defined(POLARSSL_HAVE_INT64)
+    return( ecp_mod_koblitz( N, Rp, 4, 1, 32, 0xFFFFFFFF ) );
+#else
+    return( ecp_mod_koblitz( N, Rp, 224 / 8 / sizeof( t_uint ), 0, 0, 0 ) );
+#endif
+}
+
+#endif /* POLARSSL_ECP_DP_SECP224K1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_SECP256K1_ENABLED)
+/*
+ * Fast quasi-reduction modulo p256k1 = 2^256 - R,
+ * with R = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1 = 0x01000003D1
+ */
+static int ecp_mod_p256k1( mpi *N )
+{
+    static t_uint Rp[] = {
+        BYTES_TO_T_UINT_8( 0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) };
+    return( ecp_mod_koblitz( N, Rp, 256 / 8 / sizeof( t_uint ), 0, 0, 0 ) );
+}
+#endif /* POLARSSL_ECP_DP_SECP256K1_ENABLED */
+
+#endif /* POLARSSL_ECP_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/entropy.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,377 @@
+/*
+ *  Entropy accumulator implementation
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_ENTROPY_C)
+
+#include "polarssl/entropy.h"
+#include "polarssl/entropy_poll.h"
+
+#if defined(POLARSSL_FS_IO)
+#include <stdio.h>
+#endif
+
+#if defined(POLARSSL_HAVEGE_C)
+#include "polarssl/havege.h"
+#endif
+
+#define ENTROPY_MAX_LOOP    256     /**< Maximum amount to loop before error */
+
+void entropy_init( entropy_context *ctx )
+{
+    memset( ctx, 0, sizeof(entropy_context) );
+
+#if defined(POLARSSL_THREADING_C)
+    polarssl_mutex_init( &ctx->mutex );
+#endif
+
+#if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
+    sha512_starts( &ctx->accumulator, 0 );
+#else
+    sha256_starts( &ctx->accumulator, 0 );
+#endif
+#if defined(POLARSSL_HAVEGE_C)
+    havege_init( &ctx->havege_data );
+#endif
+
+#if !defined(POLARSSL_NO_DEFAULT_ENTROPY_SOURCES)
+#if !defined(POLARSSL_NO_PLATFORM_ENTROPY)
+    entropy_add_source( ctx, platform_entropy_poll, NULL,
+                        ENTROPY_MIN_PLATFORM );
+#endif
+#if defined(POLARSSL_TIMING_C)
+    entropy_add_source( ctx, hardclock_poll, NULL, ENTROPY_MIN_HARDCLOCK );
+#endif
+#if defined(POLARSSL_HAVEGE_C)
+    entropy_add_source( ctx, havege_poll, &ctx->havege_data,
+                        ENTROPY_MIN_HAVEGE );
+#endif
+#endif /* POLARSSL_NO_DEFAULT_ENTROPY_SOURCES */
+}
+
+void entropy_free( entropy_context *ctx )
+{
+    ((void) ctx);
+#if defined(POLARSSL_THREADING_C)
+    polarssl_mutex_free( &ctx->mutex );
+#endif
+}
+
+int entropy_add_source( entropy_context *ctx,
+                        f_source_ptr f_source, void *p_source,
+                        size_t threshold )
+{
+    int index, ret = 0;
+
+#if defined(POLARSSL_THREADING_C)
+    if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 )
+        return( ret );
+#endif
+
+    index = ctx->source_count;
+    if( index >= ENTROPY_MAX_SOURCES )
+    {
+        ret = POLARSSL_ERR_ENTROPY_MAX_SOURCES;
+        goto exit;
+    }
+
+    ctx->source[index].f_source = f_source;
+    ctx->source[index].p_source = p_source;
+    ctx->source[index].threshold = threshold;
+
+    ctx->source_count++;
+
+exit:
+#if defined(POLARSSL_THREADING_C)
+    if( polarssl_mutex_unlock( &ctx->mutex ) != 0 )
+        return( POLARSSL_ERR_THREADING_MUTEX_ERROR );
+#endif
+
+    return( ret );
+}
+
+/*
+ * Entropy accumulator update
+ */
+static int entropy_update( entropy_context *ctx, unsigned char source_id,
+                           const unsigned char *data, size_t len )
+{
+    unsigned char header[2];
+    unsigned char tmp[ENTROPY_BLOCK_SIZE];
+    size_t use_len = len;
+    const unsigned char *p = data;
+
+    if( use_len > ENTROPY_BLOCK_SIZE )
+    {
+#if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
+        sha512( data, len, tmp, 0 );
+#else
+        sha256( data, len, tmp, 0 );
+#endif
+        p = tmp;
+        use_len = ENTROPY_BLOCK_SIZE;
+    }
+
+    header[0] = source_id;
+    header[1] = use_len & 0xFF;
+
+#if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
+    sha512_update( &ctx->accumulator, header, 2 );
+    sha512_update( &ctx->accumulator, p, use_len );
+#else
+    sha256_update( &ctx->accumulator, header, 2 );
+    sha256_update( &ctx->accumulator, p, use_len );
+#endif
+
+    return( 0 );
+}
+
+int entropy_update_manual( entropy_context *ctx,
+                           const unsigned char *data, size_t len )
+{
+    int ret;
+
+#if defined(POLARSSL_THREADING_C)
+    if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 )
+        return( ret );
+#endif
+
+    ret = entropy_update( ctx, ENTROPY_SOURCE_MANUAL, data, len );
+
+#if defined(POLARSSL_THREADING_C)
+    if( polarssl_mutex_unlock( &ctx->mutex ) != 0 )
+        return( POLARSSL_ERR_THREADING_MUTEX_ERROR );
+#endif
+
+    return ( ret );
+}
+
+/*
+ * Run through the different sources to add entropy to our accumulator
+ */
+static int entropy_gather_internal( entropy_context *ctx )
+{
+    int ret, i;
+    unsigned char buf[ENTROPY_MAX_GATHER];
+    size_t olen;
+
+    if( ctx->source_count == 0 )
+        return( POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED );
+
+    /*
+     * Run through our entropy sources
+     */
+    for( i = 0; i < ctx->source_count; i++ )
+    {
+        olen = 0;
+        if ( ( ret = ctx->source[i].f_source( ctx->source[i].p_source,
+                        buf, ENTROPY_MAX_GATHER, &olen ) ) != 0 )
+        {
+            return( ret );
+        }
+
+        /*
+         * Add if we actually gathered something
+         */
+        if( olen > 0 )
+        {
+            entropy_update( ctx, (unsigned char) i, buf, olen );
+            ctx->source[i].size += olen;
+        }
+    }
+
+    return( 0 );
+}
+
+/*
+ * Thread-safe wrapper for entropy_gather_internal()
+ */
+int entropy_gather( entropy_context *ctx )
+{
+    int ret;
+
+#if defined(POLARSSL_THREADING_C)
+    if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 )
+        return( ret );
+#endif
+
+    ret = entropy_gather_internal( ctx );
+
+#if defined(POLARSSL_THREADING_C)
+    if( polarssl_mutex_unlock( &ctx->mutex ) != 0 )
+        return( POLARSSL_ERR_THREADING_MUTEX_ERROR );
+#endif
+
+    return( ret );
+}
+
+int entropy_func( void *data, unsigned char *output, size_t len )
+{
+    int ret, count = 0, i, reached;
+    entropy_context *ctx = (entropy_context *) data;
+    unsigned char buf[ENTROPY_BLOCK_SIZE];
+
+    if( len > ENTROPY_BLOCK_SIZE )
+        return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
+
+#if defined(POLARSSL_THREADING_C)
+    if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 )
+        return( ret );
+#endif
+
+    /*
+     * Always gather extra entropy before a call
+     */
+    do
+    {
+        if( count++ > ENTROPY_MAX_LOOP )
+        {
+            ret = POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
+            goto exit;
+        }
+
+        if( ( ret = entropy_gather_internal( ctx ) ) != 0 )
+            goto exit;
+
+        reached = 0;
+
+        for( i = 0; i < ctx->source_count; i++ )
+            if( ctx->source[i].size >= ctx->source[i].threshold )
+                reached++;
+    }
+    while( reached != ctx->source_count );
+
+    memset( buf, 0, ENTROPY_BLOCK_SIZE );
+
+#if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
+    sha512_finish( &ctx->accumulator, buf );
+
+    /*
+     * Reset accumulator and counters and recycle existing entropy
+     */
+    memset( &ctx->accumulator, 0, sizeof( sha512_context ) );
+    sha512_starts( &ctx->accumulator, 0 );
+    sha512_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE );
+
+    /*
+     * Perform second SHA-512 on entropy
+     */
+    sha512( buf, ENTROPY_BLOCK_SIZE, buf, 0 );
+#else /* POLARSSL_ENTROPY_SHA512_ACCUMULATOR */
+    sha256_finish( &ctx->accumulator, buf );
+
+    /*
+     * Reset accumulator and counters and recycle existing entropy
+     */
+    memset( &ctx->accumulator, 0, sizeof( sha256_context ) );
+    sha256_starts( &ctx->accumulator, 0 );
+    sha256_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE );
+
+    /*
+     * Perform second SHA-256 on entropy
+     */
+    sha256( buf, ENTROPY_BLOCK_SIZE, buf, 0 );
+#endif /* POLARSSL_ENTROPY_SHA512_ACCUMULATOR */
+
+    for( i = 0; i < ctx->source_count; i++ )
+        ctx->source[i].size = 0;
+
+    memcpy( output, buf, len );
+
+    ret = 0;
+
+exit:
+#if defined(POLARSSL_THREADING_C)
+    if( polarssl_mutex_unlock( &ctx->mutex ) != 0 )
+        return( POLARSSL_ERR_THREADING_MUTEX_ERROR );
+#endif
+
+    return( ret );
+}
+
+#if defined(POLARSSL_FS_IO)
+int entropy_write_seed_file( entropy_context *ctx, const char *path )
+{
+    int ret = POLARSSL_ERR_ENTROPY_FILE_IO_ERROR;
+    FILE *f;
+    unsigned char buf[ENTROPY_BLOCK_SIZE];
+
+    if( ( f = fopen( path, "wb" ) ) == NULL )
+        return( POLARSSL_ERR_ENTROPY_FILE_IO_ERROR );
+
+    if( ( ret = entropy_func( ctx, buf, ENTROPY_BLOCK_SIZE ) ) != 0 )
+        goto exit;
+
+    if( fwrite( buf, 1, ENTROPY_BLOCK_SIZE, f ) != ENTROPY_BLOCK_SIZE )
+    {
+        ret = POLARSSL_ERR_ENTROPY_FILE_IO_ERROR;
+        goto exit;
+    }
+
+    ret = 0;
+
+exit:
+    fclose( f );
+    return( ret );
+}
+
+int entropy_update_seed_file( entropy_context *ctx, const char *path )
+{
+    FILE *f;
+    size_t n;
+    unsigned char buf[ ENTROPY_MAX_SEED_SIZE ];
+
+    if( ( f = fopen( path, "rb" ) ) == NULL )
+        return( POLARSSL_ERR_ENTROPY_FILE_IO_ERROR );
+
+    fseek( f, 0, SEEK_END );
+    n = (size_t) ftell( f );
+    fseek( f, 0, SEEK_SET );
+
+    if( n > ENTROPY_MAX_SEED_SIZE )
+        n = ENTROPY_MAX_SEED_SIZE;
+
+    if( fread( buf, 1, n, f ) != n )
+    {
+        fclose( f );
+        return( POLARSSL_ERR_ENTROPY_FILE_IO_ERROR );
+    }
+
+    fclose( f );
+
+    entropy_update_manual( ctx, buf, n );
+
+    return( entropy_write_seed_file( ctx, path ) );
+}
+#endif /* POLARSSL_FS_IO */
+
+#endif /* POLARSSL_ENTROPY_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/entropy_poll.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,142 @@
+/*
+ *  Platform-specific and custom entropy polling functions
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_ENTROPY_C)
+
+#include "polarssl/entropy.h"
+#include "polarssl/entropy_poll.h"
+
+#if defined(POLARSSL_TIMING_C)
+#include "polarssl/timing.h"
+#endif
+#if defined(POLARSSL_HAVEGE_C)
+#include "polarssl/havege.h"
+#endif
+
+#if !defined(POLARSSL_NO_PLATFORM_ENTROPY)
+#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
+
+#if !defined(_WIN32_WINNT)
+#define _WIN32_WINNT 0x0400
+#endif
+#include <windows.h>
+#include <wincrypt.h>
+
+int platform_entropy_poll( void *data, unsigned char *output, size_t len,
+                           size_t *olen )
+{
+    HCRYPTPROV provider;
+    ((void) data);
+    *olen = 0;
+
+    if( CryptAcquireContext( &provider, NULL, NULL,
+                              PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == FALSE )
+    {
+        return POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
+    }
+
+    if( CryptGenRandom( provider, (DWORD) len, output ) == FALSE )
+        return POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
+
+    CryptReleaseContext( provider, 0 );
+    *olen = len;
+
+    return( 0 );
+}
+#else /* _WIN32 && !EFIX64 && !EFI32 */
+
+#include <stdio.h>
+
+int platform_entropy_poll( void *data,
+                           unsigned char *output, size_t len, size_t *olen )
+{
+    FILE *file;
+    size_t ret;
+    ((void) data);
+
+    *olen = 0;
+
+    file = fopen( "/dev/urandom", "rb" );
+    if( file == NULL )
+        return POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
+
+    ret = fread( output, 1, len, file );
+    if( ret != len )
+    {
+        fclose( file );
+        return POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
+    }
+
+    fclose( file );
+    *olen = len;
+
+    return( 0 );
+}
+#endif /* _WIN32 && !EFIX64 && !EFI32 */
+#endif /* !POLARSSL_NO_PLATFORM_ENTROPY */
+
+#if defined(POLARSSL_TIMING_C)
+int hardclock_poll( void *data,
+                    unsigned char *output, size_t len, size_t *olen )
+{
+    unsigned long timer = hardclock();
+    ((void) data);
+    *olen = 0;
+
+    if( len < sizeof(unsigned long) )
+        return( 0 );
+
+    memcpy( output, &timer, sizeof(unsigned long) );
+    *olen = sizeof(unsigned long);
+
+    return( 0 );
+}
+#endif /* POLARSSL_TIMING_C */
+
+#if defined(POLARSSL_HAVEGE_C)
+int havege_poll( void *data,
+                 unsigned char *output, size_t len, size_t *olen )
+{
+    havege_state *hs = (havege_state *) data;
+    *olen = 0;
+
+    if( havege_random( hs, output, len ) != 0 )
+        return POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
+
+    *olen = len;
+
+    return( 0 );
+}
+#endif /* POLARSSL_HAVEGE_C */
+
+#endif /* POLARSSL_ENTROPY_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/error.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,754 @@
+/*
+ *  Error message information
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_ERROR_C)
+
+#include "polarssl/error.h"
+
+#if defined(POLARSSL_AES_C)
+#include "polarssl/aes.h"
+#endif
+
+#if defined(POLARSSL_BASE64_C)
+#include "polarssl/base64.h"
+#endif
+
+#if defined(POLARSSL_BIGNUM_C)
+#include "polarssl/bignum.h"
+#endif
+
+#if defined(POLARSSL_BLOWFISH_C)
+#include "polarssl/blowfish.h"
+#endif
+
+#if defined(POLARSSL_CAMELLIA_C)
+#include "polarssl/camellia.h"
+#endif
+
+#if defined(POLARSSL_CIPHER_C)
+#include "polarssl/cipher.h"
+#endif
+
+#if defined(POLARSSL_CTR_DRBG_C)
+#include "polarssl/ctr_drbg.h"
+#endif
+
+#if defined(POLARSSL_DES_C)
+#include "polarssl/des.h"
+#endif
+
+#if defined(POLARSSL_DHM_C)
+#include "polarssl/dhm.h"
+#endif
+
+#if defined(POLARSSL_ECP_C)
+#include "polarssl/ecp.h"
+#endif
+
+#if defined(POLARSSL_ENTROPY_C)
+#include "polarssl/entropy.h"
+#endif
+
+#if defined(POLARSSL_GCM_C)
+#include "polarssl/gcm.h"
+#endif
+
+#if defined(POLARSSL_HMAC_DRBG_C)
+#include "polarssl/hmac_drbg.h"
+#endif
+
+#if defined(POLARSSL_MD_C)
+#include "polarssl/md.h"
+#endif
+
+#if defined(POLARSSL_MD2_C)
+#include "polarssl/md2.h"
+#endif
+
+#if defined(POLARSSL_MD4_C)
+#include "polarssl/md4.h"
+#endif
+
+#if defined(POLARSSL_MD5_C)
+#include "polarssl/md5.h"
+#endif
+
+#if defined(POLARSSL_NET_C)
+#include "polarssl/net.h"
+#endif
+
+#if defined(POLARSSL_OID_C)
+#include "polarssl/oid.h"
+#endif
+
+#if defined(POLARSSL_PADLOCK_C)
+#include "polarssl/padlock.h"
+#endif
+
+#if defined(POLARSSL_PBKDF2_C)
+#include "polarssl/pbkdf2.h"
+#endif
+
+#if defined(POLARSSL_PEM_PARSE_C) || defined(POLARSSL_PEM_WRITE_C)
+#include "polarssl/pem.h"
+#endif
+
+#if defined(POLARSSL_PK_C)
+#include "polarssl/pk.h"
+#endif
+
+#if defined(POLARSSL_PKCS12_C)
+#include "polarssl/pkcs12.h"
+#endif
+
+#if defined(POLARSSL_PKCS5_C)
+#include "polarssl/pkcs5.h"
+#endif
+
+#if defined(POLARSSL_RIPEMD160_C)
+#include "polarssl/ripemd160.h"
+#endif
+
+#if defined(POLARSSL_RSA_C)
+#include "polarssl/rsa.h"
+#endif
+
+#if defined(POLARSSL_SHA1_C)
+#include "polarssl/sha1.h"
+#endif
+
+#if defined(POLARSSL_SHA256_C)
+#include "polarssl/sha256.h"
+#endif
+
+#if defined(POLARSSL_SHA512_C)
+#include "polarssl/sha512.h"
+#endif
+
+#if defined(POLARSSL_SSL_TLS_C)
+#include "polarssl/ssl.h"
+#endif
+
+#if defined(POLARSSL_THREADING_C)
+#include "polarssl/threading.h"
+#endif
+
+#if defined(POLARSSL_X509_USE_C) || defined(POLARSSL_X509_CREATE_C)
+#include "polarssl/x509.h"
+#endif
+
+#if defined(POLARSSL_XTEA_C)
+#include "polarssl/xtea.h"
+#endif
+
+
+#include <string.h>
+
+#if defined(_MSC_VER) && !defined  snprintf && !defined(EFIX64) && \
+    !defined(EFI32)
+#define  snprintf  _snprintf
+#endif
+
+void polarssl_strerror( int ret, char *buf, size_t buflen )
+{
+    size_t len;
+    int use_ret;
+
+    if( buflen == 0 )
+        return;
+
+    memset( buf, 0x00, buflen );
+    /* Reduce buflen to make sure MSVC _snprintf() ends with \0 as well */
+    buflen -= 1;
+
+    if( ret < 0 )
+        ret = -ret;
+
+    if( ret & 0xFF80 )
+    {
+        use_ret = ret & 0xFF80;
+
+        // High level error codes
+        //
+#if defined(POLARSSL_CIPHER_C)
+        if( use_ret == -(POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE) )
+            snprintf( buf, buflen, "CIPHER - The selected feature is not available" );
+        if( use_ret == -(POLARSSL_ERR_CIPHER_BAD_INPUT_DATA) )
+            snprintf( buf, buflen, "CIPHER - Bad input parameters to function" );
+        if( use_ret == -(POLARSSL_ERR_CIPHER_ALLOC_FAILED) )
+            snprintf( buf, buflen, "CIPHER - Failed to allocate memory" );
+        if( use_ret == -(POLARSSL_ERR_CIPHER_INVALID_PADDING) )
+            snprintf( buf, buflen, "CIPHER - Input data contains invalid padding and is rejected" );
+        if( use_ret == -(POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED) )
+            snprintf( buf, buflen, "CIPHER - Decryption of block requires a full block" );
+        if( use_ret == -(POLARSSL_ERR_CIPHER_AUTH_FAILED) )
+            snprintf( buf, buflen, "CIPHER - Authentication failed (for AEAD modes)" );
+#endif /* POLARSSL_CIPHER_C */
+
+#if defined(POLARSSL_DHM_C)
+        if( use_ret == -(POLARSSL_ERR_DHM_BAD_INPUT_DATA) )
+            snprintf( buf, buflen, "DHM - Bad input parameters to function" );
+        if( use_ret == -(POLARSSL_ERR_DHM_READ_PARAMS_FAILED) )
+            snprintf( buf, buflen, "DHM - Reading of the DHM parameters failed" );
+        if( use_ret == -(POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED) )
+            snprintf( buf, buflen, "DHM - Making of the DHM parameters failed" );
+        if( use_ret == -(POLARSSL_ERR_DHM_READ_PUBLIC_FAILED) )
+            snprintf( buf, buflen, "DHM - Reading of the public values failed" );
+        if( use_ret == -(POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED) )
+            snprintf( buf, buflen, "DHM - Making of the public value failed" );
+        if( use_ret == -(POLARSSL_ERR_DHM_CALC_SECRET_FAILED) )
+            snprintf( buf, buflen, "DHM - Calculation of the DHM secret failed" );
+        if( use_ret == -(POLARSSL_ERR_DHM_INVALID_FORMAT) )
+            snprintf( buf, buflen, "DHM - The ASN.1 data is not formatted correctly" );
+        if( use_ret == -(POLARSSL_ERR_DHM_MALLOC_FAILED) )
+            snprintf( buf, buflen, "DHM - Allocation of memory failed" );
+        if( use_ret == -(POLARSSL_ERR_DHM_FILE_IO_ERROR) )
+            snprintf( buf, buflen, "DHM - Read/write of file failed" );
+#endif /* POLARSSL_DHM_C */
+
+#if defined(POLARSSL_ECP_C)
+        if( use_ret == -(POLARSSL_ERR_ECP_BAD_INPUT_DATA) )
+            snprintf( buf, buflen, "ECP - Bad input parameters to function" );
+        if( use_ret == -(POLARSSL_ERR_ECP_BUFFER_TOO_SMALL) )
+            snprintf( buf, buflen, "ECP - The buffer is too small to write to" );
+        if( use_ret == -(POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE) )
+            snprintf( buf, buflen, "ECP - Requested curve not available" );
+        if( use_ret == -(POLARSSL_ERR_ECP_VERIFY_FAILED) )
+            snprintf( buf, buflen, "ECP - The signature is not valid" );
+        if( use_ret == -(POLARSSL_ERR_ECP_MALLOC_FAILED) )
+            snprintf( buf, buflen, "ECP - Memory allocation failed" );
+        if( use_ret == -(POLARSSL_ERR_ECP_RANDOM_FAILED) )
+            snprintf( buf, buflen, "ECP - Generation of random value, such as (ephemeral) key, failed" );
+        if( use_ret == -(POLARSSL_ERR_ECP_INVALID_KEY) )
+            snprintf( buf, buflen, "ECP - Invalid private or public key" );
+        if( use_ret == -(POLARSSL_ERR_ECP_SIG_LEN_MISMATCH) )
+            snprintf( buf, buflen, "ECP - Signature is valid but shorter than the user-supplied length" );
+#endif /* POLARSSL_ECP_C */
+
+#if defined(POLARSSL_MD_C)
+        if( use_ret == -(POLARSSL_ERR_MD_FEATURE_UNAVAILABLE) )
+            snprintf( buf, buflen, "MD - The selected feature is not available" );
+        if( use_ret == -(POLARSSL_ERR_MD_BAD_INPUT_DATA) )
+            snprintf( buf, buflen, "MD - Bad input parameters to function" );
+        if( use_ret == -(POLARSSL_ERR_MD_ALLOC_FAILED) )
+            snprintf( buf, buflen, "MD - Failed to allocate memory" );
+        if( use_ret == -(POLARSSL_ERR_MD_FILE_IO_ERROR) )
+            snprintf( buf, buflen, "MD - Opening or reading of file failed" );
+#endif /* POLARSSL_MD_C */
+
+#if defined(POLARSSL_PEM_PARSE_C) || defined(POLARSSL_PEM_WRITE_C)
+        if( use_ret == -(POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT) )
+            snprintf( buf, buflen, "PEM - No PEM header or footer found" );
+        if( use_ret == -(POLARSSL_ERR_PEM_INVALID_DATA) )
+            snprintf( buf, buflen, "PEM - PEM string is not as expected" );
+        if( use_ret == -(POLARSSL_ERR_PEM_MALLOC_FAILED) )
+            snprintf( buf, buflen, "PEM - Failed to allocate memory" );
+        if( use_ret == -(POLARSSL_ERR_PEM_INVALID_ENC_IV) )
+            snprintf( buf, buflen, "PEM - RSA IV is not in hex-format" );
+        if( use_ret == -(POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG) )
+            snprintf( buf, buflen, "PEM - Unsupported key encryption algorithm" );
+        if( use_ret == -(POLARSSL_ERR_PEM_PASSWORD_REQUIRED) )
+            snprintf( buf, buflen, "PEM - Private key password can't be empty" );
+        if( use_ret == -(POLARSSL_ERR_PEM_PASSWORD_MISMATCH) )
+            snprintf( buf, buflen, "PEM - Given private key password does not allow for correct decryption" );
+        if( use_ret == -(POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE) )
+            snprintf( buf, buflen, "PEM - Unavailable feature, e.g. hashing/encryption combination" );
+        if( use_ret == -(POLARSSL_ERR_PEM_BAD_INPUT_DATA) )
+            snprintf( buf, buflen, "PEM - Bad input parameters to function" );
+#endif /* POLARSSL_PEM_PARSE_C || POLARSSL_PEM_WRITE_C */
+
+#if defined(POLARSSL_PK_C)
+        if( use_ret == -(POLARSSL_ERR_PK_MALLOC_FAILED) )
+            snprintf( buf, buflen, "PK - Memory alloation failed" );
+        if( use_ret == -(POLARSSL_ERR_PK_TYPE_MISMATCH) )
+            snprintf( buf, buflen, "PK - Type mismatch, eg attempt to encrypt with an ECDSA key" );
+        if( use_ret == -(POLARSSL_ERR_PK_BAD_INPUT_DATA) )
+            snprintf( buf, buflen, "PK - Bad input parameters to function" );
+        if( use_ret == -(POLARSSL_ERR_PK_FILE_IO_ERROR) )
+            snprintf( buf, buflen, "PK - Read/write of file failed" );
+        if( use_ret == -(POLARSSL_ERR_PK_KEY_INVALID_VERSION) )
+            snprintf( buf, buflen, "PK - Unsupported key version" );
+        if( use_ret == -(POLARSSL_ERR_PK_KEY_INVALID_FORMAT) )
+            snprintf( buf, buflen, "PK - Invalid key tag or value" );
+        if( use_ret == -(POLARSSL_ERR_PK_UNKNOWN_PK_ALG) )
+            snprintf( buf, buflen, "PK - Key algorithm is unsupported (only RSA and EC are supported)" );
+        if( use_ret == -(POLARSSL_ERR_PK_PASSWORD_REQUIRED) )
+            snprintf( buf, buflen, "PK - Private key password can't be empty" );
+        if( use_ret == -(POLARSSL_ERR_PK_PASSWORD_MISMATCH) )
+            snprintf( buf, buflen, "PK - Given private key password does not allow for correct decryption" );
+        if( use_ret == -(POLARSSL_ERR_PK_INVALID_PUBKEY) )
+            snprintf( buf, buflen, "PK - The pubkey tag or value is invalid (only RSA and EC are supported)" );
+        if( use_ret == -(POLARSSL_ERR_PK_INVALID_ALG) )
+            snprintf( buf, buflen, "PK - The algorithm tag or value is invalid" );
+        if( use_ret == -(POLARSSL_ERR_PK_UNKNOWN_NAMED_CURVE) )
+            snprintf( buf, buflen, "PK - Elliptic curve is unsupported (only NIST curves are supported)" );
+        if( use_ret == -(POLARSSL_ERR_PK_FEATURE_UNAVAILABLE) )
+            snprintf( buf, buflen, "PK - Unavailable feature, e.g. RSA disabled for RSA key" );
+        if( use_ret == -(POLARSSL_ERR_PK_SIG_LEN_MISMATCH) )
+            snprintf( buf, buflen, "PK - The signature is valid but its length is less than expected" );
+#endif /* POLARSSL_PK_C */
+
+#if defined(POLARSSL_PKCS12_C)
+        if( use_ret == -(POLARSSL_ERR_PKCS12_BAD_INPUT_DATA) )
+            snprintf( buf, buflen, "PKCS12 - Bad input parameters to function" );
+        if( use_ret == -(POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE) )
+            snprintf( buf, buflen, "PKCS12 - Feature not available, e.g. unsupported encryption scheme" );
+        if( use_ret == -(POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT) )
+            snprintf( buf, buflen, "PKCS12 - PBE ASN.1 data not as expected" );
+        if( use_ret == -(POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH) )
+            snprintf( buf, buflen, "PKCS12 - Given private key password does not allow for correct decryption" );
+#endif /* POLARSSL_PKCS12_C */
+
+#if defined(POLARSSL_PKCS5_C)
+        if( use_ret == -(POLARSSL_ERR_PKCS5_BAD_INPUT_DATA) )
+            snprintf( buf, buflen, "PKCS5 - Bad input parameters to function" );
+        if( use_ret == -(POLARSSL_ERR_PKCS5_INVALID_FORMAT) )
+            snprintf( buf, buflen, "PKCS5 - Unexpected ASN.1 data" );
+        if( use_ret == -(POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE) )
+            snprintf( buf, buflen, "PKCS5 - Requested encryption or digest alg not available" );
+        if( use_ret == -(POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH) )
+            snprintf( buf, buflen, "PKCS5 - Given private key password does not allow for correct decryption" );
+#endif /* POLARSSL_PKCS5_C */
+
+#if defined(POLARSSL_RSA_C)
+        if( use_ret == -(POLARSSL_ERR_RSA_BAD_INPUT_DATA) )
+            snprintf( buf, buflen, "RSA - Bad input parameters to function" );
+        if( use_ret == -(POLARSSL_ERR_RSA_INVALID_PADDING) )
+            snprintf( buf, buflen, "RSA - Input data contains invalid padding and is rejected" );
+        if( use_ret == -(POLARSSL_ERR_RSA_KEY_GEN_FAILED) )
+            snprintf( buf, buflen, "RSA - Something failed during generation of a key" );
+        if( use_ret == -(POLARSSL_ERR_RSA_KEY_CHECK_FAILED) )
+            snprintf( buf, buflen, "RSA - Key failed to pass the libraries validity check" );
+        if( use_ret == -(POLARSSL_ERR_RSA_PUBLIC_FAILED) )
+            snprintf( buf, buflen, "RSA - The public key operation failed" );
+        if( use_ret == -(POLARSSL_ERR_RSA_PRIVATE_FAILED) )
+            snprintf( buf, buflen, "RSA - The private key operation failed" );
+        if( use_ret == -(POLARSSL_ERR_RSA_VERIFY_FAILED) )
+            snprintf( buf, buflen, "RSA - The PKCS#1 verification failed" );
+        if( use_ret == -(POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE) )
+            snprintf( buf, buflen, "RSA - The output buffer for decryption is not large enough" );
+        if( use_ret == -(POLARSSL_ERR_RSA_RNG_FAILED) )
+            snprintf( buf, buflen, "RSA - The random generator failed to generate non-zeros" );
+#endif /* POLARSSL_RSA_C */
+
+#if defined(POLARSSL_SSL_TLS_C)
+        if( use_ret == -(POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE) )
+            snprintf( buf, buflen, "SSL - The requested feature is not available" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_INPUT_DATA) )
+            snprintf( buf, buflen, "SSL - Bad input parameters to function" );
+        if( use_ret == -(POLARSSL_ERR_SSL_INVALID_MAC) )
+            snprintf( buf, buflen, "SSL - Verification of the message MAC failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_INVALID_RECORD) )
+            snprintf( buf, buflen, "SSL - An invalid SSL record was received" );
+        if( use_ret == -(POLARSSL_ERR_SSL_CONN_EOF) )
+            snprintf( buf, buflen, "SSL - The connection indicated an EOF" );
+        if( use_ret == -(POLARSSL_ERR_SSL_UNKNOWN_CIPHER) )
+            snprintf( buf, buflen, "SSL - An unknown cipher was received" );
+        if( use_ret == -(POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN) )
+            snprintf( buf, buflen, "SSL - The server has no ciphersuites in common with the client" );
+        if( use_ret == -(POLARSSL_ERR_SSL_NO_RNG) )
+            snprintf( buf, buflen, "SSL - No RNG was provided to the SSL module" );
+        if( use_ret == -(POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE) )
+            snprintf( buf, buflen, "SSL - No client certification received from the client, but required by the authentication mode" );
+        if( use_ret == -(POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE) )
+            snprintf( buf, buflen, "SSL - DESCRIPTION MISSING" );
+        if( use_ret == -(POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED) )
+            snprintf( buf, buflen, "SSL - The own certificate is not set, but needed by the server" );
+        if( use_ret == -(POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED) )
+            snprintf( buf, buflen, "SSL - The own private key or pre-shared key is not set, but needed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED) )
+            snprintf( buf, buflen, "SSL - No CA Chain is set, but required to operate" );
+        if( use_ret == -(POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE) )
+            snprintf( buf, buflen, "SSL - An unexpected message was received from our peer" );
+        if( use_ret == -(POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE) )
+        {
+            snprintf( buf, buflen, "SSL - A fatal alert message was received from our peer" );
+            return;
+        }
+        if( use_ret == -(POLARSSL_ERR_SSL_PEER_VERIFY_FAILED) )
+            snprintf( buf, buflen, "SSL - Verification of our peer failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY) )
+            snprintf( buf, buflen, "SSL - The peer notified us that the connection is going to be closed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO) )
+            snprintf( buf, buflen, "SSL - Processing of the ClientHello handshake message failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO) )
+            snprintf( buf, buflen, "SSL - Processing of the ServerHello handshake message failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE) )
+            snprintf( buf, buflen, "SSL - Processing of the Certificate handshake message failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST) )
+            snprintf( buf, buflen, "SSL - Processing of the CertificateRequest handshake message failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE) )
+            snprintf( buf, buflen, "SSL - Processing of the ServerKeyExchange handshake message failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE) )
+            snprintf( buf, buflen, "SSL - Processing of the ServerHelloDone handshake message failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE) )
+            snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP) )
+            snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS) )
+            snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY) )
+            snprintf( buf, buflen, "SSL - Processing of the CertificateVerify handshake message failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC) )
+            snprintf( buf, buflen, "SSL - Processing of the ChangeCipherSpec handshake message failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_FINISHED) )
+            snprintf( buf, buflen, "SSL - Processing of the Finished handshake message failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_MALLOC_FAILED) )
+            snprintf( buf, buflen, "SSL - Memory allocation failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_HW_ACCEL_FAILED) )
+            snprintf( buf, buflen, "SSL - Hardware acceleration function returned with error" );
+        if( use_ret == -(POLARSSL_ERR_SSL_HW_ACCEL_FALLTHROUGH) )
+            snprintf( buf, buflen, "SSL - Hardware acceleration function skipped / left alone data" );
+        if( use_ret == -(POLARSSL_ERR_SSL_COMPRESSION_FAILED) )
+            snprintf( buf, buflen, "SSL - Processing of the compression / decompression failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION) )
+            snprintf( buf, buflen, "SSL - Handshake protocol not within min/max boundaries" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_NEW_SESSION_TICKET) )
+            snprintf( buf, buflen, "SSL - Processing of the NewSessionTicket handshake message failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_SESSION_TICKET_EXPIRED) )
+            snprintf( buf, buflen, "SSL - Session ticket has expired" );
+        if( use_ret == -(POLARSSL_ERR_SSL_PK_TYPE_MISMATCH) )
+            snprintf( buf, buflen, "SSL - Public key type mismatch (eg, asked for RSA key exchange and presented EC key)" );
+        if( use_ret == -(POLARSSL_ERR_SSL_UNKNOWN_IDENTITY) )
+            snprintf( buf, buflen, "SSL - Unknown identity received (eg, PSK identity)" );
+        if( use_ret == -(POLARSSL_ERR_SSL_INTERNAL_ERROR) )
+            snprintf( buf, buflen, "SSL - Internal error (eg, unexpected failure in lower-level module)" );
+        if( use_ret == -(POLARSSL_ERR_SSL_COUNTER_WRAPPING) )
+            snprintf( buf, buflen, "SSL - A counter would wrap (eg, too many messages exchanged)" );
+#endif /* POLARSSL_SSL_TLS_C */
+
+#if defined(POLARSSL_X509_USE_C) || defined(POLARSSL_X509_CREATE_C)
+        if( use_ret == -(POLARSSL_ERR_X509_FEATURE_UNAVAILABLE) )
+            snprintf( buf, buflen, "X509 - Unavailable feature, e.g. RSA hashing/encryption combination" );
+        if( use_ret == -(POLARSSL_ERR_X509_UNKNOWN_OID) )
+            snprintf( buf, buflen, "X509 - Requested OID is unknown" );
+        if( use_ret == -(POLARSSL_ERR_X509_INVALID_FORMAT) )
+            snprintf( buf, buflen, "X509 - The CRT/CRL/CSR format is invalid, e.g. different type expected" );
+        if( use_ret == -(POLARSSL_ERR_X509_INVALID_VERSION) )
+            snprintf( buf, buflen, "X509 - The CRT/CRL/CSR version element is invalid" );
+        if( use_ret == -(POLARSSL_ERR_X509_INVALID_SERIAL) )
+            snprintf( buf, buflen, "X509 - The serial tag or value is invalid" );
+        if( use_ret == -(POLARSSL_ERR_X509_INVALID_ALG) )
+            snprintf( buf, buflen, "X509 - The algorithm tag or value is invalid" );
+        if( use_ret == -(POLARSSL_ERR_X509_INVALID_NAME) )
+            snprintf( buf, buflen, "X509 - The name tag or value is invalid" );
+        if( use_ret == -(POLARSSL_ERR_X509_INVALID_DATE) )
+            snprintf( buf, buflen, "X509 - The date tag or value is invalid" );
+        if( use_ret == -(POLARSSL_ERR_X509_INVALID_SIGNATURE) )
+            snprintf( buf, buflen, "X509 - The signature tag or value invalid" );
+        if( use_ret == -(POLARSSL_ERR_X509_INVALID_EXTENSIONS) )
+            snprintf( buf, buflen, "X509 - The extension tag or value is invalid" );
+        if( use_ret == -(POLARSSL_ERR_X509_UNKNOWN_VERSION) )
+            snprintf( buf, buflen, "X509 - CRT/CRL/CSR has an unsupported version number" );
+        if( use_ret == -(POLARSSL_ERR_X509_UNKNOWN_SIG_ALG) )
+            snprintf( buf, buflen, "X509 - Signature algorithm (oid) is unsupported" );
+        if( use_ret == -(POLARSSL_ERR_X509_SIG_MISMATCH) )
+            snprintf( buf, buflen, "X509 - Signature algorithms do not match. (see \\c ::x509_crt sig_oid)" );
+        if( use_ret == -(POLARSSL_ERR_X509_CERT_VERIFY_FAILED) )
+            snprintf( buf, buflen, "X509 - Certificate verification failed, e.g. CRL, CA or signature check failed" );
+        if( use_ret == -(POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT) )
+            snprintf( buf, buflen, "X509 - Format not recognized as DER or PEM" );
+        if( use_ret == -(POLARSSL_ERR_X509_BAD_INPUT_DATA) )
+            snprintf( buf, buflen, "X509 - Input invalid" );
+        if( use_ret == -(POLARSSL_ERR_X509_MALLOC_FAILED) )
+            snprintf( buf, buflen, "X509 - Allocation of memory failed" );
+        if( use_ret == -(POLARSSL_ERR_X509_FILE_IO_ERROR) )
+            snprintf( buf, buflen, "X509 - Read/write of file failed" );
+#endif /* POLARSSL_X509_USE,X509_CREATE_C */
+
+        if( strlen( buf ) == 0 )
+            snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret );
+    }
+
+    use_ret = ret & ~0xFF80;
+
+    if( use_ret == 0 )
+        return;
+
+    // If high level code is present, make a concatenation between both
+    // error strings.
+    //
+    len = strlen( buf );
+
+    if( len > 0 )
+    {
+        if( buflen - len < 5 )
+            return;
+
+        snprintf( buf + len, buflen - len, " : " );
+
+        buf += len + 3;
+        buflen -= len + 3;
+    }
+
+    // Low level error codes
+    //
+#if defined(POLARSSL_AES_C)
+    if( use_ret == -(POLARSSL_ERR_AES_INVALID_KEY_LENGTH) )
+        snprintf( buf, buflen, "AES - Invalid key length" );
+    if( use_ret == -(POLARSSL_ERR_AES_INVALID_INPUT_LENGTH) )
+        snprintf( buf, buflen, "AES - Invalid data input length" );
+#endif /* POLARSSL_AES_C */
+
+#if defined(POLARSSL_ASN1_PARSE_C)
+    if( use_ret == -(POLARSSL_ERR_ASN1_OUT_OF_DATA) )
+        snprintf( buf, buflen, "ASN1 - Out of data when parsing an ASN1 data structure" );
+    if( use_ret == -(POLARSSL_ERR_ASN1_UNEXPECTED_TAG) )
+        snprintf( buf, buflen, "ASN1 - ASN1 tag was of an unexpected value" );
+    if( use_ret == -(POLARSSL_ERR_ASN1_INVALID_LENGTH) )
+        snprintf( buf, buflen, "ASN1 - Error when trying to determine the length or invalid length" );
+    if( use_ret == -(POLARSSL_ERR_ASN1_LENGTH_MISMATCH) )
+        snprintf( buf, buflen, "ASN1 - Actual length differs from expected length" );
+    if( use_ret == -(POLARSSL_ERR_ASN1_INVALID_DATA) )
+        snprintf( buf, buflen, "ASN1 - Data is invalid. (not used)" );
+    if( use_ret == -(POLARSSL_ERR_ASN1_MALLOC_FAILED) )
+        snprintf( buf, buflen, "ASN1 - Memory allocation failed" );
+    if( use_ret == -(POLARSSL_ERR_ASN1_BUF_TOO_SMALL) )
+        snprintf( buf, buflen, "ASN1 - Buffer too small when writing ASN.1 data structure" );
+#endif /* POLARSSL_ASN1_PARSE_C */
+
+#if defined(POLARSSL_BASE64_C)
+    if( use_ret == -(POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL) )
+        snprintf( buf, buflen, "BASE64 - Output buffer too small" );
+    if( use_ret == -(POLARSSL_ERR_BASE64_INVALID_CHARACTER) )
+        snprintf( buf, buflen, "BASE64 - Invalid character in input" );
+#endif /* POLARSSL_BASE64_C */
+
+#if defined(POLARSSL_BIGNUM_C)
+    if( use_ret == -(POLARSSL_ERR_MPI_FILE_IO_ERROR) )
+        snprintf( buf, buflen, "BIGNUM - An error occurred while reading from or writing to a file" );
+    if( use_ret == -(POLARSSL_ERR_MPI_BAD_INPUT_DATA) )
+        snprintf( buf, buflen, "BIGNUM - Bad input parameters to function" );
+    if( use_ret == -(POLARSSL_ERR_MPI_INVALID_CHARACTER) )
+        snprintf( buf, buflen, "BIGNUM - There is an invalid character in the digit string" );
+    if( use_ret == -(POLARSSL_ERR_MPI_BUFFER_TOO_SMALL) )
+        snprintf( buf, buflen, "BIGNUM - The buffer is too small to write to" );
+    if( use_ret == -(POLARSSL_ERR_MPI_NEGATIVE_VALUE) )
+        snprintf( buf, buflen, "BIGNUM - The input arguments are negative or result in illegal output" );
+    if( use_ret == -(POLARSSL_ERR_MPI_DIVISION_BY_ZERO) )
+        snprintf( buf, buflen, "BIGNUM - The input argument for division is zero, which is not allowed" );
+    if( use_ret == -(POLARSSL_ERR_MPI_NOT_ACCEPTABLE) )
+        snprintf( buf, buflen, "BIGNUM - The input arguments are not acceptable" );
+    if( use_ret == -(POLARSSL_ERR_MPI_MALLOC_FAILED) )
+        snprintf( buf, buflen, "BIGNUM - Memory allocation failed" );
+#endif /* POLARSSL_BIGNUM_C */
+
+#if defined(POLARSSL_BLOWFISH_C)
+    if( use_ret == -(POLARSSL_ERR_BLOWFISH_INVALID_KEY_LENGTH) )
+        snprintf( buf, buflen, "BLOWFISH - Invalid key length" );
+    if( use_ret == -(POLARSSL_ERR_BLOWFISH_INVALID_INPUT_LENGTH) )
+        snprintf( buf, buflen, "BLOWFISH - Invalid data input length" );
+#endif /* POLARSSL_BLOWFISH_C */
+
+#if defined(POLARSSL_CAMELLIA_C)
+    if( use_ret == -(POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH) )
+        snprintf( buf, buflen, "CAMELLIA - Invalid key length" );
+    if( use_ret == -(POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH) )
+        snprintf( buf, buflen, "CAMELLIA - Invalid data input length" );
+#endif /* POLARSSL_CAMELLIA_C */
+
+#if defined(POLARSSL_CTR_DRBG_C)
+    if( use_ret == -(POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED) )
+        snprintf( buf, buflen, "CTR_DRBG - The entropy source failed" );
+    if( use_ret == -(POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG) )
+        snprintf( buf, buflen, "CTR_DRBG - Too many random requested in single call" );
+    if( use_ret == -(POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG) )
+        snprintf( buf, buflen, "CTR_DRBG - Input too large (Entropy + additional)" );
+    if( use_ret == -(POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR) )
+        snprintf( buf, buflen, "CTR_DRBG - Read/write error in file" );
+#endif /* POLARSSL_CTR_DRBG_C */
+
+#if defined(POLARSSL_DES_C)
+    if( use_ret == -(POLARSSL_ERR_DES_INVALID_INPUT_LENGTH) )
+        snprintf( buf, buflen, "DES - The data input has an invalid length" );
+#endif /* POLARSSL_DES_C */
+
+#if defined(POLARSSL_ENTROPY_C)
+    if( use_ret == -(POLARSSL_ERR_ENTROPY_SOURCE_FAILED) )
+        snprintf( buf, buflen, "ENTROPY - Critical entropy source failure" );
+    if( use_ret == -(POLARSSL_ERR_ENTROPY_MAX_SOURCES) )
+        snprintf( buf, buflen, "ENTROPY - No more sources can be added" );
+    if( use_ret == -(POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED) )
+        snprintf( buf, buflen, "ENTROPY - No sources have been added to poll" );
+    if( use_ret == -(POLARSSL_ERR_ENTROPY_FILE_IO_ERROR) )
+        snprintf( buf, buflen, "ENTROPY - Read/write error in file" );
+#endif /* POLARSSL_ENTROPY_C */
+
+#if defined(POLARSSL_GCM_C)
+    if( use_ret == -(POLARSSL_ERR_GCM_AUTH_FAILED) )
+        snprintf( buf, buflen, "GCM - Authenticated decryption failed" );
+    if( use_ret == -(POLARSSL_ERR_GCM_BAD_INPUT) )
+        snprintf( buf, buflen, "GCM - Bad input parameters to function" );
+#endif /* POLARSSL_GCM_C */
+
+#if defined(POLARSSL_HMAC_DRBG_C)
+    if( use_ret == -(POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG) )
+        snprintf( buf, buflen, "HMAC_DRBG - Too many random requested in single call" );
+    if( use_ret == -(POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG) )
+        snprintf( buf, buflen, "HMAC_DRBG - Input too large (Entropy + additional)" );
+    if( use_ret == -(POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR) )
+        snprintf( buf, buflen, "HMAC_DRBG - Read/write error in file" );
+    if( use_ret == -(POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED) )
+        snprintf( buf, buflen, "HMAC_DRBG - The entropy source failed" );
+#endif /* POLARSSL_HMAC_DRBG_C */
+
+#if defined(POLARSSL_MD2_C)
+    if( use_ret == -(POLARSSL_ERR_MD2_FILE_IO_ERROR) )
+        snprintf( buf, buflen, "MD2 - Read/write error in file" );
+#endif /* POLARSSL_MD2_C */
+
+#if defined(POLARSSL_MD4_C)
+    if( use_ret == -(POLARSSL_ERR_MD4_FILE_IO_ERROR) )
+        snprintf( buf, buflen, "MD4 - Read/write error in file" );
+#endif /* POLARSSL_MD4_C */
+
+#if defined(POLARSSL_MD5_C)
+    if( use_ret == -(POLARSSL_ERR_MD5_FILE_IO_ERROR) )
+        snprintf( buf, buflen, "MD5 - Read/write error in file" );
+#endif /* POLARSSL_MD5_C */
+
+#if defined(POLARSSL_NET_C)
+    if( use_ret == -(POLARSSL_ERR_NET_UNKNOWN_HOST) )
+        snprintf( buf, buflen, "NET - Failed to get an IP address for the given hostname" );
+    if( use_ret == -(POLARSSL_ERR_NET_SOCKET_FAILED) )
+        snprintf( buf, buflen, "NET - Failed to open a socket" );
+    if( use_ret == -(POLARSSL_ERR_NET_CONNECT_FAILED) )
+        snprintf( buf, buflen, "NET - The connection to the given server / port failed" );
+    if( use_ret == -(POLARSSL_ERR_NET_BIND_FAILED) )
+        snprintf( buf, buflen, "NET - Binding of the socket failed" );
+    if( use_ret == -(POLARSSL_ERR_NET_LISTEN_FAILED) )
+        snprintf( buf, buflen, "NET - Could not listen on the socket" );
+    if( use_ret == -(POLARSSL_ERR_NET_ACCEPT_FAILED) )
+        snprintf( buf, buflen, "NET - Could not accept the incoming connection" );
+    if( use_ret == -(POLARSSL_ERR_NET_RECV_FAILED) )
+        snprintf( buf, buflen, "NET - Reading information from the socket failed" );
+    if( use_ret == -(POLARSSL_ERR_NET_SEND_FAILED) )
+        snprintf( buf, buflen, "NET - Sending information through the socket failed" );
+    if( use_ret == -(POLARSSL_ERR_NET_CONN_RESET) )
+        snprintf( buf, buflen, "NET - Connection was reset by peer" );
+    if( use_ret == -(POLARSSL_ERR_NET_WANT_READ) )
+        snprintf( buf, buflen, "NET - Connection requires a read call" );
+    if( use_ret == -(POLARSSL_ERR_NET_WANT_WRITE) )
+        snprintf( buf, buflen, "NET - Connection requires a write call" );
+#endif /* POLARSSL_NET_C */
+
+#if defined(POLARSSL_OID_C)
+    if( use_ret == -(POLARSSL_ERR_OID_NOT_FOUND) )
+        snprintf( buf, buflen, "OID - OID is not found" );
+    if( use_ret == -(POLARSSL_ERR_OID_BUF_TOO_SMALL) )
+        snprintf( buf, buflen, "OID - output buffer is too small" );
+#endif /* POLARSSL_OID_C */
+
+#if defined(POLARSSL_PADLOCK_C)
+    if( use_ret == -(POLARSSL_ERR_PADLOCK_DATA_MISALIGNED) )
+        snprintf( buf, buflen, "PADLOCK - Input data should be aligned" );
+#endif /* POLARSSL_PADLOCK_C */
+
+#if defined(POLARSSL_PBKDF2_C)
+    if( use_ret == -(POLARSSL_ERR_PBKDF2_BAD_INPUT_DATA) )
+        snprintf( buf, buflen, "PBKDF2 - Bad input parameters to function" );
+#endif /* POLARSSL_PBKDF2_C */
+
+#if defined(POLARSSL_RIPEMD160_C)
+    if( use_ret == -(POLARSSL_ERR_RIPEMD160_FILE_IO_ERROR) )
+        snprintf( buf, buflen, "RIPEMD160 - Read/write error in file" );
+#endif /* POLARSSL_RIPEMD160_C */
+
+#if defined(POLARSSL_SHA1_C)
+    if( use_ret == -(POLARSSL_ERR_SHA1_FILE_IO_ERROR) )
+        snprintf( buf, buflen, "SHA1 - Read/write error in file" );
+#endif /* POLARSSL_SHA1_C */
+
+#if defined(POLARSSL_SHA256_C)
+    if( use_ret == -(POLARSSL_ERR_SHA256_FILE_IO_ERROR) )
+        snprintf( buf, buflen, "SHA256 - Read/write error in file" );
+#endif /* POLARSSL_SHA256_C */
+
+#if defined(POLARSSL_SHA512_C)
+    if( use_ret == -(POLARSSL_ERR_SHA512_FILE_IO_ERROR) )
+        snprintf( buf, buflen, "SHA512 - Read/write error in file" );
+#endif /* POLARSSL_SHA512_C */
+
+#if defined(POLARSSL_THREADING_C)
+    if( use_ret == -(POLARSSL_ERR_THREADING_FEATURE_UNAVAILABLE) )
+        snprintf( buf, buflen, "THREADING - The selected feature is not available" );
+    if( use_ret == -(POLARSSL_ERR_THREADING_BAD_INPUT_DATA) )
+        snprintf( buf, buflen, "THREADING - Bad input parameters to function" );
+    if( use_ret == -(POLARSSL_ERR_THREADING_MUTEX_ERROR) )
+        snprintf( buf, buflen, "THREADING - Locking / unlocking / free failed with error code" );
+#endif /* POLARSSL_THREADING_C */
+
+#if defined(POLARSSL_XTEA_C)
+    if( use_ret == -(POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH) )
+        snprintf( buf, buflen, "XTEA - The data input has an invalid length" );
+#endif /* POLARSSL_XTEA_C */
+
+    if( strlen( buf ) != 0 )
+        return;
+
+    snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret );
+}
+
+#if defined(POLARSSL_ERROR_STRERROR_BC)
+void error_strerror( int ret, char *buf, size_t buflen )
+{
+    polarssl_strerror( ret, buf, buflen );
+}
+#endif /* POLARSSL_ERROR_STRERROR_BC */
+
+#else /* POLARSSL_ERROR_C */
+
+#if defined(POLARSSL_ERROR_STRERROR_DUMMY)
+
+#include <string.h>
+
+/*
+ * Provide an non-function in case POLARSSL_ERROR_C is not defined
+ */
+void polarssl_strerror( int ret, char *buf, size_t buflen )
+{
+    ((void) ret);
+
+    if( buflen > 0 )
+        buf[0] = '\0';
+}
+
+#if defined(POLARSSL_ERROR_STRERROR_BC)
+void error_strerror( int ret, char *buf, size_t buflen )
+{
+    polarssl_strerror( ret, buf, buflen );
+}
+#endif /* POLARSSL_ERROR_STRERROR_BC */
+#endif /* POLARSSL_ERROR_STRERROR_DUMMY */
+
+#endif /* POLARSSL_ERROR_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/gcm.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,931 @@
+/*
+ *  NIST SP800-38D compliant GCM implementation
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*
+ * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
+ *
+ * See also:
+ * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
+ *
+ * We use the algorithm described as Shoup's method with 4-bit tables in
+ * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory.
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_GCM_C)
+
+#include "polarssl/gcm.h"
+
+#if defined(POLARSSL_AESNI_C)
+#include "polarssl/aesni.h"
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i)                            \
+{                                                       \
+    (n) = ( (uint32_t) (b)[(i)    ] << 24 )             \
+        | ( (uint32_t) (b)[(i) + 1] << 16 )             \
+        | ( (uint32_t) (b)[(i) + 2] <<  8 )             \
+        | ( (uint32_t) (b)[(i) + 3]       );            \
+}
+#endif
+
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i)                            \
+{                                                       \
+    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
+    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
+    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
+    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
+}
+#endif
+
+/*
+ * Precompute small multiples of H, that is set
+ *      HH[i] || HL[i] = H times i,
+ * where i is seen as a field element as in [MGV], ie high-order bits
+ * correspond to low powers of P. The result is stored in the same way, that
+ * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
+ * corresponds to P^127.
+ */
+static int gcm_gen_table( gcm_context *ctx )
+{
+    int ret, i, j;
+    uint64_t hi, lo;
+    uint64_t vl, vh;
+    unsigned char h[16];
+    size_t olen = 0;
+
+    memset( h, 0, 16 );
+    if( ( ret = cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 )
+        return( ret );
+
+    /* pack h as two 64-bits ints, big-endian */
+    GET_UINT32_BE( hi, h,  0  );
+    GET_UINT32_BE( lo, h,  4  );
+    vh = (uint64_t) hi << 32 | lo;
+
+    GET_UINT32_BE( hi, h,  8  );
+    GET_UINT32_BE( lo, h,  12 );
+    vl = (uint64_t) hi << 32 | lo;
+
+    /* 8 = 1000 corresponds to 1 in GF(2^128) */
+    ctx->HL[8] = vl;
+    ctx->HH[8] = vh;
+
+#if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64)
+    /* With CLMUL support, we need only h, not the rest of the table */
+    if( aesni_supports( POLARSSL_AESNI_CLMUL ) )
+        return( 0 );
+#endif
+
+    /* 0 corresponds to 0 in GF(2^128) */
+    ctx->HH[0] = 0;
+    ctx->HL[0] = 0;
+
+    for( i = 4; i > 0; i >>= 1 )
+    {
+        uint32_t T = ( vl & 1 ) * 0xe1000000U;
+        vl  = ( vh << 63 ) | ( vl >> 1 );
+        vh  = ( vh >> 1 ) ^ ( (uint64_t) T << 32);
+
+        ctx->HL[i] = vl;
+        ctx->HH[i] = vh;
+    }
+
+    for (i = 2; i < 16; i <<= 1 )
+    {
+        uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
+        vh = *HiH;
+        vl = *HiL;
+        for( j = 1; j < i; j++ )
+        {
+            HiH[j] = vh ^ ctx->HH[j];
+            HiL[j] = vl ^ ctx->HL[j];
+        }
+    }
+
+    return( 0 );
+}
+
+int gcm_init( gcm_context *ctx, cipher_id_t cipher, const unsigned char *key,
+              unsigned int keysize )
+{
+    int ret;
+    const cipher_info_t *cipher_info;
+
+    memset( ctx, 0, sizeof(gcm_context) );
+
+    cipher_info = cipher_info_from_values( cipher, keysize, POLARSSL_MODE_ECB );
+    if( cipher_info == NULL )
+        return( POLARSSL_ERR_GCM_BAD_INPUT );
+
+    if( cipher_info->block_size != 16 )
+        return( POLARSSL_ERR_GCM_BAD_INPUT );
+
+    if( ( ret = cipher_init_ctx( &ctx->cipher_ctx, cipher_info ) ) != 0 )
+        return( ret );
+
+    if( ( ret = cipher_setkey( &ctx->cipher_ctx, key, keysize,
+                               POLARSSL_ENCRYPT ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    if( ( ret = gcm_gen_table( ctx ) ) != 0 )
+        return( ret );
+
+    return( 0 );
+}
+
+/*
+ * Shoup's method for multiplication use this table with
+ *      last4[x] = x times P^128
+ * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
+ */
+static const uint64_t last4[16] =
+{
+    0x0000, 0x1c20, 0x3840, 0x2460,
+    0x7080, 0x6ca0, 0x48c0, 0x54e0,
+    0xe100, 0xfd20, 0xd940, 0xc560,
+    0x9180, 0x8da0, 0xa9c0, 0xb5e0
+};
+
+/*
+ * Sets output to x times H using the precomputed tables.
+ * x and output are seen as elements of GF(2^128) as in [MGV].
+ */
+static void gcm_mult( gcm_context *ctx, const unsigned char x[16],
+                      unsigned char output[16] )
+{
+    int i = 0;
+    unsigned char z[16];
+    unsigned char lo, hi, rem;
+    uint64_t zh, zl;
+
+#if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64)
+    if( aesni_supports( POLARSSL_AESNI_CLMUL ) ) {
+        unsigned char h[16];
+
+        PUT_UINT32_BE( ctx->HH[8] >> 32, h,  0 );
+        PUT_UINT32_BE( ctx->HH[8],       h,  4 );
+        PUT_UINT32_BE( ctx->HL[8] >> 32, h,  8 );
+        PUT_UINT32_BE( ctx->HL[8],       h, 12 );
+
+        aesni_gcm_mult( output, x, h );
+        return;
+    }
+#endif /* POLARSSL_AESNI_C && POLARSSL_HAVE_X86_64 */
+
+    memset( z, 0x00, 16 );
+
+    lo = x[15] & 0xf;
+    hi = x[15] >> 4;
+
+    zh = ctx->HH[lo];
+    zl = ctx->HL[lo];
+
+    for( i = 15; i >= 0; i-- )
+    {
+        lo = x[i] & 0xf;
+        hi = x[i] >> 4;
+
+        if( i != 15 )
+        {
+            rem = (unsigned char) zl & 0xf;
+            zl = ( zh << 60 ) | ( zl >> 4 );
+            zh = ( zh >> 4 );
+            zh ^= (uint64_t) last4[rem] << 48;
+            zh ^= ctx->HH[lo];
+            zl ^= ctx->HL[lo];
+
+        }
+
+        rem = (unsigned char) zl & 0xf;
+        zl = ( zh << 60 ) | ( zl >> 4 );
+        zh = ( zh >> 4 );
+        zh ^= (uint64_t) last4[rem] << 48;
+        zh ^= ctx->HH[hi];
+        zl ^= ctx->HL[hi];
+    }
+
+    PUT_UINT32_BE( zh >> 32, output, 0 );
+    PUT_UINT32_BE( zh, output, 4 );
+    PUT_UINT32_BE( zl >> 32, output, 8 );
+    PUT_UINT32_BE( zl, output, 12 );
+}
+
+int gcm_starts( gcm_context *ctx,
+                int mode,
+                const unsigned char *iv,
+                size_t iv_len,
+                const unsigned char *add,
+                size_t add_len )
+{
+    int ret;
+    unsigned char work_buf[16];
+    size_t i;
+    const unsigned char *p;
+    size_t use_len, olen = 0;
+
+    memset( ctx->y, 0x00, sizeof(ctx->y) );
+    memset( ctx->buf, 0x00, sizeof(ctx->buf) );
+
+    ctx->mode = mode;
+    ctx->len = 0;
+    ctx->add_len = 0;
+
+    if( iv_len == 12 )
+    {
+        memcpy( ctx->y, iv, iv_len );
+        ctx->y[15] = 1;
+    }
+    else
+    {
+        memset( work_buf, 0x00, 16 );
+        PUT_UINT32_BE( iv_len * 8, work_buf, 12 );
+
+        p = iv;
+        while( iv_len > 0 )
+        {
+            use_len = ( iv_len < 16 ) ? iv_len : 16;
+
+            for( i = 0; i < use_len; i++ )
+                ctx->y[i] ^= p[i];
+
+            gcm_mult( ctx, ctx->y, ctx->y );
+
+            iv_len -= use_len;
+            p += use_len;
+        }
+
+        for( i = 0; i < 16; i++ )
+            ctx->y[i] ^= work_buf[i];
+
+        gcm_mult( ctx, ctx->y, ctx->y );
+    }
+
+    if( ( ret = cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr,
+                             &olen ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    ctx->add_len = add_len;
+    p = add;
+    while( add_len > 0 )
+    {
+        use_len = ( add_len < 16 ) ? add_len : 16;
+
+        for( i = 0; i < use_len; i++ )
+            ctx->buf[i] ^= p[i];
+
+        gcm_mult( ctx, ctx->buf, ctx->buf );
+
+        add_len -= use_len;
+        p += use_len;
+    }
+
+    return( 0 );
+}
+
+int gcm_update( gcm_context *ctx,
+                size_t length,
+                const unsigned char *input,
+                unsigned char *output )
+{
+    int ret;
+    unsigned char ectr[16];
+    size_t i;
+    const unsigned char *p;
+    unsigned char *out_p = output;
+    size_t use_len, olen = 0;
+
+    if( output > input && (size_t) ( output - input ) < length )
+        return( POLARSSL_ERR_GCM_BAD_INPUT );
+
+    ctx->len += length;
+
+    p = input;
+    while( length > 0 )
+    {
+        use_len = ( length < 16 ) ? length : 16;
+
+        for( i = 16; i > 12; i-- )
+            if( ++ctx->y[i - 1] != 0 )
+                break;
+
+        if( ( ret = cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr,
+                                   &olen ) ) != 0 )
+        {
+            return( ret );
+        }
+
+        for( i = 0; i < use_len; i++ )
+        {
+            if( ctx->mode == GCM_DECRYPT )
+                ctx->buf[i] ^= p[i];
+            out_p[i] = ectr[i] ^ p[i];
+            if( ctx->mode == GCM_ENCRYPT )
+                ctx->buf[i] ^= out_p[i];
+        }
+
+        gcm_mult( ctx, ctx->buf, ctx->buf );
+
+        length -= use_len;
+        p += use_len;
+        out_p += use_len;
+    }
+
+    return( 0 );
+}
+
+int gcm_finish( gcm_context *ctx,
+                unsigned char *tag,
+                size_t tag_len )
+{
+    unsigned char work_buf[16];
+    size_t i;
+    uint64_t orig_len = ctx->len * 8;
+    uint64_t orig_add_len = ctx->add_len * 8;
+
+    if( tag_len > 16 )
+        return( POLARSSL_ERR_GCM_BAD_INPUT );
+
+    if( tag_len != 0 )
+        memcpy( tag, ctx->base_ectr, tag_len );
+
+    if( orig_len || orig_add_len )
+    {
+        memset( work_buf, 0x00, 16 );
+
+        PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0  );
+        PUT_UINT32_BE( ( orig_add_len       ), work_buf, 4  );
+        PUT_UINT32_BE( ( orig_len     >> 32 ), work_buf, 8  );
+        PUT_UINT32_BE( ( orig_len           ), work_buf, 12 );
+
+        for( i = 0; i < 16; i++ )
+            ctx->buf[i] ^= work_buf[i];
+
+        gcm_mult( ctx, ctx->buf, ctx->buf );
+
+        for( i = 0; i < tag_len; i++ )
+            tag[i] ^= ctx->buf[i];
+    }
+
+    return( 0 );
+}
+
+int gcm_crypt_and_tag( gcm_context *ctx,
+                       int mode,
+                       size_t length,
+                       const unsigned char *iv,
+                       size_t iv_len,
+                       const unsigned char *add,
+                       size_t add_len,
+                       const unsigned char *input,
+                       unsigned char *output,
+                       size_t tag_len,
+                       unsigned char *tag )
+{
+    int ret;
+
+    if( ( ret = gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 )
+        return( ret );
+
+    if( ( ret = gcm_update( ctx, length, input, output ) ) != 0 )
+        return( ret );
+
+    if( ( ret = gcm_finish( ctx, tag, tag_len ) ) != 0 )
+        return( ret );
+
+    return( 0 );
+}
+
+int gcm_auth_decrypt( gcm_context *ctx,
+                      size_t length,
+                      const unsigned char *iv,
+                      size_t iv_len,
+                      const unsigned char *add,
+                      size_t add_len,
+                      const unsigned char *tag,
+                      size_t tag_len,
+                      const unsigned char *input,
+                      unsigned char *output )
+{
+    int ret;
+    unsigned char check_tag[16];
+    size_t i;
+    int diff;
+
+    if( ( ret = gcm_crypt_and_tag( ctx, GCM_DECRYPT, length,
+                                   iv, iv_len, add, add_len,
+                                   input, output, tag_len, check_tag ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    /* Check tag in "constant-time" */
+    for( diff = 0, i = 0; i < tag_len; i++ )
+        diff |= tag[i] ^ check_tag[i];
+
+    if( diff != 0 )
+    {
+        memset( output, 0, length );
+        return( POLARSSL_ERR_GCM_AUTH_FAILED );
+    }
+
+    return( 0 );
+}
+
+void gcm_free( gcm_context *ctx )
+{
+    (void) cipher_free_ctx( &ctx->cipher_ctx );
+    memset( ctx, 0, sizeof( gcm_context ) );
+}
+
+#if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_AES_C)
+
+#include <stdio.h>
+
+/*
+ * AES-GCM test vectors from:
+ *
+ * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
+ */
+#define MAX_TESTS   6
+
+int key_index[MAX_TESTS] =
+    { 0, 0, 1, 1, 1, 1 };
+
+unsigned char key[MAX_TESTS][32] =
+{
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+      0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+      0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+      0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
+};
+
+size_t iv_len[MAX_TESTS] =
+    { 12, 12, 12, 12, 8, 60 };
+
+int iv_index[MAX_TESTS] =
+    { 0, 0, 1, 1, 1, 2 };
+
+unsigned char iv[MAX_TESTS][64] =
+{
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00 },
+    { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+      0xde, 0xca, 0xf8, 0x88 },
+    { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
+      0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
+      0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
+      0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
+      0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
+      0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
+      0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
+      0xa6, 0x37, 0xb3, 0x9b },
+};
+
+size_t add_len[MAX_TESTS] =
+    { 0, 0, 0, 20, 20, 20 };
+
+int add_index[MAX_TESTS] =
+    { 0, 0, 0, 1, 1, 1 };
+
+unsigned char additional[MAX_TESTS][64] =
+{
+    { 0x00 },
+    { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+      0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+      0xab, 0xad, 0xda, 0xd2 },
+};
+
+size_t pt_len[MAX_TESTS] =
+    { 0, 16, 64, 60, 60, 60 };
+
+int pt_index[MAX_TESTS] =
+    { 0, 0, 1, 1, 1, 1 };
+
+unsigned char pt[MAX_TESTS][64] =
+{
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+      0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+      0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+      0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+      0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+      0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+      0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+      0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
+};
+
+unsigned char ct[MAX_TESTS * 3][64] =
+{
+    { 0x00 },
+    { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
+      0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
+    { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
+      0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
+      0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
+      0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
+      0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
+      0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
+      0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
+      0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
+    { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
+      0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
+      0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
+      0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
+      0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
+      0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
+      0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
+      0x3d, 0x58, 0xe0, 0x91 },
+    { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
+      0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
+      0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
+      0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
+      0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
+      0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
+      0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
+      0xc2, 0x3f, 0x45, 0x98 },
+    { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
+      0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
+      0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
+      0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
+      0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
+      0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
+      0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
+      0x4c, 0x34, 0xae, 0xe5 },
+    { 0x00 },
+    { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
+      0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
+    { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
+      0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
+      0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
+      0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
+      0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
+      0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
+      0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
+      0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
+    { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
+      0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
+      0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
+      0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
+      0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
+      0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
+      0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
+      0xcc, 0xda, 0x27, 0x10 },
+    { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
+      0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
+      0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
+      0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
+      0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
+      0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
+      0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
+      0xa0, 0xf0, 0x62, 0xf7 },
+    { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
+      0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
+      0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
+      0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
+      0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
+      0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
+      0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
+      0xe9, 0xb7, 0x37, 0x3b },
+    { 0x00 },
+    { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
+      0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
+    { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
+      0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
+      0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
+      0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
+      0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
+      0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
+      0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
+      0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
+    { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
+      0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
+      0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
+      0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
+      0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
+      0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
+      0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
+      0xbc, 0xc9, 0xf6, 0x62 },
+    { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
+      0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
+      0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
+      0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
+      0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
+      0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
+      0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
+      0xf4, 0x7c, 0x9b, 0x1f },
+    { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
+      0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
+      0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
+      0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
+      0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
+      0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
+      0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
+      0x44, 0xae, 0x7e, 0x3f },
+};
+
+unsigned char tag[MAX_TESTS * 3][16] =
+{
+    { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
+      0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
+    { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
+      0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
+    { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
+      0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
+    { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
+      0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
+    { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
+      0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
+    { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
+      0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
+    { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
+      0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
+    { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
+      0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
+    { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
+      0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
+    { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
+      0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
+    { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
+      0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
+    { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
+      0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
+    { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
+      0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
+    { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
+      0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
+    { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
+      0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
+    { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
+      0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
+    { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
+      0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
+    { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
+      0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
+};
+
+int gcm_self_test( int verbose )
+{
+    gcm_context ctx;
+    unsigned char buf[64];
+    unsigned char tag_buf[16];
+    int i, j, ret;
+    cipher_id_t cipher = POLARSSL_CIPHER_ID_AES;
+
+    for( j = 0; j < 3; j++ )
+    {
+        int key_len = 128 + 64 * j;
+
+        for( i = 0; i < MAX_TESTS; i++ )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "  AES-GCM-%3d #%d (%s): ",
+                                 key_len, i, "enc" );
+
+            gcm_init( &ctx, cipher, key[key_index[i]], key_len );
+
+            ret = gcm_crypt_and_tag( &ctx, GCM_ENCRYPT,
+                                     pt_len[i],
+                                     iv[iv_index[i]], iv_len[i],
+                                     additional[add_index[i]], add_len[i],
+                                     pt[pt_index[i]], buf, 16, tag_buf );
+
+            if( ret != 0 ||
+                memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
+                memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
+            {
+                if( verbose != 0 )
+                    polarssl_printf( "failed\n" );
+
+                return( 1 );
+            }
+
+            gcm_free( &ctx );
+
+            if( verbose != 0 )
+                polarssl_printf( "passed\n" );
+
+            if( verbose != 0 )
+                polarssl_printf( "  AES-GCM-%3d #%d (%s): ",
+                                 key_len, i, "dec" );
+
+            gcm_init( &ctx, cipher, key[key_index[i]], key_len );
+
+            ret = gcm_crypt_and_tag( &ctx, GCM_DECRYPT,
+                                     pt_len[i],
+                                     iv[iv_index[i]], iv_len[i],
+                                     additional[add_index[i]], add_len[i],
+                                     ct[j * 6 + i], buf, 16, tag_buf );
+
+            if( ret != 0 ||
+                memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
+                memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
+            {
+                if( verbose != 0 )
+                    polarssl_printf( "failed\n" );
+
+                return( 1 );
+            }
+
+            gcm_free( &ctx );
+
+            if( verbose != 0 )
+                polarssl_printf( "passed\n" );
+
+            if( verbose != 0 )
+                polarssl_printf( "  AES-GCM-%3d #%d split (%s): ",
+                                 key_len, i, "enc" );
+
+            gcm_init( &ctx, cipher, key[key_index[i]], key_len );
+
+            ret = gcm_starts( &ctx, GCM_ENCRYPT,
+                              iv[iv_index[i]], iv_len[i],
+                              additional[add_index[i]], add_len[i] );
+            if( ret != 0 )
+            {
+                if( verbose != 0 )
+                    polarssl_printf( "failed\n" );
+
+                return( 1 );
+            }
+
+            if( pt_len[i] > 32 )
+            {
+                size_t rest_len = pt_len[i] - 32;
+                ret = gcm_update( &ctx, 32, pt[pt_index[i]], buf );
+                if( ret != 0 )
+                {
+                    if( verbose != 0 )
+                        polarssl_printf( "failed\n" );
+
+                    return( 1 );
+                }
+
+                ret = gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32,
+                                  buf + 32 );
+                if( ret != 0 )
+                {
+                    if( verbose != 0 )
+                        polarssl_printf( "failed\n" );
+
+                    return( 1 );
+                }
+            }
+            else
+            {
+                ret = gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf );
+                if( ret != 0 )
+                {
+                    if( verbose != 0 )
+                        polarssl_printf( "failed\n" );
+
+                    return( 1 );
+                }
+            }
+
+            ret = gcm_finish( &ctx, tag_buf, 16 );
+            if( ret != 0 ||
+                memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
+                memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
+            {
+                if( verbose != 0 )
+                    polarssl_printf( "failed\n" );
+
+                return( 1 );
+            }
+
+            gcm_free( &ctx );
+
+            if( verbose != 0 )
+                polarssl_printf( "passed\n" );
+
+            if( verbose != 0 )
+                polarssl_printf( "  AES-GCM-%3d #%d split (%s): ",
+                                 key_len, i, "dec" );
+
+            gcm_init( &ctx, cipher, key[key_index[i]], key_len );
+
+            ret = gcm_starts( &ctx, GCM_DECRYPT,
+                              iv[iv_index[i]], iv_len[i],
+                              additional[add_index[i]], add_len[i] );
+            if( ret != 0 )
+            {
+                if( verbose != 0 )
+                    polarssl_printf( "failed\n" );
+
+                return( 1 );
+            }
+
+            if( pt_len[i] > 32 )
+            {
+                size_t rest_len = pt_len[i] - 32;
+                ret = gcm_update( &ctx, 32, ct[j * 6 + i], buf );
+                if( ret != 0 )
+                {
+                    if( verbose != 0 )
+                        polarssl_printf( "failed\n" );
+
+                    return( 1 );
+                }
+
+                ret = gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32,
+                                  buf + 32 );
+                if( ret != 0 )
+                {
+                    if( verbose != 0 )
+                        polarssl_printf( "failed\n" );
+
+                    return( 1 );
+                }
+            }
+            else
+            {
+                ret = gcm_update( &ctx, pt_len[i], ct[j * 6 + i], buf );
+                if( ret != 0 )
+                {
+                    if( verbose != 0 )
+                        polarssl_printf( "failed\n" );
+
+                    return( 1 );
+                }
+            }
+
+            ret = gcm_finish( &ctx, tag_buf, 16 );
+            if( ret != 0 ||
+                memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
+                memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
+            {
+                if( verbose != 0 )
+                    polarssl_printf( "failed\n" );
+
+                return( 1 );
+            }
+
+            gcm_free( &ctx );
+
+            if( verbose != 0 )
+                polarssl_printf( "passed\n" );
+
+        }
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+    return( 0 );
+}
+
+
+
+#endif /* POLARSSL_SELF_TEST && POLARSSL_AES_C */
+
+#endif /* POLARSSL_GCM_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/havege.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,236 @@
+/**
+ *  \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  The HAVEGE RNG was designed by Andre Seznec in 2002.
+ *
+ *  http://www.irisa.fr/caps/projects/hipsor/publi.php
+ *
+ *  Contact: seznec(at)irisa_dot_fr - orocheco(at)irisa_dot_fr
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_HAVEGE_C)
+
+#include "polarssl/havege.h"
+#include "polarssl/timing.h"
+
+#include <string.h>
+
+/* ------------------------------------------------------------------------
+ * On average, one iteration accesses two 8-word blocks in the havege WALK
+ * table, and generates 16 words in the RES array.
+ *
+ * The data read in the WALK table is updated and permuted after each use.
+ * The result of the hardware clock counter read is used  for this update.
+ *
+ * 25 conditional tests are present.  The conditional tests are grouped in
+ * two nested  groups of 12 conditional tests and 1 test that controls the
+ * permutation; on average, there should be 6 tests executed and 3 of them
+ * should be mispredicted.
+ * ------------------------------------------------------------------------
+ */
+
+#define SWAP(X,Y) { int *T = X; X = Y; Y = T; }
+
+#define TST1_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1;
+#define TST2_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1;
+
+#define TST1_LEAVE U1++; }
+#define TST2_LEAVE U2++; }
+
+#define ONE_ITERATION                                   \
+                                                        \
+    PTEST = PT1 >> 20;                                  \
+                                                        \
+    TST1_ENTER  TST1_ENTER  TST1_ENTER  TST1_ENTER      \
+    TST1_ENTER  TST1_ENTER  TST1_ENTER  TST1_ENTER      \
+    TST1_ENTER  TST1_ENTER  TST1_ENTER  TST1_ENTER      \
+                                                        \
+    TST1_LEAVE  TST1_LEAVE  TST1_LEAVE  TST1_LEAVE      \
+    TST1_LEAVE  TST1_LEAVE  TST1_LEAVE  TST1_LEAVE      \
+    TST1_LEAVE  TST1_LEAVE  TST1_LEAVE  TST1_LEAVE      \
+                                                        \
+    PTX = (PT1 >> 18) & 7;                              \
+    PT1 &= 0x1FFF;                                      \
+    PT2 &= 0x1FFF;                                      \
+    CLK = (int) hardclock();                            \
+                                                        \
+    i = 0;                                              \
+    A = &WALK[PT1    ]; RES[i++] ^= *A;                 \
+    B = &WALK[PT2    ]; RES[i++] ^= *B;                 \
+    C = &WALK[PT1 ^ 1]; RES[i++] ^= *C;                 \
+    D = &WALK[PT2 ^ 4]; RES[i++] ^= *D;                 \
+                                                        \
+    IN = (*A >> (1)) ^ (*A << (31)) ^ CLK;              \
+    *A = (*B >> (2)) ^ (*B << (30)) ^ CLK;              \
+    *B = IN ^ U1;                                       \
+    *C = (*C >> (3)) ^ (*C << (29)) ^ CLK;              \
+    *D = (*D >> (4)) ^ (*D << (28)) ^ CLK;              \
+                                                        \
+    A = &WALK[PT1 ^ 2]; RES[i++] ^= *A;                 \
+    B = &WALK[PT2 ^ 2]; RES[i++] ^= *B;                 \
+    C = &WALK[PT1 ^ 3]; RES[i++] ^= *C;                 \
+    D = &WALK[PT2 ^ 6]; RES[i++] ^= *D;                 \
+                                                        \
+    if( PTEST & 1 ) SWAP( A, C );                       \
+                                                        \
+    IN = (*A >> (5)) ^ (*A << (27)) ^ CLK;              \
+    *A = (*B >> (6)) ^ (*B << (26)) ^ CLK;              \
+    *B = IN; CLK = (int) hardclock();                   \
+    *C = (*C >> (7)) ^ (*C << (25)) ^ CLK;              \
+    *D = (*D >> (8)) ^ (*D << (24)) ^ CLK;              \
+                                                        \
+    A = &WALK[PT1 ^ 4];                                 \
+    B = &WALK[PT2 ^ 1];                                 \
+                                                        \
+    PTEST = PT2 >> 1;                                   \
+                                                        \
+    PT2 = (RES[(i - 8) ^ PTY] ^ WALK[PT2 ^ PTY ^ 7]);   \
+    PT2 = ((PT2 & 0x1FFF) & (~8)) ^ ((PT1 ^ 8) & 0x8);  \
+    PTY = (PT2 >> 10) & 7;                              \
+                                                        \
+    TST2_ENTER  TST2_ENTER  TST2_ENTER  TST2_ENTER      \
+    TST2_ENTER  TST2_ENTER  TST2_ENTER  TST2_ENTER      \
+    TST2_ENTER  TST2_ENTER  TST2_ENTER  TST2_ENTER      \
+                                                        \
+    TST2_LEAVE  TST2_LEAVE  TST2_LEAVE  TST2_LEAVE      \
+    TST2_LEAVE  TST2_LEAVE  TST2_LEAVE  TST2_LEAVE      \
+    TST2_LEAVE  TST2_LEAVE  TST2_LEAVE  TST2_LEAVE      \
+                                                        \
+    C = &WALK[PT1 ^ 5];                                 \
+    D = &WALK[PT2 ^ 5];                                 \
+                                                        \
+    RES[i++] ^= *A;                                     \
+    RES[i++] ^= *B;                                     \
+    RES[i++] ^= *C;                                     \
+    RES[i++] ^= *D;                                     \
+                                                        \
+    IN = (*A >> ( 9)) ^ (*A << (23)) ^ CLK;             \
+    *A = (*B >> (10)) ^ (*B << (22)) ^ CLK;             \
+    *B = IN ^ U2;                                       \
+    *C = (*C >> (11)) ^ (*C << (21)) ^ CLK;             \
+    *D = (*D >> (12)) ^ (*D << (20)) ^ CLK;             \
+                                                        \
+    A = &WALK[PT1 ^ 6]; RES[i++] ^= *A;                 \
+    B = &WALK[PT2 ^ 3]; RES[i++] ^= *B;                 \
+    C = &WALK[PT1 ^ 7]; RES[i++] ^= *C;                 \
+    D = &WALK[PT2 ^ 7]; RES[i++] ^= *D;                 \
+                                                        \
+    IN = (*A >> (13)) ^ (*A << (19)) ^ CLK;             \
+    *A = (*B >> (14)) ^ (*B << (18)) ^ CLK;             \
+    *B = IN;                                            \
+    *C = (*C >> (15)) ^ (*C << (17)) ^ CLK;             \
+    *D = (*D >> (16)) ^ (*D << (16)) ^ CLK;             \
+                                                        \
+    PT1 = ( RES[(i - 8) ^ PTX] ^                        \
+            WALK[PT1 ^ PTX ^ 7] ) & (~1);               \
+    PT1 ^= (PT2 ^ 0x10) & 0x10;                         \
+                                                        \
+    for( n++, i = 0; i < 16; i++ )                      \
+        hs->pool[n % COLLECT_SIZE] ^= RES[i];
+
+/*
+ * Entropy gathering function
+ */
+static void havege_fill( havege_state *hs )
+{
+    int i, n = 0;
+    int  U1,  U2, *A, *B, *C, *D;
+    int PT1, PT2, *WALK, RES[16];
+    int PTX, PTY, CLK, PTEST, IN;
+
+    WALK = hs->WALK;
+    PT1  = hs->PT1;
+    PT2  = hs->PT2;
+
+    PTX  = U1 = 0;
+    PTY  = U2 = 0;
+
+    memset( RES, 0, sizeof( RES ) );
+
+    while( n < COLLECT_SIZE * 4 )
+    {
+        ONE_ITERATION
+        ONE_ITERATION
+        ONE_ITERATION
+        ONE_ITERATION
+    }
+
+    hs->PT1 = PT1;
+    hs->PT2 = PT2;
+
+    hs->offset[0] = 0;
+    hs->offset[1] = COLLECT_SIZE / 2;
+}
+
+/*
+ * HAVEGE initialization
+ */
+void havege_init( havege_state *hs )
+{
+    memset( hs, 0, sizeof( havege_state ) );
+
+    havege_fill( hs );
+}
+
+/*
+ * HAVEGE rand function
+ */
+int havege_random( void *p_rng, unsigned char *buf, size_t len )
+{
+    int val;
+    size_t use_len;
+    havege_state *hs = (havege_state *) p_rng;
+    unsigned char *p = buf;
+
+    while( len > 0 )
+    {
+        use_len = len;
+        if( use_len > sizeof(int) )
+            use_len = sizeof(int);
+
+        if( hs->offset[1] >= COLLECT_SIZE )
+            havege_fill( hs );
+
+        val  = hs->pool[hs->offset[0]++];
+        val ^= hs->pool[hs->offset[1]++];
+
+        memcpy( p, &val, use_len );
+
+        len -= use_len;
+        p += use_len;
+    }
+
+    return( 0 );
+}
+
+#endif /* POLARSSL_HAVEGE_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/hmac_drbg.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,495 @@
+/*
+ *  HMAC_DRBG implementation (NIST SP 800-90)
+ *
+ *  Copyright (C) 2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*
+ *  The NIST SP 800-90A DRBGs are described in the following publication.
+ *  http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
+ *  References below are based on rev. 1 (January 2012).
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_HMAC_DRBG_C)
+
+#include "polarssl/hmac_drbg.h"
+
+#if defined(POLARSSL_FS_IO)
+#include <stdio.h>
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
+/*
+ * HMAC_DRBG update, using optional additional data (10.1.2.2)
+ */
+void hmac_drbg_update( hmac_drbg_context *ctx,
+                       const unsigned char *additional, size_t add_len )
+{
+    size_t md_len = ctx->md_ctx.md_info->size;
+    unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
+    unsigned char sep[1];
+    unsigned char K[POLARSSL_MD_MAX_SIZE];
+
+    for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
+    {
+        /* Step 1 or 4 */
+        md_hmac_reset( &ctx->md_ctx );
+        md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
+        md_hmac_update( &ctx->md_ctx, sep, 1 );
+        if( rounds == 2 )
+            md_hmac_update( &ctx->md_ctx, additional, add_len );
+        md_hmac_finish( &ctx->md_ctx, K );
+
+        /* Step 2 or 5 */
+        md_hmac_starts( &ctx->md_ctx, K, md_len );
+        md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
+        md_hmac_finish( &ctx->md_ctx, ctx->V );
+    }
+}
+
+/*
+ * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
+ */
+int hmac_drbg_init_buf( hmac_drbg_context *ctx,
+                        const md_info_t * md_info,
+                        const unsigned char *data, size_t data_len )
+{
+    int ret;
+
+    memset( ctx, 0, sizeof( hmac_drbg_context ) );
+
+    if( ( ret = md_init_ctx( &ctx->md_ctx, md_info ) ) != 0 )
+        return( ret );
+
+    /*
+     * Set initial working state.
+     * Use the V memory location, which is currently all 0, to initialize the
+     * MD context with an all-zero key. Then set V to its initial value.
+     */
+    md_hmac_starts( &ctx->md_ctx, ctx->V, md_info->size );
+    memset( ctx->V, 0x01, md_info->size );
+
+    hmac_drbg_update( ctx, data, data_len );
+
+    return( 0 );
+}
+
+/*
+ * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman)
+ */
+int hmac_drbg_reseed( hmac_drbg_context *ctx,
+                      const unsigned char *additional, size_t len )
+{
+    unsigned char seed[POLARSSL_HMAC_DRBG_MAX_SEED_INPUT];
+    size_t seedlen;
+
+    /* III. Check input length */
+    if( len > POLARSSL_HMAC_DRBG_MAX_INPUT ||
+        ctx->entropy_len + len > POLARSSL_HMAC_DRBG_MAX_SEED_INPUT )
+    {
+        return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
+    }
+
+    memset( seed, 0, POLARSSL_HMAC_DRBG_MAX_SEED_INPUT );
+
+    /* IV. Gather entropy_len bytes of entropy for the seed */
+    if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 )
+        return( POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
+
+    seedlen = ctx->entropy_len;
+
+    /* 1. Concatenate entropy and additional data if any */
+    if( additional != NULL && len != 0 )
+    {
+        memcpy( seed + seedlen, additional, len );
+        seedlen += len;
+    }
+
+    /* 2. Update state */
+    hmac_drbg_update( ctx, seed, seedlen );
+
+    /* 3. Reset reseed_counter */
+    ctx->reseed_counter = 1;
+
+    /* 4. Done */
+    return( 0 );
+}
+
+/*
+ * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
+ */
+int hmac_drbg_init( hmac_drbg_context *ctx,
+                    const md_info_t * md_info,
+                    int (*f_entropy)(void *, unsigned char *, size_t),
+                    void *p_entropy,
+                    const unsigned char *custom,
+                    size_t len )
+{
+    int ret;
+    size_t entropy_len;
+
+    memset( ctx, 0, sizeof( hmac_drbg_context ) );
+
+    if( ( ret = md_init_ctx( &ctx->md_ctx, md_info ) ) != 0 )
+        return( ret );
+
+    /*
+     * Set initial working state.
+     * Use the V memory location, which is currently all 0, to initialize the
+     * MD context with an all-zero key. Then set V to its initial value.
+     */
+    md_hmac_starts( &ctx->md_ctx, ctx->V, md_info->size );
+    memset( ctx->V, 0x01, md_info->size );
+
+    ctx->f_entropy = f_entropy;
+    ctx->p_entropy = p_entropy;
+
+    ctx->reseed_interval = POLARSSL_HMAC_DRBG_RESEED_INTERVAL;
+
+    /*
+     * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
+     * each hash function, then according to SP800-90A rev1 10.1 table 2,
+     * min_entropy_len (in bits) is security_strength.
+     *
+     * (This also matches the sizes used in the NIST test vectors.)
+     */
+    entropy_len = md_info->size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
+                  md_info->size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
+                                        32;  /* better (256+) -> 256 bits */
+
+    /*
+     * For initialisation, use more entropy to emulate a nonce
+     * (Again, matches test vectors.)
+     */
+    ctx->entropy_len = entropy_len * 3 / 2;
+
+    if( ( ret = hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
+        return( ret );
+
+    ctx->entropy_len = entropy_len;
+
+    return( 0 );
+}
+
+/*
+ * Set prediction resistance
+ */
+void hmac_drbg_set_prediction_resistance( hmac_drbg_context *ctx,
+                                          int resistance )
+{
+    ctx->prediction_resistance = resistance;
+}
+
+/*
+ * Set entropy length grabbed for reseeds
+ */
+void hmac_drbg_set_entropy_len( hmac_drbg_context *ctx, size_t len )
+{
+    ctx->entropy_len = len;
+}
+
+/*
+ * Set reseed interval
+ */
+void hmac_drbg_set_reseed_interval( hmac_drbg_context *ctx, int interval )
+{
+    ctx->reseed_interval = interval;
+}
+
+/*
+ * HMAC_DRBG random function with optional additional data:
+ * 10.1.2.5 (arabic) + 9.3 (Roman)
+ */
+int hmac_drbg_random_with_add( void *p_rng,
+                               unsigned char *output, size_t out_len,
+                               const unsigned char *additional, size_t add_len )
+{
+    int ret;
+    hmac_drbg_context *ctx = (hmac_drbg_context *) p_rng;
+    size_t md_len = md_get_size( ctx->md_ctx.md_info );
+    size_t left = out_len;
+    unsigned char *out = output;
+
+    /* II. Check request length */
+    if( out_len > POLARSSL_HMAC_DRBG_MAX_REQUEST )
+        return( POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
+
+    /* III. Check input length */
+    if( add_len > POLARSSL_HMAC_DRBG_MAX_INPUT )
+        return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
+
+    /* 1. (aka VII and IX) Check reseed counter and PR */
+    if( ctx->f_entropy != NULL && /* For no-reseeding instances */
+        ( ctx->prediction_resistance == POLARSSL_HMAC_DRBG_PR_ON ||
+          ctx->reseed_counter > ctx->reseed_interval ) )
+    {
+        if( ( ret = hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
+            return( ret );
+
+        add_len = 0; /* VII.4 */
+    }
+
+    /* 2. Use additional data if any */
+    if( additional != NULL && add_len != 0 )
+        hmac_drbg_update( ctx, additional, add_len );
+
+    /* 3, 4, 5. Generate bytes */
+    while( left != 0 )
+    {
+        size_t use_len = left > md_len ? md_len : left;
+
+        md_hmac_reset( &ctx->md_ctx );
+        md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
+        md_hmac_finish( &ctx->md_ctx, ctx->V );
+
+        memcpy( out, ctx->V, use_len );
+        out += use_len;
+        left -= use_len;
+    }
+
+    /* 6. Update */
+    hmac_drbg_update( ctx, additional, add_len );
+
+    /* 7. Update reseed counter */
+    ctx->reseed_counter++;
+
+    /* 8. Done */
+    return( 0 );
+}
+
+/*
+ * HMAC_DRBG random function
+ */
+int hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
+{
+    return( hmac_drbg_random_with_add( p_rng, output, out_len, NULL, 0 ) );
+}
+
+/*
+ * Free an HMAC_DRBG context
+ */
+void hmac_drbg_free( hmac_drbg_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    md_free_ctx( &ctx->md_ctx );
+
+    memset( ctx, 0, sizeof( hmac_drbg_context ) );
+}
+
+#if defined(POLARSSL_FS_IO)
+int hmac_drbg_write_seed_file( hmac_drbg_context *ctx, const char *path )
+{
+    int ret;
+    FILE *f;
+    unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ];
+
+    if( ( f = fopen( path, "wb" ) ) == NULL )
+        return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
+
+    if( ( ret = hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
+        goto exit;
+
+    if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
+    {
+        ret = POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR;
+        goto exit;
+    }
+
+    ret = 0;
+
+exit:
+    fclose( f );
+    return( ret );
+}
+
+int hmac_drbg_update_seed_file( hmac_drbg_context *ctx, const char *path )
+{
+    FILE *f;
+    size_t n;
+    unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ];
+
+    if( ( f = fopen( path, "rb" ) ) == NULL )
+        return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
+
+    fseek( f, 0, SEEK_END );
+    n = (size_t) ftell( f );
+    fseek( f, 0, SEEK_SET );
+
+    if( n > POLARSSL_HMAC_DRBG_MAX_INPUT )
+    {
+        fclose( f );
+        return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
+    }
+
+    if( fread( buf, 1, n, f ) != n )
+    {
+        fclose( f );
+        return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
+    }
+
+    fclose( f );
+
+    hmac_drbg_update( ctx, buf, n );
+
+    return( hmac_drbg_write_seed_file( ctx, path ) );
+}
+#endif /* POLARSSL_FS_IO */
+
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include <stdio.h>
+
+#if !defined(POLARSSL_SHA1_C)
+/* Dummy checkup routine */
+int hmac_drbg_self_test( int verbose )
+{
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+    return( 0 );
+}
+#else
+
+#define OUTPUT_LEN  80
+
+/* From a NIST PR=true test vector */
+static unsigned char entropy_pr[] = {
+    0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
+    0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
+    0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
+    0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
+    0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
+static const unsigned char result_pr[OUTPUT_LEN] = {
+    0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
+    0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
+    0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
+    0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
+    0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
+    0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
+    0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
+
+/* From a NIST PR=false test vector */
+static unsigned char entropy_nopr[] = {
+    0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
+    0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
+    0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
+    0xe9, 0x9d, 0xfe, 0xdf };
+static const unsigned char result_nopr[OUTPUT_LEN] = {
+    0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
+    0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
+    0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
+    0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
+    0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
+    0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
+    0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
+
+/* "Entropy" from buffer */
+static size_t test_offset;
+static int hmac_drbg_self_test_entropy( void *data,
+                                        unsigned char *buf, size_t len )
+{
+    const unsigned char *p = data;
+    memcpy( buf, p + test_offset, len );
+    test_offset += len;
+    return( 0 );
+}
+
+#define CHK( c )    if( (c) != 0 )                          \
+                    {                                       \
+                        if( verbose != 0 )                  \
+                            polarssl_printf( "failed\n" );  \
+                        return( 1 );                        \
+                    }
+
+/*
+ * Checkup routine for HMAC_DRBG with SHA-1
+ */
+int hmac_drbg_self_test( int verbose )
+{
+    hmac_drbg_context ctx;
+    unsigned char buf[OUTPUT_LEN];
+    const md_info_t *md_info = md_info_from_type( POLARSSL_MD_SHA1 );
+
+    /*
+     * PR = True
+     */
+    if( verbose != 0 )
+        polarssl_printf( "  HMAC_DRBG (PR = True) : " );
+
+    test_offset = 0;
+    CHK( hmac_drbg_init( &ctx, md_info,
+                         hmac_drbg_self_test_entropy, entropy_pr,
+                         NULL, 0 ) );
+    hmac_drbg_set_prediction_resistance( &ctx, POLARSSL_HMAC_DRBG_PR_ON );
+    CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
+    CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
+    CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
+    hmac_drbg_free( &ctx );
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n" );
+
+    /*
+     * PR = False
+     */
+    if( verbose != 0 )
+        polarssl_printf( "  HMAC_DRBG (PR = False) : " );
+
+    test_offset = 0;
+    CHK( hmac_drbg_init( &ctx, md_info,
+                         hmac_drbg_self_test_entropy, entropy_nopr,
+                         NULL, 0 ) );
+    CHK( hmac_drbg_reseed( &ctx, NULL, 0 ) );
+    CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
+    CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
+    CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
+    hmac_drbg_free( &ctx );
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n" );
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+    return( 0 );
+}
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_HMAC_DRBG_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/md.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,326 @@
+/**
+ * \file md.c
+ *
+ * \brief Generic message digest wrapper for PolarSSL
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_MD_C)
+
+#include "polarssl/md.h"
+#include "polarssl/md_wrap.h"
+
+#include <stdlib.h>
+
+#if defined(_MSC_VER) && !defined strcasecmp && !defined(EFIX64) && \
+    !defined(EFI32)
+#define strcasecmp  _stricmp
+#endif
+
+static const int supported_digests[] = {
+
+#if defined(POLARSSL_MD2_C)
+        POLARSSL_MD_MD2,
+#endif
+
+#if defined(POLARSSL_MD4_C)
+        POLARSSL_MD_MD4,
+#endif
+
+#if defined(POLARSSL_MD5_C)
+        POLARSSL_MD_MD5,
+#endif
+
+#if defined(POLARSSL_RIPEMD160_C)
+        POLARSSL_MD_RIPEMD160,
+#endif
+
+#if defined(POLARSSL_SHA1_C)
+        POLARSSL_MD_SHA1,
+#endif
+
+#if defined(POLARSSL_SHA256_C)
+        POLARSSL_MD_SHA224,
+        POLARSSL_MD_SHA256,
+#endif
+
+#if defined(POLARSSL_SHA512_C)
+        POLARSSL_MD_SHA384,
+        POLARSSL_MD_SHA512,
+#endif
+
+        0
+};
+
+const int *md_list( void )
+{
+    return supported_digests;
+}
+
+const md_info_t *md_info_from_string( const char *md_name )
+{
+    if( NULL == md_name )
+        return NULL;
+
+    /* Get the appropriate digest information */
+#if defined(POLARSSL_MD2_C)
+    if( !strcasecmp( "MD2", md_name ) )
+        return md_info_from_type( POLARSSL_MD_MD2 );
+#endif
+#if defined(POLARSSL_MD4_C)
+    if( !strcasecmp( "MD4", md_name ) )
+        return md_info_from_type( POLARSSL_MD_MD4 );
+#endif
+#if defined(POLARSSL_MD5_C)
+    if( !strcasecmp( "MD5", md_name ) )
+        return md_info_from_type( POLARSSL_MD_MD5 );
+#endif
+#if defined(POLARSSL_RIPEMD160_C)
+    if( !strcasecmp( "RIPEMD160", md_name ) )
+        return md_info_from_type( POLARSSL_MD_RIPEMD160 );
+#endif
+#if defined(POLARSSL_SHA1_C)
+    if( !strcasecmp( "SHA1", md_name ) || !strcasecmp( "SHA", md_name ) )
+        return md_info_from_type( POLARSSL_MD_SHA1 );
+#endif
+#if defined(POLARSSL_SHA256_C)
+    if( !strcasecmp( "SHA224", md_name ) )
+        return md_info_from_type( POLARSSL_MD_SHA224 );
+    if( !strcasecmp( "SHA256", md_name ) )
+        return md_info_from_type( POLARSSL_MD_SHA256 );
+#endif
+#if defined(POLARSSL_SHA512_C)
+    if( !strcasecmp( "SHA384", md_name ) )
+        return md_info_from_type( POLARSSL_MD_SHA384 );
+    if( !strcasecmp( "SHA512", md_name ) )
+        return md_info_from_type( POLARSSL_MD_SHA512 );
+#endif
+    return NULL;
+}
+
+const md_info_t *md_info_from_type( md_type_t md_type )
+{
+    switch( md_type )
+    {
+#if defined(POLARSSL_MD2_C)
+        case POLARSSL_MD_MD2:
+            return &md2_info;
+#endif
+#if defined(POLARSSL_MD4_C)
+        case POLARSSL_MD_MD4:
+            return &md4_info;
+#endif
+#if defined(POLARSSL_MD5_C)
+        case POLARSSL_MD_MD5:
+            return &md5_info;
+#endif
+#if defined(POLARSSL_RIPEMD160_C)
+        case POLARSSL_MD_RIPEMD160:
+            return &ripemd160_info;
+#endif
+#if defined(POLARSSL_SHA1_C)
+        case POLARSSL_MD_SHA1:
+            return &sha1_info;
+#endif
+#if defined(POLARSSL_SHA256_C)
+        case POLARSSL_MD_SHA224:
+            return &sha224_info;
+        case POLARSSL_MD_SHA256:
+            return &sha256_info;
+#endif
+#if defined(POLARSSL_SHA512_C)
+        case POLARSSL_MD_SHA384:
+            return &sha384_info;
+        case POLARSSL_MD_SHA512:
+            return &sha512_info;
+#endif
+        default:
+            return NULL;
+    }
+}
+
+int md_init_ctx( md_context_t *ctx, const md_info_t *md_info )
+{
+    if( md_info == NULL || ctx == NULL )
+        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+    memset( ctx, 0, sizeof( md_context_t ) );
+
+    if( ( ctx->md_ctx = md_info->ctx_alloc_func() ) == NULL )
+        return POLARSSL_ERR_MD_ALLOC_FAILED;
+
+    ctx->md_info = md_info;
+
+    md_info->starts_func( ctx->md_ctx );
+
+    return 0;
+}
+
+int md_free_ctx( md_context_t *ctx )
+{
+    if( ctx == NULL || ctx->md_info == NULL )
+        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+    ctx->md_info->ctx_free_func( ctx->md_ctx );
+    ctx->md_ctx = NULL;
+
+    return 0;
+}
+
+int md_starts( md_context_t *ctx )
+{
+    if( ctx == NULL || ctx->md_info == NULL )
+        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+    ctx->md_info->starts_func( ctx->md_ctx );
+
+    return 0;
+}
+
+int md_update( md_context_t *ctx, const unsigned char *input, size_t ilen )
+{
+    if( ctx == NULL || ctx->md_info == NULL )
+        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+    ctx->md_info->update_func( ctx->md_ctx, input, ilen );
+
+    return 0;
+}
+
+int md_finish( md_context_t *ctx, unsigned char *output )
+{
+    if( ctx == NULL || ctx->md_info == NULL )
+        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+    ctx->md_info->finish_func( ctx->md_ctx, output );
+
+    return 0;
+}
+
+int md( const md_info_t *md_info, const unsigned char *input, size_t ilen,
+            unsigned char *output )
+{
+    if ( md_info == NULL )
+        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+    md_info->digest_func( input, ilen, output );
+
+    return 0;
+}
+
+int md_file( const md_info_t *md_info, const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+    int ret;
+#endif
+
+    if( md_info == NULL )
+        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+#if defined(POLARSSL_FS_IO)
+    ret = md_info->file_func( path, output );
+    if( ret != 0 )
+        return( POLARSSL_ERR_MD_FILE_IO_ERROR + ret );
+
+    return( ret );
+#else
+    ((void) path);
+    ((void) output);
+
+    return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif /* POLARSSL_FS_IO */
+}
+
+int md_hmac_starts( md_context_t *ctx, const unsigned char *key, size_t keylen )
+{
+    if( ctx == NULL || ctx->md_info == NULL )
+        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+    ctx->md_info->hmac_starts_func( ctx->md_ctx, key, keylen);
+
+    return 0;
+}
+
+int md_hmac_update( md_context_t *ctx, const unsigned char *input, size_t ilen )
+{
+    if( ctx == NULL || ctx->md_info == NULL )
+        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+    ctx->md_info->hmac_update_func( ctx->md_ctx, input, ilen );
+
+    return 0;
+}
+
+int md_hmac_finish( md_context_t *ctx, unsigned char *output)
+{
+    if( ctx == NULL || ctx->md_info == NULL )
+        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+    ctx->md_info->hmac_finish_func( ctx->md_ctx, output);
+
+    return 0;
+}
+
+int md_hmac_reset( md_context_t *ctx )
+{
+    if( ctx == NULL || ctx->md_info == NULL )
+        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+    ctx->md_info->hmac_reset_func( ctx->md_ctx);
+
+    return 0;
+}
+
+int md_hmac( const md_info_t *md_info, const unsigned char *key, size_t keylen,
+                const unsigned char *input, size_t ilen,
+                unsigned char *output )
+{
+    if( md_info == NULL )
+        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+    md_info->hmac_func( key, keylen, input, ilen, output );
+
+    return 0;
+}
+
+int md_process( md_context_t *ctx, const unsigned char *data )
+{
+    if( ctx == NULL || ctx->md_info == NULL )
+        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+    ctx->md_info->process_func( ctx->md_ctx, data );
+
+    return 0;
+}
+
+#endif /* POLARSSL_MD_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/md2.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,382 @@
+/*
+ *  RFC 1115/1319 compliant MD2 implementation
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  The MD2 algorithm was designed by Ron Rivest in 1989.
+ *
+ *  http://www.ietf.org/rfc/rfc1115.txt
+ *  http://www.ietf.org/rfc/rfc1319.txt
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_MD2_C)
+
+#include "polarssl/md2.h"
+
+#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
+#include <stdio.h>
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
+#if !defined(POLARSSL_MD2_ALT)
+
+static const unsigned char PI_SUBST[256] =
+{
+    0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36,
+    0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13, 0x62, 0xA7, 0x05, 0xF3,
+    0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C,
+    0x82, 0xCA, 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16,
+    0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, 0xBE, 0x4E,
+    0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E,
+    0xBB, 0x2F, 0xEE, 0x7A, 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2,
+    0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21,
+    0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E,
+    0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, 0xFF, 0x19, 0x30, 0xB3,
+    0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56,
+    0xAA, 0xC6, 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6,
+    0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, 0x45, 0x9D,
+    0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65,
+    0xE6, 0x2D, 0xA8, 0x02, 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0,
+    0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F,
+    0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C,
+    0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, 0x2C, 0x53, 0x0D, 0x6E,
+    0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81,
+    0x4D, 0x52, 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA,
+    0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A, 0x78, 0x88,
+    0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE,
+    0x3B, 0x00, 0x1D, 0x39, 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58,
+    0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A,
+    0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99,
+    0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14
+};
+
+/*
+ * MD2 context setup
+ */
+void md2_starts( md2_context *ctx )
+{
+    memset( ctx->cksum, 0, 16 );
+    memset( ctx->state, 0, 46 );
+    memset( ctx->buffer, 0, 16 );
+    ctx->left = 0;
+}
+
+void md2_process( md2_context *ctx )
+{
+    int i, j;
+    unsigned char t = 0;
+
+    for( i = 0; i < 16; i++ )
+    {
+        ctx->state[i + 16] = ctx->buffer[i];
+        ctx->state[i + 32] =
+            (unsigned char)( ctx->buffer[i] ^ ctx->state[i]);
+    }
+
+    for( i = 0; i < 18; i++ )
+    {
+        for( j = 0; j < 48; j++ )
+        {
+            ctx->state[j] = (unsigned char)
+               ( ctx->state[j] ^ PI_SUBST[t] );
+            t  = ctx->state[j];
+        }
+
+        t = (unsigned char)( t + i );
+    }
+
+    t = ctx->cksum[15];
+
+    for( i = 0; i < 16; i++ )
+    {
+        ctx->cksum[i] = (unsigned char)
+           ( ctx->cksum[i] ^ PI_SUBST[ctx->buffer[i] ^ t] );
+        t  = ctx->cksum[i];
+    }
+}
+
+/*
+ * MD2 process buffer
+ */
+void md2_update( md2_context *ctx, const unsigned char *input, size_t ilen )
+{
+    size_t fill;
+
+    while( ilen > 0 )
+    {
+        if( ctx->left + ilen > 16 )
+            fill = 16 - ctx->left;
+        else
+            fill = ilen;
+
+        memcpy( ctx->buffer + ctx->left, input, fill );
+
+        ctx->left += fill;
+        input += fill;
+        ilen  -= fill;
+
+        if( ctx->left == 16 )
+        {
+            ctx->left = 0;
+            md2_process( ctx );
+        }
+    }
+}
+
+/*
+ * MD2 final digest
+ */
+void md2_finish( md2_context *ctx, unsigned char output[16] )
+{
+    size_t i;
+    unsigned char x;
+
+    x = (unsigned char)( 16 - ctx->left );
+
+    for( i = ctx->left; i < 16; i++ )
+        ctx->buffer[i] = x;
+
+    md2_process( ctx );
+
+    memcpy( ctx->buffer, ctx->cksum, 16 );
+    md2_process( ctx );
+
+    memcpy( output, ctx->state, 16 );
+}
+
+#endif /* !POLARSSL_MD2_ALT */
+
+/*
+ * output = MD2( input buffer )
+ */
+void md2( const unsigned char *input, size_t ilen, unsigned char output[16] )
+{
+    md2_context ctx;
+
+    md2_starts( &ctx );
+    md2_update( &ctx, input, ilen );
+    md2_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( md2_context ) );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * output = MD2( file contents )
+ */
+int md2_file( const char *path, unsigned char output[16] )
+{
+    FILE *f;
+    size_t n;
+    md2_context ctx;
+    unsigned char buf[1024];
+
+    if( ( f = fopen( path, "rb" ) ) == NULL )
+        return( POLARSSL_ERR_MD2_FILE_IO_ERROR );
+
+    md2_starts( &ctx );
+
+    while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+        md2_update( &ctx, buf, n );
+
+    md2_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( md2_context ) );
+
+    if( ferror( f ) != 0 )
+    {
+        fclose( f );
+        return( POLARSSL_ERR_MD2_FILE_IO_ERROR );
+    }
+
+    fclose( f );
+    return( 0 );
+}
+#endif /* POLARSSL_FS_IO */
+
+/*
+ * MD2 HMAC context setup
+ */
+void md2_hmac_starts( md2_context *ctx, const unsigned char *key,
+                      size_t keylen )
+{
+    size_t i;
+    unsigned char sum[16];
+
+    if( keylen > 16 )
+    {
+        md2( key, keylen, sum );
+        keylen = 16;
+        key = sum;
+    }
+
+    memset( ctx->ipad, 0x36, 16 );
+    memset( ctx->opad, 0x5C, 16 );
+
+    for( i = 0; i < keylen; i++ )
+    {
+        ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
+        ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
+    }
+
+    md2_starts( ctx );
+    md2_update( ctx, ctx->ipad, 16 );
+
+    memset( sum, 0, sizeof( sum ) );
+}
+
+/*
+ * MD2 HMAC process buffer
+ */
+void md2_hmac_update( md2_context *ctx, const unsigned char *input,
+                      size_t ilen )
+{
+    md2_update( ctx, input, ilen );
+}
+
+/*
+ * MD2 HMAC final digest
+ */
+void md2_hmac_finish( md2_context *ctx, unsigned char output[16] )
+{
+    unsigned char tmpbuf[16];
+
+    md2_finish( ctx, tmpbuf );
+    md2_starts( ctx );
+    md2_update( ctx, ctx->opad, 16 );
+    md2_update( ctx, tmpbuf, 16 );
+    md2_finish( ctx, output );
+
+    memset( tmpbuf, 0, sizeof( tmpbuf ) );
+}
+
+/*
+ * MD2 HMAC context reset
+ */
+void md2_hmac_reset( md2_context *ctx )
+{
+    md2_starts( ctx );
+    md2_update( ctx, ctx->ipad, 16 );
+}
+
+/*
+ * output = HMAC-MD2( hmac key, input buffer )
+ */
+void md2_hmac( const unsigned char *key, size_t keylen,
+               const unsigned char *input, size_t ilen,
+               unsigned char output[16] )
+{
+    md2_context ctx;
+
+    md2_hmac_starts( &ctx, key, keylen );
+    md2_hmac_update( &ctx, input, ilen );
+    md2_hmac_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( md2_context ) );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+/*
+ * RFC 1319 test vectors
+ */
+static const char md2_test_str[7][81] =
+{
+    { "" },
+    { "a" },
+    { "abc" },
+    { "message digest" },
+    { "abcdefghijklmnopqrstuvwxyz" },
+    { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
+    { "12345678901234567890123456789012345678901234567890123456789012" \
+      "345678901234567890" }
+};
+
+static const unsigned char md2_test_sum[7][16] =
+{
+    { 0x83, 0x50, 0xE5, 0xA3, 0xE2, 0x4C, 0x15, 0x3D,
+      0xF2, 0x27, 0x5C, 0x9F, 0x80, 0x69, 0x27, 0x73 },
+    { 0x32, 0xEC, 0x01, 0xEC, 0x4A, 0x6D, 0xAC, 0x72,
+      0xC0, 0xAB, 0x96, 0xFB, 0x34, 0xC0, 0xB5, 0xD1 },
+    { 0xDA, 0x85, 0x3B, 0x0D, 0x3F, 0x88, 0xD9, 0x9B,
+      0x30, 0x28, 0x3A, 0x69, 0xE6, 0xDE, 0xD6, 0xBB },
+    { 0xAB, 0x4F, 0x49, 0x6B, 0xFB, 0x2A, 0x53, 0x0B,
+      0x21, 0x9F, 0xF3, 0x30, 0x31, 0xFE, 0x06, 0xB0 },
+    { 0x4E, 0x8D, 0xDF, 0xF3, 0x65, 0x02, 0x92, 0xAB,
+      0x5A, 0x41, 0x08, 0xC3, 0xAA, 0x47, 0x94, 0x0B },
+    { 0xDA, 0x33, 0xDE, 0xF2, 0xA4, 0x2D, 0xF1, 0x39,
+      0x75, 0x35, 0x28, 0x46, 0xC3, 0x03, 0x38, 0xCD },
+    { 0xD5, 0x97, 0x6F, 0x79, 0xD8, 0x3D, 0x3A, 0x0D,
+      0xC9, 0x80, 0x6C, 0x3C, 0x66, 0xF3, 0xEF, 0xD8 }
+};
+
+/*
+ * Checkup routine
+ */
+int md2_self_test( int verbose )
+{
+    int i;
+    unsigned char md2sum[16];
+
+    for( i = 0; i < 7; i++ )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "  MD2 test #%d: ", i + 1 );
+
+        md2( (unsigned char *) md2_test_str[i],
+             strlen( md2_test_str[i] ), md2sum );
+
+        if( memcmp( md2sum, md2_test_sum[i], 16 ) != 0 )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+    return( 0 );
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_MD2_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/md4.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,478 @@
+/*
+ *  RFC 1186/1320 compliant MD4 implementation
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  The MD4 algorithm was designed by Ron Rivest in 1990.
+ *
+ *  http://www.ietf.org/rfc/rfc1186.txt
+ *  http://www.ietf.org/rfc/rfc1320.txt
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_MD4_C)
+
+#include "polarssl/md4.h"
+
+#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
+#include <stdio.h>
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
+#if !defined(POLARSSL_MD4_ALT)
+
+/*
+ * 32-bit integer manipulation macros (little endian)
+ */
+#ifndef GET_UINT32_LE
+#define GET_UINT32_LE(n,b,i)                            \
+{                                                       \
+    (n) = ( (uint32_t) (b)[(i)    ]       )             \
+        | ( (uint32_t) (b)[(i) + 1] <<  8 )             \
+        | ( (uint32_t) (b)[(i) + 2] << 16 )             \
+        | ( (uint32_t) (b)[(i) + 3] << 24 );            \
+}
+#endif
+
+#ifndef PUT_UINT32_LE
+#define PUT_UINT32_LE(n,b,i)                            \
+{                                                       \
+    (b)[(i)    ] = (unsigned char) ( (n)       );       \
+    (b)[(i) + 1] = (unsigned char) ( (n) >>  8 );       \
+    (b)[(i) + 2] = (unsigned char) ( (n) >> 16 );       \
+    (b)[(i) + 3] = (unsigned char) ( (n) >> 24 );       \
+}
+#endif
+
+/*
+ * MD4 context setup
+ */
+void md4_starts( md4_context *ctx )
+{
+    ctx->total[0] = 0;
+    ctx->total[1] = 0;
+
+    ctx->state[0] = 0x67452301;
+    ctx->state[1] = 0xEFCDAB89;
+    ctx->state[2] = 0x98BADCFE;
+    ctx->state[3] = 0x10325476;
+}
+
+void md4_process( md4_context *ctx, const unsigned char data[64] )
+{
+    uint32_t X[16], A, B, C, D;
+
+    GET_UINT32_LE( X[ 0], data,  0 );
+    GET_UINT32_LE( X[ 1], data,  4 );
+    GET_UINT32_LE( X[ 2], data,  8 );
+    GET_UINT32_LE( X[ 3], data, 12 );
+    GET_UINT32_LE( X[ 4], data, 16 );
+    GET_UINT32_LE( X[ 5], data, 20 );
+    GET_UINT32_LE( X[ 6], data, 24 );
+    GET_UINT32_LE( X[ 7], data, 28 );
+    GET_UINT32_LE( X[ 8], data, 32 );
+    GET_UINT32_LE( X[ 9], data, 36 );
+    GET_UINT32_LE( X[10], data, 40 );
+    GET_UINT32_LE( X[11], data, 44 );
+    GET_UINT32_LE( X[12], data, 48 );
+    GET_UINT32_LE( X[13], data, 52 );
+    GET_UINT32_LE( X[14], data, 56 );
+    GET_UINT32_LE( X[15], data, 60 );
+
+#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
+
+    A = ctx->state[0];
+    B = ctx->state[1];
+    C = ctx->state[2];
+    D = ctx->state[3];
+
+#define F(x, y, z) ((x & y) | ((~x) & z))
+#define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); }
+
+    P( A, B, C, D, X[ 0],  3 );
+    P( D, A, B, C, X[ 1],  7 );
+    P( C, D, A, B, X[ 2], 11 );
+    P( B, C, D, A, X[ 3], 19 );
+    P( A, B, C, D, X[ 4],  3 );
+    P( D, A, B, C, X[ 5],  7 );
+    P( C, D, A, B, X[ 6], 11 );
+    P( B, C, D, A, X[ 7], 19 );
+    P( A, B, C, D, X[ 8],  3 );
+    P( D, A, B, C, X[ 9],  7 );
+    P( C, D, A, B, X[10], 11 );
+    P( B, C, D, A, X[11], 19 );
+    P( A, B, C, D, X[12],  3 );
+    P( D, A, B, C, X[13],  7 );
+    P( C, D, A, B, X[14], 11 );
+    P( B, C, D, A, X[15], 19 );
+
+#undef P
+#undef F
+
+#define F(x,y,z) ((x & y) | (x & z) | (y & z))
+#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); }
+
+    P( A, B, C, D, X[ 0],  3 );
+    P( D, A, B, C, X[ 4],  5 );
+    P( C, D, A, B, X[ 8],  9 );
+    P( B, C, D, A, X[12], 13 );
+    P( A, B, C, D, X[ 1],  3 );
+    P( D, A, B, C, X[ 5],  5 );
+    P( C, D, A, B, X[ 9],  9 );
+    P( B, C, D, A, X[13], 13 );
+    P( A, B, C, D, X[ 2],  3 );
+    P( D, A, B, C, X[ 6],  5 );
+    P( C, D, A, B, X[10],  9 );
+    P( B, C, D, A, X[14], 13 );
+    P( A, B, C, D, X[ 3],  3 );
+    P( D, A, B, C, X[ 7],  5 );
+    P( C, D, A, B, X[11],  9 );
+    P( B, C, D, A, X[15], 13 );
+
+#undef P
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); }
+
+    P( A, B, C, D, X[ 0],  3 );
+    P( D, A, B, C, X[ 8],  9 );
+    P( C, D, A, B, X[ 4], 11 );
+    P( B, C, D, A, X[12], 15 );
+    P( A, B, C, D, X[ 2],  3 );
+    P( D, A, B, C, X[10],  9 );
+    P( C, D, A, B, X[ 6], 11 );
+    P( B, C, D, A, X[14], 15 );
+    P( A, B, C, D, X[ 1],  3 );
+    P( D, A, B, C, X[ 9],  9 );
+    P( C, D, A, B, X[ 5], 11 );
+    P( B, C, D, A, X[13], 15 );
+    P( A, B, C, D, X[ 3],  3 );
+    P( D, A, B, C, X[11],  9 );
+    P( C, D, A, B, X[ 7], 11 );
+    P( B, C, D, A, X[15], 15 );
+
+#undef F
+#undef P
+
+    ctx->state[0] += A;
+    ctx->state[1] += B;
+    ctx->state[2] += C;
+    ctx->state[3] += D;
+}
+
+/*
+ * MD4 process buffer
+ */
+void md4_update( md4_context *ctx, const unsigned char *input, size_t ilen )
+{
+    size_t fill;
+    uint32_t left;
+
+    if( ilen <= 0 )
+        return;
+
+    left = ctx->total[0] & 0x3F;
+    fill = 64 - left;
+
+    ctx->total[0] += (uint32_t) ilen;
+    ctx->total[0] &= 0xFFFFFFFF;
+
+    if( ctx->total[0] < (uint32_t) ilen )
+        ctx->total[1]++;
+
+    if( left && ilen >= fill )
+    {
+        memcpy( (void *) (ctx->buffer + left),
+                (void *) input, fill );
+        md4_process( ctx, ctx->buffer );
+        input += fill;
+        ilen  -= fill;
+        left = 0;
+    }
+
+    while( ilen >= 64 )
+    {
+        md4_process( ctx, input );
+        input += 64;
+        ilen  -= 64;
+    }
+
+    if( ilen > 0 )
+    {
+        memcpy( (void *) (ctx->buffer + left),
+                (void *) input, ilen );
+    }
+}
+
+static const unsigned char md4_padding[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * MD4 final digest
+ */
+void md4_finish( md4_context *ctx, unsigned char output[16] )
+{
+    uint32_t last, padn;
+    uint32_t high, low;
+    unsigned char msglen[8];
+
+    high = ( ctx->total[0] >> 29 )
+         | ( ctx->total[1] <<  3 );
+    low  = ( ctx->total[0] <<  3 );
+
+    PUT_UINT32_LE( low,  msglen, 0 );
+    PUT_UINT32_LE( high, msglen, 4 );
+
+    last = ctx->total[0] & 0x3F;
+    padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+
+    md4_update( ctx, (unsigned char *) md4_padding, padn );
+    md4_update( ctx, msglen, 8 );
+
+    PUT_UINT32_LE( ctx->state[0], output,  0 );
+    PUT_UINT32_LE( ctx->state[1], output,  4 );
+    PUT_UINT32_LE( ctx->state[2], output,  8 );
+    PUT_UINT32_LE( ctx->state[3], output, 12 );
+}
+
+#endif /* !POLARSSL_MD4_ALT */
+
+/*
+ * output = MD4( input buffer )
+ */
+void md4( const unsigned char *input, size_t ilen, unsigned char output[16] )
+{
+    md4_context ctx;
+
+    md4_starts( &ctx );
+    md4_update( &ctx, input, ilen );
+    md4_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( md4_context ) );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * output = MD4( file contents )
+ */
+int md4_file( const char *path, unsigned char output[16] )
+{
+    FILE *f;
+    size_t n;
+    md4_context ctx;
+    unsigned char buf[1024];
+
+    if( ( f = fopen( path, "rb" ) ) == NULL )
+        return( POLARSSL_ERR_MD4_FILE_IO_ERROR );
+
+    md4_starts( &ctx );
+
+    while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+        md4_update( &ctx, buf, n );
+
+    md4_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( md4_context ) );
+
+    if( ferror( f ) != 0 )
+    {
+        fclose( f );
+        return( POLARSSL_ERR_MD4_FILE_IO_ERROR );
+    }
+
+    fclose( f );
+    return( 0 );
+}
+#endif /* POLARSSL_FS_IO */
+
+/*
+ * MD4 HMAC context setup
+ */
+void md4_hmac_starts( md4_context *ctx, const unsigned char *key,
+                      size_t keylen )
+{
+    size_t i;
+    unsigned char sum[16];
+
+    if( keylen > 64 )
+    {
+        md4( key, keylen, sum );
+        keylen = 16;
+        key = sum;
+    }
+
+    memset( ctx->ipad, 0x36, 64 );
+    memset( ctx->opad, 0x5C, 64 );
+
+    for( i = 0; i < keylen; i++ )
+    {
+        ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
+        ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
+    }
+
+    md4_starts( ctx );
+    md4_update( ctx, ctx->ipad, 64 );
+
+    memset( sum, 0, sizeof( sum ) );
+}
+
+/*
+ * MD4 HMAC process buffer
+ */
+void md4_hmac_update( md4_context *ctx, const unsigned char *input,
+                      size_t ilen )
+{
+    md4_update( ctx, input, ilen );
+}
+
+/*
+ * MD4 HMAC final digest
+ */
+void md4_hmac_finish( md4_context *ctx, unsigned char output[16] )
+{
+    unsigned char tmpbuf[16];
+
+    md4_finish( ctx, tmpbuf );
+    md4_starts( ctx );
+    md4_update( ctx, ctx->opad, 64 );
+    md4_update( ctx, tmpbuf, 16 );
+    md4_finish( ctx, output );
+
+    memset( tmpbuf, 0, sizeof( tmpbuf ) );
+}
+
+/*
+ * MD4 HMAC context reset
+ */
+void md4_hmac_reset( md4_context *ctx )
+{
+    md4_starts( ctx );
+    md4_update( ctx, ctx->ipad, 64 );
+}
+
+/*
+ * output = HMAC-MD4( hmac key, input buffer )
+ */
+void md4_hmac( const unsigned char *key, size_t keylen,
+               const unsigned char *input, size_t ilen,
+               unsigned char output[16] )
+{
+    md4_context ctx;
+
+    md4_hmac_starts( &ctx, key, keylen );
+    md4_hmac_update( &ctx, input, ilen );
+    md4_hmac_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( md4_context ) );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+/*
+ * RFC 1320 test vectors
+ */
+static const char md4_test_str[7][81] =
+{
+    { "" },
+    { "a" },
+    { "abc" },
+    { "message digest" },
+    { "abcdefghijklmnopqrstuvwxyz" },
+    { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
+    { "12345678901234567890123456789012345678901234567890123456789012" \
+      "345678901234567890" }
+};
+
+static const unsigned char md4_test_sum[7][16] =
+{
+    { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
+      0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
+    { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
+      0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
+    { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
+      0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
+    { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
+      0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
+    { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
+      0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
+    { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
+      0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
+    { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
+      0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
+};
+
+/*
+ * Checkup routine
+ */
+int md4_self_test( int verbose )
+{
+    int i;
+    unsigned char md4sum[16];
+
+    for( i = 0; i < 7; i++ )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "  MD4 test #%d: ", i + 1 );
+
+        md4( (unsigned char *) md4_test_str[i],
+             strlen( md4_test_str[i] ), md4sum );
+
+        if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+    return( 0 );
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_MD4_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/md5.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,599 @@
+/*
+ *  RFC 1321 compliant MD5 implementation
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  The MD5 algorithm was designed by Ron Rivest in 1991.
+ *
+ *  http://www.ietf.org/rfc/rfc1321.txt
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_MD5_C)
+
+#include "polarssl/md5.h"
+
+#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
+#include <stdio.h>
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
+#if !defined(POLARSSL_MD5_ALT)
+
+/*
+ * 32-bit integer manipulation macros (little endian)
+ */
+#ifndef GET_UINT32_LE
+#define GET_UINT32_LE(n,b,i)                            \
+{                                                       \
+    (n) = ( (uint32_t) (b)[(i)    ]       )             \
+        | ( (uint32_t) (b)[(i) + 1] <<  8 )             \
+        | ( (uint32_t) (b)[(i) + 2] << 16 )             \
+        | ( (uint32_t) (b)[(i) + 3] << 24 );            \
+}
+#endif
+
+#ifndef PUT_UINT32_LE
+#define PUT_UINT32_LE(n,b,i)                            \
+{                                                       \
+    (b)[(i)    ] = (unsigned char) ( (n)       );       \
+    (b)[(i) + 1] = (unsigned char) ( (n) >>  8 );       \
+    (b)[(i) + 2] = (unsigned char) ( (n) >> 16 );       \
+    (b)[(i) + 3] = (unsigned char) ( (n) >> 24 );       \
+}
+#endif
+
+/*
+ * MD5 context setup
+ */
+void md5_starts( md5_context *ctx )
+{
+    ctx->total[0] = 0;
+    ctx->total[1] = 0;
+
+    ctx->state[0] = 0x67452301;
+    ctx->state[1] = 0xEFCDAB89;
+    ctx->state[2] = 0x98BADCFE;
+    ctx->state[3] = 0x10325476;
+}
+
+void md5_process( md5_context *ctx, const unsigned char data[64] )
+{
+    uint32_t X[16], A, B, C, D;
+
+    GET_UINT32_LE( X[ 0], data,  0 );
+    GET_UINT32_LE( X[ 1], data,  4 );
+    GET_UINT32_LE( X[ 2], data,  8 );
+    GET_UINT32_LE( X[ 3], data, 12 );
+    GET_UINT32_LE( X[ 4], data, 16 );
+    GET_UINT32_LE( X[ 5], data, 20 );
+    GET_UINT32_LE( X[ 6], data, 24 );
+    GET_UINT32_LE( X[ 7], data, 28 );
+    GET_UINT32_LE( X[ 8], data, 32 );
+    GET_UINT32_LE( X[ 9], data, 36 );
+    GET_UINT32_LE( X[10], data, 40 );
+    GET_UINT32_LE( X[11], data, 44 );
+    GET_UINT32_LE( X[12], data, 48 );
+    GET_UINT32_LE( X[13], data, 52 );
+    GET_UINT32_LE( X[14], data, 56 );
+    GET_UINT32_LE( X[15], data, 60 );
+
+#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
+
+#define P(a,b,c,d,k,s,t)                                \
+{                                                       \
+    a += F(b,c,d) + X[k] + t; a = S(a,s) + b;           \
+}
+
+    A = ctx->state[0];
+    B = ctx->state[1];
+    C = ctx->state[2];
+    D = ctx->state[3];
+
+#define F(x,y,z) (z ^ (x & (y ^ z)))
+
+    P( A, B, C, D,  0,  7, 0xD76AA478 );
+    P( D, A, B, C,  1, 12, 0xE8C7B756 );
+    P( C, D, A, B,  2, 17, 0x242070DB );
+    P( B, C, D, A,  3, 22, 0xC1BDCEEE );
+    P( A, B, C, D,  4,  7, 0xF57C0FAF );
+    P( D, A, B, C,  5, 12, 0x4787C62A );
+    P( C, D, A, B,  6, 17, 0xA8304613 );
+    P( B, C, D, A,  7, 22, 0xFD469501 );
+    P( A, B, C, D,  8,  7, 0x698098D8 );
+    P( D, A, B, C,  9, 12, 0x8B44F7AF );
+    P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
+    P( B, C, D, A, 11, 22, 0x895CD7BE );
+    P( A, B, C, D, 12,  7, 0x6B901122 );
+    P( D, A, B, C, 13, 12, 0xFD987193 );
+    P( C, D, A, B, 14, 17, 0xA679438E );
+    P( B, C, D, A, 15, 22, 0x49B40821 );
+
+#undef F
+
+#define F(x,y,z) (y ^ (z & (x ^ y)))
+
+    P( A, B, C, D,  1,  5, 0xF61E2562 );
+    P( D, A, B, C,  6,  9, 0xC040B340 );
+    P( C, D, A, B, 11, 14, 0x265E5A51 );
+    P( B, C, D, A,  0, 20, 0xE9B6C7AA );
+    P( A, B, C, D,  5,  5, 0xD62F105D );
+    P( D, A, B, C, 10,  9, 0x02441453 );
+    P( C, D, A, B, 15, 14, 0xD8A1E681 );
+    P( B, C, D, A,  4, 20, 0xE7D3FBC8 );
+    P( A, B, C, D,  9,  5, 0x21E1CDE6 );
+    P( D, A, B, C, 14,  9, 0xC33707D6 );
+    P( C, D, A, B,  3, 14, 0xF4D50D87 );
+    P( B, C, D, A,  8, 20, 0x455A14ED );
+    P( A, B, C, D, 13,  5, 0xA9E3E905 );
+    P( D, A, B, C,  2,  9, 0xFCEFA3F8 );
+    P( C, D, A, B,  7, 14, 0x676F02D9 );
+    P( B, C, D, A, 12, 20, 0x8D2A4C8A );
+
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+
+    P( A, B, C, D,  5,  4, 0xFFFA3942 );
+    P( D, A, B, C,  8, 11, 0x8771F681 );
+    P( C, D, A, B, 11, 16, 0x6D9D6122 );
+    P( B, C, D, A, 14, 23, 0xFDE5380C );
+    P( A, B, C, D,  1,  4, 0xA4BEEA44 );
+    P( D, A, B, C,  4, 11, 0x4BDECFA9 );
+    P( C, D, A, B,  7, 16, 0xF6BB4B60 );
+    P( B, C, D, A, 10, 23, 0xBEBFBC70 );
+    P( A, B, C, D, 13,  4, 0x289B7EC6 );
+    P( D, A, B, C,  0, 11, 0xEAA127FA );
+    P( C, D, A, B,  3, 16, 0xD4EF3085 );
+    P( B, C, D, A,  6, 23, 0x04881D05 );
+    P( A, B, C, D,  9,  4, 0xD9D4D039 );
+    P( D, A, B, C, 12, 11, 0xE6DB99E5 );
+    P( C, D, A, B, 15, 16, 0x1FA27CF8 );
+    P( B, C, D, A,  2, 23, 0xC4AC5665 );
+
+#undef F
+
+#define F(x,y,z) (y ^ (x | ~z))
+
+    P( A, B, C, D,  0,  6, 0xF4292244 );
+    P( D, A, B, C,  7, 10, 0x432AFF97 );
+    P( C, D, A, B, 14, 15, 0xAB9423A7 );
+    P( B, C, D, A,  5, 21, 0xFC93A039 );
+    P( A, B, C, D, 12,  6, 0x655B59C3 );
+    P( D, A, B, C,  3, 10, 0x8F0CCC92 );
+    P( C, D, A, B, 10, 15, 0xFFEFF47D );
+    P( B, C, D, A,  1, 21, 0x85845DD1 );
+    P( A, B, C, D,  8,  6, 0x6FA87E4F );
+    P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
+    P( C, D, A, B,  6, 15, 0xA3014314 );
+    P( B, C, D, A, 13, 21, 0x4E0811A1 );
+    P( A, B, C, D,  4,  6, 0xF7537E82 );
+    P( D, A, B, C, 11, 10, 0xBD3AF235 );
+    P( C, D, A, B,  2, 15, 0x2AD7D2BB );
+    P( B, C, D, A,  9, 21, 0xEB86D391 );
+
+#undef F
+
+    ctx->state[0] += A;
+    ctx->state[1] += B;
+    ctx->state[2] += C;
+    ctx->state[3] += D;
+}
+
+/*
+ * MD5 process buffer
+ */
+void md5_update( md5_context *ctx, const unsigned char *input, size_t ilen )
+{
+    size_t fill;
+    uint32_t left;
+
+    if( ilen <= 0 )
+        return;
+
+    left = ctx->total[0] & 0x3F;
+    fill = 64 - left;
+
+    ctx->total[0] += (uint32_t) ilen;
+    ctx->total[0] &= 0xFFFFFFFF;
+
+    if( ctx->total[0] < (uint32_t) ilen )
+        ctx->total[1]++;
+
+    if( left && ilen >= fill )
+    {
+        memcpy( (void *) (ctx->buffer + left), input, fill );
+        md5_process( ctx, ctx->buffer );
+        input += fill;
+        ilen  -= fill;
+        left = 0;
+    }
+
+    while( ilen >= 64 )
+    {
+        md5_process( ctx, input );
+        input += 64;
+        ilen  -= 64;
+    }
+
+    if( ilen > 0 )
+    {
+        memcpy( (void *) (ctx->buffer + left), input, ilen );
+    }
+}
+
+static const unsigned char md5_padding[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * MD5 final digest
+ */
+void md5_finish( md5_context *ctx, unsigned char output[16] )
+{
+    uint32_t last, padn;
+    uint32_t high, low;
+    unsigned char msglen[8];
+
+    high = ( ctx->total[0] >> 29 )
+         | ( ctx->total[1] <<  3 );
+    low  = ( ctx->total[0] <<  3 );
+
+    PUT_UINT32_LE( low,  msglen, 0 );
+    PUT_UINT32_LE( high, msglen, 4 );
+
+    last = ctx->total[0] & 0x3F;
+    padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+
+    md5_update( ctx, md5_padding, padn );
+    md5_update( ctx, msglen, 8 );
+
+    PUT_UINT32_LE( ctx->state[0], output,  0 );
+    PUT_UINT32_LE( ctx->state[1], output,  4 );
+    PUT_UINT32_LE( ctx->state[2], output,  8 );
+    PUT_UINT32_LE( ctx->state[3], output, 12 );
+}
+
+#endif /* !POLARSSL_MD5_ALT */
+
+/*
+ * output = MD5( input buffer )
+ */
+void md5( const unsigned char *input, size_t ilen, unsigned char output[16] )
+{
+    md5_context ctx;
+
+    md5_starts( &ctx );
+    md5_update( &ctx, input, ilen );
+    md5_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( md5_context ) );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * output = MD5( file contents )
+ */
+int md5_file( const char *path, unsigned char output[16] )
+{
+    FILE *f;
+    size_t n;
+    md5_context ctx;
+    unsigned char buf[1024];
+
+    if( ( f = fopen( path, "rb" ) ) == NULL )
+        return( POLARSSL_ERR_MD5_FILE_IO_ERROR );
+
+    md5_starts( &ctx );
+
+    while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+        md5_update( &ctx, buf, n );
+
+    md5_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( md5_context ) );
+
+    if( ferror( f ) != 0 )
+    {
+        fclose( f );
+        return( POLARSSL_ERR_MD5_FILE_IO_ERROR );
+    }
+
+    fclose( f );
+    return( 0 );
+}
+#endif /* POLARSSL_FS_IO */
+
+/*
+ * MD5 HMAC context setup
+ */
+void md5_hmac_starts( md5_context *ctx, const unsigned char *key,
+                      size_t keylen )
+{
+    size_t i;
+    unsigned char sum[16];
+
+    if( keylen > 64 )
+    {
+        md5( key, keylen, sum );
+        keylen = 16;
+        key = sum;
+    }
+
+    memset( ctx->ipad, 0x36, 64 );
+    memset( ctx->opad, 0x5C, 64 );
+
+    for( i = 0; i < keylen; i++ )
+    {
+        ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
+        ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
+    }
+
+    md5_starts( ctx );
+    md5_update( ctx, ctx->ipad, 64 );
+
+    memset( sum, 0, sizeof( sum ) );
+}
+
+/*
+ * MD5 HMAC process buffer
+ */
+void md5_hmac_update( md5_context *ctx, const unsigned char *input,
+                      size_t ilen )
+{
+    md5_update( ctx, input, ilen );
+}
+
+/*
+ * MD5 HMAC final digest
+ */
+void md5_hmac_finish( md5_context *ctx, unsigned char output[16] )
+{
+    unsigned char tmpbuf[16];
+
+    md5_finish( ctx, tmpbuf );
+    md5_starts( ctx );
+    md5_update( ctx, ctx->opad, 64 );
+    md5_update( ctx, tmpbuf, 16 );
+    md5_finish( ctx, output );
+
+    memset( tmpbuf, 0, sizeof( tmpbuf ) );
+}
+
+/*
+ * MD5 HMAC context reset
+ */
+void md5_hmac_reset( md5_context *ctx )
+{
+    md5_starts( ctx );
+    md5_update( ctx, ctx->ipad, 64 );
+}
+
+/*
+ * output = HMAC-MD5( hmac key, input buffer )
+ */
+void md5_hmac( const unsigned char *key, size_t keylen,
+               const unsigned char *input, size_t ilen,
+               unsigned char output[16] )
+{
+    md5_context ctx;
+
+    md5_hmac_starts( &ctx, key, keylen );
+    md5_hmac_update( &ctx, input, ilen );
+    md5_hmac_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( md5_context ) );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+/*
+ * RFC 1321 test vectors
+ */
+static unsigned char md5_test_buf[7][81] =
+{
+    { "" },
+    { "a" },
+    { "abc" },
+    { "message digest" },
+    { "abcdefghijklmnopqrstuvwxyz" },
+    { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
+    { "12345678901234567890123456789012345678901234567890123456789012" \
+      "345678901234567890" }
+};
+
+static const int md5_test_buflen[7] =
+{
+    0, 1, 3, 14, 26, 62, 80
+};
+
+static const unsigned char md5_test_sum[7][16] =
+{
+    { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04,
+      0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E },
+    { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8,
+      0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 },
+    { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0,
+      0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 },
+    { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D,
+      0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 },
+    { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00,
+      0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B },
+    { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5,
+      0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F },
+    { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55,
+      0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A }
+};
+
+/*
+ * RFC 2202 test vectors
+ */
+static unsigned char md5_hmac_test_key[7][26] =
+{
+    { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" },
+    { "Jefe" },
+    { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" },
+    { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
+      "\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
+    { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" },
+    { "" }, /* 0xAA 80 times */
+    { "" }
+};
+
+static const int md5_hmac_test_keylen[7] =
+{
+    16, 4, 16, 25, 16, 80, 80
+};
+
+static unsigned char md5_hmac_test_buf[7][74] =
+{
+    { "Hi There" },
+    { "what do ya want for nothing?" },
+    { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
+    { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
+    { "Test With Truncation" },
+    { "Test Using Larger Than Block-Size Key - Hash Key First" },
+    { "Test Using Larger Than Block-Size Key and Larger"
+      " Than One Block-Size Data" }
+};
+
+static const int md5_hmac_test_buflen[7] =
+{
+    8, 28, 50, 50, 20, 54, 73
+};
+
+static const unsigned char md5_hmac_test_sum[7][16] =
+{
+    { 0x92, 0x94, 0x72, 0x7A, 0x36, 0x38, 0xBB, 0x1C,
+      0x13, 0xF4, 0x8E, 0xF8, 0x15, 0x8B, 0xFC, 0x9D },
+    { 0x75, 0x0C, 0x78, 0x3E, 0x6A, 0xB0, 0xB5, 0x03,
+      0xEA, 0xA8, 0x6E, 0x31, 0x0A, 0x5D, 0xB7, 0x38 },
+    { 0x56, 0xBE, 0x34, 0x52, 0x1D, 0x14, 0x4C, 0x88,
+      0xDB, 0xB8, 0xC7, 0x33, 0xF0, 0xE8, 0xB3, 0xF6 },
+    { 0x69, 0x7E, 0xAF, 0x0A, 0xCA, 0x3A, 0x3A, 0xEA,
+      0x3A, 0x75, 0x16, 0x47, 0x46, 0xFF, 0xAA, 0x79 },
+    { 0x56, 0x46, 0x1E, 0xF2, 0x34, 0x2E, 0xDC, 0x00,
+      0xF9, 0xBA, 0xB9, 0x95 },
+    { 0x6B, 0x1A, 0xB7, 0xFE, 0x4B, 0xD7, 0xBF, 0x8F,
+      0x0B, 0x62, 0xE6, 0xCE, 0x61, 0xB9, 0xD0, 0xCD },
+    { 0x6F, 0x63, 0x0F, 0xAD, 0x67, 0xCD, 0xA0, 0xEE,
+      0x1F, 0xB1, 0xF5, 0x62, 0xDB, 0x3A, 0xA5, 0x3E }
+};
+
+/*
+ * Checkup routine
+ */
+int md5_self_test( int verbose )
+{
+    int i, buflen;
+    unsigned char buf[1024];
+    unsigned char md5sum[16];
+    md5_context ctx;
+
+    for( i = 0; i < 7; i++ )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "  MD5 test #%d: ", i + 1 );
+
+        md5( md5_test_buf[i], md5_test_buflen[i], md5sum );
+
+        if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+    for( i = 0; i < 7; i++ )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "  HMAC-MD5 test #%d: ", i + 1 );
+
+        if( i == 5 || i == 6 )
+        {
+            memset( buf, '\xAA', buflen = 80 );
+            md5_hmac_starts( &ctx, buf, buflen );
+        }
+        else
+            md5_hmac_starts( &ctx, md5_hmac_test_key[i],
+                                   md5_hmac_test_keylen[i] );
+
+        md5_hmac_update( &ctx, md5_hmac_test_buf[i],
+                               md5_hmac_test_buflen[i] );
+
+        md5_hmac_finish( &ctx, md5sum );
+
+        buflen = ( i == 4 ) ? 12 : 16;
+
+        if( memcmp( md5sum, md5_hmac_test_sum[i], buflen ) != 0 )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+    return( 0 );
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_MD5_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/md_wrap.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,911 @@
+/**
+ * \file md_wrap.c
+
+ * \brief Generic message digest wrapper for PolarSSL
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_MD_C)
+
+#include "polarssl/md_wrap.h"
+
+#if defined(POLARSSL_MD2_C)
+#include "polarssl/md2.h"
+#endif
+
+#if defined(POLARSSL_MD4_C)
+#include "polarssl/md4.h"
+#endif
+
+#if defined(POLARSSL_MD5_C)
+#include "polarssl/md5.h"
+#endif
+
+#if defined(POLARSSL_RIPEMD160_C)
+#include "polarssl/ripemd160.h"
+#endif
+
+#if defined(POLARSSL_SHA1_C)
+#include "polarssl/sha1.h"
+#endif
+
+#if defined(POLARSSL_SHA256_C)
+#include "polarssl/sha256.h"
+#endif
+
+#if defined(POLARSSL_SHA512_C)
+#include "polarssl/sha512.h"
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+#include <stdlib.h>
+
+#if defined(POLARSSL_MD2_C)
+
+static void md2_starts_wrap( void *ctx )
+{
+    md2_starts( (md2_context *) ctx );
+}
+
+static void md2_update_wrap( void *ctx, const unsigned char *input,
+                             size_t ilen )
+{
+    md2_update( (md2_context *) ctx, input, ilen );
+}
+
+static void md2_finish_wrap( void *ctx, unsigned char *output )
+{
+    md2_finish( (md2_context *) ctx, output );
+}
+
+static int md2_file_wrap( const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+    return md2_file( path, output );
+#else
+    ((void) path);
+    ((void) output);
+    return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+static void md2_hmac_starts_wrap( void *ctx, const unsigned char *key,
+                                  size_t keylen )
+{
+    md2_hmac_starts( (md2_context *) ctx, key, keylen );
+}
+
+static void md2_hmac_update_wrap( void *ctx, const unsigned char *input,
+                                  size_t ilen )
+{
+    md2_hmac_update( (md2_context *) ctx, input, ilen );
+}
+
+static void md2_hmac_finish_wrap( void *ctx, unsigned char *output )
+{
+    md2_hmac_finish( (md2_context *) ctx, output );
+}
+
+static void md2_hmac_reset_wrap( void *ctx )
+{
+    md2_hmac_reset( (md2_context *) ctx );
+}
+
+static void * md2_ctx_alloc( void )
+{
+    return polarssl_malloc( sizeof( md2_context ) );
+}
+
+static void md2_ctx_free( void *ctx )
+{
+    polarssl_free( ctx );
+}
+
+static void md2_process_wrap( void *ctx, const unsigned char *data )
+{
+    ((void) data);
+
+    md2_process( (md2_context *) ctx );
+}
+
+const md_info_t md2_info = {
+    POLARSSL_MD_MD2,
+    "MD2",
+    16,
+    md2_starts_wrap,
+    md2_update_wrap,
+    md2_finish_wrap,
+    md2,
+    md2_file_wrap,
+    md2_hmac_starts_wrap,
+    md2_hmac_update_wrap,
+    md2_hmac_finish_wrap,
+    md2_hmac_reset_wrap,
+    md2_hmac,
+    md2_ctx_alloc,
+    md2_ctx_free,
+    md2_process_wrap,
+};
+
+#endif /* POLARSSL_MD2_C */
+
+#if defined(POLARSSL_MD4_C)
+
+static void md4_starts_wrap( void *ctx )
+{
+    md4_starts( (md4_context *) ctx );
+}
+
+static void md4_update_wrap( void *ctx, const unsigned char *input,
+                             size_t ilen )
+{
+    md4_update( (md4_context *) ctx, input, ilen );
+}
+
+static void md4_finish_wrap( void *ctx, unsigned char *output )
+{
+    md4_finish( (md4_context *) ctx, output );
+}
+
+static int md4_file_wrap( const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+    return md4_file( path, output );
+#else
+    ((void) path);
+    ((void) output);
+    return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+static void md4_hmac_starts_wrap( void *ctx, const unsigned char *key,
+                                  size_t keylen )
+{
+    md4_hmac_starts( (md4_context *) ctx, key, keylen );
+}
+
+static void md4_hmac_update_wrap( void *ctx, const unsigned char *input,
+                                  size_t ilen )
+{
+    md4_hmac_update( (md4_context *) ctx, input, ilen );
+}
+
+static void md4_hmac_finish_wrap( void *ctx, unsigned char *output )
+{
+    md4_hmac_finish( (md4_context *) ctx, output );
+}
+
+static void md4_hmac_reset_wrap( void *ctx )
+{
+    md4_hmac_reset( (md4_context *) ctx );
+}
+
+static void *md4_ctx_alloc( void )
+{
+    return polarssl_malloc( sizeof( md4_context ) );
+}
+
+static void md4_ctx_free( void *ctx )
+{
+    polarssl_free( ctx );
+}
+
+static void md4_process_wrap( void *ctx, const unsigned char *data )
+{
+    md4_process( (md4_context *) ctx, data );
+}
+
+const md_info_t md4_info = {
+    POLARSSL_MD_MD4,
+    "MD4",
+    16,
+    md4_starts_wrap,
+    md4_update_wrap,
+    md4_finish_wrap,
+    md4,
+    md4_file_wrap,
+    md4_hmac_starts_wrap,
+    md4_hmac_update_wrap,
+    md4_hmac_finish_wrap,
+    md4_hmac_reset_wrap,
+    md4_hmac,
+    md4_ctx_alloc,
+    md4_ctx_free,
+    md4_process_wrap,
+};
+
+#endif /* POLARSSL_MD4_C */
+
+#if defined(POLARSSL_MD5_C)
+
+static void md5_starts_wrap( void *ctx )
+{
+    md5_starts( (md5_context *) ctx );
+}
+
+static void md5_update_wrap( void *ctx, const unsigned char *input,
+                             size_t ilen )
+{
+    md5_update( (md5_context *) ctx, input, ilen );
+}
+
+static void md5_finish_wrap( void *ctx, unsigned char *output )
+{
+    md5_finish( (md5_context *) ctx, output );
+}
+
+static int md5_file_wrap( const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+    return md5_file( path, output );
+#else
+    ((void) path);
+    ((void) output);
+    return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+static void md5_hmac_starts_wrap( void *ctx, const unsigned char *key,
+                                  size_t keylen )
+{
+    md5_hmac_starts( (md5_context *) ctx, key, keylen );
+}
+
+static void md5_hmac_update_wrap( void *ctx, const unsigned char *input,
+                                  size_t ilen )
+{
+    md5_hmac_update( (md5_context *) ctx, input, ilen );
+}
+
+static void md5_hmac_finish_wrap( void *ctx, unsigned char *output )
+{
+    md5_hmac_finish( (md5_context *) ctx, output );
+}
+
+static void md5_hmac_reset_wrap( void *ctx )
+{
+    md5_hmac_reset( (md5_context *) ctx );
+}
+
+static void * md5_ctx_alloc( void )
+{
+    return polarssl_malloc( sizeof( md5_context ) );
+}
+
+static void md5_ctx_free( void *ctx )
+{
+    polarssl_free( ctx );
+}
+
+static void md5_process_wrap( void *ctx, const unsigned char *data )
+{
+    md5_process( (md5_context *) ctx, data );
+}
+
+const md_info_t md5_info = {
+    POLARSSL_MD_MD5,
+    "MD5",
+    16,
+    md5_starts_wrap,
+    md5_update_wrap,
+    md5_finish_wrap,
+    md5,
+    md5_file_wrap,
+    md5_hmac_starts_wrap,
+    md5_hmac_update_wrap,
+    md5_hmac_finish_wrap,
+    md5_hmac_reset_wrap,
+    md5_hmac,
+    md5_ctx_alloc,
+    md5_ctx_free,
+    md5_process_wrap,
+};
+
+#endif /* POLARSSL_MD5_C */
+
+#if defined(POLARSSL_RIPEMD160_C)
+
+static void ripemd160_starts_wrap( void *ctx )
+{
+    ripemd160_starts( (ripemd160_context *) ctx );
+}
+
+static void ripemd160_update_wrap( void *ctx, const unsigned char *input,
+                                   size_t ilen )
+{
+    ripemd160_update( (ripemd160_context *) ctx, input, ilen );
+}
+
+static void ripemd160_finish_wrap( void *ctx, unsigned char *output )
+{
+    ripemd160_finish( (ripemd160_context *) ctx, output );
+}
+
+static int ripemd160_file_wrap( const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+    return ripemd160_file( path, output );
+#else
+    ((void) path);
+    ((void) output);
+    return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+static void ripemd160_hmac_starts_wrap( void *ctx, const unsigned char *key,
+                                        size_t keylen )
+{
+    ripemd160_hmac_starts( (ripemd160_context *) ctx, key, keylen );
+}
+
+static void ripemd160_hmac_update_wrap( void *ctx, const unsigned char *input,
+                                        size_t ilen )
+{
+    ripemd160_hmac_update( (ripemd160_context *) ctx, input, ilen );
+}
+
+static void ripemd160_hmac_finish_wrap( void *ctx, unsigned char *output )
+{
+    ripemd160_hmac_finish( (ripemd160_context *) ctx, output );
+}
+
+static void ripemd160_hmac_reset_wrap( void *ctx )
+{
+    ripemd160_hmac_reset( (ripemd160_context *) ctx );
+}
+
+static void * ripemd160_ctx_alloc( void )
+{
+    return polarssl_malloc( sizeof( ripemd160_context ) );
+}
+
+static void ripemd160_ctx_free( void *ctx )
+{
+    polarssl_free( ctx );
+}
+
+static void ripemd160_process_wrap( void *ctx, const unsigned char *data )
+{
+    ripemd160_process( (ripemd160_context *) ctx, data );
+}
+
+const md_info_t ripemd160_info = {
+    POLARSSL_MD_RIPEMD160,
+    "RIPEMD160",
+    20,
+    ripemd160_starts_wrap,
+    ripemd160_update_wrap,
+    ripemd160_finish_wrap,
+    ripemd160,
+    ripemd160_file_wrap,
+    ripemd160_hmac_starts_wrap,
+    ripemd160_hmac_update_wrap,
+    ripemd160_hmac_finish_wrap,
+    ripemd160_hmac_reset_wrap,
+    ripemd160_hmac,
+    ripemd160_ctx_alloc,
+    ripemd160_ctx_free,
+    ripemd160_process_wrap,
+};
+
+#endif /* POLARSSL_RIPEMD160_C */
+
+#if defined(POLARSSL_SHA1_C)
+
+static void sha1_starts_wrap( void *ctx )
+{
+    sha1_starts( (sha1_context *) ctx );
+}
+
+static void sha1_update_wrap( void *ctx, const unsigned char *input,
+                              size_t ilen )
+{
+    sha1_update( (sha1_context *) ctx, input, ilen );
+}
+
+static void sha1_finish_wrap( void *ctx, unsigned char *output )
+{
+    sha1_finish( (sha1_context *) ctx, output );
+}
+
+static int sha1_file_wrap( const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+    return sha1_file( path, output );
+#else
+    ((void) path);
+    ((void) output);
+    return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+static void sha1_hmac_starts_wrap( void *ctx, const unsigned char *key,
+                                   size_t keylen )
+{
+    sha1_hmac_starts( (sha1_context *) ctx, key, keylen );
+}
+
+static void sha1_hmac_update_wrap( void *ctx, const unsigned char *input,
+                                   size_t ilen )
+{
+    sha1_hmac_update( (sha1_context *) ctx, input, ilen );
+}
+
+static void sha1_hmac_finish_wrap( void *ctx, unsigned char *output )
+{
+    sha1_hmac_finish( (sha1_context *) ctx, output );
+}
+
+static void sha1_hmac_reset_wrap( void *ctx )
+{
+    sha1_hmac_reset( (sha1_context *) ctx );
+}
+
+static void * sha1_ctx_alloc( void )
+{
+    return polarssl_malloc( sizeof( sha1_context ) );
+}
+
+static void sha1_ctx_free( void *ctx )
+{
+    polarssl_free( ctx );
+}
+
+static void sha1_process_wrap( void *ctx, const unsigned char *data )
+{
+    sha1_process( (sha1_context *) ctx, data );
+}
+
+const md_info_t sha1_info = {
+    POLARSSL_MD_SHA1,
+    "SHA1",
+    20,
+    sha1_starts_wrap,
+    sha1_update_wrap,
+    sha1_finish_wrap,
+    sha1,
+    sha1_file_wrap,
+    sha1_hmac_starts_wrap,
+    sha1_hmac_update_wrap,
+    sha1_hmac_finish_wrap,
+    sha1_hmac_reset_wrap,
+    sha1_hmac,
+    sha1_ctx_alloc,
+    sha1_ctx_free,
+    sha1_process_wrap,
+};
+
+#endif /* POLARSSL_SHA1_C */
+
+/*
+ * Wrappers for generic message digests
+ */
+#if defined(POLARSSL_SHA256_C)
+
+static void sha224_starts_wrap( void *ctx )
+{
+    sha256_starts( (sha256_context *) ctx, 1 );
+}
+
+static void sha224_update_wrap( void *ctx, const unsigned char *input,
+                                size_t ilen )
+{
+    sha256_update( (sha256_context *) ctx, input, ilen );
+}
+
+static void sha224_finish_wrap( void *ctx, unsigned char *output )
+{
+    sha256_finish( (sha256_context *) ctx, output );
+}
+
+static void sha224_wrap( const unsigned char *input, size_t ilen,
+                    unsigned char *output )
+{
+    sha256( input, ilen, output, 1 );
+}
+
+static int sha224_file_wrap( const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+    return sha256_file( path, output, 1 );
+#else
+    ((void) path);
+    ((void) output);
+    return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+static void sha224_hmac_starts_wrap( void *ctx, const unsigned char *key,
+                                     size_t keylen )
+{
+    sha256_hmac_starts( (sha256_context *) ctx, key, keylen, 1 );
+}
+
+static void sha224_hmac_update_wrap( void *ctx, const unsigned char *input,
+                                     size_t ilen )
+{
+    sha256_hmac_update( (sha256_context *) ctx, input, ilen );
+}
+
+static void sha224_hmac_finish_wrap( void *ctx, unsigned char *output )
+{
+    sha256_hmac_finish( (sha256_context *) ctx, output );
+}
+
+static void sha224_hmac_reset_wrap( void *ctx )
+{
+    sha256_hmac_reset( (sha256_context *) ctx );
+}
+
+static void sha224_hmac_wrap( const unsigned char *key, size_t keylen,
+        const unsigned char *input, size_t ilen,
+        unsigned char *output )
+{
+    sha256_hmac( key, keylen, input, ilen, output, 1 );
+}
+
+static void * sha224_ctx_alloc( void )
+{
+    return polarssl_malloc( sizeof( sha256_context ) );
+}
+
+static void sha224_ctx_free( void *ctx )
+{
+    polarssl_free( ctx );
+}
+
+static void sha224_process_wrap( void *ctx, const unsigned char *data )
+{
+    sha256_process( (sha256_context *) ctx, data );
+}
+
+const md_info_t sha224_info = {
+    POLARSSL_MD_SHA224,
+    "SHA224",
+    28,
+    sha224_starts_wrap,
+    sha224_update_wrap,
+    sha224_finish_wrap,
+    sha224_wrap,
+    sha224_file_wrap,
+    sha224_hmac_starts_wrap,
+    sha224_hmac_update_wrap,
+    sha224_hmac_finish_wrap,
+    sha224_hmac_reset_wrap,
+    sha224_hmac_wrap,
+    sha224_ctx_alloc,
+    sha224_ctx_free,
+    sha224_process_wrap,
+};
+
+static void sha256_starts_wrap( void *ctx )
+{
+    sha256_starts( (sha256_context *) ctx, 0 );
+}
+
+static void sha256_update_wrap( void *ctx, const unsigned char *input,
+                                size_t ilen )
+{
+    sha256_update( (sha256_context *) ctx, input, ilen );
+}
+
+static void sha256_finish_wrap( void *ctx, unsigned char *output )
+{
+    sha256_finish( (sha256_context *) ctx, output );
+}
+
+static void sha256_wrap( const unsigned char *input, size_t ilen,
+                    unsigned char *output )
+{
+    sha256( input, ilen, output, 0 );
+}
+
+static int sha256_file_wrap( const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+    return sha256_file( path, output, 0 );
+#else
+    ((void) path);
+    ((void) output);
+    return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+static void sha256_hmac_starts_wrap( void *ctx, const unsigned char *key,
+                                     size_t keylen )
+{
+    sha256_hmac_starts( (sha256_context *) ctx, key, keylen, 0 );
+}
+
+static void sha256_hmac_update_wrap( void *ctx, const unsigned char *input,
+                                     size_t ilen )
+{
+    sha256_hmac_update( (sha256_context *) ctx, input, ilen );
+}
+
+static void sha256_hmac_finish_wrap( void *ctx, unsigned char *output )
+{
+    sha256_hmac_finish( (sha256_context *) ctx, output );
+}
+
+static void sha256_hmac_reset_wrap( void *ctx )
+{
+    sha256_hmac_reset( (sha256_context *) ctx );
+}
+
+static void sha256_hmac_wrap( const unsigned char *key, size_t keylen,
+        const unsigned char *input, size_t ilen,
+        unsigned char *output )
+{
+    sha256_hmac( key, keylen, input, ilen, output, 0 );
+}
+
+static void * sha256_ctx_alloc( void )
+{
+    return polarssl_malloc( sizeof( sha256_context ) );
+}
+
+static void sha256_ctx_free( void *ctx )
+{
+    polarssl_free( ctx );
+}
+
+static void sha256_process_wrap( void *ctx, const unsigned char *data )
+{
+    sha256_process( (sha256_context *) ctx, data );
+}
+
+const md_info_t sha256_info = {
+    POLARSSL_MD_SHA256,
+    "SHA256",
+    32,
+    sha256_starts_wrap,
+    sha256_update_wrap,
+    sha256_finish_wrap,
+    sha256_wrap,
+    sha256_file_wrap,
+    sha256_hmac_starts_wrap,
+    sha256_hmac_update_wrap,
+    sha256_hmac_finish_wrap,
+    sha256_hmac_reset_wrap,
+    sha256_hmac_wrap,
+    sha256_ctx_alloc,
+    sha256_ctx_free,
+    sha256_process_wrap,
+};
+
+#endif /* POLARSSL_SHA256_C */
+
+#if defined(POLARSSL_SHA512_C)
+
+static void sha384_starts_wrap( void *ctx )
+{
+    sha512_starts( (sha512_context *) ctx, 1 );
+}
+
+static void sha384_update_wrap( void *ctx, const unsigned char *input,
+                                size_t ilen )
+{
+    sha512_update( (sha512_context *) ctx, input, ilen );
+}
+
+static void sha384_finish_wrap( void *ctx, unsigned char *output )
+{
+    sha512_finish( (sha512_context *) ctx, output );
+}
+
+static void sha384_wrap( const unsigned char *input, size_t ilen,
+                    unsigned char *output )
+{
+    sha512( input, ilen, output, 1 );
+}
+
+static int sha384_file_wrap( const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+    return sha512_file( path, output, 1 );
+#else
+    ((void) path);
+    ((void) output);
+    return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+static void sha384_hmac_starts_wrap( void *ctx, const unsigned char *key,
+                                     size_t keylen )
+{
+    sha512_hmac_starts( (sha512_context *) ctx, key, keylen, 1 );
+}
+
+static void sha384_hmac_update_wrap( void *ctx, const unsigned char *input,
+                                     size_t ilen )
+{
+    sha512_hmac_update( (sha512_context *) ctx, input, ilen );
+}
+
+static void sha384_hmac_finish_wrap( void *ctx, unsigned char *output )
+{
+    sha512_hmac_finish( (sha512_context *) ctx, output );
+}
+
+static void sha384_hmac_reset_wrap( void *ctx )
+{
+    sha512_hmac_reset( (sha512_context *) ctx );
+}
+
+static void sha384_hmac_wrap( const unsigned char *key, size_t keylen,
+        const unsigned char *input, size_t ilen,
+        unsigned char *output )
+{
+    sha512_hmac( key, keylen, input, ilen, output, 1 );
+}
+
+static void * sha384_ctx_alloc( void )
+{
+    return polarssl_malloc( sizeof( sha512_context ) );
+}
+
+static void sha384_ctx_free( void *ctx )
+{
+    polarssl_free( ctx );
+}
+
+static void sha384_process_wrap( void *ctx, const unsigned char *data )
+{
+    sha512_process( (sha512_context *) ctx, data );
+}
+
+const md_info_t sha384_info = {
+    POLARSSL_MD_SHA384,
+    "SHA384",
+    48,
+    sha384_starts_wrap,
+    sha384_update_wrap,
+    sha384_finish_wrap,
+    sha384_wrap,
+    sha384_file_wrap,
+    sha384_hmac_starts_wrap,
+    sha384_hmac_update_wrap,
+    sha384_hmac_finish_wrap,
+    sha384_hmac_reset_wrap,
+    sha384_hmac_wrap,
+    sha384_ctx_alloc,
+    sha384_ctx_free,
+    sha384_process_wrap,
+};
+
+static void sha512_starts_wrap( void *ctx )
+{
+    sha512_starts( (sha512_context *) ctx, 0 );
+}
+
+static void sha512_update_wrap( void *ctx, const unsigned char *input,
+                                size_t ilen )
+{
+    sha512_update( (sha512_context *) ctx, input, ilen );
+}
+
+static void sha512_finish_wrap( void *ctx, unsigned char *output )
+{
+    sha512_finish( (sha512_context *) ctx, output );
+}
+
+static void sha512_wrap( const unsigned char *input, size_t ilen,
+                    unsigned char *output )
+{
+    sha512( input, ilen, output, 0 );
+}
+
+static int sha512_file_wrap( const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+    return sha512_file( path, output, 0 );
+#else
+    ((void) path);
+    ((void) output);
+    return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+static void sha512_hmac_starts_wrap( void *ctx, const unsigned char *key,
+                                     size_t keylen )
+{
+    sha512_hmac_starts( (sha512_context *) ctx, key, keylen, 0 );
+}
+
+static void sha512_hmac_update_wrap( void *ctx, const unsigned char *input,
+                                     size_t ilen )
+{
+    sha512_hmac_update( (sha512_context *) ctx, input, ilen );
+}
+
+static void sha512_hmac_finish_wrap( void *ctx, unsigned char *output )
+{
+    sha512_hmac_finish( (sha512_context *) ctx, output );
+}
+
+static void sha512_hmac_reset_wrap( void *ctx )
+{
+    sha512_hmac_reset( (sha512_context *) ctx );
+}
+
+static void sha512_hmac_wrap( const unsigned char *key, size_t keylen,
+        const unsigned char *input, size_t ilen,
+        unsigned char *output )
+{
+    sha512_hmac( key, keylen, input, ilen, output, 0 );
+}
+
+static void * sha512_ctx_alloc( void )
+{
+    return polarssl_malloc( sizeof( sha512_context ) );
+}
+
+static void sha512_ctx_free( void *ctx )
+{
+    polarssl_free( ctx );
+}
+
+static void sha512_process_wrap( void *ctx, const unsigned char *data )
+{
+    sha512_process( (sha512_context *) ctx, data );
+}
+
+const md_info_t sha512_info = {
+    POLARSSL_MD_SHA512,
+    "SHA512",
+    64,
+    sha512_starts_wrap,
+    sha512_update_wrap,
+    sha512_finish_wrap,
+    sha512_wrap,
+    sha512_file_wrap,
+    sha512_hmac_starts_wrap,
+    sha512_hmac_update_wrap,
+    sha512_hmac_finish_wrap,
+    sha512_hmac_reset_wrap,
+    sha512_hmac_wrap,
+    sha512_ctx_alloc,
+    sha512_ctx_free,
+    sha512_process_wrap,
+};
+
+#endif /* POLARSSL_SHA512_C */
+
+#endif /* POLARSSL_MD_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/memory_buffer_alloc.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,579 @@
+/*
+ *  Buffer-based memory allocator
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_MEMORY_BUFFER_ALLOC_C)
+
+#include "polarssl/memory_buffer_alloc.h"
+
+#include <string.h>
+
+#if defined(POLARSSL_MEMORY_DEBUG)
+#include <stdio.h>
+#if defined(POLARSSL_MEMORY_BACKTRACE)
+#include <execinfo.h>
+#endif
+#endif
+
+#if defined(POLARSSL_THREADING_C)
+#include "polarssl/threading.h"
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_fprintf fprintf
+#endif
+
+#define MAGIC1       0xFF00AA55
+#define MAGIC2       0xEE119966
+#define MAX_BT 20
+
+typedef struct _memory_header memory_header;
+struct _memory_header
+{
+    size_t          magic1;
+    size_t          size;
+    size_t          alloc;
+    memory_header   *prev;
+    memory_header   *next;
+    memory_header   *prev_free;
+    memory_header   *next_free;
+#if defined(POLARSSL_MEMORY_BACKTRACE)
+    char            **trace;
+    size_t          trace_count;
+#endif
+    size_t          magic2;
+};
+
+typedef struct
+{
+    unsigned char   *buf;
+    size_t          len;
+    memory_header   *first;
+    memory_header   *first_free;
+    size_t          current_alloc_size;
+    int             verify;
+#if defined(POLARSSL_MEMORY_DEBUG)
+    size_t          malloc_count;
+    size_t          free_count;
+    size_t          total_used;
+    size_t          maximum_used;
+    size_t          header_count;
+    size_t          maximum_header_count;
+#endif
+#if defined(POLARSSL_THREADING_C)
+    threading_mutex_t   mutex;
+#endif
+}
+buffer_alloc_ctx;
+
+static buffer_alloc_ctx heap;
+
+#if defined(POLARSSL_MEMORY_DEBUG)
+static void debug_header( memory_header *hdr )
+{
+#if defined(POLARSSL_MEMORY_BACKTRACE)
+    size_t i;
+#endif
+
+    polarssl_fprintf( stderr, "HDR:  PTR(%10u), PREV(%10u), NEXT(%10u), "
+                              "ALLOC(%u), SIZE(%10u)\n",
+                      (size_t) hdr, (size_t) hdr->prev, (size_t) hdr->next,
+                      hdr->alloc, hdr->size );
+    polarssl_fprintf( stderr, "      FPREV(%10u), FNEXT(%10u)\n",
+                      (size_t) hdr->prev_free, (size_t) hdr->next_free );
+
+#if defined(POLARSSL_MEMORY_BACKTRACE)
+    polarssl_fprintf( stderr, "TRACE: \n" );
+    for( i = 0; i < hdr->trace_count; i++ )
+        polarssl_fprintf( stderr, "%s\n", hdr->trace[i] );
+    polarssl_fprintf( stderr, "\n" );
+#endif
+}
+
+static void debug_chain()
+{
+    memory_header *cur = heap.first;
+
+    polarssl_fprintf( stderr, "\nBlock list\n" );
+    while( cur != NULL )
+    {
+        debug_header( cur );
+        cur = cur->next;
+    }
+
+    polarssl_fprintf( stderr, "Free list\n" );
+    cur = heap.first_free;
+
+    while( cur != NULL )
+    {
+        debug_header( cur );
+        cur = cur->next_free;
+    }
+}
+#endif /* POLARSSL_MEMORY_DEBUG */
+
+static int verify_header( memory_header *hdr )
+{
+    if( hdr->magic1 != MAGIC1 )
+    {
+#if defined(POLARSSL_MEMORY_DEBUG)
+        polarssl_fprintf( stderr, "FATAL: MAGIC1 mismatch\n" );
+#endif
+        return( 1 );
+    }
+
+    if( hdr->magic2 != MAGIC2 )
+    {
+#if defined(POLARSSL_MEMORY_DEBUG)
+        polarssl_fprintf( stderr, "FATAL: MAGIC2 mismatch\n" );
+#endif
+        return( 1 );
+    }
+
+    if( hdr->alloc > 1 )
+    {
+#if defined(POLARSSL_MEMORY_DEBUG)
+        polarssl_fprintf( stderr, "FATAL: alloc has illegal value\n" );
+#endif
+        return( 1 );
+    }
+
+    if( hdr->prev != NULL && hdr->prev == hdr->next )
+    {
+#if defined(POLARSSL_MEMORY_DEBUG)
+        polarssl_fprintf( stderr, "FATAL: prev == next\n" );
+#endif
+        return( 1 );
+    }
+
+    if( hdr->prev_free != NULL && hdr->prev_free == hdr->next_free )
+    {
+#if defined(POLARSSL_MEMORY_DEBUG)
+        polarssl_fprintf( stderr, "FATAL: prev_free == next_free\n" );
+#endif
+        return( 1 );
+    }
+
+    return( 0 );
+}
+
+static int verify_chain()
+{
+    memory_header *prv = heap.first, *cur = heap.first->next;
+
+    if( verify_header( heap.first ) != 0 )
+    {
+#if defined(POLARSSL_MEMORY_DEBUG)
+        polarssl_fprintf( stderr, "FATAL: verification of first header "
+                                  "failed\n" );
+#endif
+        return( 1 );
+    }
+
+    if( heap.first->prev != NULL )
+    {
+#if defined(POLARSSL_MEMORY_DEBUG)
+        polarssl_fprintf( stderr, "FATAL: verification failed: "
+                                  "first->prev != NULL\n" );
+#endif
+        return( 1 );
+    }
+
+    while( cur != NULL )
+    {
+        if( verify_header( cur ) != 0 )
+        {
+#if defined(POLARSSL_MEMORY_DEBUG)
+            polarssl_fprintf( stderr, "FATAL: verification of header "
+                                      "failed\n" );
+#endif
+            return( 1 );
+        }
+
+        if( cur->prev != prv )
+        {
+#if defined(POLARSSL_MEMORY_DEBUG)
+            polarssl_fprintf( stderr, "FATAL: verification failed: "
+                                      "cur->prev != prv\n" );
+#endif
+            return( 1 );
+        }
+
+        prv = cur;
+        cur = cur->next;
+    }
+
+    return( 0 );
+}
+
+static void *buffer_alloc_malloc( size_t len )
+{
+    memory_header *new, *cur = heap.first_free;
+    unsigned char *p;
+#if defined(POLARSSL_MEMORY_BACKTRACE)
+    void *trace_buffer[MAX_BT];
+    size_t trace_cnt;
+#endif
+
+    if( heap.buf == NULL || heap.first == NULL )
+        return( NULL );
+
+    if( len % POLARSSL_MEMORY_ALIGN_MULTIPLE )
+    {
+        len -= len % POLARSSL_MEMORY_ALIGN_MULTIPLE;
+        len += POLARSSL_MEMORY_ALIGN_MULTIPLE;
+    }
+
+    // Find block that fits
+    //
+    while( cur != NULL )
+    {
+        if( cur->size >= len )
+            break;
+
+        cur = cur->next_free;
+    }
+
+    if( cur == NULL )
+        return( NULL );
+
+    if( cur->alloc != 0 )
+    {
+#if defined(POLARSSL_MEMORY_DEBUG)
+        polarssl_fprintf( stderr, "FATAL: block in free_list but allocated "
+                                  "data\n" );
+#endif
+        exit( 1 );
+    }
+
+#if defined(POLARSSL_MEMORY_DEBUG)
+    heap.malloc_count++;
+#endif
+
+    // Found location, split block if > memory_header + 4 room left
+    //
+    if( cur->size - len < sizeof(memory_header) +
+                          POLARSSL_MEMORY_ALIGN_MULTIPLE )
+    {
+        cur->alloc = 1;
+
+        // Remove from free_list
+        //
+        if( cur->prev_free != NULL )
+            cur->prev_free->next_free = cur->next_free;
+        else
+            heap.first_free = cur->next_free;
+
+        if( cur->next_free != NULL )
+            cur->next_free->prev_free = cur->prev_free;
+
+        cur->prev_free = NULL;
+        cur->next_free = NULL;
+
+#if defined(POLARSSL_MEMORY_DEBUG)
+        heap.total_used += cur->size;
+        if( heap.total_used > heap.maximum_used)
+            heap.maximum_used = heap.total_used;
+#endif
+#if defined(POLARSSL_MEMORY_BACKTRACE)
+        trace_cnt = backtrace( trace_buffer, MAX_BT );
+        cur->trace = backtrace_symbols( trace_buffer, trace_cnt );
+        cur->trace_count = trace_cnt;
+#endif
+
+        if( ( heap.verify & MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 )
+            exit( 1 );
+
+        return ( (unsigned char *) cur ) + sizeof(memory_header);
+    }
+
+    p = ( (unsigned char *) cur ) + sizeof(memory_header) + len;
+    new = (memory_header *) p;
+
+    new->size = cur->size - len - sizeof(memory_header);
+    new->alloc = 0;
+    new->prev = cur;
+    new->next = cur->next;
+#if defined(POLARSSL_MEMORY_BACKTRACE)
+    new->trace = NULL;
+    new->trace_count = 0;
+#endif
+    new->magic1 = MAGIC1;
+    new->magic2 = MAGIC2;
+
+    if( new->next != NULL )
+        new->next->prev = new;
+
+    // Replace cur with new in free_list
+    //
+    new->prev_free = cur->prev_free;
+    new->next_free = cur->next_free;
+    if( new->prev_free != NULL )
+        new->prev_free->next_free = new;
+    else
+        heap.first_free = new;
+
+    if( new->next_free != NULL )
+        new->next_free->prev_free = new;
+
+    cur->alloc = 1;
+    cur->size = len;
+    cur->next = new;
+    cur->prev_free = NULL;
+    cur->next_free = NULL;
+
+#if defined(POLARSSL_MEMORY_DEBUG)
+    heap.header_count++;
+    if( heap.header_count > heap.maximum_header_count )
+        heap.maximum_header_count = heap.header_count;
+    heap.total_used += cur->size;
+    if( heap.total_used > heap.maximum_used)
+        heap.maximum_used = heap.total_used;
+#endif
+#if defined(POLARSSL_MEMORY_BACKTRACE)
+    trace_cnt = backtrace( trace_buffer, MAX_BT );
+    cur->trace = backtrace_symbols( trace_buffer, trace_cnt );
+    cur->trace_count = trace_cnt;
+#endif
+
+    if( ( heap.verify & MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 )
+        exit( 1 );
+
+    return ( (unsigned char *) cur ) + sizeof(memory_header);
+}
+
+static void buffer_alloc_free( void *ptr )
+{
+    memory_header *hdr, *old = NULL;
+    unsigned char *p = (unsigned char *) ptr;
+
+    if( ptr == NULL || heap.buf == NULL || heap.first == NULL )
+        return;
+
+    if( p < heap.buf || p > heap.buf + heap.len )
+    {
+#if defined(POLARSSL_MEMORY_DEBUG)
+        polarssl_fprintf( stderr, "FATAL: polarssl_free() outside of managed "
+                                  "space\n" );
+#endif
+        exit( 1 );
+    }
+
+    p -= sizeof(memory_header);
+    hdr = (memory_header *) p;
+
+    if( verify_header( hdr ) != 0 )
+        exit( 1 );
+
+    if( hdr->alloc != 1 )
+    {
+#if defined(POLARSSL_MEMORY_DEBUG)
+        polarssl_fprintf( stderr, "FATAL: polarssl_free() on unallocated "
+                                  "data\n" );
+#endif
+        exit( 1 );
+    }
+
+    hdr->alloc = 0;
+
+#if defined(POLARSSL_MEMORY_DEBUG)
+    heap.free_count++;
+    heap.total_used -= hdr->size;
+#endif
+
+    // Regroup with block before
+    //
+    if( hdr->prev != NULL && hdr->prev->alloc == 0 )
+    {
+#if defined(POLARSSL_MEMORY_DEBUG)
+        heap.header_count--;
+#endif
+        hdr->prev->size += sizeof(memory_header) + hdr->size;
+        hdr->prev->next = hdr->next;
+        old = hdr;
+        hdr = hdr->prev;
+
+        if( hdr->next != NULL )
+            hdr->next->prev = hdr;
+
+#if defined(POLARSSL_MEMORY_BACKTRACE)
+        free( old->trace );
+#endif
+        memset( old, 0, sizeof(memory_header) );
+    }
+
+    // Regroup with block after
+    //
+    if( hdr->next != NULL && hdr->next->alloc == 0 )
+    {
+#if defined(POLARSSL_MEMORY_DEBUG)
+        heap.header_count--;
+#endif
+        hdr->size += sizeof(memory_header) + hdr->next->size;
+        old = hdr->next;
+        hdr->next = hdr->next->next;
+
+        if( hdr->prev_free != NULL || hdr->next_free != NULL )
+        {
+            if( hdr->prev_free != NULL )
+                hdr->prev_free->next_free = hdr->next_free;
+            else
+                heap.first_free = hdr->next_free;
+
+            if( hdr->next_free != NULL )
+                hdr->next_free->prev_free = hdr->prev_free;
+        }
+
+        hdr->prev_free = old->prev_free;
+        hdr->next_free = old->next_free;
+
+        if( hdr->prev_free != NULL )
+            hdr->prev_free->next_free = hdr;
+        else
+            heap.first_free = hdr;
+
+        if( hdr->next_free != NULL )
+            hdr->next_free->prev_free = hdr;
+
+        if( hdr->next != NULL )
+            hdr->next->prev = hdr;
+
+#if defined(POLARSSL_MEMORY_BACKTRACE)
+        free( old->trace );
+#endif
+        memset( old, 0, sizeof(memory_header) );
+    }
+
+    // Prepend to free_list if we have not merged
+    // (Does not have to stay in same order as prev / next list)
+    //
+    if( old == NULL )
+    {
+        hdr->next_free = heap.first_free;
+        heap.first_free->prev_free = hdr;
+        heap.first_free = hdr;
+    }
+
+#if defined(POLARSSL_MEMORY_BACKTRACE)
+    hdr->trace = NULL;
+    hdr->trace_count = 0;
+#endif
+
+    if( ( heap.verify & MEMORY_VERIFY_FREE ) && verify_chain() != 0 )
+        exit( 1 );
+}
+
+void memory_buffer_set_verify( int verify )
+{
+    heap.verify = verify;
+}
+
+int memory_buffer_alloc_verify()
+{
+    return verify_chain();
+}
+
+#if defined(POLARSSL_MEMORY_DEBUG)
+void memory_buffer_alloc_status()
+{
+    polarssl_fprintf( stderr,
+                      "Current use: %u blocks / %u bytes, max: %u blocks / "
+                      "%u bytes (total %u bytes), malloc / free: %u / %u\n",
+                      heap.header_count, heap.total_used,
+                      heap.maximum_header_count, heap.maximum_used,
+                      heap.maximum_header_count * sizeof( memory_header )
+                      + heap.maximum_used,
+                      heap.malloc_count, heap.free_count );
+
+    if( heap.first->next == NULL )
+        polarssl_fprintf( stderr, "All memory de-allocated in stack buffer\n" );
+    else
+    {
+        polarssl_fprintf( stderr, "Memory currently allocated:\n" );
+        debug_chain();
+    }
+}
+#endif /* POLARSSL_MEMORY_DEBUG */
+
+#if defined(POLARSSL_THREADING_C)
+static void *buffer_alloc_malloc_mutexed( size_t len )
+{
+    void *buf;
+    polarssl_mutex_lock( &heap.mutex );
+    buf = buffer_alloc_malloc( len );
+    polarssl_mutex_unlock( &heap.mutex );
+    return( buf );
+}
+
+static void buffer_alloc_free_mutexed( void *ptr )
+{
+    polarssl_mutex_lock( &heap.mutex );
+    buffer_alloc_free( ptr );
+    polarssl_mutex_unlock( &heap.mutex );
+}
+#endif /* POLARSSL_THREADING_C */
+
+int memory_buffer_alloc_init( unsigned char *buf, size_t len )
+{
+    memset( &heap, 0, sizeof(buffer_alloc_ctx) );
+    memset( buf, 0, len );
+
+#if defined(POLARSSL_THREADING_C)
+    polarssl_mutex_init( &heap.mutex );
+    platform_set_malloc_free( buffer_alloc_malloc_mutexed,
+                              buffer_alloc_free_mutexed );
+#else
+    platform_set_malloc_free( buffer_alloc_malloc, buffer_alloc_free );
+#endif
+
+    heap.buf = buf;
+    heap.len = len;
+
+    heap.first = (memory_header *) buf;
+    heap.first->size = len - sizeof(memory_header);
+    heap.first->magic1 = MAGIC1;
+    heap.first->magic2 = MAGIC2;
+    heap.first_free = heap.first;
+    return( 0 );
+}
+
+void memory_buffer_alloc_free()
+{
+#if defined(POLARSSL_THREADING_C)
+    polarssl_mutex_free( &heap.mutex );
+#endif
+    memset( &heap, 0, sizeof(buffer_alloc_ctx) );
+}
+
+#endif /* POLARSSL_MEMORY_BUFFER_ALLOC_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/oid.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,686 @@
+/**
+ * \file oid.c
+ *
+ * \brief Object Identifier (OID) database
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_OID_C)
+
+#include "polarssl/oid.h"
+#include "polarssl/rsa.h"
+
+#if defined(POLARSSL_X509_USE_C) || defined(POLARSSL_X509_CREATE_C)
+#include "polarssl/x509.h"
+#endif
+
+#include <stdio.h>
+
+/*
+ * Macro to automatically add the size of #define'd OIDs
+ */
+#define ADD_LEN(s)      s, OID_SIZE(s)
+
+/*
+ * Macro to generate an internal function for oid_XXX_from_asn1() (used by
+ * the other functions)
+ */
+#define FN_OID_TYPED_FROM_ASN1( TYPE_T, NAME, LIST )                        \
+static const TYPE_T * oid_ ## NAME ## _from_asn1( const asn1_buf *oid )     \
+{                                                                           \
+    const TYPE_T *p = LIST;                                                 \
+    const oid_descriptor_t *cur = (const oid_descriptor_t *) p;             \
+    if( p == NULL || oid == NULL ) return( NULL );                          \
+    while( cur->asn1 != NULL ) {                                            \
+        if( cur->asn1_len == oid->len &&                                    \
+            memcmp( cur->asn1, oid->p, oid->len ) == 0 ) {                  \
+            return( p );                                                    \
+        }                                                                   \
+        p++;                                                                \
+        cur = (const oid_descriptor_t *) p;                                 \
+    }                                                                       \
+    return( NULL );                                                         \
+}
+
+/*
+ * Macro to generate a function for retrieving a single attribute from the
+ * descriptor of an oid_descriptor_t wrapper.
+ */
+#define FN_OID_GET_DESCRIPTOR_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \
+int FN_NAME( const asn1_buf *oid, ATTR1_TYPE * ATTR1 )                  \
+{                                                                       \
+    const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid );        \
+    if( data == NULL ) return ( POLARSSL_ERR_OID_NOT_FOUND );           \
+    *ATTR1 = data->descriptor.ATTR1;                                    \
+    return( 0 );                                                        \
+}
+
+/*
+ * Macro to generate a function for retrieving a single attribute from an
+ * oid_descriptor_t wrapper.
+ */
+#define FN_OID_GET_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \
+int FN_NAME( const asn1_buf *oid, ATTR1_TYPE * ATTR1 )                  \
+{                                                                       \
+    const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid );        \
+    if( data == NULL ) return ( POLARSSL_ERR_OID_NOT_FOUND );           \
+    *ATTR1 = data->ATTR1;                                               \
+    return( 0 );                                                        \
+}
+
+/*
+ * Macro to generate a function for retrieving two attributes from an
+ * oid_descriptor_t wrapper.
+ */
+#define FN_OID_GET_ATTR2(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1,     \
+                         ATTR2_TYPE, ATTR2)                                 \
+int FN_NAME( const asn1_buf *oid, ATTR1_TYPE * ATTR1, ATTR2_TYPE * ATTR2 )  \
+{                                                                           \
+    const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid );            \
+    if( data == NULL ) return ( POLARSSL_ERR_OID_NOT_FOUND );               \
+    *ATTR1 = data->ATTR1;                                                   \
+    *ATTR2 = data->ATTR2;                                                   \
+    return( 0 );                                                            \
+}
+
+/*
+ * Macro to generate a function for retrieving the OID based on a single
+ * attribute from a oid_descriptor_t wrapper.
+ */
+#define FN_OID_GET_OID_BY_ATTR1(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1)   \
+int FN_NAME( ATTR1_TYPE ATTR1, const char **oid, size_t *olen )             \
+{                                                                           \
+    const TYPE_T *cur = LIST;                                               \
+    while( cur->descriptor.asn1 != NULL ) {                                 \
+        if( cur->ATTR1 == ATTR1 ) {                                         \
+            *oid = cur->descriptor.asn1;                                    \
+            *olen = cur->descriptor.asn1_len;                               \
+            return( 0 );                                                    \
+        }                                                                   \
+        cur++;                                                              \
+    }                                                                       \
+    return( POLARSSL_ERR_OID_NOT_FOUND );                                   \
+}
+
+/*
+ * Macro to generate a function for retrieving the OID based on two
+ * attributes from a oid_descriptor_t wrapper.
+ */
+#define FN_OID_GET_OID_BY_ATTR2(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1,   \
+                                ATTR2_TYPE, ATTR2)                          \
+int FN_NAME( ATTR1_TYPE ATTR1, ATTR2_TYPE ATTR2, const char **oid ,         \
+             size_t *olen )                                                 \
+{                                                                           \
+    const TYPE_T *cur = LIST;                                               \
+    while( cur->descriptor.asn1 != NULL ) {                                 \
+        if( cur->ATTR1 == ATTR1 && cur->ATTR2 == ATTR2 ) {                  \
+            *oid = cur->descriptor.asn1;                                    \
+            *olen = cur->descriptor.asn1_len;                               \
+            return( 0 );                                                    \
+        }                                                                   \
+        cur++;                                                              \
+    }                                                                       \
+    return( POLARSSL_ERR_OID_NOT_FOUND );                                   \
+}
+
+/*
+ * For X520 attribute types
+ */
+typedef struct {
+    oid_descriptor_t    descriptor;
+    const char          *short_name;
+} oid_x520_attr_t;
+
+static const oid_x520_attr_t oid_x520_attr_type[] =
+{
+    {
+        { ADD_LEN( OID_AT_CN ),          "id-at-commonName",               "Common Name" },
+        "CN",
+    },
+    {
+        { ADD_LEN( OID_AT_COUNTRY ),     "id-at-countryName",              "Country" },
+        "C",
+    },
+    {
+        { ADD_LEN( OID_AT_LOCALITY ),    "id-at-locality",                 "Locality" },
+        "L",
+    },
+    {
+        { ADD_LEN( OID_AT_STATE ),       "id-at-state",                    "State" },
+        "ST",
+    },
+    {
+        { ADD_LEN( OID_AT_ORGANIZATION ),"id-at-organizationName",         "Organization" },
+        "O",
+    },
+    {
+        { ADD_LEN( OID_AT_ORG_UNIT ),    "id-at-organizationalUnitName",   "Org Unit" },
+        "OU",
+    },
+    {
+        { ADD_LEN( OID_PKCS9_EMAIL ),    "emailAddress",                   "E-mail address" },
+        "emailAddress",
+    },
+    {
+        { ADD_LEN( OID_AT_SERIAL_NUMBER ),"id-at-serialNumber",            "Serial number" },
+        "serialNumber",
+    },
+    {
+        { ADD_LEN( OID_AT_POSTAL_ADDRESS ),"id-at-postalAddress",          "Postal address" },
+        "postalAddress",
+    },
+    {
+        { ADD_LEN( OID_AT_POSTAL_CODE ), "id-at-postalCode",               "Postal code" },
+        "postalCode",
+    },
+    {
+        { ADD_LEN( OID_AT_SUR_NAME ),    "id-at-surName",                  "Surname" },
+        "SN",
+    },
+    {
+        { ADD_LEN( OID_AT_GIVEN_NAME ),  "id-at-givenName",                "Given name" },
+        "GN",
+    },
+    {
+        { ADD_LEN( OID_AT_INITIALS ),    "id-at-initials",                 "Initials" },
+        "initials",
+    },
+    {
+        { ADD_LEN( OID_AT_GENERATION_QUALIFIER ), "id-at-generationQualifier", "Generation qualifier" },
+        "generationQualifier",
+    },
+    {
+        { ADD_LEN( OID_AT_TITLE ),       "id-at-title",                    "Title" },
+        "title",
+    },
+    {
+        { ADD_LEN( OID_AT_DN_QUALIFIER ),"id-at-dnQualifier",              "Distinguished Name qualifier" },
+        "dnQualifier",
+    },
+    {
+        { ADD_LEN( OID_AT_PSEUDONYM ),   "id-at-pseudonym",                "Pseudonym" },
+        "pseudonym",
+    },
+    {
+        { ADD_LEN( OID_DOMAIN_COMPONENT ), "id-domainComponent",           "Domain component" },
+        "DC",
+    },
+    {
+        { NULL, 0, NULL, NULL },
+        NULL,
+    }
+};
+
+FN_OID_TYPED_FROM_ASN1(oid_x520_attr_t, x520_attr, oid_x520_attr_type);
+FN_OID_GET_ATTR1(oid_get_attr_short_name, oid_x520_attr_t, x520_attr, const char *, short_name);
+
+#if defined(POLARSSL_X509_USE_C) || defined(POLARSSL_X509_CREATE_C)
+/*
+ * For X509 extensions
+ */
+typedef struct {
+    oid_descriptor_t    descriptor;
+    int                 ext_type;
+} oid_x509_ext_t;
+
+static const oid_x509_ext_t oid_x509_ext[] =
+{
+    {
+        { ADD_LEN( OID_BASIC_CONSTRAINTS ),    "id-ce-basicConstraints",   "Basic Constraints" },
+        EXT_BASIC_CONSTRAINTS,
+    },
+    {
+        { ADD_LEN( OID_KEY_USAGE ),            "id-ce-keyUsage",           "Key Usage" },
+        EXT_KEY_USAGE,
+    },
+    {
+        { ADD_LEN( OID_EXTENDED_KEY_USAGE ),   "id-ce-keyUsage",           "Extended Key Usage" },
+        EXT_EXTENDED_KEY_USAGE,
+    },
+    {
+        { ADD_LEN( OID_SUBJECT_ALT_NAME ),     "id-ce-subjectAltName",     "Subject Alt Name" },
+        EXT_SUBJECT_ALT_NAME,
+    },
+    {
+        { ADD_LEN( OID_NS_CERT_TYPE ),         "id-netscape-certtype",     "Netscape Certificate Type" },
+        EXT_NS_CERT_TYPE,
+    },
+    {
+        { NULL, 0, NULL, NULL },
+        0,
+    },
+};
+
+FN_OID_TYPED_FROM_ASN1(oid_x509_ext_t, x509_ext, oid_x509_ext);
+FN_OID_GET_ATTR1(oid_get_x509_ext_type, oid_x509_ext_t, x509_ext, int, ext_type);
+
+static const oid_descriptor_t oid_ext_key_usage[] =
+{
+    { ADD_LEN( OID_SERVER_AUTH ),      "id-kp-serverAuth",      "TLS Web Server Authentication" },
+    { ADD_LEN( OID_CLIENT_AUTH ),      "id-kp-clientAuth",      "TLS Web Client Authentication" },
+    { ADD_LEN( OID_CODE_SIGNING ),     "id-kp-codeSigning",     "Code Signing" },
+    { ADD_LEN( OID_EMAIL_PROTECTION ), "id-kp-emailProtection", "E-mail Protection" },
+    { ADD_LEN( OID_TIME_STAMPING ),    "id-kp-timeStamping",    "Time Stamping" },
+    { ADD_LEN( OID_OCSP_SIGNING ),     "id-kp-OCSPSigning",     "OCSP Signing" },
+    { NULL, 0, NULL, NULL },
+};
+
+FN_OID_TYPED_FROM_ASN1(oid_descriptor_t, ext_key_usage, oid_ext_key_usage);
+FN_OID_GET_ATTR1(oid_get_extended_key_usage, oid_descriptor_t, ext_key_usage, const char *, description);
+#endif /* POLARSSL_X509_USE_C || POLARSSL_X509_CREATE_C */
+
+#if defined(POLARSSL_MD_C)
+/*
+ * For SignatureAlgorithmIdentifier
+ */
+typedef struct {
+    oid_descriptor_t    descriptor;
+    md_type_t           md_alg;
+    pk_type_t           pk_alg;
+} oid_sig_alg_t;
+
+static const oid_sig_alg_t oid_sig_alg[] =
+{
+    {
+        { ADD_LEN( OID_PKCS1_MD2 ),        "md2WithRSAEncryption",     "RSA with MD2" },
+        POLARSSL_MD_MD2,      POLARSSL_PK_RSA,
+    },
+    {
+        { ADD_LEN( OID_PKCS1_MD4 ),        "md4WithRSAEncryption",     "RSA with MD4" },
+        POLARSSL_MD_MD4,      POLARSSL_PK_RSA,
+    },
+    {
+        { ADD_LEN( OID_PKCS1_MD5 ),        "md5WithRSAEncryption",     "RSA with MD5" },
+        POLARSSL_MD_MD5,      POLARSSL_PK_RSA,
+    },
+    {
+        { ADD_LEN( OID_PKCS1_SHA1 ),       "sha-1WithRSAEncryption",   "RSA with SHA1" },
+        POLARSSL_MD_SHA1,     POLARSSL_PK_RSA,
+    },
+    {
+        { ADD_LEN( OID_PKCS1_SHA224 ),     "sha224WithRSAEncryption",  "RSA with SHA-224" },
+        POLARSSL_MD_SHA224,   POLARSSL_PK_RSA,
+    },
+    {
+        { ADD_LEN( OID_PKCS1_SHA256 ),     "sha256WithRSAEncryption",  "RSA with SHA-256" },
+        POLARSSL_MD_SHA256,   POLARSSL_PK_RSA,
+    },
+    {
+        { ADD_LEN( OID_PKCS1_SHA384 ),     "sha384WithRSAEncryption",  "RSA with SHA-384" },
+        POLARSSL_MD_SHA384,   POLARSSL_PK_RSA,
+    },
+    {
+        { ADD_LEN( OID_PKCS1_SHA512 ),     "sha512WithRSAEncryption",  "RSA with SHA-512" },
+        POLARSSL_MD_SHA512,   POLARSSL_PK_RSA,
+    },
+    {
+        { ADD_LEN( OID_RSA_SHA_OBS ),      "sha-1WithRSAEncryption",   "RSA with SHA1" },
+        POLARSSL_MD_SHA1,     POLARSSL_PK_RSA,
+    },
+    {
+        { ADD_LEN( OID_ECDSA_SHA1 ),       "ecdsa-with-SHA1",      "ECDSA with SHA1" },
+        POLARSSL_MD_SHA1,     POLARSSL_PK_ECDSA,
+    },
+    {
+        { ADD_LEN( OID_ECDSA_SHA224 ),     "ecdsa-with-SHA224",    "ECDSA with SHA224" },
+        POLARSSL_MD_SHA224,   POLARSSL_PK_ECDSA,
+    },
+    {
+        { ADD_LEN( OID_ECDSA_SHA256 ),     "ecdsa-with-SHA256",    "ECDSA with SHA256" },
+        POLARSSL_MD_SHA256,   POLARSSL_PK_ECDSA,
+    },
+    {
+        { ADD_LEN( OID_ECDSA_SHA384 ),     "ecdsa-with-SHA384",    "ECDSA with SHA384" },
+        POLARSSL_MD_SHA384,   POLARSSL_PK_ECDSA,
+    },
+    {
+        { ADD_LEN( OID_ECDSA_SHA512 ),     "ecdsa-with-SHA512",    "ECDSA with SHA512" },
+        POLARSSL_MD_SHA512,   POLARSSL_PK_ECDSA,
+    },
+    {
+        { NULL, 0, NULL, NULL },
+        0, 0,
+    },
+};
+
+FN_OID_TYPED_FROM_ASN1(oid_sig_alg_t, sig_alg, oid_sig_alg);
+FN_OID_GET_DESCRIPTOR_ATTR1(oid_get_sig_alg_desc, oid_sig_alg_t, sig_alg, const char *, description);
+FN_OID_GET_ATTR2(oid_get_sig_alg, oid_sig_alg_t, sig_alg, md_type_t, md_alg, pk_type_t, pk_alg);
+FN_OID_GET_OID_BY_ATTR2(oid_get_oid_by_sig_alg, oid_sig_alg_t, oid_sig_alg, pk_type_t, pk_alg, md_type_t, md_alg);
+#endif /* POLARSSL_MD_C */
+
+/*
+ * For PublicKeyInfo (PKCS1, RFC 5480)
+ */
+typedef struct {
+    oid_descriptor_t    descriptor;
+    pk_type_t           pk_alg;
+} oid_pk_alg_t;
+
+static const oid_pk_alg_t oid_pk_alg[] =
+{
+    {
+        { ADD_LEN( OID_PKCS1_RSA ),      "rsaEncryption",   "RSA" },
+        POLARSSL_PK_RSA,
+    },
+    {
+        { ADD_LEN( OID_EC_ALG_UNRESTRICTED ),  "id-ecPublicKey",   "Generic EC key" },
+        POLARSSL_PK_ECKEY,
+    },
+    {
+        { ADD_LEN( OID_EC_ALG_ECDH ),          "id-ecDH",          "EC key for ECDH" },
+        POLARSSL_PK_ECKEY_DH,
+    },
+    {
+        { NULL, 0, NULL, NULL },
+        0,
+    },
+};
+
+FN_OID_TYPED_FROM_ASN1(oid_pk_alg_t, pk_alg, oid_pk_alg);
+FN_OID_GET_ATTR1(oid_get_pk_alg, oid_pk_alg_t, pk_alg, pk_type_t, pk_alg);
+FN_OID_GET_OID_BY_ATTR1(oid_get_oid_by_pk_alg, oid_pk_alg_t, oid_pk_alg, pk_type_t, pk_alg);
+
+#if defined(POLARSSL_ECP_C)
+/*
+ * For namedCurve (RFC 5480)
+ */
+typedef struct {
+    oid_descriptor_t    descriptor;
+    ecp_group_id        grp_id;
+} oid_ecp_grp_t;
+
+static const oid_ecp_grp_t oid_ecp_grp[] =
+{
+    {
+        { ADD_LEN( OID_EC_GRP_SECP192R1 ), "secp192r1",    "secp192r1" },
+        POLARSSL_ECP_DP_SECP192R1,
+    },
+    {
+        { ADD_LEN( OID_EC_GRP_SECP224R1 ), "secp224r1",    "secp224r1" },
+        POLARSSL_ECP_DP_SECP224R1,
+    },
+    {
+        { ADD_LEN( OID_EC_GRP_SECP256R1 ), "secp256r1",    "secp256r1" },
+        POLARSSL_ECP_DP_SECP256R1,
+    },
+    {
+        { ADD_LEN( OID_EC_GRP_SECP384R1 ), "secp384r1",    "secp384r1" },
+        POLARSSL_ECP_DP_SECP384R1,
+    },
+    {
+        { ADD_LEN( OID_EC_GRP_SECP521R1 ), "secp521r1",    "secp521r1" },
+        POLARSSL_ECP_DP_SECP521R1,
+    },
+    {
+        { ADD_LEN( OID_EC_GRP_SECP192K1 ), "secp192k1",    "secp192k1" },
+        POLARSSL_ECP_DP_SECP192K1,
+    },
+    {
+        { ADD_LEN( OID_EC_GRP_SECP224K1 ), "secp224k1",    "secp224k1" },
+        POLARSSL_ECP_DP_SECP224K1,
+    },
+    {
+        { ADD_LEN( OID_EC_GRP_SECP256K1 ), "secp256k1",    "secp256k1" },
+        POLARSSL_ECP_DP_SECP256K1,
+    },
+    {
+        { ADD_LEN( OID_EC_GRP_BP256R1 ),   "brainpoolP256r1","brainpool256r1" },
+        POLARSSL_ECP_DP_BP256R1,
+    },
+    {
+        { ADD_LEN( OID_EC_GRP_BP384R1 ),   "brainpoolP384r1","brainpool384r1" },
+        POLARSSL_ECP_DP_BP384R1,
+    },
+    {
+        { ADD_LEN( OID_EC_GRP_BP512R1 ),   "brainpoolP512r1","brainpool512r1" },
+        POLARSSL_ECP_DP_BP512R1,
+    },
+    {
+        { NULL, 0, NULL, NULL },
+        0,
+    },
+};
+
+FN_OID_TYPED_FROM_ASN1(oid_ecp_grp_t, grp_id, oid_ecp_grp);
+FN_OID_GET_ATTR1(oid_get_ec_grp, oid_ecp_grp_t, grp_id, ecp_group_id, grp_id);
+FN_OID_GET_OID_BY_ATTR1(oid_get_oid_by_ec_grp, oid_ecp_grp_t, oid_ecp_grp, ecp_group_id, grp_id);
+#endif /* POLARSSL_ECP_C */
+
+#if defined(POLARSSL_CIPHER_C)
+/*
+ * For PKCS#5 PBES2 encryption algorithm
+ */
+typedef struct {
+    oid_descriptor_t    descriptor;
+    cipher_type_t       cipher_alg;
+} oid_cipher_alg_t;
+
+static const oid_cipher_alg_t oid_cipher_alg[] =
+{
+    {
+        { ADD_LEN( OID_DES_CBC ),              "desCBC",       "DES-CBC" },
+        POLARSSL_CIPHER_DES_CBC,
+    },
+    {
+        { ADD_LEN( OID_DES_EDE3_CBC ),         "des-ede3-cbc", "DES-EDE3-CBC" },
+        POLARSSL_CIPHER_DES_EDE3_CBC,
+    },
+    {
+        { NULL, 0, NULL, NULL },
+        0,
+    },
+};
+
+FN_OID_TYPED_FROM_ASN1(oid_cipher_alg_t, cipher_alg, oid_cipher_alg);
+FN_OID_GET_ATTR1(oid_get_cipher_alg, oid_cipher_alg_t, cipher_alg, cipher_type_t, cipher_alg);
+#endif /* POLARSSL_CIPHER_C */
+
+#if defined(POLARSSL_MD_C)
+/*
+ * For digestAlgorithm
+ */
+typedef struct {
+    oid_descriptor_t    descriptor;
+    md_type_t           md_alg;
+} oid_md_alg_t;
+
+static const oid_md_alg_t oid_md_alg[] =
+{
+    {
+        { ADD_LEN( OID_DIGEST_ALG_MD2 ),       "id-md2",       "MD2" },
+        POLARSSL_MD_MD2,
+    },
+    {
+        { ADD_LEN( OID_DIGEST_ALG_MD4 ),       "id-md4",       "MD4" },
+        POLARSSL_MD_MD4,
+    },
+    {
+        { ADD_LEN( OID_DIGEST_ALG_MD5 ),       "id-md5",       "MD5" },
+        POLARSSL_MD_MD5,
+    },
+    {
+        { ADD_LEN( OID_DIGEST_ALG_SHA1 ),      "id-sha1",      "SHA-1" },
+        POLARSSL_MD_SHA1,
+    },
+    {
+        { ADD_LEN( OID_DIGEST_ALG_SHA1 ),      "id-sha1",      "SHA-1" },
+        POLARSSL_MD_SHA1,
+    },
+    {
+        { ADD_LEN( OID_DIGEST_ALG_SHA224 ),    "id-sha224",    "SHA-224" },
+        POLARSSL_MD_SHA224,
+    },
+    {
+        { ADD_LEN( OID_DIGEST_ALG_SHA256 ),    "id-sha256",    "SHA-256" },
+        POLARSSL_MD_SHA256,
+    },
+    {
+        { ADD_LEN( OID_DIGEST_ALG_SHA384 ),    "id-sha384",    "SHA-384" },
+        POLARSSL_MD_SHA384,
+    },
+    {
+        { ADD_LEN( OID_DIGEST_ALG_SHA512 ),    "id-sha512",    "SHA-512" },
+        POLARSSL_MD_SHA512,
+    },
+    {
+        { NULL, 0, NULL, NULL },
+        0,
+    },
+};
+
+FN_OID_TYPED_FROM_ASN1(oid_md_alg_t, md_alg, oid_md_alg);
+FN_OID_GET_ATTR1(oid_get_md_alg, oid_md_alg_t, md_alg, md_type_t, md_alg);
+FN_OID_GET_OID_BY_ATTR1(oid_get_oid_by_md, oid_md_alg_t, oid_md_alg, md_type_t, md_alg);
+#endif /* POLARSSL_MD_C */
+
+#if defined(POLARSSL_PKCS12_C)
+/*
+ * For PKCS#12 PBEs
+ */
+typedef struct {
+    oid_descriptor_t    descriptor;
+    md_type_t           md_alg;
+    cipher_type_t       cipher_alg;
+} oid_pkcs12_pbe_alg_t;
+
+static const oid_pkcs12_pbe_alg_t oid_pkcs12_pbe_alg[] =
+{
+    {
+        { ADD_LEN( OID_PKCS12_PBE_SHA1_DES3_EDE_CBC ), "pbeWithSHAAnd3-KeyTripleDES-CBC", "PBE with SHA1 and 3-Key 3DES" },
+        POLARSSL_MD_SHA1,      POLARSSL_CIPHER_DES_EDE3_CBC,
+    },
+    {
+        { ADD_LEN( OID_PKCS12_PBE_SHA1_DES2_EDE_CBC ), "pbeWithSHAAnd2-KeyTripleDES-CBC", "PBE with SHA1 and 2-Key 3DES" },
+        POLARSSL_MD_SHA1,      POLARSSL_CIPHER_DES_EDE_CBC,
+    },
+    {
+        { NULL, 0, NULL, NULL },
+        0, 0,
+    },
+};
+
+FN_OID_TYPED_FROM_ASN1(oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, oid_pkcs12_pbe_alg);
+FN_OID_GET_ATTR2(oid_get_pkcs12_pbe_alg, oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, md_type_t, md_alg, cipher_type_t, cipher_alg);
+#endif /* POLARSSL_PKCS12_C */
+
+#if defined(_MSC_VER) && !defined snprintf && !defined(EFIX64) && \
+    !defined(EFI32)
+#include <stdarg.h>
+
+#if !defined vsnprintf
+#define vsnprintf _vsnprintf
+#endif // vsnprintf
+
+/*
+ * Windows _snprintf and _vsnprintf are not compatible to linux versions.
+ * Result value is not size of buffer needed, but -1 if no fit is possible.
+ *
+ * This fuction tries to 'fix' this by at least suggesting enlarging the
+ * size by 20.
+ */
+static int compat_snprintf(char *str, size_t size, const char *format, ...)
+{
+    va_list ap;
+    int res = -1;
+
+    va_start( ap, format );
+
+    res = vsnprintf( str, size, format, ap );
+
+    va_end( ap );
+
+    // No quick fix possible
+    if ( res < 0 )
+        return( (int) size + 20 );
+
+    return res;
+}
+
+#define snprintf compat_snprintf
+#endif /* _MSC_VER && !snprintf && !EFIX64 && !EFI32 */
+
+#define SAFE_SNPRINTF()                         \
+{                                               \
+    if( ret == -1 )                             \
+        return POLARSSL_ERR_OID_BUF_TOO_SMALL;  \
+                                                \
+    if ( (unsigned int) ret >= n ) {            \
+        p[n - 1] = '\0';                        \
+        return POLARSSL_ERR_OID_BUF_TOO_SMALL;  \
+    }                                           \
+                                                \
+    n -= (unsigned int) ret;                    \
+    p += (unsigned int) ret;                    \
+}
+
+/* Return the x.y.z.... style numeric string for the given OID */
+int oid_get_numeric_string( char *buf, size_t size,
+                            const asn1_buf *oid )
+{
+    int ret;
+    size_t i, n;
+    unsigned int value;
+    char *p;
+
+    p = buf;
+    n = size;
+
+    /* First byte contains first two dots */
+    if( oid->len > 0 )
+    {
+        ret = snprintf( p, n, "%d.%d", oid->p[0] / 40, oid->p[0] % 40 );
+        SAFE_SNPRINTF();
+    }
+
+    value = 0;
+    for( i = 1; i < oid->len; i++ )
+    {
+        /* Prevent overflow in value. */
+        if ( ( ( value << 7 ) >> 7 ) != value )
+            return( POLARSSL_ERR_OID_BUF_TOO_SMALL );
+
+        value <<= 7;
+        value += oid->p[i] & 0x7F;
+
+        if( !( oid->p[i] & 0x80 ) )
+        {
+            /* Last byte */
+            ret = snprintf( p, n, ".%d", value );
+            SAFE_SNPRINTF();
+            value = 0;
+        }
+    }
+
+    return( (int) ( size - n ) );
+}
+
+#endif /* POLARSSL_OID_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/padlock.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,168 @@
+/*
+ *  VIA PadLock support functions
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  This implementation is based on the VIA PadLock Programming Guide:
+ *
+ *  http://www.via.com.tw/en/downloads/whitepapers/initiatives/padlock/
+ *  programming_guide.pdf
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_PADLOCK_C)
+
+#include "polarssl/padlock.h"
+
+#if defined(POLARSSL_HAVE_X86)
+
+/*
+ * PadLock detection routine
+ */
+int padlock_supports( int feature )
+{
+    static int flags = -1;
+    int ebx = 0, edx = 0;
+
+    if( flags == -1 )
+    {
+        asm( "movl  %%ebx, %0           \n"     \
+             "movl  $0xC0000000, %%eax  \n"     \
+             "cpuid                     \n"     \
+             "cmpl  $0xC0000001, %%eax  \n"     \
+             "movl  $0, %%edx           \n"     \
+             "jb    unsupported         \n"     \
+             "movl  $0xC0000001, %%eax  \n"     \
+             "cpuid                     \n"     \
+             "unsupported:              \n"     \
+             "movl  %%edx, %1           \n"     \
+             "movl  %2, %%ebx           \n"
+             : "=m" (ebx), "=m" (edx)
+             :  "m" (ebx)
+             : "eax", "ecx", "edx" );
+
+        flags = edx;
+    }
+
+    return( flags & feature );
+}
+
+/*
+ * PadLock AES-ECB block en(de)cryption
+ */
+int padlock_xcryptecb( aes_context *ctx,
+                       int mode,
+                       const unsigned char input[16],
+                       unsigned char output[16] )
+{
+    int ebx = 0;
+    uint32_t *rk;
+    uint32_t *blk;
+    uint32_t *ctrl;
+    unsigned char buf[256];
+
+    rk  = ctx->rk;
+    blk = PADLOCK_ALIGN16( buf );
+    memcpy( blk, input, 16 );
+
+     ctrl = blk + 4;
+    *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + ( mode^1 ) - 10 ) << 9 );
+
+    asm( "pushfl; popfl         \n"     \
+         "movl    %%ebx, %0     \n"     \
+         "movl    $1, %%ecx     \n"     \
+         "movl    %2, %%edx     \n"     \
+         "movl    %3, %%ebx     \n"     \
+         "movl    %4, %%esi     \n"     \
+         "movl    %4, %%edi     \n"     \
+         ".byte  0xf3,0x0f,0xa7,0xc8\n" \
+         "movl    %1, %%ebx     \n"
+         : "=m" (ebx)
+         :  "m" (ebx), "m" (ctrl), "m" (rk), "m" (blk)
+         : "ecx", "edx", "esi", "edi" );
+
+    memcpy( output, blk, 16 );
+
+    return( 0 );
+}
+
+/*
+ * PadLock AES-CBC buffer en(de)cryption
+ */
+int padlock_xcryptcbc( aes_context *ctx,
+                       int mode,
+                       size_t length,
+                       unsigned char iv[16],
+                       const unsigned char *input,
+                       unsigned char *output )
+{
+    int ebx = 0;
+    size_t count;
+    uint32_t *rk;
+    uint32_t *iw;
+    uint32_t *ctrl;
+    unsigned char buf[256];
+
+    if( ( (long) input  & 15 ) != 0 ||
+        ( (long) output & 15 ) != 0 )
+        return( POLARSSL_ERR_PADLOCK_DATA_MISALIGNED );
+
+    rk = ctx->rk;
+    iw = PADLOCK_ALIGN16( buf );
+    memcpy( iw, iv, 16 );
+
+     ctrl = iw + 4;
+    *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + (mode^1) - 10 ) << 9 );
+
+    count = (length + 15) >> 4;
+
+    asm( "pushfl; popfl         \n"     \
+         "movl    %%ebx, %0     \n"     \
+         "movl    %2, %%ecx     \n"     \
+         "movl    %3, %%edx     \n"     \
+         "movl    %4, %%ebx     \n"     \
+         "movl    %5, %%esi     \n"     \
+         "movl    %6, %%edi     \n"     \
+         "movl    %7, %%eax     \n"     \
+         ".byte  0xf3,0x0f,0xa7,0xd0\n" \
+         "movl    %1, %%ebx     \n"
+         : "=m" (ebx)
+         :  "m" (ebx), "m" (count), "m" (ctrl),
+            "m"  (rk), "m" (input), "m" (output), "m" (iw)
+         : "eax", "ecx", "edx", "esi", "edi" );
+
+    memcpy( iv, iw, 16 );
+
+    return( 0 );
+}
+
+#endif /* POLARSSL_HAVE_X86 */
+
+#endif /* POLARSSL_PADLOCK_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/pbkdf2.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,66 @@
+/**
+ * \file pbkdf2.c
+ *
+ * \brief Password-Based Key Derivation Function 2 (from PKCS#5)
+ *        DEPRECATED: Use pkcs5.c instead
+ *
+ * \author Mathias Olsson <mathias@kompetensum.com>
+ *
+ *  Copyright (C) 2006-2012, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * PBKDF2 is part of PKCS#5
+ *
+ * http://tools.ietf.org/html/rfc2898 (Specification)
+ * http://tools.ietf.org/html/rfc6070 (Test vectors)
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_PBKDF2_C)
+
+#include "polarssl/pbkdf2.h"
+#include "polarssl/pkcs5.h"
+
+int pbkdf2_hmac( 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 )
+{
+    return pkcs5_pbkdf2_hmac( ctx, password, plen, salt, slen, iteration_count,
+                              key_length, output );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+int pbkdf2_self_test( int verbose )
+{
+    return pkcs5_self_test( verbose );
+}
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_PBKDF2_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/pem.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,437 @@
+/*
+ *  Privacy Enhanced Mail (PEM) decoding
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_PEM_PARSE_C) || defined(POLARSSL_PEM_WRITE_C)
+#include "polarssl/pem.h"
+#include "polarssl/base64.h"
+#include "polarssl/des.h"
+#include "polarssl/aes.h"
+#include "polarssl/md5.h"
+#include "polarssl/cipher.h"
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+#include <stdlib.h>
+
+#if defined(POLARSSL_PEM_PARSE_C)
+void pem_init( pem_context *ctx )
+{
+    memset( ctx, 0, sizeof( pem_context ) );
+}
+
+#if defined(POLARSSL_MD5_C) && defined(POLARSSL_CIPHER_MODE_CBC) &&         \
+    ( defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C) )
+/*
+ * Read a 16-byte hex string and convert it to binary
+ */
+static int pem_get_iv( const unsigned char *s, unsigned char *iv,
+                       size_t iv_len )
+{
+    size_t i, j, k;
+
+    memset( iv, 0, iv_len );
+
+    for( i = 0; i < iv_len * 2; i++, s++ )
+    {
+        if( *s >= '0' && *s <= '9' ) j = *s - '0'; else
+        if( *s >= 'A' && *s <= 'F' ) j = *s - '7'; else
+        if( *s >= 'a' && *s <= 'f' ) j = *s - 'W'; else
+            return( POLARSSL_ERR_PEM_INVALID_ENC_IV );
+
+        k = ( ( i & 1 ) != 0 ) ? j : j << 4;
+
+        iv[i >> 1] = (unsigned char)( iv[i >> 1] | k );
+    }
+
+    return( 0 );
+}
+
+static void pem_pbkdf1( unsigned char *key, size_t keylen,
+                        unsigned char *iv,
+                        const unsigned char *pwd, size_t pwdlen )
+{
+    md5_context md5_ctx;
+    unsigned char md5sum[16];
+    size_t use_len;
+
+    /*
+     * key[ 0..15] = MD5(pwd || IV)
+     */
+    md5_starts( &md5_ctx );
+    md5_update( &md5_ctx, pwd, pwdlen );
+    md5_update( &md5_ctx, iv,  8 );
+    md5_finish( &md5_ctx, md5sum );
+
+    if( keylen <= 16 )
+    {
+        memcpy( key, md5sum, keylen );
+
+        memset( &md5_ctx, 0, sizeof(  md5_ctx ) );
+        memset( md5sum, 0, 16 );
+        return;
+    }
+
+    memcpy( key, md5sum, 16 );
+
+    /*
+     * key[16..23] = MD5(key[ 0..15] || pwd || IV])
+     */
+    md5_starts( &md5_ctx );
+    md5_update( &md5_ctx, md5sum,  16 );
+    md5_update( &md5_ctx, pwd, pwdlen );
+    md5_update( &md5_ctx, iv,  8 );
+    md5_finish( &md5_ctx, md5sum );
+
+    use_len = 16;
+    if( keylen < 32 )
+        use_len = keylen - 16;
+
+    memcpy( key + 16, md5sum, use_len );
+
+    memset( &md5_ctx, 0, sizeof(  md5_ctx ) );
+    memset( md5sum, 0, 16 );
+}
+
+#if defined(POLARSSL_DES_C)
+/*
+ * Decrypt with DES-CBC, using PBKDF1 for key derivation
+ */
+static void pem_des_decrypt( unsigned char des_iv[8],
+                               unsigned char *buf, size_t buflen,
+                               const unsigned char *pwd, size_t pwdlen )
+{
+    des_context des_ctx;
+    unsigned char des_key[8];
+
+    pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen );
+
+    des_setkey_dec( &des_ctx, des_key );
+    des_crypt_cbc( &des_ctx, DES_DECRYPT, buflen,
+                     des_iv, buf, buf );
+
+    memset( &des_ctx, 0, sizeof( des_ctx ) );
+    memset( des_key, 0, 8 );
+}
+
+/*
+ * Decrypt with 3DES-CBC, using PBKDF1 for key derivation
+ */
+static void pem_des3_decrypt( unsigned char des3_iv[8],
+                               unsigned char *buf, size_t buflen,
+                               const unsigned char *pwd, size_t pwdlen )
+{
+    des3_context des3_ctx;
+    unsigned char des3_key[24];
+
+    pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen );
+
+    des3_set3key_dec( &des3_ctx, des3_key );
+    des3_crypt_cbc( &des3_ctx, DES_DECRYPT, buflen,
+                     des3_iv, buf, buf );
+
+    memset( &des3_ctx, 0, sizeof( des3_ctx ) );
+    memset( des3_key, 0, 24 );
+}
+#endif /* POLARSSL_DES_C */
+
+#if defined(POLARSSL_AES_C)
+/*
+ * Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation
+ */
+static void pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen,
+                               unsigned char *buf, size_t buflen,
+                               const unsigned char *pwd, size_t pwdlen )
+{
+    aes_context aes_ctx;
+    unsigned char aes_key[32];
+
+    pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen );
+
+    aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 );
+    aes_crypt_cbc( &aes_ctx, AES_DECRYPT, buflen,
+                     aes_iv, buf, buf );
+
+    memset( &aes_ctx, 0, sizeof( aes_ctx ) );
+    memset( aes_key, 0, keylen );
+}
+#endif /* POLARSSL_AES_C */
+
+#endif /* POLARSSL_MD5_C && POLARSSL_CIPHER_MODE_CBC &&
+          ( POLARSSL_AES_C || POLARSSL_DES_C ) */
+
+int pem_read_buffer( pem_context *ctx, const char *header, const char *footer,
+                     const unsigned char *data, const unsigned char *pwd,
+                     size_t pwdlen, size_t *use_len )
+{
+    int ret, enc;
+    size_t len;
+    unsigned char *buf;
+    const unsigned char *s1, *s2, *end;
+#if defined(POLARSSL_MD5_C) && defined(POLARSSL_CIPHER_MODE_CBC) &&         \
+    ( defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C) )
+    unsigned char pem_iv[16];
+    cipher_type_t enc_alg = POLARSSL_CIPHER_NONE;
+#else
+    ((void) pwd);
+    ((void) pwdlen);
+#endif /* POLARSSL_MD5_C && POLARSSL_CIPHER_MODE_CBC &&
+          ( POLARSSL_AES_C || POLARSSL_DES_C ) */
+
+    if( ctx == NULL )
+        return( POLARSSL_ERR_PEM_BAD_INPUT_DATA );
+
+    s1 = (unsigned char *) strstr( (const char *) data, header );
+
+    if( s1 == NULL )
+        return( POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT );
+
+    s2 = (unsigned char *) strstr( (const char *) data, footer );
+
+    if( s2 == NULL || s2 <= s1 )
+        return( POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT );
+
+    s1 += strlen( header );
+    if( *s1 == '\r' ) s1++;
+    if( *s1 == '\n' ) s1++;
+    else return( POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT );
+
+    end = s2;
+    end += strlen( footer );
+    if( *end == '\r' ) end++;
+    if( *end == '\n' ) end++;
+    *use_len = end - data;
+
+    enc = 0;
+
+    if( memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 )
+    {
+#if defined(POLARSSL_MD5_C) && defined(POLARSSL_CIPHER_MODE_CBC) &&         \
+    ( defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C) )
+        enc++;
+
+        s1 += 22;
+        if( *s1 == '\r' ) s1++;
+        if( *s1 == '\n' ) s1++;
+        else return( POLARSSL_ERR_PEM_INVALID_DATA );
+
+
+#if defined(POLARSSL_DES_C)
+        if( memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) == 0 )
+        {
+            enc_alg = POLARSSL_CIPHER_DES_EDE3_CBC;
+
+            s1 += 23;
+            if( pem_get_iv( s1, pem_iv, 8 ) != 0 )
+                return( POLARSSL_ERR_PEM_INVALID_ENC_IV );
+
+            s1 += 16;
+        }
+        else if( memcmp( s1, "DEK-Info: DES-CBC,", 18 ) == 0 )
+        {
+            enc_alg = POLARSSL_CIPHER_DES_CBC;
+
+            s1 += 18;
+            if( pem_get_iv( s1, pem_iv, 8) != 0 )
+                return( POLARSSL_ERR_PEM_INVALID_ENC_IV );
+
+            s1 += 16;
+        }
+#endif /* POLARSSL_DES_C */
+
+#if defined(POLARSSL_AES_C)
+        if( memcmp( s1, "DEK-Info: AES-", 14 ) == 0 )
+        {
+            if( memcmp( s1, "DEK-Info: AES-128-CBC,", 22 ) == 0 )
+                enc_alg = POLARSSL_CIPHER_AES_128_CBC;
+            else if( memcmp( s1, "DEK-Info: AES-192-CBC,", 22 ) == 0 )
+                enc_alg = POLARSSL_CIPHER_AES_192_CBC;
+            else if( memcmp( s1, "DEK-Info: AES-256-CBC,", 22 ) == 0 )
+                enc_alg = POLARSSL_CIPHER_AES_256_CBC;
+            else
+                return( POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG );
+
+            s1 += 22;
+            if( pem_get_iv( s1, pem_iv, 16 ) != 0 )
+                return( POLARSSL_ERR_PEM_INVALID_ENC_IV );
+
+            s1 += 32;
+        }
+#endif /* POLARSSL_AES_C */
+
+        if( enc_alg == POLARSSL_CIPHER_NONE )
+            return( POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG );
+
+        if( *s1 == '\r' ) s1++;
+        if( *s1 == '\n' ) s1++;
+        else return( POLARSSL_ERR_PEM_INVALID_DATA );
+#else
+        return( POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE );
+#endif /* POLARSSL_MD5_C && POLARSSL_CIPHER_MODE_CBC &&
+          ( POLARSSL_AES_C || POLARSSL_DES_C ) */
+    }
+
+    len = 0;
+    ret = base64_decode( NULL, &len, s1, s2 - s1 );
+
+    if( ret == POLARSSL_ERR_BASE64_INVALID_CHARACTER )
+        return( POLARSSL_ERR_PEM_INVALID_DATA + ret );
+
+    if( ( buf = (unsigned char *) polarssl_malloc( len ) ) == NULL )
+        return( POLARSSL_ERR_PEM_MALLOC_FAILED );
+
+    if( ( ret = base64_decode( buf, &len, s1, s2 - s1 ) ) != 0 )
+    {
+        polarssl_free( buf );
+        return( POLARSSL_ERR_PEM_INVALID_DATA + ret );
+    }
+
+    if( enc != 0 )
+    {
+#if defined(POLARSSL_MD5_C) && defined(POLARSSL_CIPHER_MODE_CBC) &&         \
+    ( defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C) )
+        if( pwd == NULL )
+        {
+            polarssl_free( buf );
+            return( POLARSSL_ERR_PEM_PASSWORD_REQUIRED );
+        }
+
+#if defined(POLARSSL_DES_C)
+        if( enc_alg == POLARSSL_CIPHER_DES_EDE3_CBC )
+            pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen );
+        else if( enc_alg == POLARSSL_CIPHER_DES_CBC )
+            pem_des_decrypt( pem_iv, buf, len, pwd, pwdlen );
+#endif /* POLARSSL_DES_C */
+
+#if defined(POLARSSL_AES_C)
+        if( enc_alg == POLARSSL_CIPHER_AES_128_CBC )
+            pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen );
+        else if( enc_alg == POLARSSL_CIPHER_AES_192_CBC )
+            pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen );
+        else if( enc_alg == POLARSSL_CIPHER_AES_256_CBC )
+            pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen );
+#endif /* POLARSSL_AES_C */
+
+        /*
+         * The result will be ASN.1 starting with a SEQUENCE tag, with 1 to 3
+         * length bytes (allow 4 to be sure) in all known use cases.
+         *
+         * Use that as heurisitic to try detecting password mismatchs.
+         */
+        if( len <= 2 || buf[0] != 0x30 || buf[1] > 0x83 )
+        {
+            polarssl_free( buf );
+            return( POLARSSL_ERR_PEM_PASSWORD_MISMATCH );
+        }
+#else
+        polarssl_free( buf );
+        return( POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE );
+#endif /* POLARSSL_MD5_C && POLARSSL_CIPHER_MODE_CBC &&
+          ( POLARSSL_AES_C || POLARSSL_DES_C ) */
+    }
+
+    ctx->buf = buf;
+    ctx->buflen = len;
+
+    return( 0 );
+}
+
+void pem_free( pem_context *ctx )
+{
+    if( ctx->buf )
+        polarssl_free( ctx->buf );
+
+    if( ctx->info )
+        polarssl_free( ctx->info );
+
+    memset( ctx, 0, sizeof( pem_context ) );
+}
+#endif /* POLARSSL_PEM_PARSE_C */
+
+#if defined(POLARSSL_PEM_WRITE_C)
+int 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 )
+{
+    int ret;
+    unsigned char *encode_buf, *c, *p = buf;
+    size_t len = 0, use_len = 0, add_len = 0;
+
+    base64_encode( NULL, &use_len, der_data, der_len );
+    add_len = strlen( header ) + strlen( footer ) + ( use_len / 64 ) + 1;
+
+    if( use_len + add_len > buf_len )
+    {
+        *olen = use_len + add_len;
+        return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
+    }
+
+    if( ( encode_buf = polarssl_malloc( use_len ) ) == NULL )
+        return( POLARSSL_ERR_PEM_MALLOC_FAILED );
+
+    if( ( ret = base64_encode( encode_buf, &use_len, der_data,
+                               der_len ) ) != 0 )
+    {
+        polarssl_free( encode_buf );
+        return( ret );
+    }
+
+    memcpy( p, header, strlen( header ) );
+    p += strlen( header );
+    c = encode_buf;
+
+    while( use_len )
+    {
+        len = ( use_len > 64 ) ? 64 : use_len;
+        memcpy( p, c, len );
+        use_len -= len;
+        p += len;
+        c += len;
+        *p++ = '\n';
+    }
+
+    memcpy( p, footer, strlen( footer ) );
+    p += strlen( footer );
+
+    *p++ = '\0';
+    *olen = p - buf;
+
+    polarssl_free( encode_buf );
+    return( 0 );
+}
+#endif /* POLARSSL_PEM_WRITE_C */
+#endif /* POLARSSL_PEM_PARSE_C || POLARSSL_PEM_WRITE_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/pk.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,296 @@
+/*
+ *  Public Key abstraction layer
+ *
+ *  Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_PK_C)
+
+#include "polarssl/pk.h"
+#include "polarssl/pk_wrap.h"
+
+#if defined(POLARSSL_RSA_C)
+#include "polarssl/rsa.h"
+#endif
+#if defined(POLARSSL_ECP_C)
+#include "polarssl/ecp.h"
+#endif
+#if defined(POLARSSL_ECDSA_C)
+#include "polarssl/ecdsa.h"
+#endif
+
+/*
+ * Initialise a pk_context
+ */
+void pk_init( pk_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    ctx->pk_info = NULL;
+    ctx->pk_ctx = NULL;
+}
+
+/*
+ * Free (the components of) a pk_context
+ */
+void pk_free( pk_context *ctx )
+{
+    if( ctx == NULL || ctx->pk_info == NULL)
+        return;
+
+    ctx->pk_info->ctx_free_func( ctx->pk_ctx );
+    ctx->pk_ctx = NULL;
+
+    ctx->pk_info = NULL;
+}
+
+/*
+ * Get pk_info structure from type
+ */
+const pk_info_t * pk_info_from_type( pk_type_t pk_type )
+{
+    switch( pk_type ) {
+#if defined(POLARSSL_RSA_C)
+        case POLARSSL_PK_RSA:
+            return &rsa_info;
+#endif
+#if defined(POLARSSL_ECP_C)
+        case POLARSSL_PK_ECKEY:
+            return &eckey_info;
+        case POLARSSL_PK_ECKEY_DH:
+            return &eckeydh_info;
+#endif
+#if defined(POLARSSL_ECDSA_C)
+        case POLARSSL_PK_ECDSA:
+            return &ecdsa_info;
+#endif
+        /* POLARSSL_PK_RSA_ALT omitted on purpose */
+        default:
+            return NULL;
+    }
+}
+
+/*
+ * Initialise context
+ */
+int pk_init_ctx( pk_context *ctx, const pk_info_t *info )
+{
+    if( ctx == NULL || info == NULL || ctx->pk_info != NULL )
+        return( POLARSSL_ERR_PK_BAD_INPUT_DATA );
+
+    if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL )
+        return( POLARSSL_ERR_PK_MALLOC_FAILED );
+
+    ctx->pk_info = info;
+
+    return( 0 );
+}
+
+/*
+ * Initialize an RSA-alt context
+ */
+int pk_init_ctx_rsa_alt( pk_context *ctx, void * key,
+                         pk_rsa_alt_decrypt_func decrypt_func,
+                         pk_rsa_alt_sign_func sign_func,
+                         pk_rsa_alt_key_len_func key_len_func )
+{
+    rsa_alt_context *rsa_alt;
+    const pk_info_t *info = &rsa_alt_info;
+
+    if( ctx == NULL || ctx->pk_info != NULL )
+        return( POLARSSL_ERR_PK_BAD_INPUT_DATA );
+
+    if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL )
+        return( POLARSSL_ERR_PK_MALLOC_FAILED );
+
+    ctx->pk_info = info;
+
+    rsa_alt = (rsa_alt_context *) ctx->pk_ctx;
+
+    rsa_alt->key = key;
+    rsa_alt->decrypt_func = decrypt_func;
+    rsa_alt->sign_func = sign_func;
+    rsa_alt->key_len_func = key_len_func;
+
+    return( 0 );
+}
+
+/*
+ * Tell if a PK can do the operations of the given type
+ */
+int pk_can_do( pk_context *ctx, pk_type_t type )
+{
+    /* null or NONE context can't do anything */
+    if( ctx == NULL || ctx->pk_info == NULL )
+        return( 0 );
+
+    return( ctx->pk_info->can_do( type ) );
+}
+
+/*
+ * Helper for pk_sign and pk_verify
+ */
+static inline int pk_hashlen_helper( md_type_t md_alg, size_t *hash_len )
+{
+    const md_info_t *md_info;
+
+    if( *hash_len != 0 )
+        return( 0 );
+
+    if( ( md_info = md_info_from_type( md_alg ) ) == NULL )
+        return( -1 );
+
+    *hash_len = md_info->size;
+    return( 0 );
+}
+
+/*
+ * Verify a signature
+ */
+int pk_verify( pk_context *ctx, md_type_t md_alg,
+               const unsigned char *hash, size_t hash_len,
+               const unsigned char *sig, size_t sig_len )
+{
+    if( ctx == NULL || ctx->pk_info == NULL ||
+        pk_hashlen_helper( md_alg, &hash_len ) != 0 )
+        return( POLARSSL_ERR_PK_BAD_INPUT_DATA );
+
+    if( ctx->pk_info->verify_func == NULL )
+        return( POLARSSL_ERR_PK_TYPE_MISMATCH );
+
+    return( ctx->pk_info->verify_func( ctx->pk_ctx, md_alg, hash, hash_len,
+                                       sig, sig_len ) );
+}
+
+/*
+ * Make a signature
+ */
+int pk_sign( pk_context *ctx, 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 )
+{
+    if( ctx == NULL || ctx->pk_info == NULL ||
+        pk_hashlen_helper( md_alg, &hash_len ) != 0 )
+        return( POLARSSL_ERR_PK_BAD_INPUT_DATA );
+
+    if( ctx->pk_info->sign_func == NULL )
+        return( POLARSSL_ERR_PK_TYPE_MISMATCH );
+
+    return( ctx->pk_info->sign_func( ctx->pk_ctx, md_alg, hash, hash_len,
+                                     sig, sig_len, f_rng, p_rng ) );
+}
+
+/*
+ * Decrypt message
+ */
+int pk_decrypt( 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 )
+{
+    if( ctx == NULL || ctx->pk_info == NULL )
+        return( POLARSSL_ERR_PK_BAD_INPUT_DATA );
+
+    if( ctx->pk_info->decrypt_func == NULL )
+        return( POLARSSL_ERR_PK_TYPE_MISMATCH );
+
+    return( ctx->pk_info->decrypt_func( ctx->pk_ctx, input, ilen,
+                output, olen, osize, f_rng, p_rng ) );
+}
+
+/*
+ * Encrypt message
+ */
+int pk_encrypt( 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 )
+{
+    if( ctx == NULL || ctx->pk_info == NULL )
+        return( POLARSSL_ERR_PK_BAD_INPUT_DATA );
+
+    if( ctx->pk_info->encrypt_func == NULL )
+        return( POLARSSL_ERR_PK_TYPE_MISMATCH );
+
+    return( ctx->pk_info->encrypt_func( ctx->pk_ctx, input, ilen,
+                output, olen, osize, f_rng, p_rng ) );
+}
+
+/*
+ * Get key size in bits
+ */
+size_t pk_get_size( const pk_context *ctx )
+{
+    if( ctx == NULL || ctx->pk_info == NULL )
+        return( 0 );
+
+    return( ctx->pk_info->get_size( ctx->pk_ctx ) );
+}
+
+/*
+ * Export debug information
+ */
+int pk_debug( const pk_context *ctx, pk_debug_item *items )
+{
+    if( ctx == NULL || ctx->pk_info == NULL )
+        return( POLARSSL_ERR_PK_BAD_INPUT_DATA );
+
+    if( ctx->pk_info->debug_func == NULL )
+        return( POLARSSL_ERR_PK_TYPE_MISMATCH );
+
+    ctx->pk_info->debug_func( ctx->pk_ctx, items );
+    return( 0 );
+}
+
+/*
+ * Access the PK type name
+ */
+const char * pk_get_name( const pk_context *ctx )
+{
+    if( ctx == NULL || ctx->pk_info == NULL )
+        return( "invalid PK" );
+
+    return( ctx->pk_info->name );
+}
+
+/*
+ * Access the PK type
+ */
+pk_type_t pk_get_type( const pk_context *ctx )
+{
+    if( ctx == NULL || ctx->pk_info == NULL )
+        return( POLARSSL_PK_NONE );
+
+    return( ctx->pk_info->type );
+}
+
+#endif /* POLARSSL_PK_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/pk_wrap.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,443 @@
+/*
+ *  Public Key abstraction layer: wrapper functions
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_PK_C)
+
+#include "polarssl/pk_wrap.h"
+
+/* Even if RSA not activated, for the sake of RSA-alt */
+#include "polarssl/rsa.h"
+
+#if defined(POLARSSL_ECP_C)
+#include "polarssl/ecp.h"
+#endif
+
+#if defined(POLARSSL_ECDSA_C)
+#include "polarssl/ecdsa.h"
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdlib.h>
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+/* Used by RSA-alt too */
+static int rsa_can_do( pk_type_t type )
+{
+    return( type == POLARSSL_PK_RSA );
+}
+
+#if defined(POLARSSL_RSA_C)
+static size_t rsa_get_size( const void *ctx )
+{
+    return( 8 * ((const rsa_context *) ctx)->len );
+}
+
+static int rsa_verify_wrap( void *ctx, md_type_t md_alg,
+                   const unsigned char *hash, size_t hash_len,
+                   const unsigned char *sig, size_t sig_len )
+{
+    int ret;
+
+    if( sig_len < ((rsa_context *) ctx)->len )
+        return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+
+    if( ( ret = rsa_pkcs1_verify( (rsa_context *) ctx, NULL, NULL,
+                                  RSA_PUBLIC, md_alg,
+                                  (unsigned int) hash_len, hash, sig ) ) != 0 )
+        return( ret );
+
+    if( sig_len > ((rsa_context *) ctx)->len )
+        return( POLARSSL_ERR_PK_SIG_LEN_MISMATCH );
+
+    return( 0 );
+}
+
+static int rsa_sign_wrap( void *ctx, 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 )
+{
+    *sig_len = ((rsa_context *) ctx)->len;
+
+    return( rsa_pkcs1_sign( (rsa_context *) ctx, f_rng, p_rng, RSA_PRIVATE,
+                md_alg, (unsigned int) hash_len, hash, sig ) );
+}
+
+static int rsa_decrypt_wrap( 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 )
+{
+    if( ilen != ((rsa_context *) ctx)->len )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    return( rsa_pkcs1_decrypt( (rsa_context *) ctx, f_rng, p_rng,
+                RSA_PRIVATE, olen, input, output, osize ) );
+}
+
+static int rsa_encrypt_wrap( 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 )
+{
+    ((void) osize);
+
+    *olen = ((rsa_context *) ctx)->len;
+
+    return( rsa_pkcs1_encrypt( (rsa_context *) ctx,
+                f_rng, p_rng, RSA_PUBLIC, ilen, input, output ) );
+}
+
+static void *rsa_alloc_wrap( void )
+{
+    void *ctx = polarssl_malloc( sizeof( rsa_context ) );
+
+    if( ctx != NULL )
+        rsa_init( (rsa_context *) ctx, 0, 0 );
+
+    return ctx;
+}
+
+static void rsa_free_wrap( void *ctx )
+{
+    rsa_free( (rsa_context *) ctx );
+    polarssl_free( ctx );
+}
+
+static void rsa_debug( const void *ctx, pk_debug_item *items )
+{
+    items->type = POLARSSL_PK_DEBUG_MPI;
+    items->name = "rsa.N";
+    items->value = &( ((rsa_context *) ctx)->N );
+
+    items++;
+
+    items->type = POLARSSL_PK_DEBUG_MPI;
+    items->name = "rsa.E";
+    items->value = &( ((rsa_context *) ctx)->E );
+}
+
+const pk_info_t rsa_info = {
+    POLARSSL_PK_RSA,
+    "RSA",
+    rsa_get_size,
+    rsa_can_do,
+    rsa_verify_wrap,
+    rsa_sign_wrap,
+    rsa_decrypt_wrap,
+    rsa_encrypt_wrap,
+    rsa_alloc_wrap,
+    rsa_free_wrap,
+    rsa_debug,
+};
+#endif /* POLARSSL_RSA_C */
+
+#if defined(POLARSSL_ECP_C)
+/*
+ * Generic EC key
+ */
+static int eckey_can_do( pk_type_t type )
+{
+    return( type == POLARSSL_PK_ECKEY ||
+            type == POLARSSL_PK_ECKEY_DH ||
+            type == POLARSSL_PK_ECDSA );
+}
+
+static size_t eckey_get_size( const void *ctx )
+{
+    return( ((ecp_keypair *) ctx)->grp.pbits );
+}
+
+#if defined(POLARSSL_ECDSA_C)
+/* Forward declarations */
+static int ecdsa_verify_wrap( void *ctx, md_type_t md_alg,
+                       const unsigned char *hash, size_t hash_len,
+                       const unsigned char *sig, size_t sig_len );
+
+static int ecdsa_sign_wrap( void *ctx, 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 );
+
+static int eckey_verify_wrap( void *ctx, md_type_t md_alg,
+                       const unsigned char *hash, size_t hash_len,
+                       const unsigned char *sig, size_t sig_len )
+{
+    int ret;
+    ecdsa_context ecdsa;
+
+    ecdsa_init( &ecdsa );
+
+    if( ( ret = ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 )
+        ret = ecdsa_verify_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len );
+
+    ecdsa_free( &ecdsa );
+
+    return( ret );
+}
+
+static int eckey_sign_wrap( void *ctx, 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 )
+{
+    int ret;
+    ecdsa_context ecdsa;
+
+    ecdsa_init( &ecdsa );
+
+    if( ( ret = ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 )
+        ret = ecdsa_sign_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len,
+                               f_rng, p_rng );
+
+    ecdsa_free( &ecdsa );
+
+    return( ret );
+}
+
+#endif /* POLARSSL_ECDSA_C */
+
+static void *eckey_alloc_wrap( void )
+{
+    void *ctx = polarssl_malloc( sizeof( ecp_keypair ) );
+
+    if( ctx != NULL )
+        ecp_keypair_init( ctx );
+
+    return( ctx );
+}
+
+static void eckey_free_wrap( void *ctx )
+{
+    ecp_keypair_free( (ecp_keypair *) ctx );
+    polarssl_free( ctx );
+}
+
+static void eckey_debug( const void *ctx, pk_debug_item *items )
+{
+    items->type = POLARSSL_PK_DEBUG_ECP;
+    items->name = "eckey.Q";
+    items->value = &( ((ecp_keypair *) ctx)->Q );
+}
+
+const pk_info_t eckey_info = {
+    POLARSSL_PK_ECKEY,
+    "EC",
+    eckey_get_size,
+    eckey_can_do,
+#if defined(POLARSSL_ECDSA_C)
+    eckey_verify_wrap,
+    eckey_sign_wrap,
+#else
+    NULL,
+    NULL,
+#endif
+    NULL,
+    NULL,
+    eckey_alloc_wrap,
+    eckey_free_wrap,
+    eckey_debug,
+};
+
+/*
+ * EC key restricted to ECDH
+ */
+static int eckeydh_can_do( pk_type_t type )
+{
+    return( type == POLARSSL_PK_ECKEY ||
+            type == POLARSSL_PK_ECKEY_DH );
+}
+
+const pk_info_t eckeydh_info = {
+    POLARSSL_PK_ECKEY_DH,
+    "EC_DH",
+    eckey_get_size,         /* Same underlying key structure */
+    eckeydh_can_do,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    eckey_alloc_wrap,       /* Same underlying key structure */
+    eckey_free_wrap,        /* Same underlying key structure */
+    eckey_debug,            /* Same underlying key structure */
+};
+#endif /* POLARSSL_ECP_C */
+
+#if defined(POLARSSL_ECDSA_C)
+static int ecdsa_can_do( pk_type_t type )
+{
+    return( type == POLARSSL_PK_ECDSA );
+}
+
+static int ecdsa_verify_wrap( void *ctx, md_type_t md_alg,
+                       const unsigned char *hash, size_t hash_len,
+                       const unsigned char *sig, size_t sig_len )
+{
+    int ret;
+    ((void) md_alg);
+
+    ret = ecdsa_read_signature( (ecdsa_context *) ctx,
+                                hash, hash_len, sig, sig_len );
+
+    if( ret == POLARSSL_ERR_ECP_SIG_LEN_MISMATCH )
+        return( POLARSSL_ERR_PK_SIG_LEN_MISMATCH );
+
+    return( ret );
+}
+
+static int ecdsa_sign_wrap( void *ctx, 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 )
+{
+    /* Use deterministic ECDSA by default if available */
+#if defined(POLARSSL_ECDSA_DETERMINISTIC)
+    ((void) f_rng);
+    ((void) p_rng);
+
+    return( ecdsa_write_signature_det( (ecdsa_context *) ctx,
+                hash, hash_len, sig, sig_len, md_alg ) );
+#else
+    ((void) md_alg);
+
+    return( ecdsa_write_signature( (ecdsa_context *) ctx,
+                hash, hash_len, sig, sig_len, f_rng, p_rng ) );
+#endif /* POLARSSL_ECDSA_DETERMINISTIC */
+}
+
+static void *ecdsa_alloc_wrap( void )
+{
+    void *ctx = polarssl_malloc( sizeof( ecdsa_context ) );
+
+    if( ctx != NULL )
+        ecdsa_init( (ecdsa_context *) ctx );
+
+    return( ctx );
+}
+
+static void ecdsa_free_wrap( void *ctx )
+{
+    ecdsa_free( (ecdsa_context *) ctx );
+    polarssl_free( ctx );
+}
+
+const pk_info_t ecdsa_info = {
+    POLARSSL_PK_ECDSA,
+    "ECDSA",
+    eckey_get_size,     /* Compatible key structures */
+    ecdsa_can_do,
+    ecdsa_verify_wrap,
+    ecdsa_sign_wrap,
+    NULL,
+    NULL,
+    ecdsa_alloc_wrap,
+    ecdsa_free_wrap,
+    eckey_debug,        /* Compatible key structures */
+};
+#endif /* POLARSSL_ECDSA_C */
+
+/*
+ * Support for alternative RSA-private implementations
+ */
+
+static size_t rsa_alt_get_size( const void *ctx )
+{
+    const rsa_alt_context *rsa_alt = (const rsa_alt_context *) ctx;
+
+    return( 8 * rsa_alt->key_len_func( rsa_alt->key ) );
+}
+
+static int rsa_alt_sign_wrap( void *ctx, 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 )
+{
+    rsa_alt_context *rsa_alt = (rsa_alt_context *) ctx;
+
+    *sig_len = rsa_alt->key_len_func( rsa_alt->key );
+
+    return( rsa_alt->sign_func( rsa_alt->key, f_rng, p_rng, RSA_PRIVATE,
+                md_alg, (unsigned int) hash_len, hash, sig ) );
+}
+
+static int rsa_alt_decrypt_wrap( 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 )
+{
+    rsa_alt_context *rsa_alt = (rsa_alt_context *) ctx;
+
+    ((void) f_rng);
+    ((void) p_rng);
+
+    if( ilen != rsa_alt->key_len_func( rsa_alt->key ) )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    return( rsa_alt->decrypt_func( rsa_alt->key,
+                RSA_PRIVATE, olen, input, output, osize ) );
+}
+
+static void *rsa_alt_alloc_wrap( void )
+{
+    void *ctx = polarssl_malloc( sizeof( rsa_alt_context ) );
+
+    if( ctx != NULL )
+        memset( ctx, 0, sizeof( rsa_alt_context ) );
+
+    return ctx;
+}
+
+static void rsa_alt_free_wrap( void *ctx )
+{
+    polarssl_free( ctx );
+}
+
+const pk_info_t rsa_alt_info = {
+    POLARSSL_PK_RSA_ALT,
+    "RSA-alt",
+    rsa_alt_get_size,
+    rsa_can_do,
+    NULL,
+    rsa_alt_sign_wrap,
+    rsa_alt_decrypt_wrap,
+    NULL,
+    rsa_alt_alloc_wrap,
+    rsa_alt_free_wrap,
+    NULL,
+};
+
+#endif /* POLARSSL_PK_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/pkcs11.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,238 @@
+/**
+ * \file pkcs11.c
+ *
+ * \brief Wrapper for PKCS#11 library libpkcs11-helper
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/pkcs11.h"
+
+#if defined(POLARSSL_PKCS11_C)
+#include "polarssl/md.h"
+#include "polarssl/oid.h"
+#include "polarssl/x509_crt.h"
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdlib.h>
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+int pkcs11_x509_cert_init( x509_crt *cert, pkcs11h_certificate_t pkcs11_cert )
+{
+    int ret = 1;
+    unsigned char *cert_blob = NULL;
+    size_t cert_blob_size = 0;
+
+    if( cert == NULL )
+    {
+        ret = 2;
+        goto cleanup;
+    }
+
+    if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, NULL,
+                                                &cert_blob_size ) != CKR_OK )
+    {
+        ret = 3;
+        goto cleanup;
+    }
+
+    cert_blob = polarssl_malloc( cert_blob_size );
+    if( NULL == cert_blob )
+    {
+        ret = 4;
+        goto cleanup;
+    }
+
+    if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, cert_blob,
+                                                &cert_blob_size ) != CKR_OK )
+    {
+        ret = 5;
+        goto cleanup;
+    }
+
+    if( 0 != x509_crt_parse(cert, cert_blob, cert_blob_size ) )
+    {
+        ret = 6;
+        goto cleanup;
+    }
+
+    ret = 0;
+
+cleanup:
+    if( NULL != cert_blob )
+        polarssl_free( cert_blob );
+
+    return ret;
+}
+
+
+int pkcs11_priv_key_init( pkcs11_context *priv_key,
+        pkcs11h_certificate_t pkcs11_cert )
+{
+    int ret = 1;
+    x509_crt cert;
+
+    x509_crt_init( &cert );
+
+    if( priv_key == NULL )
+        goto cleanup;
+
+    if( 0 != pkcs11_x509_cert_init( &cert, pkcs11_cert ) )
+        goto cleanup;
+
+    priv_key->len = pk_get_len(&cert.pk);
+    priv_key->pkcs11h_cert = pkcs11_cert;
+
+    ret = 0;
+
+cleanup:
+    x509_crt_free( &cert );
+
+    return ret;
+}
+
+void pkcs11_priv_key_free( pkcs11_context *priv_key )
+{
+    if( NULL != priv_key )
+        pkcs11h_certificate_freeCertificate( priv_key->pkcs11h_cert );
+}
+
+int pkcs11_decrypt( pkcs11_context *ctx,
+                       int mode, size_t *olen,
+                       const unsigned char *input,
+                       unsigned char *output,
+                       size_t output_max_len )
+{
+    size_t input_len, output_len;
+
+    if( NULL == ctx )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    if( RSA_PRIVATE != mode )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    output_len = input_len = ctx->len;
+
+    if( input_len < 16 || input_len > output_max_len )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    /* Determine size of output buffer */
+    if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input,
+            input_len, NULL, &output_len ) != CKR_OK )
+    {
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+    }
+
+    if( output_len > output_max_len )
+        return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE );
+
+    if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input,
+            input_len, output, &output_len ) != CKR_OK )
+    {
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+    }
+    *olen = output_len;
+    return( 0 );
+}
+
+int pkcs11_sign( pkcs11_context *ctx,
+                    int mode,
+                    md_type_t md_alg,
+                    unsigned int hashlen,
+                    const unsigned char *hash,
+                    unsigned char *sig )
+{
+    size_t sig_len = 0, asn_len = 0, oid_size = 0;
+    unsigned char *p = sig;
+    const char *oid;
+
+    if( NULL == ctx )
+        return POLARSSL_ERR_RSA_BAD_INPUT_DATA;
+
+    if( RSA_PRIVATE != mode )
+        return POLARSSL_ERR_RSA_BAD_INPUT_DATA;
+
+    if( md_alg != POLARSSL_MD_NONE )
+    {
+        const md_info_t *md_info = md_info_from_type( md_alg );
+        if( md_info == NULL )
+            return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+        if( oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 )
+            return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+        hashlen = md_get_size( md_info );
+        asn_len = 10 + oid_size;
+    }
+
+    sig_len = ctx->len;
+    if ( hashlen > sig_len || asn_len > sig_len ||
+         hashlen + asn_len > sig_len )
+    {
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+    }
+
+    if( md_alg != POLARSSL_MD_NONE)
+    {
+        /*
+         * DigestInfo ::= SEQUENCE {
+         *   digestAlgorithm DigestAlgorithmIdentifier,
+         *   digest Digest }
+         *
+         * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
+         *
+         * Digest ::= OCTET STRING
+         */
+        *p++ = ASN1_SEQUENCE | ASN1_CONSTRUCTED;
+        *p++ = (unsigned char) ( 0x08 + oid_size + hashlen );
+        *p++ = ASN1_SEQUENCE | ASN1_CONSTRUCTED;
+        *p++ = (unsigned char) ( 0x04 + oid_size );
+        *p++ = ASN1_OID;
+        *p++ = oid_size & 0xFF;
+        memcpy( p, oid, oid_size );
+        p += oid_size;
+        *p++ = ASN1_NULL;
+        *p++ = 0x00;
+        *p++ = ASN1_OCTET_STRING;
+        *p++ = hashlen;
+    }
+
+    memcpy( p, hash, hashlen );
+
+    if( pkcs11h_certificate_signAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, sig,
+            asn_len + hashlen, sig, &sig_len ) != CKR_OK )
+    {
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+    }
+
+    return( 0 );
+}
+
+#endif /* defined(POLARSSL_PKCS11_C) */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/pkcs12.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,340 @@
+/*
+ *  PKCS#12 Personal Information Exchange Syntax
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  The PKCS #12 Personal Information Exchange Syntax Standard v1.1
+ *
+ *  http://www.rsa.com/rsalabs/pkcs/files/h11301-wp-pkcs-12v1-1-personal-information-exchange-syntax.pdf
+ *  ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1-1.asn
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_PKCS12_C)
+
+#include "polarssl/pkcs12.h"
+#include "polarssl/asn1.h"
+#include "polarssl/cipher.h"
+
+#if defined(POLARSSL_ARC4_C)
+#include "polarssl/arc4.h"
+#endif
+
+#if defined(POLARSSL_DES_C)
+#include "polarssl/des.h"
+#endif
+
+static int pkcs12_parse_pbe_params( asn1_buf *params,
+                                    asn1_buf *salt, int *iterations )
+{
+    int ret;
+    unsigned char **p = &params->p;
+    const unsigned char *end = params->p + params->len;
+
+    /*
+     *  pkcs-12PbeParams ::= SEQUENCE {
+     *    salt          OCTET STRING,
+     *    iterations    INTEGER
+     *  }
+     *
+     */
+    if( params->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) )
+        return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT +
+                POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
+
+    if( ( ret = asn1_get_tag( p, end, &salt->len, ASN1_OCTET_STRING ) ) != 0 )
+        return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT + ret );
+
+    salt->p = *p;
+    *p += salt->len;
+
+    if( ( ret = asn1_get_int( p, end, iterations ) ) != 0 )
+        return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT + ret );
+
+    if( *p != end )
+        return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    return( 0 );
+}
+
+static int pkcs12_pbe_derive_key_iv( asn1_buf *pbe_params, md_type_t md_type,
+                                     const unsigned char *pwd,  size_t pwdlen,
+                                     unsigned char *key, size_t keylen,
+                                     unsigned char *iv,  size_t ivlen )
+{
+    int ret, iterations;
+    asn1_buf salt;
+    size_t i;
+    unsigned char unipwd[258];
+
+    memset(&salt, 0, sizeof(asn1_buf));
+    memset(&unipwd, 0, sizeof(unipwd));
+
+    if( ( ret = pkcs12_parse_pbe_params( pbe_params, &salt,
+                                         &iterations ) ) != 0 )
+        return( ret );
+
+    for(i = 0; i < pwdlen; i++)
+        unipwd[i * 2 + 1] = pwd[i];
+
+    if( ( ret = pkcs12_derivation( key, keylen, unipwd, pwdlen * 2 + 2,
+                                   salt.p, salt.len, md_type,
+                                   PKCS12_DERIVE_KEY, iterations ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    if( iv == NULL || ivlen == 0 )
+        return( 0 );
+
+    if( ( ret = pkcs12_derivation( iv, ivlen, unipwd, pwdlen * 2 + 2,
+                                   salt.p, salt.len, md_type,
+                                   PKCS12_DERIVE_IV, iterations ) ) != 0 )
+    {
+        return( ret );
+    }
+    return( 0 );
+}
+
+int pkcs12_pbe_sha1_rc4_128( asn1_buf *pbe_params, int mode,
+                             const unsigned char *pwd,  size_t pwdlen,
+                             const unsigned char *data, size_t len,
+                             unsigned char *output )
+{
+#if !defined(POLARSSL_ARC4_C)
+    ((void) pbe_params);
+    ((void) mode);
+    ((void) pwd);
+    ((void) pwdlen);
+    ((void) data);
+    ((void) len);
+    ((void) output);
+    return( POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE );
+#else
+    int ret;
+    unsigned char key[16];
+    arc4_context ctx;
+    ((void) mode);
+
+    if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, POLARSSL_MD_SHA1,
+                                          pwd, pwdlen,
+                                          key, 16, NULL, 0 ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    arc4_setup( &ctx, key, 16 );
+    if( ( ret = arc4_crypt( &ctx, len, data, output ) ) != 0 )
+        return( ret );
+
+    return( 0 );
+#endif /* POLARSSL_ARC4_C */
+}
+
+int pkcs12_pbe( asn1_buf *pbe_params, int mode,
+                cipher_type_t cipher_type, md_type_t md_type,
+                const unsigned char *pwd,  size_t pwdlen,
+                const unsigned char *data, size_t len,
+                unsigned char *output )
+{
+    int ret, keylen = 0;
+    unsigned char key[32];
+    unsigned char iv[16];
+    const cipher_info_t *cipher_info;
+    cipher_context_t cipher_ctx;
+    size_t olen = 0;
+
+    cipher_info = cipher_info_from_type( cipher_type );
+    if( cipher_info == NULL )
+        return( POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE );
+
+    keylen = cipher_info->key_length / 8;
+
+    if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, md_type, pwd, pwdlen,
+                                          key, keylen,
+                                          iv, cipher_info->iv_size ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    if( ( ret = cipher_init_ctx( &cipher_ctx, cipher_info ) ) != 0 )
+        goto exit;
+
+    if( ( ret = cipher_setkey( &cipher_ctx, key, 8 * keylen, mode ) ) != 0 )
+        goto exit;
+
+    if( ( ret = cipher_set_iv( &cipher_ctx, iv, cipher_info->iv_size ) ) != 0 )
+        goto exit;
+
+    if( ( ret = cipher_reset( &cipher_ctx ) ) != 0 )
+        goto exit;
+
+    if( ( ret = cipher_update( &cipher_ctx, data, len,
+                                output, &olen ) ) != 0 )
+    {
+        goto exit;
+    }
+
+    if( ( ret = cipher_finish( &cipher_ctx, output + olen, &olen ) ) != 0 )
+        ret = POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH;
+
+exit:
+    cipher_free_ctx( &cipher_ctx );
+
+    return( ret );
+}
+
+static void pkcs12_fill_buffer( unsigned char *data, size_t data_len,
+                                const unsigned char *filler, size_t fill_len )
+{
+    unsigned char *p = data;
+    size_t use_len;
+
+    while( data_len > 0 )
+    {
+        use_len = ( data_len > fill_len ) ? fill_len : data_len;
+        memcpy( p, filler, use_len );
+        p += use_len;
+        data_len -= use_len;
+    }
+}
+
+int pkcs12_derivation( unsigned char *data, size_t datalen,
+                       const unsigned char *pwd, size_t pwdlen,
+                       const unsigned char *salt, size_t saltlen,
+                       md_type_t md_type, int id, int iterations )
+{
+    int ret;
+    unsigned int j;
+
+    unsigned char diversifier[128];
+    unsigned char salt_block[128], pwd_block[128], hash_block[128];
+    unsigned char hash_output[POLARSSL_MD_MAX_SIZE];
+    unsigned char *p;
+    unsigned char c;
+
+    size_t hlen, use_len, v, i;
+
+    const md_info_t *md_info;
+    md_context_t md_ctx;
+
+    // This version only allows max of 64 bytes of password or salt
+    if( datalen > 128 || pwdlen > 64 || saltlen > 64 )
+        return( POLARSSL_ERR_PKCS12_BAD_INPUT_DATA );
+
+    md_info = md_info_from_type( md_type );
+    if( md_info == NULL )
+        return( POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE );
+
+    if ( ( ret = md_init_ctx( &md_ctx, md_info ) ) != 0 )
+        return( ret );
+    hlen = md_get_size( md_info );
+
+    if( hlen <= 32 )
+        v = 64;
+    else
+        v = 128;
+
+    memset( diversifier, (unsigned char) id, v );
+
+    pkcs12_fill_buffer( salt_block, v, salt, saltlen );
+    pkcs12_fill_buffer( pwd_block,  v, pwd,  pwdlen  );
+
+    p = data;
+    while( datalen > 0 )
+    {
+        // Calculate hash( diversifier || salt_block || pwd_block )
+        if( ( ret = md_starts( &md_ctx ) ) != 0 )
+            goto exit;
+
+        if( ( ret = md_update( &md_ctx, diversifier, v ) ) != 0 )
+            goto exit;
+
+        if( ( ret = md_update( &md_ctx, salt_block, v ) ) != 0 )
+            goto exit;
+
+        if( ( ret = md_update( &md_ctx, pwd_block, v ) ) != 0 )
+            goto exit;
+
+        if( ( ret = md_finish( &md_ctx, hash_output ) ) != 0 )
+            goto exit;
+
+        // Perform remaining ( iterations - 1 ) recursive hash calculations
+        for( i = 1; i < (size_t) iterations; i++ )
+        {
+            if( ( ret = md( md_info, hash_output, hlen, hash_output ) ) != 0 )
+                goto exit;
+        }
+
+        use_len = ( datalen > hlen ) ? hlen : datalen;
+        memcpy( p, hash_output, use_len );
+        datalen -= use_len;
+        p += use_len;
+
+        if( datalen == 0 )
+            break;
+
+        // Concatenating copies of hash_output into hash_block (B)
+        pkcs12_fill_buffer( hash_block, v, hash_output, hlen );
+
+        // B += 1
+        for( i = v; i > 0; i-- )
+            if( ++hash_block[i - 1] != 0 )
+                break;
+
+        // salt_block += B
+        c = 0;
+        for( i = v; i > 0; i-- )
+        {
+            j = salt_block[i - 1] + hash_block[i - 1] + c;
+            c = (unsigned char) (j >> 8);
+            salt_block[i - 1] = j & 0xFF;
+        }
+
+        // pwd_block  += B
+        c = 0;
+        for( i = v; i > 0; i-- )
+        {
+            j = pwd_block[i - 1] + hash_block[i - 1] + c;
+            c = (unsigned char) (j >> 8);
+            pwd_block[i - 1] = j & 0xFF;
+        }
+    }
+
+    ret = 0;
+
+exit:
+    md_free_ctx( &md_ctx );
+
+    return( ret );
+}
+
+#endif /* POLARSSL_PKCS12_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/pkcs5.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,406 @@
+/**
+ * \file pkcs5.c
+ *
+ * \brief PKCS#5 functions
+ *
+ * \author Mathias Olsson <mathias@kompetensum.com>
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * PKCS#5 includes PBKDF2 and more
+ *
+ * http://tools.ietf.org/html/rfc2898 (Specification)
+ * http://tools.ietf.org/html/rfc6070 (Test vectors)
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_PKCS5_C)
+
+#include "polarssl/pkcs5.h"
+#include "polarssl/asn1.h"
+#include "polarssl/cipher.h"
+#include "polarssl/oid.h"
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
+static int pkcs5_parse_pbkdf2_params( asn1_buf *params,
+                                      asn1_buf *salt, int *iterations,
+                                      int *keylen, md_type_t *md_type )
+{
+    int ret;
+    asn1_buf prf_alg_oid;
+    unsigned char **p = &params->p;
+    const unsigned char *end = params->p + params->len;
+
+    if( params->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) )
+        return( POLARSSL_ERR_PKCS5_INVALID_FORMAT +
+                POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
+    /*
+     *  PBKDF2-params ::= SEQUENCE {
+     *    salt              OCTET STRING,
+     *    iterationCount    INTEGER,
+     *    keyLength         INTEGER OPTIONAL
+     *    prf               AlgorithmIdentifier DEFAULT algid-hmacWithSHA1
+     *  }
+     *
+     */
+    if( ( ret = asn1_get_tag( p, end, &salt->len, ASN1_OCTET_STRING ) ) != 0 )
+        return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret );
+
+    salt->p = *p;
+    *p += salt->len;
+
+    if( ( ret = asn1_get_int( p, end, iterations ) ) != 0 )
+        return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret );
+
+    if( *p == end )
+        return( 0 );
+
+    if( ( ret = asn1_get_int( p, end, keylen ) ) != 0 )
+    {
+        if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+            return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret );
+    }
+
+    if( *p == end )
+        return( 0 );
+
+    if( ( ret = asn1_get_alg_null( p, end, &prf_alg_oid ) ) != 0 )
+        return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret );
+
+    if( !OID_CMP( OID_HMAC_SHA1, &prf_alg_oid ) )
+        return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE );
+
+    *md_type = POLARSSL_MD_SHA1;
+
+    if( *p != end )
+        return( POLARSSL_ERR_PKCS5_INVALID_FORMAT +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    return( 0 );
+}
+
+int pkcs5_pbes2( asn1_buf *pbe_params, int mode,
+                 const unsigned char *pwd,  size_t pwdlen,
+                 const unsigned char *data, size_t datalen,
+                 unsigned char *output )
+{
+    int ret, iterations = 0, keylen = 0;
+    unsigned char *p, *end;
+    asn1_buf kdf_alg_oid, enc_scheme_oid, kdf_alg_params, enc_scheme_params;
+    asn1_buf salt;
+    md_type_t md_type = POLARSSL_MD_SHA1;
+    unsigned char key[32], iv[32];
+    size_t olen = 0;
+    const md_info_t *md_info;
+    const cipher_info_t *cipher_info;
+    md_context_t md_ctx;
+    cipher_type_t cipher_alg;
+    cipher_context_t cipher_ctx;
+
+    p = pbe_params->p;
+    end = p + pbe_params->len;
+
+    memset( &md_ctx, 0, sizeof(md_context_t) );
+    memset( &cipher_ctx, 0, sizeof(cipher_context_t) );
+
+    /*
+     *  PBES2-params ::= SEQUENCE {
+     *    keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},
+     *    encryptionScheme AlgorithmIdentifier {{PBES2-Encs}}
+     *  }
+     */
+    if( pbe_params->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) )
+        return( POLARSSL_ERR_PKCS5_INVALID_FORMAT +
+                POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
+
+    if( ( ret = asn1_get_alg( &p, end, &kdf_alg_oid, &kdf_alg_params ) ) != 0 )
+        return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret );
+
+    // Only PBKDF2 supported at the moment
+    //
+    if( !OID_CMP( OID_PKCS5_PBKDF2, &kdf_alg_oid ) )
+        return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE );
+
+    if( ( ret = pkcs5_parse_pbkdf2_params( &kdf_alg_params,
+                                           &salt, &iterations, &keylen,
+                                           &md_type ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    md_info = md_info_from_type( md_type );
+    if( md_info == NULL )
+        return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE );
+
+    if( ( ret = asn1_get_alg( &p, end, &enc_scheme_oid,
+                              &enc_scheme_params ) ) != 0 )
+    {
+        return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret );
+    }
+
+    if ( oid_get_cipher_alg( &enc_scheme_oid, &cipher_alg ) != 0 )
+        return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE );
+
+    cipher_info = cipher_info_from_type( cipher_alg );
+    if( cipher_info == NULL )
+        return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE );
+
+    keylen = cipher_info->key_length / 8;
+
+    if( enc_scheme_params.tag != ASN1_OCTET_STRING ||
+        enc_scheme_params.len != cipher_info->iv_size )
+    {
+        return( POLARSSL_ERR_PKCS5_INVALID_FORMAT );
+    }
+
+    memcpy( iv, enc_scheme_params.p, enc_scheme_params.len );
+
+    if( ( ret = md_init_ctx( &md_ctx, md_info ) ) != 0 )
+        goto exit;
+
+    if ( ( ret = pkcs5_pbkdf2_hmac( &md_ctx, pwd, pwdlen, salt.p, salt.len,
+                                    iterations, keylen, key ) ) != 0 )
+    {
+        goto exit;
+    }
+
+    if( ( ret = cipher_init_ctx( &cipher_ctx, cipher_info ) ) != 0 )
+        goto exit;
+
+    if( ( ret = cipher_setkey( &cipher_ctx, key, 8 * keylen, mode ) ) != 0 )
+        goto exit;
+
+    if( ( ret = cipher_set_iv( &cipher_ctx, iv, enc_scheme_params.len ) ) != 0 )
+        goto exit;
+
+    if( ( ret = cipher_reset( &cipher_ctx ) ) != 0 )
+        goto exit;
+
+    if( ( ret = cipher_update( &cipher_ctx, data, datalen,
+                                output, &olen ) ) != 0 )
+    {
+        goto exit;
+    }
+
+    if( ( ret = cipher_finish( &cipher_ctx, output + olen, &olen ) ) != 0 )
+        ret = POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH;
+
+exit:
+    md_free_ctx( &md_ctx );
+    cipher_free_ctx( &cipher_ctx );
+
+    return( ret );
+}
+
+int pkcs5_pbkdf2_hmac( 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 )
+{
+    int ret, j;
+    unsigned int i;
+    unsigned char md1[POLARSSL_MD_MAX_SIZE];
+    unsigned char work[POLARSSL_MD_MAX_SIZE];
+    unsigned char md_size = md_get_size( ctx->md_info );
+    size_t use_len;
+    unsigned char *out_p = output;
+    unsigned char counter[4];
+
+    memset( counter, 0, 4 );
+    counter[3] = 1;
+
+    if( iteration_count > 0xFFFFFFFF )
+        return( POLARSSL_ERR_PKCS5_BAD_INPUT_DATA );
+
+    while( key_length )
+    {
+        // U1 ends up in work
+        //
+        if( ( ret = md_hmac_starts( ctx, password, plen ) ) != 0 )
+            return( ret );
+
+        if( ( ret = md_hmac_update( ctx, salt, slen ) ) != 0 )
+            return( ret );
+
+        if( ( ret = md_hmac_update( ctx, counter, 4 ) ) != 0 )
+            return( ret );
+
+        if( ( ret = md_hmac_finish( ctx, work ) ) != 0 )
+            return( ret );
+
+        memcpy( md1, work, md_size );
+
+        for ( i = 1; i < iteration_count; i++ )
+        {
+            // U2 ends up in md1
+            //
+            if( ( ret = md_hmac_starts( ctx, password, plen ) ) != 0 )
+                return( ret );
+
+            if( ( ret = md_hmac_update( ctx, md1, md_size ) ) != 0 )
+                return( ret );
+
+            if( ( ret = md_hmac_finish( ctx, md1 ) ) != 0 )
+                return( ret );
+
+            // U1 xor U2
+            //
+            for( j = 0; j < md_size; j++ )
+                work[j] ^= md1[j];
+        }
+
+        use_len = ( key_length < md_size ) ? key_length : md_size;
+        memcpy( out_p, work, use_len );
+
+        key_length -= (uint32_t) use_len;
+        out_p += use_len;
+
+        for( i = 4; i > 0; i-- )
+            if( ++counter[i - 1] != 0 )
+                break;
+    }
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include <stdio.h>
+
+#define MAX_TESTS   6
+
+size_t plen[MAX_TESTS] =
+    { 8, 8, 8, 8, 24, 9 };
+
+unsigned char password[MAX_TESTS][32] =
+{
+    "password",
+    "password",
+    "password",
+    "password",
+    "passwordPASSWORDpassword",
+    "pass\0word",
+};
+
+size_t slen[MAX_TESTS] =
+    { 4, 4, 4, 4, 36, 5 };
+
+unsigned char salt[MAX_TESTS][40] =
+{
+    "salt",
+    "salt",
+    "salt",
+    "salt",
+    "saltSALTsaltSALTsaltSALTsaltSALTsalt",
+    "sa\0lt",
+};
+
+uint32_t it_cnt[MAX_TESTS] =
+    { 1, 2, 4096, 16777216, 4096, 4096 };
+
+uint32_t key_len[MAX_TESTS] =
+    { 20, 20, 20, 20, 25, 16 };
+
+
+unsigned char result_key[MAX_TESTS][32] =
+{
+    { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71,
+      0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06,
+      0x2f, 0xe0, 0x37, 0xa6 },
+    { 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c,
+      0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0,
+      0xd8, 0xde, 0x89, 0x57 },
+    { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a,
+      0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0,
+      0x65, 0xa4, 0x29, 0xc1 },
+    { 0xee, 0xfe, 0x3d, 0x61, 0xcd, 0x4d, 0xa4, 0xe4,
+      0xe9, 0x94, 0x5b, 0x3d, 0x6b, 0xa2, 0x15, 0x8c,
+      0x26, 0x34, 0xe9, 0x84 },
+    { 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b,
+      0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a,
+      0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70,
+      0x38 },
+    { 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d,
+      0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 },
+};
+
+int pkcs5_self_test( int verbose )
+{
+    md_context_t sha1_ctx;
+    const md_info_t *info_sha1;
+    int ret, i;
+    unsigned char key[64];
+
+    info_sha1 = md_info_from_type( POLARSSL_MD_SHA1 );
+    if( info_sha1 == NULL )
+        return( 1 );
+
+    if( ( ret = md_init_ctx( &sha1_ctx, info_sha1 ) ) != 0 )
+        return( 1 );
+
+    if( verbose != 0 )
+        polarssl_printf( "  PBKDF2 note: test #3 may be slow!\n" );
+
+    for( i = 0; i < MAX_TESTS; i++ )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "  PBKDF2 (SHA1) #%d: ", i );
+
+        ret = pkcs5_pbkdf2_hmac( &sha1_ctx, password[i], plen[i], salt[i],
+                                  slen[i], it_cnt[i], key_len[i], key );
+        if( ret != 0 ||
+            memcmp( result_key[i], key, key_len[i] ) != 0 )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "passed\n" );
+    }
+
+    polarssl_printf( "\n" );
+
+    if( ( ret = md_free_ctx( &sha1_ctx ) ) != 0 )
+        return( 1 );
+
+    return( 0 );
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_PKCS5_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/pkparse.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,1253 @@
+/*
+ *  Public Key layer for parsing key files and structures
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_PK_PARSE_C)
+
+#include "polarssl/pk.h"
+#include "polarssl/asn1.h"
+#include "polarssl/oid.h"
+
+#if defined(POLARSSL_RSA_C)
+#include "polarssl/rsa.h"
+#endif
+#if defined(POLARSSL_ECP_C)
+#include "polarssl/ecp.h"
+#endif
+#if defined(POLARSSL_ECDSA_C)
+#include "polarssl/ecdsa.h"
+#endif
+#if defined(POLARSSL_PEM_PARSE_C)
+#include "polarssl/pem.h"
+#endif
+#if defined(POLARSSL_PKCS5_C)
+#include "polarssl/pkcs5.h"
+#endif
+#if defined(POLARSSL_PKCS12_C)
+#include "polarssl/pkcs12.h"
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdlib.h>
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * Load all data from a file into a given buffer.
+ */
+static int load_file( const char *path, unsigned char **buf, size_t *n )
+{
+    FILE *f;
+    long size;
+
+    if( ( f = fopen( path, "rb" ) ) == NULL )
+        return( POLARSSL_ERR_PK_FILE_IO_ERROR );
+
+    fseek( f, 0, SEEK_END );
+    if( ( size = ftell( f ) ) == -1 )
+    {
+        fclose( f );
+        return( POLARSSL_ERR_PK_FILE_IO_ERROR );
+    }
+    fseek( f, 0, SEEK_SET );
+
+    *n = (size_t) size;
+
+    if( *n + 1 == 0 ||
+        ( *buf = (unsigned char *) polarssl_malloc( *n + 1 ) ) == NULL )
+    {
+        fclose( f );
+        return( POLARSSL_ERR_PK_MALLOC_FAILED );
+    }
+
+    if( fread( *buf, 1, *n, f ) != *n )
+    {
+        fclose( f );
+        polarssl_free( *buf );
+        return( POLARSSL_ERR_PK_FILE_IO_ERROR );
+    }
+
+    fclose( f );
+
+    (*buf)[*n] = '\0';
+
+    return( 0 );
+}
+
+/*
+ * Load and parse a private key
+ */
+int pk_parse_keyfile( pk_context *ctx,
+                      const char *path, const char *pwd )
+{
+    int ret;
+    size_t n;
+    unsigned char *buf;
+
+    if ( (ret = load_file( path, &buf, &n ) ) != 0 )
+        return( ret );
+
+    if( pwd == NULL )
+        ret = pk_parse_key( ctx, buf, n, NULL, 0 );
+    else
+        ret = pk_parse_key( ctx, buf, n,
+                (const unsigned char *) pwd, strlen( pwd ) );
+
+    memset( buf, 0, n + 1 );
+    polarssl_free( buf );
+
+    return( ret );
+}
+
+/*
+ * Load and parse a public key
+ */
+int pk_parse_public_keyfile( pk_context *ctx, const char *path )
+{
+    int ret;
+    size_t n;
+    unsigned char *buf;
+
+    if ( (ret = load_file( path, &buf, &n ) ) != 0 )
+        return( ret );
+
+    ret = pk_parse_public_key( ctx, buf, n );
+
+    memset( buf, 0, n + 1 );
+    polarssl_free( buf );
+
+    return( ret );
+}
+#endif /* POLARSSL_FS_IO */
+
+#if defined(POLARSSL_ECP_C)
+/* Minimally parse an ECParameters buffer to and asn1_buf
+ *
+ * ECParameters ::= CHOICE {
+ *   namedCurve         OBJECT IDENTIFIER
+ *   specifiedCurve     SpecifiedECDomain -- = SEQUENCE { ... }
+ *   -- implicitCurve   NULL
+ * }
+ */
+static int pk_get_ecparams( unsigned char **p, const unsigned char *end,
+                            asn1_buf *params )
+{
+    int ret;
+
+    /* Tag may be either OID or SEQUENCE */
+    params->tag = **p;
+    if( params->tag != ASN1_OID
+#if defined(POLARSSL_PK_PARSE_EC_EXTENDED)
+            && params->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE )
+#endif
+            )
+    {
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT +
+                POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
+    }
+
+    if( ( ret = asn1_get_tag( p, end, &params->len, params->tag ) ) != 0 )
+    {
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+    }
+
+    params->p = *p;
+    *p += params->len;
+
+    if( *p != end )
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_PK_PARSE_EC_EXTENDED)
+/*
+ * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it.
+ * WARNING: the resulting group should only be used with
+ * pk_group_id_from_specified(), since its base point may not be set correctly
+ * if it was encoded compressed.
+ *
+ *  SpecifiedECDomain ::= SEQUENCE {
+ *      version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...),
+ *      fieldID FieldID {{FieldTypes}},
+ *      curve Curve,
+ *      base ECPoint,
+ *      order INTEGER,
+ *      cofactor INTEGER OPTIONAL,
+ *      hash HashAlgorithm OPTIONAL,
+ *      ...
+ *  }
+ *
+ * We only support prime-field as field type, and ignore hash and cofactor.
+ */
+static int pk_group_from_specified( const asn1_buf *params, ecp_group *grp )
+{
+    int ret;
+    unsigned char *p = params->p;
+    const unsigned char * const end = params->p + params->len;
+    const unsigned char *end_field, *end_curve;
+    size_t len;
+    int ver;
+
+    /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */
+    if( ( ret = asn1_get_int( &p, end, &ver ) ) != 0 )
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+    if( ver < 1 || ver > 3 )
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT );
+
+    /*
+     * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field
+     *       fieldType FIELD-ID.&id({IOSet}),
+     *       parameters FIELD-ID.&Type({IOSet}{@fieldType})
+     * }
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+        return( ret );
+
+    end_field = p + len;
+
+    /*
+     * FIELD-ID ::= TYPE-IDENTIFIER
+     * FieldTypes FIELD-ID ::= {
+     *       { Prime-p IDENTIFIED BY prime-field } |
+     *       { Characteristic-two IDENTIFIED BY characteristic-two-field }
+     * }
+     * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 }
+     */
+    if( ( ret = asn1_get_tag( &p, end_field, &len, ASN1_OID ) ) != 0 )
+        return( ret );
+
+    if( len != OID_SIZE( OID_ANSI_X9_62_PRIME_FIELD ) ||
+        memcmp( p, OID_ANSI_X9_62_PRIME_FIELD, len ) != 0 )
+    {
+        return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE );
+    }
+
+    p += len;
+
+    /* Prime-p ::= INTEGER -- Field of size p. */
+    if( ( ret = asn1_get_mpi( &p, end_field, &grp->P ) ) != 0 )
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+    grp->pbits = mpi_msb( &grp->P );
+
+    if( p != end_field )
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    /*
+     * Curve ::= SEQUENCE {
+     *       a FieldElement,
+     *       b FieldElement,
+     *       seed BIT STRING OPTIONAL
+     *       -- Shall be present if used in SpecifiedECDomain
+     *       -- with version equal to ecdpVer2 or ecdpVer3
+     * }
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+        return( ret );
+
+    end_curve = p + len;
+
+    /*
+     * FieldElement ::= OCTET STRING
+     * containing an integer in the case of a prime field
+     */
+    if( ( ret = asn1_get_tag( &p, end_curve, &len, ASN1_OCTET_STRING ) ) != 0 ||
+        ( ret = mpi_read_binary( &grp->A, p, len ) ) != 0 )
+    {
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+    }
+
+    p += len;
+
+    if( ( ret = asn1_get_tag( &p, end_curve, &len, ASN1_OCTET_STRING ) ) != 0 ||
+        ( ret = mpi_read_binary( &grp->B, p, len ) ) != 0 )
+    {
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+    }
+
+    p += len;
+
+    /* Ignore seed BIT STRING OPTIONAL */
+    if( ( ret = asn1_get_tag( &p, end_curve, &len, ASN1_BIT_STRING ) ) == 0 )
+        p += len;
+
+    if( p != end_curve )
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    /*
+     * ECPoint ::= OCTET STRING
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 )
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+    if( ( ret = ecp_point_read_binary( grp, &grp->G,
+                                      ( const unsigned char *) p, len ) ) != 0 )
+    {
+        /*
+         * If we can't read the point because it's compressed, cheat by
+         * reading only the X coordinate and the parity bit of Y.
+         */
+        if( ret != POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE ||
+            ( p[0] != 0x02 && p[0] != 0x03 ) ||
+            len != mpi_size( &grp->P ) + 1 ||
+            mpi_read_binary( &grp->G.X, p + 1, len - 1 ) != 0 ||
+            mpi_lset( &grp->G.Y, p[0] - 2 ) != 0 ||
+            mpi_lset( &grp->G.Z, 1 ) != 0 )
+        {
+            return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT );
+        }
+    }
+
+    p += len;
+
+    /*
+     * order INTEGER
+     */
+    if( ( ret = asn1_get_mpi( &p, end, &grp->N ) ) )
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+    grp->nbits = mpi_msb( &grp->N );
+
+    /*
+     * Allow optional elements by purposefully not enforcing p == end here.
+     */
+
+    return( 0 );
+}
+
+/*
+ * Find the group id associated with an (almost filled) group as generated by
+ * pk_group_from_specified(), or return an error if unknown.
+ */
+static int pk_group_id_from_group( const ecp_group *grp, ecp_group_id *grp_id )
+{
+    int ret = 0;
+    ecp_group ref;
+    const ecp_group_id *id;
+
+    ecp_group_init( &ref );
+
+    for( id = ecp_grp_id_list(); *id != POLARSSL_ECP_DP_NONE; id++ )
+    {
+        /* Load the group associated to that id */
+        ecp_group_free( &ref );
+        MPI_CHK( ecp_use_known_dp( &ref, *id ) );
+
+        /* Compare to the group we were given, starting with easy tests */
+        if( grp->pbits == ref.pbits && grp->nbits == ref.nbits &&
+            mpi_cmp_mpi( &grp->P, &ref.P ) == 0 &&
+            mpi_cmp_mpi( &grp->A, &ref.A ) == 0 &&
+            mpi_cmp_mpi( &grp->B, &ref.B ) == 0 &&
+            mpi_cmp_mpi( &grp->N, &ref.N ) == 0 &&
+            mpi_cmp_mpi( &grp->G.X, &ref.G.X ) == 0 &&
+            mpi_cmp_mpi( &grp->G.Z, &ref.G.Z ) == 0 &&
+            /* For Y we may only know the parity bit, so compare only that */
+            mpi_get_bit( &grp->G.Y, 0 ) == mpi_get_bit( &ref.G.Y, 0 ) )
+        {
+            break;
+        }
+
+    }
+
+cleanup:
+    ecp_group_free( &ref );
+
+    *grp_id = *id;
+
+    if( ret == 0 && *id == POLARSSL_ECP_DP_NONE )
+        ret = POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE;
+
+    return( ret );
+}
+
+/*
+ * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID
+ */
+static int pk_group_id_from_specified( const asn1_buf *params,
+                                       ecp_group_id *grp_id )
+{
+    int ret;
+    ecp_group grp;
+
+    ecp_group_init( &grp );
+
+    if( ( ret = pk_group_from_specified( params, &grp ) ) != 0 )
+        goto cleanup;
+
+    ret = pk_group_id_from_group( &grp, grp_id );
+
+cleanup:
+    ecp_group_free( &grp );
+
+    return( ret );
+}
+#endif /* POLARSSL_PK_PARSE_EC_EXTENDED */
+
+/*
+ * Use EC parameters to initialise an EC group
+ *
+ * ECParameters ::= CHOICE {
+ *   namedCurve         OBJECT IDENTIFIER
+ *   specifiedCurve     SpecifiedECDomain -- = SEQUENCE { ... }
+ *   -- implicitCurve   NULL
+ */
+static int pk_use_ecparams( const asn1_buf *params, ecp_group *grp )
+{
+    int ret;
+    ecp_group_id grp_id;
+
+    if( params->tag == ASN1_OID )
+    {
+        if( oid_get_ec_grp( params, &grp_id ) != 0 )
+            return( POLARSSL_ERR_PK_UNKNOWN_NAMED_CURVE );
+    }
+    else
+    {
+#if defined(POLARSSL_PK_PARSE_EC_EXTENDED)
+        if( ( ret = pk_group_id_from_specified( params, &grp_id ) ) != 0 )
+            return( ret );
+#else
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT );
+#endif
+    }
+
+    /*
+     * grp may already be initilialized; if so, make sure IDs match
+     */
+    if( grp->id != POLARSSL_ECP_DP_NONE && grp->id != grp_id )
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT );
+
+    if( ( ret = ecp_use_known_dp( grp, grp_id ) ) != 0 )
+        return( ret );
+
+    return( 0 );
+}
+
+/*
+ * EC public key is an EC point
+ *
+ * The caller is responsible for clearing the structure upon failure if
+ * desired. Take care to pass along the possible ECP_FEATURE_UNAVAILABLE
+ * return code of ecp_point_read_binary() and leave p in a usable state.
+ */
+static int pk_get_ecpubkey( unsigned char **p, const unsigned char *end,
+                            ecp_keypair *key )
+{
+    int ret;
+
+    if( ( ret = ecp_point_read_binary( &key->grp, &key->Q,
+                    (const unsigned char *) *p, end - *p ) ) == 0 )
+    {
+        ret = ecp_check_pubkey( &key->grp, &key->Q );
+    }
+
+    /*
+     * We know ecp_point_read_binary consumed all bytes or failed
+     */
+    *p = (unsigned char *) end;
+
+    return( ret );
+}
+#endif /* POLARSSL_ECP_C */
+
+#if defined(POLARSSL_RSA_C)
+/*
+ *  RSAPublicKey ::= SEQUENCE {
+ *      modulus           INTEGER,  -- n
+ *      publicExponent    INTEGER   -- e
+ *  }
+ */
+static int pk_get_rsapubkey( unsigned char **p,
+                             const unsigned char *end,
+                             rsa_context *rsa )
+{
+    int ret;
+    size_t len;
+
+    if( ( ret = asn1_get_tag( p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+        return( POLARSSL_ERR_PK_INVALID_PUBKEY + ret );
+
+    if( *p + len != end )
+        return( POLARSSL_ERR_PK_INVALID_PUBKEY +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    if( ( ret = asn1_get_mpi( p, end, &rsa->N ) ) != 0 ||
+        ( ret = asn1_get_mpi( p, end, &rsa->E ) ) != 0 )
+        return( POLARSSL_ERR_PK_INVALID_PUBKEY + ret );
+
+    if( *p != end )
+        return( POLARSSL_ERR_PK_INVALID_PUBKEY +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    if( ( ret = rsa_check_pubkey( rsa ) ) != 0 )
+        return( POLARSSL_ERR_PK_INVALID_PUBKEY );
+
+    rsa->len = mpi_size( &rsa->N );
+
+    return( 0 );
+}
+#endif /* POLARSSL_RSA_C */
+
+/* Get a PK algorithm identifier
+ *
+ *  AlgorithmIdentifier  ::=  SEQUENCE  {
+ *       algorithm               OBJECT IDENTIFIER,
+ *       parameters              ANY DEFINED BY algorithm OPTIONAL  }
+ */
+static int pk_get_pk_alg( unsigned char **p,
+                          const unsigned char *end,
+                          pk_type_t *pk_alg, asn1_buf *params )
+{
+    int ret;
+    asn1_buf alg_oid;
+
+    memset( params, 0, sizeof(asn1_buf) );
+
+    if( ( ret = asn1_get_alg( p, end, &alg_oid, params ) ) != 0 )
+        return( POLARSSL_ERR_PK_INVALID_ALG + ret );
+
+    if( oid_get_pk_alg( &alg_oid, pk_alg ) != 0 )
+        return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG );
+
+    /*
+     * No parameters with RSA (only for EC)
+     */
+    if( *pk_alg == POLARSSL_PK_RSA &&
+            ( ( params->tag != ASN1_NULL && params->tag != 0 ) ||
+                params->len != 0 ) )
+    {
+        return( POLARSSL_ERR_PK_INVALID_ALG );
+    }
+
+    return( 0 );
+}
+
+/*
+ *  SubjectPublicKeyInfo  ::=  SEQUENCE  {
+ *       algorithm            AlgorithmIdentifier,
+ *       subjectPublicKey     BIT STRING }
+ */
+int pk_parse_subpubkey( unsigned char **p, const unsigned char *end,
+                        pk_context *pk )
+{
+    int ret;
+    size_t len;
+    asn1_buf alg_params;
+    pk_type_t pk_alg = POLARSSL_PK_NONE;
+    const pk_info_t *pk_info;
+
+    if( ( ret = asn1_get_tag( p, end, &len,
+                    ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+    }
+
+    end = *p + len;
+
+    if( ( ret = pk_get_pk_alg( p, end, &pk_alg, &alg_params ) ) != 0 )
+        return( ret );
+
+    if( ( ret = asn1_get_bitstring_null( p, end, &len ) ) != 0 )
+        return( POLARSSL_ERR_PK_INVALID_PUBKEY + ret );
+
+    if( *p + len != end )
+        return( POLARSSL_ERR_PK_INVALID_PUBKEY +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    if( ( pk_info = pk_info_from_type( pk_alg ) ) == NULL )
+        return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG );
+
+    if( ( ret = pk_init_ctx( pk, pk_info ) ) != 0 )
+        return( ret );
+
+#if defined(POLARSSL_RSA_C)
+    if( pk_alg == POLARSSL_PK_RSA )
+    {
+        ret = pk_get_rsapubkey( p, end, pk_rsa( *pk ) );
+    } else
+#endif /* POLARSSL_RSA_C */
+#if defined(POLARSSL_ECP_C)
+    if( pk_alg == POLARSSL_PK_ECKEY_DH || pk_alg == POLARSSL_PK_ECKEY )
+    {
+        ret = pk_use_ecparams( &alg_params, &pk_ec( *pk )->grp );
+        if( ret == 0 )
+            ret = pk_get_ecpubkey( p, end, pk_ec( *pk ) );
+    } else
+#endif /* POLARSSL_ECP_C */
+        ret = POLARSSL_ERR_PK_UNKNOWN_PK_ALG;
+
+    if( ret == 0 && *p != end )
+        ret = POLARSSL_ERR_PK_INVALID_PUBKEY
+              POLARSSL_ERR_ASN1_LENGTH_MISMATCH;
+
+    if( ret != 0 )
+        pk_free( pk );
+
+    return( ret );
+}
+
+#if defined(POLARSSL_RSA_C)
+/*
+ * Parse a PKCS#1 encoded private RSA key
+ */
+static int pk_parse_key_pkcs1_der( rsa_context *rsa,
+                                   const unsigned char *key,
+                                   size_t keylen )
+{
+    int ret;
+    size_t len;
+    unsigned char *p, *end;
+
+    p = (unsigned char *) key;
+    end = p + keylen;
+
+    /*
+     * This function parses the RSAPrivateKey (PKCS#1)
+     *
+     *  RSAPrivateKey ::= SEQUENCE {
+     *      version           Version,
+     *      modulus           INTEGER,  -- n
+     *      publicExponent    INTEGER,  -- e
+     *      privateExponent   INTEGER,  -- d
+     *      prime1            INTEGER,  -- p
+     *      prime2            INTEGER,  -- q
+     *      exponent1         INTEGER,  -- d mod (p-1)
+     *      exponent2         INTEGER,  -- d mod (q-1)
+     *      coefficient       INTEGER,  -- (inverse of q) mod p
+     *      otherPrimeInfos   OtherPrimeInfos OPTIONAL
+     *  }
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+    }
+
+    end = p + len;
+
+    if( ( ret = asn1_get_int( &p, end, &rsa->ver ) ) != 0 )
+    {
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+    }
+
+    if( rsa->ver != 0 )
+    {
+        return( POLARSSL_ERR_PK_KEY_INVALID_VERSION );
+    }
+
+    if( ( ret = asn1_get_mpi( &p, end, &rsa->N  ) ) != 0 ||
+        ( ret = asn1_get_mpi( &p, end, &rsa->E  ) ) != 0 ||
+        ( ret = asn1_get_mpi( &p, end, &rsa->D  ) ) != 0 ||
+        ( ret = asn1_get_mpi( &p, end, &rsa->P  ) ) != 0 ||
+        ( ret = asn1_get_mpi( &p, end, &rsa->Q  ) ) != 0 ||
+        ( ret = asn1_get_mpi( &p, end, &rsa->DP ) ) != 0 ||
+        ( ret = asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 ||
+        ( ret = asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 )
+    {
+        rsa_free( rsa );
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+    }
+
+    rsa->len = mpi_size( &rsa->N );
+
+    if( p != end )
+    {
+        rsa_free( rsa );
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+    }
+
+    if( ( ret = rsa_check_privkey( rsa ) ) != 0 )
+    {
+        rsa_free( rsa );
+        return( ret );
+    }
+
+    return( 0 );
+}
+#endif /* POLARSSL_RSA_C */
+
+#if defined(POLARSSL_ECP_C)
+/*
+ * Parse a SEC1 encoded private EC key
+ */
+static int pk_parse_key_sec1_der( ecp_keypair *eck,
+                                  const unsigned char *key,
+                                  size_t keylen )
+{
+    int ret;
+    int version, pubkey_done;
+    size_t len;
+    asn1_buf params;
+    unsigned char *p = (unsigned char *) key;
+    unsigned char *end = p + keylen;
+    unsigned char *end2;
+
+    /*
+     * RFC 5915, or SEC1 Appendix C.4
+     *
+     * ECPrivateKey ::= SEQUENCE {
+     *      version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
+     *      privateKey     OCTET STRING,
+     *      parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
+     *      publicKey  [1] BIT STRING OPTIONAL
+     *    }
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+    }
+
+    end = p + len;
+
+    if( ( ret = asn1_get_int( &p, end, &version ) ) != 0 )
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+    if( version != 1 )
+        return( POLARSSL_ERR_PK_KEY_INVALID_VERSION );
+
+    if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 )
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+    if( ( ret = mpi_read_binary( &eck->d, p, len ) ) != 0 )
+    {
+        ecp_keypair_free( eck );
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+    }
+
+    p += len;
+
+    /*
+     * Is 'parameters' present?
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len,
+                    ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) == 0 )
+    {
+        if( ( ret = pk_get_ecparams( &p, p + len, &params) ) != 0 ||
+            ( ret = pk_use_ecparams( &params, &eck->grp )  ) != 0 )
+        {
+            ecp_keypair_free( eck );
+            return( ret );
+        }
+    }
+    else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+    {
+        ecp_keypair_free( eck );
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+    }
+
+    /*
+     * Is 'publickey' present? If not, or if we can't read it (eg because it
+     * is compressed), create it from the private key.
+     */
+    pubkey_done = 0;
+    if( ( ret = asn1_get_tag( &p, end, &len,
+                    ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1 ) ) == 0 )
+    {
+        end2 = p + len;
+
+        if( ( ret = asn1_get_bitstring_null( &p, end2, &len ) ) != 0 )
+            return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+        if( p + len != end2 )
+            return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT +
+                    POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+        if( ( ret = pk_get_ecpubkey( &p, end2, eck ) ) == 0 )
+            pubkey_done = 1;
+        else
+        {
+            /*
+             * The only acceptable failure mode of pk_get_ecpubkey() above
+             * is if the point format is not recognized.
+             */
+            if( ret != POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE )
+                return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT );
+        }
+    }
+    else if ( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+    {
+        ecp_keypair_free( eck );
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+    }
+
+    if( ! pubkey_done &&
+        ( ret = ecp_mul( &eck->grp, &eck->Q, &eck->d, &eck->grp.G,
+                                                      NULL, NULL ) ) != 0 )
+    {
+        ecp_keypair_free( eck );
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+    }
+
+    if( ( ret = ecp_check_privkey( &eck->grp, &eck->d ) ) != 0 )
+    {
+        ecp_keypair_free( eck );
+        return( ret );
+    }
+
+    return 0;
+}
+#endif /* POLARSSL_ECP_C */
+
+/*
+ * Parse an unencrypted PKCS#8 encoded private key
+ */
+static int pk_parse_key_pkcs8_unencrypted_der(
+                                    pk_context *pk,
+                                    const unsigned char* key,
+                                    size_t keylen )
+{
+    int ret, version;
+    size_t len;
+    asn1_buf params;
+    unsigned char *p = (unsigned char *) key;
+    unsigned char *end = p + keylen;
+    pk_type_t pk_alg = POLARSSL_PK_NONE;
+    const pk_info_t *pk_info;
+
+    /*
+     * This function parses the PrivatKeyInfo object (PKCS#8 v1.2 = RFC 5208)
+     *
+     *    PrivateKeyInfo ::= SEQUENCE {
+     *      version                   Version,
+     *      privateKeyAlgorithm       PrivateKeyAlgorithmIdentifier,
+     *      privateKey                PrivateKey,
+     *      attributes           [0]  IMPLICIT Attributes OPTIONAL }
+     *
+     *    Version ::= INTEGER
+     *    PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
+     *    PrivateKey ::= OCTET STRING
+     *
+     *  The PrivateKey OCTET STRING is a SEC1 ECPrivateKey
+     */
+
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+    }
+
+    end = p + len;
+
+    if( ( ret = asn1_get_int( &p, end, &version ) ) != 0 )
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+    if( version != 0 )
+        return( POLARSSL_ERR_PK_KEY_INVALID_VERSION + ret );
+
+    if( ( ret = pk_get_pk_alg( &p, end, &pk_alg, &params ) ) != 0 )
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+    if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 )
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+    if( len < 1 )
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT +
+                POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+    if( ( pk_info = pk_info_from_type( pk_alg ) ) == NULL )
+        return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG );
+
+    if( ( ret = pk_init_ctx( pk, pk_info ) ) != 0 )
+        return( ret );
+
+#if defined(POLARSSL_RSA_C)
+    if( pk_alg == POLARSSL_PK_RSA )
+    {
+        if( ( ret = pk_parse_key_pkcs1_der( pk_rsa( *pk ), p, len ) ) != 0 )
+        {
+            pk_free( pk );
+            return( ret );
+        }
+    } else
+#endif /* POLARSSL_RSA_C */
+#if defined(POLARSSL_ECP_C)
+    if( pk_alg == POLARSSL_PK_ECKEY || pk_alg == POLARSSL_PK_ECKEY_DH )
+    {
+        if( ( ret = pk_use_ecparams( &params, &pk_ec( *pk )->grp ) ) != 0 ||
+            ( ret = pk_parse_key_sec1_der( pk_ec( *pk ), p, len )  ) != 0 )
+        {
+            pk_free( pk );
+            return( ret );
+        }
+    } else
+#endif /* POLARSSL_ECP_C */
+        return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG );
+
+    return 0;
+}
+
+/*
+ * Parse an encrypted PKCS#8 encoded private key
+ */
+static int pk_parse_key_pkcs8_encrypted_der(
+                                    pk_context *pk,
+                                    const unsigned char *key, size_t keylen,
+                                    const unsigned char *pwd, size_t pwdlen )
+{
+    int ret, decrypted = 0;
+    size_t len;
+    unsigned char buf[2048];
+    unsigned char *p, *end;
+    asn1_buf pbe_alg_oid, pbe_params;
+#if defined(POLARSSL_PKCS12_C)
+    cipher_type_t cipher_alg;
+    md_type_t md_alg;
+#endif
+
+    memset( buf, 0, sizeof( buf ) );
+
+    p = (unsigned char *) key;
+    end = p + keylen;
+
+    if( pwdlen == 0 )
+        return( POLARSSL_ERR_PK_PASSWORD_REQUIRED );
+
+    /*
+     * This function parses the EncryptedPrivatKeyInfo object (PKCS#8)
+     *
+     *  EncryptedPrivateKeyInfo ::= SEQUENCE {
+     *    encryptionAlgorithm  EncryptionAlgorithmIdentifier,
+     *    encryptedData        EncryptedData
+     *  }
+     *
+     *  EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
+     *
+     *  EncryptedData ::= OCTET STRING
+     *
+     *  The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+    }
+
+    end = p + len;
+
+    if( ( ret = asn1_get_alg( &p, end, &pbe_alg_oid, &pbe_params ) ) != 0 )
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+    if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 )
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+    if( len > sizeof( buf ) )
+        return( POLARSSL_ERR_PK_BAD_INPUT_DATA );
+
+    /*
+     * Decrypt EncryptedData with appropriate PDE
+     */
+#if defined(POLARSSL_PKCS12_C)
+    if( oid_get_pkcs12_pbe_alg( &pbe_alg_oid, &md_alg, &cipher_alg ) == 0 )
+    {
+        if( ( ret = pkcs12_pbe( &pbe_params, PKCS12_PBE_DECRYPT,
+                                cipher_alg, md_alg,
+                                pwd, pwdlen, p, len, buf ) ) != 0 )
+        {
+            if( ret == POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH )
+                return( POLARSSL_ERR_PK_PASSWORD_MISMATCH );
+
+            return( ret );
+        }
+
+        decrypted = 1;
+    }
+    else if( OID_CMP( OID_PKCS12_PBE_SHA1_RC4_128, &pbe_alg_oid ) )
+    {
+        if( ( ret = pkcs12_pbe_sha1_rc4_128( &pbe_params,
+                                             PKCS12_PBE_DECRYPT,
+                                             pwd, pwdlen,
+                                             p, len, buf ) ) != 0 )
+        {
+            return( ret );
+        }
+
+        // Best guess for password mismatch when using RC4. If first tag is
+        // not ASN1_CONSTRUCTED | ASN1_SEQUENCE
+        //
+        if( *buf != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) )
+            return( POLARSSL_ERR_PK_PASSWORD_MISMATCH );
+
+        decrypted = 1;
+    }
+    else
+#endif /* POLARSSL_PKCS12_C */
+#if defined(POLARSSL_PKCS5_C)
+    if( OID_CMP( OID_PKCS5_PBES2, &pbe_alg_oid ) )
+    {
+        if( ( ret = pkcs5_pbes2( &pbe_params, PKCS5_DECRYPT, pwd, pwdlen,
+                                  p, len, buf ) ) != 0 )
+        {
+            if( ret == POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH )
+                return( POLARSSL_ERR_PK_PASSWORD_MISMATCH );
+
+            return( ret );
+        }
+
+        decrypted = 1;
+    }
+    else
+#endif /* POLARSSL_PKCS5_C */
+    {
+        ((void) pwd);
+    }
+
+    if( decrypted == 0 )
+        return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE );
+
+    return( pk_parse_key_pkcs8_unencrypted_der( pk, buf, len ) );
+}
+
+/*
+ * Parse a private key
+ */
+int pk_parse_key( pk_context *pk,
+                  const unsigned char *key, size_t keylen,
+                  const unsigned char *pwd, size_t pwdlen )
+{
+    int ret;
+    const pk_info_t *pk_info;
+
+#if defined(POLARSSL_PEM_PARSE_C)
+    size_t len;
+    pem_context pem;
+
+    pem_init( &pem );
+
+#if defined(POLARSSL_RSA_C)
+    ret = pem_read_buffer( &pem,
+                           "-----BEGIN RSA PRIVATE KEY-----",
+                           "-----END RSA PRIVATE KEY-----",
+                           key, pwd, pwdlen, &len );
+    if( ret == 0 )
+    {
+        if( ( pk_info = pk_info_from_type( POLARSSL_PK_RSA ) ) == NULL )
+            return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG );
+
+        if( ( ret = pk_init_ctx( pk, pk_info                    ) ) != 0 ||
+            ( ret = pk_parse_key_pkcs1_der( pk_rsa( *pk ),
+                                            pem.buf, pem.buflen ) ) != 0 )
+        {
+            pk_free( pk );
+        }
+
+        pem_free( &pem );
+        return( ret );
+    }
+    else if( ret == POLARSSL_ERR_PEM_PASSWORD_MISMATCH )
+        return( POLARSSL_ERR_PK_PASSWORD_MISMATCH );
+    else if( ret == POLARSSL_ERR_PEM_PASSWORD_REQUIRED )
+        return( POLARSSL_ERR_PK_PASSWORD_REQUIRED );
+    else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
+        return( ret );
+#endif /* POLARSSL_RSA_C */
+
+#if defined(POLARSSL_ECP_C)
+    ret = pem_read_buffer( &pem,
+                           "-----BEGIN EC PRIVATE KEY-----",
+                           "-----END EC PRIVATE KEY-----",
+                           key, pwd, pwdlen, &len );
+    if( ret == 0 )
+    {
+        if( ( pk_info = pk_info_from_type( POLARSSL_PK_ECKEY ) ) == NULL )
+            return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG );
+
+        if( ( ret = pk_init_ctx( pk, pk_info                   ) ) != 0 ||
+            ( ret = pk_parse_key_sec1_der( pk_ec( *pk ),
+                                           pem.buf, pem.buflen ) ) != 0 )
+        {
+            pk_free( pk );
+        }
+
+        pem_free( &pem );
+        return( ret );
+    }
+    else if( ret == POLARSSL_ERR_PEM_PASSWORD_MISMATCH )
+        return( POLARSSL_ERR_PK_PASSWORD_MISMATCH );
+    else if( ret == POLARSSL_ERR_PEM_PASSWORD_REQUIRED )
+        return( POLARSSL_ERR_PK_PASSWORD_REQUIRED );
+    else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
+        return( ret );
+#endif /* POLARSSL_ECP_C */
+
+    ret = pem_read_buffer( &pem,
+                           "-----BEGIN PRIVATE KEY-----",
+                           "-----END PRIVATE KEY-----",
+                           key, NULL, 0, &len );
+    if( ret == 0 )
+    {
+        if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk,
+                                                pem.buf, pem.buflen ) ) != 0 )
+        {
+            pk_free( pk );
+        }
+
+        pem_free( &pem );
+        return( ret );
+    }
+    else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
+        return( ret );
+
+    ret = pem_read_buffer( &pem,
+                           "-----BEGIN ENCRYPTED PRIVATE KEY-----",
+                           "-----END ENCRYPTED PRIVATE KEY-----",
+                           key, NULL, 0, &len );
+    if( ret == 0 )
+    {
+        if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk,
+                                                      pem.buf, pem.buflen,
+                                                      pwd, pwdlen ) ) != 0 )
+        {
+            pk_free( pk );
+        }
+
+        pem_free( &pem );
+        return( ret );
+    }
+    else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
+        return( ret );
+#else
+    ((void) pwd);
+    ((void) pwdlen);
+#endif /* POLARSSL_PEM_PARSE_C */
+
+    /*
+    * At this point we only know it's not a PEM formatted key. Could be any
+    * of the known DER encoded private key formats
+    *
+    * We try the different DER format parsers to see if one passes without
+    * error
+    */
+    if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk, key, keylen,
+                                                  pwd, pwdlen ) ) == 0 )
+    {
+        return( 0 );
+    }
+
+    pk_free( pk );
+
+    if( ret == POLARSSL_ERR_PK_PASSWORD_MISMATCH )
+    {
+        return( ret );
+    }
+
+    if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, key, keylen ) ) == 0 )
+        return( 0 );
+
+    pk_free( pk );
+
+#if defined(POLARSSL_RSA_C)
+    if( ( pk_info = pk_info_from_type( POLARSSL_PK_RSA ) ) == NULL )
+        return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG );
+
+    if( ( ret = pk_init_ctx( pk, pk_info                           ) ) != 0 ||
+        ( ret = pk_parse_key_pkcs1_der( pk_rsa( *pk ), key, keylen ) ) == 0 )
+    {
+        return( 0 );
+    }
+
+    pk_free( pk );
+#endif /* POLARSSL_RSA_C */
+
+#if defined(POLARSSL_ECP_C)
+    if( ( pk_info = pk_info_from_type( POLARSSL_PK_ECKEY ) ) == NULL )
+        return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG );
+
+    if( ( ret = pk_init_ctx( pk, pk_info                         ) ) != 0 ||
+        ( ret = pk_parse_key_sec1_der( pk_ec( *pk ), key, keylen ) ) == 0 )
+    {
+        return( 0 );
+    }
+
+    pk_free( pk );
+#endif /* POLARSSL_ECP_C */
+
+    return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT );
+}
+
+/*
+ * Parse a public key
+ */
+int pk_parse_public_key( pk_context *ctx,
+                         const unsigned char *key, size_t keylen )
+{
+    int ret;
+    unsigned char *p;
+#if defined(POLARSSL_PEM_PARSE_C)
+    size_t len;
+    pem_context pem;
+
+    pem_init( &pem );
+    ret = pem_read_buffer( &pem,
+            "-----BEGIN PUBLIC KEY-----",
+            "-----END PUBLIC KEY-----",
+            key, NULL, 0, &len );
+
+    if( ret == 0 )
+    {
+        /*
+         * Was PEM encoded
+         */
+        key = pem.buf;
+        keylen = pem.buflen;
+    }
+    else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
+    {
+        pem_free( &pem );
+        return( ret );
+    }
+#endif /* POLARSSL_PEM_PARSE_C */
+    p = (unsigned char *) key;
+
+    ret = pk_parse_subpubkey( &p, p + keylen, ctx );
+
+#if defined(POLARSSL_PEM_PARSE_C)
+    pem_free( &pem );
+#endif
+
+    return( ret );
+}
+
+#endif /* POLARSSL_PK_PARSE_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/pkwrite.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,360 @@
+/*
+ *  Public Key layer for writing key files and structures
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_PK_WRITE_C)
+
+#include "polarssl/pk.h"
+#include "polarssl/asn1write.h"
+#include "polarssl/oid.h"
+
+#if defined(POLARSSL_RSA_C)
+#include "polarssl/rsa.h"
+#endif
+#if defined(POLARSSL_ECP_C)
+#include "polarssl/ecp.h"
+#endif
+#if defined(POLARSSL_ECDSA_C)
+#include "polarssl/ecdsa.h"
+#endif
+#if defined(POLARSSL_PEM_WRITE_C)
+#include "polarssl/pem.h"
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdlib.h>
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+#if defined(POLARSSL_RSA_C)
+/*
+ *  RSAPublicKey ::= SEQUENCE {
+ *      modulus           INTEGER,  -- n
+ *      publicExponent    INTEGER   -- e
+ *  }
+ */
+static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start,
+                                  rsa_context *rsa )
+{
+    int ret;
+    size_t len = 0;
+
+    ASN1_CHK_ADD( len, asn1_write_mpi( p, start, &rsa->E ) );
+    ASN1_CHK_ADD( len, asn1_write_mpi( p, start, &rsa->N ) );
+
+    ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED |
+                                                 ASN1_SEQUENCE ) );
+
+    return( (int) len );
+}
+#endif /* POLARSSL_RSA_C */
+
+#if defined(POLARSSL_ECP_C)
+/*
+ * EC public key is an EC point
+ */
+static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start,
+                                 ecp_keypair *ec )
+{
+    int ret;
+    size_t len = 0;
+    unsigned char buf[POLARSSL_ECP_MAX_PT_LEN];
+
+    if( ( ret = ecp_point_write_binary( &ec->grp, &ec->Q,
+                                        POLARSSL_ECP_PF_UNCOMPRESSED,
+                                        &len, buf, sizeof( buf ) ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    if( *p - start < (int) len )
+        return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+    *p -= len;
+    memcpy( *p, buf, len );
+
+    return( (int) len );
+}
+
+/*
+ * ECParameters ::= CHOICE {
+ *   namedCurve         OBJECT IDENTIFIER
+ * }
+ */
+static int pk_write_ec_param( unsigned char **p, unsigned char *start,
+                                ecp_keypair *ec )
+{
+    int ret;
+    size_t len = 0;
+    const char *oid;
+    size_t oid_len;
+
+    if( ( ret = oid_get_oid_by_ec_grp( ec->grp.id, &oid, &oid_len ) ) != 0 )
+        return( ret );
+
+    ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) );
+
+    return( (int) len );
+}
+#endif /* POLARSSL_ECP_C */
+
+int pk_write_pubkey( unsigned char **p, unsigned char *start,
+                     const pk_context *key )
+{
+    int ret;
+    size_t len = 0;
+
+#if defined(POLARSSL_RSA_C)
+    if( pk_get_type( key ) == POLARSSL_PK_RSA )
+        ASN1_CHK_ADD( len, pk_write_rsa_pubkey( p, start, pk_rsa( *key ) ) );
+    else
+#endif
+#if defined(POLARSSL_ECP_C)
+    if( pk_get_type( key ) == POLARSSL_PK_ECKEY )
+        ASN1_CHK_ADD( len, pk_write_ec_pubkey( p, start, pk_ec( *key ) ) );
+    else
+#endif
+        return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE );
+
+    return( (int) len );
+}
+
+int pk_write_pubkey_der( pk_context *key, unsigned char *buf, size_t size )
+{
+    int ret;
+    unsigned char *c;
+    size_t len = 0, par_len = 0, oid_len;
+    const char *oid;
+
+    c = buf + size;
+
+    ASN1_CHK_ADD( len, pk_write_pubkey( &c, buf, key ) );
+
+    if( c - buf < 1 )
+        return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+    /*
+     *  SubjectPublicKeyInfo  ::=  SEQUENCE  {
+     *       algorithm            AlgorithmIdentifier,
+     *       subjectPublicKey     BIT STRING }
+     */
+    *--c = 0;
+    len += 1;
+
+    ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_BIT_STRING ) );
+
+    if( ( ret = oid_get_oid_by_pk_alg( pk_get_type( key ),
+                                       &oid, &oid_len ) ) != 0 )
+    {
+        return( ret );
+    }
+
+#if defined(POLARSSL_ECP_C)
+    if( pk_get_type( key ) == POLARSSL_PK_ECKEY )
+    {
+        ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, pk_ec( *key ) ) );
+    }
+#endif
+
+    ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, buf, oid, oid_len,
+                                                        par_len ) );
+
+    ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED |
+                                                ASN1_SEQUENCE ) );
+
+    return( (int) len );
+}
+
+int pk_write_key_der( pk_context *key, unsigned char *buf, size_t size )
+{
+    int ret;
+    unsigned char *c = buf + size;
+    size_t len = 0;
+
+#if defined(POLARSSL_RSA_C)
+    if( pk_get_type( key ) == POLARSSL_PK_RSA )
+    {
+        rsa_context *rsa = pk_rsa( *key );
+
+        ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->QP ) );
+        ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DQ ) );
+        ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DP ) );
+        ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->Q ) );
+        ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->P ) );
+        ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->D ) );
+        ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->E ) );
+        ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->N ) );
+        ASN1_CHK_ADD( len, asn1_write_int( &c, buf, 0 ) );
+
+        ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
+        ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED |
+                                                    ASN1_SEQUENCE ) );
+    }
+    else
+#endif /* POLARSSL_RSA_C */
+#if defined(POLARSSL_ECP_C)
+    if( pk_get_type( key ) == POLARSSL_PK_ECKEY )
+    {
+        ecp_keypair *ec = pk_ec( *key );
+        size_t pub_len = 0, par_len = 0;
+
+        /*
+         * RFC 5915, or SEC1 Appendix C.4
+         *
+         * ECPrivateKey ::= SEQUENCE {
+         *      version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
+         *      privateKey     OCTET STRING,
+         *      parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
+         *      publicKey  [1] BIT STRING OPTIONAL
+         *    }
+         */
+
+        /* publicKey */
+        ASN1_CHK_ADD( pub_len, pk_write_ec_pubkey( &c, buf, ec ) );
+
+        if( c - buf < 1 )
+            return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+        *--c = 0;
+        pub_len += 1;
+
+        ASN1_CHK_ADD( pub_len, asn1_write_len( &c, buf, pub_len ) );
+        ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, buf, ASN1_BIT_STRING ) );
+
+        ASN1_CHK_ADD( pub_len, asn1_write_len( &c, buf, pub_len ) );
+        ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, buf,
+                            ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1 ) );
+        len += pub_len;
+
+        /* parameters */
+        ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, ec ) );
+
+        ASN1_CHK_ADD( par_len, asn1_write_len( &c, buf, par_len ) );
+        ASN1_CHK_ADD( par_len, asn1_write_tag( &c, buf,
+                            ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) );
+        len += par_len;
+
+        /* privateKey: write as MPI then fix tag */
+        ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &ec->d ) );
+        *c = ASN1_OCTET_STRING;
+
+        /* version */
+        ASN1_CHK_ADD( len, asn1_write_int( &c, buf, 1 ) );
+
+        ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
+        ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED |
+                                                    ASN1_SEQUENCE ) );
+    }
+    else
+#endif /* POLARSSL_ECP_C */
+        return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE );
+
+    return( (int) len );
+}
+
+#if defined(POLARSSL_PEM_WRITE_C)
+
+#define PEM_BEGIN_PUBLIC_KEY    "-----BEGIN PUBLIC KEY-----\n"
+#define PEM_END_PUBLIC_KEY      "-----END PUBLIC KEY-----\n"
+
+#define PEM_BEGIN_PRIVATE_KEY_RSA   "-----BEGIN RSA PRIVATE KEY-----\n"
+#define PEM_END_PRIVATE_KEY_RSA     "-----END RSA PRIVATE KEY-----\n"
+#define PEM_BEGIN_PRIVATE_KEY_EC    "-----BEGIN EC PRIVATE KEY-----\n"
+#define PEM_END_PRIVATE_KEY_EC      "-----END EC PRIVATE KEY-----\n"
+
+int pk_write_pubkey_pem( pk_context *key, unsigned char *buf, size_t size )
+{
+    int ret;
+    unsigned char output_buf[4096];
+    size_t olen = 0;
+
+    if( ( ret = pk_write_pubkey_der( key, output_buf,
+                                     sizeof(output_buf) ) ) < 0 )
+    {
+        return( ret );
+    }
+
+    if( ( ret = pem_write_buffer( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
+                                  output_buf + sizeof(output_buf) - ret,
+                                  ret, buf, size, &olen ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    return( 0 );
+}
+
+int pk_write_key_pem( pk_context *key, unsigned char *buf, size_t size )
+{
+    int ret;
+    unsigned char output_buf[4096];
+    const char *begin, *end;
+    size_t olen = 0;
+
+    if( ( ret = pk_write_key_der( key, output_buf, sizeof(output_buf) ) ) < 0 )
+        return( ret );
+
+#if defined(POLARSSL_RSA_C)
+    if( pk_get_type( key ) == POLARSSL_PK_RSA )
+    {
+        begin = PEM_BEGIN_PRIVATE_KEY_RSA;
+        end = PEM_END_PRIVATE_KEY_RSA;
+    }
+    else
+#endif
+#if defined(POLARSSL_ECP_C)
+    if( pk_get_type( key ) == POLARSSL_PK_ECKEY )
+    {
+        begin = PEM_BEGIN_PRIVATE_KEY_EC;
+        end = PEM_END_PRIVATE_KEY_EC;
+    }
+    else
+#endif
+        return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE );
+
+    if( ( ret = pem_write_buffer( begin, end,
+                                  output_buf + sizeof(output_buf) - ret,
+                                  ret, buf, size, &olen ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    return( 0 );
+}
+#endif /* POLARSSL_PEM_WRITE_C */
+
+#endif /* POLARSSL_PK_WRITE_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/platform.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,118 @@
+/*
+ *  Platform abstraction layer
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+
+#include "polarssl/platform.h"
+
+#if defined(POLARSSL_PLATFORM_MEMORY)
+#if !defined(POLARSSL_PLATFORM_STD_MALLOC)
+static void *platform_malloc_uninit( size_t len )
+{
+    ((void) len);
+    return( NULL );
+}
+
+#define POLARSSL_PLATFORM_STD_MALLOC   platform_malloc_uninit
+#endif /* !POLARSSL_PLATFORM_STD_MALLOC */
+
+#if !defined(POLARSSL_PLATFORM_STD_FREE)
+static void platform_free_uninit( void *ptr )
+{
+    ((void) ptr);
+}
+
+#define POLARSSL_PLATFORM_STD_FREE     platform_free_uninit
+#endif /* !POLARSSL_PLATFORM_STD_FREE */
+
+void * (*polarssl_malloc)( size_t ) = POLARSSL_PLATFORM_STD_MALLOC;
+void (*polarssl_free)( void * )     = POLARSSL_PLATFORM_STD_FREE;
+
+int platform_set_malloc_free( void * (*malloc_func)( size_t ),
+                              void (*free_func)( void * ) )
+{
+    polarssl_malloc = malloc_func;
+    polarssl_free = free_func;
+    return( 0 );
+}
+#endif /* POLARSSL_PLATFORM_MEMORY */
+
+#if defined(POLARSSL_PLATFORM_PRINTF_ALT)
+#if !defined(POLARSSL_PLATFORM_STD_PRINTF)
+/*
+ * Make dummy function to prevent NULL pointer dereferences
+ */
+static int platform_printf_uninit( const char *format, ... )
+{
+    ((void) format);
+    return( 0 );
+}
+
+#define POLARSSL_PLATFORM_STD_PRINTF    platform_printf_uninit
+#endif /* !POLARSSL_PLATFORM_STD_PRINTF */
+
+int (*polarssl_printf)( const char *, ... ) = POLARSSL_PLATFORM_STD_PRINTF;
+
+int platform_set_printf( int (*printf_func)( const char *, ... ) )
+{
+    polarssl_printf = printf_func;
+    return( 0 );
+}
+#endif /* POLARSSL_PLATFORM_PRINTF_ALT */
+
+#if defined(POLARSSL_PLATFORM_FPRINTF_ALT)
+#if !defined(POLARSSL_PLATFORM_STD_FPRINTF)
+/*
+ * Make dummy function to prevent NULL pointer dereferences
+ */
+static int platform_fprintf_uninit( FILE *stream, const char *format, ... )
+{
+    ((void) stream);
+    ((void) format);
+    return( 0 );
+}
+
+#define POLARSSL_PLATFORM_STD_FPRINTF   platform_fprintf_uninit
+#endif /* !POLARSSL_PLATFORM_STD_FPRINTF */
+
+int (*polarssl_fprintf)( FILE *, const char *, ... ) =
+                                        POLARSSL_PLATFORM_STD_FPRINTF;
+
+int platform_set_fprintf( int (*fprintf_func)( FILE *, const char *, ... ) )
+{
+    polarssl_fprintf = fprintf_func;
+    return( 0 );
+}
+#endif /* POLARSSL_PLATFORM_FPRINTF_ALT */
+
+#endif /* POLARSSL_PLATFORM_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/ripemd160.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,637 @@
+/*
+ *  RIPE MD-160 implementation
+ *
+ *  Copyright (C) 2014-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*
+ *  The RIPEMD-160 algorithm was designed by RIPE in 1996
+ *  http://homes.esat.kuleuven.be/~bosselae/ripemd160.html
+ *  http://ehash.iaik.tugraz.at/wiki/RIPEMD-160
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_RIPEMD160_C)
+
+#include "polarssl/ripemd160.h"
+
+#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
+#include <stdio.h>
+#endif
+
+#if defined(POLARSSL_SELF_TEST)
+#include <string.h>
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
+/*
+ * 32-bit integer manipulation macros (little endian)
+ */
+#ifndef GET_UINT32_LE
+#define GET_UINT32_LE(n,b,i)                            \
+{                                                       \
+    (n) = ( (uint32_t) (b)[(i)    ]       )             \
+        | ( (uint32_t) (b)[(i) + 1] <<  8 )             \
+        | ( (uint32_t) (b)[(i) + 2] << 16 )             \
+        | ( (uint32_t) (b)[(i) + 3] << 24 );            \
+}
+#endif
+
+#ifndef PUT_UINT32_LE
+#define PUT_UINT32_LE(n,b,i)                            \
+{                                                       \
+    (b)[(i)    ] = (unsigned char) ( (n)       );       \
+    (b)[(i) + 1] = (unsigned char) ( (n) >>  8 );       \
+    (b)[(i) + 2] = (unsigned char) ( (n) >> 16 );       \
+    (b)[(i) + 3] = (unsigned char) ( (n) >> 24 );       \
+}
+#endif
+
+/*
+ * RIPEMD-160 context setup
+ */
+void ripemd160_starts( ripemd160_context *ctx )
+{
+    ctx->total[0] = 0;
+    ctx->total[1] = 0;
+
+    ctx->state[0] = 0x67452301;
+    ctx->state[1] = 0xEFCDAB89;
+    ctx->state[2] = 0x98BADCFE;
+    ctx->state[3] = 0x10325476;
+    ctx->state[4] = 0xC3D2E1F0;
+}
+
+/*
+ * Process one block
+ */
+void ripemd160_process( ripemd160_context *ctx, const unsigned char data[64] )
+{
+    uint32_t A, B, C, D, E, Ap, Bp, Cp, Dp, Ep, X[16];
+
+    GET_UINT32_LE( X[ 0], data,  0 );
+    GET_UINT32_LE( X[ 1], data,  4 );
+    GET_UINT32_LE( X[ 2], data,  8 );
+    GET_UINT32_LE( X[ 3], data, 12 );
+    GET_UINT32_LE( X[ 4], data, 16 );
+    GET_UINT32_LE( X[ 5], data, 20 );
+    GET_UINT32_LE( X[ 6], data, 24 );
+    GET_UINT32_LE( X[ 7], data, 28 );
+    GET_UINT32_LE( X[ 8], data, 32 );
+    GET_UINT32_LE( X[ 9], data, 36 );
+    GET_UINT32_LE( X[10], data, 40 );
+    GET_UINT32_LE( X[11], data, 44 );
+    GET_UINT32_LE( X[12], data, 48 );
+    GET_UINT32_LE( X[13], data, 52 );
+    GET_UINT32_LE( X[14], data, 56 );
+    GET_UINT32_LE( X[15], data, 60 );
+
+    A = Ap = ctx->state[0];
+    B = Bp = ctx->state[1];
+    C = Cp = ctx->state[2];
+    D = Dp = ctx->state[3];
+    E = Ep = ctx->state[4];
+
+#define F1( x, y, z )   ( x ^ y ^ z )
+#define F2( x, y, z )   ( ( x & y ) | ( ~x & z ) )
+#define F3( x, y, z )   ( ( x | ~y ) ^ z )
+#define F4( x, y, z )   ( ( x & z ) | ( y & ~z ) )
+#define F5( x, y, z )   ( x ^ ( y | ~z ) )
+
+#define S( x, n ) ( ( x << n ) | ( x >> (32 - n) ) )
+
+#define P( a, b, c, d, e, r, s, f, k )      \
+    a += f( b, c, d ) + X[r] + k;           \
+    a = S( a, s ) + e;                      \
+    c = S( c, 10 );
+
+#define P2( a, b, c, d, e, r, s, rp, sp )   \
+    P( a, b, c, d, e, r, s, F, K );         \
+    P( a ## p, b ## p, c ## p, d ## p, e ## p, rp, sp, Fp, Kp );
+
+#define F   F1
+#define K   0x00000000
+#define Fp  F5
+#define Kp  0x50A28BE6
+    P2( A, B, C, D, E,  0, 11,  5,  8 );
+    P2( E, A, B, C, D,  1, 14, 14,  9 );
+    P2( D, E, A, B, C,  2, 15,  7,  9 );
+    P2( C, D, E, A, B,  3, 12,  0, 11 );
+    P2( B, C, D, E, A,  4,  5,  9, 13 );
+    P2( A, B, C, D, E,  5,  8,  2, 15 );
+    P2( E, A, B, C, D,  6,  7, 11, 15 );
+    P2( D, E, A, B, C,  7,  9,  4,  5 );
+    P2( C, D, E, A, B,  8, 11, 13,  7 );
+    P2( B, C, D, E, A,  9, 13,  6,  7 );
+    P2( A, B, C, D, E, 10, 14, 15,  8 );
+    P2( E, A, B, C, D, 11, 15,  8, 11 );
+    P2( D, E, A, B, C, 12,  6,  1, 14 );
+    P2( C, D, E, A, B, 13,  7, 10, 14 );
+    P2( B, C, D, E, A, 14,  9,  3, 12 );
+    P2( A, B, C, D, E, 15,  8, 12,  6 );
+#undef F
+#undef K
+#undef Fp
+#undef Kp
+
+#define F   F2
+#define K   0x5A827999
+#define Fp  F4
+#define Kp  0x5C4DD124
+    P2( E, A, B, C, D,  7,  7,  6,  9 );
+    P2( D, E, A, B, C,  4,  6, 11, 13 );
+    P2( C, D, E, A, B, 13,  8,  3, 15 );
+    P2( B, C, D, E, A,  1, 13,  7,  7 );
+    P2( A, B, C, D, E, 10, 11,  0, 12 );
+    P2( E, A, B, C, D,  6,  9, 13,  8 );
+    P2( D, E, A, B, C, 15,  7,  5,  9 );
+    P2( C, D, E, A, B,  3, 15, 10, 11 );
+    P2( B, C, D, E, A, 12,  7, 14,  7 );
+    P2( A, B, C, D, E,  0, 12, 15,  7 );
+    P2( E, A, B, C, D,  9, 15,  8, 12 );
+    P2( D, E, A, B, C,  5,  9, 12,  7 );
+    P2( C, D, E, A, B,  2, 11,  4,  6 );
+    P2( B, C, D, E, A, 14,  7,  9, 15 );
+    P2( A, B, C, D, E, 11, 13,  1, 13 );
+    P2( E, A, B, C, D,  8, 12,  2, 11 );
+#undef F
+#undef K
+#undef Fp
+#undef Kp
+
+#define F   F3
+#define K   0x6ED9EBA1
+#define Fp  F3
+#define Kp  0x6D703EF3
+    P2( D, E, A, B, C,  3, 11, 15,  9 );
+    P2( C, D, E, A, B, 10, 13,  5,  7 );
+    P2( B, C, D, E, A, 14,  6,  1, 15 );
+    P2( A, B, C, D, E,  4,  7,  3, 11 );
+    P2( E, A, B, C, D,  9, 14,  7,  8 );
+    P2( D, E, A, B, C, 15,  9, 14,  6 );
+    P2( C, D, E, A, B,  8, 13,  6,  6 );
+    P2( B, C, D, E, A,  1, 15,  9, 14 );
+    P2( A, B, C, D, E,  2, 14, 11, 12 );
+    P2( E, A, B, C, D,  7,  8,  8, 13 );
+    P2( D, E, A, B, C,  0, 13, 12,  5 );
+    P2( C, D, E, A, B,  6,  6,  2, 14 );
+    P2( B, C, D, E, A, 13,  5, 10, 13 );
+    P2( A, B, C, D, E, 11, 12,  0, 13 );
+    P2( E, A, B, C, D,  5,  7,  4,  7 );
+    P2( D, E, A, B, C, 12,  5, 13,  5 );
+#undef F
+#undef K
+#undef Fp
+#undef Kp
+
+#define F   F4
+#define K   0x8F1BBCDC
+#define Fp  F2
+#define Kp  0x7A6D76E9
+    P2( C, D, E, A, B,  1, 11,  8, 15 );
+    P2( B, C, D, E, A,  9, 12,  6,  5 );
+    P2( A, B, C, D, E, 11, 14,  4,  8 );
+    P2( E, A, B, C, D, 10, 15,  1, 11 );
+    P2( D, E, A, B, C,  0, 14,  3, 14 );
+    P2( C, D, E, A, B,  8, 15, 11, 14 );
+    P2( B, C, D, E, A, 12,  9, 15,  6 );
+    P2( A, B, C, D, E,  4,  8,  0, 14 );
+    P2( E, A, B, C, D, 13,  9,  5,  6 );
+    P2( D, E, A, B, C,  3, 14, 12,  9 );
+    P2( C, D, E, A, B,  7,  5,  2, 12 );
+    P2( B, C, D, E, A, 15,  6, 13,  9 );
+    P2( A, B, C, D, E, 14,  8,  9, 12 );
+    P2( E, A, B, C, D,  5,  6,  7,  5 );
+    P2( D, E, A, B, C,  6,  5, 10, 15 );
+    P2( C, D, E, A, B,  2, 12, 14,  8 );
+#undef F
+#undef K
+#undef Fp
+#undef Kp
+
+#define F   F5
+#define K   0xA953FD4E
+#define Fp  F1
+#define Kp  0x00000000
+    P2( B, C, D, E, A,  4,  9, 12,  8 );
+    P2( A, B, C, D, E,  0, 15, 15,  5 );
+    P2( E, A, B, C, D,  5,  5, 10, 12 );
+    P2( D, E, A, B, C,  9, 11,  4,  9 );
+    P2( C, D, E, A, B,  7,  6,  1, 12 );
+    P2( B, C, D, E, A, 12,  8,  5,  5 );
+    P2( A, B, C, D, E,  2, 13,  8, 14 );
+    P2( E, A, B, C, D, 10, 12,  7,  6 );
+    P2( D, E, A, B, C, 14,  5,  6,  8 );
+    P2( C, D, E, A, B,  1, 12,  2, 13 );
+    P2( B, C, D, E, A,  3, 13, 13,  6 );
+    P2( A, B, C, D, E,  8, 14, 14,  5 );
+    P2( E, A, B, C, D, 11, 11,  0, 15 );
+    P2( D, E, A, B, C,  6,  8,  3, 13 );
+    P2( C, D, E, A, B, 15,  5,  9, 11 );
+    P2( B, C, D, E, A, 13,  6, 11, 11 );
+#undef F
+#undef K
+#undef Fp
+#undef Kp
+
+    C             = ctx->state[1] + C + Dp;
+    ctx->state[1] = ctx->state[2] + D + Ep;
+    ctx->state[2] = ctx->state[3] + E + Ap;
+    ctx->state[3] = ctx->state[4] + A + Bp;
+    ctx->state[4] = ctx->state[0] + B + Cp;
+    ctx->state[0] = C;
+}
+
+/*
+ * RIPEMD-160 process buffer
+ */
+void ripemd160_update( ripemd160_context *ctx,
+                       const unsigned char *input, size_t ilen )
+{
+    size_t fill;
+    uint32_t left;
+
+    if( ilen <= 0 )
+        return;
+
+    left = ctx->total[0] & 0x3F;
+    fill = 64 - left;
+
+    ctx->total[0] += (uint32_t) ilen;
+    ctx->total[0] &= 0xFFFFFFFF;
+
+    if( ctx->total[0] < (uint32_t) ilen )
+        ctx->total[1]++;
+
+    if( left && ilen >= fill )
+    {
+        memcpy( (void *) (ctx->buffer + left), input, fill );
+        ripemd160_process( ctx, ctx->buffer );
+        input += fill;
+        ilen  -= fill;
+        left = 0;
+    }
+
+    while( ilen >= 64 )
+    {
+        ripemd160_process( ctx, input );
+        input += 64;
+        ilen  -= 64;
+    }
+
+    if( ilen > 0 )
+    {
+        memcpy( (void *) (ctx->buffer + left), input, ilen );
+    }
+}
+
+static const unsigned char ripemd160_padding[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * RIPEMD-160 final digest
+ */
+void ripemd160_finish( ripemd160_context *ctx, unsigned char output[20] )
+{
+    uint32_t last, padn;
+    uint32_t high, low;
+    unsigned char msglen[8];
+
+    high = ( ctx->total[0] >> 29 )
+         | ( ctx->total[1] <<  3 );
+    low  = ( ctx->total[0] <<  3 );
+
+    PUT_UINT32_LE( low,  msglen, 0 );
+    PUT_UINT32_LE( high, msglen, 4 );
+
+    last = ctx->total[0] & 0x3F;
+    padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+
+    ripemd160_update( ctx, ripemd160_padding, padn );
+    ripemd160_update( ctx, msglen, 8 );
+
+    PUT_UINT32_LE( ctx->state[0], output,  0 );
+    PUT_UINT32_LE( ctx->state[1], output,  4 );
+    PUT_UINT32_LE( ctx->state[2], output,  8 );
+    PUT_UINT32_LE( ctx->state[3], output, 12 );
+    PUT_UINT32_LE( ctx->state[4], output, 16 );
+}
+
+/*
+ * output = RIPEMD-160( input buffer )
+ */
+void ripemd160( const unsigned char *input, size_t ilen,
+                unsigned char output[20] )
+{
+    ripemd160_context ctx;
+
+    ripemd160_starts( &ctx );
+    ripemd160_update( &ctx, input, ilen );
+    ripemd160_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( ripemd160_context ) );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * output = RIPEMD-160( file contents )
+ */
+int ripemd160_file( const char *path, unsigned char output[20] )
+{
+    FILE *f;
+    size_t n;
+    ripemd160_context ctx;
+    unsigned char buf[1024];
+
+    if( ( f = fopen( path, "rb" ) ) == NULL )
+        return( POLARSSL_ERR_RIPEMD160_FILE_IO_ERROR );
+
+    ripemd160_starts( &ctx );
+
+    while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+        ripemd160_update( &ctx, buf, n );
+
+    ripemd160_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( ripemd160_context ) );
+
+    if( ferror( f ) != 0 )
+    {
+        fclose( f );
+        return( POLARSSL_ERR_RIPEMD160_FILE_IO_ERROR );
+    }
+
+    fclose( f );
+    return( 0 );
+}
+#endif /* POLARSSL_FS_IO */
+
+/*
+ * RIPEMD-160 HMAC context setup
+ */
+void ripemd160_hmac_starts( ripemd160_context *ctx,
+                            const unsigned char *key, size_t keylen )
+{
+    size_t i;
+    unsigned char sum[20];
+
+    if( keylen > 64 )
+    {
+        ripemd160( key, keylen, sum );
+        keylen = 20;
+        key = sum;
+    }
+
+    memset( ctx->ipad, 0x36, 64 );
+    memset( ctx->opad, 0x5C, 64 );
+
+    for( i = 0; i < keylen; i++ )
+    {
+        ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
+        ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
+    }
+
+    ripemd160_starts( ctx );
+    ripemd160_update( ctx, ctx->ipad, 64 );
+
+    memset( sum, 0, sizeof( sum ) );
+}
+
+/*
+ * RIPEMD-160 HMAC process buffer
+ */
+void ripemd160_hmac_update( ripemd160_context *ctx,
+                            const unsigned char *input, size_t ilen )
+{
+    ripemd160_update( ctx, input, ilen );
+}
+
+/*
+ * RIPEMD-160 HMAC final digest
+ */
+void ripemd160_hmac_finish( ripemd160_context *ctx, unsigned char output[20] )
+{
+    unsigned char tmpbuf[20];
+
+    ripemd160_finish( ctx, tmpbuf );
+    ripemd160_starts( ctx );
+    ripemd160_update( ctx, ctx->opad, 64 );
+    ripemd160_update( ctx, tmpbuf, 20 );
+    ripemd160_finish( ctx, output );
+
+    memset( tmpbuf, 0, sizeof( tmpbuf ) );
+}
+
+/*
+ * RIPEMD-160 HMAC context reset
+ */
+void ripemd160_hmac_reset( ripemd160_context *ctx )
+{
+    ripemd160_starts( ctx );
+    ripemd160_update( ctx, ctx->ipad, 64 );
+}
+
+/*
+ * output = HMAC-RIPEMD-160( hmac key, input buffer )
+ */
+void ripemd160_hmac( const unsigned char *key, size_t keylen,
+                     const unsigned char *input, size_t ilen,
+                     unsigned char output[20] )
+{
+    ripemd160_context ctx;
+
+    ripemd160_hmac_starts( &ctx, key, keylen );
+    ripemd160_hmac_update( &ctx, input, ilen );
+    ripemd160_hmac_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( ripemd160_context ) );
+}
+
+
+#if defined(POLARSSL_SELF_TEST)
+/*
+ * Test vectors from the RIPEMD-160 paper and
+ * http://homes.esat.kuleuven.be/~bosselae/ripemd160.html#HMAC
+ */
+#define TESTS   8
+#define KEYS    2
+static const char *ripemd160_test_input[TESTS] =
+{
+    "",
+    "a",
+    "abc",
+    "message digest",
+    "abcdefghijklmnopqrstuvwxyz",
+    "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+    "1234567890123456789012345678901234567890"
+        "1234567890123456789012345678901234567890",
+};
+
+static const unsigned char ripemd160_test_md[TESTS][20] =
+{
+    { 0x9c, 0x11, 0x85, 0xa5, 0xc5, 0xe9, 0xfc, 0x54, 0x61, 0x28,
+      0x08, 0x97, 0x7e, 0xe8, 0xf5, 0x48, 0xb2, 0x25, 0x8d, 0x31 },
+    { 0x0b, 0xdc, 0x9d, 0x2d, 0x25, 0x6b, 0x3e, 0xe9, 0xda, 0xae,
+      0x34, 0x7b, 0xe6, 0xf4, 0xdc, 0x83, 0x5a, 0x46, 0x7f, 0xfe },
+    { 0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a, 0x9b, 0x04,
+      0x4a, 0x8e, 0x98, 0xc6, 0xb0, 0x87, 0xf1, 0x5a, 0x0b, 0xfc },
+    { 0x5d, 0x06, 0x89, 0xef, 0x49, 0xd2, 0xfa, 0xe5, 0x72, 0xb8,
+      0x81, 0xb1, 0x23, 0xa8, 0x5f, 0xfa, 0x21, 0x59, 0x5f, 0x36 },
+    { 0xf7, 0x1c, 0x27, 0x10, 0x9c, 0x69, 0x2c, 0x1b, 0x56, 0xbb,
+      0xdc, 0xeb, 0x5b, 0x9d, 0x28, 0x65, 0xb3, 0x70, 0x8d, 0xbc },
+    { 0x12, 0xa0, 0x53, 0x38, 0x4a, 0x9c, 0x0c, 0x88, 0xe4, 0x05,
+      0xa0, 0x6c, 0x27, 0xdc, 0xf4, 0x9a, 0xda, 0x62, 0xeb, 0x2b },
+    { 0xb0, 0xe2, 0x0b, 0x6e, 0x31, 0x16, 0x64, 0x02, 0x86, 0xed,
+      0x3a, 0x87, 0xa5, 0x71, 0x30, 0x79, 0xb2, 0x1f, 0x51, 0x89 },
+    { 0x9b, 0x75, 0x2e, 0x45, 0x57, 0x3d, 0x4b, 0x39, 0xf4, 0xdb,
+      0xd3, 0x32, 0x3c, 0xab, 0x82, 0xbf, 0x63, 0x32, 0x6b, 0xfb },
+};
+
+static const unsigned char ripemd160_test_hmac[KEYS][TESTS][20] =
+{
+  {
+    { 0xcf, 0x38, 0x76, 0x77, 0xbf, 0xda, 0x84, 0x83, 0xe6, 0x3b,
+      0x57, 0xe0, 0x6c, 0x3b, 0x5e, 0xcd, 0x8b, 0x7f, 0xc0, 0x55 },
+    { 0x0d, 0x35, 0x1d, 0x71, 0xb7, 0x8e, 0x36, 0xdb, 0xb7, 0x39,
+      0x1c, 0x81, 0x0a, 0x0d, 0x2b, 0x62, 0x40, 0xdd, 0xba, 0xfc },
+    { 0xf7, 0xef, 0x28, 0x8c, 0xb1, 0xbb, 0xcc, 0x61, 0x60, 0xd7,
+      0x65, 0x07, 0xe0, 0xa3, 0xbb, 0xf7, 0x12, 0xfb, 0x67, 0xd6 },
+    { 0xf8, 0x36, 0x62, 0xcc, 0x8d, 0x33, 0x9c, 0x22, 0x7e, 0x60,
+      0x0f, 0xcd, 0x63, 0x6c, 0x57, 0xd2, 0x57, 0x1b, 0x1c, 0x34 },
+    { 0x84, 0x3d, 0x1c, 0x4e, 0xb8, 0x80, 0xac, 0x8a, 0xc0, 0xc9,
+      0xc9, 0x56, 0x96, 0x50, 0x79, 0x57, 0xd0, 0x15, 0x5d, 0xdb },
+    { 0x60, 0xf5, 0xef, 0x19, 0x8a, 0x2d, 0xd5, 0x74, 0x55, 0x45,
+      0xc1, 0xf0, 0xc4, 0x7a, 0xa3, 0xfb, 0x57, 0x76, 0xf8, 0x81 },
+    { 0xe4, 0x9c, 0x13, 0x6a, 0x9e, 0x56, 0x27, 0xe0, 0x68, 0x1b,
+      0x80, 0x8a, 0x3b, 0x97, 0xe6, 0xa6, 0xe6, 0x61, 0xae, 0x79 },
+    { 0x31, 0xbe, 0x3c, 0xc9, 0x8c, 0xee, 0x37, 0xb7, 0x9b, 0x06,
+      0x19, 0xe3, 0xe1, 0xc2, 0xbe, 0x4f, 0x1a, 0xa5, 0x6e, 0x6c },
+  },
+  {
+    { 0xfe, 0x69, 0xa6, 0x6c, 0x74, 0x23, 0xee, 0xa9, 0xc8, 0xfa,
+      0x2e, 0xff, 0x8d, 0x9d, 0xaf, 0xb4, 0xf1, 0x7a, 0x62, 0xf5 },
+    { 0x85, 0x74, 0x3e, 0x89, 0x9b, 0xc8, 0x2d, 0xbf, 0xa3, 0x6f,
+      0xaa, 0xa7, 0xa2, 0x5b, 0x7c, 0xfd, 0x37, 0x24, 0x32, 0xcd },
+    { 0x6e, 0x4a, 0xfd, 0x50, 0x1f, 0xa6, 0xb4, 0xa1, 0x82, 0x3c,
+      0xa3, 0xb1, 0x0b, 0xd9, 0xaa, 0x0b, 0xa9, 0x7b, 0xa1, 0x82 },
+    { 0x2e, 0x06, 0x6e, 0x62, 0x4b, 0xad, 0xb7, 0x6a, 0x18, 0x4c,
+      0x8f, 0x90, 0xfb, 0xa0, 0x53, 0x33, 0x0e, 0x65, 0x0e, 0x92 },
+    { 0x07, 0xe9, 0x42, 0xaa, 0x4e, 0x3c, 0xd7, 0xc0, 0x4d, 0xed,
+      0xc1, 0xd4, 0x6e, 0x2e, 0x8c, 0xc4, 0xc7, 0x41, 0xb3, 0xd9 },
+    { 0xb6, 0x58, 0x23, 0x18, 0xdd, 0xcf, 0xb6, 0x7a, 0x53, 0xa6,
+      0x7d, 0x67, 0x6b, 0x8a, 0xd8, 0x69, 0xad, 0xed, 0x62, 0x9a },
+    { 0xf1, 0xbe, 0x3e, 0xe8, 0x77, 0x70, 0x31, 0x40, 0xd3, 0x4f,
+      0x97, 0xea, 0x1a, 0xb3, 0xa0, 0x7c, 0x14, 0x13, 0x33, 0xe2 },
+    { 0x85, 0xf1, 0x64, 0x70, 0x3e, 0x61, 0xa6, 0x31, 0x31, 0xbe,
+      0x7e, 0x45, 0x95, 0x8e, 0x07, 0x94, 0x12, 0x39, 0x04, 0xf9 },
+  },
+};
+
+static const unsigned char ripemd160_test_key[KEYS][20] =
+{
+    { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
+      0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x01, 0x23, 0x45, 0x67 },
+    { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc,
+      0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x00, 0x11, 0x22, 0x33 },
+};
+
+/*
+ * Checkup routine
+ */
+int ripemd160_self_test( int verbose )
+{
+    int i, j;
+    unsigned char output[20];
+
+    memset( output, 0, sizeof output );
+
+    for( i = 0; i < TESTS; i++ )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "  RIPEMD-160 test #%d: ", i + 1 );
+
+        ripemd160( (const unsigned char *) ripemd160_test_input[i],
+                   strlen( ripemd160_test_input[i] ),
+                   output );
+
+        if( memcmp( output, ripemd160_test_md[i], 20 ) != 0 )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "passed\n" );
+
+        for( j = 0; j < KEYS; j++ )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "  HMAC-RIPEMD-160 test #%d, key #%d: ",
+                                 i + 1, j + 1 );
+
+            ripemd160_hmac( ripemd160_test_key[j], 20,
+                            (const unsigned char *) ripemd160_test_input[i],
+                            strlen( ripemd160_test_input[i] ),
+                            output );
+
+            if( memcmp( output, ripemd160_test_hmac[j][i], 20 ) != 0 )
+            {
+                if( verbose != 0 )
+                    polarssl_printf( "failed\n" );
+
+                return( 1 );
+            }
+
+            if( verbose != 0 )
+                polarssl_printf( "passed\n" );
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "\n" );
+    }
+
+    return( 0 );
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_RIPEMD160_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/rsa.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,1613 @@
+/*
+ *  The RSA public-key cryptosystem
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  RSA was designed by Ron Rivest, Adi Shamir and Len Adleman.
+ *
+ *  http://theory.lcs.mit.edu/~rivest/rsapaper.pdf
+ *  http://www.cacr.math.uwaterloo.ca/hac/about/chap8.pdf
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_RSA_C)
+
+#include "polarssl/rsa.h"
+#include "polarssl/oid.h"
+
+#if defined(POLARSSL_PKCS1_V21)
+#include "polarssl/md.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
+/*
+ * Initialize an RSA context
+ */
+void rsa_init( rsa_context *ctx,
+               int padding,
+               int hash_id )
+{
+    memset( ctx, 0, sizeof( rsa_context ) );
+
+    rsa_set_padding( ctx, padding, hash_id );
+
+#if defined(POLARSSL_THREADING_C)
+    polarssl_mutex_init( &ctx->mutex );
+#endif
+}
+
+/*
+ * Set padding for an existing RSA context
+ */
+void rsa_set_padding( rsa_context *ctx, int padding, int hash_id )
+{
+    ctx->padding = padding;
+    ctx->hash_id = hash_id;
+}
+
+#if defined(POLARSSL_GENPRIME)
+
+/*
+ * Generate an RSA keypair
+ */
+int rsa_gen_key( rsa_context *ctx,
+                 int (*f_rng)(void *, unsigned char *, size_t),
+                 void *p_rng,
+                 unsigned int nbits, int exponent )
+{
+    int ret;
+    mpi P1, Q1, H, G;
+
+    if( f_rng == NULL || nbits < 128 || exponent < 3 )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    mpi_init( &P1 ); mpi_init( &Q1 ); mpi_init( &H ); mpi_init( &G );
+
+    /*
+     * find primes P and Q with Q < P so that:
+     * GCD( E, (P-1)*(Q-1) ) == 1
+     */
+    MPI_CHK( mpi_lset( &ctx->E, exponent ) );
+
+    do
+    {
+        MPI_CHK( mpi_gen_prime( &ctx->P, ( nbits + 1 ) >> 1, 0,
+                                f_rng, p_rng ) );
+
+        MPI_CHK( mpi_gen_prime( &ctx->Q, ( nbits + 1 ) >> 1, 0,
+                                f_rng, p_rng ) );
+
+        if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 )
+            mpi_swap( &ctx->P, &ctx->Q );
+
+        if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 )
+            continue;
+
+        MPI_CHK( mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) );
+        if( mpi_msb( &ctx->N ) != nbits )
+            continue;
+
+        MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) );
+        MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) );
+        MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) );
+        MPI_CHK( mpi_gcd( &G, &ctx->E, &H  ) );
+    }
+    while( mpi_cmp_int( &G, 1 ) != 0 );
+
+    /*
+     * D  = E^-1 mod ((P-1)*(Q-1))
+     * DP = D mod (P - 1)
+     * DQ = D mod (Q - 1)
+     * QP = Q^-1 mod P
+     */
+    MPI_CHK( mpi_inv_mod( &ctx->D , &ctx->E, &H  ) );
+    MPI_CHK( mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) );
+    MPI_CHK( mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) );
+    MPI_CHK( mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) );
+
+    ctx->len = ( mpi_msb( &ctx->N ) + 7 ) >> 3;
+
+cleanup:
+
+    mpi_free( &P1 ); mpi_free( &Q1 ); mpi_free( &H ); mpi_free( &G );
+
+    if( ret != 0 )
+    {
+        rsa_free( ctx );
+        return( POLARSSL_ERR_RSA_KEY_GEN_FAILED + ret );
+    }
+
+    return( 0 );
+}
+
+#endif /* POLARSSL_GENPRIME */
+
+/*
+ * Check a public RSA key
+ */
+int rsa_check_pubkey( const rsa_context *ctx )
+{
+    if( !ctx->N.p || !ctx->E.p )
+        return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+
+    if( ( ctx->N.p[0] & 1 ) == 0 ||
+        ( ctx->E.p[0] & 1 ) == 0 )
+        return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+
+    if( mpi_msb( &ctx->N ) < 128 ||
+        mpi_msb( &ctx->N ) > POLARSSL_MPI_MAX_BITS )
+        return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+
+    if( mpi_msb( &ctx->E ) < 2 ||
+        mpi_cmp_mpi( &ctx->E, &ctx->N ) >= 0 )
+        return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+
+    return( 0 );
+}
+
+/*
+ * Check a private RSA key
+ */
+int rsa_check_privkey( const rsa_context *ctx )
+{
+    int ret;
+    mpi PQ, DE, P1, Q1, H, I, G, G2, L1, L2, DP, DQ, QP;
+
+    if( ( ret = rsa_check_pubkey( ctx ) ) != 0 )
+        return( ret );
+
+    if( !ctx->P.p || !ctx->Q.p || !ctx->D.p )
+        return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+
+    mpi_init( &PQ ); mpi_init( &DE ); mpi_init( &P1 ); mpi_init( &Q1 );
+    mpi_init( &H  ); mpi_init( &I  ); mpi_init( &G  ); mpi_init( &G2 );
+    mpi_init( &L1 ); mpi_init( &L2 ); mpi_init( &DP ); mpi_init( &DQ );
+    mpi_init( &QP );
+
+    MPI_CHK( mpi_mul_mpi( &PQ, &ctx->P, &ctx->Q ) );
+    MPI_CHK( mpi_mul_mpi( &DE, &ctx->D, &ctx->E ) );
+    MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) );
+    MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) );
+    MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) );
+    MPI_CHK( mpi_gcd( &G, &ctx->E, &H  ) );
+
+    MPI_CHK( mpi_gcd( &G2, &P1, &Q1 ) );
+    MPI_CHK( mpi_div_mpi( &L1, &L2, &H, &G2 ) );
+    MPI_CHK( mpi_mod_mpi( &I, &DE, &L1  ) );
+
+    MPI_CHK( mpi_mod_mpi( &DP, &ctx->D, &P1 ) );
+    MPI_CHK( mpi_mod_mpi( &DQ, &ctx->D, &Q1 ) );
+    MPI_CHK( mpi_inv_mod( &QP, &ctx->Q, &ctx->P ) );
+    /*
+     * Check for a valid PKCS1v2 private key
+     */
+    if( mpi_cmp_mpi( &PQ, &ctx->N ) != 0 ||
+        mpi_cmp_mpi( &DP, &ctx->DP ) != 0 ||
+        mpi_cmp_mpi( &DQ, &ctx->DQ ) != 0 ||
+        mpi_cmp_mpi( &QP, &ctx->QP ) != 0 ||
+        mpi_cmp_int( &L2, 0 ) != 0 ||
+        mpi_cmp_int( &I, 1 ) != 0 ||
+        mpi_cmp_int( &G, 1 ) != 0 )
+    {
+        ret = POLARSSL_ERR_RSA_KEY_CHECK_FAILED;
+    }
+
+cleanup:
+    mpi_free( &PQ ); mpi_free( &DE ); mpi_free( &P1 ); mpi_free( &Q1 );
+    mpi_free( &H  ); mpi_free( &I  ); mpi_free( &G  ); mpi_free( &G2 );
+    mpi_free( &L1 ); mpi_free( &L2 ); mpi_free( &DP ); mpi_free( &DQ );
+    mpi_free( &QP );
+
+    if( ret == POLARSSL_ERR_RSA_KEY_CHECK_FAILED )
+        return( ret );
+
+    if( ret != 0 )
+        return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED + ret );
+
+    return( 0 );
+}
+
+/*
+ * Do an RSA public key operation
+ */
+int rsa_public( rsa_context *ctx,
+                const unsigned char *input,
+                unsigned char *output )
+{
+    int ret;
+    size_t olen;
+    mpi T;
+
+    mpi_init( &T );
+
+    MPI_CHK( mpi_read_binary( &T, input, ctx->len ) );
+
+    if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
+    {
+        mpi_free( &T );
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+    }
+
+    olen = ctx->len;
+    MPI_CHK( mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) );
+    MPI_CHK( mpi_write_binary( &T, output, olen ) );
+
+cleanup:
+
+    mpi_free( &T );
+
+    if( ret != 0 )
+        return( POLARSSL_ERR_RSA_PUBLIC_FAILED + ret );
+
+    return( 0 );
+}
+
+#if !defined(POLARSSL_RSA_NO_CRT)
+/*
+ * Generate or update blinding values, see section 10 of:
+ *  KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
+ *  DSS, and other systems. In : Advances in Cryptology—CRYPTO’96. Springer
+ *  Berlin Heidelberg, 1996. p. 104-113.
+ */
+static int rsa_prepare_blinding( rsa_context *ctx, mpi *Vi, mpi *Vf,
+                 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+    int ret, count = 0;
+
+#if defined(POLARSSL_THREADING_C)
+    polarssl_mutex_lock( &ctx->mutex );
+#endif
+
+    if( ctx->Vf.p != NULL )
+    {
+        /* We already have blinding values, just update them by squaring */
+        MPI_CHK( mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) );
+        MPI_CHK( mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) );
+        MPI_CHK( mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) );
+        MPI_CHK( mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->N ) );
+
+        goto done;
+    }
+
+    /* Unblinding value: Vf = random number, invertible mod N */
+    do {
+        if( count++ > 10 )
+            return( POLARSSL_ERR_RSA_RNG_FAILED );
+
+        MPI_CHK( mpi_fill_random( &ctx->Vf, ctx->len - 1, f_rng, p_rng ) );
+        MPI_CHK( mpi_gcd( &ctx->Vi, &ctx->Vf, &ctx->N ) );
+    } while( mpi_cmp_int( &ctx->Vi, 1 ) != 0 );
+
+    /* Blinding value: Vi =  Vf^(-e) mod N */
+    MPI_CHK( mpi_inv_mod( &ctx->Vi, &ctx->Vf, &ctx->N ) );
+    MPI_CHK( mpi_exp_mod( &ctx->Vi, &ctx->Vi, &ctx->E, &ctx->N, &ctx->RN ) );
+
+done:
+    if( Vi != &ctx->Vi )
+    {
+        MPI_CHK( mpi_copy( Vi, &ctx->Vi ) );
+        MPI_CHK( mpi_copy( Vf, &ctx->Vf ) );
+    }
+
+cleanup:
+#if defined(POLARSSL_THREADING_C)
+    polarssl_mutex_unlock( &ctx->mutex );
+#endif
+
+    return( ret );
+}
+#endif /* !POLARSSL_RSA_NO_CRT */
+
+/*
+ * Do an RSA private key operation
+ */
+int rsa_private( rsa_context *ctx,
+                 int (*f_rng)(void *, unsigned char *, size_t),
+                 void *p_rng,
+                 const unsigned char *input,
+                 unsigned char *output )
+{
+    int ret;
+    size_t olen;
+    mpi T, T1, T2;
+#if !defined(POLARSSL_RSA_NO_CRT)
+    mpi *Vi, *Vf;
+
+    /*
+     * When using the Chinese Remainder Theorem, we use blinding values.
+     * Without threading, we just read them directly from the context,
+     * otherwise we make a local copy in order to reduce locking contention.
+     */
+#if defined(POLARSSL_THREADING_C)
+    mpi Vi_copy, Vf_copy;
+
+    mpi_init( &Vi_copy ); mpi_init( &Vf_copy );
+    Vi = &Vi_copy;
+    Vf = &Vf_copy;
+#else
+    Vi = &ctx->Vi;
+    Vf = &ctx->Vf;
+#endif
+#endif /* !POLARSSL_RSA_NO_CRT */
+
+    mpi_init( &T ); mpi_init( &T1 ); mpi_init( &T2 );
+
+    MPI_CHK( mpi_read_binary( &T, input, ctx->len ) );
+    if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
+    {
+        mpi_free( &T );
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+    }
+
+#if defined(POLARSSL_RSA_NO_CRT)
+    ((void) f_rng);
+    ((void) p_rng);
+    MPI_CHK( mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) );
+#else
+    if( f_rng != NULL )
+    {
+        /*
+         * Blinding
+         * T = T * Vi mod N
+         */
+        MPI_CHK( rsa_prepare_blinding( ctx, Vi, Vf, f_rng, p_rng ) );
+        MPI_CHK( mpi_mul_mpi( &T, &T, Vi ) );
+        MPI_CHK( mpi_mod_mpi( &T, &T, &ctx->N ) );
+    }
+
+    /*
+     * faster decryption using the CRT
+     *
+     * T1 = input ^ dP mod P
+     * T2 = input ^ dQ mod Q
+     */
+    MPI_CHK( mpi_exp_mod( &T1, &T, &ctx->DP, &ctx->P, &ctx->RP ) );
+    MPI_CHK( mpi_exp_mod( &T2, &T, &ctx->DQ, &ctx->Q, &ctx->RQ ) );
+
+    /*
+     * T = (T1 - T2) * (Q^-1 mod P) mod P
+     */
+    MPI_CHK( mpi_sub_mpi( &T, &T1, &T2 ) );
+    MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->QP ) );
+    MPI_CHK( mpi_mod_mpi( &T, &T1, &ctx->P ) );
+
+    /*
+     * T = T2 + T * Q
+     */
+    MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->Q ) );
+    MPI_CHK( mpi_add_mpi( &T, &T2, &T1 ) );
+
+    if( f_rng != NULL )
+    {
+        /*
+         * Unblind
+         * T = T * Vf mod N
+         */
+        MPI_CHK( mpi_mul_mpi( &T, &T, Vf ) );
+        MPI_CHK( mpi_mod_mpi( &T, &T, &ctx->N ) );
+    }
+#endif /* POLARSSL_RSA_NO_CRT */
+
+    olen = ctx->len;
+    MPI_CHK( mpi_write_binary( &T, output, olen ) );
+
+cleanup:
+    mpi_free( &T ); mpi_free( &T1 ); mpi_free( &T2 );
+#if !defined(POLARSSL_RSA_NO_CRT) && defined(POLARSSL_THREADING_C)
+    mpi_free( &Vi_copy ); mpi_free( &Vf_copy );
+#endif
+
+    if( ret != 0 )
+        return( POLARSSL_ERR_RSA_PRIVATE_FAILED + ret );
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_PKCS1_V21)
+/**
+ * Generate and apply the MGF1 operation (from PKCS#1 v2.1) to a buffer.
+ *
+ * \param dst       buffer to mask
+ * \param dlen      length of destination buffer
+ * \param src       source of the mask generation
+ * \param slen      length of the source buffer
+ * \param md_ctx    message digest context to use
+ */
+static void mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src,
+                      size_t slen, md_context_t *md_ctx )
+{
+    unsigned char mask[POLARSSL_MD_MAX_SIZE];
+    unsigned char counter[4];
+    unsigned char *p;
+    unsigned int hlen;
+    size_t i, use_len;
+
+    memset( mask, 0, POLARSSL_MD_MAX_SIZE );
+    memset( counter, 0, 4 );
+
+    hlen = md_ctx->md_info->size;
+
+    // Generate and apply dbMask
+    //
+    p = dst;
+
+    while( dlen > 0 )
+    {
+        use_len = hlen;
+        if( dlen < hlen )
+            use_len = dlen;
+
+        md_starts( md_ctx );
+        md_update( md_ctx, src, slen );
+        md_update( md_ctx, counter, 4 );
+        md_finish( md_ctx, mask );
+
+        for( i = 0; i < use_len; ++i )
+            *p++ ^= mask[i];
+
+        counter[3]++;
+
+        dlen -= use_len;
+    }
+}
+#endif /* POLARSSL_PKCS1_V21 */
+
+#if defined(POLARSSL_PKCS1_V21)
+/*
+ * Implementation of the PKCS#1 v2.1 RSAES-OAEP-ENCRYPT function
+ */
+int rsa_rsaes_oaep_encrypt( 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 )
+{
+    size_t olen;
+    int ret;
+    unsigned char *p = output;
+    unsigned int hlen;
+    const md_info_t *md_info;
+    md_context_t md_ctx;
+
+    if( ctx->padding != RSA_PKCS_V21 || f_rng == NULL )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    md_info = md_info_from_type( ctx->hash_id );
+    if( md_info == NULL )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    olen = ctx->len;
+    hlen = md_get_size( md_info );
+
+    if( olen < ilen + 2 * hlen + 2 || f_rng == NULL )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    memset( output, 0, olen );
+
+    *p++ = 0;
+
+    // Generate a random octet string seed
+    //
+    if( ( ret = f_rng( p_rng, p, hlen ) ) != 0 )
+        return( POLARSSL_ERR_RSA_RNG_FAILED + ret );
+
+    p += hlen;
+
+    // Construct DB
+    //
+    md( md_info, label, label_len, p );
+    p += hlen;
+    p += olen - 2 * hlen - 2 - ilen;
+    *p++ = 1;
+    memcpy( p, input, ilen );
+
+    md_init_ctx( &md_ctx, md_info );
+
+    // maskedDB: Apply dbMask to DB
+    //
+    mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen,
+               &md_ctx );
+
+    // maskedSeed: Apply seedMask to seed
+    //
+    mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1,
+               &md_ctx );
+
+    md_free_ctx( &md_ctx );
+
+    return( ( mode == RSA_PUBLIC )
+            ? rsa_public(  ctx, output, output )
+            : rsa_private( ctx, f_rng, p_rng, output, output ) );
+}
+#endif /* POLARSSL_PKCS1_V21 */
+
+#if defined(POLARSSL_PKCS1_V15)
+/*
+ * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-ENCRYPT function
+ */
+int rsa_rsaes_pkcs1_v15_encrypt( 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 )
+{
+    size_t nb_pad, olen;
+    int ret;
+    unsigned char *p = output;
+
+    if( ctx->padding != RSA_PKCS_V15 || f_rng == NULL )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    olen = ctx->len;
+
+    if( olen < ilen + 11 )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    nb_pad = olen - 3 - ilen;
+
+    *p++ = 0;
+    if( mode == RSA_PUBLIC )
+    {
+        *p++ = RSA_CRYPT;
+
+        while( nb_pad-- > 0 )
+        {
+            int rng_dl = 100;
+
+            do {
+                ret = f_rng( p_rng, p, 1 );
+            } while( *p == 0 && --rng_dl && ret == 0 );
+
+            // Check if RNG failed to generate data
+            //
+            if( rng_dl == 0 || ret != 0)
+                return POLARSSL_ERR_RSA_RNG_FAILED + ret;
+
+            p++;
+        }
+    }
+    else
+    {
+        *p++ = RSA_SIGN;
+
+        while( nb_pad-- > 0 )
+            *p++ = 0xFF;
+    }
+
+    *p++ = 0;
+    memcpy( p, input, ilen );
+
+    return( ( mode == RSA_PUBLIC )
+            ? rsa_public(  ctx, output, output )
+            : rsa_private( ctx, f_rng, p_rng, output, output ) );
+}
+#endif /* POLARSSL_PKCS1_V15 */
+
+/*
+ * Add the message padding, then do an RSA operation
+ */
+int rsa_pkcs1_encrypt( 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 )
+{
+    switch( ctx->padding )
+    {
+#if defined(POLARSSL_PKCS1_V15)
+        case RSA_PKCS_V15:
+            return rsa_rsaes_pkcs1_v15_encrypt( ctx, f_rng, p_rng, mode, ilen,
+                                                input, output );
+#endif
+
+#if defined(POLARSSL_PKCS1_V21)
+        case RSA_PKCS_V21:
+            return rsa_rsaes_oaep_encrypt( ctx, f_rng, p_rng, mode, NULL, 0,
+                                           ilen, input, output );
+#endif
+
+        default:
+            return( POLARSSL_ERR_RSA_INVALID_PADDING );
+    }
+}
+
+#if defined(POLARSSL_PKCS1_V21)
+/*
+ * Implementation of the PKCS#1 v2.1 RSAES-OAEP-DECRYPT function
+ */
+int rsa_rsaes_oaep_decrypt( 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 )
+{
+    int ret;
+    size_t ilen, i, pad_len;
+    unsigned char *p, bad, pad_done;
+    unsigned char buf[POLARSSL_MPI_MAX_SIZE];
+    unsigned char lhash[POLARSSL_MD_MAX_SIZE];
+    unsigned int hlen;
+    const md_info_t *md_info;
+    md_context_t md_ctx;
+
+    /*
+     * Parameters sanity checks
+     */
+    if( ctx->padding != RSA_PKCS_V21 )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    ilen = ctx->len;
+
+    if( ilen < 16 || ilen > sizeof( buf ) )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    md_info = md_info_from_type( ctx->hash_id );
+    if( md_info == NULL )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    /*
+     * RSA operation
+     */
+    ret = ( mode == RSA_PUBLIC )
+          ? rsa_public(  ctx, input, buf )
+          : rsa_private( ctx, f_rng, p_rng, input, buf );
+
+    if( ret != 0 )
+        return( ret );
+
+    /*
+     * Unmask data and generate lHash
+     */
+    hlen = md_get_size( md_info );
+
+    md_init_ctx( &md_ctx, md_info );
+
+    /* Generate lHash */
+    md( md_info, label, label_len, lhash );
+
+    /* seed: Apply seedMask to maskedSeed */
+    mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1,
+               &md_ctx );
+
+    /* DB: Apply dbMask to maskedDB */
+    mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen,
+               &md_ctx );
+
+    md_free_ctx( &md_ctx );
+
+    /*
+     * Check contents, in "constant-time"
+     */
+    p = buf;
+    bad = 0;
+
+    bad |= *p++; /* First byte must be 0 */
+
+    p += hlen; /* Skip seed */
+
+    /* Check lHash */
+    for( i = 0; i < hlen; i++ )
+        bad |= lhash[i] ^ *p++;
+
+    /* Get zero-padding len, but always read till end of buffer
+     * (minus one, for the 01 byte) */
+    pad_len = 0;
+    pad_done = 0;
+    for( i = 0; i < ilen - 2 * hlen - 2; i++ )
+    {
+        pad_done |= p[i];
+        pad_len += ( pad_done == 0 );
+    }
+
+    p += pad_len;
+    bad |= *p++ ^ 0x01;
+
+    /*
+     * The only information "leaked" is whether the padding was correct or not
+     * (eg, no data is copied if it was not correct). This meets the
+     * recommendations in PKCS#1 v2.2: an opponent cannot distinguish between
+     * the different error conditions.
+     */
+    if( bad != 0 )
+        return( POLARSSL_ERR_RSA_INVALID_PADDING );
+
+    if (ilen - (p - buf) > output_max_len)
+        return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE );
+
+    *olen = ilen - (p - buf);
+    memcpy( output, p, *olen );
+
+    return( 0 );
+}
+#endif /* POLARSSL_PKCS1_V21 */
+
+#if defined(POLARSSL_PKCS1_V15)
+/*
+ * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function
+ */
+int rsa_rsaes_pkcs1_v15_decrypt( 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)
+{
+    int ret;
+    size_t ilen, pad_count = 0, i;
+    unsigned char *p, bad, pad_done = 0;
+    unsigned char buf[POLARSSL_MPI_MAX_SIZE];
+
+    if( ctx->padding != RSA_PKCS_V15 )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    ilen = ctx->len;
+
+    if( ilen < 16 || ilen > sizeof( buf ) )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    ret = ( mode == RSA_PUBLIC )
+          ? rsa_public(  ctx, input, buf )
+          : rsa_private( ctx, f_rng, p_rng, input, buf );
+
+    if( ret != 0 )
+        return( ret );
+
+    p = buf;
+    bad = 0;
+
+    /*
+     * Check and get padding len in "constant-time"
+     */
+    bad |= *p++; /* First byte must be 0 */
+
+    /* This test does not depend on secret data */
+    if( mode == RSA_PRIVATE )
+    {
+        bad |= *p++ ^ RSA_CRYPT;
+
+        /* Get padding len, but always read till end of buffer
+         * (minus one, for the 00 byte) */
+        for( i = 0; i < ilen - 3; i++ )
+        {
+            pad_done |= ( p[i] == 0 );
+            pad_count += ( pad_done == 0 );
+        }
+
+        p += pad_count;
+        bad |= *p++; /* Must be zero */
+    }
+    else
+    {
+        bad |= *p++ ^ RSA_SIGN;
+
+        /* Get padding len, but always read till end of buffer
+         * (minus one, for the 00 byte) */
+        for( i = 0; i < ilen - 3; i++ )
+        {
+            pad_done |= ( p[i] != 0xFF );
+            pad_count += ( pad_done == 0 );
+        }
+
+        p += pad_count;
+        bad |= *p++; /* Must be zero */
+    }
+
+    if( bad )
+        return( POLARSSL_ERR_RSA_INVALID_PADDING );
+
+    if (ilen - (p - buf) > output_max_len)
+        return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE );
+
+    *olen = ilen - (p - buf);
+    memcpy( output, p, *olen );
+
+    return( 0 );
+}
+#endif /* POLARSSL_PKCS1_V15 */
+
+/*
+ * Do an RSA operation, then remove the message padding
+ */
+int rsa_pkcs1_decrypt( 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)
+{
+    switch( ctx->padding )
+    {
+#if defined(POLARSSL_PKCS1_V15)
+        case RSA_PKCS_V15:
+            return rsa_rsaes_pkcs1_v15_decrypt( ctx, f_rng, p_rng, mode, olen,
+                                                input, output, output_max_len );
+#endif
+
+#if defined(POLARSSL_PKCS1_V21)
+        case RSA_PKCS_V21:
+            return rsa_rsaes_oaep_decrypt( ctx, f_rng, p_rng, mode, NULL, 0,
+                                           olen, input, output,
+                                           output_max_len );
+#endif
+
+        default:
+            return( POLARSSL_ERR_RSA_INVALID_PADDING );
+    }
+}
+
+#if defined(POLARSSL_PKCS1_V21)
+/*
+ * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function
+ */
+int rsa_rsassa_pss_sign( rsa_context *ctx,
+                         int (*f_rng)(void *, unsigned char *, size_t),
+                         void *p_rng,
+                         int mode,
+                         md_type_t md_alg,
+                         unsigned int hashlen,
+                         const unsigned char *hash,
+                         unsigned char *sig )
+{
+    size_t olen;
+    unsigned char *p = sig;
+    unsigned char salt[POLARSSL_MD_MAX_SIZE];
+    unsigned int slen, hlen, offset = 0;
+    int ret;
+    size_t msb;
+    const md_info_t *md_info;
+    md_context_t md_ctx;
+
+    if( ctx->padding != RSA_PKCS_V21 || f_rng == NULL )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    olen = ctx->len;
+
+    if( md_alg != POLARSSL_MD_NONE )
+    {
+        // Gather length of hash to sign
+        //
+        md_info = md_info_from_type( md_alg );
+        if( md_info == NULL )
+            return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+        hashlen = md_get_size( md_info );
+    }
+
+    md_info = md_info_from_type( ctx->hash_id );
+    if( md_info == NULL )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    hlen = md_get_size( md_info );
+    slen = hlen;
+
+    if( olen < hlen + slen + 2 )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    memset( sig, 0, olen );
+
+    // Generate salt of length slen
+    //
+    if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 )
+        return( POLARSSL_ERR_RSA_RNG_FAILED + ret );
+
+    // Note: EMSA-PSS encoding is over the length of N - 1 bits
+    //
+    msb = mpi_msb( &ctx->N ) - 1;
+    p += olen - hlen * 2 - 2;
+    *p++ = 0x01;
+    memcpy( p, salt, slen );
+    p += slen;
+
+    md_init_ctx( &md_ctx, md_info );
+
+    // Generate H = Hash( M' )
+    //
+    md_starts( &md_ctx );
+    md_update( &md_ctx, p, 8 );
+    md_update( &md_ctx, hash, hashlen );
+    md_update( &md_ctx, salt, slen );
+    md_finish( &md_ctx, p );
+
+    // Compensate for boundary condition when applying mask
+    //
+    if( msb % 8 == 0 )
+        offset = 1;
+
+    // maskedDB: Apply dbMask to DB
+    //
+    mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen, &md_ctx );
+
+    md_free_ctx( &md_ctx );
+
+    msb = mpi_msb( &ctx->N ) - 1;
+    sig[0] &= 0xFF >> ( olen * 8 - msb );
+
+    p += hlen;
+    *p++ = 0xBC;
+
+    return( ( mode == RSA_PUBLIC )
+            ? rsa_public(  ctx, sig, sig )
+            : rsa_private( ctx, f_rng, p_rng, sig, sig ) );
+}
+#endif /* POLARSSL_PKCS1_V21 */
+
+#if defined(POLARSSL_PKCS1_V15)
+/*
+ * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-V1_5-SIGN function
+ */
+/*
+ * Do an RSA operation to sign the message digest
+ */
+int rsa_rsassa_pkcs1_v15_sign( rsa_context *ctx,
+                               int (*f_rng)(void *, unsigned char *, size_t),
+                               void *p_rng,
+                               int mode,
+                               md_type_t md_alg,
+                               unsigned int hashlen,
+                               const unsigned char *hash,
+                               unsigned char *sig )
+{
+    size_t nb_pad, olen, oid_size = 0;
+    unsigned char *p = sig;
+    const char *oid;
+
+    if( ctx->padding != RSA_PKCS_V15 )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    olen = ctx->len;
+    nb_pad = olen - 3;
+
+    if( md_alg != POLARSSL_MD_NONE )
+    {
+        const md_info_t *md_info = md_info_from_type( md_alg );
+        if( md_info == NULL )
+            return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+        if( oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 )
+            return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+        nb_pad -= 10 + oid_size;
+
+        hashlen = md_get_size( md_info );
+    }
+
+    nb_pad -= hashlen;
+
+    if( ( nb_pad < 8 ) || ( nb_pad > olen ) )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    *p++ = 0;
+    *p++ = RSA_SIGN;
+    memset( p, 0xFF, nb_pad );
+    p += nb_pad;
+    *p++ = 0;
+
+    if( md_alg == POLARSSL_MD_NONE )
+    {
+        memcpy( p, hash, hashlen );
+    }
+    else
+    {
+        /*
+         * DigestInfo ::= SEQUENCE {
+         *   digestAlgorithm DigestAlgorithmIdentifier,
+         *   digest Digest }
+         *
+         * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
+         *
+         * Digest ::= OCTET STRING
+         */
+        *p++ = ASN1_SEQUENCE | ASN1_CONSTRUCTED;
+        *p++ = (unsigned char) ( 0x08 + oid_size + hashlen );
+        *p++ = ASN1_SEQUENCE | ASN1_CONSTRUCTED;
+        *p++ = (unsigned char) ( 0x04 + oid_size );
+        *p++ = ASN1_OID;
+        *p++ = oid_size & 0xFF;
+        memcpy( p, oid, oid_size );
+        p += oid_size;
+        *p++ = ASN1_NULL;
+        *p++ = 0x00;
+        *p++ = ASN1_OCTET_STRING;
+        *p++ = hashlen;
+        memcpy( p, hash, hashlen );
+    }
+
+    return( ( mode == RSA_PUBLIC )
+            ? rsa_public(  ctx, sig, sig )
+            : rsa_private( ctx, f_rng, p_rng, sig, sig ) );
+}
+#endif /* POLARSSL_PKCS1_V15 */
+
+/*
+ * Do an RSA operation to sign the message digest
+ */
+int rsa_pkcs1_sign( rsa_context *ctx,
+                    int (*f_rng)(void *, unsigned char *, size_t),
+                    void *p_rng,
+                    int mode,
+                    md_type_t md_alg,
+                    unsigned int hashlen,
+                    const unsigned char *hash,
+                    unsigned char *sig )
+{
+    switch( ctx->padding )
+    {
+#if defined(POLARSSL_PKCS1_V15)
+        case RSA_PKCS_V15:
+            return rsa_rsassa_pkcs1_v15_sign( ctx, f_rng, p_rng, mode, md_alg,
+                                              hashlen, hash, sig );
+#endif
+
+#if defined(POLARSSL_PKCS1_V21)
+        case RSA_PKCS_V21:
+            return rsa_rsassa_pss_sign( ctx, f_rng, p_rng, mode, md_alg,
+                                        hashlen, hash, sig );
+#endif
+
+        default:
+            return( POLARSSL_ERR_RSA_INVALID_PADDING );
+    }
+}
+
+#if defined(POLARSSL_PKCS1_V21)
+/*
+ * Implementation of the PKCS#1 v2.1 RSASSA-PSS-VERIFY function
+ */
+int rsa_rsassa_pss_verify( rsa_context *ctx,
+                           int (*f_rng)(void *, unsigned char *, size_t),
+                           void *p_rng,
+                           int mode,
+                           md_type_t md_alg,
+                           unsigned int hashlen,
+                           const unsigned char *hash,
+                           const unsigned char *sig )
+{
+    int ret;
+    size_t siglen;
+    unsigned char *p;
+    unsigned char buf[POLARSSL_MPI_MAX_SIZE];
+    unsigned char result[POLARSSL_MD_MAX_SIZE];
+    unsigned char zeros[8];
+    unsigned int hlen;
+    size_t slen, msb;
+    const md_info_t *md_info;
+    md_context_t md_ctx;
+
+    if( ctx->padding != RSA_PKCS_V21 )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    siglen = ctx->len;
+
+    if( siglen < 16 || siglen > sizeof( buf ) )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    ret = ( mode == RSA_PUBLIC )
+          ? rsa_public(  ctx, sig, buf )
+          : rsa_private( ctx, f_rng, p_rng, sig, buf );
+
+    if( ret != 0 )
+        return( ret );
+
+    p = buf;
+
+    if( buf[siglen - 1] != 0xBC )
+        return( POLARSSL_ERR_RSA_INVALID_PADDING );
+
+    if( md_alg != POLARSSL_MD_NONE )
+    {
+        // Gather length of hash to sign
+        //
+        md_info = md_info_from_type( md_alg );
+        if( md_info == NULL )
+            return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+        hashlen = md_get_size( md_info );
+    }
+
+    md_info = md_info_from_type( ctx->hash_id );
+    if( md_info == NULL )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    hlen = md_get_size( md_info );
+    slen = siglen - hlen - 1;
+
+    memset( zeros, 0, 8 );
+
+    // Note: EMSA-PSS verification is over the length of N - 1 bits
+    //
+    msb = mpi_msb( &ctx->N ) - 1;
+
+    // Compensate for boundary condition when applying mask
+    //
+    if( msb % 8 == 0 )
+    {
+        p++;
+        siglen -= 1;
+    }
+    if( buf[0] >> ( 8 - siglen * 8 + msb ) )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    md_init_ctx( &md_ctx, md_info );
+
+    mgf_mask( p, siglen - hlen - 1, p + siglen - hlen - 1, hlen, &md_ctx );
+
+    buf[0] &= 0xFF >> ( siglen * 8 - msb );
+
+    while( p < buf + siglen && *p == 0 )
+        p++;
+
+    if( p == buf + siglen ||
+        *p++ != 0x01 )
+    {
+        md_free_ctx( &md_ctx );
+        return( POLARSSL_ERR_RSA_INVALID_PADDING );
+    }
+
+    slen -= p - buf;
+
+    // Generate H = Hash( M' )
+    //
+    md_starts( &md_ctx );
+    md_update( &md_ctx, zeros, 8 );
+    md_update( &md_ctx, hash, hashlen );
+    md_update( &md_ctx, p, slen );
+    md_finish( &md_ctx, result );
+
+    md_free_ctx( &md_ctx );
+
+    if( memcmp( p + slen, result, hlen ) == 0 )
+        return( 0 );
+    else
+        return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+}
+#endif /* POLARSSL_PKCS1_V21 */
+
+#if defined(POLARSSL_PKCS1_V15)
+/*
+ * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-v1_5-VERIFY function
+ */
+int rsa_rsassa_pkcs1_v15_verify( rsa_context *ctx,
+                                 int (*f_rng)(void *, unsigned char *, size_t),
+                                 void *p_rng,
+                                 int mode,
+                                 md_type_t md_alg,
+                                 unsigned int hashlen,
+                                 const unsigned char *hash,
+                                 const unsigned char *sig )
+{
+    int ret;
+    size_t len, siglen, asn1_len;
+    unsigned char *p, *end;
+    unsigned char buf[POLARSSL_MPI_MAX_SIZE];
+    md_type_t msg_md_alg;
+    const md_info_t *md_info;
+    asn1_buf oid;
+
+    if( ctx->padding != RSA_PKCS_V15 )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    siglen = ctx->len;
+
+    if( siglen < 16 || siglen > sizeof( buf ) )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    ret = ( mode == RSA_PUBLIC )
+          ? rsa_public(  ctx, sig, buf )
+          : rsa_private( ctx, f_rng, p_rng, sig, buf );
+
+    if( ret != 0 )
+        return( ret );
+
+    p = buf;
+
+    if( *p++ != 0 || *p++ != RSA_SIGN )
+        return( POLARSSL_ERR_RSA_INVALID_PADDING );
+
+    while( *p != 0 )
+    {
+        if( p >= buf + siglen - 1 || *p != 0xFF )
+            return( POLARSSL_ERR_RSA_INVALID_PADDING );
+        p++;
+    }
+    p++;
+
+    len = siglen - ( p - buf );
+
+    if( len == hashlen && md_alg == POLARSSL_MD_NONE )
+    {
+        if( memcmp( p, hash, hashlen ) == 0 )
+            return( 0 );
+        else
+            return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+    }
+
+    md_info = md_info_from_type( md_alg );
+    if( md_info == NULL )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+    hashlen = md_get_size( md_info );
+
+    end = p + len;
+
+    // Parse the ASN.1 structure inside the PKCS#1 v1.5 structure
+    //
+    if( ( ret = asn1_get_tag( &p, end, &asn1_len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+        return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+
+    if( asn1_len + 2 != len )
+        return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+
+    if( ( ret = asn1_get_tag( &p, end, &asn1_len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+        return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+
+    if( asn1_len + 6 + hashlen != len )
+        return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+
+    if( ( ret = asn1_get_tag( &p, end, &oid.len, ASN1_OID ) ) != 0 )
+        return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+
+    oid.p = p;
+    p += oid.len;
+
+    if( oid_get_md_alg( &oid, &msg_md_alg ) != 0 )
+        return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+
+    if( md_alg != msg_md_alg )
+        return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+
+    /*
+     * assume the algorithm parameters must be NULL
+     */
+    if( ( ret = asn1_get_tag( &p, end, &asn1_len, ASN1_NULL ) ) != 0 )
+        return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+
+    if( ( ret = asn1_get_tag( &p, end, &asn1_len, ASN1_OCTET_STRING ) ) != 0 )
+        return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+
+    if( asn1_len != hashlen )
+        return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+
+    if( memcmp( p, hash, hashlen ) != 0 )
+        return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+
+    p += hashlen;
+
+    if( p != end )
+        return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+
+    return( 0 );
+}
+#endif /* POLARSSL_PKCS1_V15 */
+
+/*
+ * Do an RSA operation and check the message digest
+ */
+int rsa_pkcs1_verify( rsa_context *ctx,
+                      int (*f_rng)(void *, unsigned char *, size_t),
+                      void *p_rng,
+                      int mode,
+                      md_type_t md_alg,
+                      unsigned int hashlen,
+                      const unsigned char *hash,
+                      const unsigned char *sig )
+{
+    switch( ctx->padding )
+    {
+#if defined(POLARSSL_PKCS1_V15)
+        case RSA_PKCS_V15:
+            return rsa_rsassa_pkcs1_v15_verify( ctx, f_rng, p_rng, mode, md_alg,
+                                                hashlen, hash, sig );
+#endif
+
+#if defined(POLARSSL_PKCS1_V21)
+        case RSA_PKCS_V21:
+            return rsa_rsassa_pss_verify( ctx, f_rng, p_rng, mode, md_alg,
+                                          hashlen, hash, sig );
+#endif
+
+        default:
+            return( POLARSSL_ERR_RSA_INVALID_PADDING );
+    }
+}
+
+/*
+ * Copy the components of an RSA key
+ */
+int rsa_copy( rsa_context *dst, const rsa_context *src )
+{
+    int ret;
+
+    dst->ver = src->ver;
+    dst->len = src->len;
+
+    MPI_CHK( mpi_copy( &dst->N, &src->N ) );
+    MPI_CHK( mpi_copy( &dst->E, &src->E ) );
+
+    MPI_CHK( mpi_copy( &dst->D, &src->D ) );
+    MPI_CHK( mpi_copy( &dst->P, &src->P ) );
+    MPI_CHK( mpi_copy( &dst->Q, &src->Q ) );
+    MPI_CHK( mpi_copy( &dst->DP, &src->DP ) );
+    MPI_CHK( mpi_copy( &dst->DQ, &src->DQ ) );
+    MPI_CHK( mpi_copy( &dst->QP, &src->QP ) );
+
+    MPI_CHK( mpi_copy( &dst->RN, &src->RN ) );
+    MPI_CHK( mpi_copy( &dst->RP, &src->RP ) );
+    MPI_CHK( mpi_copy( &dst->RQ, &src->RQ ) );
+
+#if !defined(POLARSSL_RSA_NO_CRT)
+    MPI_CHK( mpi_copy( &dst->Vi, &src->Vi ) );
+    MPI_CHK( mpi_copy( &dst->Vf, &src->Vf ) );
+#endif
+
+    dst->padding = src->padding;
+    dst->hash_id = src->hash_id;
+
+cleanup:
+    if( ret != 0 )
+        rsa_free( dst );
+
+    return( ret );
+}
+
+/*
+ * Free the components of an RSA key
+ */
+void rsa_free( rsa_context *ctx )
+{
+#if !defined(POLARSSL_RSA_NO_CRT)
+    mpi_free( &ctx->Vi ); mpi_free( &ctx->Vf );
+#endif
+    mpi_free( &ctx->RQ ); mpi_free( &ctx->RP ); mpi_free( &ctx->RN );
+    mpi_free( &ctx->QP ); mpi_free( &ctx->DQ ); mpi_free( &ctx->DP );
+    mpi_free( &ctx->Q  ); mpi_free( &ctx->P  ); mpi_free( &ctx->D );
+    mpi_free( &ctx->E  ); mpi_free( &ctx->N  );
+
+#if defined(POLARSSL_THREADING_C)
+    polarssl_mutex_free( &ctx->mutex );
+#endif
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include "polarssl/sha1.h"
+
+/*
+ * Example RSA-1024 keypair, for test purposes
+ */
+#define KEY_LEN 128
+
+#define RSA_N   "9292758453063D803DD603D5E777D788" \
+                "8ED1D5BF35786190FA2F23EBC0848AEA" \
+                "DDA92CA6C3D80B32C4D109BE0F36D6AE" \
+                "7130B9CED7ACDF54CFC7555AC14EEBAB" \
+                "93A89813FBF3C4F8066D2D800F7C38A8" \
+                "1AE31942917403FF4946B0A83D3D3E05" \
+                "EE57C6F5F5606FB5D4BC6CD34EE0801A" \
+                "5E94BB77B07507233A0BC7BAC8F90F79"
+
+#define RSA_E   "10001"
+
+#define RSA_D   "24BF6185468786FDD303083D25E64EFC" \
+                "66CA472BC44D253102F8B4A9D3BFA750" \
+                "91386C0077937FE33FA3252D28855837" \
+                "AE1B484A8A9A45F7EE8C0C634F99E8CD" \
+                "DF79C5CE07EE72C7F123142198164234" \
+                "CABB724CF78B8173B9F880FC86322407" \
+                "AF1FEDFDDE2BEB674CA15F3E81A1521E" \
+                "071513A1E85B5DFA031F21ECAE91A34D"
+
+#define RSA_P   "C36D0EB7FCD285223CFB5AABA5BDA3D8" \
+                "2C01CAD19EA484A87EA4377637E75500" \
+                "FCB2005C5C7DD6EC4AC023CDA285D796" \
+                "C3D9E75E1EFC42488BB4F1D13AC30A57"
+
+#define RSA_Q   "C000DF51A7C77AE8D7C7370C1FF55B69" \
+                "E211C2B9E5DB1ED0BF61D0D9899620F4" \
+                "910E4168387E3C30AA1E00C339A79508" \
+                "8452DD96A9A5EA5D9DCA68DA636032AF"
+
+#define RSA_DP  "C1ACF567564274FB07A0BBAD5D26E298" \
+                "3C94D22288ACD763FD8E5600ED4A702D" \
+                "F84198A5F06C2E72236AE490C93F07F8" \
+                "3CC559CD27BC2D1CA488811730BB5725"
+
+#define RSA_DQ  "4959CBF6F8FEF750AEE6977C155579C7" \
+                "D8AAEA56749EA28623272E4F7D0592AF" \
+                "7C1F1313CAC9471B5C523BFE592F517B" \
+                "407A1BD76C164B93DA2D32A383E58357"
+
+#define RSA_QP  "9AE7FBC99546432DF71896FC239EADAE" \
+                "F38D18D2B2F0E2DD275AA977E2BF4411" \
+                "F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \
+                "A74206CEC169D74BF5A8C50D6F48EA08"
+
+#define PT_LEN  24
+#define RSA_PT  "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \
+                "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD"
+
+#if defined(POLARSSL_PKCS1_V15)
+static int myrand( void *rng_state, unsigned char *output, size_t len )
+{
+#if !defined(__OpenBSD__)
+    size_t i;
+
+    if( rng_state != NULL )
+        rng_state  = NULL;
+
+    for( i = 0; i < len; ++i )
+        output[i] = rand();
+#else
+    if( rng_state != NULL )
+        rng_state = NULL;
+
+    arc4random_buf( output, len );
+#endif /* !OpenBSD */
+
+    return( 0 );
+}
+#endif /* POLARSSL_PKCS1_V15 */
+
+/*
+ * Checkup routine
+ */
+int rsa_self_test( int verbose )
+{
+    int ret = 0;
+#if defined(POLARSSL_PKCS1_V15)
+    size_t len;
+    rsa_context rsa;
+    unsigned char rsa_plaintext[PT_LEN];
+    unsigned char rsa_decrypted[PT_LEN];
+    unsigned char rsa_ciphertext[KEY_LEN];
+#if defined(POLARSSL_SHA1_C)
+    unsigned char sha1sum[20];
+#endif
+
+    rsa_init( &rsa, RSA_PKCS_V15, 0 );
+
+    rsa.len = KEY_LEN;
+    MPI_CHK( mpi_read_string( &rsa.N , 16, RSA_N  ) );
+    MPI_CHK( mpi_read_string( &rsa.E , 16, RSA_E  ) );
+    MPI_CHK( mpi_read_string( &rsa.D , 16, RSA_D  ) );
+    MPI_CHK( mpi_read_string( &rsa.P , 16, RSA_P  ) );
+    MPI_CHK( mpi_read_string( &rsa.Q , 16, RSA_Q  ) );
+    MPI_CHK( mpi_read_string( &rsa.DP, 16, RSA_DP ) );
+    MPI_CHK( mpi_read_string( &rsa.DQ, 16, RSA_DQ ) );
+    MPI_CHK( mpi_read_string( &rsa.QP, 16, RSA_QP ) );
+
+    if( verbose != 0 )
+        polarssl_printf( "  RSA key validation: " );
+
+    if( rsa_check_pubkey(  &rsa ) != 0 ||
+        rsa_check_privkey( &rsa ) != 0 )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "failed\n" );
+
+        return( 1 );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n  PKCS#1 encryption : " );
+
+    memcpy( rsa_plaintext, RSA_PT, PT_LEN );
+
+    if( rsa_pkcs1_encrypt( &rsa, myrand, NULL, RSA_PUBLIC, PT_LEN,
+                           rsa_plaintext, rsa_ciphertext ) != 0 )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "failed\n" );
+
+        return( 1 );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n  PKCS#1 decryption : " );
+
+    if( rsa_pkcs1_decrypt( &rsa, myrand, NULL, RSA_PRIVATE, &len,
+                           rsa_ciphertext, rsa_decrypted,
+                           sizeof(rsa_decrypted) ) != 0 )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "failed\n" );
+
+        return( 1 );
+    }
+
+    if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "failed\n" );
+
+        return( 1 );
+    }
+
+#if defined(POLARSSL_SHA1_C)
+    if( verbose != 0 )
+        polarssl_printf( "passed\n  PKCS#1 data sign  : " );
+
+    sha1( rsa_plaintext, PT_LEN, sha1sum );
+
+    if( rsa_pkcs1_sign( &rsa, myrand, NULL, RSA_PRIVATE, POLARSSL_MD_SHA1, 0,
+                        sha1sum, rsa_ciphertext ) != 0 )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "failed\n" );
+
+        return( 1 );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n  PKCS#1 sig. verify: " );
+
+    if( rsa_pkcs1_verify( &rsa, NULL, NULL, RSA_PUBLIC, POLARSSL_MD_SHA1, 0,
+                          sha1sum, rsa_ciphertext ) != 0 )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "failed\n" );
+
+        return( 1 );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n\n" );
+#endif /* POLARSSL_SHA1_C */
+
+cleanup:
+    rsa_free( &rsa );
+#else /* POLARSSL_PKCS1_V15 */
+    ((void) verbose);
+#endif /* POLARSSL_PKCS1_V15 */
+    return( ret );
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_RSA_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/sha1.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,638 @@
+/*
+ *  FIPS-180-1 compliant SHA-1 implementation
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  The SHA-1 standard was published by NIST in 1993.
+ *
+ *  http://www.itl.nist.gov/fipspubs/fip180-1.htm
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_SHA1_C)
+
+#include "polarssl/sha1.h"
+
+#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
+#include <stdio.h>
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
+#if !defined(POLARSSL_SHA1_ALT)
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i)                            \
+{                                                       \
+    (n) = ( (uint32_t) (b)[(i)    ] << 24 )             \
+        | ( (uint32_t) (b)[(i) + 1] << 16 )             \
+        | ( (uint32_t) (b)[(i) + 2] <<  8 )             \
+        | ( (uint32_t) (b)[(i) + 3]       );            \
+}
+#endif
+
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i)                            \
+{                                                       \
+    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
+    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
+    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
+    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
+}
+#endif
+
+/*
+ * SHA-1 context setup
+ */
+void sha1_starts( sha1_context *ctx )
+{
+    ctx->total[0] = 0;
+    ctx->total[1] = 0;
+
+    ctx->state[0] = 0x67452301;
+    ctx->state[1] = 0xEFCDAB89;
+    ctx->state[2] = 0x98BADCFE;
+    ctx->state[3] = 0x10325476;
+    ctx->state[4] = 0xC3D2E1F0;
+}
+
+void sha1_process( sha1_context *ctx, const unsigned char data[64] )
+{
+    uint32_t temp, W[16], A, B, C, D, E;
+
+    GET_UINT32_BE( W[ 0], data,  0 );
+    GET_UINT32_BE( W[ 1], data,  4 );
+    GET_UINT32_BE( W[ 2], data,  8 );
+    GET_UINT32_BE( W[ 3], data, 12 );
+    GET_UINT32_BE( W[ 4], data, 16 );
+    GET_UINT32_BE( W[ 5], data, 20 );
+    GET_UINT32_BE( W[ 6], data, 24 );
+    GET_UINT32_BE( W[ 7], data, 28 );
+    GET_UINT32_BE( W[ 8], data, 32 );
+    GET_UINT32_BE( W[ 9], data, 36 );
+    GET_UINT32_BE( W[10], data, 40 );
+    GET_UINT32_BE( W[11], data, 44 );
+    GET_UINT32_BE( W[12], data, 48 );
+    GET_UINT32_BE( W[13], data, 52 );
+    GET_UINT32_BE( W[14], data, 56 );
+    GET_UINT32_BE( W[15], data, 60 );
+
+#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
+
+#define R(t)                                            \
+(                                                       \
+    temp = W[(t -  3) & 0x0F] ^ W[(t - 8) & 0x0F] ^     \
+           W[(t - 14) & 0x0F] ^ W[ t      & 0x0F],      \
+    ( W[t & 0x0F] = S(temp,1) )                         \
+)
+
+#define P(a,b,c,d,e,x)                                  \
+{                                                       \
+    e += S(a,5) + F(b,c,d) + K + x; b = S(b,30);        \
+}
+
+    A = ctx->state[0];
+    B = ctx->state[1];
+    C = ctx->state[2];
+    D = ctx->state[3];
+    E = ctx->state[4];
+
+#define F(x,y,z) (z ^ (x & (y ^ z)))
+#define K 0x5A827999
+
+    P( A, B, C, D, E, W[0]  );
+    P( E, A, B, C, D, W[1]  );
+    P( D, E, A, B, C, W[2]  );
+    P( C, D, E, A, B, W[3]  );
+    P( B, C, D, E, A, W[4]  );
+    P( A, B, C, D, E, W[5]  );
+    P( E, A, B, C, D, W[6]  );
+    P( D, E, A, B, C, W[7]  );
+    P( C, D, E, A, B, W[8]  );
+    P( B, C, D, E, A, W[9]  );
+    P( A, B, C, D, E, W[10] );
+    P( E, A, B, C, D, W[11] );
+    P( D, E, A, B, C, W[12] );
+    P( C, D, E, A, B, W[13] );
+    P( B, C, D, E, A, W[14] );
+    P( A, B, C, D, E, W[15] );
+    P( E, A, B, C, D, R(16) );
+    P( D, E, A, B, C, R(17) );
+    P( C, D, E, A, B, R(18) );
+    P( B, C, D, E, A, R(19) );
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0x6ED9EBA1
+
+    P( A, B, C, D, E, R(20) );
+    P( E, A, B, C, D, R(21) );
+    P( D, E, A, B, C, R(22) );
+    P( C, D, E, A, B, R(23) );
+    P( B, C, D, E, A, R(24) );
+    P( A, B, C, D, E, R(25) );
+    P( E, A, B, C, D, R(26) );
+    P( D, E, A, B, C, R(27) );
+    P( C, D, E, A, B, R(28) );
+    P( B, C, D, E, A, R(29) );
+    P( A, B, C, D, E, R(30) );
+    P( E, A, B, C, D, R(31) );
+    P( D, E, A, B, C, R(32) );
+    P( C, D, E, A, B, R(33) );
+    P( B, C, D, E, A, R(34) );
+    P( A, B, C, D, E, R(35) );
+    P( E, A, B, C, D, R(36) );
+    P( D, E, A, B, C, R(37) );
+    P( C, D, E, A, B, R(38) );
+    P( B, C, D, E, A, R(39) );
+
+#undef K
+#undef F
+
+#define F(x,y,z) ((x & y) | (z & (x | y)))
+#define K 0x8F1BBCDC
+
+    P( A, B, C, D, E, R(40) );
+    P( E, A, B, C, D, R(41) );
+    P( D, E, A, B, C, R(42) );
+    P( C, D, E, A, B, R(43) );
+    P( B, C, D, E, A, R(44) );
+    P( A, B, C, D, E, R(45) );
+    P( E, A, B, C, D, R(46) );
+    P( D, E, A, B, C, R(47) );
+    P( C, D, E, A, B, R(48) );
+    P( B, C, D, E, A, R(49) );
+    P( A, B, C, D, E, R(50) );
+    P( E, A, B, C, D, R(51) );
+    P( D, E, A, B, C, R(52) );
+    P( C, D, E, A, B, R(53) );
+    P( B, C, D, E, A, R(54) );
+    P( A, B, C, D, E, R(55) );
+    P( E, A, B, C, D, R(56) );
+    P( D, E, A, B, C, R(57) );
+    P( C, D, E, A, B, R(58) );
+    P( B, C, D, E, A, R(59) );
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0xCA62C1D6
+
+    P( A, B, C, D, E, R(60) );
+    P( E, A, B, C, D, R(61) );
+    P( D, E, A, B, C, R(62) );
+    P( C, D, E, A, B, R(63) );
+    P( B, C, D, E, A, R(64) );
+    P( A, B, C, D, E, R(65) );
+    P( E, A, B, C, D, R(66) );
+    P( D, E, A, B, C, R(67) );
+    P( C, D, E, A, B, R(68) );
+    P( B, C, D, E, A, R(69) );
+    P( A, B, C, D, E, R(70) );
+    P( E, A, B, C, D, R(71) );
+    P( D, E, A, B, C, R(72) );
+    P( C, D, E, A, B, R(73) );
+    P( B, C, D, E, A, R(74) );
+    P( A, B, C, D, E, R(75) );
+    P( E, A, B, C, D, R(76) );
+    P( D, E, A, B, C, R(77) );
+    P( C, D, E, A, B, R(78) );
+    P( B, C, D, E, A, R(79) );
+
+#undef K
+#undef F
+
+    ctx->state[0] += A;
+    ctx->state[1] += B;
+    ctx->state[2] += C;
+    ctx->state[3] += D;
+    ctx->state[4] += E;
+}
+
+/*
+ * SHA-1 process buffer
+ */
+void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen )
+{
+    size_t fill;
+    uint32_t left;
+
+    if( ilen <= 0 )
+        return;
+
+    left = ctx->total[0] & 0x3F;
+    fill = 64 - left;
+
+    ctx->total[0] += (uint32_t) ilen;
+    ctx->total[0] &= 0xFFFFFFFF;
+
+    if( ctx->total[0] < (uint32_t) ilen )
+        ctx->total[1]++;
+
+    if( left && ilen >= fill )
+    {
+        memcpy( (void *) (ctx->buffer + left), input, fill );
+        sha1_process( ctx, ctx->buffer );
+        input += fill;
+        ilen  -= fill;
+        left = 0;
+    }
+
+    while( ilen >= 64 )
+    {
+        sha1_process( ctx, input );
+        input += 64;
+        ilen  -= 64;
+    }
+
+    if( ilen > 0 )
+        memcpy( (void *) (ctx->buffer + left), input, ilen );
+}
+
+static const unsigned char sha1_padding[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * SHA-1 final digest
+ */
+void sha1_finish( sha1_context *ctx, unsigned char output[20] )
+{
+    uint32_t last, padn;
+    uint32_t high, low;
+    unsigned char msglen[8];
+
+    high = ( ctx->total[0] >> 29 )
+         | ( ctx->total[1] <<  3 );
+    low  = ( ctx->total[0] <<  3 );
+
+    PUT_UINT32_BE( high, msglen, 0 );
+    PUT_UINT32_BE( low,  msglen, 4 );
+
+    last = ctx->total[0] & 0x3F;
+    padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+
+    sha1_update( ctx, sha1_padding, padn );
+    sha1_update( ctx, msglen, 8 );
+
+    PUT_UINT32_BE( ctx->state[0], output,  0 );
+    PUT_UINT32_BE( ctx->state[1], output,  4 );
+    PUT_UINT32_BE( ctx->state[2], output,  8 );
+    PUT_UINT32_BE( ctx->state[3], output, 12 );
+    PUT_UINT32_BE( ctx->state[4], output, 16 );
+}
+
+#endif /* !POLARSSL_SHA1_ALT */
+
+/*
+ * output = SHA-1( input buffer )
+ */
+void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] )
+{
+    sha1_context ctx;
+
+    sha1_starts( &ctx );
+    sha1_update( &ctx, input, ilen );
+    sha1_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( sha1_context ) );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * output = SHA-1( file contents )
+ */
+int sha1_file( const char *path, unsigned char output[20] )
+{
+    FILE *f;
+    size_t n;
+    sha1_context ctx;
+    unsigned char buf[1024];
+
+    if( ( f = fopen( path, "rb" ) ) == NULL )
+        return( POLARSSL_ERR_SHA1_FILE_IO_ERROR );
+
+    sha1_starts( &ctx );
+
+    while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+        sha1_update( &ctx, buf, n );
+
+    sha1_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( sha1_context ) );
+
+    if( ferror( f ) != 0 )
+    {
+        fclose( f );
+        return( POLARSSL_ERR_SHA1_FILE_IO_ERROR );
+    }
+
+    fclose( f );
+    return( 0 );
+}
+#endif /* POLARSSL_FS_IO */
+
+/*
+ * SHA-1 HMAC context setup
+ */
+void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key,
+                       size_t keylen )
+{
+    size_t i;
+    unsigned char sum[20];
+
+    if( keylen > 64 )
+    {
+        sha1( key, keylen, sum );
+        keylen = 20;
+        key = sum;
+    }
+
+    memset( ctx->ipad, 0x36, 64 );
+    memset( ctx->opad, 0x5C, 64 );
+
+    for( i = 0; i < keylen; i++ )
+    {
+        ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
+        ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
+    }
+
+    sha1_starts( ctx );
+    sha1_update( ctx, ctx->ipad, 64 );
+
+    memset( sum, 0, sizeof( sum ) );
+}
+
+/*
+ * SHA-1 HMAC process buffer
+ */
+void sha1_hmac_update( sha1_context *ctx, const unsigned char *input,
+                       size_t ilen )
+{
+    sha1_update( ctx, input, ilen );
+}
+
+/*
+ * SHA-1 HMAC final digest
+ */
+void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] )
+{
+    unsigned char tmpbuf[20];
+
+    sha1_finish( ctx, tmpbuf );
+    sha1_starts( ctx );
+    sha1_update( ctx, ctx->opad, 64 );
+    sha1_update( ctx, tmpbuf, 20 );
+    sha1_finish( ctx, output );
+
+    memset( tmpbuf, 0, sizeof( tmpbuf ) );
+}
+
+/*
+ * SHA1 HMAC context reset
+ */
+void sha1_hmac_reset( sha1_context *ctx )
+{
+    sha1_starts( ctx );
+    sha1_update( ctx, ctx->ipad, 64 );
+}
+
+/*
+ * output = HMAC-SHA-1( hmac key, input buffer )
+ */
+void sha1_hmac( const unsigned char *key, size_t keylen,
+                const unsigned char *input, size_t ilen,
+                unsigned char output[20] )
+{
+    sha1_context ctx;
+
+    sha1_hmac_starts( &ctx, key, keylen );
+    sha1_hmac_update( &ctx, input, ilen );
+    sha1_hmac_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( sha1_context ) );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+/*
+ * FIPS-180-1 test vectors
+ */
+static unsigned char sha1_test_buf[3][57] =
+{
+    { "abc" },
+    { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
+    { "" }
+};
+
+static const int sha1_test_buflen[3] =
+{
+    3, 56, 1000
+};
+
+static const unsigned char sha1_test_sum[3][20] =
+{
+    { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E,
+      0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D },
+    { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE,
+      0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 },
+    { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E,
+      0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F }
+};
+
+/*
+ * RFC 2202 test vectors
+ */
+static unsigned char sha1_hmac_test_key[7][26] =
+{
+    { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
+      "\x0B\x0B\x0B\x0B" },
+    { "Jefe" },
+    { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+      "\xAA\xAA\xAA\xAA" },
+    { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
+      "\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
+    { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
+      "\x0C\x0C\x0C\x0C" },
+    { "" }, /* 0xAA 80 times */
+    { "" }
+};
+
+static const int sha1_hmac_test_keylen[7] =
+{
+    20, 4, 20, 25, 20, 80, 80
+};
+
+static unsigned char sha1_hmac_test_buf[7][74] =
+{
+    { "Hi There" },
+    { "what do ya want for nothing?" },
+    { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
+    { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
+    { "Test With Truncation" },
+    { "Test Using Larger Than Block-Size Key - Hash Key First" },
+    { "Test Using Larger Than Block-Size Key and Larger"
+      " Than One Block-Size Data" }
+};
+
+static const int sha1_hmac_test_buflen[7] =
+{
+    8, 28, 50, 50, 20, 54, 73
+};
+
+static const unsigned char sha1_hmac_test_sum[7][20] =
+{
+    { 0xB6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xE2, 0x8B,
+      0xC0, 0xB6, 0xFB, 0x37, 0x8C, 0x8E, 0xF1, 0x46, 0xBE, 0x00 },
+    { 0xEF, 0xFC, 0xDF, 0x6A, 0xE5, 0xEB, 0x2F, 0xA2, 0xD2, 0x74,
+      0x16, 0xD5, 0xF1, 0x84, 0xDF, 0x9C, 0x25, 0x9A, 0x7C, 0x79 },
+    { 0x12, 0x5D, 0x73, 0x42, 0xB9, 0xAC, 0x11, 0xCD, 0x91, 0xA3,
+      0x9A, 0xF4, 0x8A, 0xA1, 0x7B, 0x4F, 0x63, 0xF1, 0x75, 0xD3 },
+    { 0x4C, 0x90, 0x07, 0xF4, 0x02, 0x62, 0x50, 0xC6, 0xBC, 0x84,
+      0x14, 0xF9, 0xBF, 0x50, 0xC8, 0x6C, 0x2D, 0x72, 0x35, 0xDA },
+    { 0x4C, 0x1A, 0x03, 0x42, 0x4B, 0x55, 0xE0, 0x7F, 0xE7, 0xF2,
+      0x7B, 0xE1 },
+    { 0xAA, 0x4A, 0xE5, 0xE1, 0x52, 0x72, 0xD0, 0x0E, 0x95, 0x70,
+      0x56, 0x37, 0xCE, 0x8A, 0x3B, 0x55, 0xED, 0x40, 0x21, 0x12 },
+    { 0xE8, 0xE9, 0x9D, 0x0F, 0x45, 0x23, 0x7D, 0x78, 0x6D, 0x6B,
+      0xBA, 0xA7, 0x96, 0x5C, 0x78, 0x08, 0xBB, 0xFF, 0x1A, 0x91 }
+};
+
+/*
+ * Checkup routine
+ */
+int sha1_self_test( int verbose )
+{
+    int i, j, buflen;
+    unsigned char buf[1024];
+    unsigned char sha1sum[20];
+    sha1_context ctx;
+
+    /*
+     * SHA-1
+     */
+    for( i = 0; i < 3; i++ )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "  SHA-1 test #%d: ", i + 1 );
+
+        sha1_starts( &ctx );
+
+        if( i == 2 )
+        {
+            memset( buf, 'a', buflen = 1000 );
+
+            for( j = 0; j < 1000; j++ )
+                sha1_update( &ctx, buf, buflen );
+        }
+        else
+            sha1_update( &ctx, sha1_test_buf[i],
+                               sha1_test_buflen[i] );
+
+        sha1_finish( &ctx, sha1sum );
+
+        if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+    for( i = 0; i < 7; i++ )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "  HMAC-SHA-1 test #%d: ", i + 1 );
+
+        if( i == 5 || i == 6 )
+        {
+            memset( buf, '\xAA', buflen = 80 );
+            sha1_hmac_starts( &ctx, buf, buflen );
+        }
+        else
+            sha1_hmac_starts( &ctx, sha1_hmac_test_key[i],
+                                    sha1_hmac_test_keylen[i] );
+
+        sha1_hmac_update( &ctx, sha1_hmac_test_buf[i],
+                                sha1_hmac_test_buflen[i] );
+
+        sha1_hmac_finish( &ctx, sha1sum );
+
+        buflen = ( i == 4 ) ? 12 : 20;
+
+        if( memcmp( sha1sum, sha1_hmac_test_sum[i], buflen ) != 0 )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+    return( 0 );
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_SHA1_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/sha256.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,719 @@
+/*
+ *  FIPS-180-2 compliant SHA-256 implementation
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  The SHA-256 Secure Hash Standard was published by NIST in 2002.
+ *
+ *  http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_SHA256_C)
+
+#include "polarssl/sha256.h"
+
+#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
+#include <stdio.h>
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
+#if !defined(POLARSSL_SHA256_ALT)
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i)                            \
+{                                                       \
+    (n) = ( (uint32_t) (b)[(i)    ] << 24 )             \
+        | ( (uint32_t) (b)[(i) + 1] << 16 )             \
+        | ( (uint32_t) (b)[(i) + 2] <<  8 )             \
+        | ( (uint32_t) (b)[(i) + 3]       );            \
+}
+#endif
+
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i)                            \
+{                                                       \
+    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
+    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
+    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
+    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
+}
+#endif
+
+/*
+ * SHA-256 context setup
+ */
+void sha256_starts( sha256_context *ctx, int is224 )
+{
+    ctx->total[0] = 0;
+    ctx->total[1] = 0;
+
+    if( is224 == 0 )
+    {
+        /* SHA-256 */
+        ctx->state[0] = 0x6A09E667;
+        ctx->state[1] = 0xBB67AE85;
+        ctx->state[2] = 0x3C6EF372;
+        ctx->state[3] = 0xA54FF53A;
+        ctx->state[4] = 0x510E527F;
+        ctx->state[5] = 0x9B05688C;
+        ctx->state[6] = 0x1F83D9AB;
+        ctx->state[7] = 0x5BE0CD19;
+    }
+    else
+    {
+        /* SHA-224 */
+        ctx->state[0] = 0xC1059ED8;
+        ctx->state[1] = 0x367CD507;
+        ctx->state[2] = 0x3070DD17;
+        ctx->state[3] = 0xF70E5939;
+        ctx->state[4] = 0xFFC00B31;
+        ctx->state[5] = 0x68581511;
+        ctx->state[6] = 0x64F98FA7;
+        ctx->state[7] = 0xBEFA4FA4;
+    }
+
+    ctx->is224 = is224;
+}
+
+void sha256_process( sha256_context *ctx, const unsigned char data[64] )
+{
+    uint32_t temp1, temp2, W[64];
+    uint32_t A, B, C, D, E, F, G, H;
+
+    GET_UINT32_BE( W[ 0], data,  0 );
+    GET_UINT32_BE( W[ 1], data,  4 );
+    GET_UINT32_BE( W[ 2], data,  8 );
+    GET_UINT32_BE( W[ 3], data, 12 );
+    GET_UINT32_BE( W[ 4], data, 16 );
+    GET_UINT32_BE( W[ 5], data, 20 );
+    GET_UINT32_BE( W[ 6], data, 24 );
+    GET_UINT32_BE( W[ 7], data, 28 );
+    GET_UINT32_BE( W[ 8], data, 32 );
+    GET_UINT32_BE( W[ 9], data, 36 );
+    GET_UINT32_BE( W[10], data, 40 );
+    GET_UINT32_BE( W[11], data, 44 );
+    GET_UINT32_BE( W[12], data, 48 );
+    GET_UINT32_BE( W[13], data, 52 );
+    GET_UINT32_BE( W[14], data, 56 );
+    GET_UINT32_BE( W[15], data, 60 );
+
+#define  SHR(x,n) ((x & 0xFFFFFFFF) >> n)
+#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
+
+#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^  SHR(x, 3))
+#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^  SHR(x,10))
+
+#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
+#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
+
+#define F0(x,y,z) ((x & y) | (z & (x | y)))
+#define F1(x,y,z) (z ^ (x & (y ^ z)))
+
+#define R(t)                                    \
+(                                               \
+    W[t] = S1(W[t -  2]) + W[t -  7] +          \
+           S0(W[t - 15]) + W[t - 16]            \
+)
+
+#define P(a,b,c,d,e,f,g,h,x,K)                  \
+{                                               \
+    temp1 = h + S3(e) + F1(e,f,g) + K + x;      \
+    temp2 = S2(a) + F0(a,b,c);                  \
+    d += temp1; h = temp1 + temp2;              \
+}
+
+    A = ctx->state[0];
+    B = ctx->state[1];
+    C = ctx->state[2];
+    D = ctx->state[3];
+    E = ctx->state[4];
+    F = ctx->state[5];
+    G = ctx->state[6];
+    H = ctx->state[7];
+
+    P( A, B, C, D, E, F, G, H, W[ 0], 0x428A2F98 );
+    P( H, A, B, C, D, E, F, G, W[ 1], 0x71374491 );
+    P( G, H, A, B, C, D, E, F, W[ 2], 0xB5C0FBCF );
+    P( F, G, H, A, B, C, D, E, W[ 3], 0xE9B5DBA5 );
+    P( E, F, G, H, A, B, C, D, W[ 4], 0x3956C25B );
+    P( D, E, F, G, H, A, B, C, W[ 5], 0x59F111F1 );
+    P( C, D, E, F, G, H, A, B, W[ 6], 0x923F82A4 );
+    P( B, C, D, E, F, G, H, A, W[ 7], 0xAB1C5ED5 );
+    P( A, B, C, D, E, F, G, H, W[ 8], 0xD807AA98 );
+    P( H, A, B, C, D, E, F, G, W[ 9], 0x12835B01 );
+    P( G, H, A, B, C, D, E, F, W[10], 0x243185BE );
+    P( F, G, H, A, B, C, D, E, W[11], 0x550C7DC3 );
+    P( E, F, G, H, A, B, C, D, W[12], 0x72BE5D74 );
+    P( D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE );
+    P( C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7 );
+    P( B, C, D, E, F, G, H, A, W[15], 0xC19BF174 );
+    P( A, B, C, D, E, F, G, H, R(16), 0xE49B69C1 );
+    P( H, A, B, C, D, E, F, G, R(17), 0xEFBE4786 );
+    P( G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6 );
+    P( F, G, H, A, B, C, D, E, R(19), 0x240CA1CC );
+    P( E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F );
+    P( D, E, F, G, H, A, B, C, R(21), 0x4A7484AA );
+    P( C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC );
+    P( B, C, D, E, F, G, H, A, R(23), 0x76F988DA );
+    P( A, B, C, D, E, F, G, H, R(24), 0x983E5152 );
+    P( H, A, B, C, D, E, F, G, R(25), 0xA831C66D );
+    P( G, H, A, B, C, D, E, F, R(26), 0xB00327C8 );
+    P( F, G, H, A, B, C, D, E, R(27), 0xBF597FC7 );
+    P( E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3 );
+    P( D, E, F, G, H, A, B, C, R(29), 0xD5A79147 );
+    P( C, D, E, F, G, H, A, B, R(30), 0x06CA6351 );
+    P( B, C, D, E, F, G, H, A, R(31), 0x14292967 );
+    P( A, B, C, D, E, F, G, H, R(32), 0x27B70A85 );
+    P( H, A, B, C, D, E, F, G, R(33), 0x2E1B2138 );
+    P( G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC );
+    P( F, G, H, A, B, C, D, E, R(35), 0x53380D13 );
+    P( E, F, G, H, A, B, C, D, R(36), 0x650A7354 );
+    P( D, E, F, G, H, A, B, C, R(37), 0x766A0ABB );
+    P( C, D, E, F, G, H, A, B, R(38), 0x81C2C92E );
+    P( B, C, D, E, F, G, H, A, R(39), 0x92722C85 );
+    P( A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1 );
+    P( H, A, B, C, D, E, F, G, R(41), 0xA81A664B );
+    P( G, H, A, B, C, D, E, F, R(42), 0xC24B8B70 );
+    P( F, G, H, A, B, C, D, E, R(43), 0xC76C51A3 );
+    P( E, F, G, H, A, B, C, D, R(44), 0xD192E819 );
+    P( D, E, F, G, H, A, B, C, R(45), 0xD6990624 );
+    P( C, D, E, F, G, H, A, B, R(46), 0xF40E3585 );
+    P( B, C, D, E, F, G, H, A, R(47), 0x106AA070 );
+    P( A, B, C, D, E, F, G, H, R(48), 0x19A4C116 );
+    P( H, A, B, C, D, E, F, G, R(49), 0x1E376C08 );
+    P( G, H, A, B, C, D, E, F, R(50), 0x2748774C );
+    P( F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5 );
+    P( E, F, G, H, A, B, C, D, R(52), 0x391C0CB3 );
+    P( D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A );
+    P( C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F );
+    P( B, C, D, E, F, G, H, A, R(55), 0x682E6FF3 );
+    P( A, B, C, D, E, F, G, H, R(56), 0x748F82EE );
+    P( H, A, B, C, D, E, F, G, R(57), 0x78A5636F );
+    P( G, H, A, B, C, D, E, F, R(58), 0x84C87814 );
+    P( F, G, H, A, B, C, D, E, R(59), 0x8CC70208 );
+    P( E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA );
+    P( D, E, F, G, H, A, B, C, R(61), 0xA4506CEB );
+    P( C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7 );
+    P( B, C, D, E, F, G, H, A, R(63), 0xC67178F2 );
+
+    ctx->state[0] += A;
+    ctx->state[1] += B;
+    ctx->state[2] += C;
+    ctx->state[3] += D;
+    ctx->state[4] += E;
+    ctx->state[5] += F;
+    ctx->state[6] += G;
+    ctx->state[7] += H;
+}
+
+/*
+ * SHA-256 process buffer
+ */
+void sha256_update( sha256_context *ctx, const unsigned char *input,
+                    size_t ilen )
+{
+    size_t fill;
+    uint32_t left;
+
+    if( ilen <= 0 )
+        return;
+
+    left = ctx->total[0] & 0x3F;
+    fill = 64 - left;
+
+    ctx->total[0] += (uint32_t) ilen;
+    ctx->total[0] &= 0xFFFFFFFF;
+
+    if( ctx->total[0] < (uint32_t) ilen )
+        ctx->total[1]++;
+
+    if( left && ilen >= fill )
+    {
+        memcpy( (void *) (ctx->buffer + left), input, fill );
+        sha256_process( ctx, ctx->buffer );
+        input += fill;
+        ilen  -= fill;
+        left = 0;
+    }
+
+    while( ilen >= 64 )
+    {
+        sha256_process( ctx, input );
+        input += 64;
+        ilen  -= 64;
+    }
+
+    if( ilen > 0 )
+        memcpy( (void *) (ctx->buffer + left), input, ilen );
+}
+
+static const unsigned char sha256_padding[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * SHA-256 final digest
+ */
+void sha256_finish( sha256_context *ctx, unsigned char output[32] )
+{
+    uint32_t last, padn;
+    uint32_t high, low;
+    unsigned char msglen[8];
+
+    high = ( ctx->total[0] >> 29 )
+         | ( ctx->total[1] <<  3 );
+    low  = ( ctx->total[0] <<  3 );
+
+    PUT_UINT32_BE( high, msglen, 0 );
+    PUT_UINT32_BE( low,  msglen, 4 );
+
+    last = ctx->total[0] & 0x3F;
+    padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+
+    sha256_update( ctx, sha256_padding, padn );
+    sha256_update( ctx, msglen, 8 );
+
+    PUT_UINT32_BE( ctx->state[0], output,  0 );
+    PUT_UINT32_BE( ctx->state[1], output,  4 );
+    PUT_UINT32_BE( ctx->state[2], output,  8 );
+    PUT_UINT32_BE( ctx->state[3], output, 12 );
+    PUT_UINT32_BE( ctx->state[4], output, 16 );
+    PUT_UINT32_BE( ctx->state[5], output, 20 );
+    PUT_UINT32_BE( ctx->state[6], output, 24 );
+
+    if( ctx->is224 == 0 )
+        PUT_UINT32_BE( ctx->state[7], output, 28 );
+}
+
+#endif /* !POLARSSL_SHA256_ALT */
+
+/*
+ * output = SHA-256( input buffer )
+ */
+void sha256( const unsigned char *input, size_t ilen,
+             unsigned char output[32], int is224 )
+{
+    sha256_context ctx;
+
+    sha256_starts( &ctx, is224 );
+    sha256_update( &ctx, input, ilen );
+    sha256_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( sha256_context ) );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * output = SHA-256( file contents )
+ */
+int sha256_file( const char *path, unsigned char output[32], int is224 )
+{
+    FILE *f;
+    size_t n;
+    sha256_context ctx;
+    unsigned char buf[1024];
+
+    if( ( f = fopen( path, "rb" ) ) == NULL )
+        return( POLARSSL_ERR_SHA256_FILE_IO_ERROR );
+
+    sha256_starts( &ctx, is224 );
+
+    while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+        sha256_update( &ctx, buf, n );
+
+    sha256_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( sha256_context ) );
+
+    if( ferror( f ) != 0 )
+    {
+        fclose( f );
+        return( POLARSSL_ERR_SHA256_FILE_IO_ERROR );
+    }
+
+    fclose( f );
+    return( 0 );
+}
+#endif /* POLARSSL_FS_IO */
+
+/*
+ * SHA-256 HMAC context setup
+ */
+void sha256_hmac_starts( sha256_context *ctx, const unsigned char *key,
+                         size_t keylen, int is224 )
+{
+    size_t i;
+    unsigned char sum[32];
+
+    if( keylen > 64 )
+    {
+        sha256( key, keylen, sum, is224 );
+        keylen = ( is224 ) ? 28 : 32;
+        key = sum;
+    }
+
+    memset( ctx->ipad, 0x36, 64 );
+    memset( ctx->opad, 0x5C, 64 );
+
+    for( i = 0; i < keylen; i++ )
+    {
+        ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
+        ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
+    }
+
+    sha256_starts( ctx, is224 );
+    sha256_update( ctx, ctx->ipad, 64 );
+
+    memset( sum, 0, sizeof( sum ) );
+}
+
+/*
+ * SHA-256 HMAC process buffer
+ */
+void sha256_hmac_update( sha256_context *ctx, const unsigned char *input,
+                         size_t ilen )
+{
+    sha256_update( ctx, input, ilen );
+}
+
+/*
+ * SHA-256 HMAC final digest
+ */
+void sha256_hmac_finish( sha256_context *ctx, unsigned char output[32] )
+{
+    int is224, hlen;
+    unsigned char tmpbuf[32];
+
+    is224 = ctx->is224;
+    hlen = ( is224 == 0 ) ? 32 : 28;
+
+    sha256_finish( ctx, tmpbuf );
+    sha256_starts( ctx, is224 );
+    sha256_update( ctx, ctx->opad, 64 );
+    sha256_update( ctx, tmpbuf, hlen );
+    sha256_finish( ctx, output );
+
+    memset( tmpbuf, 0, sizeof( tmpbuf ) );
+}
+
+/*
+ * SHA-256 HMAC context reset
+ */
+void sha256_hmac_reset( sha256_context *ctx )
+{
+    sha256_starts( ctx, ctx->is224 );
+    sha256_update( ctx, ctx->ipad, 64 );
+}
+
+/*
+ * output = HMAC-SHA-256( hmac key, input buffer )
+ */
+void sha256_hmac( const unsigned char *key, size_t keylen,
+                  const unsigned char *input, size_t ilen,
+                  unsigned char output[32], int is224 )
+{
+    sha256_context ctx;
+
+    sha256_hmac_starts( &ctx, key, keylen, is224 );
+    sha256_hmac_update( &ctx, input, ilen );
+    sha256_hmac_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( sha256_context ) );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+/*
+ * FIPS-180-2 test vectors
+ */
+static unsigned char sha256_test_buf[3][57] =
+{
+    { "abc" },
+    { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
+    { "" }
+};
+
+static const int sha256_test_buflen[3] =
+{
+    3, 56, 1000
+};
+
+static const unsigned char sha256_test_sum[6][32] =
+{
+    /*
+     * SHA-224 test vectors
+     */
+    { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22,
+      0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3,
+      0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7,
+      0xE3, 0x6C, 0x9D, 0xA7 },
+    { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC,
+      0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50,
+      0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19,
+      0x52, 0x52, 0x25, 0x25 },
+    { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8,
+      0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B,
+      0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE,
+      0x4E, 0xE7, 0xAD, 0x67 },
+
+    /*
+     * SHA-256 test vectors
+     */
+    { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA,
+      0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23,
+      0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C,
+      0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD },
+    { 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8,
+      0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39,
+      0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67,
+      0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 },
+    { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92,
+      0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67,
+      0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E,
+      0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 }
+};
+
+/*
+ * RFC 4231 test vectors
+ */
+static unsigned char sha256_hmac_test_key[7][26] =
+{
+    { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
+      "\x0B\x0B\x0B\x0B" },
+    { "Jefe" },
+    { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+      "\xAA\xAA\xAA\xAA" },
+    { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
+      "\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
+    { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
+      "\x0C\x0C\x0C\x0C" },
+    { "" }, /* 0xAA 131 times */
+    { "" }
+};
+
+static const int sha256_hmac_test_keylen[7] =
+{
+    20, 4, 20, 25, 20, 131, 131
+};
+
+static unsigned char sha256_hmac_test_buf[7][153] =
+{
+    { "Hi There" },
+    { "what do ya want for nothing?" },
+    { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
+    { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
+    { "Test With Truncation" },
+    { "Test Using Larger Than Block-Size Key - Hash Key First" },
+    { "This is a test using a larger than block-size key "
+      "and a larger than block-size data. The key needs to "
+      "be hashed before being used by the HMAC algorithm." }
+};
+
+static const int sha256_hmac_test_buflen[7] =
+{
+    8, 28, 50, 50, 20, 54, 152
+};
+
+static const unsigned char sha256_hmac_test_sum[14][32] =
+{
+    /*
+     * HMAC-SHA-224 test vectors
+     */
+    { 0x89, 0x6F, 0xB1, 0x12, 0x8A, 0xBB, 0xDF, 0x19,
+      0x68, 0x32, 0x10, 0x7C, 0xD4, 0x9D, 0xF3, 0x3F,
+      0x47, 0xB4, 0xB1, 0x16, 0x99, 0x12, 0xBA, 0x4F,
+      0x53, 0x68, 0x4B, 0x22 },
+    { 0xA3, 0x0E, 0x01, 0x09, 0x8B, 0xC6, 0xDB, 0xBF,
+      0x45, 0x69, 0x0F, 0x3A, 0x7E, 0x9E, 0x6D, 0x0F,
+      0x8B, 0xBE, 0xA2, 0xA3, 0x9E, 0x61, 0x48, 0x00,
+      0x8F, 0xD0, 0x5E, 0x44 },
+    { 0x7F, 0xB3, 0xCB, 0x35, 0x88, 0xC6, 0xC1, 0xF6,
+      0xFF, 0xA9, 0x69, 0x4D, 0x7D, 0x6A, 0xD2, 0x64,
+      0x93, 0x65, 0xB0, 0xC1, 0xF6, 0x5D, 0x69, 0xD1,
+      0xEC, 0x83, 0x33, 0xEA },
+    { 0x6C, 0x11, 0x50, 0x68, 0x74, 0x01, 0x3C, 0xAC,
+      0x6A, 0x2A, 0xBC, 0x1B, 0xB3, 0x82, 0x62, 0x7C,
+      0xEC, 0x6A, 0x90, 0xD8, 0x6E, 0xFC, 0x01, 0x2D,
+      0xE7, 0xAF, 0xEC, 0x5A },
+    { 0x0E, 0x2A, 0xEA, 0x68, 0xA9, 0x0C, 0x8D, 0x37,
+      0xC9, 0x88, 0xBC, 0xDB, 0x9F, 0xCA, 0x6F, 0xA8 },
+    { 0x95, 0xE9, 0xA0, 0xDB, 0x96, 0x20, 0x95, 0xAD,
+      0xAE, 0xBE, 0x9B, 0x2D, 0x6F, 0x0D, 0xBC, 0xE2,
+      0xD4, 0x99, 0xF1, 0x12, 0xF2, 0xD2, 0xB7, 0x27,
+      0x3F, 0xA6, 0x87, 0x0E },
+    { 0x3A, 0x85, 0x41, 0x66, 0xAC, 0x5D, 0x9F, 0x02,
+      0x3F, 0x54, 0xD5, 0x17, 0xD0, 0xB3, 0x9D, 0xBD,
+      0x94, 0x67, 0x70, 0xDB, 0x9C, 0x2B, 0x95, 0xC9,
+      0xF6, 0xF5, 0x65, 0xD1 },
+
+    /*
+     * HMAC-SHA-256 test vectors
+     */
+    { 0xB0, 0x34, 0x4C, 0x61, 0xD8, 0xDB, 0x38, 0x53,
+      0x5C, 0xA8, 0xAF, 0xCE, 0xAF, 0x0B, 0xF1, 0x2B,
+      0x88, 0x1D, 0xC2, 0x00, 0xC9, 0x83, 0x3D, 0xA7,
+      0x26, 0xE9, 0x37, 0x6C, 0x2E, 0x32, 0xCF, 0xF7 },
+    { 0x5B, 0xDC, 0xC1, 0x46, 0xBF, 0x60, 0x75, 0x4E,
+      0x6A, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xC7,
+      0x5A, 0x00, 0x3F, 0x08, 0x9D, 0x27, 0x39, 0x83,
+      0x9D, 0xEC, 0x58, 0xB9, 0x64, 0xEC, 0x38, 0x43 },
+    { 0x77, 0x3E, 0xA9, 0x1E, 0x36, 0x80, 0x0E, 0x46,
+      0x85, 0x4D, 0xB8, 0xEB, 0xD0, 0x91, 0x81, 0xA7,
+      0x29, 0x59, 0x09, 0x8B, 0x3E, 0xF8, 0xC1, 0x22,
+      0xD9, 0x63, 0x55, 0x14, 0xCE, 0xD5, 0x65, 0xFE },
+    { 0x82, 0x55, 0x8A, 0x38, 0x9A, 0x44, 0x3C, 0x0E,
+      0xA4, 0xCC, 0x81, 0x98, 0x99, 0xF2, 0x08, 0x3A,
+      0x85, 0xF0, 0xFA, 0xA3, 0xE5, 0x78, 0xF8, 0x07,
+      0x7A, 0x2E, 0x3F, 0xF4, 0x67, 0x29, 0x66, 0x5B },
+    { 0xA3, 0xB6, 0x16, 0x74, 0x73, 0x10, 0x0E, 0xE0,
+      0x6E, 0x0C, 0x79, 0x6C, 0x29, 0x55, 0x55, 0x2B },
+    { 0x60, 0xE4, 0x31, 0x59, 0x1E, 0xE0, 0xB6, 0x7F,
+      0x0D, 0x8A, 0x26, 0xAA, 0xCB, 0xF5, 0xB7, 0x7F,
+      0x8E, 0x0B, 0xC6, 0x21, 0x37, 0x28, 0xC5, 0x14,
+      0x05, 0x46, 0x04, 0x0F, 0x0E, 0xE3, 0x7F, 0x54 },
+    { 0x9B, 0x09, 0xFF, 0xA7, 0x1B, 0x94, 0x2F, 0xCB,
+      0x27, 0x63, 0x5F, 0xBC, 0xD5, 0xB0, 0xE9, 0x44,
+      0xBF, 0xDC, 0x63, 0x64, 0x4F, 0x07, 0x13, 0x93,
+      0x8A, 0x7F, 0x51, 0x53, 0x5C, 0x3A, 0x35, 0xE2 }
+};
+
+/*
+ * Checkup routine
+ */
+int sha256_self_test( int verbose )
+{
+    int i, j, k, buflen;
+    unsigned char buf[1024];
+    unsigned char sha256sum[32];
+    sha256_context ctx;
+
+    for( i = 0; i < 6; i++ )
+    {
+        j = i % 3;
+        k = i < 3;
+
+        if( verbose != 0 )
+            polarssl_printf( "  SHA-%d test #%d: ", 256 - k * 32, j + 1 );
+
+        sha256_starts( &ctx, k );
+
+        if( j == 2 )
+        {
+            memset( buf, 'a', buflen = 1000 );
+
+            for( j = 0; j < 1000; j++ )
+                sha256_update( &ctx, buf, buflen );
+        }
+        else
+            sha256_update( &ctx, sha256_test_buf[j],
+                                 sha256_test_buflen[j] );
+
+        sha256_finish( &ctx, sha256sum );
+
+        if( memcmp( sha256sum, sha256_test_sum[i], 32 - k * 4 ) != 0 )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+    for( i = 0; i < 14; i++ )
+    {
+        j = i % 7;
+        k = i < 7;
+
+        if( verbose != 0 )
+            polarssl_printf( "  HMAC-SHA-%d test #%d: ", 256 - k * 32, j + 1 );
+
+        if( j == 5 || j == 6 )
+        {
+            memset( buf, '\xAA', buflen = 131 );
+            sha256_hmac_starts( &ctx, buf, buflen, k );
+        }
+        else
+            sha256_hmac_starts( &ctx, sha256_hmac_test_key[j],
+                                      sha256_hmac_test_keylen[j], k );
+
+        sha256_hmac_update( &ctx, sha256_hmac_test_buf[j],
+                                  sha256_hmac_test_buflen[j] );
+
+        sha256_hmac_finish( &ctx, sha256sum );
+
+        buflen = ( j == 4 ) ? 16 : 32 - k * 4;
+
+        if( memcmp( sha256sum, sha256_hmac_test_sum[i], buflen ) != 0 )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+    return( 0 );
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_SHA256_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/sha512.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,773 @@
+/*
+ *  FIPS-180-2 compliant SHA-384/512 implementation
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  The SHA-512 Secure Hash Standard was published by NIST in 2002.
+ *
+ *  http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_SHA512_C)
+
+#include "polarssl/sha512.h"
+
+#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
+#include <stdio.h>
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
+#if !defined(POLARSSL_SHA512_ALT)
+
+/*
+ * 64-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT64_BE
+#define GET_UINT64_BE(n,b,i)                            \
+{                                                       \
+    (n) = ( (uint64_t) (b)[(i)    ] << 56 )       \
+        | ( (uint64_t) (b)[(i) + 1] << 48 )       \
+        | ( (uint64_t) (b)[(i) + 2] << 40 )       \
+        | ( (uint64_t) (b)[(i) + 3] << 32 )       \
+        | ( (uint64_t) (b)[(i) + 4] << 24 )       \
+        | ( (uint64_t) (b)[(i) + 5] << 16 )       \
+        | ( (uint64_t) (b)[(i) + 6] <<  8 )       \
+        | ( (uint64_t) (b)[(i) + 7]       );      \
+}
+#endif /* GET_UINT64_BE */
+
+#ifndef PUT_UINT64_BE
+#define PUT_UINT64_BE(n,b,i)                            \
+{                                                       \
+    (b)[(i)    ] = (unsigned char) ( (n) >> 56 );       \
+    (b)[(i) + 1] = (unsigned char) ( (n) >> 48 );       \
+    (b)[(i) + 2] = (unsigned char) ( (n) >> 40 );       \
+    (b)[(i) + 3] = (unsigned char) ( (n) >> 32 );       \
+    (b)[(i) + 4] = (unsigned char) ( (n) >> 24 );       \
+    (b)[(i) + 5] = (unsigned char) ( (n) >> 16 );       \
+    (b)[(i) + 6] = (unsigned char) ( (n) >>  8 );       \
+    (b)[(i) + 7] = (unsigned char) ( (n)       );       \
+}
+#endif /* PUT_UINT64_BE */
+
+/*
+ * Round constants
+ */
+static const uint64_t K[80] =
+{
+    UL64(0x428A2F98D728AE22),  UL64(0x7137449123EF65CD),
+    UL64(0xB5C0FBCFEC4D3B2F),  UL64(0xE9B5DBA58189DBBC),
+    UL64(0x3956C25BF348B538),  UL64(0x59F111F1B605D019),
+    UL64(0x923F82A4AF194F9B),  UL64(0xAB1C5ED5DA6D8118),
+    UL64(0xD807AA98A3030242),  UL64(0x12835B0145706FBE),
+    UL64(0x243185BE4EE4B28C),  UL64(0x550C7DC3D5FFB4E2),
+    UL64(0x72BE5D74F27B896F),  UL64(0x80DEB1FE3B1696B1),
+    UL64(0x9BDC06A725C71235),  UL64(0xC19BF174CF692694),
+    UL64(0xE49B69C19EF14AD2),  UL64(0xEFBE4786384F25E3),
+    UL64(0x0FC19DC68B8CD5B5),  UL64(0x240CA1CC77AC9C65),
+    UL64(0x2DE92C6F592B0275),  UL64(0x4A7484AA6EA6E483),
+    UL64(0x5CB0A9DCBD41FBD4),  UL64(0x76F988DA831153B5),
+    UL64(0x983E5152EE66DFAB),  UL64(0xA831C66D2DB43210),
+    UL64(0xB00327C898FB213F),  UL64(0xBF597FC7BEEF0EE4),
+    UL64(0xC6E00BF33DA88FC2),  UL64(0xD5A79147930AA725),
+    UL64(0x06CA6351E003826F),  UL64(0x142929670A0E6E70),
+    UL64(0x27B70A8546D22FFC),  UL64(0x2E1B21385C26C926),
+    UL64(0x4D2C6DFC5AC42AED),  UL64(0x53380D139D95B3DF),
+    UL64(0x650A73548BAF63DE),  UL64(0x766A0ABB3C77B2A8),
+    UL64(0x81C2C92E47EDAEE6),  UL64(0x92722C851482353B),
+    UL64(0xA2BFE8A14CF10364),  UL64(0xA81A664BBC423001),
+    UL64(0xC24B8B70D0F89791),  UL64(0xC76C51A30654BE30),
+    UL64(0xD192E819D6EF5218),  UL64(0xD69906245565A910),
+    UL64(0xF40E35855771202A),  UL64(0x106AA07032BBD1B8),
+    UL64(0x19A4C116B8D2D0C8),  UL64(0x1E376C085141AB53),
+    UL64(0x2748774CDF8EEB99),  UL64(0x34B0BCB5E19B48A8),
+    UL64(0x391C0CB3C5C95A63),  UL64(0x4ED8AA4AE3418ACB),
+    UL64(0x5B9CCA4F7763E373),  UL64(0x682E6FF3D6B2B8A3),
+    UL64(0x748F82EE5DEFB2FC),  UL64(0x78A5636F43172F60),
+    UL64(0x84C87814A1F0AB72),  UL64(0x8CC702081A6439EC),
+    UL64(0x90BEFFFA23631E28),  UL64(0xA4506CEBDE82BDE9),
+    UL64(0xBEF9A3F7B2C67915),  UL64(0xC67178F2E372532B),
+    UL64(0xCA273ECEEA26619C),  UL64(0xD186B8C721C0C207),
+    UL64(0xEADA7DD6CDE0EB1E),  UL64(0xF57D4F7FEE6ED178),
+    UL64(0x06F067AA72176FBA),  UL64(0x0A637DC5A2C898A6),
+    UL64(0x113F9804BEF90DAE),  UL64(0x1B710B35131C471B),
+    UL64(0x28DB77F523047D84),  UL64(0x32CAAB7B40C72493),
+    UL64(0x3C9EBE0A15C9BEBC),  UL64(0x431D67C49C100D4C),
+    UL64(0x4CC5D4BECB3E42B6),  UL64(0x597F299CFC657E2A),
+    UL64(0x5FCB6FAB3AD6FAEC),  UL64(0x6C44198C4A475817)
+};
+
+/*
+ * SHA-512 context setup
+ */
+void sha512_starts( sha512_context *ctx, int is384 )
+{
+    ctx->total[0] = 0;
+    ctx->total[1] = 0;
+
+    if( is384 == 0 )
+    {
+        /* SHA-512 */
+        ctx->state[0] = UL64(0x6A09E667F3BCC908);
+        ctx->state[1] = UL64(0xBB67AE8584CAA73B);
+        ctx->state[2] = UL64(0x3C6EF372FE94F82B);
+        ctx->state[3] = UL64(0xA54FF53A5F1D36F1);
+        ctx->state[4] = UL64(0x510E527FADE682D1);
+        ctx->state[5] = UL64(0x9B05688C2B3E6C1F);
+        ctx->state[6] = UL64(0x1F83D9ABFB41BD6B);
+        ctx->state[7] = UL64(0x5BE0CD19137E2179);
+    }
+    else
+    {
+        /* SHA-384 */
+        ctx->state[0] = UL64(0xCBBB9D5DC1059ED8);
+        ctx->state[1] = UL64(0x629A292A367CD507);
+        ctx->state[2] = UL64(0x9159015A3070DD17);
+        ctx->state[3] = UL64(0x152FECD8F70E5939);
+        ctx->state[4] = UL64(0x67332667FFC00B31);
+        ctx->state[5] = UL64(0x8EB44A8768581511);
+        ctx->state[6] = UL64(0xDB0C2E0D64F98FA7);
+        ctx->state[7] = UL64(0x47B5481DBEFA4FA4);
+    }
+
+    ctx->is384 = is384;
+}
+
+void sha512_process( sha512_context *ctx, const unsigned char data[128] )
+{
+    int i;
+    uint64_t temp1, temp2, W[80];
+    uint64_t A, B, C, D, E, F, G, H;
+
+#define  SHR(x,n) (x >> n)
+#define ROTR(x,n) (SHR(x,n) | (x << (64 - n)))
+
+#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^  SHR(x, 7))
+#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^  SHR(x, 6))
+
+#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
+#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
+
+#define F0(x,y,z) ((x & y) | (z & (x | y)))
+#define F1(x,y,z) (z ^ (x & (y ^ z)))
+
+#define P(a,b,c,d,e,f,g,h,x,K)                  \
+{                                               \
+    temp1 = h + S3(e) + F1(e,f,g) + K + x;      \
+    temp2 = S2(a) + F0(a,b,c);                  \
+    d += temp1; h = temp1 + temp2;              \
+}
+
+    for( i = 0; i < 16; i++ )
+    {
+        GET_UINT64_BE( W[i], data, i << 3 );
+    }
+
+    for( ; i < 80; i++ )
+    {
+        W[i] = S1(W[i -  2]) + W[i -  7] +
+               S0(W[i - 15]) + W[i - 16];
+    }
+
+    A = ctx->state[0];
+    B = ctx->state[1];
+    C = ctx->state[2];
+    D = ctx->state[3];
+    E = ctx->state[4];
+    F = ctx->state[5];
+    G = ctx->state[6];
+    H = ctx->state[7];
+    i = 0;
+
+    do
+    {
+        P( A, B, C, D, E, F, G, H, W[i], K[i] ); i++;
+        P( H, A, B, C, D, E, F, G, W[i], K[i] ); i++;
+        P( G, H, A, B, C, D, E, F, W[i], K[i] ); i++;
+        P( F, G, H, A, B, C, D, E, W[i], K[i] ); i++;
+        P( E, F, G, H, A, B, C, D, W[i], K[i] ); i++;
+        P( D, E, F, G, H, A, B, C, W[i], K[i] ); i++;
+        P( C, D, E, F, G, H, A, B, W[i], K[i] ); i++;
+        P( B, C, D, E, F, G, H, A, W[i], K[i] ); i++;
+    }
+    while( i < 80 );
+
+    ctx->state[0] += A;
+    ctx->state[1] += B;
+    ctx->state[2] += C;
+    ctx->state[3] += D;
+    ctx->state[4] += E;
+    ctx->state[5] += F;
+    ctx->state[6] += G;
+    ctx->state[7] += H;
+}
+
+/*
+ * SHA-512 process buffer
+ */
+void sha512_update( sha512_context *ctx, const unsigned char *input,
+                    size_t ilen )
+{
+    size_t fill;
+    unsigned int left;
+
+    if( ilen <= 0 )
+        return;
+
+    left = (unsigned int) (ctx->total[0] & 0x7F);
+    fill = 128 - left;
+
+    ctx->total[0] += (uint64_t) ilen;
+
+    if( ctx->total[0] < (uint64_t) ilen )
+        ctx->total[1]++;
+
+    if( left && ilen >= fill )
+    {
+        memcpy( (void *) (ctx->buffer + left), input, fill );
+        sha512_process( ctx, ctx->buffer );
+        input += fill;
+        ilen  -= fill;
+        left = 0;
+    }
+
+    while( ilen >= 128 )
+    {
+        sha512_process( ctx, input );
+        input += 128;
+        ilen  -= 128;
+    }
+
+    if( ilen > 0 )
+        memcpy( (void *) (ctx->buffer + left), input, ilen );
+}
+
+static const unsigned char sha512_padding[128] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * SHA-512 final digest
+ */
+void sha512_finish( sha512_context *ctx, unsigned char output[64] )
+{
+    size_t last, padn;
+    uint64_t high, low;
+    unsigned char msglen[16];
+
+    high = ( ctx->total[0] >> 61 )
+         | ( ctx->total[1] <<  3 );
+    low  = ( ctx->total[0] <<  3 );
+
+    PUT_UINT64_BE( high, msglen, 0 );
+    PUT_UINT64_BE( low,  msglen, 8 );
+
+    last = (size_t)( ctx->total[0] & 0x7F );
+    padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last );
+
+    sha512_update( ctx, sha512_padding, padn );
+    sha512_update( ctx, msglen, 16 );
+
+    PUT_UINT64_BE( ctx->state[0], output,  0 );
+    PUT_UINT64_BE( ctx->state[1], output,  8 );
+    PUT_UINT64_BE( ctx->state[2], output, 16 );
+    PUT_UINT64_BE( ctx->state[3], output, 24 );
+    PUT_UINT64_BE( ctx->state[4], output, 32 );
+    PUT_UINT64_BE( ctx->state[5], output, 40 );
+
+    if( ctx->is384 == 0 )
+    {
+        PUT_UINT64_BE( ctx->state[6], output, 48 );
+        PUT_UINT64_BE( ctx->state[7], output, 56 );
+    }
+}
+
+#endif /* !POLARSSL_SHA512_ALT */
+
+/*
+ * output = SHA-512( input buffer )
+ */
+void sha512( const unsigned char *input, size_t ilen,
+             unsigned char output[64], int is384 )
+{
+    sha512_context ctx;
+
+    sha512_starts( &ctx, is384 );
+    sha512_update( &ctx, input, ilen );
+    sha512_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( sha512_context ) );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * output = SHA-512( file contents )
+ */
+int sha512_file( const char *path, unsigned char output[64], int is384 )
+{
+    FILE *f;
+    size_t n;
+    sha512_context ctx;
+    unsigned char buf[1024];
+
+    if( ( f = fopen( path, "rb" ) ) == NULL )
+        return( POLARSSL_ERR_SHA512_FILE_IO_ERROR );
+
+    sha512_starts( &ctx, is384 );
+
+    while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+        sha512_update( &ctx, buf, n );
+
+    sha512_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( sha512_context ) );
+
+    if( ferror( f ) != 0 )
+    {
+        fclose( f );
+        return( POLARSSL_ERR_SHA512_FILE_IO_ERROR );
+    }
+
+    fclose( f );
+    return( 0 );
+}
+#endif /* POLARSSL_FS_IO */
+
+/*
+ * SHA-512 HMAC context setup
+ */
+void sha512_hmac_starts( sha512_context *ctx, const unsigned char *key,
+                         size_t keylen, int is384 )
+{
+    size_t i;
+    unsigned char sum[64];
+
+    if( keylen > 128 )
+    {
+        sha512( key, keylen, sum, is384 );
+        keylen = ( is384 ) ? 48 : 64;
+        key = sum;
+    }
+
+    memset( ctx->ipad, 0x36, 128 );
+    memset( ctx->opad, 0x5C, 128 );
+
+    for( i = 0; i < keylen; i++ )
+    {
+        ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
+        ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
+    }
+
+    sha512_starts( ctx, is384 );
+    sha512_update( ctx, ctx->ipad, 128 );
+
+    memset( sum, 0, sizeof( sum ) );
+}
+
+/*
+ * SHA-512 HMAC process buffer
+ */
+void sha512_hmac_update( sha512_context  *ctx,
+                         const unsigned char *input, size_t ilen )
+{
+    sha512_update( ctx, input, ilen );
+}
+
+/*
+ * SHA-512 HMAC final digest
+ */
+void sha512_hmac_finish( sha512_context *ctx, unsigned char output[64] )
+{
+    int is384, hlen;
+    unsigned char tmpbuf[64];
+
+    is384 = ctx->is384;
+    hlen = ( is384 == 0 ) ? 64 : 48;
+
+    sha512_finish( ctx, tmpbuf );
+    sha512_starts( ctx, is384 );
+    sha512_update( ctx, ctx->opad, 128 );
+    sha512_update( ctx, tmpbuf, hlen );
+    sha512_finish( ctx, output );
+
+    memset( tmpbuf, 0, sizeof( tmpbuf ) );
+}
+
+/*
+ * SHA-512 HMAC context reset
+ */
+void sha512_hmac_reset( sha512_context *ctx )
+{
+    sha512_starts( ctx, ctx->is384 );
+    sha512_update( ctx, ctx->ipad, 128 );
+}
+
+/*
+ * output = HMAC-SHA-512( hmac key, input buffer )
+ */
+void sha512_hmac( const unsigned char *key, size_t keylen,
+                const unsigned char *input, size_t ilen,
+                unsigned char output[64], int is384 )
+{
+    sha512_context ctx;
+
+    sha512_hmac_starts( &ctx, key, keylen, is384 );
+    sha512_hmac_update( &ctx, input, ilen );
+    sha512_hmac_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( sha512_context ) );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+/*
+ * FIPS-180-2 test vectors
+ */
+static unsigned char sha512_test_buf[3][113] =
+{
+    { "abc" },
+    { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
+      "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" },
+    { "" }
+};
+
+static const int sha512_test_buflen[3] =
+{
+    3, 112, 1000
+};
+
+static const unsigned char sha512_test_sum[6][64] =
+{
+    /*
+     * SHA-384 test vectors
+     */
+    { 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B,
+      0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07,
+      0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63,
+      0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, 0x5B, 0xED,
+      0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23,
+      0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7 },
+    { 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8,
+      0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47,
+      0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2,
+      0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, 0xF7, 0x12,
+      0xFC, 0xC7, 0xC7, 0x1A, 0x55, 0x7E, 0x2D, 0xB9,
+      0x66, 0xC3, 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39 },
+    { 0x9D, 0x0E, 0x18, 0x09, 0x71, 0x64, 0x74, 0xCB,
+      0x08, 0x6E, 0x83, 0x4E, 0x31, 0x0A, 0x4A, 0x1C,
+      0xED, 0x14, 0x9E, 0x9C, 0x00, 0xF2, 0x48, 0x52,
+      0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B,
+      0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB,
+      0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 },
+
+    /*
+     * SHA-512 test vectors
+     */
+    { 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA,
+      0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31,
+      0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2,
+      0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A,
+      0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8,
+      0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD,
+      0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E,
+      0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F },
+    { 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA,
+      0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F,
+      0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1,
+      0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18,
+      0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4,
+      0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A,
+      0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54,
+      0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09 },
+    { 0xE7, 0x18, 0x48, 0x3D, 0x0C, 0xE7, 0x69, 0x64,
+      0x4E, 0x2E, 0x42, 0xC7, 0xBC, 0x15, 0xB4, 0x63,
+      0x8E, 0x1F, 0x98, 0xB1, 0x3B, 0x20, 0x44, 0x28,
+      0x56, 0x32, 0xA8, 0x03, 0xAF, 0xA9, 0x73, 0xEB,
+      0xDE, 0x0F, 0xF2, 0x44, 0x87, 0x7E, 0xA6, 0x0A,
+      0x4C, 0xB0, 0x43, 0x2C, 0xE5, 0x77, 0xC3, 0x1B,
+      0xEB, 0x00, 0x9C, 0x5C, 0x2C, 0x49, 0xAA, 0x2E,
+      0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B }
+};
+
+/*
+ * RFC 4231 test vectors
+ */
+static unsigned char sha512_hmac_test_key[7][26] =
+{
+    { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
+      "\x0B\x0B\x0B\x0B" },
+    { "Jefe" },
+    { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+      "\xAA\xAA\xAA\xAA" },
+    { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
+      "\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
+    { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
+      "\x0C\x0C\x0C\x0C" },
+    { "" }, /* 0xAA 131 times */
+    { "" }
+};
+
+static const int sha512_hmac_test_keylen[7] =
+{
+    20, 4, 20, 25, 20, 131, 131
+};
+
+static unsigned char sha512_hmac_test_buf[7][153] =
+{
+    { "Hi There" },
+    { "what do ya want for nothing?" },
+    { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
+    { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
+    { "Test With Truncation" },
+    { "Test Using Larger Than Block-Size Key - Hash Key First" },
+    { "This is a test using a larger than block-size key "
+      "and a larger than block-size data. The key needs to "
+      "be hashed before being used by the HMAC algorithm." }
+};
+
+static const int sha512_hmac_test_buflen[7] =
+{
+    8, 28, 50, 50, 20, 54, 152
+};
+
+static const unsigned char sha512_hmac_test_sum[14][64] =
+{
+    /*
+     * HMAC-SHA-384 test vectors
+     */
+    { 0xAF, 0xD0, 0x39, 0x44, 0xD8, 0x48, 0x95, 0x62,
+      0x6B, 0x08, 0x25, 0xF4, 0xAB, 0x46, 0x90, 0x7F,
+      0x15, 0xF9, 0xDA, 0xDB, 0xE4, 0x10, 0x1E, 0xC6,
+      0x82, 0xAA, 0x03, 0x4C, 0x7C, 0xEB, 0xC5, 0x9C,
+      0xFA, 0xEA, 0x9E, 0xA9, 0x07, 0x6E, 0xDE, 0x7F,
+      0x4A, 0xF1, 0x52, 0xE8, 0xB2, 0xFA, 0x9C, 0xB6 },
+    { 0xAF, 0x45, 0xD2, 0xE3, 0x76, 0x48, 0x40, 0x31,
+      0x61, 0x7F, 0x78, 0xD2, 0xB5, 0x8A, 0x6B, 0x1B,
+      0x9C, 0x7E, 0xF4, 0x64, 0xF5, 0xA0, 0x1B, 0x47,
+      0xE4, 0x2E, 0xC3, 0x73, 0x63, 0x22, 0x44, 0x5E,
+      0x8E, 0x22, 0x40, 0xCA, 0x5E, 0x69, 0xE2, 0xC7,
+      0x8B, 0x32, 0x39, 0xEC, 0xFA, 0xB2, 0x16, 0x49 },
+    { 0x88, 0x06, 0x26, 0x08, 0xD3, 0xE6, 0xAD, 0x8A,
+      0x0A, 0xA2, 0xAC, 0xE0, 0x14, 0xC8, 0xA8, 0x6F,
+      0x0A, 0xA6, 0x35, 0xD9, 0x47, 0xAC, 0x9F, 0xEB,
+      0xE8, 0x3E, 0xF4, 0xE5, 0x59, 0x66, 0x14, 0x4B,
+      0x2A, 0x5A, 0xB3, 0x9D, 0xC1, 0x38, 0x14, 0xB9,
+      0x4E, 0x3A, 0xB6, 0xE1, 0x01, 0xA3, 0x4F, 0x27 },
+    { 0x3E, 0x8A, 0x69, 0xB7, 0x78, 0x3C, 0x25, 0x85,
+      0x19, 0x33, 0xAB, 0x62, 0x90, 0xAF, 0x6C, 0xA7,
+      0x7A, 0x99, 0x81, 0x48, 0x08, 0x50, 0x00, 0x9C,
+      0xC5, 0x57, 0x7C, 0x6E, 0x1F, 0x57, 0x3B, 0x4E,
+      0x68, 0x01, 0xDD, 0x23, 0xC4, 0xA7, 0xD6, 0x79,
+      0xCC, 0xF8, 0xA3, 0x86, 0xC6, 0x74, 0xCF, 0xFB },
+    { 0x3A, 0xBF, 0x34, 0xC3, 0x50, 0x3B, 0x2A, 0x23,
+      0xA4, 0x6E, 0xFC, 0x61, 0x9B, 0xAE, 0xF8, 0x97 },
+    { 0x4E, 0xCE, 0x08, 0x44, 0x85, 0x81, 0x3E, 0x90,
+      0x88, 0xD2, 0xC6, 0x3A, 0x04, 0x1B, 0xC5, 0xB4,
+      0x4F, 0x9E, 0xF1, 0x01, 0x2A, 0x2B, 0x58, 0x8F,
+      0x3C, 0xD1, 0x1F, 0x05, 0x03, 0x3A, 0xC4, 0xC6,
+      0x0C, 0x2E, 0xF6, 0xAB, 0x40, 0x30, 0xFE, 0x82,
+      0x96, 0x24, 0x8D, 0xF1, 0x63, 0xF4, 0x49, 0x52 },
+    { 0x66, 0x17, 0x17, 0x8E, 0x94, 0x1F, 0x02, 0x0D,
+      0x35, 0x1E, 0x2F, 0x25, 0x4E, 0x8F, 0xD3, 0x2C,
+      0x60, 0x24, 0x20, 0xFE, 0xB0, 0xB8, 0xFB, 0x9A,
+      0xDC, 0xCE, 0xBB, 0x82, 0x46, 0x1E, 0x99, 0xC5,
+      0xA6, 0x78, 0xCC, 0x31, 0xE7, 0x99, 0x17, 0x6D,
+      0x38, 0x60, 0xE6, 0x11, 0x0C, 0x46, 0x52, 0x3E },
+
+    /*
+     * HMAC-SHA-512 test vectors
+     */
+    { 0x87, 0xAA, 0x7C, 0xDE, 0xA5, 0xEF, 0x61, 0x9D,
+      0x4F, 0xF0, 0xB4, 0x24, 0x1A, 0x1D, 0x6C, 0xB0,
+      0x23, 0x79, 0xF4, 0xE2, 0xCE, 0x4E, 0xC2, 0x78,
+      0x7A, 0xD0, 0xB3, 0x05, 0x45, 0xE1, 0x7C, 0xDE,
+      0xDA, 0xA8, 0x33, 0xB7, 0xD6, 0xB8, 0xA7, 0x02,
+      0x03, 0x8B, 0x27, 0x4E, 0xAE, 0xA3, 0xF4, 0xE4,
+      0xBE, 0x9D, 0x91, 0x4E, 0xEB, 0x61, 0xF1, 0x70,
+      0x2E, 0x69, 0x6C, 0x20, 0x3A, 0x12, 0x68, 0x54 },
+    { 0x16, 0x4B, 0x7A, 0x7B, 0xFC, 0xF8, 0x19, 0xE2,
+      0xE3, 0x95, 0xFB, 0xE7, 0x3B, 0x56, 0xE0, 0xA3,
+      0x87, 0xBD, 0x64, 0x22, 0x2E, 0x83, 0x1F, 0xD6,
+      0x10, 0x27, 0x0C, 0xD7, 0xEA, 0x25, 0x05, 0x54,
+      0x97, 0x58, 0xBF, 0x75, 0xC0, 0x5A, 0x99, 0x4A,
+      0x6D, 0x03, 0x4F, 0x65, 0xF8, 0xF0, 0xE6, 0xFD,
+      0xCA, 0xEA, 0xB1, 0xA3, 0x4D, 0x4A, 0x6B, 0x4B,
+      0x63, 0x6E, 0x07, 0x0A, 0x38, 0xBC, 0xE7, 0x37 },
+    { 0xFA, 0x73, 0xB0, 0x08, 0x9D, 0x56, 0xA2, 0x84,
+      0xEF, 0xB0, 0xF0, 0x75, 0x6C, 0x89, 0x0B, 0xE9,
+      0xB1, 0xB5, 0xDB, 0xDD, 0x8E, 0xE8, 0x1A, 0x36,
+      0x55, 0xF8, 0x3E, 0x33, 0xB2, 0x27, 0x9D, 0x39,
+      0xBF, 0x3E, 0x84, 0x82, 0x79, 0xA7, 0x22, 0xC8,
+      0x06, 0xB4, 0x85, 0xA4, 0x7E, 0x67, 0xC8, 0x07,
+      0xB9, 0x46, 0xA3, 0x37, 0xBE, 0xE8, 0x94, 0x26,
+      0x74, 0x27, 0x88, 0x59, 0xE1, 0x32, 0x92, 0xFB },
+    { 0xB0, 0xBA, 0x46, 0x56, 0x37, 0x45, 0x8C, 0x69,
+      0x90, 0xE5, 0xA8, 0xC5, 0xF6, 0x1D, 0x4A, 0xF7,
+      0xE5, 0x76, 0xD9, 0x7F, 0xF9, 0x4B, 0x87, 0x2D,
+      0xE7, 0x6F, 0x80, 0x50, 0x36, 0x1E, 0xE3, 0xDB,
+      0xA9, 0x1C, 0xA5, 0xC1, 0x1A, 0xA2, 0x5E, 0xB4,
+      0xD6, 0x79, 0x27, 0x5C, 0xC5, 0x78, 0x80, 0x63,
+      0xA5, 0xF1, 0x97, 0x41, 0x12, 0x0C, 0x4F, 0x2D,
+      0xE2, 0xAD, 0xEB, 0xEB, 0x10, 0xA2, 0x98, 0xDD },
+    { 0x41, 0x5F, 0xAD, 0x62, 0x71, 0x58, 0x0A, 0x53,
+      0x1D, 0x41, 0x79, 0xBC, 0x89, 0x1D, 0x87, 0xA6 },
+    { 0x80, 0xB2, 0x42, 0x63, 0xC7, 0xC1, 0xA3, 0xEB,
+      0xB7, 0x14, 0x93, 0xC1, 0xDD, 0x7B, 0xE8, 0xB4,
+      0x9B, 0x46, 0xD1, 0xF4, 0x1B, 0x4A, 0xEE, 0xC1,
+      0x12, 0x1B, 0x01, 0x37, 0x83, 0xF8, 0xF3, 0x52,
+      0x6B, 0x56, 0xD0, 0x37, 0xE0, 0x5F, 0x25, 0x98,
+      0xBD, 0x0F, 0xD2, 0x21, 0x5D, 0x6A, 0x1E, 0x52,
+      0x95, 0xE6, 0x4F, 0x73, 0xF6, 0x3F, 0x0A, 0xEC,
+      0x8B, 0x91, 0x5A, 0x98, 0x5D, 0x78, 0x65, 0x98 },
+    { 0xE3, 0x7B, 0x6A, 0x77, 0x5D, 0xC8, 0x7D, 0xBA,
+      0xA4, 0xDF, 0xA9, 0xF9, 0x6E, 0x5E, 0x3F, 0xFD,
+      0xDE, 0xBD, 0x71, 0xF8, 0x86, 0x72, 0x89, 0x86,
+      0x5D, 0xF5, 0xA3, 0x2D, 0x20, 0xCD, 0xC9, 0x44,
+      0xB6, 0x02, 0x2C, 0xAC, 0x3C, 0x49, 0x82, 0xB1,
+      0x0D, 0x5E, 0xEB, 0x55, 0xC3, 0xE4, 0xDE, 0x15,
+      0x13, 0x46, 0x76, 0xFB, 0x6D, 0xE0, 0x44, 0x60,
+      0x65, 0xC9, 0x74, 0x40, 0xFA, 0x8C, 0x6A, 0x58 }
+};
+
+/*
+ * Checkup routine
+ */
+int sha512_self_test( int verbose )
+{
+    int i, j, k, buflen;
+    unsigned char buf[1024];
+    unsigned char sha512sum[64];
+    sha512_context ctx;
+
+    for( i = 0; i < 6; i++ )
+    {
+        j = i % 3;
+        k = i < 3;
+
+        if( verbose != 0 )
+            polarssl_printf( "  SHA-%d test #%d: ", 512 - k * 128, j + 1 );
+
+        sha512_starts( &ctx, k );
+
+        if( j == 2 )
+        {
+            memset( buf, 'a', buflen = 1000 );
+
+            for( j = 0; j < 1000; j++ )
+                sha512_update( &ctx, buf, buflen );
+        }
+        else
+            sha512_update( &ctx, sha512_test_buf[j],
+                                 sha512_test_buflen[j] );
+
+        sha512_finish( &ctx, sha512sum );
+
+        if( memcmp( sha512sum, sha512_test_sum[i], 64 - k * 16 ) != 0 )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+    for( i = 0; i < 14; i++ )
+    {
+        j = i % 7;
+        k = i < 7;
+
+        if( verbose != 0 )
+            polarssl_printf( "  HMAC-SHA-%d test #%d: ", 512 - k * 128, j + 1 );
+
+        if( j == 5 || j == 6 )
+        {
+            memset( buf, '\xAA', buflen = 131 );
+            sha512_hmac_starts( &ctx, buf, buflen, k );
+        }
+        else
+            sha512_hmac_starts( &ctx, sha512_hmac_test_key[j],
+                                      sha512_hmac_test_keylen[j], k );
+
+        sha512_hmac_update( &ctx, sha512_hmac_test_buf[j],
+                                  sha512_hmac_test_buflen[j] );
+
+        sha512_hmac_finish( &ctx, sha512sum );
+
+        buflen = ( j == 4 ) ? 16 : 64 - k * 16;
+
+        if( memcmp( sha512sum, sha512_hmac_test_sum[i], buflen ) != 0 )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+    return( 0 );
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_SHA512_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/ssl_cache.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,338 @@
+/*
+ *  SSL session cache implementation
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * These session callbacks use a simple chained list
+ * to store and retrieve the session information.
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_SSL_CACHE_C)
+
+#include "polarssl/ssl_cache.h"
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+#include <stdlib.h>
+
+void ssl_cache_init( ssl_cache_context *cache )
+{
+    memset( cache, 0, sizeof( ssl_cache_context ) );
+
+    cache->timeout = SSL_CACHE_DEFAULT_TIMEOUT;
+    cache->max_entries = SSL_CACHE_DEFAULT_MAX_ENTRIES;
+
+#if defined(POLARSSL_THREADING_C)
+    polarssl_mutex_init( &cache->mutex );
+#endif
+}
+
+int ssl_cache_get( void *data, ssl_session *session )
+{
+    int ret = 1;
+#if defined(POLARSSL_HAVE_TIME)
+    time_t t = time( NULL );
+#endif
+    ssl_cache_context *cache = (ssl_cache_context *) data;
+    ssl_cache_entry *cur, *entry;
+
+#if defined(POLARSSL_THREADING_C)
+    if( polarssl_mutex_lock( &cache->mutex ) != 0 )
+        return( 1 );
+#endif
+
+    cur = cache->chain;
+    entry = NULL;
+
+    while( cur != NULL )
+    {
+        entry = cur;
+        cur = cur->next;
+
+#if defined(POLARSSL_HAVE_TIME)
+        if( cache->timeout != 0 &&
+            (int) ( t - entry->timestamp ) > cache->timeout )
+            continue;
+#endif
+
+        if( session->ciphersuite != entry->session.ciphersuite ||
+            session->compression != entry->session.compression ||
+            session->length != entry->session.length )
+            continue;
+
+        if( memcmp( session->id, entry->session.id,
+                    entry->session.length ) != 0 )
+            continue;
+
+        memcpy( session->master, entry->session.master, 48 );
+
+        session->verify_result = entry->session.verify_result;
+
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+        /*
+         * Restore peer certificate (without rest of the original chain)
+         */
+        if( entry->peer_cert.p != NULL )
+        {
+            session->peer_cert =
+                (x509_crt *) polarssl_malloc( sizeof(x509_crt) );
+
+            if( session->peer_cert == NULL )
+            {
+                ret = 1;
+                goto exit;
+            }
+
+            x509_crt_init( session->peer_cert );
+            if( x509_crt_parse( session->peer_cert, entry->peer_cert.p,
+                                entry->peer_cert.len ) != 0 )
+            {
+                polarssl_free( session->peer_cert );
+                session->peer_cert = NULL;
+                ret = 1;
+                goto exit;
+            }
+        }
+#endif /* POLARSSL_X509_CRT_PARSE_C */
+
+        ret = 0;
+        goto exit;
+    }
+
+exit:
+#if defined(POLARSSL_THREADING_C)
+    if( polarssl_mutex_unlock( &cache->mutex ) != 0 )
+        ret = 1;
+#endif
+
+    return( ret );
+}
+
+int ssl_cache_set( void *data, const ssl_session *session )
+{
+    int ret = 1;
+#if defined(POLARSSL_HAVE_TIME)
+    time_t t = time( NULL ), oldest = 0;
+    ssl_cache_entry *old = NULL;
+#endif
+    ssl_cache_context *cache = (ssl_cache_context *) data;
+    ssl_cache_entry *cur, *prv;
+    int count = 0;
+
+#if defined(POLARSSL_THREADING_C)
+    if( ( ret = polarssl_mutex_lock( &cache->mutex ) ) != 0 )
+        return( ret );
+#endif
+
+    cur = cache->chain;
+    prv = NULL;
+
+    while( cur != NULL )
+    {
+        count++;
+
+#if defined(POLARSSL_HAVE_TIME)
+        if( cache->timeout != 0 &&
+            (int) ( t - cur->timestamp ) > cache->timeout )
+        {
+            cur->timestamp = t;
+            break; /* expired, reuse this slot, update timestamp */
+        }
+#endif
+
+        if( memcmp( session->id, cur->session.id, cur->session.length ) == 0 )
+            break; /* client reconnected, keep timestamp for session id */
+
+#if defined(POLARSSL_HAVE_TIME)
+        if( oldest == 0 || cur->timestamp < oldest )
+        {
+            oldest = cur->timestamp;
+            old = cur;
+        }
+#endif
+
+        prv = cur;
+        cur = cur->next;
+    }
+
+    if( cur == NULL )
+    {
+#if defined(POLARSSL_HAVE_TIME)
+        /*
+         * Reuse oldest entry if max_entries reached
+         */
+        if( count >= cache->max_entries )
+        {
+            if( old == NULL )
+            {
+                ret = 1;
+                goto exit;
+            }
+
+            cur = old;
+        }
+#else /* POLARSSL_HAVE_TIME */
+        /*
+         * Reuse first entry in chain if max_entries reached,
+         * but move to last place
+         */
+        if( count >= cache->max_entries )
+        {
+            if( cache->chain == NULL )
+            {
+                ret = 1;
+                goto exit;
+            }
+
+            cur = cache->chain;
+            cache->chain = cur->next;
+            cur->next = NULL;
+            prv->next = cur;
+        }
+#endif /* POLARSSL_HAVE_TIME */
+        else
+        {
+            /*
+             * max_entries not reached, create new entry
+             */
+            cur = (ssl_cache_entry *)
+                        polarssl_malloc( sizeof(ssl_cache_entry) );
+            if( cur == NULL )
+            {
+                ret = 1;
+                goto exit;
+            }
+
+            memset( cur, 0, sizeof(ssl_cache_entry) );
+
+            if( prv == NULL )
+                cache->chain = cur;
+            else
+                prv->next = cur;
+        }
+
+#if defined(POLARSSL_HAVE_TIME)
+        cur->timestamp = t;
+#endif
+    }
+
+    memcpy( &cur->session, session, sizeof( ssl_session ) );
+
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+    /*
+     * If we're reusing an entry, free its certificate first
+     */
+    if( cur->peer_cert.p != NULL )
+    {
+        polarssl_free( cur->peer_cert.p );
+        memset( &cur->peer_cert, 0, sizeof(x509_buf) );
+    }
+
+    /*
+     * Store peer certificate
+     */
+    if( session->peer_cert != NULL )
+    {
+        cur->peer_cert.p = (unsigned char *)
+                                polarssl_malloc( session->peer_cert->raw.len );
+        if( cur->peer_cert.p == NULL )
+        {
+            ret = 1;
+            goto exit;
+        }
+
+        memcpy( cur->peer_cert.p, session->peer_cert->raw.p,
+                session->peer_cert->raw.len );
+        cur->peer_cert.len = session->peer_cert->raw.len;
+
+        cur->session.peer_cert = NULL;
+    }
+#endif /* POLARSSL_X509_CRT_PARSE_C */
+
+    ret = 0;
+
+exit:
+#if defined(POLARSSL_THREADING_C)
+    if( polarssl_mutex_unlock( &cache->mutex ) != 0 )
+        ret = 1;
+#endif
+
+    return( ret );
+}
+
+#if defined(POLARSSL_HAVE_TIME)
+void ssl_cache_set_timeout( ssl_cache_context *cache, int timeout )
+{
+    if( timeout < 0 ) timeout = 0;
+
+    cache->timeout = timeout;
+}
+#endif /* POLARSSL_HAVE_TIME */
+
+void ssl_cache_set_max_entries( ssl_cache_context *cache, int max )
+{
+    if( max < 0 ) max = 0;
+
+    cache->max_entries = max;
+}
+
+void ssl_cache_free( ssl_cache_context *cache )
+{
+    ssl_cache_entry *cur, *prv;
+
+    cur = cache->chain;
+
+    while( cur != NULL )
+    {
+        prv = cur;
+        cur = cur->next;
+
+        ssl_session_free( &prv->session );
+
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+        if( prv->peer_cert.p != NULL )
+            polarssl_free( prv->peer_cert.p );
+#endif /* POLARSSL_X509_CRT_PARSE_C */
+
+        polarssl_free( prv );
+    }
+
+#if defined(POLARSSL_THREADING_C)
+    polarssl_mutex_free( &cache->mutex );
+#endif
+}
+
+#endif /* POLARSSL_SSL_CACHE_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/ssl_ciphersuites.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,1697 @@
+/**
+ * \file ssl_ciphersuites.c
+ *
+ * \brief SSL ciphersuites for PolarSSL
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_SSL_TLS_C)
+
+#include "polarssl/ssl_ciphersuites.h"
+#include "polarssl/ssl.h"
+
+#include <stdlib.h>
+
+#if defined(_MSC_VER) && !defined strcasecmp && !defined(EFIX64) && \
+    !defined(EFI32)
+#define strcasecmp _stricmp
+#endif
+
+/*
+ * Ordered from most preferred to least preferred in terms of security.
+ *
+ * Current rule (except rc4, weak and null which come last):
+ * 1. By key exchange:
+ *    Forward-secure non-PSK > forward-secure PSK > other non-PSK > other PSK
+ * 2. By key length and cipher:
+ *    AES-256 > Camellia-256 > AES-128 > Camellia-128 > 3DES
+ * 3. By cipher mode when relevant GCM > CBC
+ * 4. By hash function used
+ * 5. By key exchange/auth again: EC > non-EC
+ */
+static const int ciphersuite_preference[] =
+{
+    /* All AES-256 ephemeral suites */
+    TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+    TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+    TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
+    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
+    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
+    TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
+    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+    TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
+
+    /* All CAMELLIA-256 ephemeral suites */
+    TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,
+    TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384,
+    TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384,
+    TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
+    TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384,
+    TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
+    TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
+
+    /* All AES-128 ephemeral suites */
+    TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+    TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+    TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
+    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
+    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
+    TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
+    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+    TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
+
+    /* All CAMELLIA-128 ephemeral suites */
+    TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,
+    TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256,
+    TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256,
+    TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
+    TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+    TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+    TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
+
+    /* All remaining >= 128-bit ephemeral suites */
+    TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
+    TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
+    TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
+
+    /* The PSK ephemeral suites */
+    TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,
+    TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
+    TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,
+    TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA,
+    TLS_DHE_PSK_WITH_AES_256_CBC_SHA,
+    TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384,
+    TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+    TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+
+    TLS_DHE_PSK_WITH_AES_128_GCM_SHA256,
+    TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
+    TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,
+    TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
+    TLS_DHE_PSK_WITH_AES_128_CBC_SHA,
+    TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256,
+    TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+    TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+
+    TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,
+    TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA,
+
+    /* All AES-256 suites */
+    TLS_RSA_WITH_AES_256_GCM_SHA384,
+    TLS_RSA_WITH_AES_256_CBC_SHA256,
+    TLS_RSA_WITH_AES_256_CBC_SHA,
+    TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,
+    TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,
+    TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
+    TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,
+    TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,
+    TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
+
+    /* All CAMELLIA-256 suites */
+    TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384,
+    TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256,
+    TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,
+    TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384,
+    TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384,
+    TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,
+    TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
+
+    /* All AES-128 suites */
+    TLS_RSA_WITH_AES_128_GCM_SHA256,
+    TLS_RSA_WITH_AES_128_CBC_SHA256,
+    TLS_RSA_WITH_AES_128_CBC_SHA,
+    TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
+    TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
+    TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
+    TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
+    TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
+    TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
+
+    /* All CAMELLIA-128 suites */
+    TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256,
+    TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+    TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,
+    TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256,
+    TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+    TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,
+    TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
+
+    /* All remaining >= 128-bit suites */
+    TLS_RSA_WITH_3DES_EDE_CBC_SHA,
+    TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
+    TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
+
+    /* The RSA PSK suites */
+    TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,
+    TLS_RSA_PSK_WITH_AES_256_CBC_SHA384,
+    TLS_RSA_PSK_WITH_AES_256_CBC_SHA,
+    TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384,
+    TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+
+    TLS_RSA_PSK_WITH_AES_128_GCM_SHA256,
+    TLS_RSA_PSK_WITH_AES_128_CBC_SHA256,
+    TLS_RSA_PSK_WITH_AES_128_CBC_SHA,
+    TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256,
+    TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+
+    TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
+
+    /* The PSK suites */
+    TLS_PSK_WITH_AES_256_GCM_SHA384,
+    TLS_PSK_WITH_AES_256_CBC_SHA384,
+    TLS_PSK_WITH_AES_256_CBC_SHA,
+    TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384,
+    TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+
+    TLS_PSK_WITH_AES_128_GCM_SHA256,
+    TLS_PSK_WITH_AES_128_CBC_SHA256,
+    TLS_PSK_WITH_AES_128_CBC_SHA,
+    TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256,
+    TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+
+    TLS_PSK_WITH_3DES_EDE_CBC_SHA,
+
+    /* RC4 suites */
+    TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
+    TLS_ECDHE_RSA_WITH_RC4_128_SHA,
+    TLS_ECDHE_PSK_WITH_RC4_128_SHA,
+    TLS_DHE_PSK_WITH_RC4_128_SHA,
+    TLS_RSA_WITH_RC4_128_SHA,
+    TLS_RSA_WITH_RC4_128_MD5,
+    TLS_ECDH_RSA_WITH_RC4_128_SHA,
+    TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
+    TLS_RSA_PSK_WITH_RC4_128_SHA,
+    TLS_PSK_WITH_RC4_128_SHA,
+
+    /* Weak suites */
+    TLS_DHE_RSA_WITH_DES_CBC_SHA,
+    TLS_RSA_WITH_DES_CBC_SHA,
+
+    /* NULL suites */
+    TLS_ECDHE_ECDSA_WITH_NULL_SHA,
+    TLS_ECDHE_RSA_WITH_NULL_SHA,
+    TLS_ECDHE_PSK_WITH_NULL_SHA384,
+    TLS_ECDHE_PSK_WITH_NULL_SHA256,
+    TLS_ECDHE_PSK_WITH_NULL_SHA,
+    TLS_DHE_PSK_WITH_NULL_SHA384,
+    TLS_DHE_PSK_WITH_NULL_SHA256,
+    TLS_DHE_PSK_WITH_NULL_SHA,
+
+    TLS_RSA_WITH_NULL_SHA256,
+    TLS_RSA_WITH_NULL_SHA,
+    TLS_RSA_WITH_NULL_MD5,
+    TLS_ECDH_RSA_WITH_NULL_SHA,
+    TLS_ECDH_ECDSA_WITH_NULL_SHA,
+    TLS_RSA_PSK_WITH_NULL_SHA384,
+    TLS_RSA_PSK_WITH_NULL_SHA256,
+    TLS_RSA_PSK_WITH_NULL_SHA,
+    TLS_PSK_WITH_NULL_SHA384,
+    TLS_PSK_WITH_NULL_SHA256,
+    TLS_PSK_WITH_NULL_SHA,
+
+    0
+};
+
+#define MAX_CIPHERSUITES    160
+static int supported_ciphersuites[MAX_CIPHERSUITES];
+static int supported_init = 0;
+
+static const ssl_ciphersuite_t ciphersuite_definitions[] =
+{
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+#if defined(POLARSSL_AES_C)
+#if defined(POLARSSL_SHA1_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    { TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA",
+      POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+    { TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA",
+      POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#endif /* POLARSSL_SHA1_C */
+#if defined(POLARSSL_SHA256_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    { TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256",
+      POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#if defined(POLARSSL_GCM_C)
+    { TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256",
+      POLARSSL_CIPHER_AES_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_GCM_C */
+#endif /* POLARSSL_SHA256_C */
+#if defined(POLARSSL_SHA512_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    { TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384",
+      POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#if defined(POLARSSL_GCM_C)
+    { TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384",
+      POLARSSL_CIPHER_AES_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_GCM_C */
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_AES_C */
+
+#if defined(POLARSSL_CAMELLIA_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+#if defined(POLARSSL_SHA256_C)
+    { TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA256",
+      POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA256_C */
+#if defined(POLARSSL_SHA512_C)
+    { TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA384",
+      POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+#if defined(POLARSSL_GCM_C)
+#if defined(POLARSSL_SHA256_C)
+    { TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-GCM-SHA256",
+      POLARSSL_CIPHER_CAMELLIA_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA256_C */
+#if defined(POLARSSL_SHA512_C)
+    { TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-GCM-SHA384",
+      POLARSSL_CIPHER_CAMELLIA_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_GCM_C */
+#endif /* POLARSSL_CAMELLIA_C */
+
+#if defined(POLARSSL_DES_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+#if defined(POLARSSL_SHA1_C)
+    { TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-3DES-EDE-CBC-SHA",
+      POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#endif /* POLARSSL_DES_C */
+
+#if defined(POLARSSL_ARC4_C)
+#if defined(POLARSSL_SHA1_C)
+    { TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, "TLS-ECDHE-ECDSA-WITH-RC4-128-SHA",
+      POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_ARC4_C */
+
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+#if defined(POLARSSL_SHA1_C)
+    { TLS_ECDHE_ECDSA_WITH_NULL_SHA, "TLS-ECDHE-ECDSA-WITH-NULL-SHA",
+      POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_WEAK },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_CIPHER_NULL_CIPHER */
+#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
+
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED)
+#if defined(POLARSSL_AES_C)
+#if defined(POLARSSL_SHA1_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA",
+      POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+    { TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA",
+      POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#endif /* POLARSSL_SHA1_C */
+#if defined(POLARSSL_SHA256_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256",
+      POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#if defined(POLARSSL_GCM_C)
+    { TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256",
+      POLARSSL_CIPHER_AES_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_GCM_C */
+#endif /* POLARSSL_SHA256_C */
+#if defined(POLARSSL_SHA512_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    { TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384",
+      POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#if defined(POLARSSL_GCM_C)
+    { TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384",
+      POLARSSL_CIPHER_AES_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_GCM_C */
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_AES_C */
+
+#if defined(POLARSSL_CAMELLIA_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+#if defined(POLARSSL_SHA256_C)
+    { TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA256",
+      POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA256_C */
+#if defined(POLARSSL_SHA512_C)
+    { TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA384",
+      POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+#if defined(POLARSSL_GCM_C)
+#if defined(POLARSSL_SHA256_C)
+    { TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-GCM-SHA256",
+      POLARSSL_CIPHER_CAMELLIA_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA256_C */
+#if defined(POLARSSL_SHA512_C)
+    { TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-GCM-SHA384",
+      POLARSSL_CIPHER_CAMELLIA_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_GCM_C */
+#endif /* POLARSSL_CAMELLIA_C */
+
+#if defined(POLARSSL_DES_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+#if defined(POLARSSL_SHA1_C)
+    { TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA",
+      POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#endif /* POLARSSL_DES_C */
+
+#if defined(POLARSSL_ARC4_C)
+#if defined(POLARSSL_SHA1_C)
+    { TLS_ECDHE_RSA_WITH_RC4_128_SHA, "TLS-ECDHE-RSA-WITH-RC4-128-SHA",
+      POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_ARC4_C */
+
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+#if defined(POLARSSL_SHA1_C)
+    { TLS_ECDHE_RSA_WITH_NULL_SHA, "TLS-ECDHE-RSA-WITH-NULL-SHA",
+      POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_WEAK },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_CIPHER_NULL_CIPHER */
+#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED */
+
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED)
+#if defined(POLARSSL_AES_C)
+#if defined(POLARSSL_SHA512_C) && defined(POLARSSL_GCM_C)
+    { TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384",
+      POLARSSL_CIPHER_AES_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_DHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA512_C && POLARSSL_GCM_C */
+
+#if defined(POLARSSL_SHA256_C)
+#if defined(POLARSSL_GCM_C)
+    { TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256",
+      POLARSSL_CIPHER_AES_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_GCM_C */
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    { TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256",
+      POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+
+    { TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256",
+      POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#endif /* POLARSSL_SHA256_C */
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+#if defined(POLARSSL_SHA1_C)
+    { TLS_DHE_RSA_WITH_AES_128_CBC_SHA, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA",
+      POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+
+    { TLS_DHE_RSA_WITH_AES_256_CBC_SHA, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA",
+      POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#endif /* POLARSSL_AES_C */
+
+#if defined(POLARSSL_CAMELLIA_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+#if defined(POLARSSL_SHA256_C)
+    { TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256",
+      POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+
+    { TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256",
+      POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA256_C */
+
+#if defined(POLARSSL_SHA1_C)
+    { TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA",
+      POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+
+    { TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA",
+      POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#if defined(POLARSSL_GCM_C)
+#if defined(POLARSSL_SHA256_C)
+    { TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-GCM-SHA256",
+      POLARSSL_CIPHER_CAMELLIA_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA256_C */
+
+#if defined(POLARSSL_SHA512_C)
+    { TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-RSA-WITH-CAMELLIA-256-GCM-SHA384",
+      POLARSSL_CIPHER_CAMELLIA_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_DHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_GCM_C */
+#endif /* POLARSSL_CAMELLIA_C */
+
+#if defined(POLARSSL_DES_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+#if defined(POLARSSL_SHA1_C)
+    { TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA",
+      POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#endif /* POLARSSL_DES_C */
+#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED */
+
+#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED)
+#if defined(POLARSSL_AES_C)
+#if defined(POLARSSL_SHA512_C) && defined(POLARSSL_GCM_C)
+    { TLS_RSA_WITH_AES_256_GCM_SHA384, "TLS-RSA-WITH-AES-256-GCM-SHA384",
+      POLARSSL_CIPHER_AES_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA512_C && POLARSSL_GCM_C */
+
+#if defined(POLARSSL_SHA256_C)
+#if defined(POLARSSL_GCM_C)
+    { TLS_RSA_WITH_AES_128_GCM_SHA256, "TLS-RSA-WITH-AES-128-GCM-SHA256",
+      POLARSSL_CIPHER_AES_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_GCM_C */
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    { TLS_RSA_WITH_AES_128_CBC_SHA256, "TLS-RSA-WITH-AES-128-CBC-SHA256",
+      POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+
+    { TLS_RSA_WITH_AES_256_CBC_SHA256, "TLS-RSA-WITH-AES-256-CBC-SHA256",
+      POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#endif /* POLARSSL_SHA256_C */
+
+#if defined(POLARSSL_SHA1_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    { TLS_RSA_WITH_AES_128_CBC_SHA, "TLS-RSA-WITH-AES-128-CBC-SHA",
+      POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+
+    { TLS_RSA_WITH_AES_256_CBC_SHA, "TLS-RSA-WITH-AES-256-CBC-SHA",
+      POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_AES_C */
+
+#if defined(POLARSSL_CAMELLIA_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+#if defined(POLARSSL_SHA256_C)
+    { TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256",
+      POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+
+    { TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256",
+      POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA256_C */
+
+#if defined(POLARSSL_SHA1_C)
+    { TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA",
+      POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+
+    { TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA",
+      POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+#if defined(POLARSSL_GCM_C)
+#if defined(POLARSSL_SHA256_C)
+    { TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-WITH-CAMELLIA-128-GCM-SHA256",
+      POLARSSL_CIPHER_CAMELLIA_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA256_C */
+
+#if defined(POLARSSL_SHA1_C)
+    { TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-WITH-CAMELLIA-256-GCM-SHA384",
+      POLARSSL_CIPHER_CAMELLIA_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_GCM_C */
+#endif /* POLARSSL_CAMELLIA_C */
+
+#if defined(POLARSSL_DES_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+#if defined(POLARSSL_SHA1_C)
+    { TLS_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-RSA-WITH-3DES-EDE-CBC-SHA",
+      POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#endif /* POLARSSL_DES_C */
+
+#if defined(POLARSSL_ARC4_C)
+#if defined(POLARSSL_MD5_C)
+    { TLS_RSA_WITH_RC4_128_MD5, "TLS-RSA-WITH-RC4-128-MD5",
+      POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_MD5, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif
+
+#if defined(POLARSSL_SHA1_C)
+    { TLS_RSA_WITH_RC4_128_SHA, "TLS-RSA-WITH-RC4-128-SHA",
+      POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif
+#endif /* POLARSSL_ARC4_C */
+#endif /* POLARSSL_KEY_EXCHANGE_RSA_ENABLED */
+
+#if defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED)
+#if defined(POLARSSL_AES_C)
+#if defined(POLARSSL_SHA1_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    { TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA",
+      POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+    { TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA",
+      POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#endif /* POLARSSL_SHA1_C */
+#if defined(POLARSSL_SHA256_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    { TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA256",
+      POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDH_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#if defined(POLARSSL_GCM_C)
+    { TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-AES-128-GCM-SHA256",
+      POLARSSL_CIPHER_AES_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDH_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_GCM_C */
+#endif /* POLARSSL_SHA256_C */
+#if defined(POLARSSL_SHA512_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    { TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA384",
+      POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDH_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#if defined(POLARSSL_GCM_C)
+    { TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-AES-256-GCM-SHA384",
+      POLARSSL_CIPHER_AES_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDH_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_GCM_C */
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_AES_C */
+
+#if defined(POLARSSL_CAMELLIA_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+#if defined(POLARSSL_SHA256_C)
+    { TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-CBC-SHA256",
+      POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDH_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA256_C */
+#if defined(POLARSSL_SHA512_C)
+    { TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-CBC-SHA384",
+      POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDH_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+#if defined(POLARSSL_GCM_C)
+#if defined(POLARSSL_SHA256_C)
+    { TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-GCM-SHA256",
+      POLARSSL_CIPHER_CAMELLIA_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDH_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA256_C */
+#if defined(POLARSSL_SHA512_C)
+    { TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-GCM-SHA384",
+      POLARSSL_CIPHER_CAMELLIA_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDH_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_GCM_C */
+#endif /* POLARSSL_CAMELLIA_C */
+
+#if defined(POLARSSL_DES_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+#if defined(POLARSSL_SHA1_C)
+    { TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDH-RSA-WITH-3DES-EDE-CBC-SHA",
+      POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#endif /* POLARSSL_DES_C */
+
+#if defined(POLARSSL_ARC4_C)
+#if defined(POLARSSL_SHA1_C)
+    { TLS_ECDH_RSA_WITH_RC4_128_SHA, "TLS-ECDH-RSA-WITH-RC4-128-SHA",
+      POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_ARC4_C */
+
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+#if defined(POLARSSL_SHA1_C)
+    { TLS_ECDH_RSA_WITH_NULL_SHA, "TLS-ECDH-RSA-WITH-NULL-SHA",
+      POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_WEAK },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_CIPHER_NULL_CIPHER */
+#endif /* POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED */
+
+#if defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+#if defined(POLARSSL_AES_C)
+#if defined(POLARSSL_SHA1_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    { TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA",
+      POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+    { TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA",
+      POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#endif /* POLARSSL_SHA1_C */
+#if defined(POLARSSL_SHA256_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    { TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA256",
+      POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#if defined(POLARSSL_GCM_C)
+    { TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256",
+      POLARSSL_CIPHER_AES_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_GCM_C */
+#endif /* POLARSSL_SHA256_C */
+#if defined(POLARSSL_SHA512_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    { TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA384",
+      POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#if defined(POLARSSL_GCM_C)
+    { TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-GCM-SHA384",
+      POLARSSL_CIPHER_AES_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_GCM_C */
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_AES_C */
+
+#if defined(POLARSSL_CAMELLIA_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+#if defined(POLARSSL_SHA256_C)
+    { TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-CBC-SHA256",
+      POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA256_C */
+#if defined(POLARSSL_SHA512_C)
+    { TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384",
+      POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+#if defined(POLARSSL_GCM_C)
+#if defined(POLARSSL_SHA256_C)
+    { TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-GCM-SHA256",
+      POLARSSL_CIPHER_CAMELLIA_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA256_C */
+#if defined(POLARSSL_SHA512_C)
+    { TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-GCM-SHA384",
+      POLARSSL_CIPHER_CAMELLIA_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_GCM_C */
+#endif /* POLARSSL_CAMELLIA_C */
+
+#if defined(POLARSSL_DES_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+#if defined(POLARSSL_SHA1_C)
+    { TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDH-ECDSA-WITH-3DES-EDE-CBC-SHA",
+      POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#endif /* POLARSSL_DES_C */
+
+#if defined(POLARSSL_ARC4_C)
+#if defined(POLARSSL_SHA1_C)
+    { TLS_ECDH_ECDSA_WITH_RC4_128_SHA, "TLS-ECDH-ECDSA-WITH-RC4-128-SHA",
+      POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_ARC4_C */
+
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+#if defined(POLARSSL_SHA1_C)
+    { TLS_ECDH_ECDSA_WITH_NULL_SHA, "TLS-ECDH-ECDSA-WITH-NULL-SHA",
+      POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_WEAK },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_CIPHER_NULL_CIPHER */
+#endif /* POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
+
+#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED)
+#if defined(POLARSSL_AES_C)
+#if defined(POLARSSL_GCM_C)
+#if defined(POLARSSL_SHA256_C)
+    { TLS_PSK_WITH_AES_128_GCM_SHA256, "TLS-PSK-WITH-AES-128-GCM-SHA256",
+      POLARSSL_CIPHER_AES_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA256_C */
+
+#if defined(POLARSSL_SHA512_C)
+    { TLS_PSK_WITH_AES_256_GCM_SHA384, "TLS-PSK-WITH-AES-256-GCM-SHA384",
+      POLARSSL_CIPHER_AES_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_GCM_C */
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+#if defined(POLARSSL_SHA256_C)
+    { TLS_PSK_WITH_AES_128_CBC_SHA256, "TLS-PSK-WITH-AES-128-CBC-SHA256",
+      POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA256_C */
+
+#if defined(POLARSSL_SHA512_C)
+    { TLS_PSK_WITH_AES_256_CBC_SHA384, "TLS-PSK-WITH-AES-256-CBC-SHA384",
+      POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA512_C */
+
+#if defined(POLARSSL_SHA1_C)
+    { TLS_PSK_WITH_AES_128_CBC_SHA, "TLS-PSK-WITH-AES-128-CBC-SHA",
+      POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+
+    { TLS_PSK_WITH_AES_256_CBC_SHA, "TLS-PSK-WITH-AES-256-CBC-SHA",
+      POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#endif /* POLARSSL_AES_C */
+
+#if defined(POLARSSL_CAMELLIA_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+#if defined(POLARSSL_SHA256_C)
+    { TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-PSK-WITH-CAMELLIA-128-CBC-SHA256",
+      POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA256_C */
+
+#if defined(POLARSSL_SHA512_C)
+    { TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-PSK-WITH-CAMELLIA-256-CBC-SHA384",
+      POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+#if defined(POLARSSL_GCM_C)
+#if defined(POLARSSL_SHA256_C)
+    { TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-PSK-WITH-CAMELLIA-128-GCM-SHA256",
+      POLARSSL_CIPHER_CAMELLIA_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA256_C */
+
+#if defined(POLARSSL_SHA512_C)
+    { TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-PSK-WITH-CAMELLIA-256-GCM-SHA384",
+      POLARSSL_CIPHER_CAMELLIA_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_GCM_C */
+#endif /* POLARSSL_CAMELLIA_C */
+
+#if defined(POLARSSL_DES_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+#if defined(POLARSSL_SHA1_C)
+    { TLS_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-PSK-WITH-3DES-EDE-CBC-SHA",
+      POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#endif /* POLARSSL_DES_C */
+
+#if defined(POLARSSL_ARC4_C)
+#if defined(POLARSSL_SHA1_C)
+    { TLS_PSK_WITH_RC4_128_SHA, "TLS-PSK-WITH-RC4-128-SHA",
+      POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_ARC4_C */
+#endif /* POLARSSL_KEY_EXCHANGE_PSK_ENABLED */
+
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED)
+#if defined(POLARSSL_AES_C)
+#if defined(POLARSSL_GCM_C)
+#if defined(POLARSSL_SHA256_C)
+    { TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, "TLS-DHE-PSK-WITH-AES-128-GCM-SHA256",
+      POLARSSL_CIPHER_AES_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA256_C */
+
+#if defined(POLARSSL_SHA512_C)
+    { TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, "TLS-DHE-PSK-WITH-AES-256-GCM-SHA384",
+      POLARSSL_CIPHER_AES_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_DHE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_GCM_C */
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+#if defined(POLARSSL_SHA256_C)
+    { TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA256",
+      POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA256_C */
+
+#if defined(POLARSSL_SHA512_C)
+    { TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA384",
+      POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_DHE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA512_C */
+
+#if defined(POLARSSL_SHA1_C)
+    { TLS_DHE_PSK_WITH_AES_128_CBC_SHA, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA",
+      POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+
+    { TLS_DHE_PSK_WITH_AES_256_CBC_SHA, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA",
+      POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#endif /* POLARSSL_AES_C */
+
+#if defined(POLARSSL_CAMELLIA_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+#if defined(POLARSSL_SHA256_C)
+    { TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-CBC-SHA256",
+      POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA256_C */
+
+#if defined(POLARSSL_SHA512_C)
+    { TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-CBC-SHA384",
+      POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_DHE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+#if defined(POLARSSL_GCM_C)
+#if defined(POLARSSL_SHA256_C)
+    { TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-GCM-SHA256",
+      POLARSSL_CIPHER_CAMELLIA_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA256_C */
+
+#if defined(POLARSSL_SHA512_C)
+    { TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-GCM-SHA384",
+      POLARSSL_CIPHER_CAMELLIA_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_DHE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_GCM_C */
+#endif /* POLARSSL_CAMELLIA_C */
+
+#if defined(POLARSSL_DES_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+#if defined(POLARSSL_SHA1_C)
+    { TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-DHE-PSK-WITH-3DES-EDE-CBC-SHA",
+      POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#endif /* POLARSSL_DES_C */
+
+#if defined(POLARSSL_ARC4_C)
+#if defined(POLARSSL_SHA1_C)
+    { TLS_DHE_PSK_WITH_RC4_128_SHA, "TLS-DHE-PSK-WITH-RC4-128-SHA",
+      POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_ARC4_C */
+#endif /* POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */
+
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
+#if defined(POLARSSL_AES_C)
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+#if defined(POLARSSL_SHA256_C)
+    { TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256",
+      POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA256_C */
+
+#if defined(POLARSSL_SHA512_C)
+    { TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA384",
+      POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA512_C */
+
+#if defined(POLARSSL_SHA1_C)
+    { TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA",
+      POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+
+    { TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA",
+      POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#endif /* POLARSSL_AES_C */
+
+#if defined(POLARSSL_CAMELLIA_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+#if defined(POLARSSL_SHA256_C)
+    { TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-CAMELLIA-128-CBC-SHA256",
+      POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA256_C */
+
+#if defined(POLARSSL_SHA512_C)
+    { TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-CAMELLIA-256-CBC-SHA384",
+      POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#endif /* POLARSSL_CAMELLIA_C */
+
+#if defined(POLARSSL_DES_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+#if defined(POLARSSL_SHA1_C)
+    { TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-PSK-WITH-3DES-EDE-CBC-SHA",
+      POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#endif /* POLARSSL_DES_C */
+
+#if defined(POLARSSL_ARC4_C)
+#if defined(POLARSSL_SHA1_C)
+    { TLS_ECDHE_PSK_WITH_RC4_128_SHA, "TLS-ECDHE-PSK-WITH-RC4-128-SHA",
+      POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_ARC4_C */
+#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
+
+#if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED)
+#if defined(POLARSSL_AES_C)
+#if defined(POLARSSL_GCM_C)
+#if defined(POLARSSL_SHA256_C)
+    { TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, "TLS-RSA-PSK-WITH-AES-128-GCM-SHA256",
+      POLARSSL_CIPHER_AES_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA256_C */
+
+#if defined(POLARSSL_SHA512_C)
+    { TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, "TLS-RSA-PSK-WITH-AES-256-GCM-SHA384",
+      POLARSSL_CIPHER_AES_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_RSA_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_GCM_C */
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+#if defined(POLARSSL_SHA256_C)
+    { TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA256",
+      POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA256_C */
+
+#if defined(POLARSSL_SHA512_C)
+    { TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA384",
+      POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_RSA_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA512_C */
+
+#if defined(POLARSSL_SHA1_C)
+    { TLS_RSA_PSK_WITH_AES_128_CBC_SHA, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA",
+      POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+
+    { TLS_RSA_PSK_WITH_AES_256_CBC_SHA, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA",
+      POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#endif /* POLARSSL_AES_C */
+
+#if defined(POLARSSL_CAMELLIA_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+#if defined(POLARSSL_SHA256_C)
+    { TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-CBC-SHA256",
+      POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA256_C */
+
+#if defined(POLARSSL_SHA512_C)
+    { TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-CBC-SHA384",
+      POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_RSA_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+#if defined(POLARSSL_GCM_C)
+#if defined(POLARSSL_SHA256_C)
+    { TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-GCM-SHA256",
+      POLARSSL_CIPHER_CAMELLIA_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA256_C */
+
+#if defined(POLARSSL_SHA512_C)
+    { TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-GCM-SHA384",
+      POLARSSL_CIPHER_CAMELLIA_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_RSA_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_GCM_C */
+#endif /* POLARSSL_CAMELLIA_C */
+
+#if defined(POLARSSL_DES_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+#if defined(POLARSSL_SHA1_C)
+    { TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-RSA-PSK-WITH-3DES-EDE-CBC-SHA",
+      POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#endif /* POLARSSL_DES_C */
+
+#if defined(POLARSSL_ARC4_C)
+#if defined(POLARSSL_SHA1_C)
+    { TLS_RSA_PSK_WITH_RC4_128_SHA, "TLS-RSA-PSK-WITH-RC4-128-SHA",
+      POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_ARC4_C */
+#endif /* POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED */
+
+#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES)
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED)
+#if defined(POLARSSL_MD5_C)
+    { TLS_RSA_WITH_NULL_MD5, "TLS-RSA-WITH-NULL-MD5",
+      POLARSSL_CIPHER_NULL, POLARSSL_MD_MD5, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_WEAK },
+#endif
+
+#if defined(POLARSSL_SHA1_C)
+    { TLS_RSA_WITH_NULL_SHA, "TLS-RSA-WITH-NULL-SHA",
+      POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_WEAK },
+#endif
+
+#if defined(POLARSSL_SHA256_C)
+    { TLS_RSA_WITH_NULL_SHA256, "TLS-RSA-WITH-NULL-SHA256",
+      POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_WEAK },
+#endif
+#endif /* POLARSSL_KEY_EXCHANGE_RSA_ENABLED */
+
+#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED)
+#if defined(POLARSSL_SHA1_C)
+    { TLS_PSK_WITH_NULL_SHA, "TLS-PSK-WITH-NULL-SHA",
+      POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_WEAK },
+#endif /* POLARSSL_SHA1_C */
+
+#if defined(POLARSSL_SHA256_C)
+    { TLS_PSK_WITH_NULL_SHA256, "TLS-PSK-WITH-NULL-SHA256",
+      POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_WEAK },
+#endif
+
+#if defined(POLARSSL_SHA512_C)
+    { TLS_PSK_WITH_NULL_SHA384, "TLS-PSK-WITH-NULL-SHA384",
+      POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_WEAK },
+#endif
+#endif /* POLARSSL_KEY_EXCHANGE_PSK_ENABLED */
+
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED)
+#if defined(POLARSSL_SHA1_C)
+    { TLS_DHE_PSK_WITH_NULL_SHA, "TLS-DHE-PSK-WITH-NULL-SHA",
+      POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_WEAK },
+#endif /* POLARSSL_SHA1_C */
+
+#if defined(POLARSSL_SHA256_C)
+    { TLS_DHE_PSK_WITH_NULL_SHA256, "TLS-DHE-PSK-WITH-NULL-SHA256",
+      POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_WEAK },
+#endif
+
+#if defined(POLARSSL_SHA512_C)
+    { TLS_DHE_PSK_WITH_NULL_SHA384, "TLS-DHE-PSK-WITH-NULL-SHA384",
+      POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_DHE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_WEAK },
+#endif
+#endif /* POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */
+
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
+#if defined(POLARSSL_SHA1_C)
+    { TLS_ECDHE_PSK_WITH_NULL_SHA, "TLS-ECDHE-PSK-WITH-NULL-SHA",
+      POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_WEAK },
+#endif /* POLARSSL_SHA1_C */
+
+#if defined(POLARSSL_SHA256_C)
+    { TLS_ECDHE_PSK_WITH_NULL_SHA256, "TLS-ECDHE-PSK-WITH-NULL-SHA256",
+      POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_WEAK },
+#endif
+
+#if defined(POLARSSL_SHA512_C)
+    { TLS_ECDHE_PSK_WITH_NULL_SHA384, "TLS-ECDHE-PSK-WITH-NULL-SHA384",
+      POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_WEAK },
+#endif
+#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
+
+#if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED)
+#if defined(POLARSSL_SHA1_C)
+    { TLS_RSA_PSK_WITH_NULL_SHA, "TLS-RSA-PSK-WITH-NULL-SHA",
+      POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_WEAK },
+#endif /* POLARSSL_SHA1_C */
+
+#if defined(POLARSSL_SHA256_C)
+    { TLS_RSA_PSK_WITH_NULL_SHA256, "TLS-RSA-PSK-WITH-NULL-SHA256",
+      POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_WEAK },
+#endif
+
+#if defined(POLARSSL_SHA512_C)
+    { TLS_RSA_PSK_WITH_NULL_SHA384, "TLS-RSA-PSK-WITH-NULL-SHA384",
+      POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_RSA_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_WEAK },
+#endif
+#endif /* POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED */
+#endif /* POLARSSL_CIPHER_NULL_CIPHER */
+
+#if defined(POLARSSL_DES_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED)
+#if defined(POLARSSL_SHA1_C)
+    { TLS_DHE_RSA_WITH_DES_CBC_SHA, "TLS-DHE-RSA-WITH-DES-CBC-SHA",
+      POLARSSL_CIPHER_DES_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_WEAK },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED */
+
+#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED)
+#if defined(POLARSSL_SHA1_C)
+    { TLS_RSA_WITH_DES_CBC_SHA, "TLS-RSA-WITH-DES-CBC-SHA",
+      POLARSSL_CIPHER_DES_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_WEAK },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_KEY_EXCHANGE_RSA_ENABLED */
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#endif /* POLARSSL_DES_C */
+#endif /* POLARSSL_ENABLE_WEAK_CIPHERSUITES */
+
+    { 0, "", 0, 0, 0, 0, 0, 0, 0, 0 }
+};
+
+const int *ssl_list_ciphersuites( void )
+{
+    /*
+     * On initial call filter out all ciphersuites not supported by current
+     * build based on presence in the ciphersuite_definitions.
+     */
+    if( supported_init == 0 )
+    {
+        const int *p = ciphersuite_preference;
+        int *q = supported_ciphersuites;
+        size_t i;
+        size_t max = sizeof(supported_ciphersuites) / sizeof(int);
+
+        for( i = 0; i < max - 1 && p[i] != 0; i++ )
+        {
+            if( ssl_ciphersuite_from_id( p[i] ) != NULL )
+                *(q++) = p[i];
+        }
+        *q = 0;
+
+        supported_init = 1;
+    }
+
+    return supported_ciphersuites;
+};
+
+const ssl_ciphersuite_t *ssl_ciphersuite_from_string(
+                                                const char *ciphersuite_name )
+{
+    const ssl_ciphersuite_t *cur = ciphersuite_definitions;
+
+    if( NULL == ciphersuite_name )
+        return( NULL );
+
+    while( cur->id != 0 )
+    {
+        if( 0 == strcasecmp( cur->name, ciphersuite_name ) )
+            return( cur );
+
+        cur++;
+    }
+
+    return( NULL );
+}
+
+const ssl_ciphersuite_t *ssl_ciphersuite_from_id( int ciphersuite )
+{
+    const ssl_ciphersuite_t *cur = ciphersuite_definitions;
+
+    while( cur->id != 0 )
+    {
+        if( cur->id == ciphersuite )
+            return( cur );
+
+        cur++;
+    }
+
+    return( NULL );
+}
+
+const char *ssl_get_ciphersuite_name( const int ciphersuite_id )
+{
+    const ssl_ciphersuite_t *cur;
+
+    cur = ssl_ciphersuite_from_id( ciphersuite_id );
+
+    if( cur == NULL )
+        return( "unknown" );
+
+    return( cur->name );
+}
+
+int ssl_get_ciphersuite_id( const char *ciphersuite_name )
+{
+    const ssl_ciphersuite_t *cur;
+
+    cur = ssl_ciphersuite_from_string( ciphersuite_name );
+
+    if( cur == NULL )
+        return( 0 );
+
+    return( cur->id );
+}
+
+#if defined(POLARSSL_PK_C)
+pk_type_t ssl_get_ciphersuite_sig_pk_alg( const ssl_ciphersuite_t *info )
+{
+    switch( info->key_exchange )
+    {
+        case POLARSSL_KEY_EXCHANGE_RSA:
+        case POLARSSL_KEY_EXCHANGE_DHE_RSA:
+        case POLARSSL_KEY_EXCHANGE_ECDHE_RSA:
+        case POLARSSL_KEY_EXCHANGE_RSA_PSK:
+            return( POLARSSL_PK_RSA );
+
+        case POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA:
+            return( POLARSSL_PK_ECDSA );
+
+        case POLARSSL_KEY_EXCHANGE_ECDH_RSA:
+        case POLARSSL_KEY_EXCHANGE_ECDH_ECDSA:
+            return( POLARSSL_PK_ECKEY );
+
+        default:
+            return( POLARSSL_PK_NONE );
+    }
+}
+#endif /* POLARSSL_PK_C */
+
+#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C)
+int ssl_ciphersuite_uses_ec( const ssl_ciphersuite_t *info )
+{
+    switch( info->key_exchange )
+    {
+        case POLARSSL_KEY_EXCHANGE_ECDHE_RSA:
+        case POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA:
+        case POLARSSL_KEY_EXCHANGE_ECDHE_PSK:
+        case POLARSSL_KEY_EXCHANGE_ECDH_RSA:
+        case POLARSSL_KEY_EXCHANGE_ECDH_ECDSA:
+            return( 1 );
+
+        default:
+            return( 0 );
+    }
+}
+#endif /* POLARSSL_ECDH_C || POLARSSL_ECDSA_C */
+
+#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
+int ssl_ciphersuite_uses_psk( const ssl_ciphersuite_t *info )
+{
+    switch( info->key_exchange )
+    {
+        case POLARSSL_KEY_EXCHANGE_PSK:
+        case POLARSSL_KEY_EXCHANGE_RSA_PSK:
+        case POLARSSL_KEY_EXCHANGE_DHE_PSK:
+        case POLARSSL_KEY_EXCHANGE_ECDHE_PSK:
+            return( 1 );
+
+        default:
+            return( 0 );
+    }
+}
+#endif /* POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED */
+
+#endif /* POLARSSL_SSL_TLS_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/ssl_cli.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,2619 @@
+/*
+ *  SSLv3/TLSv1 client-side functions
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_SSL_CLI_C)
+
+#include "polarssl/debug.h"
+#include "polarssl/ssl.h"
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
+#include <basetsd.h>
+typedef UINT32 uint32_t;
+#else
+#include <inttypes.h>
+#endif
+
+#if defined(POLARSSL_HAVE_TIME)
+#include <time.h>
+#endif
+
+#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
+static void ssl_write_hostname_ext( ssl_context *ssl,
+                                    unsigned char *buf,
+                                    size_t *olen )
+{
+    unsigned char *p = buf;
+
+    *olen = 0;
+
+    if ( ssl->hostname == NULL )
+        return;
+
+    SSL_DEBUG_MSG( 3, ( "client hello, adding server name extension: %s",
+                   ssl->hostname ) );
+
+    /*
+     * struct {
+     *     NameType name_type;
+     *     select (name_type) {
+     *         case host_name: HostName;
+     *     } name;
+     * } ServerName;
+     *
+     * enum {
+     *     host_name(0), (255)
+     * } NameType;
+     *
+     * opaque HostName<1..2^16-1>;
+     *
+     * struct {
+     *     ServerName server_name_list<1..2^16-1>
+     * } ServerNameList;
+     */
+    *p++ = (unsigned char)( ( TLS_EXT_SERVERNAME >> 8 ) & 0xFF );
+    *p++ = (unsigned char)( ( TLS_EXT_SERVERNAME      ) & 0xFF );
+
+    *p++ = (unsigned char)( ( (ssl->hostname_len + 5) >> 8 ) & 0xFF );
+    *p++ = (unsigned char)( ( (ssl->hostname_len + 5)      ) & 0xFF );
+
+    *p++ = (unsigned char)( ( (ssl->hostname_len + 3) >> 8 ) & 0xFF );
+    *p++ = (unsigned char)( ( (ssl->hostname_len + 3)      ) & 0xFF );
+
+    *p++ = (unsigned char)( ( TLS_EXT_SERVERNAME_HOSTNAME ) & 0xFF );
+    *p++ = (unsigned char)( ( ssl->hostname_len >> 8 ) & 0xFF );
+    *p++ = (unsigned char)( ( ssl->hostname_len      ) & 0xFF );
+
+    memcpy( p, ssl->hostname, ssl->hostname_len );
+
+    *olen = ssl->hostname_len + 9;
+}
+#endif /* POLARSSL_SSL_SERVER_NAME_INDICATION */
+
+static void ssl_write_renegotiation_ext( ssl_context *ssl,
+                                         unsigned char *buf,
+                                         size_t *olen )
+{
+    unsigned char *p = buf;
+
+    *olen = 0;
+
+    if( ssl->renegotiation != SSL_RENEGOTIATION )
+        return;
+
+    SSL_DEBUG_MSG( 3, ( "client hello, adding renegotiation extension" ) );
+
+    /*
+     * Secure renegotiation
+     */
+    *p++ = (unsigned char)( ( TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF );
+    *p++ = (unsigned char)( ( TLS_EXT_RENEGOTIATION_INFO      ) & 0xFF );
+
+    *p++ = 0x00;
+    *p++ = ( ssl->verify_data_len + 1 ) & 0xFF;
+    *p++ = ssl->verify_data_len & 0xFF;
+
+    memcpy( p, ssl->own_verify_data, ssl->verify_data_len );
+
+    *olen = 5 + ssl->verify_data_len;
+}
+
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+static void ssl_write_signature_algorithms_ext( ssl_context *ssl,
+                                                unsigned char *buf,
+                                                size_t *olen )
+{
+    unsigned char *p = buf;
+    unsigned char *sig_alg_list = buf + 6;
+    size_t sig_alg_len = 0;
+
+    *olen = 0;
+
+    if( ssl->max_minor_ver != SSL_MINOR_VERSION_3 )
+        return;
+
+    SSL_DEBUG_MSG( 3, ( "client hello, adding signature_algorithms extension" ) );
+
+    /*
+     * Prepare signature_algorithms extension (TLS 1.2)
+     */
+#if defined(POLARSSL_RSA_C)
+#if defined(POLARSSL_SHA512_C)
+    sig_alg_list[sig_alg_len++] = SSL_HASH_SHA512;
+    sig_alg_list[sig_alg_len++] = SSL_SIG_RSA;
+    sig_alg_list[sig_alg_len++] = SSL_HASH_SHA384;
+    sig_alg_list[sig_alg_len++] = SSL_SIG_RSA;
+#endif
+#if defined(POLARSSL_SHA256_C)
+    sig_alg_list[sig_alg_len++] = SSL_HASH_SHA256;
+    sig_alg_list[sig_alg_len++] = SSL_SIG_RSA;
+    sig_alg_list[sig_alg_len++] = SSL_HASH_SHA224;
+    sig_alg_list[sig_alg_len++] = SSL_SIG_RSA;
+#endif
+#if defined(POLARSSL_SHA1_C)
+    sig_alg_list[sig_alg_len++] = SSL_HASH_SHA1;
+    sig_alg_list[sig_alg_len++] = SSL_SIG_RSA;
+#endif
+#if defined(POLARSSL_MD5_C)
+    sig_alg_list[sig_alg_len++] = SSL_HASH_MD5;
+    sig_alg_list[sig_alg_len++] = SSL_SIG_RSA;
+#endif
+#endif /* POLARSSL_RSA_C */
+#if defined(POLARSSL_ECDSA_C)
+#if defined(POLARSSL_SHA512_C)
+    sig_alg_list[sig_alg_len++] = SSL_HASH_SHA512;
+    sig_alg_list[sig_alg_len++] = SSL_SIG_ECDSA;
+    sig_alg_list[sig_alg_len++] = SSL_HASH_SHA384;
+    sig_alg_list[sig_alg_len++] = SSL_SIG_ECDSA;
+#endif
+#if defined(POLARSSL_SHA256_C)
+    sig_alg_list[sig_alg_len++] = SSL_HASH_SHA256;
+    sig_alg_list[sig_alg_len++] = SSL_SIG_ECDSA;
+    sig_alg_list[sig_alg_len++] = SSL_HASH_SHA224;
+    sig_alg_list[sig_alg_len++] = SSL_SIG_ECDSA;
+#endif
+#if defined(POLARSSL_SHA1_C)
+    sig_alg_list[sig_alg_len++] = SSL_HASH_SHA1;
+    sig_alg_list[sig_alg_len++] = SSL_SIG_ECDSA;
+#endif
+#if defined(POLARSSL_MD5_C)
+    sig_alg_list[sig_alg_len++] = SSL_HASH_MD5;
+    sig_alg_list[sig_alg_len++] = SSL_SIG_ECDSA;
+#endif
+#endif /* POLARSSL_ECDSA_C */
+
+    /*
+     * enum {
+     *     none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5),
+     *     sha512(6), (255)
+     * } HashAlgorithm;
+     *
+     * enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) }
+     *   SignatureAlgorithm;
+     *
+     * struct {
+     *     HashAlgorithm hash;
+     *     SignatureAlgorithm signature;
+     * } SignatureAndHashAlgorithm;
+     *
+     * SignatureAndHashAlgorithm
+     *   supported_signature_algorithms<2..2^16-2>;
+     */
+    *p++ = (unsigned char)( ( TLS_EXT_SIG_ALG >> 8 ) & 0xFF );
+    *p++ = (unsigned char)( ( TLS_EXT_SIG_ALG      ) & 0xFF );
+
+    *p++ = (unsigned char)( ( ( sig_alg_len + 2 ) >> 8 ) & 0xFF );
+    *p++ = (unsigned char)( ( ( sig_alg_len + 2 )      ) & 0xFF );
+
+    *p++ = (unsigned char)( ( sig_alg_len >> 8 ) & 0xFF );
+    *p++ = (unsigned char)( ( sig_alg_len      ) & 0xFF );
+
+    *olen = 6 + sig_alg_len;
+}
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
+
+#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C)
+static void ssl_write_supported_elliptic_curves_ext( ssl_context *ssl,
+                                                     unsigned char *buf,
+                                                     size_t *olen )
+{
+    unsigned char *p = buf;
+    unsigned char *elliptic_curve_list = p + 6;
+    size_t elliptic_curve_len = 0;
+    const ecp_curve_info *info;
+#if defined(POLARSSL_SSL_SET_CURVES)
+    const ecp_group_id *grp_id;
+#else
+    ((void) ssl);
+#endif
+
+    *olen = 0;
+
+    SSL_DEBUG_MSG( 3, ( "client hello, adding supported_elliptic_curves extension" ) );
+
+#if defined(POLARSSL_SSL_SET_CURVES)
+    for( grp_id = ssl->curve_list; *grp_id != POLARSSL_ECP_DP_NONE; grp_id++ )
+    {
+        info = ecp_curve_info_from_grp_id( *grp_id );
+#else
+    for( info = ecp_curve_list(); info->grp_id != POLARSSL_ECP_DP_NONE; info++ )
+    {
+#endif
+
+        elliptic_curve_list[elliptic_curve_len++] = info->tls_id >> 8;
+        elliptic_curve_list[elliptic_curve_len++] = info->tls_id & 0xFF;
+    }
+
+    if( elliptic_curve_len == 0 )
+        return;
+
+    *p++ = (unsigned char)( ( TLS_EXT_SUPPORTED_ELLIPTIC_CURVES >> 8 ) & 0xFF );
+    *p++ = (unsigned char)( ( TLS_EXT_SUPPORTED_ELLIPTIC_CURVES      ) & 0xFF );
+
+    *p++ = (unsigned char)( ( ( elliptic_curve_len + 2 ) >> 8 ) & 0xFF );
+    *p++ = (unsigned char)( ( ( elliptic_curve_len + 2 )      ) & 0xFF );
+
+    *p++ = (unsigned char)( ( ( elliptic_curve_len     ) >> 8 ) & 0xFF );
+    *p++ = (unsigned char)( ( ( elliptic_curve_len     )      ) & 0xFF );
+
+    *olen = 6 + elliptic_curve_len;
+}
+
+static void ssl_write_supported_point_formats_ext( ssl_context *ssl,
+                                                   unsigned char *buf,
+                                                   size_t *olen )
+{
+    unsigned char *p = buf;
+    ((void) ssl);
+
+    *olen = 0;
+
+    SSL_DEBUG_MSG( 3, ( "client hello, adding supported_point_formats extension" ) );
+
+    *p++ = (unsigned char)( ( TLS_EXT_SUPPORTED_POINT_FORMATS >> 8 ) & 0xFF );
+    *p++ = (unsigned char)( ( TLS_EXT_SUPPORTED_POINT_FORMATS      ) & 0xFF );
+
+    *p++ = 0x00;
+    *p++ = 2;
+
+    *p++ = 1;
+    *p++ = POLARSSL_ECP_PF_UNCOMPRESSED;
+
+    *olen = 6;
+}
+#endif /* POLARSSL_ECDH_C || POLARSSL_ECDSA_C */
+
+#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH)
+static void ssl_write_max_fragment_length_ext( ssl_context *ssl,
+                                               unsigned char *buf,
+                                               size_t *olen )
+{
+    unsigned char *p = buf;
+
+    if( ssl->mfl_code == SSL_MAX_FRAG_LEN_NONE ) {
+        *olen = 0;
+        return;
+    }
+
+    SSL_DEBUG_MSG( 3, ( "client hello, adding max_fragment_length extension" ) );
+
+    *p++ = (unsigned char)( ( TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 ) & 0xFF );
+    *p++ = (unsigned char)( ( TLS_EXT_MAX_FRAGMENT_LENGTH      ) & 0xFF );
+
+    *p++ = 0x00;
+    *p++ = 1;
+
+    *p++ = ssl->mfl_code;
+
+    *olen = 5;
+}
+#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */
+
+#if defined(POLARSSL_SSL_TRUNCATED_HMAC)
+static void ssl_write_truncated_hmac_ext( ssl_context *ssl,
+                                          unsigned char *buf, size_t *olen )
+{
+    unsigned char *p = buf;
+
+    if( ssl->trunc_hmac == SSL_TRUNC_HMAC_DISABLED )
+    {
+        *olen = 0;
+        return;
+    }
+
+    SSL_DEBUG_MSG( 3, ( "client hello, adding truncated_hmac extension" ) );
+
+    *p++ = (unsigned char)( ( TLS_EXT_TRUNCATED_HMAC >> 8 ) & 0xFF );
+    *p++ = (unsigned char)( ( TLS_EXT_TRUNCATED_HMAC      ) & 0xFF );
+
+    *p++ = 0x00;
+    *p++ = 0x00;
+
+    *olen = 4;
+}
+#endif /* POLARSSL_SSL_TRUNCATED_HMAC */
+
+#if defined(POLARSSL_SSL_SESSION_TICKETS)
+static void ssl_write_session_ticket_ext( ssl_context *ssl,
+                                          unsigned char *buf, size_t *olen )
+{
+    unsigned char *p = buf;
+    size_t tlen = ssl->session_negotiate->ticket_len;
+
+    if( ssl->session_tickets == SSL_SESSION_TICKETS_DISABLED )
+    {
+        *olen = 0;
+        return;
+    }
+
+    SSL_DEBUG_MSG( 3, ( "client hello, adding session ticket extension" ) );
+
+    *p++ = (unsigned char)( ( TLS_EXT_SESSION_TICKET >> 8 ) & 0xFF );
+    *p++ = (unsigned char)( ( TLS_EXT_SESSION_TICKET      ) & 0xFF );
+
+    *p++ = (unsigned char)( ( tlen >> 8 ) & 0xFF );
+    *p++ = (unsigned char)( ( tlen      ) & 0xFF );
+
+    *olen = 4;
+
+    if( ssl->session_negotiate->ticket == NULL ||
+        ssl->session_negotiate->ticket_len == 0 )
+    {
+        return;
+    }
+
+    SSL_DEBUG_MSG( 3, ( "sending session ticket of length %d", tlen ) );
+
+    memcpy( p, ssl->session_negotiate->ticket, tlen );
+
+    *olen += tlen;
+}
+#endif /* POLARSSL_SSL_SESSION_TICKETS */
+
+#if defined(POLARSSL_SSL_ALPN)
+static void ssl_write_alpn_ext( ssl_context *ssl,
+                                unsigned char *buf, size_t *olen )
+{
+    unsigned char *p = buf;
+    const char **cur;
+
+    if( ssl->alpn_list == NULL )
+    {
+        *olen = 0;
+        return;
+    }
+
+    SSL_DEBUG_MSG( 3, ( "client hello, adding alpn extension" ) );
+
+    *p++ = (unsigned char)( ( TLS_EXT_ALPN >> 8 ) & 0xFF );
+    *p++ = (unsigned char)( ( TLS_EXT_ALPN      ) & 0xFF );
+
+    /*
+     * opaque ProtocolName<1..2^8-1>;
+     *
+     * struct {
+     *     ProtocolName protocol_name_list<2..2^16-1>
+     * } ProtocolNameList;
+     */
+
+    /* Skip writing extension and list length for now */
+    p += 4;
+
+    for( cur = ssl->alpn_list; *cur != NULL; cur++ )
+    {
+        *p = (unsigned char)( strlen( *cur ) & 0xFF );
+        memcpy( p + 1, *cur, *p );
+        p += 1 + *p;
+    }
+
+    *olen = p - buf;
+
+    /* List length = olen - 2 (ext_type) - 2 (ext_len) - 2 (list_len) */
+    buf[4] = (unsigned char)( ( ( *olen - 6 ) >> 8 ) & 0xFF );
+    buf[5] = (unsigned char)( ( ( *olen - 6 )      ) & 0xFF );
+
+    /* Extension length = olen - 2 (ext_type) - 2 (ext_len) */
+    buf[2] = (unsigned char)( ( ( *olen - 4 ) >> 8 ) & 0xFF );
+    buf[3] = (unsigned char)( ( ( *olen - 4 )      ) & 0xFF );
+}
+#endif /* POLARSSL_SSL_ALPN */
+
+static int ssl_write_client_hello( ssl_context *ssl )
+{
+    int ret;
+    size_t i, n, olen, ext_len = 0;
+    unsigned char *buf;
+    unsigned char *p, *q;
+#if defined(POLARSSL_HAVE_TIME)
+    time_t t;
+#endif
+    const int *ciphersuites;
+    const ssl_ciphersuite_t *ciphersuite_info;
+
+    SSL_DEBUG_MSG( 2, ( "=> write client hello" ) );
+
+    if( ssl->f_rng == NULL )
+    {
+        SSL_DEBUG_MSG( 1, ( "no RNG provided") );
+        return( POLARSSL_ERR_SSL_NO_RNG );
+    }
+
+    if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE )
+    {
+        ssl->major_ver = ssl->min_major_ver;
+        ssl->minor_ver = ssl->min_minor_ver;
+    }
+
+    if( ssl->max_major_ver == 0 && ssl->max_minor_ver == 0 )
+    {
+        ssl->max_major_ver = SSL_MAX_MAJOR_VERSION;
+        ssl->max_minor_ver = SSL_MAX_MINOR_VERSION;
+    }
+
+    /*
+     *     0  .   0   handshake type
+     *     1  .   3   handshake length
+     *     4  .   5   highest version supported
+     *     6  .   9   current UNIX time
+     *    10  .  37   random bytes
+     */
+    buf = ssl->out_msg;
+    p = buf + 4;
+
+    *p++ = (unsigned char) ssl->max_major_ver;
+    *p++ = (unsigned char) ssl->max_minor_ver;
+
+    SSL_DEBUG_MSG( 3, ( "client hello, max version: [%d:%d]",
+                   buf[4], buf[5] ) );
+
+#if defined(POLARSSL_HAVE_TIME)
+    t = time( NULL );
+    *p++ = (unsigned char)( t >> 24 );
+    *p++ = (unsigned char)( t >> 16 );
+    *p++ = (unsigned char)( t >>  8 );
+    *p++ = (unsigned char)( t       );
+
+    SSL_DEBUG_MSG( 3, ( "client hello, current time: %lu", t ) );
+#else
+    if( ( ret = ssl->f_rng( ssl->p_rng, p, 4 ) ) != 0 )
+        return( ret );
+
+    p += 4;
+#endif /* POLARSSL_HAVE_TIME */
+
+    if( ( ret = ssl->f_rng( ssl->p_rng, p, 28 ) ) != 0 )
+        return( ret );
+
+    p += 28;
+
+    memcpy( ssl->handshake->randbytes, buf + 6, 32 );
+
+    SSL_DEBUG_BUF( 3, "client hello, random bytes", buf + 6, 32 );
+
+    /*
+     *    38  .  38   session id length
+     *    39  . 39+n  session id
+     *   40+n . 41+n  ciphersuitelist length
+     *   42+n . ..    ciphersuitelist
+     *   ..   . ..    compression methods length
+     *   ..   . ..    compression methods
+     *   ..   . ..    extensions length
+     *   ..   . ..    extensions
+     */
+    n = ssl->session_negotiate->length;
+
+    if( ssl->renegotiation != SSL_INITIAL_HANDSHAKE || n < 16 || n > 32 ||
+        ssl->handshake->resume == 0 )
+    {
+        n = 0;
+    }
+
+#if defined(POLARSSL_SSL_SESSION_TICKETS)
+    /*
+     * RFC 5077 section 3.4: "When presenting a ticket, the client MAY
+     * generate and include a Session ID in the TLS ClientHello."
+     */
+    if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE &&
+        ssl->session_negotiate->ticket != NULL &&
+        ssl->session_negotiate->ticket_len != 0 )
+    {
+        ret = ssl->f_rng( ssl->p_rng, ssl->session_negotiate->id, 32 );
+
+        if( ret != 0 )
+            return( ret );
+
+        ssl->session_negotiate->length = n = 32;
+    }
+#endif /* POLARSSL_SSL_SESSION_TICKETS */
+
+    *p++ = (unsigned char) n;
+
+    for( i = 0; i < n; i++ )
+        *p++ = ssl->session_negotiate->id[i];
+
+    SSL_DEBUG_MSG( 3, ( "client hello, session id len.: %d", n ) );
+    SSL_DEBUG_BUF( 3,   "client hello, session id", buf + 39, n );
+
+    ciphersuites = ssl->ciphersuite_list[ssl->minor_ver];
+    n = 0;
+    q = p;
+
+    // Skip writing ciphersuite length for now
+    p += 2;
+
+    /*
+     * Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV
+     */
+    if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE )
+    {
+        *p++ = (unsigned char)( SSL_EMPTY_RENEGOTIATION_INFO >> 8 );
+        *p++ = (unsigned char)( SSL_EMPTY_RENEGOTIATION_INFO      );
+        n++;
+    }
+
+    for( i = 0; ciphersuites[i] != 0; i++ )
+    {
+        ciphersuite_info = ssl_ciphersuite_from_id( ciphersuites[i] );
+
+        if( ciphersuite_info == NULL )
+            continue;
+
+        if( ciphersuite_info->min_minor_ver > ssl->max_minor_ver ||
+            ciphersuite_info->max_minor_ver < ssl->min_minor_ver )
+            continue;
+
+        SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %2d",
+                       ciphersuites[i] ) );
+
+        n++;
+        *p++ = (unsigned char)( ciphersuites[i] >> 8 );
+        *p++ = (unsigned char)( ciphersuites[i]      );
+    }
+
+    *q++ = (unsigned char)( n >> 7 );
+    *q++ = (unsigned char)( n << 1 );
+
+    SSL_DEBUG_MSG( 3, ( "client hello, got %d ciphersuites", n ) );
+
+
+#if defined(POLARSSL_ZLIB_SUPPORT)
+    SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 2 ) );
+    SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d %d",
+                        SSL_COMPRESS_DEFLATE, SSL_COMPRESS_NULL ) );
+
+    *p++ = 2;
+    *p++ = SSL_COMPRESS_DEFLATE;
+    *p++ = SSL_COMPRESS_NULL;
+#else
+    SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 1 ) );
+    SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d", SSL_COMPRESS_NULL ) );
+
+    *p++ = 1;
+    *p++ = SSL_COMPRESS_NULL;
+#endif /* POLARSSL_ZLIB_SUPPORT */
+
+    // First write extensions, then the total length
+    //
+#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
+    ssl_write_hostname_ext( ssl, p + 2 + ext_len, &olen );
+    ext_len += olen;
+#endif
+
+    ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen );
+    ext_len += olen;
+
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+    ssl_write_signature_algorithms_ext( ssl, p + 2 + ext_len, &olen );
+    ext_len += olen;
+#endif
+
+#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C)
+    ssl_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len, &olen );
+    ext_len += olen;
+
+    ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen );
+    ext_len += olen;
+#endif
+
+#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH)
+    ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen );
+    ext_len += olen;
+#endif
+
+#if defined(POLARSSL_SSL_TRUNCATED_HMAC)
+    ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len, &olen );
+    ext_len += olen;
+#endif
+
+#if defined(POLARSSL_SSL_SESSION_TICKETS)
+    ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, &olen );
+    ext_len += olen;
+#endif
+
+#if defined(POLARSSL_SSL_ALPN)
+    ssl_write_alpn_ext( ssl, p + 2 + ext_len, &olen );
+    ext_len += olen;
+#endif
+
+    SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %d",
+                   ext_len ) );
+
+    if( ext_len > 0 )
+    {
+        *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF );
+        *p++ = (unsigned char)( ( ext_len      ) & 0xFF );
+        p += ext_len;
+    }
+
+    ssl->out_msglen  = p - buf;
+    ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+    ssl->out_msg[0]  = SSL_HS_CLIENT_HELLO;
+
+    ssl->state++;
+
+    if( ( ret = ssl_write_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+        return( ret );
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= write client hello" ) );
+
+    return( 0 );
+}
+
+static int ssl_parse_renegotiation_info( ssl_context *ssl,
+                                         const unsigned char *buf,
+                                         size_t len )
+{
+    int ret;
+
+    if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE )
+    {
+        if( len != 1 || buf[0] != 0x0 )
+        {
+            SSL_DEBUG_MSG( 1, ( "non-zero length renegotiated connection field" ) );
+
+            if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
+                return( ret );
+
+            return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+        }
+
+        ssl->secure_renegotiation = SSL_SECURE_RENEGOTIATION;
+    }
+    else
+    {
+        /* Check verify-data in constant-time. The length OTOH is no secret */
+        if( len    != 1 + ssl->verify_data_len * 2 ||
+            buf[0] !=     ssl->verify_data_len * 2 ||
+            safer_memcmp( buf + 1,
+                          ssl->own_verify_data, ssl->verify_data_len ) != 0 ||
+            safer_memcmp( buf + 1 + ssl->verify_data_len,
+                          ssl->peer_verify_data, ssl->verify_data_len ) != 0 )
+        {
+            SSL_DEBUG_MSG( 1, ( "non-matching renegotiated connection field" ) );
+
+            if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
+                return( ret );
+
+            return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+        }
+    }
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH)
+static int ssl_parse_max_fragment_length_ext( ssl_context *ssl,
+                                              const unsigned char *buf,
+                                              size_t len )
+{
+    /*
+     * server should use the extension only if we did,
+     * and if so the server's value should match ours (and len is always 1)
+     */
+    if( ssl->mfl_code == SSL_MAX_FRAG_LEN_NONE ||
+        len != 1 ||
+        buf[0] != ssl->mfl_code )
+    {
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+    }
+
+    return( 0 );
+}
+#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */
+
+#if defined(POLARSSL_SSL_TRUNCATED_HMAC)
+static int ssl_parse_truncated_hmac_ext( ssl_context *ssl,
+                                         const unsigned char *buf,
+                                         size_t len )
+{
+    if( ssl->trunc_hmac == SSL_TRUNC_HMAC_DISABLED ||
+        len != 0 )
+    {
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+    }
+
+    ((void) buf);
+
+    ssl->session_negotiate->trunc_hmac = SSL_TRUNC_HMAC_ENABLED;
+
+    return( 0 );
+}
+#endif /* POLARSSL_SSL_TRUNCATED_HMAC */
+
+#if defined(POLARSSL_SSL_SESSION_TICKETS)
+static int ssl_parse_session_ticket_ext( ssl_context *ssl,
+                                         const unsigned char *buf,
+                                         size_t len )
+{
+    if( ssl->session_tickets == SSL_SESSION_TICKETS_DISABLED ||
+        len != 0 )
+    {
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+    }
+
+    ((void) buf);
+
+    ssl->handshake->new_session_ticket = 1;
+
+    return( 0 );
+}
+#endif /* POLARSSL_SSL_SESSION_TICKETS */
+
+#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C)
+static int ssl_parse_supported_point_formats_ext( ssl_context *ssl,
+                                                  const unsigned char *buf,
+                                                  size_t len )
+{
+    size_t list_size;
+    const unsigned char *p;
+
+    list_size = buf[0];
+    if( list_size + 1 != len )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+    }
+
+    p = buf + 2;
+    while( list_size > 0 )
+    {
+        if( p[0] == POLARSSL_ECP_PF_UNCOMPRESSED ||
+            p[0] == POLARSSL_ECP_PF_COMPRESSED )
+        {
+            ssl->handshake->ecdh_ctx.point_format = p[0];
+            SSL_DEBUG_MSG( 4, ( "point format selected: %d", p[0] ) );
+            return( 0 );
+        }
+
+        list_size--;
+        p++;
+    }
+
+    return( 0 );
+}
+#endif /* POLARSSL_ECDH_C || POLARSSL_ECDSA_C */
+
+#if defined(POLARSSL_SSL_ALPN)
+static int ssl_parse_alpn_ext( ssl_context *ssl,
+                               const unsigned char *buf, size_t len )
+{
+    size_t list_len, name_len;
+    const char **p;
+
+    /* If we didn't send it, the server shouldn't send it */
+    if( ssl->alpn_list == NULL )
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+
+    /*
+     * opaque ProtocolName<1..2^8-1>;
+     *
+     * struct {
+     *     ProtocolName protocol_name_list<2..2^16-1>
+     * } ProtocolNameList;
+     *
+     * the "ProtocolNameList" MUST contain exactly one "ProtocolName"
+     */
+
+    /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */
+    if( len < 4 )
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+
+    list_len = ( buf[0] << 8 ) | buf[1];
+    if( list_len != len - 2 )
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+
+    name_len = buf[2];
+    if( name_len != list_len - 1 )
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+
+    /* Check that the server chosen protocol was in our list and save it */
+    for( p = ssl->alpn_list; *p != NULL; p++ )
+    {
+        if( name_len == strlen( *p ) &&
+            memcmp( buf + 3, *p, name_len ) == 0 )
+        {
+            ssl->alpn_chosen = *p;
+            return( 0 );
+        }
+    }
+
+    return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+}
+#endif /* POLARSSL_SSL_ALPN */
+
+static int ssl_parse_server_hello( ssl_context *ssl )
+{
+    int ret, i, comp;
+    size_t n;
+    size_t ext_len = 0;
+    unsigned char *buf, *ext;
+    int renegotiation_info_seen = 0;
+    int handshake_failure = 0;
+#if defined(POLARSSL_DEBUG_C)
+    uint32_t t;
+#endif
+
+    SSL_DEBUG_MSG( 2, ( "=> parse server hello" ) );
+
+    /*
+     *     0  .   0   handshake type
+     *     1  .   3   handshake length
+     *     4  .   5   protocol version
+     *     6  .   9   UNIX time()
+     *    10  .  37   random bytes
+     */
+    buf = ssl->in_msg;
+
+    if( ( ret = ssl_read_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+        return( ret );
+    }
+
+    if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
+        return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+    }
+
+    SSL_DEBUG_MSG( 3, ( "server hello, chosen version: [%d:%d]",
+                   buf[4], buf[5] ) );
+
+    if( ssl->in_hslen < 42 ||
+        buf[0] != SSL_HS_SERVER_HELLO ||
+        buf[4] != SSL_MAJOR_VERSION_3 )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+    }
+
+    if( buf[5] > ssl->max_minor_ver )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+    }
+
+    ssl->minor_ver = buf[5];
+
+    if( ssl->minor_ver < ssl->min_minor_ver )
+    {
+        SSL_DEBUG_MSG( 1, ( "server only supports ssl smaller than minimum"
+                            " [%d:%d] < [%d:%d]", ssl->major_ver,
+                            ssl->minor_ver, buf[4], buf[5] ) );
+
+        ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL,
+                                     SSL_ALERT_MSG_PROTOCOL_VERSION );
+
+        return( POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION );
+    }
+
+#if defined(POLARSSL_DEBUG_C)
+    t = ( (uint32_t) buf[6] << 24 )
+      | ( (uint32_t) buf[7] << 16 )
+      | ( (uint32_t) buf[8] <<  8 )
+      | ( (uint32_t) buf[9]       );
+    SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) );
+#endif
+
+    memcpy( ssl->handshake->randbytes + 32, buf + 6, 32 );
+
+    n = buf[38];
+
+    SSL_DEBUG_BUF( 3,   "server hello, random bytes", buf + 6, 32 );
+
+    if( n > 32 )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+    }
+
+    /*
+     *    38  .  38   session id length
+     *    39  . 38+n  session id
+     *   39+n . 40+n  chosen ciphersuite
+     *   41+n . 41+n  chosen compression alg.
+     *   42+n . 43+n  extensions length
+     *   44+n . 44+n+m extensions
+     */
+    if( ssl->in_hslen > 42 + n )
+    {
+        ext_len = ( ( buf[42 + n] <<  8 )
+                  | ( buf[43 + n]       ) );
+
+        if( ( ext_len > 0 && ext_len < 4 ) ||
+            ssl->in_hslen != 44 + n + ext_len )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+        }
+    }
+
+    i = ( buf[39 + n] << 8 ) | buf[40 + n];
+    comp = buf[41 + n];
+
+    /*
+     * Initialize update checksum functions
+     */
+    ssl->transform_negotiate->ciphersuite_info = ssl_ciphersuite_from_id( i );
+
+    if( ssl->transform_negotiate->ciphersuite_info == NULL )
+    {
+        SSL_DEBUG_MSG( 1, ( "ciphersuite info for %04x not found", i ) );
+        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+    }
+
+    ssl_optimize_checksum( ssl, ssl->transform_negotiate->ciphersuite_info );
+
+    SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) );
+    SSL_DEBUG_BUF( 3,   "server hello, session id", buf + 39, n );
+
+    /*
+     * Check if the session can be resumed
+     */
+    if( ssl->renegotiation != SSL_INITIAL_HANDSHAKE ||
+        ssl->handshake->resume == 0 || n == 0 ||
+        ssl->session_negotiate->ciphersuite != i ||
+        ssl->session_negotiate->compression != comp ||
+        ssl->session_negotiate->length != n ||
+        memcmp( ssl->session_negotiate->id, buf + 39, n ) != 0 )
+    {
+        ssl->state++;
+        ssl->handshake->resume = 0;
+#if defined(POLARSSL_HAVE_TIME)
+        ssl->session_negotiate->start = time( NULL );
+#endif
+        ssl->session_negotiate->ciphersuite = i;
+        ssl->session_negotiate->compression = comp;
+        ssl->session_negotiate->length = n;
+        memcpy( ssl->session_negotiate->id, buf + 39, n );
+    }
+    else
+    {
+        ssl->state = SSL_SERVER_CHANGE_CIPHER_SPEC;
+
+        if( ( ret = ssl_derive_keys( ssl ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_derive_keys", ret );
+            return( ret );
+        }
+    }
+
+    SSL_DEBUG_MSG( 3, ( "%s session has been resumed",
+                   ssl->handshake->resume ? "a" : "no" ) );
+
+    SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %d", i ) );
+    SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", buf[41 + n] ) );
+
+    i = 0;
+    while( 1 )
+    {
+        if( ssl->ciphersuite_list[ssl->minor_ver][i] == 0 )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+        }
+
+        if( ssl->ciphersuite_list[ssl->minor_ver][i++] ==
+            ssl->session_negotiate->ciphersuite )
+        {
+            break;
+        }
+    }
+
+    if( comp != SSL_COMPRESS_NULL
+#if defined(POLARSSL_ZLIB_SUPPORT)
+        && comp != SSL_COMPRESS_DEFLATE
+#endif
+      )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+    }
+    ssl->session_negotiate->compression = comp;
+
+    ext = buf + 44 + n;
+
+    SSL_DEBUG_MSG( 2, ( "server hello, total extension length: %d", ext_len ) );
+
+    while( ext_len )
+    {
+        unsigned int ext_id   = ( ( ext[0] <<  8 )
+                                | ( ext[1]       ) );
+        unsigned int ext_size = ( ( ext[2] <<  8 )
+                                | ( ext[3]       ) );
+
+        if( ext_size + 4 > ext_len )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+        }
+
+        switch( ext_id )
+        {
+        case TLS_EXT_RENEGOTIATION_INFO:
+            SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) );
+            renegotiation_info_seen = 1;
+
+            if( ( ret = ssl_parse_renegotiation_info( ssl, ext + 4,
+                                                      ext_size ) ) != 0 )
+                return( ret );
+
+            break;
+
+#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH)
+        case TLS_EXT_MAX_FRAGMENT_LENGTH:
+            SSL_DEBUG_MSG( 3, ( "found max_fragment_length extension" ) );
+
+            if( ( ret = ssl_parse_max_fragment_length_ext( ssl,
+                            ext + 4, ext_size ) ) != 0 )
+            {
+                return( ret );
+            }
+
+            break;
+#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */
+
+#if defined(POLARSSL_SSL_TRUNCATED_HMAC)
+        case TLS_EXT_TRUNCATED_HMAC:
+            SSL_DEBUG_MSG( 3, ( "found truncated_hmac extension" ) );
+
+            if( ( ret = ssl_parse_truncated_hmac_ext( ssl,
+                            ext + 4, ext_size ) ) != 0 )
+            {
+                return( ret );
+            }
+
+            break;
+#endif /* POLARSSL_SSL_TRUNCATED_HMAC */
+
+#if defined(POLARSSL_SSL_SESSION_TICKETS)
+        case TLS_EXT_SESSION_TICKET:
+            SSL_DEBUG_MSG( 3, ( "found session_ticket extension" ) );
+
+            if( ( ret = ssl_parse_session_ticket_ext( ssl,
+                            ext + 4, ext_size ) ) != 0 )
+            {
+                return( ret );
+            }
+
+            break;
+#endif /* POLARSSL_SSL_SESSION_TICKETS */
+
+#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C)
+        case TLS_EXT_SUPPORTED_POINT_FORMATS:
+            SSL_DEBUG_MSG( 3, ( "found supported_point_formats extension" ) );
+
+            if( ( ret = ssl_parse_supported_point_formats_ext( ssl,
+                            ext + 4, ext_size ) ) != 0 )
+            {
+                return( ret );
+            }
+
+            break;
+#endif /* POLARSSL_ECDH_C || POLARSSL_ECDSA_C */
+
+#if defined(POLARSSL_SSL_ALPN)
+        case TLS_EXT_ALPN:
+            SSL_DEBUG_MSG( 3, ( "found alpn extension" ) );
+
+            if( ( ret = ssl_parse_alpn_ext( ssl, ext + 4, ext_size ) ) != 0 )
+                return( ret );
+
+            break;
+#endif /* POLARSSL_SSL_ALPN */
+
+        default:
+            SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)",
+                           ext_id ) );
+        }
+
+        ext_len -= 4 + ext_size;
+        ext += 4 + ext_size;
+
+        if( ext_len > 0 && ext_len < 4 )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+        }
+    }
+
+    /*
+     * Renegotiation security checks
+     */
+    if( ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION &&
+        ssl->allow_legacy_renegotiation == SSL_LEGACY_BREAK_HANDSHAKE )
+    {
+        SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) );
+        handshake_failure = 1;
+    }
+    else if( ssl->renegotiation == SSL_RENEGOTIATION &&
+             ssl->secure_renegotiation == SSL_SECURE_RENEGOTIATION &&
+             renegotiation_info_seen == 0 )
+    {
+        SSL_DEBUG_MSG( 1, ( "renegotiation_info extension missing (secure)" ) );
+        handshake_failure = 1;
+    }
+    else if( ssl->renegotiation == SSL_RENEGOTIATION &&
+             ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION &&
+             ssl->allow_legacy_renegotiation == SSL_LEGACY_NO_RENEGOTIATION )
+    {
+        SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) );
+        handshake_failure = 1;
+    }
+    else if( ssl->renegotiation == SSL_RENEGOTIATION &&
+             ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION &&
+             renegotiation_info_seen == 1 )
+    {
+        SSL_DEBUG_MSG( 1, ( "renegotiation_info extension present (legacy)" ) );
+        handshake_failure = 1;
+    }
+
+    if( handshake_failure == 1 )
+    {
+        if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
+            return( ret );
+
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= parse server hello" ) );
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) ||                       \
+    defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED)
+static int ssl_parse_server_dh_params( ssl_context *ssl, unsigned char **p,
+                                       unsigned char *end )
+{
+    int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
+
+    /*
+     * Ephemeral DH parameters:
+     *
+     * struct {
+     *     opaque dh_p<1..2^16-1>;
+     *     opaque dh_g<1..2^16-1>;
+     *     opaque dh_Ys<1..2^16-1>;
+     * } ServerDHParams;
+     */
+    if( ( ret = dhm_read_params( &ssl->handshake->dhm_ctx, p, end ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 2, ( "dhm_read_params" ), ret );
+        return( ret );
+    }
+
+    if( ssl->handshake->dhm_ctx.len < 64  ||
+        ssl->handshake->dhm_ctx.len > 512 )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad server key exchange message (DHM length)" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+    }
+
+    SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P  );
+    SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G  );
+    SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY );
+
+    return( ret );
+}
+#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */
+
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ||                   \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) ||                     \
+    defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||                      \
+    defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+static int ssl_check_server_ecdh_params( const ssl_context *ssl )
+{
+    const ecp_curve_info *curve_info;
+
+    curve_info = ecp_curve_info_from_grp_id( ssl->handshake->ecdh_ctx.grp.id );
+    if( curve_info == NULL )
+    {
+        SSL_DEBUG_MSG( 1, ( "Should never happen" ) );
+        return( -1 );
+    }
+
+    SSL_DEBUG_MSG( 2, ( "ECDH curve: %s", curve_info->name ) );
+
+#if defined(POLARSSL_SSL_ECP_SET_CURVES)
+    if( ! ssl_curve_is_acceptable( ssl, ssl->handshake->ecdh_ctx.grp.id ) )
+#else
+    if( ssl->handshake->ecdh_ctx.grp.nbits < 163 ||
+        ssl->handshake->ecdh_ctx.grp.nbits > 521 )
+#endif
+        return( -1 );
+
+    SSL_DEBUG_ECP( 3, "ECDH: Qp", &ssl->handshake->ecdh_ctx.Qp );
+
+    return( 0 );
+}
+#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
+
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ||                   \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
+static int ssl_parse_server_ecdh_params( ssl_context *ssl,
+                                         unsigned char **p,
+                                         unsigned char *end )
+{
+    int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
+
+    /*
+     * Ephemeral ECDH parameters:
+     *
+     * struct {
+     *     ECParameters curve_params;
+     *     ECPoint      public;
+     * } ServerECDHParams;
+     */
+    if( ( ret = ecdh_read_params( &ssl->handshake->ecdh_ctx,
+                                  (const unsigned char **) p, end ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, ( "ecdh_read_params" ), ret );
+        return( ret );
+    }
+
+    if( ssl_check_server_ecdh_params( ssl ) != 0 )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad server key exchange message (ECDHE curve)" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+    }
+
+    return( ret );
+}
+#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
+
+#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
+static int ssl_parse_server_psk_hint( ssl_context *ssl,
+                                      unsigned char **p,
+                                      unsigned char *end )
+{
+    int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
+    size_t  len;
+    ((void) ssl);
+
+    /*
+     * PSK parameters:
+     *
+     * opaque psk_identity_hint<0..2^16-1>;
+     */
+    len = (*p)[0] << 8 | (*p)[1];
+    *p += 2;
+
+    if( (*p) + len > end )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad server key exchange message (psk_identity_hint length)" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+    }
+
+    // TODO: Retrieve PSK identity hint and callback to app
+    //
+    *p += len;
+    ret = 0;
+
+    return( ret );
+}
+#endif /* POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED */
+
+#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) ||                           \
+    defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED)
+/*
+ * Generate a pre-master secret and encrypt it with the server's RSA key
+ */
+static int ssl_write_encrypted_pms( ssl_context *ssl,
+                                    size_t offset, size_t *olen,
+                                    size_t pms_offset )
+{
+    int ret;
+    size_t len_bytes = ssl->minor_ver == SSL_MINOR_VERSION_0 ? 0 : 2;
+    unsigned char *p = ssl->handshake->premaster + pms_offset;
+
+    /*
+     * Generate (part of) the pre-master as
+     *  struct {
+     *      ProtocolVersion client_version;
+     *      opaque random[46];
+     *  } PreMasterSecret;
+     */
+    p[0] = (unsigned char) ssl->max_major_ver;
+    p[1] = (unsigned char) ssl->max_minor_ver;
+
+    if( ( ret = ssl->f_rng( ssl->p_rng, p + 2, 46 ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "f_rng", ret );
+        return( ret );
+    }
+
+    ssl->handshake->pmslen = 48;
+
+    /*
+     * Now write it out, encrypted
+     */
+    if( ! pk_can_do( &ssl->session_negotiate->peer_cert->pk,
+                POLARSSL_PK_RSA ) )
+    {
+        SSL_DEBUG_MSG( 1, ( "certificate key type mismatch" ) );
+        return( POLARSSL_ERR_SSL_PK_TYPE_MISMATCH );
+    }
+
+    if( ( ret = pk_encrypt( &ssl->session_negotiate->peer_cert->pk,
+                            p, ssl->handshake->pmslen,
+                            ssl->out_msg + offset + len_bytes, olen,
+                            SSL_MAX_CONTENT_LEN - offset - len_bytes,
+                            ssl->f_rng, ssl->p_rng ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "rsa_pkcs1_encrypt", ret );
+        return( ret );
+    }
+
+#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_2)
+    if( len_bytes == 2 )
+    {
+        ssl->out_msg[offset+0] = (unsigned char)( *olen >> 8 );
+        ssl->out_msg[offset+1] = (unsigned char)( *olen      );
+        *olen += 2;
+    }
+#endif
+
+    return( 0 );
+}
+#endif /* POLARSSL_KEY_EXCHANGE_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED */
+
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) ||                       \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+static int ssl_parse_signature_algorithm( ssl_context *ssl,
+                                          unsigned char **p,
+                                          unsigned char *end,
+                                          md_type_t *md_alg,
+                                          pk_type_t *pk_alg )
+{
+    ((void) ssl);
+    *md_alg = POLARSSL_MD_NONE;
+    *pk_alg = POLARSSL_PK_NONE;
+
+    /* Only in TLS 1.2 */
+    if( ssl->minor_ver != SSL_MINOR_VERSION_3 )
+    {
+        return( 0 );
+    }
+
+    if( (*p) + 2 > end )
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+
+    /*
+     * Get hash algorithm
+     */
+    if( ( *md_alg = ssl_md_alg_from_hash( (*p)[0] ) ) == POLARSSL_MD_NONE )
+    {
+        SSL_DEBUG_MSG( 2, ( "Server used unsupported "
+                            "HashAlgorithm %d", *(p)[0] ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+    }
+
+    /*
+     * Get signature algorithm
+     */
+    if( ( *pk_alg = ssl_pk_alg_from_sig( (*p)[1] ) ) == POLARSSL_PK_NONE )
+    {
+        SSL_DEBUG_MSG( 2, ( "server used unsupported "
+                            "SignatureAlgorithm %d", (*p)[1] ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+    }
+
+    SSL_DEBUG_MSG( 2, ( "Server used SignatureAlgorithm %d", (*p)[1] ) );
+    SSL_DEBUG_MSG( 2, ( "Server used HashAlgorithm %d", (*p)[0] ) );
+    *p += 2;
+
+    return( 0 );
+}
+#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
+
+
+#if defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
+    defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+static int ssl_get_ecdh_params_from_cert( ssl_context *ssl )
+{
+    int ret;
+    const ecp_keypair *peer_key;
+
+    if( ! pk_can_do( &ssl->session_negotiate->peer_cert->pk,
+                     POLARSSL_PK_ECKEY ) )
+    {
+        SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) );
+        return( POLARSSL_ERR_SSL_PK_TYPE_MISMATCH );
+    }
+
+    peer_key = pk_ec( ssl->session_negotiate->peer_cert->pk );
+
+    if( ( ret = ecdh_get_params( &ssl->handshake->ecdh_ctx, peer_key,
+                                 POLARSSL_ECDH_THEIRS ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, ( "ecdh_get_params" ), ret );
+        return( ret );
+    }
+
+    if( ssl_check_server_ecdh_params( ssl ) != 0 )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad server certificate (ECDH curve)" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE );
+    }
+
+    return( ret );
+}
+#endif /* POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||
+          POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
+
+static int ssl_parse_server_key_exchange( ssl_context *ssl )
+{
+    int ret;
+    const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
+    unsigned char *p, *end;
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) ||                       \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+    size_t sig_len, params_len;
+    unsigned char hash[64];
+    md_type_t md_alg = POLARSSL_MD_NONE;
+    size_t hashlen;
+    pk_type_t pk_alg = POLARSSL_PK_NONE;
+#endif
+
+    SSL_DEBUG_MSG( 2, ( "=> parse server key exchange" ) );
+
+#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED)
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA )
+    {
+        SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) );
+        ssl->state++;
+        return( 0 );
+    }
+    ((void) p);
+    ((void) end);
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
+    defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_RSA ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_ECDSA )
+    {
+        if( ( ret = ssl_get_ecdh_params_from_cert( ssl ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_get_ecdh_params_from_cert", ret );
+            return( ret );
+        }
+
+        SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) );
+        ssl->state++;
+        return( 0 );
+    }
+    ((void) p);
+    ((void) end);
+#endif /* POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
+
+    if( ( ret = ssl_read_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+        return( ret );
+    }
+
+    if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
+        return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+    }
+
+    /*
+     * ServerKeyExchange may be skipped with PSK and RSA-PSK when the server
+     * doesn't use a psk_identity_hint
+     */
+    if( ssl->in_msg[0] != SSL_HS_SERVER_KEY_EXCHANGE )
+    {
+        if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ||
+            ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK )
+        {
+            ssl->record_read = 1;
+            goto exit;
+        }
+
+        SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
+        return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+    }
+
+    p   = ssl->in_msg + 4;
+    end = ssl->in_msg + ssl->in_hslen;
+    SSL_DEBUG_BUF( 3,   "server key exchange", p, ssl->in_hslen - 4 );
+
+#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK )
+    {
+        if( ssl_parse_server_psk_hint( ssl, &p, end ) != 0 )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+        }
+    } /* FALLTROUGH */
+#endif /* POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED */
+
+#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) ||                       \
+    defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED)
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK )
+        ; /* nothing more to do */
+    else
+#endif /* POLARSSL_KEY_EXCHANGE_PSK_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED */
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) ||                       \
+    defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED)
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_RSA ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK )
+    {
+        if( ssl_parse_server_dh_params( ssl, &p, end ) != 0 )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+        }
+    }
+    else
+#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) ||                     \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA )
+    {
+        if( ssl_parse_server_ecdh_params( ssl, &p, end ) != 0 )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+        }
+    }
+    else
+#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
+    {
+        SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+        return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+    }
+
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) ||                       \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_RSA ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA )
+    {
+        params_len = p - ( ssl->in_msg + 4 );
+
+        /*
+         * Handle the digitally-signed structure
+         */
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+        if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
+        {
+            if( ssl_parse_signature_algorithm( ssl, &p, end,
+                                               &md_alg, &pk_alg ) != 0 )
+            {
+                SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
+                return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+            }
+
+            if( pk_alg != ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ) )
+            {
+                SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
+                return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+            }
+        }
+        else
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
+#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_1)
+        if( ssl->minor_ver < SSL_MINOR_VERSION_3 )
+        {
+            pk_alg = ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info );
+
+            /* Default hash for ECDSA is SHA-1 */
+            if( pk_alg == POLARSSL_PK_ECDSA && md_alg == POLARSSL_MD_NONE )
+                md_alg = POLARSSL_MD_SHA1;
+        }
+        else
+#endif
+        {
+            SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+            return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+        }
+
+        /*
+         * Read signature
+         */
+        sig_len = ( p[0] << 8 ) | p[1];
+        p += 2;
+
+        if( end != p + sig_len )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+        }
+
+        SSL_DEBUG_BUF( 3, "signature", p, sig_len );
+
+        /*
+         * Compute the hash that has been signed
+         */
+#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_1)
+        if( md_alg == POLARSSL_MD_NONE )
+        {
+            md5_context md5;
+            sha1_context sha1;
+
+            hashlen = 36;
+
+            /*
+             * digitally-signed struct {
+             *     opaque md5_hash[16];
+             *     opaque sha_hash[20];
+             * };
+             *
+             * md5_hash
+             *     MD5(ClientHello.random + ServerHello.random
+             *                            + ServerParams);
+             * sha_hash
+             *     SHA(ClientHello.random + ServerHello.random
+             *                            + ServerParams);
+             */
+            md5_starts( &md5 );
+            md5_update( &md5, ssl->handshake->randbytes, 64 );
+            md5_update( &md5, ssl->in_msg + 4, params_len );
+            md5_finish( &md5, hash );
+
+            sha1_starts( &sha1 );
+            sha1_update( &sha1, ssl->handshake->randbytes, 64 );
+            sha1_update( &sha1, ssl->in_msg + 4, params_len );
+            sha1_finish( &sha1, hash + 16 );
+        }
+        else
+#endif /* POLARSSL_SSL_PROTO_SSL3 || POLARSSL_SSL_PROTO_TLS1 || \
+          POLARSSL_SSL_PROTO_TLS1_1 */
+#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_2)
+        if( md_alg != POLARSSL_MD_NONE )
+        {
+            md_context_t ctx;
+
+            /* Info from md_alg will be used instead */
+            hashlen = 0;
+
+            /*
+             * digitally-signed struct {
+             *     opaque client_random[32];
+             *     opaque server_random[32];
+             *     ServerDHParams params;
+             * };
+             */
+            if( ( ret = md_init_ctx( &ctx,
+                                     md_info_from_type( md_alg ) ) ) != 0 )
+            {
+                SSL_DEBUG_RET( 1, "md_init_ctx", ret );
+                return( ret );
+            }
+
+            md_starts( &ctx );
+            md_update( &ctx, ssl->handshake->randbytes, 64 );
+            md_update( &ctx, ssl->in_msg + 4, params_len );
+            md_finish( &ctx, hash );
+            md_free_ctx( &ctx );
+        }
+        else
+#endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 || \
+          POLARSSL_SSL_PROTO_TLS1_2 */
+        {
+            SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+            return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+        }
+
+        SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen :
+                (unsigned int) ( md_info_from_type( md_alg ) )->size );
+
+        /*
+         * Verify signature
+         */
+        if( ! pk_can_do( &ssl->session_negotiate->peer_cert->pk, pk_alg ) )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
+            return( POLARSSL_ERR_SSL_PK_TYPE_MISMATCH );
+        }
+
+        if( ( ret = pk_verify( &ssl->session_negotiate->peer_cert->pk,
+                               md_alg, hash, hashlen, p, sig_len ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "pk_verify", ret );
+            return( ret );
+        }
+    }
+#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
+
+exit:
+    ssl->state++;
+
+    SSL_DEBUG_MSG( 2, ( "<= parse server key exchange" ) );
+
+    return( 0 );
+}
+
+#if !defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED)       && \
+    !defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED)   && \
+    !defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \
+    !defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+static int ssl_parse_certificate_request( ssl_context *ssl )
+{
+    int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
+    const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
+
+    SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) );
+
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK )
+    {
+        SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) );
+        ssl->state++;
+        return( 0 );
+    }
+
+    SSL_DEBUG_MSG( 1, ( "should not happen" ) );
+    return( ret );
+}
+#else
+static int ssl_parse_certificate_request( ssl_context *ssl )
+{
+    int ret;
+    unsigned char *buf, *p;
+    size_t n = 0, m = 0;
+    size_t cert_type_len = 0, dn_len = 0;
+    const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
+
+    SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) );
+
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK )
+    {
+        SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) );
+        ssl->state++;
+        return( 0 );
+    }
+
+    /*
+     *     0  .   0   handshake type
+     *     1  .   3   handshake length
+     *     4  .   4   cert type count
+     *     5  .. m-1  cert types
+     *     m  .. m+1  sig alg length (TLS 1.2 only)
+     *    m+1 .. n-1  SignatureAndHashAlgorithms (TLS 1.2 only)
+     *     n  .. n+1  length of all DNs
+     *    n+2 .. n+3  length of DN 1
+     *    n+4 .. ...  Distinguished Name #1
+     *    ... .. ...  length of DN 2, etc.
+     */
+    if( ssl->record_read == 0 )
+    {
+        if( ( ret = ssl_read_record( ssl ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+            return( ret );
+        }
+
+        if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
+            return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+        }
+
+        ssl->record_read = 1;
+    }
+
+    ssl->client_auth = 0;
+    ssl->state++;
+
+    if( ssl->in_msg[0] == SSL_HS_CERTIFICATE_REQUEST )
+        ssl->client_auth++;
+
+    SSL_DEBUG_MSG( 3, ( "got %s certificate request",
+                        ssl->client_auth ? "a" : "no" ) );
+
+    if( ssl->client_auth == 0 )
+        goto exit;
+
+    ssl->record_read = 0;
+
+    // TODO: handshake_failure alert for an anonymous server to request
+    // client authentication
+
+    buf = ssl->in_msg;
+
+    // Retrieve cert types
+    //
+    cert_type_len = buf[4];
+    n = cert_type_len;
+
+    if( ssl->in_hslen < 6 + n )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST );
+    }
+
+    p = buf + 5;
+    while( cert_type_len > 0 )
+    {
+#if defined(POLARSSL_RSA_C)
+        if( *p == SSL_CERT_TYPE_RSA_SIGN &&
+            pk_can_do( ssl_own_key( ssl ), POLARSSL_PK_RSA ) )
+        {
+            ssl->handshake->cert_type = SSL_CERT_TYPE_RSA_SIGN;
+            break;
+        }
+        else
+#endif
+#if defined(POLARSSL_ECDSA_C)
+        if( *p == SSL_CERT_TYPE_ECDSA_SIGN &&
+            pk_can_do( ssl_own_key( ssl ), POLARSSL_PK_ECDSA ) )
+        {
+            ssl->handshake->cert_type = SSL_CERT_TYPE_ECDSA_SIGN;
+            break;
+        }
+        else
+#endif
+        {
+            ; /* Unsupported cert type, ignore */
+        }
+
+        cert_type_len--;
+        p++;
+    }
+
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+    if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
+    {
+        /* Ignored, see comments about hash in write_certificate_verify */
+        // TODO: should check the signature part against our pk_key though
+        size_t sig_alg_len = ( ( buf[5 + n] <<  8 )
+                             | ( buf[6 + n]       ) );
+
+        p = buf + 7 + n;
+        m += 2;
+        n += sig_alg_len;
+
+        if( ssl->in_hslen < 6 + n )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST );
+        }
+    }
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
+
+    /* Ignore certificate_authorities, we only have one cert anyway */
+    // TODO: should not send cert if no CA matches
+    dn_len = ( ( buf[5 + m + n] <<  8 )
+             | ( buf[6 + m + n]       ) );
+
+    n += dn_len;
+    if( ssl->in_hslen != 7 + m + n )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST );
+    }
+
+exit:
+    SSL_DEBUG_MSG( 2, ( "<= parse certificate request" ) );
+
+    return( 0 );
+}
+#endif /* !POLARSSL_KEY_EXCHANGE_RSA_ENABLED &&
+          !POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED &&
+          !POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED &&
+          !POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
+
+static int ssl_parse_server_hello_done( ssl_context *ssl )
+{
+    int ret;
+
+    SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) );
+
+    if( ssl->record_read == 0 )
+    {
+        if( ( ret = ssl_read_record( ssl ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+            return( ret );
+        }
+
+        if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) );
+            return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+        }
+    }
+    ssl->record_read = 0;
+
+    if( ssl->in_hslen  != 4 ||
+        ssl->in_msg[0] != SSL_HS_SERVER_HELLO_DONE )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE );
+    }
+
+    ssl->state++;
+
+    SSL_DEBUG_MSG( 2, ( "<= parse server hello done" ) );
+
+    return( 0 );
+}
+
+static int ssl_write_client_key_exchange( ssl_context *ssl )
+{
+    int ret;
+    size_t i, n;
+    const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
+
+    SSL_DEBUG_MSG( 2, ( "=> write client key exchange" ) );
+
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED)
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_RSA )
+    {
+        /*
+         * DHM key exchange -- send G^X mod P
+         */
+        n = ssl->handshake->dhm_ctx.len;
+
+        ssl->out_msg[4] = (unsigned char)( n >> 8 );
+        ssl->out_msg[5] = (unsigned char)( n      );
+        i = 6;
+
+        ret = dhm_make_public( &ssl->handshake->dhm_ctx,
+                                (int) mpi_size( &ssl->handshake->dhm_ctx.P ),
+                               &ssl->out_msg[i], n,
+                                ssl->f_rng, ssl->p_rng );
+        if( ret != 0 )
+        {
+            SSL_DEBUG_RET( 1, "dhm_make_public", ret );
+            return( ret );
+        }
+
+        SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X  );
+        SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX );
+
+        ssl->handshake->pmslen = ssl->handshake->dhm_ctx.len;
+
+        if( ( ret = dhm_calc_secret( &ssl->handshake->dhm_ctx,
+                                      ssl->handshake->premaster,
+                                     &ssl->handshake->pmslen,
+                                      ssl->f_rng, ssl->p_rng ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "dhm_calc_secret", ret );
+            return( ret );
+        }
+
+        SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K  );
+    }
+    else
+#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED */
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ||                   \
+    defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||                      \
+    defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_RSA ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_ECDSA )
+    {
+        /*
+         * ECDH key exchange -- send client public value
+         */
+        i = 4;
+
+        ret = ecdh_make_public( &ssl->handshake->ecdh_ctx,
+                                &n,
+                                &ssl->out_msg[i], 1000,
+                                ssl->f_rng, ssl->p_rng );
+        if( ret != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ecdh_make_public", ret );
+            return( ret );
+        }
+
+        SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q );
+
+        if( ( ret = ecdh_calc_secret( &ssl->handshake->ecdh_ctx,
+                                      &ssl->handshake->pmslen,
+                                       ssl->handshake->premaster,
+                                       POLARSSL_MPI_MAX_SIZE,
+                                       ssl->f_rng, ssl->p_rng ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ecdh_calc_secret", ret );
+            return( ret );
+        }
+
+        SSL_DEBUG_MPI( 3, "ECDH: z", &ssl->handshake->ecdh_ctx.z );
+    }
+    else
+#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
+#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK )
+    {
+        /*
+         * opaque psk_identity<0..2^16-1>;
+         */
+        if( ssl->psk == NULL || ssl->psk_identity == NULL )
+            return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED );
+
+        i = 4;
+        n = ssl->psk_identity_len;
+        ssl->out_msg[i++] = (unsigned char)( n >> 8 );
+        ssl->out_msg[i++] = (unsigned char)( n      );
+
+        memcpy( ssl->out_msg + i, ssl->psk_identity, ssl->psk_identity_len );
+        i += ssl->psk_identity_len;
+
+#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED)
+        if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK )
+        {
+            n = 0;
+        }
+        else
+#endif
+#if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED)
+        if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK )
+        {
+            if( ( ret = ssl_write_encrypted_pms( ssl, i, &n, 2 ) ) != 0 )
+                return( ret );
+        }
+        else
+#endif
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED)
+        if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK )
+        {
+            /*
+             * ClientDiffieHellmanPublic public (DHM send G^X mod P)
+             */
+            n = ssl->handshake->dhm_ctx.len;
+            ssl->out_msg[i++] = (unsigned char)( n >> 8 );
+            ssl->out_msg[i++] = (unsigned char)( n      );
+
+            ret = dhm_make_public( &ssl->handshake->dhm_ctx,
+                    (int) mpi_size( &ssl->handshake->dhm_ctx.P ),
+                    &ssl->out_msg[i], n,
+                    ssl->f_rng, ssl->p_rng );
+            if( ret != 0 )
+            {
+                SSL_DEBUG_RET( 1, "dhm_make_public", ret );
+                return( ret );
+            }
+        }
+        else
+#endif /* POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
+        if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK )
+        {
+            /*
+             * ClientECDiffieHellmanPublic public;
+             */
+            ret = ecdh_make_public( &ssl->handshake->ecdh_ctx, &n,
+                    &ssl->out_msg[i], SSL_MAX_CONTENT_LEN - i,
+                    ssl->f_rng, ssl->p_rng );
+            if( ret != 0 )
+            {
+                SSL_DEBUG_RET( 1, "ecdh_make_public", ret );
+                return( ret );
+            }
+
+            SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q );
+        }
+        else
+#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
+        {
+            SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+            return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+        }
+
+        if( ( ret = ssl_psk_derive_premaster( ssl,
+                        ciphersuite_info->key_exchange ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_psk_derive_premaster", ret );
+            return( ret );
+        }
+    }
+    else
+#endif /* POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED */
+#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED)
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA )
+    {
+        i = 4;
+        if( ( ret = ssl_write_encrypted_pms( ssl, i, &n, 0 ) ) != 0 )
+            return( ret );
+    }
+    else
+#endif /* POLARSSL_KEY_EXCHANGE_RSA_ENABLED */
+    {
+        ((void) ciphersuite_info);
+        SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+        return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+    }
+
+    if( ( ret = ssl_derive_keys( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_derive_keys", ret );
+        return( ret );
+    }
+
+    ssl->out_msglen  = i + n;
+    ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+    ssl->out_msg[0]  = SSL_HS_CLIENT_KEY_EXCHANGE;
+
+    ssl->state++;
+
+    if( ( ret = ssl_write_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+        return( ret );
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= write client key exchange" ) );
+
+    return( 0 );
+}
+
+#if !defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED)       && \
+    !defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED)   && \
+    !defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \
+    !defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+static int ssl_write_certificate_verify( ssl_context *ssl )
+{
+    int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
+    const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
+
+    SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) );
+
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK )
+    {
+        SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) );
+        ssl->state++;
+        return( 0 );
+    }
+
+    SSL_DEBUG_MSG( 1, ( "should not happen" ) );
+    return( ret );
+}
+#else
+static int ssl_write_certificate_verify( ssl_context *ssl )
+{
+    int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
+    const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
+    size_t n = 0, offset = 0;
+    unsigned char hash[48];
+    unsigned char *hash_start = hash;
+    md_type_t md_alg = POLARSSL_MD_NONE;
+    unsigned int hashlen;
+
+    SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) );
+
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK )
+    {
+        SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) );
+        ssl->state++;
+        return( 0 );
+    }
+
+    if( ssl->client_auth == 0 || ssl_own_cert( ssl ) == NULL )
+    {
+        SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) );
+        ssl->state++;
+        return( 0 );
+    }
+
+    if( ssl_own_key( ssl ) == NULL )
+    {
+        SSL_DEBUG_MSG( 1, ( "got no private key" ) );
+        return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED );
+    }
+
+    /*
+     * Make an RSA signature of the handshake digests
+     */
+    ssl->handshake->calc_verify( ssl, hash );
+
+#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_1)
+    if( ssl->minor_ver != SSL_MINOR_VERSION_3 )
+    {
+        /*
+         * digitally-signed struct {
+         *     opaque md5_hash[16];
+         *     opaque sha_hash[20];
+         * };
+         *
+         * md5_hash
+         *     MD5(handshake_messages);
+         *
+         * sha_hash
+         *     SHA(handshake_messages);
+         */
+        hashlen = 36;
+        md_alg = POLARSSL_MD_NONE;
+
+        /*
+         * For ECDSA, default hash is SHA-1 only
+         */
+        if( pk_can_do( ssl_own_key( ssl ), POLARSSL_PK_ECDSA ) )
+        {
+            hash_start += 16;
+            hashlen -= 16;
+            md_alg = POLARSSL_MD_SHA1;
+        }
+    }
+    else
+#endif /* POLARSSL_SSL_PROTO_SSL3 || POLARSSL_SSL_PROTO_TLS1 || \
+          POLARSSL_SSL_PROTO_TLS1_1 */
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+    if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
+    {
+        /*
+         * digitally-signed struct {
+         *     opaque handshake_messages[handshake_messages_length];
+         * };
+         *
+         * Taking shortcut here. We assume that the server always allows the
+         * PRF Hash function and has sent it in the allowed signature
+         * algorithms list received in the Certificate Request message.
+         *
+         * Until we encounter a server that does not, we will take this
+         * shortcut.
+         *
+         * Reason: Otherwise we should have running hashes for SHA512 and SHA224
+         *         in order to satisfy 'weird' needs from the server side.
+         */
+        if( ssl->transform_negotiate->ciphersuite_info->mac ==
+            POLARSSL_MD_SHA384 )
+        {
+            md_alg = POLARSSL_MD_SHA384;
+            ssl->out_msg[4] = SSL_HASH_SHA384;
+        }
+        else
+        {
+            md_alg = POLARSSL_MD_SHA256;
+            ssl->out_msg[4] = SSL_HASH_SHA256;
+        }
+        ssl->out_msg[5] = ssl_sig_from_pk( ssl_own_key( ssl ) );
+
+        /* Info from md_alg will be used instead */
+        hashlen = 0;
+        offset = 2;
+    }
+    else
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
+    {
+        SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+        return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+    }
+
+    if( ( ret = pk_sign( ssl_own_key( ssl ), md_alg, hash_start, hashlen,
+                         ssl->out_msg + 6 + offset, &n,
+                         ssl->f_rng, ssl->p_rng ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "pk_sign", ret );
+        return( ret );
+    }
+
+    ssl->out_msg[4 + offset] = (unsigned char)( n >> 8 );
+    ssl->out_msg[5 + offset] = (unsigned char)( n      );
+
+    ssl->out_msglen  = 6 + n + offset;
+    ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+    ssl->out_msg[0]  = SSL_HS_CERTIFICATE_VERIFY;
+
+    ssl->state++;
+
+    if( ( ret = ssl_write_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+        return( ret );
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= write certificate verify" ) );
+
+    return( ret );
+}
+#endif /* !POLARSSL_KEY_EXCHANGE_RSA_ENABLED &&
+          !POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED &&
+          !POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED */
+
+#if defined(POLARSSL_SSL_SESSION_TICKETS)
+static int ssl_parse_new_session_ticket( ssl_context *ssl )
+{
+    int ret;
+    uint32_t lifetime;
+    size_t ticket_len;
+    unsigned char *ticket;
+
+    SSL_DEBUG_MSG( 2, ( "=> parse new session ticket" ) );
+
+    if( ( ret = ssl_read_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+        return( ret );
+    }
+
+    if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) );
+        return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+    }
+
+    /*
+     * struct {
+     *     uint32 ticket_lifetime_hint;
+     *     opaque ticket<0..2^16-1>;
+     * } NewSessionTicket;
+     *
+     * 0  .  0   handshake message type
+     * 1  .  3   handshake message length
+     * 4  .  7   ticket_lifetime_hint
+     * 8  .  9   ticket_len (n)
+     * 10 .  9+n ticket content
+     */
+    if( ssl->in_msg[0] != SSL_HS_NEW_SESSION_TICKET ||
+        ssl->in_hslen < 10 )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_NEW_SESSION_TICKET );
+    }
+
+    lifetime = ( ssl->in_msg[4] << 24 ) | ( ssl->in_msg[5] << 16 ) |
+               ( ssl->in_msg[6] <<  8 ) | ( ssl->in_msg[7]       );
+
+    ticket_len = ( ssl->in_msg[8] << 8 ) | ( ssl->in_msg[9] );
+
+    if( ticket_len + 10 != ssl->in_hslen )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_NEW_SESSION_TICKET );
+    }
+
+    SSL_DEBUG_MSG( 3, ( "ticket length: %d", ticket_len ) );
+
+    /* We're not waiting for a NewSessionTicket message any more */
+    ssl->handshake->new_session_ticket = 0;
+
+    /*
+     * Zero-length ticket means the server changed his mind and doesn't want
+     * to send a ticket after all, so just forget it
+     */
+    if( ticket_len == 0)
+        return( 0 );
+
+    polarssl_free( ssl->session_negotiate->ticket );
+    ssl->session_negotiate->ticket = NULL;
+    ssl->session_negotiate->ticket_len = 0;
+
+    if( ( ticket = polarssl_malloc( ticket_len ) ) == NULL )
+    {
+        SSL_DEBUG_MSG( 1, ( "ticket malloc failed" ) );
+        return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+    }
+
+    memcpy( ticket, ssl->in_msg + 10, ticket_len );
+
+    ssl->session_negotiate->ticket = ticket;
+    ssl->session_negotiate->ticket_len = ticket_len;
+    ssl->session_negotiate->ticket_lifetime = lifetime;
+
+    /*
+     * RFC 5077 section 3.4:
+     * "If the client receives a session ticket from the server, then it
+     * discards any Session ID that was sent in the ServerHello."
+     */
+    SSL_DEBUG_MSG( 3, ( "ticket in use, discarding session id" ) );
+    ssl->session_negotiate->length = 0;
+
+    SSL_DEBUG_MSG( 2, ( "<= parse new session ticket" ) );
+
+    return( 0 );
+}
+#endif /* POLARSSL_SSL_SESSION_TICKETS */
+
+/*
+ * SSL handshake -- client side -- single step
+ */
+int ssl_handshake_client_step( ssl_context *ssl )
+{
+    int ret = 0;
+
+    if( ssl->state == SSL_HANDSHAKE_OVER )
+        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+    SSL_DEBUG_MSG( 2, ( "client state: %d", ssl->state ) );
+
+    if( ( ret = ssl_flush_output( ssl ) ) != 0 )
+        return( ret );
+
+    switch( ssl->state )
+    {
+        case SSL_HELLO_REQUEST:
+            ssl->state = SSL_CLIENT_HELLO;
+            break;
+
+       /*
+        *  ==>   ClientHello
+        */
+       case SSL_CLIENT_HELLO:
+           ret = ssl_write_client_hello( ssl );
+           break;
+
+       /*
+        *  <==   ServerHello
+        *        Certificate
+        *      ( ServerKeyExchange  )
+        *      ( CertificateRequest )
+        *        ServerHelloDone
+        */
+       case SSL_SERVER_HELLO:
+           ret = ssl_parse_server_hello( ssl );
+           break;
+
+       case SSL_SERVER_CERTIFICATE:
+           ret = ssl_parse_certificate( ssl );
+           break;
+
+       case SSL_SERVER_KEY_EXCHANGE:
+           ret = ssl_parse_server_key_exchange( ssl );
+           break;
+
+       case SSL_CERTIFICATE_REQUEST:
+           ret = ssl_parse_certificate_request( ssl );
+           break;
+
+       case SSL_SERVER_HELLO_DONE:
+           ret = ssl_parse_server_hello_done( ssl );
+           break;
+
+       /*
+        *  ==> ( Certificate/Alert  )
+        *        ClientKeyExchange
+        *      ( CertificateVerify  )
+        *        ChangeCipherSpec
+        *        Finished
+        */
+       case SSL_CLIENT_CERTIFICATE:
+           ret = ssl_write_certificate( ssl );
+           break;
+
+       case SSL_CLIENT_KEY_EXCHANGE:
+           ret = ssl_write_client_key_exchange( ssl );
+           break;
+
+       case SSL_CERTIFICATE_VERIFY:
+           ret = ssl_write_certificate_verify( ssl );
+           break;
+
+       case SSL_CLIENT_CHANGE_CIPHER_SPEC:
+           ret = ssl_write_change_cipher_spec( ssl );
+           break;
+
+       case SSL_CLIENT_FINISHED:
+           ret = ssl_write_finished( ssl );
+           break;
+
+       /*
+        *  <==   ( NewSessionTicket )
+        *        ChangeCipherSpec
+        *        Finished
+        */
+       case SSL_SERVER_CHANGE_CIPHER_SPEC:
+#if defined(POLARSSL_SSL_SESSION_TICKETS)
+           if( ssl->handshake->new_session_ticket != 0 )
+               ret = ssl_parse_new_session_ticket( ssl );
+           else
+#endif
+               ret = ssl_parse_change_cipher_spec( ssl );
+           break;
+
+       case SSL_SERVER_FINISHED:
+           ret = ssl_parse_finished( ssl );
+           break;
+
+       case SSL_FLUSH_BUFFERS:
+           SSL_DEBUG_MSG( 2, ( "handshake: done" ) );
+           ssl->state = SSL_HANDSHAKE_WRAPUP;
+           break;
+
+       case SSL_HANDSHAKE_WRAPUP:
+           ssl_handshake_wrapup( ssl );
+           break;
+
+       default:
+           SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) );
+           return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+   }
+
+    return( ret );
+}
+#endif /* POLARSSL_SSL_CLI_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/ssl_srv.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,3289 @@
+/*
+ *  SSLv3/TLSv1 server-side functions
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_SSL_SRV_C)
+
+#include "polarssl/debug.h"
+#include "polarssl/ssl.h"
+#if defined(POLARSSL_ECP_C)
+#include "polarssl/ecp.h"
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#if defined(POLARSSL_HAVE_TIME)
+#include <time.h>
+#endif
+
+#if defined(POLARSSL_SSL_SESSION_TICKETS)
+/*
+ * Serialize a session in the following format:
+ *  0   .   n-1     session structure, n = sizeof(ssl_session)
+ *  n   .   n+2     peer_cert length = m (0 if no certificate)
+ *  n+3 .   n+2+m   peer cert ASN.1
+ *
+ *  Assumes ticket is NULL (always true on server side).
+ */
+static int ssl_save_session( const ssl_session *session,
+                             unsigned char *buf, size_t buf_len,
+                             size_t *olen )
+{
+    unsigned char *p = buf;
+    size_t left = buf_len;
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+    size_t cert_len;
+#endif /* POLARSSL_X509_CRT_PARSE_C */
+
+    if( left < sizeof( ssl_session ) )
+        return( -1 );
+
+    memcpy( p, session, sizeof( ssl_session ) );
+    p += sizeof( ssl_session );
+    left -= sizeof( ssl_session );
+
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+    if( session->peer_cert == NULL )
+        cert_len = 0;
+    else
+        cert_len = session->peer_cert->raw.len;
+
+    if( left < 3 + cert_len )
+        return( -1 );
+
+    *p++ = (unsigned char)( cert_len >> 16 & 0xFF );
+    *p++ = (unsigned char)( cert_len >>  8 & 0xFF );
+    *p++ = (unsigned char)( cert_len       & 0xFF );
+
+    if( session->peer_cert != NULL )
+        memcpy( p, session->peer_cert->raw.p, cert_len );
+
+    p += cert_len;
+#endif /* POLARSSL_X509_CRT_PARSE_C */
+
+    *olen = p - buf;
+
+    return( 0 );
+}
+
+/*
+ * Unserialise session, see ssl_save_session()
+ */
+static int ssl_load_session( ssl_session *session,
+                             const unsigned char *buf, size_t len )
+{
+    const unsigned char *p = buf;
+    const unsigned char * const end = buf + len;
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+    size_t cert_len;
+#endif /* POLARSSL_X509_CRT_PARSE_C */
+
+    if( p + sizeof( ssl_session ) > end )
+        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+    memcpy( session, p, sizeof( ssl_session ) );
+    p += sizeof( ssl_session );
+
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+    if( p + 3 > end )
+        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+    cert_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2];
+    p += 3;
+
+    if( cert_len == 0 )
+    {
+        session->peer_cert = NULL;
+    }
+    else
+    {
+        int ret;
+
+        if( p + cert_len > end )
+            return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+        session->peer_cert = polarssl_malloc( sizeof( x509_crt ) );
+
+        if( session->peer_cert == NULL )
+            return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+
+        x509_crt_init( session->peer_cert );
+
+        if( ( ret = x509_crt_parse( session->peer_cert, p, cert_len ) ) != 0 )
+        {
+            x509_crt_free( session->peer_cert );
+            polarssl_free( session->peer_cert );
+            session->peer_cert = NULL;
+            return( ret );
+        }
+
+        p += cert_len;
+    }
+#endif /* POLARSSL_X509_CRT_PARSE_C */
+
+    if( p != end )
+        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+    return( 0 );
+}
+
+/*
+ * Create session ticket, secured as recommended in RFC 5077 section 4:
+ *
+ *    struct {
+ *        opaque key_name[16];
+ *        opaque iv[16];
+ *        opaque encrypted_state<0..2^16-1>;
+ *        opaque mac[32];
+ *    } ticket;
+ *
+ * (the internal state structure differs, however).
+ */
+static int ssl_write_ticket( ssl_context *ssl, size_t *tlen )
+{
+    int ret;
+    unsigned char * const start = ssl->out_msg + 10;
+    unsigned char *p = start;
+    unsigned char *state;
+    unsigned char iv[16];
+    size_t clear_len, enc_len, pad_len, i;
+
+    *tlen = 0;
+
+    if( ssl->ticket_keys == NULL )
+        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+    /* Write key name */
+    memcpy( p, ssl->ticket_keys->key_name, 16 );
+    p += 16;
+
+    /* Generate and write IV (with a copy for aes_crypt) */
+    if( ( ret = ssl->f_rng( ssl->p_rng, p, 16 ) ) != 0 )
+        return( ret );
+    memcpy( iv, p, 16 );
+    p += 16;
+
+    /*
+     * Dump session state
+     *
+     * After the session state itself, we still need room for 16 bytes of
+     * padding and 32 bytes of MAC, so there's only so much room left
+     */
+    state = p + 2;
+    if( ssl_save_session( ssl->session_negotiate, state,
+                          SSL_MAX_CONTENT_LEN - (state - ssl->out_ctr) - 48,
+                          &clear_len ) != 0 )
+    {
+        return( POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE );
+    }
+    SSL_DEBUG_BUF( 3, "session ticket cleartext", state, clear_len );
+
+    /* Apply PKCS padding */
+    pad_len = 16 - clear_len % 16;
+    enc_len = clear_len + pad_len;
+    for( i = clear_len; i < enc_len; i++ )
+        state[i] = (unsigned char) pad_len;
+
+    /* Encrypt */
+    if( ( ret = aes_crypt_cbc( &ssl->ticket_keys->enc, AES_ENCRYPT,
+                               enc_len, iv, state, state ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    /* Write length */
+    *p++ = (unsigned char)( ( enc_len >> 8 ) & 0xFF );
+    *p++ = (unsigned char)( ( enc_len      ) & 0xFF );
+    p = state + enc_len;
+
+    /* Compute and write MAC( key_name + iv + enc_state_len + enc_state ) */
+    sha256_hmac( ssl->ticket_keys->mac_key, 16, start, p - start, p, 0 );
+    p += 32;
+
+    *tlen = p - start;
+
+    SSL_DEBUG_BUF( 3, "session ticket structure", start, *tlen );
+
+    return( 0 );
+}
+
+/*
+ * Load session ticket (see ssl_write_ticket for structure)
+ */
+static int ssl_parse_ticket( ssl_context *ssl,
+                             unsigned char *buf,
+                             size_t len )
+{
+    int ret;
+    ssl_session session;
+    unsigned char *key_name = buf;
+    unsigned char *iv = buf + 16;
+    unsigned char *enc_len_p = iv + 16;
+    unsigned char *ticket = enc_len_p + 2;
+    unsigned char *mac;
+    unsigned char computed_mac[32];
+    size_t enc_len, clear_len, i;
+    unsigned char pad_len, diff;
+
+    SSL_DEBUG_BUF( 3, "session ticket structure", buf, len );
+
+    if( len < 34 || ssl->ticket_keys == NULL )
+        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+    enc_len = ( enc_len_p[0] << 8 ) | enc_len_p[1];
+    mac = ticket + enc_len;
+
+    if( len != enc_len + 66 )
+        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+    /* Check name, in constant time though it's not a big secret */
+    diff = 0;
+    for( i = 0; i < 16; i++ )
+        diff |= key_name[i] ^ ssl->ticket_keys->key_name[i];
+    /* don't return yet, check the MAC anyway */
+
+    /* Check mac, with constant-time buffer comparison */
+    sha256_hmac( ssl->ticket_keys->mac_key, 16, buf, len - 32,
+                 computed_mac, 0 );
+
+    for( i = 0; i < 32; i++ )
+        diff |= mac[i] ^ computed_mac[i];
+
+    /* Now return if ticket is not authentic, since we want to avoid
+     * decrypting arbitrary attacker-chosen data */
+    if( diff != 0 )
+        return( POLARSSL_ERR_SSL_INVALID_MAC );
+
+    /* Decrypt */
+    if( ( ret = aes_crypt_cbc( &ssl->ticket_keys->dec, AES_DECRYPT,
+                               enc_len, iv, ticket, ticket ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    /* Check PKCS padding */
+    pad_len = ticket[enc_len - 1];
+
+    ret = 0;
+    for( i = 2; i < pad_len; i++ )
+        if( ticket[enc_len - i] != pad_len )
+            ret = POLARSSL_ERR_SSL_BAD_INPUT_DATA;
+    if( ret != 0 )
+        return( ret );
+
+    clear_len = enc_len - pad_len;
+
+    SSL_DEBUG_BUF( 3, "session ticket cleartext", ticket, clear_len );
+
+    /* Actually load session */
+    if( ( ret = ssl_load_session( &session, ticket, clear_len ) ) != 0 )
+    {
+        SSL_DEBUG_MSG( 1, ( "failed to parse ticket content" ) );
+        ssl_session_free( &session );
+        return( ret );
+    }
+
+#if defined(POLARSSL_HAVE_TIME)
+    /* Check if still valid */
+    if( (int) ( time( NULL) - session.start ) > ssl->ticket_lifetime )
+    {
+        SSL_DEBUG_MSG( 1, ( "session ticket expired" ) );
+        ssl_session_free( &session );
+        return( POLARSSL_ERR_SSL_SESSION_TICKET_EXPIRED );
+    }
+#endif
+
+    /*
+     * Keep the session ID sent by the client, since we MUST send it back to
+     * inform him we're accepting the ticket  (RFC 5077 section 3.4)
+     */
+    session.length = ssl->session_negotiate->length;
+    memcpy( &session.id, ssl->session_negotiate->id, session.length );
+
+    ssl_session_free( ssl->session_negotiate );
+    memcpy( ssl->session_negotiate, &session, sizeof( ssl_session ) );
+    memset( &session, 0, sizeof( ssl_session ) );
+
+    return( 0 );
+}
+#endif /* POLARSSL_SSL_SESSION_TICKETS */
+
+#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
+/*
+ * Wrapper around f_sni, allowing use of ssl_set_own_cert() but
+ * making it act on ssl->hanshake->sni_key_cert instead.
+ */
+static int ssl_sni_wrapper( ssl_context *ssl,
+                            const unsigned char* name, size_t len )
+{
+    int ret;
+    ssl_key_cert *key_cert_ori = ssl->key_cert;
+
+    ssl->key_cert = NULL;
+    ret = ssl->f_sni( ssl->p_sni, ssl, name, len );
+    ssl->handshake->sni_key_cert = ssl->key_cert;
+
+    ssl->key_cert = key_cert_ori;
+
+    return( ret );
+}
+
+static int ssl_parse_servername_ext( ssl_context *ssl,
+                                     const unsigned char *buf,
+                                     size_t len )
+{
+    int ret;
+    size_t servername_list_size, hostname_len;
+    const unsigned char *p;
+
+    SSL_DEBUG_MSG( 3, ( "parse ServerName extension" ) );
+
+    servername_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
+    if( servername_list_size + 2 != len )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+    }
+
+    p = buf + 2;
+    while( servername_list_size > 0 )
+    {
+        hostname_len = ( ( p[1] << 8 ) | p[2] );
+        if( hostname_len + 3 > servername_list_size )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+        }
+
+        if( p[0] == TLS_EXT_SERVERNAME_HOSTNAME )
+        {
+            ret = ssl_sni_wrapper( ssl, p + 3, hostname_len );
+            if( ret != 0 )
+            {
+                SSL_DEBUG_RET( 1, "ssl_sni_wrapper", ret );
+                ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL,
+                        SSL_ALERT_MSG_UNRECOGNIZED_NAME );
+                return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+            }
+            return( 0 );
+        }
+
+        servername_list_size -= hostname_len + 3;
+        p += hostname_len + 3;
+    }
+
+    if( servername_list_size != 0 )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+    }
+
+    return( 0 );
+}
+#endif /* POLARSSL_SSL_SERVER_NAME_INDICATION */
+
+static int ssl_parse_renegotiation_info( ssl_context *ssl,
+                                         const unsigned char *buf,
+                                         size_t len )
+{
+    int ret;
+
+    if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE )
+    {
+        if( len != 1 || buf[0] != 0x0 )
+        {
+            SSL_DEBUG_MSG( 1, ( "non-zero length renegotiated connection field" ) );
+
+            if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
+                return( ret );
+
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+        }
+
+        ssl->secure_renegotiation = SSL_SECURE_RENEGOTIATION;
+    }
+    else
+    {
+        /* Check verify-data in constant-time. The length OTOH is no secret */
+        if( len    != 1 + ssl->verify_data_len ||
+            buf[0] !=     ssl->verify_data_len ||
+            safer_memcmp( buf + 1, ssl->peer_verify_data,
+                          ssl->verify_data_len ) != 0 )
+        {
+            SSL_DEBUG_MSG( 1, ( "non-matching renegotiated connection field" ) );
+
+            if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
+                return( ret );
+
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+        }
+    }
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+static int ssl_parse_signature_algorithms_ext( ssl_context *ssl,
+                                               const unsigned char *buf,
+                                               size_t len )
+{
+    size_t sig_alg_list_size;
+    const unsigned char *p;
+
+    sig_alg_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
+    if( sig_alg_list_size + 2 != len ||
+        sig_alg_list_size %2 != 0 )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+    }
+
+    p = buf + 2;
+    while( sig_alg_list_size > 0 )
+    {
+        /*
+         * For now, just ignore signature algorithm and rely on offered
+         * ciphersuites only. To be fixed later.
+         */
+#if defined(POLARSSL_SHA512_C)
+        if( p[0] == SSL_HASH_SHA512 )
+        {
+            ssl->handshake->sig_alg = SSL_HASH_SHA512;
+            break;
+        }
+        if( p[0] == SSL_HASH_SHA384 )
+        {
+            ssl->handshake->sig_alg = SSL_HASH_SHA384;
+            break;
+        }
+#endif /* POLARSSL_SHA512_C */
+#if defined(POLARSSL_SHA256_C)
+        if( p[0] == SSL_HASH_SHA256 )
+        {
+            ssl->handshake->sig_alg = SSL_HASH_SHA256;
+            break;
+        }
+        if( p[0] == SSL_HASH_SHA224 )
+        {
+            ssl->handshake->sig_alg = SSL_HASH_SHA224;
+            break;
+        }
+#endif /* POLARSSL_SHA256_C */
+        if( p[0] == SSL_HASH_SHA1 )
+        {
+            ssl->handshake->sig_alg = SSL_HASH_SHA1;
+            break;
+        }
+        if( p[0] == SSL_HASH_MD5 )
+        {
+            ssl->handshake->sig_alg = SSL_HASH_MD5;
+            break;
+        }
+
+        sig_alg_list_size -= 2;
+        p += 2;
+    }
+
+    SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: %d",
+                   ssl->handshake->sig_alg ) );
+
+    return( 0 );
+}
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
+
+#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C)
+static int ssl_parse_supported_elliptic_curves( ssl_context *ssl,
+                                                const unsigned char *buf,
+                                                size_t len )
+{
+    size_t list_size, our_size;
+    const unsigned char *p;
+    const ecp_curve_info *curve_info, **curves;
+
+    list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
+    if( list_size + 2 != len ||
+        list_size % 2 != 0 )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+    }
+
+    /* Don't allow our peer to make us allocate too much memory,
+     * and leave room for a final 0 */
+    our_size = list_size / 2 + 1;
+    if( our_size > POLARSSL_ECP_DP_MAX )
+        our_size = POLARSSL_ECP_DP_MAX;
+
+    if( ( curves = polarssl_malloc( our_size * sizeof( *curves ) ) ) == NULL )
+        return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+
+    /* explicit void pointer cast for buggy MS compiler */
+    memset( (void *) curves, 0, our_size * sizeof( *curves ) );
+    ssl->handshake->curves = curves;
+
+    p = buf + 2;
+    while( list_size > 0 && our_size > 1 )
+    {
+        curve_info = ecp_curve_info_from_tls_id( ( p[0] << 8 ) | p[1] );
+
+        if( curve_info != NULL )
+        {
+            *curves++ = curve_info;
+            our_size--;
+        }
+
+        list_size -= 2;
+        p += 2;
+    }
+
+    return( 0 );
+}
+
+static int ssl_parse_supported_point_formats( ssl_context *ssl,
+                                              const unsigned char *buf,
+                                              size_t len )
+{
+    size_t list_size;
+    const unsigned char *p;
+
+    list_size = buf[0];
+    if( list_size + 1 != len )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+    }
+
+    p = buf + 2;
+    while( list_size > 0 )
+    {
+        if( p[0] == POLARSSL_ECP_PF_UNCOMPRESSED ||
+            p[0] == POLARSSL_ECP_PF_COMPRESSED )
+        {
+            ssl->handshake->ecdh_ctx.point_format = p[0];
+            SSL_DEBUG_MSG( 4, ( "point format selected: %d", p[0] ) );
+            return( 0 );
+        }
+
+        list_size--;
+        p++;
+    }
+
+    return( 0 );
+}
+#endif /* POLARSSL_ECDH_C || POLARSSL_ECDSA_C */
+
+#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH)
+static int ssl_parse_max_fragment_length_ext( ssl_context *ssl,
+                                              const unsigned char *buf,
+                                              size_t len )
+{
+    if( len != 1 || buf[0] >= SSL_MAX_FRAG_LEN_INVALID )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+    }
+
+    ssl->session_negotiate->mfl_code = buf[0];
+
+    return( 0 );
+}
+#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */
+
+#if defined(POLARSSL_SSL_TRUNCATED_HMAC)
+static int ssl_parse_truncated_hmac_ext( ssl_context *ssl,
+                                         const unsigned char *buf,
+                                         size_t len )
+{
+    if( len != 0 )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+    }
+
+    ((void) buf);
+
+    ssl->session_negotiate->trunc_hmac = SSL_TRUNC_HMAC_ENABLED;
+
+    return( 0 );
+}
+#endif /* POLARSSL_SSL_TRUNCATED_HMAC */
+
+#if defined(POLARSSL_SSL_SESSION_TICKETS)
+static int ssl_parse_session_ticket_ext( ssl_context *ssl,
+                                         unsigned char *buf,
+                                         size_t len )
+{
+    int ret;
+
+    if( ssl->session_tickets == SSL_SESSION_TICKETS_DISABLED )
+        return( 0 );
+
+    /* Remember the client asked us to send a new ticket */
+    ssl->handshake->new_session_ticket = 1;
+
+    SSL_DEBUG_MSG( 3, ( "ticket length: %d", len ) );
+
+    if( len == 0 )
+        return( 0 );
+
+    if( ssl->renegotiation != SSL_INITIAL_HANDSHAKE )
+    {
+        SSL_DEBUG_MSG( 3, ( "ticket rejected: renegotiating" ) );
+        return( 0 );
+    }
+
+    /*
+     * Failures are ok: just ignore the ticket and proceed.
+     */
+    if( ( ret = ssl_parse_ticket( ssl, buf, len ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_parse_ticket", ret );
+        return( 0 );
+    }
+
+    SSL_DEBUG_MSG( 3, ( "session successfully restored from ticket" ) );
+
+    ssl->handshake->resume = 1;
+
+    /* Don't send a new ticket after all, this one is OK */
+    ssl->handshake->new_session_ticket = 0;
+
+    return( 0 );
+}
+#endif /* POLARSSL_SSL_SESSION_TICKETS */
+
+#if defined(POLARSSL_SSL_ALPN)
+static int ssl_parse_alpn_ext( ssl_context *ssl,
+                               unsigned char *buf, size_t len )
+{
+    size_t list_len, cur_len;
+    const unsigned char *theirs, *start, *end;
+    const char **ours;
+
+    /* If ALPN not configured, just ignore the extension */
+    if( ssl->alpn_list == NULL )
+        return( 0 );
+
+    /*
+     * opaque ProtocolName<1..2^8-1>;
+     *
+     * struct {
+     *     ProtocolName protocol_name_list<2..2^16-1>
+     * } ProtocolNameList;
+     */
+
+    /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */
+    if( len < 4 )
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+
+    list_len = ( buf[0] << 8 ) | buf[1];
+    if( list_len != len - 2 )
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+
+    /*
+     * Use our order of preference
+     */
+    start = buf + 2;
+    end = buf + len;
+    for( ours = ssl->alpn_list; *ours != NULL; ours++ )
+    {
+        for( theirs = start; theirs != end; theirs += cur_len )
+        {
+            /* If the list is well formed, we should get equality first */
+            if( theirs > end )
+                return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+
+            cur_len = *theirs++;
+
+            /* Empty strings MUST NOT be included */
+            if( cur_len == 0 )
+                return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+
+            if( cur_len == strlen( *ours ) &&
+                memcmp( theirs, *ours, cur_len ) == 0 )
+            {
+                ssl->alpn_chosen = *ours;
+                return( 0 );
+            }
+        }
+    }
+
+    /* If we get there, no match was found */
+    ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL,
+                            SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL );
+    return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+}
+#endif /* POLARSSL_SSL_ALPN */
+
+/*
+ * Auxiliary functions for ServerHello parsing and related actions
+ */
+
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+/*
+ * Return 1 if the given EC key uses the given curve, 0 otherwise
+ */
+#if defined(POLARSSL_ECDSA_C)
+static int ssl_key_matches_curves( pk_context *pk,
+                                   const ecp_curve_info **curves )
+{
+    const ecp_curve_info **crv = curves;
+    ecp_group_id grp_id = pk_ec( *pk )->grp.id;
+
+    while( *crv != NULL )
+    {
+        if( (*crv)->grp_id == grp_id )
+            return( 1 );
+        crv++;
+    }
+
+    return( 0 );
+}
+#endif /* POLARSSL_ECDSA_C */
+
+/*
+ * Try picking a certificate for this ciphersuite,
+ * return 0 on success and -1 on failure.
+ */
+static int ssl_pick_cert( ssl_context *ssl,
+                          const ssl_ciphersuite_t * ciphersuite_info )
+{
+    ssl_key_cert *cur, *list;
+    pk_type_t pk_alg = ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info );
+
+#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
+    if( ssl->handshake->sni_key_cert != NULL )
+        list = ssl->handshake->sni_key_cert;
+    else
+#endif
+        list = ssl->handshake->key_cert;
+
+    if( pk_alg == POLARSSL_PK_NONE )
+        return( 0 );
+
+    for( cur = list; cur != NULL; cur = cur->next )
+    {
+        if( ! pk_can_do( cur->key, pk_alg ) )
+            continue;
+
+        /*
+         * This avoids sending the client a cert it'll reject based on
+         * keyUsage or other extensions.
+         *
+         * It also allows the user to provision different certificates for
+         * different uses based on keyUsage, eg if they want to avoid signing
+         * and decrypting with the same RSA key.
+         */
+        if( ssl_check_cert_usage( cur->cert, ciphersuite_info,
+                                  SSL_IS_SERVER ) != 0 )
+        {
+            continue;
+        }
+
+#if defined(POLARSSL_ECDSA_C)
+        if( pk_alg == POLARSSL_PK_ECDSA )
+        {
+            if( ssl_key_matches_curves( cur->key, ssl->handshake->curves ) )
+                break;
+        }
+        else
+#endif
+            break;
+    }
+
+    if( cur == NULL )
+        return( -1 );
+
+    ssl->handshake->key_cert = cur;
+    return( 0 );
+}
+#endif /* POLARSSL_X509_CRT_PARSE_C */
+
+/*
+ * Check if a given ciphersuite is suitable for use with our config/keys/etc
+ * Sets ciphersuite_info only if the suite matches.
+ */
+static int ssl_ciphersuite_match( ssl_context *ssl, int suite_id,
+                                  const ssl_ciphersuite_t **ciphersuite_info )
+{
+    const ssl_ciphersuite_t *suite_info;
+
+    suite_info = ssl_ciphersuite_from_id( suite_id );
+    if( suite_info == NULL )
+    {
+        SSL_DEBUG_MSG( 1, ( "ciphersuite info for %04x not found", suite_id ) );
+        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+    }
+
+    if( suite_info->min_minor_ver > ssl->minor_ver ||
+        suite_info->max_minor_ver < ssl->minor_ver )
+        return( 0 );
+
+#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C)
+    if( ssl_ciphersuite_uses_ec( suite_info ) &&
+        ( ssl->handshake->curves == NULL ||
+          ssl->handshake->curves[0] == NULL ) )
+        return( 0 );
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
+    /* If the ciphersuite requires a pre-shared key and we don't
+     * have one, skip it now rather than failing later */
+    if( ssl_ciphersuite_uses_psk( suite_info ) &&
+        ssl->f_psk == NULL &&
+        ( ssl->psk == NULL || ssl->psk_identity == NULL ||
+          ssl->psk_identity_len == 0 || ssl->psk_len == 0 ) )
+        return( 0 );
+#endif
+
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+    /*
+     * Final check: if ciphersuite requires us to have a
+     * certificate/key of a particular type:
+     * - select the appropriate certificate if we have one, or
+     * - try the next ciphersuite if we don't
+     * This must be done last since we modify the key_cert list.
+     */
+    if( ssl_pick_cert( ssl, suite_info ) != 0 )
+        return( 0 );
+#endif
+
+    *ciphersuite_info = suite_info;
+    return( 0 );
+}
+
+#if defined(POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO)
+static int ssl_parse_client_hello_v2( ssl_context *ssl )
+{
+    int ret;
+    unsigned int i, j;
+    size_t n;
+    unsigned int ciph_len, sess_len, chal_len;
+    unsigned char *buf, *p;
+    const int *ciphersuites;
+    const ssl_ciphersuite_t *ciphersuite_info;
+
+    SSL_DEBUG_MSG( 2, ( "=> parse client hello v2" ) );
+
+    if( ssl->renegotiation != SSL_INITIAL_HANDSHAKE )
+    {
+        SSL_DEBUG_MSG( 1, ( "client hello v2 illegal for renegotiation" ) );
+
+        if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
+            return( ret );
+
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+    }
+
+    buf = ssl->in_hdr;
+
+    SSL_DEBUG_BUF( 4, "record header", buf, 5 );
+
+    SSL_DEBUG_MSG( 3, ( "client hello v2, message type: %d",
+                   buf[2] ) );
+    SSL_DEBUG_MSG( 3, ( "client hello v2, message len.: %d",
+                   ( ( buf[0] & 0x7F ) << 8 ) | buf[1] ) );
+    SSL_DEBUG_MSG( 3, ( "client hello v2, max. version: [%d:%d]",
+                   buf[3], buf[4] ) );
+
+    /*
+     * SSLv2 Client Hello
+     *
+     * Record layer:
+     *     0  .   1   message length
+     *
+     * SSL layer:
+     *     2  .   2   message type
+     *     3  .   4   protocol version
+     */
+    if( buf[2] != SSL_HS_CLIENT_HELLO ||
+        buf[3] != SSL_MAJOR_VERSION_3 )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+    }
+
+    n = ( ( buf[0] << 8 ) | buf[1] ) & 0x7FFF;
+
+    if( n < 17 || n > 512 )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+    }
+
+    ssl->major_ver = SSL_MAJOR_VERSION_3;
+    ssl->minor_ver = ( buf[4] <= ssl->max_minor_ver )
+                     ? buf[4]  : ssl->max_minor_ver;
+
+    if( ssl->minor_ver < ssl->min_minor_ver )
+    {
+        SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum"
+                            " [%d:%d] < [%d:%d]",
+                            ssl->major_ver, ssl->minor_ver,
+                            ssl->min_major_ver, ssl->min_minor_ver ) );
+
+        ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL,
+                                     SSL_ALERT_MSG_PROTOCOL_VERSION );
+        return( POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION );
+    }
+
+    ssl->handshake->max_major_ver = buf[3];
+    ssl->handshake->max_minor_ver = buf[4];
+
+    if( ( ret = ssl_fetch_input( ssl, 2 + n ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_fetch_input", ret );
+        return( ret );
+    }
+
+    ssl->handshake->update_checksum( ssl, buf + 2, n );
+
+    buf = ssl->in_msg;
+    n = ssl->in_left - 5;
+
+    /*
+     *    0  .   1   ciphersuitelist length
+     *    2  .   3   session id length
+     *    4  .   5   challenge length
+     *    6  .  ..   ciphersuitelist
+     *   ..  .  ..   session id
+     *   ..  .  ..   challenge
+     */
+    SSL_DEBUG_BUF( 4, "record contents", buf, n );
+
+    ciph_len = ( buf[0] << 8 ) | buf[1];
+    sess_len = ( buf[2] << 8 ) | buf[3];
+    chal_len = ( buf[4] << 8 ) | buf[5];
+
+    SSL_DEBUG_MSG( 3, ( "ciph_len: %d, sess_len: %d, chal_len: %d",
+                   ciph_len, sess_len, chal_len ) );
+
+    /*
+     * Make sure each parameter length is valid
+     */
+    if( ciph_len < 3 || ( ciph_len % 3 ) != 0 )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+    }
+
+    if( sess_len > 32 )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+    }
+
+    if( chal_len < 8 || chal_len > 32 )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+    }
+
+    if( n != 6 + ciph_len + sess_len + chal_len )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+    }
+
+    SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist",
+                   buf + 6, ciph_len );
+    SSL_DEBUG_BUF( 3, "client hello, session id",
+                   buf + 6 + ciph_len, sess_len );
+    SSL_DEBUG_BUF( 3, "client hello, challenge",
+                   buf + 6 + ciph_len + sess_len, chal_len );
+
+    p = buf + 6 + ciph_len;
+    ssl->session_negotiate->length = sess_len;
+    memset( ssl->session_negotiate->id, 0,
+            sizeof( ssl->session_negotiate->id ) );
+    memcpy( ssl->session_negotiate->id, p, ssl->session_negotiate->length );
+
+    p += sess_len;
+    memset( ssl->handshake->randbytes, 0, 64 );
+    memcpy( ssl->handshake->randbytes + 32 - chal_len, p, chal_len );
+
+    /*
+     * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV
+     */
+    for( i = 0, p = buf + 6; i < ciph_len; i += 3, p += 3 )
+    {
+        if( p[0] == 0 && p[1] == 0 && p[2] == SSL_EMPTY_RENEGOTIATION_INFO )
+        {
+            SSL_DEBUG_MSG( 3, ( "received TLS_EMPTY_RENEGOTIATION_INFO " ) );
+            if( ssl->renegotiation == SSL_RENEGOTIATION )
+            {
+                SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV during renegotiation" ) );
+
+                if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
+                    return( ret );
+
+                return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+            }
+            ssl->secure_renegotiation = SSL_SECURE_RENEGOTIATION;
+            break;
+        }
+    }
+
+    ciphersuites = ssl->ciphersuite_list[ssl->minor_ver];
+    ciphersuite_info = NULL;
+#if defined(POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE)
+    for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 )
+    {
+        for( i = 0; ciphersuites[i] != 0; i++ )
+#else
+    for( i = 0; ciphersuites[i] != 0; i++ )
+    {
+        for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 )
+#endif
+        {
+            if( p[0] != 0 ||
+                p[1] != ( ( ciphersuites[i] >> 8 ) & 0xFF ) ||
+                p[2] != ( ( ciphersuites[i]      ) & 0xFF ) )
+                continue;
+
+            if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i],
+                                               &ciphersuite_info ) ) != 0 )
+                return( ret );
+
+            if( ciphersuite_info != NULL )
+                goto have_ciphersuite_v2;
+        }
+    }
+
+    SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) );
+
+    return( POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN );
+
+have_ciphersuite_v2:
+    ssl->session_negotiate->ciphersuite = ciphersuites[i];
+    ssl->transform_negotiate->ciphersuite_info = ciphersuite_info;
+    ssl_optimize_checksum( ssl, ssl->transform_negotiate->ciphersuite_info );
+
+    /*
+     * SSLv2 Client Hello relevant renegotiation security checks
+     */
+    if( ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION &&
+        ssl->allow_legacy_renegotiation == SSL_LEGACY_BREAK_HANDSHAKE )
+    {
+        SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) );
+
+        if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
+            return( ret );
+
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+    }
+
+    ssl->in_left = 0;
+    ssl->state++;
+
+    SSL_DEBUG_MSG( 2, ( "<= parse client hello v2" ) );
+
+    return( 0 );
+}
+#endif /* POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */
+
+static int ssl_parse_client_hello( ssl_context *ssl )
+{
+    int ret;
+    unsigned int i, j;
+    size_t n;
+    unsigned int ciph_len, sess_len;
+    unsigned int comp_len;
+    unsigned int ext_len = 0;
+    unsigned char *buf, *p, *ext;
+    int renegotiation_info_seen = 0;
+    int handshake_failure = 0;
+    const int *ciphersuites;
+    const ssl_ciphersuite_t *ciphersuite_info;
+
+    SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) );
+
+    if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE &&
+        ( ret = ssl_fetch_input( ssl, 5 ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_fetch_input", ret );
+        return( ret );
+    }
+
+    buf = ssl->in_hdr;
+
+#if defined(POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO)
+    if( ( buf[0] & 0x80 ) != 0 )
+        return ssl_parse_client_hello_v2( ssl );
+#endif
+
+    SSL_DEBUG_BUF( 4, "record header", buf, 5 );
+
+    SSL_DEBUG_MSG( 3, ( "client hello v3, message type: %d",
+                   buf[0] ) );
+    SSL_DEBUG_MSG( 3, ( "client hello v3, message len.: %d",
+                   ( buf[3] << 8 ) | buf[4] ) );
+    SSL_DEBUG_MSG( 3, ( "client hello v3, protocol ver: [%d:%d]",
+                   buf[1], buf[2] ) );
+
+    /*
+     * SSLv3/TLS Client Hello
+     *
+     * Record layer:
+     *     0  .   0   message type
+     *     1  .   2   protocol version
+     *     3  .   4   message length
+     */
+
+    /* According to RFC 5246 Appendix E.1, the version here is typically
+     * "{03,00}, the lowest version number supported by the client, [or] the
+     * value of ClientHello.client_version", so the only meaningful check here
+     * is the major version shouldn't be less than 3 */
+    if( buf[0] != SSL_MSG_HANDSHAKE ||
+        buf[1] < SSL_MAJOR_VERSION_3 )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+    }
+
+    n = ( buf[3] << 8 ) | buf[4];
+
+    if( n < 45 || n > SSL_MAX_CONTENT_LEN )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+    }
+
+    if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE &&
+        ( ret = ssl_fetch_input( ssl, 5 + n ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_fetch_input", ret );
+        return( ret );
+    }
+
+    buf = ssl->in_msg;
+    if( !ssl->renegotiation )
+        n = ssl->in_left - 5;
+    else
+        n = ssl->in_msglen;
+
+    ssl->handshake->update_checksum( ssl, buf, n );
+
+    /*
+     * SSL layer:
+     *     0  .   0   handshake type
+     *     1  .   3   handshake length
+     *     4  .   5   protocol version
+     *     6  .   9   UNIX time()
+     *    10  .  37   random bytes
+     *    38  .  38   session id length
+     *    39  . 38+x  session id
+     *   39+x . 40+x  ciphersuitelist length
+     *   41+x .  ..   ciphersuitelist
+     *    ..  .  ..   compression alg.
+     *    ..  .  ..   extensions
+     */
+    SSL_DEBUG_BUF( 4, "record contents", buf, n );
+
+    SSL_DEBUG_MSG( 3, ( "client hello v3, handshake type: %d",
+                   buf[0] ) );
+    SSL_DEBUG_MSG( 3, ( "client hello v3, handshake len.: %d",
+                   ( buf[1] << 16 ) | ( buf[2] << 8 ) | buf[3] ) );
+    SSL_DEBUG_MSG( 3, ( "client hello v3, max. version: [%d:%d]",
+                   buf[4], buf[5] ) );
+
+    /*
+     * Check the handshake type and protocol version
+     */
+    if( buf[0] != SSL_HS_CLIENT_HELLO )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+    }
+
+    ssl->major_ver = buf[4];
+    ssl->minor_ver = buf[5];
+
+    ssl->handshake->max_major_ver = ssl->major_ver;
+    ssl->handshake->max_minor_ver = ssl->minor_ver;
+
+    if( ssl->major_ver < ssl->min_major_ver ||
+        ssl->minor_ver < ssl->min_minor_ver )
+    {
+        SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum"
+                            " [%d:%d] < [%d:%d]",
+                            ssl->major_ver, ssl->minor_ver,
+                            ssl->min_major_ver, ssl->min_minor_ver ) );
+
+        ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL,
+                                     SSL_ALERT_MSG_PROTOCOL_VERSION );
+
+        return( POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION );
+    }
+
+    if( ssl->major_ver > ssl->max_major_ver )
+    {
+        ssl->major_ver = ssl->max_major_ver;
+        ssl->minor_ver = ssl->max_minor_ver;
+    }
+    else if( ssl->minor_ver > ssl->max_minor_ver )
+        ssl->minor_ver = ssl->max_minor_ver;
+
+    memcpy( ssl->handshake->randbytes, buf + 6, 32 );
+
+    /*
+     * Check the handshake message length
+     */
+    if( buf[1] != 0 || n != (unsigned int) 4 + ( ( buf[2] << 8 ) | buf[3] ) )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+    }
+
+    /*
+     * Check the session length
+     */
+    sess_len = buf[38];
+
+    if( sess_len > 32 )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+    }
+
+    ssl->session_negotiate->length = sess_len;
+    memset( ssl->session_negotiate->id, 0,
+            sizeof( ssl->session_negotiate->id ) );
+    memcpy( ssl->session_negotiate->id, buf + 39,
+            ssl->session_negotiate->length );
+
+    /*
+     * Check the ciphersuitelist length
+     */
+    ciph_len = ( buf[39 + sess_len] << 8 )
+             | ( buf[40 + sess_len]      );
+
+    if( ciph_len < 2 || ( ciph_len % 2 ) != 0 )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+    }
+
+    /*
+     * Check the compression algorithms length
+     */
+    comp_len = buf[41 + sess_len + ciph_len];
+
+    if( comp_len < 1 || comp_len > 16 )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+    }
+
+    /*
+     * Check the extension length
+     */
+    if( n > 42 + sess_len + ciph_len + comp_len )
+    {
+        ext_len = ( buf[42 + sess_len + ciph_len + comp_len] << 8 )
+                | ( buf[43 + sess_len + ciph_len + comp_len]      );
+
+        if( ( ext_len > 0 && ext_len < 4 ) ||
+            n != 44 + sess_len + ciph_len + comp_len + ext_len )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+            SSL_DEBUG_BUF( 3, "Ext", buf + 44 + sess_len + ciph_len + comp_len, ext_len);
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+        }
+    }
+
+    ssl->session_negotiate->compression = SSL_COMPRESS_NULL;
+#if defined(POLARSSL_ZLIB_SUPPORT)
+    for( i = 0; i < comp_len; ++i )
+    {
+        if( buf[42 + sess_len + ciph_len + i] == SSL_COMPRESS_DEFLATE )
+        {
+            ssl->session_negotiate->compression = SSL_COMPRESS_DEFLATE;
+            break;
+        }
+    }
+#endif
+
+    SSL_DEBUG_BUF( 3, "client hello, random bytes",
+                   buf +  6,  32 );
+    SSL_DEBUG_BUF( 3, "client hello, session id",
+                   buf + 38,  sess_len );
+    SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist",
+                   buf + 41 + sess_len,  ciph_len );
+    SSL_DEBUG_BUF( 3, "client hello, compression",
+                   buf + 42 + sess_len + ciph_len, comp_len );
+
+    /*
+     * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV
+     */
+    for( i = 0, p = buf + 41 + sess_len; i < ciph_len; i += 2, p += 2 )
+    {
+        if( p[0] == 0 && p[1] == SSL_EMPTY_RENEGOTIATION_INFO )
+        {
+            SSL_DEBUG_MSG( 3, ( "received TLS_EMPTY_RENEGOTIATION_INFO " ) );
+            if( ssl->renegotiation == SSL_RENEGOTIATION )
+            {
+                SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV during renegotiation" ) );
+
+                if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
+                    return( ret );
+
+                return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+            }
+            ssl->secure_renegotiation = SSL_SECURE_RENEGOTIATION;
+            break;
+        }
+    }
+
+    ext = buf + 44 + sess_len + ciph_len + comp_len;
+
+    while( ext_len )
+    {
+        unsigned int ext_id   = ( ( ext[0] <<  8 )
+                                | ( ext[1]       ) );
+        unsigned int ext_size = ( ( ext[2] <<  8 )
+                                | ( ext[3]       ) );
+
+        if( ext_size + 4 > ext_len )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+        }
+        switch( ext_id )
+        {
+#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
+        case TLS_EXT_SERVERNAME:
+            SSL_DEBUG_MSG( 3, ( "found ServerName extension" ) );
+            if( ssl->f_sni == NULL )
+                break;
+
+            ret = ssl_parse_servername_ext( ssl, ext + 4, ext_size );
+            if( ret != 0 )
+                return( ret );
+            break;
+#endif /* POLARSSL_SSL_SERVER_NAME_INDICATION */
+
+        case TLS_EXT_RENEGOTIATION_INFO:
+            SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) );
+            renegotiation_info_seen = 1;
+
+            ret = ssl_parse_renegotiation_info( ssl, ext + 4, ext_size );
+            if( ret != 0 )
+                return( ret );
+            break;
+
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+        case TLS_EXT_SIG_ALG:
+            SSL_DEBUG_MSG( 3, ( "found signature_algorithms extension" ) );
+            if( ssl->renegotiation == SSL_RENEGOTIATION )
+                break;
+
+            ret = ssl_parse_signature_algorithms_ext( ssl, ext + 4, ext_size );
+            if( ret != 0 )
+                return( ret );
+            break;
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
+
+#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C)
+        case TLS_EXT_SUPPORTED_ELLIPTIC_CURVES:
+            SSL_DEBUG_MSG( 3, ( "found supported elliptic curves extension" ) );
+
+            ret = ssl_parse_supported_elliptic_curves( ssl, ext + 4, ext_size );
+            if( ret != 0 )
+                return( ret );
+            break;
+
+        case TLS_EXT_SUPPORTED_POINT_FORMATS:
+            SSL_DEBUG_MSG( 3, ( "found supported point formats extension" ) );
+            ssl->handshake->cli_exts |= TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT;
+
+            ret = ssl_parse_supported_point_formats( ssl, ext + 4, ext_size );
+            if( ret != 0 )
+                return( ret );
+            break;
+#endif /* POLARSSL_ECDH_C || POLARSSL_ECDSA_C */
+
+#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH)
+        case TLS_EXT_MAX_FRAGMENT_LENGTH:
+            SSL_DEBUG_MSG( 3, ( "found max fragment length extension" ) );
+
+            ret = ssl_parse_max_fragment_length_ext( ssl, ext + 4, ext_size );
+            if( ret != 0 )
+                return( ret );
+            break;
+#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */
+
+#if defined(POLARSSL_SSL_TRUNCATED_HMAC)
+        case TLS_EXT_TRUNCATED_HMAC:
+            SSL_DEBUG_MSG( 3, ( "found truncated hmac extension" ) );
+
+            ret = ssl_parse_truncated_hmac_ext( ssl, ext + 4, ext_size );
+            if( ret != 0 )
+                return( ret );
+            break;
+#endif /* POLARSSL_SSL_TRUNCATED_HMAC */
+
+#if defined(POLARSSL_SSL_SESSION_TICKETS)
+        case TLS_EXT_SESSION_TICKET:
+            SSL_DEBUG_MSG( 3, ( "found session ticket extension" ) );
+
+            ret = ssl_parse_session_ticket_ext( ssl, ext + 4, ext_size );
+            if( ret != 0 )
+                return( ret );
+            break;
+#endif /* POLARSSL_SSL_SESSION_TICKETS */
+
+#if defined(POLARSSL_SSL_ALPN)
+        case TLS_EXT_ALPN:
+            SSL_DEBUG_MSG( 3, ( "found alpn extension" ) );
+
+            ret = ssl_parse_alpn_ext( ssl, ext + 4, ext_size );
+            if( ret != 0 )
+                return( ret );
+            break;
+#endif /* POLARSSL_SSL_SESSION_TICKETS */
+
+        default:
+            SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)",
+                           ext_id ) );
+        }
+
+        ext_len -= 4 + ext_size;
+        ext += 4 + ext_size;
+
+        if( ext_len > 0 && ext_len < 4 )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+        }
+    }
+
+    /*
+     * Renegotiation security checks
+     */
+    if( ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION &&
+        ssl->allow_legacy_renegotiation == SSL_LEGACY_BREAK_HANDSHAKE )
+    {
+        SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) );
+        handshake_failure = 1;
+    }
+    else if( ssl->renegotiation == SSL_RENEGOTIATION &&
+             ssl->secure_renegotiation == SSL_SECURE_RENEGOTIATION &&
+             renegotiation_info_seen == 0 )
+    {
+        SSL_DEBUG_MSG( 1, ( "renegotiation_info extension missing (secure)" ) );
+        handshake_failure = 1;
+    }
+    else if( ssl->renegotiation == SSL_RENEGOTIATION &&
+             ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION &&
+             ssl->allow_legacy_renegotiation == SSL_LEGACY_NO_RENEGOTIATION )
+    {
+        SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) );
+        handshake_failure = 1;
+    }
+    else if( ssl->renegotiation == SSL_RENEGOTIATION &&
+             ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION &&
+             renegotiation_info_seen == 1 )
+    {
+        SSL_DEBUG_MSG( 1, ( "renegotiation_info extension present (legacy)" ) );
+        handshake_failure = 1;
+    }
+
+    if( handshake_failure == 1 )
+    {
+        if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
+            return( ret );
+
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+    }
+
+    /*
+     * Search for a matching ciphersuite
+     * (At the end because we need information from the EC-based extensions
+     * and certificate from the SNI callback triggered by the SNI extension.)
+     */
+    ciphersuites = ssl->ciphersuite_list[ssl->minor_ver];
+    ciphersuite_info = NULL;
+#if defined(POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE)
+    for( j = 0, p = buf + 41 + sess_len; j < ciph_len; j += 2, p += 2 )
+    {
+        for( i = 0; ciphersuites[i] != 0; i++ )
+#else
+    for( i = 0; ciphersuites[i] != 0; i++ )
+    {
+        for( j = 0, p = buf + 41 + sess_len; j < ciph_len; j += 2, p += 2 )
+#endif
+        {
+            if( p[0] != ( ( ciphersuites[i] >> 8 ) & 0xFF ) ||
+                p[1] != ( ( ciphersuites[i]      ) & 0xFF ) )
+                continue;
+
+            if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i],
+                                               &ciphersuite_info ) ) != 0 )
+                return( ret );
+
+            if( ciphersuite_info != NULL )
+                goto have_ciphersuite;
+        }
+    }
+
+    SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) );
+
+    if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
+        return( ret );
+
+    return( POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN );
+
+have_ciphersuite:
+    ssl->session_negotiate->ciphersuite = ciphersuites[i];
+    ssl->transform_negotiate->ciphersuite_info = ciphersuite_info;
+    ssl_optimize_checksum( ssl, ssl->transform_negotiate->ciphersuite_info );
+
+    ssl->in_left = 0;
+    ssl->state++;
+
+    SSL_DEBUG_MSG( 2, ( "<= parse client hello" ) );
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_SSL_TRUNCATED_HMAC)
+static void ssl_write_truncated_hmac_ext( ssl_context *ssl,
+                                          unsigned char *buf,
+                                          size_t *olen )
+{
+    unsigned char *p = buf;
+
+    if( ssl->session_negotiate->trunc_hmac == SSL_TRUNC_HMAC_DISABLED )
+    {
+        *olen = 0;
+        return;
+    }
+
+    SSL_DEBUG_MSG( 3, ( "server hello, adding truncated hmac extension" ) );
+
+    *p++ = (unsigned char)( ( TLS_EXT_TRUNCATED_HMAC >> 8 ) & 0xFF );
+    *p++ = (unsigned char)( ( TLS_EXT_TRUNCATED_HMAC      ) & 0xFF );
+
+    *p++ = 0x00;
+    *p++ = 0x00;
+
+    *olen = 4;
+}
+#endif /* POLARSSL_SSL_TRUNCATED_HMAC */
+
+#if defined(POLARSSL_SSL_SESSION_TICKETS)
+static void ssl_write_session_ticket_ext( ssl_context *ssl,
+                                          unsigned char *buf,
+                                          size_t *olen )
+{
+    unsigned char *p = buf;
+
+    if( ssl->handshake->new_session_ticket == 0 )
+    {
+        *olen = 0;
+        return;
+    }
+
+    SSL_DEBUG_MSG( 3, ( "server hello, adding session ticket extension" ) );
+
+    *p++ = (unsigned char)( ( TLS_EXT_SESSION_TICKET >> 8 ) & 0xFF );
+    *p++ = (unsigned char)( ( TLS_EXT_SESSION_TICKET      ) & 0xFF );
+
+    *p++ = 0x00;
+    *p++ = 0x00;
+
+    *olen = 4;
+}
+#endif /* POLARSSL_SSL_SESSION_TICKETS */
+
+static void ssl_write_renegotiation_ext( ssl_context *ssl,
+                                         unsigned char *buf,
+                                         size_t *olen )
+{
+    unsigned char *p = buf;
+
+    if( ssl->secure_renegotiation != SSL_SECURE_RENEGOTIATION )
+    {
+        *olen = 0;
+        return;
+    }
+
+    SSL_DEBUG_MSG( 3, ( "server hello, secure renegotiation extension" ) );
+
+    *p++ = (unsigned char)( ( TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF );
+    *p++ = (unsigned char)( ( TLS_EXT_RENEGOTIATION_INFO      ) & 0xFF );
+
+    *p++ = 0x00;
+    *p++ = ( ssl->verify_data_len * 2 + 1 ) & 0xFF;
+    *p++ = ssl->verify_data_len * 2 & 0xFF;
+
+    memcpy( p, ssl->peer_verify_data, ssl->verify_data_len );
+    p += ssl->verify_data_len;
+    memcpy( p, ssl->own_verify_data, ssl->verify_data_len );
+    p += ssl->verify_data_len;
+
+    *olen = 5 + ssl->verify_data_len * 2;
+}
+
+#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH)
+static void ssl_write_max_fragment_length_ext( ssl_context *ssl,
+                                               unsigned char *buf,
+                                               size_t *olen )
+{
+    unsigned char *p = buf;
+
+    if( ssl->session_negotiate->mfl_code == SSL_MAX_FRAG_LEN_NONE )
+    {
+        *olen = 0;
+        return;
+    }
+
+    SSL_DEBUG_MSG( 3, ( "server hello, max_fragment_length extension" ) );
+
+    *p++ = (unsigned char)( ( TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 ) & 0xFF );
+    *p++ = (unsigned char)( ( TLS_EXT_MAX_FRAGMENT_LENGTH      ) & 0xFF );
+
+    *p++ = 0x00;
+    *p++ = 1;
+
+    *p++ = ssl->session_negotiate->mfl_code;
+
+    *olen = 5;
+}
+#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */
+
+#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C)
+static void ssl_write_supported_point_formats_ext( ssl_context *ssl,
+                                                   unsigned char *buf,
+                                                   size_t *olen )
+{
+    unsigned char *p = buf;
+    ((void) ssl);
+
+    if( ( ssl->handshake->cli_exts &
+          TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT ) == 0 )
+    {
+        *olen = 0;
+        return;
+    }
+
+    SSL_DEBUG_MSG( 3, ( "server hello, supported_point_formats extension" ) );
+
+    *p++ = (unsigned char)( ( TLS_EXT_SUPPORTED_POINT_FORMATS >> 8 ) & 0xFF );
+    *p++ = (unsigned char)( ( TLS_EXT_SUPPORTED_POINT_FORMATS      ) & 0xFF );
+
+    *p++ = 0x00;
+    *p++ = 2;
+
+    *p++ = 1;
+    *p++ = POLARSSL_ECP_PF_UNCOMPRESSED;
+
+    *olen = 6;
+}
+#endif /* POLARSSL_ECDH_C || POLARSSL_ECDSA_C */
+
+#if defined(POLARSSL_SSL_ALPN )
+static void ssl_write_alpn_ext( ssl_context *ssl,
+                                unsigned char *buf, size_t *olen )
+{
+    if( ssl->alpn_chosen == NULL )
+    {
+        *olen = 0;
+        return;
+    }
+
+    SSL_DEBUG_MSG( 3, ( "server hello, adding alpn extension" ) );
+
+    /*
+     * 0 . 1    ext identifier
+     * 2 . 3    ext length
+     * 4 . 5    protocol list length
+     * 6 . 6    protocol name length
+     * 7 . 7+n  protocol name
+     */
+    buf[0] = (unsigned char)( ( TLS_EXT_ALPN >> 8 ) & 0xFF );
+    buf[1] = (unsigned char)( ( TLS_EXT_ALPN      ) & 0xFF );
+
+    *olen = 7 + strlen( ssl->alpn_chosen );
+
+    buf[2] = (unsigned char)( ( ( *olen - 4 ) >> 8 ) & 0xFF );
+    buf[3] = (unsigned char)( ( ( *olen - 4 )      ) & 0xFF );
+
+    buf[4] = (unsigned char)( ( ( *olen - 6 ) >> 8 ) & 0xFF );
+    buf[5] = (unsigned char)( ( ( *olen - 6 )      ) & 0xFF );
+
+    buf[6] = (unsigned char)( ( ( *olen - 7 )      ) & 0xFF );
+
+    memcpy( buf + 7, ssl->alpn_chosen, *olen - 7 );
+}
+#endif /* POLARSSL_ECDH_C || POLARSSL_ECDSA_C */
+
+static int ssl_write_server_hello( ssl_context *ssl )
+{
+#if defined(POLARSSL_HAVE_TIME)
+    time_t t;
+#endif
+    int ret;
+    size_t olen, ext_len = 0, n;
+    unsigned char *buf, *p;
+
+    SSL_DEBUG_MSG( 2, ( "=> write server hello" ) );
+
+    if( ssl->f_rng == NULL )
+    {
+        SSL_DEBUG_MSG( 1, ( "no RNG provided") );
+        return( POLARSSL_ERR_SSL_NO_RNG );
+    }
+
+    /*
+     *     0  .   0   handshake type
+     *     1  .   3   handshake length
+     *     4  .   5   protocol version
+     *     6  .   9   UNIX time()
+     *    10  .  37   random bytes
+     */
+    buf = ssl->out_msg;
+    p = buf + 4;
+
+    *p++ = (unsigned char) ssl->major_ver;
+    *p++ = (unsigned char) ssl->minor_ver;
+
+    SSL_DEBUG_MSG( 3, ( "server hello, chosen version: [%d:%d]",
+                   buf[4], buf[5] ) );
+
+#if defined(POLARSSL_HAVE_TIME)
+    t = time( NULL );
+    *p++ = (unsigned char)( t >> 24 );
+    *p++ = (unsigned char)( t >> 16 );
+    *p++ = (unsigned char)( t >>  8 );
+    *p++ = (unsigned char)( t       );
+
+    SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) );
+#else
+    if( ( ret = ssl->f_rng( ssl->p_rng, p, 4 ) ) != 0 )
+        return( ret );
+
+    p += 4;
+#endif /* POLARSSL_HAVE_TIME */
+
+    if( ( ret = ssl->f_rng( ssl->p_rng, p, 28 ) ) != 0 )
+        return( ret );
+
+    p += 28;
+
+    memcpy( ssl->handshake->randbytes + 32, buf + 6, 32 );
+
+    SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 6, 32 );
+
+    /*
+     * Resume is 0  by default, see ssl_handshake_init().
+     * It may be already set to 1 by ssl_parse_session_ticket_ext().
+     * If not, try looking up session ID in our cache.
+     */
+    if( ssl->handshake->resume == 0 &&
+        ssl->renegotiation == SSL_INITIAL_HANDSHAKE &&
+        ssl->session_negotiate->length != 0 &&
+        ssl->f_get_cache != NULL &&
+        ssl->f_get_cache( ssl->p_get_cache, ssl->session_negotiate ) == 0 )
+    {
+        SSL_DEBUG_MSG( 3, ( "session successfully restored from cache" ) );
+        ssl->handshake->resume = 1;
+    }
+
+    if( ssl->handshake->resume == 0 )
+    {
+        /*
+         * New session, create a new session id,
+         * unless we're about to issue a session ticket
+         */
+        ssl->state++;
+
+#if defined(POLARSSL_HAVE_TIME)
+        ssl->session_negotiate->start = time( NULL );
+#endif
+
+#if defined(POLARSSL_SSL_SESSION_TICKETS)
+        if( ssl->handshake->new_session_ticket != 0 )
+        {
+            ssl->session_negotiate->length = n = 0;
+            memset( ssl->session_negotiate->id, 0, 32 );
+        }
+        else
+#endif /* POLARSSL_SSL_SESSION_TICKETS */
+        {
+            ssl->session_negotiate->length = n = 32;
+            if( ( ret = ssl->f_rng( ssl->p_rng, ssl->session_negotiate->id,
+                                    n ) ) != 0 )
+                return( ret );
+        }
+    }
+    else
+    {
+        /*
+         * Resuming a session
+         */
+        n = ssl->session_negotiate->length;
+        ssl->state = SSL_SERVER_CHANGE_CIPHER_SPEC;
+
+        if( ( ret = ssl_derive_keys( ssl ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_derive_keys", ret );
+            return( ret );
+        }
+    }
+
+    /*
+     *    38  .  38     session id length
+     *    39  . 38+n    session id
+     *   39+n . 40+n    chosen ciphersuite
+     *   41+n . 41+n    chosen compression alg.
+     *   42+n . 43+n    extensions length
+     *   44+n . 43+n+m  extensions
+     */
+    *p++ = (unsigned char) ssl->session_negotiate->length;
+    memcpy( p, ssl->session_negotiate->id, ssl->session_negotiate->length );
+    p += ssl->session_negotiate->length;
+
+    SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) );
+    SSL_DEBUG_BUF( 3,   "server hello, session id", buf + 39, n );
+    SSL_DEBUG_MSG( 3, ( "%s session has been resumed",
+                   ssl->handshake->resume ? "a" : "no" ) );
+
+    *p++ = (unsigned char)( ssl->session_negotiate->ciphersuite >> 8 );
+    *p++ = (unsigned char)( ssl->session_negotiate->ciphersuite      );
+    *p++ = (unsigned char)( ssl->session_negotiate->compression      );
+
+    SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s",
+           ssl_get_ciphersuite_name( ssl->session_negotiate->ciphersuite ) ) );
+    SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: 0x%02X",
+                   ssl->session_negotiate->compression ) );
+
+    /*
+     *  First write extensions, then the total length
+     */
+    ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen );
+    ext_len += olen;
+
+#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH)
+    ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen );
+    ext_len += olen;
+#endif
+
+#if defined(POLARSSL_SSL_TRUNCATED_HMAC)
+    ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len, &olen );
+    ext_len += olen;
+#endif
+
+#if defined(POLARSSL_SSL_SESSION_TICKETS)
+    ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, &olen );
+    ext_len += olen;
+#endif
+
+#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C)
+    ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen );
+    ext_len += olen;
+#endif
+
+#if defined(POLARSSL_SSL_ALPN)
+    ssl_write_alpn_ext( ssl, p + 2 + ext_len, &olen );
+    ext_len += olen;
+#endif
+
+    SSL_DEBUG_MSG( 3, ( "server hello, total extension length: %d", ext_len ) );
+
+    if( ext_len > 0 )
+    {
+        *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF );
+        *p++ = (unsigned char)( ( ext_len      ) & 0xFF );
+        p += ext_len;
+    }
+
+    ssl->out_msglen  = p - buf;
+    ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+    ssl->out_msg[0]  = SSL_HS_SERVER_HELLO;
+
+    ret = ssl_write_record( ssl );
+
+    SSL_DEBUG_MSG( 2, ( "<= write server hello" ) );
+
+    return( ret );
+}
+
+#if !defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED)       && \
+    !defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED)   && \
+    !defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \
+    !defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+static int ssl_write_certificate_request( ssl_context *ssl )
+{
+    int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
+    const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
+
+    SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) );
+
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK )
+    {
+        SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) );
+        ssl->state++;
+        return( 0 );
+    }
+
+    SSL_DEBUG_MSG( 1, ( "should not happen" ) );
+    return( ret );
+}
+#else
+static int ssl_write_certificate_request( ssl_context *ssl )
+{
+    int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
+    const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
+    size_t dn_size, total_dn_size; /* excluding length bytes */
+    size_t ct_len, sa_len; /* including length bytes */
+    unsigned char *buf, *p;
+    const x509_crt *crt;
+
+    SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) );
+
+    ssl->state++;
+
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ||
+        ssl->authmode == SSL_VERIFY_NONE )
+    {
+        SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) );
+        return( 0 );
+    }
+
+    /*
+     *     0  .   0   handshake type
+     *     1  .   3   handshake length
+     *     4  .   4   cert type count
+     *     5  .. m-1  cert types
+     *     m  .. m+1  sig alg length (TLS 1.2 only)
+     *    m+1 .. n-1  SignatureAndHashAlgorithms (TLS 1.2 only)
+     *     n  .. n+1  length of all DNs
+     *    n+2 .. n+3  length of DN 1
+     *    n+4 .. ...  Distinguished Name #1
+     *    ... .. ...  length of DN 2, etc.
+     */
+    buf = ssl->out_msg;
+    p = buf + 4;
+
+    /*
+     * Supported certificate types
+     *
+     *     ClientCertificateType certificate_types<1..2^8-1>;
+     *     enum { (255) } ClientCertificateType;
+     */
+    ct_len = 0;
+
+#if defined(POLARSSL_RSA_C)
+    p[1 + ct_len++] = SSL_CERT_TYPE_RSA_SIGN;
+#endif
+#if defined(POLARSSL_ECDSA_C)
+    p[1 + ct_len++] = SSL_CERT_TYPE_ECDSA_SIGN;
+#endif
+
+    p[0] = (unsigned char) ct_len++;
+    p += ct_len;
+
+    sa_len = 0;
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+    /*
+     * Add signature_algorithms for verify (TLS 1.2)
+     *
+     *     SignatureAndHashAlgorithm supported_signature_algorithms<2..2^16-2>;
+     *
+     *     struct {
+     *           HashAlgorithm hash;
+     *           SignatureAlgorithm signature;
+     *     } SignatureAndHashAlgorithm;
+     *
+     *     enum { (255) } HashAlgorithm;
+     *     enum { (255) } SignatureAlgorithm;
+     */
+    if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
+    {
+        /*
+         * Only use current running hash algorithm that is already required
+         * for requested ciphersuite.
+         */
+        ssl->handshake->verify_sig_alg = SSL_HASH_SHA256;
+
+        if( ssl->transform_negotiate->ciphersuite_info->mac ==
+            POLARSSL_MD_SHA384 )
+        {
+            ssl->handshake->verify_sig_alg = SSL_HASH_SHA384;
+        }
+
+        /*
+         * Supported signature algorithms
+         */
+#if defined(POLARSSL_RSA_C)
+        p[2 + sa_len++] = ssl->handshake->verify_sig_alg;
+        p[2 + sa_len++] = SSL_SIG_RSA;
+#endif
+#if defined(POLARSSL_ECDSA_C)
+        p[2 + sa_len++] = ssl->handshake->verify_sig_alg;
+        p[2 + sa_len++] = SSL_SIG_ECDSA;
+#endif
+
+        p[0] = (unsigned char)( sa_len >> 8 );
+        p[1] = (unsigned char)( sa_len      );
+        sa_len += 2;
+        p += sa_len;
+    }
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
+
+    /*
+     * DistinguishedName certificate_authorities<0..2^16-1>;
+     * opaque DistinguishedName<1..2^16-1>;
+     */
+    p += 2;
+    crt = ssl->ca_chain;
+
+    total_dn_size = 0;
+    while( crt != NULL && crt->version != 0 )
+    {
+        if( p - buf > 4096 )
+            break;
+
+        dn_size = crt->subject_raw.len;
+        *p++ = (unsigned char)( dn_size >> 8 );
+        *p++ = (unsigned char)( dn_size      );
+        memcpy( p, crt->subject_raw.p, dn_size );
+        p += dn_size;
+
+        SSL_DEBUG_BUF( 3, "requested DN", p, dn_size );
+
+        total_dn_size += 2 + dn_size;
+        crt = crt->next;
+    }
+
+    ssl->out_msglen  = p - buf;
+    ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+    ssl->out_msg[0]  = SSL_HS_CERTIFICATE_REQUEST;
+    ssl->out_msg[4 + ct_len + sa_len] = (unsigned char)( total_dn_size  >> 8 );
+    ssl->out_msg[5 + ct_len + sa_len] = (unsigned char)( total_dn_size       );
+
+    ret = ssl_write_record( ssl );
+
+    SSL_DEBUG_MSG( 2, ( "<= write certificate request" ) );
+
+    return( ret );
+}
+#endif /* !POLARSSL_KEY_EXCHANGE_RSA_ENABLED &&
+          !POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED &&
+          !POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED &&
+          !POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
+
+#if defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
+    defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+static int ssl_get_ecdh_params_from_cert( ssl_context *ssl )
+{
+    int ret;
+
+    if( ! pk_can_do( ssl_own_key( ssl ), POLARSSL_PK_ECKEY ) )
+    {
+        SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) );
+        return( POLARSSL_ERR_SSL_PK_TYPE_MISMATCH );
+    }
+
+    if( ( ret = ecdh_get_params( &ssl->handshake->ecdh_ctx,
+                                 pk_ec( *ssl_own_key( ssl ) ),
+                                 POLARSSL_ECDH_OURS ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, ( "ecdh_get_params" ), ret );
+        return( ret );
+    }
+
+    return( 0 );
+}
+#endif /* POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||
+          POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
+
+static int ssl_write_server_key_exchange( ssl_context *ssl )
+{
+    int ret;
+    size_t n = 0;
+    const ssl_ciphersuite_t *ciphersuite_info =
+                            ssl->transform_negotiate->ciphersuite_info;
+
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) ||                       \
+    defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) ||                       \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) ||                     \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+    unsigned char *p = ssl->out_msg + 4;
+    unsigned char *dig_signed = p;
+    size_t dig_signed_len = 0, len;
+    ((void) dig_signed);
+    ((void) dig_signed_len);
+#endif
+
+    SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) );
+
+#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) ||                           \
+    defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) ||                           \
+    defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED)
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK )
+    {
+        SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) );
+        ssl->state++;
+        return( 0 );
+    }
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
+    defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_RSA ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_ECDSA )
+    {
+        ssl_get_ecdh_params_from_cert( ssl );
+
+        SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) );
+        ssl->state++;
+        return( 0 );
+    }
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) ||                       \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK )
+    {
+        /* TODO: Support identity hints */
+        *(p++) = 0x00;
+        *(p++) = 0x00;
+
+        n += 2;
+    }
+#endif /* POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
+
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) ||                       \
+    defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED)
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_RSA ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK )
+    {
+        /*
+         * Ephemeral DH parameters:
+         *
+         * struct {
+         *     opaque dh_p<1..2^16-1>;
+         *     opaque dh_g<1..2^16-1>;
+         *     opaque dh_Ys<1..2^16-1>;
+         * } ServerDHParams;
+         */
+        if( ( ret = mpi_copy( &ssl->handshake->dhm_ctx.P, &ssl->dhm_P ) ) != 0 ||
+            ( ret = mpi_copy( &ssl->handshake->dhm_ctx.G, &ssl->dhm_G ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "mpi_copy", ret );
+            return( ret );
+        }
+
+        if( ( ret = dhm_make_params( &ssl->handshake->dhm_ctx,
+                        (int) mpi_size( &ssl->handshake->dhm_ctx.P ),
+                        p, &len, ssl->f_rng, ssl->p_rng ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "dhm_make_params", ret );
+            return( ret );
+        }
+
+        dig_signed = p;
+        dig_signed_len = len;
+
+        p += len;
+        n += len;
+
+        SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X  );
+        SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P  );
+        SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G  );
+        SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX );
+    }
+#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */
+
+#if defined(POLARSSL_KEY_EXCHANGE__SOME__ECDHE_ENABLED)
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK )
+    {
+        /*
+         * Ephemeral ECDH parameters:
+         *
+         * struct {
+         *     ECParameters curve_params;
+         *     ECPoint      public;
+         * } ServerECDHParams;
+         */
+        const ecp_curve_info **curve = NULL;
+#if defined(POLARSSL_SSL_SET_CURVES)
+        const ecp_group_id *gid;
+
+        /* Match our preference list against the offered curves */
+        for( gid = ssl->curve_list; *gid != POLARSSL_ECP_DP_NONE; gid++ )
+            for( curve = ssl->handshake->curves; *curve != NULL; curve++ )
+                if( (*curve)->grp_id == *gid )
+                    goto curve_matching_done;
+
+curve_matching_done:
+#else
+        curve = ssl->handshake->curves;
+#endif
+
+        if( *curve == NULL )
+        {
+            SSL_DEBUG_MSG( 1, ( "no matching curve for ECDHE" ) );
+            return( POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN );
+        }
+
+        SSL_DEBUG_MSG( 2, ( "ECDHE curve: %s", (*curve)->name ) );
+
+        if( ( ret = ecp_use_known_dp( &ssl->handshake->ecdh_ctx.grp,
+                                       (*curve)->grp_id ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ecp_use_known_dp", ret );
+            return( ret );
+        }
+
+        if( ( ret = ecdh_make_params( &ssl->handshake->ecdh_ctx, &len,
+                                      p, SSL_MAX_CONTENT_LEN - n,
+                                      ssl->f_rng, ssl->p_rng ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ecdh_make_params", ret );
+            return( ret );
+        }
+
+        dig_signed = p;
+        dig_signed_len = len;
+
+        p += len;
+        n += len;
+
+        SSL_DEBUG_ECP( 3, "ECDH: Q ", &ssl->handshake->ecdh_ctx.Q );
+    }
+#endif /* POLARSSL_KEY_EXCHANGE__SOME__ECDHE_ENABLED */
+
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) ||                       \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_RSA ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA )
+    {
+        size_t signature_len = 0;
+        unsigned int hashlen = 0;
+        unsigned char hash[64];
+        md_type_t md_alg = POLARSSL_MD_NONE;
+
+        /*
+         * Choose hash algorithm. NONE means MD5 + SHA1 here.
+         */
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+        if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
+        {
+            md_alg = ssl_md_alg_from_hash( ssl->handshake->sig_alg );
+
+            if( md_alg == POLARSSL_MD_NONE )
+            {
+                SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+                return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+            }
+        }
+        else
+#endif
+#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_1)
+        if ( ciphersuite_info->key_exchange ==
+                  POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA )
+        {
+            md_alg = POLARSSL_MD_SHA1;
+        }
+        else
+#endif
+        {
+            md_alg = POLARSSL_MD_NONE;
+        }
+
+        /*
+         * Compute the hash to be signed
+         */
+#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_1)
+        if( md_alg == POLARSSL_MD_NONE )
+        {
+            md5_context md5;
+            sha1_context sha1;
+
+            /*
+             * digitally-signed struct {
+             *     opaque md5_hash[16];
+             *     opaque sha_hash[20];
+             * };
+             *
+             * md5_hash
+             *     MD5(ClientHello.random + ServerHello.random
+             *                            + ServerParams);
+             * sha_hash
+             *     SHA(ClientHello.random + ServerHello.random
+             *                            + ServerParams);
+             */
+            md5_starts( &md5 );
+            md5_update( &md5, ssl->handshake->randbytes,  64 );
+            md5_update( &md5, dig_signed, dig_signed_len );
+            md5_finish( &md5, hash );
+
+            sha1_starts( &sha1 );
+            sha1_update( &sha1, ssl->handshake->randbytes,  64 );
+            sha1_update( &sha1, dig_signed, dig_signed_len );
+            sha1_finish( &sha1, hash + 16 );
+
+            hashlen = 36;
+        }
+        else
+#endif /* POLARSSL_SSL_PROTO_SSL3 || POLARSSL_SSL_PROTO_TLS1 || \
+          POLARSSL_SSL_PROTO_TLS1_1 */
+#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_2)
+        if( md_alg != POLARSSL_MD_NONE )
+        {
+            md_context_t ctx;
+
+            /* Info from md_alg will be used instead */
+            hashlen = 0;
+
+            /*
+             * digitally-signed struct {
+             *     opaque client_random[32];
+             *     opaque server_random[32];
+             *     ServerDHParams params;
+             * };
+             */
+            if( ( ret = md_init_ctx( &ctx, md_info_from_type(md_alg) ) ) != 0 )
+            {
+                SSL_DEBUG_RET( 1, "md_init_ctx", ret );
+                return( ret );
+            }
+
+            md_starts( &ctx );
+            md_update( &ctx, ssl->handshake->randbytes, 64 );
+            md_update( &ctx, dig_signed, dig_signed_len );
+            md_finish( &ctx, hash );
+
+            if( ( ret = md_free_ctx( &ctx ) ) != 0 )
+            {
+                SSL_DEBUG_RET( 1, "md_free_ctx", ret );
+                return( ret );
+            }
+
+        }
+        else
+#endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 || \
+          POLARSSL_SSL_PROTO_TLS1_2 */
+        {
+            SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+            return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+        }
+
+        SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen :
+                (unsigned int) ( md_info_from_type( md_alg ) )->size );
+
+        /*
+         * Make the signature
+         */
+        if( ssl_own_key( ssl ) == NULL )
+        {
+            SSL_DEBUG_MSG( 1, ( "got no private key" ) );
+            return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED );
+        }
+
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+        if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
+        {
+            *(p++) = ssl->handshake->sig_alg;
+            *(p++) = ssl_sig_from_pk( ssl_own_key( ssl ) );
+
+            n += 2;
+        }
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
+
+        if( ( ret = pk_sign( ssl_own_key( ssl ), md_alg, hash, hashlen,
+                        p + 2 , &signature_len,
+                        ssl->f_rng, ssl->p_rng ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "pk_sign", ret );
+            return( ret );
+        }
+
+        *(p++) = (unsigned char)( signature_len >> 8 );
+        *(p++) = (unsigned char)( signature_len      );
+        n += 2;
+
+        SSL_DEBUG_BUF( 3, "my signature", p, signature_len );
+
+        p += signature_len;
+        n += signature_len;
+    }
+#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) ||
+          POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
+
+    ssl->out_msglen  = 4 + n;
+    ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+    ssl->out_msg[0]  = SSL_HS_SERVER_KEY_EXCHANGE;
+
+    ssl->state++;
+
+    if( ( ret = ssl_write_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+        return( ret );
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= write server key exchange" ) );
+
+    return( 0 );
+}
+
+static int ssl_write_server_hello_done( ssl_context *ssl )
+{
+    int ret;
+
+    SSL_DEBUG_MSG( 2, ( "=> write server hello done" ) );
+
+    ssl->out_msglen  = 4;
+    ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+    ssl->out_msg[0]  = SSL_HS_SERVER_HELLO_DONE;
+
+    ssl->state++;
+
+    if( ( ret = ssl_write_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+        return( ret );
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= write server hello done" ) );
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) ||                       \
+    defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED)
+static int ssl_parse_client_dh_public( ssl_context *ssl, unsigned char **p,
+                                       const unsigned char *end )
+{
+    int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
+    size_t n;
+
+    /*
+     * Receive G^Y mod P, premaster = (G^Y)^X mod P
+     */
+    if( *p + 2 > end )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
+    }
+
+    n = ( (*p)[0] << 8 ) | (*p)[1];
+    *p += 2;
+
+    if( *p + n > end )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
+    }
+
+    if( ( ret = dhm_read_public( &ssl->handshake->dhm_ctx, *p, n ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "dhm_read_public", ret );
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP );
+    }
+
+    *p += n;
+
+    SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY );
+
+    return( ret );
+}
+#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */
+
+#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) ||                           \
+    defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED)
+static int ssl_parse_encrypted_pms( ssl_context *ssl,
+                                    const unsigned char *p,
+                                    const unsigned char *end,
+                                    size_t pms_offset )
+{
+    int ret;
+    size_t len = pk_get_len( ssl_own_key( ssl ) );
+    unsigned char *pms = ssl->handshake->premaster + pms_offset;
+
+    if( ! pk_can_do( ssl_own_key( ssl ), POLARSSL_PK_RSA ) )
+    {
+        SSL_DEBUG_MSG( 1, ( "got no RSA private key" ) );
+        return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED );
+    }
+
+    /*
+     * Decrypt the premaster using own private RSA key
+     */
+#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_2)
+    if( ssl->minor_ver != SSL_MINOR_VERSION_0 )
+    {
+        if( *p++ != ( ( len >> 8 ) & 0xFF ) ||
+            *p++ != ( ( len      ) & 0xFF ) )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
+        }
+    }
+#endif
+
+    if( p + len != end )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
+    }
+
+    ret = pk_decrypt( ssl_own_key( ssl ), p, len,
+                      pms, &ssl->handshake->pmslen,
+                      sizeof( ssl->handshake->premaster ) - pms_offset,
+                      ssl->f_rng, ssl->p_rng );
+
+    if( ret != 0 || ssl->handshake->pmslen != 48 ||
+        pms[0] != ssl->handshake->max_major_ver ||
+        pms[1] != ssl->handshake->max_minor_ver )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
+
+        /*
+         * Protection against Bleichenbacher's attack:
+         * invalid PKCS#1 v1.5 padding must not cause
+         * the connection to end immediately; instead,
+         * send a bad_record_mac later in the handshake.
+         */
+        ssl->handshake->pmslen = 48;
+
+        ret = ssl->f_rng( ssl->p_rng, pms, ssl->handshake->pmslen );
+        if( ret != 0 )
+            return( ret );
+    }
+
+    return( ret );
+}
+#endif /* POLARSSL_KEY_EXCHANGE_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED */
+
+#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
+static int ssl_parse_client_psk_identity( ssl_context *ssl, unsigned char **p,
+                                          const unsigned char *end )
+{
+    int ret = 0;
+    size_t n;
+
+    if( ssl->f_psk == NULL &&
+        ( ssl->psk == NULL || ssl->psk_identity == NULL ||
+          ssl->psk_identity_len == 0 || ssl->psk_len == 0 ) )
+    {
+        SSL_DEBUG_MSG( 1, ( "got no pre-shared key" ) );
+        return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED );
+    }
+
+    /*
+     * Receive client pre-shared key identity name
+     */
+    if( *p + 2 > end )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
+    }
+
+    n = ( (*p)[0] << 8 ) | (*p)[1];
+    *p += 2;
+
+    if( n < 1 || n > 65535 || *p + n > end )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
+    }
+
+    if( ssl->f_psk != NULL )
+    {
+        if( ( ret != ssl->f_psk( ssl->p_psk, ssl, *p, n ) ) != 0 )
+            ret = POLARSSL_ERR_SSL_UNKNOWN_IDENTITY;
+    }
+
+    if( ret == 0 )
+    {
+        /* Identity is not a big secret since clients send it in the clear,
+         * but treat it carefully anyway, just in case */
+        if( n != ssl->psk_identity_len ||
+            safer_memcmp( ssl->psk_identity, *p, n ) != 0 )
+        {
+            ret = POLARSSL_ERR_SSL_UNKNOWN_IDENTITY;
+        }
+    }
+
+    if( ret == POLARSSL_ERR_SSL_UNKNOWN_IDENTITY )
+    {
+        SSL_DEBUG_BUF( 3, "Unknown PSK identity", *p, n );
+        if( ( ret = ssl_send_alert_message( ssl,
+                              SSL_ALERT_LEVEL_FATAL,
+                              SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY ) ) != 0 )
+        {
+            return( ret );
+        }
+
+        return( POLARSSL_ERR_SSL_UNKNOWN_IDENTITY );
+    }
+
+    *p += n;
+    ret = 0;
+
+    return( ret );
+}
+#endif /* POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED */
+
+static int ssl_parse_client_key_exchange( ssl_context *ssl )
+{
+    int ret;
+    const ssl_ciphersuite_t *ciphersuite_info;
+
+    ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
+
+    SSL_DEBUG_MSG( 2, ( "=> parse client key exchange" ) );
+
+    if( ( ret = ssl_read_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+        return( ret );
+    }
+
+    if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
+    }
+
+    if( ssl->in_msg[0] != SSL_HS_CLIENT_KEY_EXCHANGE )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
+    }
+
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED)
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_RSA )
+    {
+        unsigned char *p = ssl->in_msg + 4;
+        unsigned char *end = ssl->in_msg + ssl->in_hslen;
+
+        if( ( ret = ssl_parse_client_dh_public( ssl, &p, end ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, ( "ssl_parse_client_dh_public" ), ret );
+            return( ret );
+        }
+
+        if( p != end )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
+        }
+
+        ssl->handshake->pmslen = ssl->handshake->dhm_ctx.len;
+
+        if( ( ret = dhm_calc_secret( &ssl->handshake->dhm_ctx,
+                                      ssl->handshake->premaster,
+                                     &ssl->handshake->pmslen,
+                                      ssl->f_rng, ssl->p_rng ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "dhm_calc_secret", ret );
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS );
+        }
+
+        SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K  );
+    }
+    else
+#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED */
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ||                   \
+    defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||                      \
+    defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_RSA ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_ECDSA )
+    {
+        if( ( ret = ecdh_read_public( &ssl->handshake->ecdh_ctx,
+                        ssl->in_msg + 4, ssl->in_hslen - 4 ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ecdh_read_public", ret );
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP );
+        }
+
+        SSL_DEBUG_ECP( 3, "ECDH: Qp ", &ssl->handshake->ecdh_ctx.Qp );
+
+        if( ( ret = ecdh_calc_secret( &ssl->handshake->ecdh_ctx,
+                                      &ssl->handshake->pmslen,
+                                       ssl->handshake->premaster,
+                                       POLARSSL_MPI_MAX_SIZE,
+                                       ssl->f_rng, ssl->p_rng ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ecdh_calc_secret", ret );
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS );
+        }
+
+        SSL_DEBUG_MPI( 3, "ECDH: z  ", &ssl->handshake->ecdh_ctx.z );
+    }
+    else
+#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
+#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED)
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK )
+    {
+        unsigned char *p = ssl->in_msg + 4;
+        unsigned char *end = ssl->in_msg + ssl->in_hslen;
+
+        if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret );
+            return( ret );
+        }
+
+        if( p != end )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
+        }
+
+        if( ( ret = ssl_psk_derive_premaster( ssl,
+                        ciphersuite_info->key_exchange ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_psk_derive_premaster", ret );
+            return( ret );
+        }
+    }
+    else
+#endif /* POLARSSL_KEY_EXCHANGE_PSK_ENABLED */
+#if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED)
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK )
+    {
+        unsigned char *p = ssl->in_msg + 4;
+        unsigned char *end = ssl->in_msg + ssl->in_hslen;
+
+        if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret );
+            return( ret );
+        }
+
+        if( ( ret = ssl_parse_encrypted_pms( ssl, p, end, 2 ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, ( "ssl_parse_encrypted_pms" ), ret );
+            return( ret );
+        }
+
+        if( ( ret = ssl_psk_derive_premaster( ssl,
+                        ciphersuite_info->key_exchange ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_psk_derive_premaster", ret );
+            return( ret );
+        }
+    }
+    else
+#endif /* POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED */
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED)
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK )
+    {
+        unsigned char *p = ssl->in_msg + 4;
+        unsigned char *end = ssl->in_msg + ssl->in_hslen;
+
+        if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret );
+            return( ret );
+        }
+        if( ( ret = ssl_parse_client_dh_public( ssl, &p, end ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, ( "ssl_parse_client_dh_public" ), ret );
+            return( ret );
+        }
+
+        if( p != end )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
+        }
+
+        if( ( ret = ssl_psk_derive_premaster( ssl,
+                        ciphersuite_info->key_exchange ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_psk_derive_premaster", ret );
+            return( ret );
+        }
+    }
+    else
+#endif /* POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK )
+    {
+        unsigned char *p = ssl->in_msg + 4;
+        unsigned char *end = ssl->in_msg + ssl->in_hslen;
+
+        if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret );
+            return( ret );
+        }
+
+        if( ( ret = ecdh_read_public( &ssl->handshake->ecdh_ctx,
+                                       p, end - p ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ecdh_read_public", ret );
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP );
+        }
+
+        SSL_DEBUG_ECP( 3, "ECDH: Qp ", &ssl->handshake->ecdh_ctx.Qp );
+
+        if( ( ret = ssl_psk_derive_premaster( ssl,
+                        ciphersuite_info->key_exchange ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_psk_derive_premaster", ret );
+            return( ret );
+        }
+    }
+    else
+#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
+#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED)
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA )
+    {
+        if( ( ret = ssl_parse_encrypted_pms( ssl,
+                                             ssl->in_msg + 4,
+                                             ssl->in_msg + ssl->in_hslen,
+                                             0 ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, ( "ssl_parse_parse_encrypted_pms_secret" ), ret );
+            return( ret );
+        }
+    }
+    else
+#endif /* POLARSSL_KEY_EXCHANGE_RSA_ENABLED */
+    {
+        SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+        return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+    }
+
+    if( ( ret = ssl_derive_keys( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_derive_keys", ret );
+        return( ret );
+    }
+
+    ssl->state++;
+
+    SSL_DEBUG_MSG( 2, ( "<= parse client key exchange" ) );
+
+    return( 0 );
+}
+
+#if !defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED)       && \
+    !defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED)   && \
+    !defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \
+    !defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+static int ssl_parse_certificate_verify( ssl_context *ssl )
+{
+    int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
+    const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
+
+    SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) );
+
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK )
+    {
+        SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) );
+        ssl->state++;
+        return( 0 );
+    }
+
+    SSL_DEBUG_MSG( 1, ( "should not happen" ) );
+    return( ret );
+}
+#else
+static int ssl_parse_certificate_verify( ssl_context *ssl )
+{
+    int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
+    size_t sa_len, sig_len;
+    unsigned char hash[48];
+    unsigned char *hash_start = hash;
+    size_t hashlen;
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+    pk_type_t pk_alg;
+#endif
+    md_type_t md_alg;
+    const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
+
+    SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) );
+
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK )
+    {
+        SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) );
+        ssl->state++;
+        return( 0 );
+    }
+
+    if( ssl->session_negotiate->peer_cert == NULL )
+    {
+        SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) );
+        ssl->state++;
+        return( 0 );
+    }
+
+    ssl->handshake->calc_verify( ssl, hash );
+
+    if( ( ret = ssl_read_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+        return( ret );
+    }
+
+    ssl->state++;
+
+    if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
+    }
+
+    if( ssl->in_msg[0] != SSL_HS_CERTIFICATE_VERIFY )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
+    }
+
+    /*
+     *     0  .   0   handshake type
+     *     1  .   3   handshake length
+     *     4  .   5   sig alg (TLS 1.2 only)
+     *    4+n .  5+n  signature length (n = sa_len)
+     *    6+n . 6+n+m signature (m = sig_len)
+     */
+
+#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_1)
+    if( ssl->minor_ver != SSL_MINOR_VERSION_3 )
+    {
+        sa_len = 0;
+
+        md_alg = POLARSSL_MD_NONE;
+        hashlen = 36;
+
+        /* For ECDSA, use SHA-1, not MD-5 + SHA-1 */
+        if( pk_can_do( &ssl->session_negotiate->peer_cert->pk,
+                        POLARSSL_PK_ECDSA ) )
+        {
+            hash_start += 16;
+            hashlen -= 16;
+            md_alg = POLARSSL_MD_SHA1;
+        }
+    }
+    else
+#endif /* POLARSSL_SSL_PROTO_SSL3 || POLARSSL_SSL_PROTO_TLS1 ||
+          POLARSSL_SSL_PROTO_TLS1_1 */
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+    if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
+    {
+        sa_len = 2;
+
+        /*
+         * Hash
+         */
+        if( ssl->in_msg[4] != ssl->handshake->verify_sig_alg )
+        {
+            SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg"
+                                " for verify message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
+        }
+
+        md_alg = ssl_md_alg_from_hash( ssl->handshake->verify_sig_alg );
+
+        /* Info from md_alg will be used instead */
+        hashlen = 0;
+
+        /*
+         * Signature
+         */
+        if( ( pk_alg = ssl_pk_alg_from_sig( ssl->in_msg[5] ) )
+                        == POLARSSL_PK_NONE )
+        {
+            SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg"
+                                " for verify message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
+        }
+
+        /*
+         * Check the certificate's key type matches the signature alg
+         */
+        if( ! pk_can_do( &ssl->session_negotiate->peer_cert->pk, pk_alg ) )
+        {
+            SSL_DEBUG_MSG( 1, ( "sig_alg doesn't match cert key" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
+        }
+    }
+    else
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
+    {
+        SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+        return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+    }
+
+    sig_len = ( ssl->in_msg[4 + sa_len] << 8 ) | ssl->in_msg[5 + sa_len];
+
+    if( sa_len + sig_len + 6 != ssl->in_hslen )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
+    }
+
+    if( ( ret = pk_verify( &ssl->session_negotiate->peer_cert->pk,
+                           md_alg, hash_start, hashlen,
+                           ssl->in_msg + 6 + sa_len, sig_len ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "pk_verify", ret );
+        return( ret );
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= parse certificate verify" ) );
+
+    return( ret );
+}
+#endif /* !POLARSSL_KEY_EXCHANGE_RSA_ENABLED &&
+          !POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED &&
+          !POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED */
+
+#if defined(POLARSSL_SSL_SESSION_TICKETS)
+static int ssl_write_new_session_ticket( ssl_context *ssl )
+{
+    int ret;
+    size_t tlen;
+    uint32_t lifetime = (uint32_t) ssl->ticket_lifetime;
+
+    SSL_DEBUG_MSG( 2, ( "=> write new session ticket" ) );
+
+    ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+    ssl->out_msg[0]  = SSL_HS_NEW_SESSION_TICKET;
+
+    /*
+     * struct {
+     *     uint32 ticket_lifetime_hint;
+     *     opaque ticket<0..2^16-1>;
+     * } NewSessionTicket;
+     *
+     * 4  .  7   ticket_lifetime_hint (0 = unspecified)
+     * 8  .  9   ticket_len (n)
+     * 10 .  9+n ticket content
+     */
+
+    ssl->out_msg[4] = ( lifetime >> 24 ) & 0xFF;
+    ssl->out_msg[5] = ( lifetime >> 16 ) & 0xFF;
+    ssl->out_msg[6] = ( lifetime >>  8 ) & 0xFF;
+    ssl->out_msg[7] = ( lifetime       ) & 0xFF;
+
+    if( ( ret = ssl_write_ticket( ssl, &tlen ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_write_ticket", ret );
+        tlen = 0;
+    }
+
+    ssl->out_msg[8] = (unsigned char)( ( tlen >> 8 ) & 0xFF );
+    ssl->out_msg[9] = (unsigned char)( ( tlen      ) & 0xFF );
+
+    ssl->out_msglen = 10 + tlen;
+
+    /*
+     * Morally equivalent to updating ssl->state, but NewSessionTicket and
+     * ChangeCipherSpec share the same state.
+     */
+    ssl->handshake->new_session_ticket = 0;
+
+    if( ( ret = ssl_write_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+        return( ret );
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= write new session ticket" ) );
+
+    return( 0 );
+}
+#endif /* POLARSSL_SSL_SESSION_TICKETS */
+
+/*
+ * SSL handshake -- server side -- single step
+ */
+int ssl_handshake_server_step( ssl_context *ssl )
+{
+    int ret = 0;
+
+    if( ssl->state == SSL_HANDSHAKE_OVER )
+        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+    SSL_DEBUG_MSG( 2, ( "server state: %d", ssl->state ) );
+
+    if( ( ret = ssl_flush_output( ssl ) ) != 0 )
+        return( ret );
+
+    switch( ssl->state )
+    {
+        case SSL_HELLO_REQUEST:
+            ssl->state = SSL_CLIENT_HELLO;
+            break;
+
+        /*
+         *  <==   ClientHello
+         */
+        case SSL_CLIENT_HELLO:
+            ret = ssl_parse_client_hello( ssl );
+            break;
+
+        /*
+         *  ==>   ServerHello
+         *        Certificate
+         *      ( ServerKeyExchange  )
+         *      ( CertificateRequest )
+         *        ServerHelloDone
+         */
+        case SSL_SERVER_HELLO:
+            ret = ssl_write_server_hello( ssl );
+            break;
+
+        case SSL_SERVER_CERTIFICATE:
+            ret = ssl_write_certificate( ssl );
+            break;
+
+        case SSL_SERVER_KEY_EXCHANGE:
+            ret = ssl_write_server_key_exchange( ssl );
+            break;
+
+        case SSL_CERTIFICATE_REQUEST:
+            ret = ssl_write_certificate_request( ssl );
+            break;
+
+        case SSL_SERVER_HELLO_DONE:
+            ret = ssl_write_server_hello_done( ssl );
+            break;
+
+        /*
+         *  <== ( Certificate/Alert  )
+         *        ClientKeyExchange
+         *      ( CertificateVerify  )
+         *        ChangeCipherSpec
+         *        Finished
+         */
+        case SSL_CLIENT_CERTIFICATE:
+            ret = ssl_parse_certificate( ssl );
+            break;
+
+        case SSL_CLIENT_KEY_EXCHANGE:
+            ret = ssl_parse_client_key_exchange( ssl );
+            break;
+
+        case SSL_CERTIFICATE_VERIFY:
+            ret = ssl_parse_certificate_verify( ssl );
+            break;
+
+        case SSL_CLIENT_CHANGE_CIPHER_SPEC:
+            ret = ssl_parse_change_cipher_spec( ssl );
+            break;
+
+        case SSL_CLIENT_FINISHED:
+            ret = ssl_parse_finished( ssl );
+            break;
+
+        /*
+         *  ==> ( NewSessionTicket )
+         *        ChangeCipherSpec
+         *        Finished
+         */
+        case SSL_SERVER_CHANGE_CIPHER_SPEC:
+#if defined(POLARSSL_SSL_SESSION_TICKETS)
+            if( ssl->handshake->new_session_ticket != 0 )
+                ret = ssl_write_new_session_ticket( ssl );
+            else
+#endif
+                ret = ssl_write_change_cipher_spec( ssl );
+            break;
+
+        case SSL_SERVER_FINISHED:
+            ret = ssl_write_finished( ssl );
+            break;
+
+        case SSL_FLUSH_BUFFERS:
+            SSL_DEBUG_MSG( 2, ( "handshake: done" ) );
+            ssl->state = SSL_HANDSHAKE_WRAPUP;
+            break;
+
+        case SSL_HANDSHAKE_WRAPUP:
+            ssl_handshake_wrapup( ssl );
+            break;
+
+        default:
+            SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) );
+            return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+    }
+
+    return( ret );
+}
+#endif /* POLARSSL_SSL_SRV_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/ssl_tls.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,4893 @@
+/*
+ *  SSLv3/TLSv1 shared functions
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  The SSL 3.0 specification was drafted by Netscape in 1996,
+ *  and became an IETF standard in 1999.
+ *
+ *  http://wp.netscape.com/eng/ssl3/
+ *  http://www.ietf.org/rfc/rfc2246.txt
+ *  http://www.ietf.org/rfc/rfc4346.txt
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_SSL_TLS_C)
+
+#include "polarssl/debug.h"
+#include "polarssl/ssl.h"
+
+#if defined(POLARSSL_X509_CRT_PARSE_C) && \
+    defined(POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE)
+#include "polarssl/oid.h"
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+#include <stdlib.h>
+
+#if defined(_MSC_VER) && !defined strcasecmp && !defined(EFIX64) && \
+    !defined(EFI32)
+#define strcasecmp _stricmp
+#endif
+
+#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH)
+/*
+ * Convert max_fragment_length codes to length.
+ * RFC 6066 says:
+ *    enum{
+ *        2^9(1), 2^10(2), 2^11(3), 2^12(4), (255)
+ *    } MaxFragmentLength;
+ * and we add 0 -> extension unused
+ */
+static unsigned int mfl_code_to_length[SSL_MAX_FRAG_LEN_INVALID] =
+{
+    SSL_MAX_CONTENT_LEN,    /* SSL_MAX_FRAG_LEN_NONE */
+    512,                    /* SSL_MAX_FRAG_LEN_512  */
+    1024,                   /* SSL_MAX_FRAG_LEN_1024 */
+    2048,                   /* SSL_MAX_FRAG_LEN_2048 */
+    4096,                   /* SSL_MAX_FRAG_LEN_4096 */
+};
+#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */
+
+static int ssl_session_copy( ssl_session *dst, const ssl_session *src )
+{
+    ssl_session_free( dst );
+    memcpy( dst, src, sizeof( ssl_session ) );
+
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+    if( src->peer_cert != NULL )
+    {
+        int ret;
+
+        dst->peer_cert = (x509_crt *) polarssl_malloc( sizeof(x509_crt) );
+        if( dst->peer_cert == NULL )
+            return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+
+        x509_crt_init( dst->peer_cert );
+
+        if( ( ret = x509_crt_parse( dst->peer_cert, src->peer_cert->raw.p,
+                                    src->peer_cert->raw.len ) != 0 ) )
+        {
+            polarssl_free( dst->peer_cert );
+            dst->peer_cert = NULL;
+            return( ret );
+        }
+    }
+#endif /* POLARSSL_X509_CRT_PARSE_C */
+
+#if defined(POLARSSL_SSL_SESSION_TICKETS)
+    if( src->ticket != NULL )
+    {
+        dst->ticket = (unsigned char *) polarssl_malloc( src->ticket_len );
+        if( dst->ticket == NULL )
+            return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+
+        memcpy( dst->ticket, src->ticket, src->ticket_len );
+    }
+#endif /* POLARSSL_SSL_SESSION_TICKETS */
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_SSL_HW_RECORD_ACCEL)
+int (*ssl_hw_record_init)(ssl_context *ssl,
+                     const unsigned char *key_enc, const unsigned char *key_dec,
+                     size_t keylen,
+                     const unsigned char *iv_enc,  const unsigned char *iv_dec,
+                     size_t ivlen,
+                     const unsigned char *mac_enc, const unsigned char *mac_dec,
+                     size_t maclen) = NULL;
+int (*ssl_hw_record_activate)(ssl_context *ssl, int direction) = NULL;
+int (*ssl_hw_record_reset)(ssl_context *ssl) = NULL;
+int (*ssl_hw_record_write)(ssl_context *ssl) = NULL;
+int (*ssl_hw_record_read)(ssl_context *ssl) = NULL;
+int (*ssl_hw_record_finish)(ssl_context *ssl) = NULL;
+#endif /* POLARSSL_SSL_HW_RECORD_ACCEL */
+
+/*
+ * Key material generation
+ */
+#if defined(POLARSSL_SSL_PROTO_SSL3)
+static int ssl3_prf( const unsigned char *secret, size_t slen,
+                     const char *label,
+                     const unsigned char *random, size_t rlen,
+                     unsigned char *dstbuf, size_t dlen )
+{
+    size_t i;
+    md5_context md5;
+    sha1_context sha1;
+    unsigned char padding[16];
+    unsigned char sha1sum[20];
+    ((void)label);
+
+    /*
+     *  SSLv3:
+     *    block =
+     *      MD5( secret + SHA1( 'A'    + secret + random ) ) +
+     *      MD5( secret + SHA1( 'BB'   + secret + random ) ) +
+     *      MD5( secret + SHA1( 'CCC'  + secret + random ) ) +
+     *      ...
+     */
+    for( i = 0; i < dlen / 16; i++ )
+    {
+        memset( padding, (unsigned char) ('A' + i), 1 + i );
+
+        sha1_starts( &sha1 );
+        sha1_update( &sha1, padding, 1 + i );
+        sha1_update( &sha1, secret, slen );
+        sha1_update( &sha1, random, rlen );
+        sha1_finish( &sha1, sha1sum );
+
+        md5_starts( &md5 );
+        md5_update( &md5, secret, slen );
+        md5_update( &md5, sha1sum, 20 );
+        md5_finish( &md5, dstbuf + i * 16 );
+    }
+
+    memset( &md5,  0, sizeof( md5  ) );
+    memset( &sha1, 0, sizeof( sha1 ) );
+
+    memset( padding, 0, sizeof( padding ) );
+    memset( sha1sum, 0, sizeof( sha1sum ) );
+
+    return( 0 );
+}
+#endif /* POLARSSL_SSL_PROTO_SSL3 */
+
+#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1)
+static int tls1_prf( const unsigned char *secret, size_t slen,
+                     const char *label,
+                     const unsigned char *random, size_t rlen,
+                     unsigned char *dstbuf, size_t dlen )
+{
+    size_t nb, hs;
+    size_t i, j, k;
+    const unsigned char *S1, *S2;
+    unsigned char tmp[128];
+    unsigned char h_i[20];
+
+    if( sizeof( tmp ) < 20 + strlen( label ) + rlen )
+        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+    hs = ( slen + 1 ) / 2;
+    S1 = secret;
+    S2 = secret + slen - hs;
+
+    nb = strlen( label );
+    memcpy( tmp + 20, label, nb );
+    memcpy( tmp + 20 + nb, random, rlen );
+    nb += rlen;
+
+    /*
+     * First compute P_md5(secret,label+random)[0..dlen]
+     */
+    md5_hmac( S1, hs, tmp + 20, nb, 4 + tmp );
+
+    for( i = 0; i < dlen; i += 16 )
+    {
+        md5_hmac( S1, hs, 4 + tmp, 16 + nb, h_i );
+        md5_hmac( S1, hs, 4 + tmp, 16,  4 + tmp );
+
+        k = ( i + 16 > dlen ) ? dlen % 16 : 16;
+
+        for( j = 0; j < k; j++ )
+            dstbuf[i + j]  = h_i[j];
+    }
+
+    /*
+     * XOR out with P_sha1(secret,label+random)[0..dlen]
+     */
+    sha1_hmac( S2, hs, tmp + 20, nb, tmp );
+
+    for( i = 0; i < dlen; i += 20 )
+    {
+        sha1_hmac( S2, hs, tmp, 20 + nb, h_i );
+        sha1_hmac( S2, hs, tmp, 20,      tmp );
+
+        k = ( i + 20 > dlen ) ? dlen % 20 : 20;
+
+        for( j = 0; j < k; j++ )
+            dstbuf[i + j] = (unsigned char)( dstbuf[i + j] ^ h_i[j] );
+    }
+
+    memset( tmp, 0, sizeof( tmp ) );
+    memset( h_i, 0, sizeof( h_i ) );
+
+    return( 0 );
+}
+#endif /* POLARSSL_SSL_PROTO_TLS1) || POLARSSL_SSL_PROTO_TLS1_1 */
+
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+#if defined(POLARSSL_SHA256_C)
+static int tls_prf_sha256( const unsigned char *secret, size_t slen,
+                           const char *label,
+                           const unsigned char *random, size_t rlen,
+                           unsigned char *dstbuf, size_t dlen )
+{
+    size_t nb;
+    size_t i, j, k;
+    unsigned char tmp[128];
+    unsigned char h_i[32];
+
+    if( sizeof( tmp ) < 32 + strlen( label ) + rlen )
+        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+    nb = strlen( label );
+    memcpy( tmp + 32, label, nb );
+    memcpy( tmp + 32 + nb, random, rlen );
+    nb += rlen;
+
+    /*
+     * Compute P_<hash>(secret, label + random)[0..dlen]
+     */
+    sha256_hmac( secret, slen, tmp + 32, nb, tmp, 0 );
+
+    for( i = 0; i < dlen; i += 32 )
+    {
+        sha256_hmac( secret, slen, tmp, 32 + nb, h_i, 0 );
+        sha256_hmac( secret, slen, tmp, 32,      tmp, 0 );
+
+        k = ( i + 32 > dlen ) ? dlen % 32 : 32;
+
+        for( j = 0; j < k; j++ )
+            dstbuf[i + j]  = h_i[j];
+    }
+
+    memset( tmp, 0, sizeof( tmp ) );
+    memset( h_i, 0, sizeof( h_i ) );
+
+    return( 0 );
+}
+#endif /* POLARSSL_SHA256_C */
+
+#if defined(POLARSSL_SHA512_C)
+static int tls_prf_sha384( const unsigned char *secret, size_t slen,
+                           const char *label,
+                           const unsigned char *random, size_t rlen,
+                           unsigned char *dstbuf, size_t dlen )
+{
+    size_t nb;
+    size_t i, j, k;
+    unsigned char tmp[128];
+    unsigned char h_i[48];
+
+    if( sizeof( tmp ) < 48 + strlen( label ) + rlen )
+        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+    nb = strlen( label );
+    memcpy( tmp + 48, label, nb );
+    memcpy( tmp + 48 + nb, random, rlen );
+    nb += rlen;
+
+    /*
+     * Compute P_<hash>(secret, label + random)[0..dlen]
+     */
+    sha512_hmac( secret, slen, tmp + 48, nb, tmp, 1 );
+
+    for( i = 0; i < dlen; i += 48 )
+    {
+        sha512_hmac( secret, slen, tmp, 48 + nb, h_i, 1 );
+        sha512_hmac( secret, slen, tmp, 48,      tmp, 1 );
+
+        k = ( i + 48 > dlen ) ? dlen % 48 : 48;
+
+        for( j = 0; j < k; j++ )
+            dstbuf[i + j]  = h_i[j];
+    }
+
+    memset( tmp, 0, sizeof( tmp ) );
+    memset( h_i, 0, sizeof( h_i ) );
+
+    return( 0 );
+}
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
+
+static void ssl_update_checksum_start(ssl_context *, const unsigned char *, size_t);
+
+#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_1)
+static void ssl_update_checksum_md5sha1(ssl_context *, const unsigned char *, size_t);
+#endif
+
+#if defined(POLARSSL_SSL_PROTO_SSL3)
+static void ssl_calc_verify_ssl(ssl_context *,unsigned char *);
+static void ssl_calc_finished_ssl(ssl_context *,unsigned char *,int);
+#endif
+
+#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1)
+static void ssl_calc_verify_tls(ssl_context *,unsigned char *);
+static void ssl_calc_finished_tls(ssl_context *,unsigned char *,int);
+#endif
+
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+#if defined(POLARSSL_SHA256_C)
+static void ssl_update_checksum_sha256(ssl_context *, const unsigned char *, size_t);
+static void ssl_calc_verify_tls_sha256(ssl_context *,unsigned char *);
+static void ssl_calc_finished_tls_sha256(ssl_context *,unsigned char *,int);
+#endif
+
+#if defined(POLARSSL_SHA512_C)
+static void ssl_update_checksum_sha384(ssl_context *, const unsigned char *, size_t);
+static void ssl_calc_verify_tls_sha384(ssl_context *,unsigned char *);
+static void ssl_calc_finished_tls_sha384(ssl_context *,unsigned char *,int);
+#endif
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
+
+int ssl_derive_keys( ssl_context *ssl )
+{
+    int ret = 0;
+    unsigned char tmp[64];
+    unsigned char keyblk[256];
+    unsigned char *key1;
+    unsigned char *key2;
+    unsigned char *mac_enc;
+    unsigned char *mac_dec;
+    size_t iv_copy_len;
+    const cipher_info_t *cipher_info;
+    const md_info_t *md_info;
+
+    ssl_session *session = ssl->session_negotiate;
+    ssl_transform *transform = ssl->transform_negotiate;
+    ssl_handshake_params *handshake = ssl->handshake;
+
+    SSL_DEBUG_MSG( 2, ( "=> derive keys" ) );
+
+    cipher_info = cipher_info_from_type( transform->ciphersuite_info->cipher );
+    if( cipher_info == NULL )
+    {
+        SSL_DEBUG_MSG( 1, ( "cipher info for %d not found",
+                            transform->ciphersuite_info->cipher ) );
+        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+    }
+
+    md_info = md_info_from_type( transform->ciphersuite_info->mac );
+    if( md_info == NULL )
+    {
+        SSL_DEBUG_MSG( 1, ( "md info for %d not found",
+                            transform->ciphersuite_info->mac ) );
+        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+    }
+
+    /*
+     * Set appropriate PRF function and other SSL / TLS / TLS1.2 functions
+     */
+#if defined(POLARSSL_SSL_PROTO_SSL3)
+    if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
+    {
+        handshake->tls_prf = ssl3_prf;
+        handshake->calc_verify = ssl_calc_verify_ssl;
+        handshake->calc_finished = ssl_calc_finished_ssl;
+    }
+    else
+#endif
+#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1)
+    if( ssl->minor_ver < SSL_MINOR_VERSION_3 )
+    {
+        handshake->tls_prf = tls1_prf;
+        handshake->calc_verify = ssl_calc_verify_tls;
+        handshake->calc_finished = ssl_calc_finished_tls;
+    }
+    else
+#endif
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+#if defined(POLARSSL_SHA512_C)
+    if( ssl->minor_ver == SSL_MINOR_VERSION_3 &&
+        transform->ciphersuite_info->mac == POLARSSL_MD_SHA384 )
+    {
+        handshake->tls_prf = tls_prf_sha384;
+        handshake->calc_verify = ssl_calc_verify_tls_sha384;
+        handshake->calc_finished = ssl_calc_finished_tls_sha384;
+    }
+    else
+#endif
+#if defined(POLARSSL_SHA256_C)
+    if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
+    {
+        handshake->tls_prf = tls_prf_sha256;
+        handshake->calc_verify = ssl_calc_verify_tls_sha256;
+        handshake->calc_finished = ssl_calc_finished_tls_sha256;
+    }
+    else
+#endif
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
+    {
+        SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+        return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+    }
+
+    /*
+     * SSLv3:
+     *   master =
+     *     MD5( premaster + SHA1( 'A'   + premaster + randbytes ) ) +
+     *     MD5( premaster + SHA1( 'BB'  + premaster + randbytes ) ) +
+     *     MD5( premaster + SHA1( 'CCC' + premaster + randbytes ) )
+     *
+     * TLSv1+:
+     *   master = PRF( premaster, "master secret", randbytes )[0..47]
+     */
+    if( handshake->resume == 0 )
+    {
+        SSL_DEBUG_BUF( 3, "premaster secret", handshake->premaster,
+                       handshake->pmslen );
+
+        handshake->tls_prf( handshake->premaster, handshake->pmslen,
+                            "master secret",
+                            handshake->randbytes, 64, session->master, 48 );
+
+        memset( handshake->premaster, 0, sizeof( handshake->premaster ) );
+    }
+    else
+        SSL_DEBUG_MSG( 3, ( "no premaster (session resumed)" ) );
+
+    /*
+     * Swap the client and server random values.
+     */
+    memcpy( tmp, handshake->randbytes, 64 );
+    memcpy( handshake->randbytes, tmp + 32, 32 );
+    memcpy( handshake->randbytes + 32, tmp, 32 );
+    memset( tmp, 0, sizeof( tmp ) );
+
+    /*
+     *  SSLv3:
+     *    key block =
+     *      MD5( master + SHA1( 'A'    + master + randbytes ) ) +
+     *      MD5( master + SHA1( 'BB'   + master + randbytes ) ) +
+     *      MD5( master + SHA1( 'CCC'  + master + randbytes ) ) +
+     *      MD5( master + SHA1( 'DDDD' + master + randbytes ) ) +
+     *      ...
+     *
+     *  TLSv1:
+     *    key block = PRF( master, "key expansion", randbytes )
+     */
+    handshake->tls_prf( session->master, 48, "key expansion",
+                        handshake->randbytes, 64, keyblk, 256 );
+
+    SSL_DEBUG_MSG( 3, ( "ciphersuite = %s",
+                   ssl_get_ciphersuite_name( session->ciphersuite ) ) );
+    SSL_DEBUG_BUF( 3, "master secret", session->master, 48 );
+    SSL_DEBUG_BUF( 4, "random bytes", handshake->randbytes, 64 );
+    SSL_DEBUG_BUF( 4, "key block", keyblk, 256 );
+
+    memset( handshake->randbytes, 0, sizeof( handshake->randbytes ) );
+
+    /*
+     * Determine the appropriate key, IV and MAC length.
+     */
+
+    if( cipher_info->mode == POLARSSL_MODE_GCM )
+    {
+        transform->keylen = cipher_info->key_length;
+        transform->keylen /= 8;
+        transform->minlen = 1;
+        transform->ivlen = 12;
+        transform->fixed_ivlen = 4;
+        transform->maclen = 0;
+    }
+    else
+    {
+        if( md_info->type != POLARSSL_MD_NONE )
+        {
+            int ret;
+
+            if( ( ret = md_init_ctx( &transform->md_ctx_enc, md_info ) ) != 0 )
+            {
+                SSL_DEBUG_RET( 1, "md_init_ctx", ret );
+                return( ret );
+            }
+
+            if( ( ret = md_init_ctx( &transform->md_ctx_dec, md_info ) ) != 0 )
+            {
+                SSL_DEBUG_RET( 1, "md_init_ctx", ret );
+                return( ret );
+            }
+
+            transform->maclen = md_get_size( md_info );
+
+#if defined(POLARSSL_SSL_TRUNCATED_HMAC)
+            /*
+             * If HMAC is to be truncated, we shall keep the leftmost bytes,
+             * (rfc 6066 page 13 or rfc 2104 section 4),
+             * so we only need to adjust the length here.
+             */
+            if( session->trunc_hmac == SSL_TRUNC_HMAC_ENABLED )
+                transform->maclen = SSL_TRUNCATED_HMAC_LEN;
+#endif /* POLARSSL_SSL_TRUNCATED_HMAC */
+        }
+
+        transform->keylen = cipher_info->key_length;
+        transform->keylen /= 8;
+        transform->ivlen = cipher_info->iv_size;
+
+        transform->minlen = transform->keylen;
+        if( transform->minlen < transform->maclen )
+        {
+            if( cipher_info->mode == POLARSSL_MODE_STREAM )
+                transform->minlen = transform->maclen;
+            else
+                transform->minlen += transform->keylen;
+        }
+    }
+
+    SSL_DEBUG_MSG( 3, ( "keylen: %d, minlen: %d, ivlen: %d, maclen: %d",
+                   transform->keylen, transform->minlen, transform->ivlen,
+                   transform->maclen ) );
+
+    /*
+     * Finally setup the cipher contexts, IVs and MAC secrets.
+     */
+    if( ssl->endpoint == SSL_IS_CLIENT )
+    {
+        key1 = keyblk + transform->maclen * 2;
+        key2 = keyblk + transform->maclen * 2 + transform->keylen;
+
+        mac_enc = keyblk;
+        mac_dec = keyblk + transform->maclen;
+
+        /*
+         * This is not used in TLS v1.1.
+         */
+        iv_copy_len = ( transform->fixed_ivlen ) ?
+                            transform->fixed_ivlen : transform->ivlen;
+        memcpy( transform->iv_enc, key2 + transform->keylen,  iv_copy_len );
+        memcpy( transform->iv_dec, key2 + transform->keylen + iv_copy_len,
+                iv_copy_len );
+    }
+    else
+    {
+        key1 = keyblk + transform->maclen * 2 + transform->keylen;
+        key2 = keyblk + transform->maclen * 2;
+
+        mac_enc = keyblk + transform->maclen;
+        mac_dec = keyblk;
+
+        /*
+         * This is not used in TLS v1.1.
+         */
+        iv_copy_len = ( transform->fixed_ivlen ) ?
+                            transform->fixed_ivlen : transform->ivlen;
+        memcpy( transform->iv_dec, key1 + transform->keylen,  iv_copy_len );
+        memcpy( transform->iv_enc, key1 + transform->keylen + iv_copy_len,
+                iv_copy_len );
+    }
+
+#if defined(POLARSSL_SSL_PROTO_SSL3)
+    if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
+    {
+        if( transform->maclen > sizeof transform->mac_enc )
+        {
+            SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+            return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+        }
+
+        memcpy( transform->mac_enc, mac_enc, transform->maclen );
+        memcpy( transform->mac_dec, mac_dec, transform->maclen );
+    }
+    else
+#endif /* POLARSSL_SSL_PROTO_SSL3 */
+#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_2)
+    if( ssl->minor_ver >= SSL_MINOR_VERSION_1 )
+    {
+        md_hmac_starts( &transform->md_ctx_enc, mac_enc, transform->maclen );
+        md_hmac_starts( &transform->md_ctx_dec, mac_dec, transform->maclen );
+    }
+    else
+#endif
+    {
+        SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+        return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+    }
+
+#if defined(POLARSSL_SSL_HW_RECORD_ACCEL)
+    if( ssl_hw_record_init != NULL)
+    {
+        int ret = 0;
+
+        SSL_DEBUG_MSG( 2, ( "going for ssl_hw_record_init()" ) );
+
+        if( ( ret = ssl_hw_record_init( ssl, key1, key2, transform->keylen,
+                                        transform->iv_enc, transform->iv_dec,
+                                        iv_copy_len,
+                                        mac_enc, mac_dec,
+                                        transform->maclen ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_hw_record_init", ret );
+            return POLARSSL_ERR_SSL_HW_ACCEL_FAILED;
+        }
+    }
+#endif /* POLARSSL_SSL_HW_RECORD_ACCEL */
+
+    if( ( ret = cipher_init_ctx( &transform->cipher_ctx_enc,
+                                 cipher_info ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "cipher_init_ctx", ret );
+        return( ret );
+    }
+
+    if( ( ret = cipher_init_ctx( &transform->cipher_ctx_dec,
+                                 cipher_info ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "cipher_init_ctx", ret );
+        return( ret );
+    }
+
+    if( ( ret = cipher_setkey( &transform->cipher_ctx_enc, key1,
+                               cipher_info->key_length,
+                               POLARSSL_ENCRYPT ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "cipher_setkey", ret );
+        return( ret );
+    }
+
+    if( ( ret = cipher_setkey( &transform->cipher_ctx_dec, key2,
+                               cipher_info->key_length,
+                               POLARSSL_DECRYPT ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "cipher_setkey", ret );
+        return( ret );
+    }
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    if( cipher_info->mode == POLARSSL_MODE_CBC )
+    {
+        if( ( ret = cipher_set_padding_mode( &transform->cipher_ctx_enc,
+                                             POLARSSL_PADDING_NONE ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_set_padding_mode", ret );
+            return( ret );
+        }
+
+        if( ( ret = cipher_set_padding_mode( &transform->cipher_ctx_dec,
+                                             POLARSSL_PADDING_NONE ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_set_padding_mode", ret );
+            return( ret );
+        }
+    }
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+    memset( keyblk, 0, sizeof( keyblk ) );
+
+#if defined(POLARSSL_ZLIB_SUPPORT)
+    // Initialize compression
+    //
+    if( session->compression == SSL_COMPRESS_DEFLATE )
+    {
+        if( ssl->compress_buf == NULL )
+        {
+            SSL_DEBUG_MSG( 3, ( "Allocating compression buffer" ) );
+            ssl->compress_buf = polarssl_malloc( SSL_BUFFER_LEN );
+            if( ssl->compress_buf == NULL )
+            {
+                SSL_DEBUG_MSG( 1, ( "malloc(%d bytes) failed",
+                                    SSL_BUFFER_LEN ) );
+                return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+            }
+        }
+
+        SSL_DEBUG_MSG( 3, ( "Initializing zlib states" ) );
+
+        memset( &transform->ctx_deflate, 0, sizeof( transform->ctx_deflate ) );
+        memset( &transform->ctx_inflate, 0, sizeof( transform->ctx_inflate ) );
+
+        if( deflateInit( &transform->ctx_deflate,
+                         Z_DEFAULT_COMPRESSION )   != Z_OK ||
+            inflateInit( &transform->ctx_inflate ) != Z_OK )
+        {
+            SSL_DEBUG_MSG( 1, ( "Failed to initialize compression" ) );
+            return( POLARSSL_ERR_SSL_COMPRESSION_FAILED );
+        }
+    }
+#endif /* POLARSSL_ZLIB_SUPPORT */
+
+    SSL_DEBUG_MSG( 2, ( "<= derive keys" ) );
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_SSL_PROTO_SSL3)
+void ssl_calc_verify_ssl( ssl_context *ssl, unsigned char hash[36] )
+{
+    md5_context md5;
+    sha1_context sha1;
+    unsigned char pad_1[48];
+    unsigned char pad_2[48];
+
+    SSL_DEBUG_MSG( 2, ( "=> calc verify ssl" ) );
+
+    memcpy( &md5 , &ssl->handshake->fin_md5 , sizeof(md5_context)  );
+    memcpy( &sha1, &ssl->handshake->fin_sha1, sizeof(sha1_context) );
+
+    memset( pad_1, 0x36, 48 );
+    memset( pad_2, 0x5C, 48 );
+
+    md5_update( &md5, ssl->session_negotiate->master, 48 );
+    md5_update( &md5, pad_1, 48 );
+    md5_finish( &md5, hash );
+
+    md5_starts( &md5 );
+    md5_update( &md5, ssl->session_negotiate->master, 48 );
+    md5_update( &md5, pad_2, 48 );
+    md5_update( &md5, hash,  16 );
+    md5_finish( &md5, hash );
+
+    sha1_update( &sha1, ssl->session_negotiate->master, 48 );
+    sha1_update( &sha1, pad_1, 40 );
+    sha1_finish( &sha1, hash + 16 );
+
+    sha1_starts( &sha1 );
+    sha1_update( &sha1, ssl->session_negotiate->master, 48 );
+    sha1_update( &sha1, pad_2, 40 );
+    sha1_update( &sha1, hash + 16, 20 );
+    sha1_finish( &sha1, hash + 16 );
+
+    SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 );
+    SSL_DEBUG_MSG( 2, ( "<= calc verify" ) );
+
+    return;
+}
+#endif /* POLARSSL_SSL_PROTO_SSL3 */
+
+#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1)
+void ssl_calc_verify_tls( ssl_context *ssl, unsigned char hash[36] )
+{
+    md5_context md5;
+    sha1_context sha1;
+
+    SSL_DEBUG_MSG( 2, ( "=> calc verify tls" ) );
+
+    memcpy( &md5 , &ssl->handshake->fin_md5 , sizeof(md5_context)  );
+    memcpy( &sha1, &ssl->handshake->fin_sha1, sizeof(sha1_context) );
+
+     md5_finish( &md5,  hash );
+    sha1_finish( &sha1, hash + 16 );
+
+    SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 );
+    SSL_DEBUG_MSG( 2, ( "<= calc verify" ) );
+
+    return;
+}
+#endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 */
+
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+#if defined(POLARSSL_SHA256_C)
+void ssl_calc_verify_tls_sha256( ssl_context *ssl, unsigned char hash[32] )
+{
+    sha256_context sha256;
+
+    SSL_DEBUG_MSG( 2, ( "=> calc verify sha256" ) );
+
+    memcpy( &sha256, &ssl->handshake->fin_sha256, sizeof(sha256_context) );
+    sha256_finish( &sha256, hash );
+
+    SSL_DEBUG_BUF( 3, "calculated verify result", hash, 32 );
+    SSL_DEBUG_MSG( 2, ( "<= calc verify" ) );
+
+    return;
+}
+#endif /* POLARSSL_SHA256_C */
+
+#if defined(POLARSSL_SHA512_C)
+void ssl_calc_verify_tls_sha384( ssl_context *ssl, unsigned char hash[48] )
+{
+    sha512_context sha512;
+
+    SSL_DEBUG_MSG( 2, ( "=> calc verify sha384" ) );
+
+    memcpy( &sha512, &ssl->handshake->fin_sha512, sizeof(sha512_context) );
+    sha512_finish( &sha512, hash );
+
+    SSL_DEBUG_BUF( 3, "calculated verify result", hash, 48 );
+    SSL_DEBUG_MSG( 2, ( "<= calc verify" ) );
+
+    return;
+}
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
+
+#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
+int ssl_psk_derive_premaster( ssl_context *ssl, key_exchange_type_t key_ex )
+{
+    unsigned char *p = ssl->handshake->premaster;
+    unsigned char *end = p + sizeof( ssl->handshake->premaster );
+
+    /*
+     * PMS = struct {
+     *     opaque other_secret<0..2^16-1>;
+     *     opaque psk<0..2^16-1>;
+     * };
+     * with "other_secret" depending on the particular key exchange
+     */
+#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED)
+    if( key_ex == POLARSSL_KEY_EXCHANGE_PSK )
+    {
+        if( end - p < 2 + (int) ssl->psk_len )
+            return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+        *(p++) = (unsigned char)( ssl->psk_len >> 8 );
+        *(p++) = (unsigned char)( ssl->psk_len      );
+        p += ssl->psk_len;
+    }
+    else
+#endif /* POLARSSL_KEY_EXCHANGE_PSK_ENABLED */
+#if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED)
+    if( key_ex == POLARSSL_KEY_EXCHANGE_RSA_PSK )
+    {
+        /*
+         * other_secret already set by the ClientKeyExchange message,
+         * and is 48 bytes long
+         */
+        *p++ = 0;
+        *p++ = 48;
+        p += 48;
+    }
+    else
+#endif /* POLARSSL_KEY_EXCHANGE_RSA_PKS_ENABLED */
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED)
+    if( key_ex == POLARSSL_KEY_EXCHANGE_DHE_PSK )
+    {
+        int ret;
+        size_t len = ssl->handshake->dhm_ctx.len;
+
+        if( end - p < 2 + (int) len )
+            return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+        *(p++) = (unsigned char)( len >> 8 );
+        *(p++) = (unsigned char)( len );
+        if( ( ret = dhm_calc_secret( &ssl->handshake->dhm_ctx,
+                                      p, &len, ssl->f_rng, ssl->p_rng ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "dhm_calc_secret", ret );
+            return( ret );
+        }
+        p += len;
+
+        SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K  );
+    }
+    else
+#endif /* POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
+    if( key_ex == POLARSSL_KEY_EXCHANGE_ECDHE_PSK )
+    {
+        int ret;
+        size_t zlen;
+
+        if( ( ret = ecdh_calc_secret( &ssl->handshake->ecdh_ctx, &zlen,
+                                       p + 2, end - (p + 2),
+                                       ssl->f_rng, ssl->p_rng ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ecdh_calc_secret", ret );
+            return( ret );
+        }
+
+        *(p++) = (unsigned char)( zlen >> 8 );
+        *(p++) = (unsigned char)( zlen      );
+        p += zlen;
+
+        SSL_DEBUG_MPI( 3, "ECDH: z", &ssl->handshake->ecdh_ctx.z );
+    }
+    else
+#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
+    {
+        SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+        return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+    }
+
+    /* opaque psk<0..2^16-1>; */
+    if( end - p < 2 + (int) ssl->psk_len )
+            return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+    *(p++) = (unsigned char)( ssl->psk_len >> 8 );
+    *(p++) = (unsigned char)( ssl->psk_len      );
+    memcpy( p, ssl->psk, ssl->psk_len );
+    p += ssl->psk_len;
+
+    ssl->handshake->pmslen = p - ssl->handshake->premaster;
+
+    return( 0 );
+}
+#endif /* POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED */
+
+#if defined(POLARSSL_SSL_PROTO_SSL3)
+/*
+ * SSLv3.0 MAC functions
+ */
+static void ssl_mac( md_context_t *md_ctx, unsigned char *secret,
+                     unsigned char *buf, size_t len,
+                     unsigned char *ctr, int type )
+{
+    unsigned char header[11];
+    unsigned char padding[48];
+    int padlen = 0;
+    int md_size = md_get_size( md_ctx->md_info );
+    int md_type = md_get_type( md_ctx->md_info );
+
+    if( md_type == POLARSSL_MD_MD5 )
+        padlen = 48;
+    else if( md_type == POLARSSL_MD_SHA1 )
+        padlen = 40;
+    else if( md_type == POLARSSL_MD_SHA256 )
+        padlen = 32;
+    else if( md_type == POLARSSL_MD_SHA384 )
+        padlen = 16;
+
+    memcpy( header, ctr, 8 );
+    header[ 8] = (unsigned char)  type;
+    header[ 9] = (unsigned char)( len >> 8 );
+    header[10] = (unsigned char)( len      );
+
+    memset( padding, 0x36, padlen );
+    md_starts( md_ctx );
+    md_update( md_ctx, secret,  md_size );
+    md_update( md_ctx, padding, padlen  );
+    md_update( md_ctx, header,  11      );
+    md_update( md_ctx, buf,     len     );
+    md_finish( md_ctx, buf +    len     );
+
+    memset( padding, 0x5C, padlen );
+    md_starts( md_ctx );
+    md_update( md_ctx, secret,    md_size );
+    md_update( md_ctx, padding,   padlen  );
+    md_update( md_ctx, buf + len, md_size );
+    md_finish( md_ctx, buf + len          );
+}
+#endif /* POLARSSL_SSL_PROTO_SSL3 */
+
+/*
+ * Encryption/decryption functions
+ */
+static int ssl_encrypt_buf( ssl_context *ssl )
+{
+    size_t i;
+
+    SSL_DEBUG_MSG( 2, ( "=> encrypt buf" ) );
+
+    /*
+     * Add MAC before encrypt, except for GCM
+     */
+#if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER) ||     \
+    ( defined(POLARSSL_CIPHER_MODE_CBC) &&                                  \
+      ( defined(POLARSSL_AES_C) || defined(POLARSSL_CAMELLIA_C) ) )
+    if( ssl->transform_out->cipher_ctx_enc.cipher_info->mode !=
+                                                        POLARSSL_MODE_GCM )
+    {
+#if defined(POLARSSL_SSL_PROTO_SSL3)
+        if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
+        {
+            ssl_mac( &ssl->transform_out->md_ctx_enc,
+                      ssl->transform_out->mac_enc,
+                      ssl->out_msg, ssl->out_msglen,
+                      ssl->out_ctr, ssl->out_msgtype );
+        }
+        else
+#endif
+#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \
+        defined(POLARSSL_SSL_PROTO_TLS1_2)
+        if( ssl->minor_ver >= SSL_MINOR_VERSION_1 )
+        {
+            md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_ctr, 13 );
+            md_hmac_update( &ssl->transform_out->md_ctx_enc,
+                             ssl->out_msg, ssl->out_msglen );
+            md_hmac_finish( &ssl->transform_out->md_ctx_enc,
+                             ssl->out_msg + ssl->out_msglen );
+            md_hmac_reset( &ssl->transform_out->md_ctx_enc );
+        }
+        else
+#endif
+        {
+            SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+            return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+        }
+
+        SSL_DEBUG_BUF( 4, "computed mac",
+                       ssl->out_msg + ssl->out_msglen,
+                       ssl->transform_out->maclen );
+
+        ssl->out_msglen += ssl->transform_out->maclen;
+    }
+#endif /* GCM not the only option */
+
+    /*
+     * Encrypt
+     */
+#if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER)
+    if( ssl->transform_out->cipher_ctx_enc.cipher_info->mode ==
+                                                        POLARSSL_MODE_STREAM )
+    {
+        int ret;
+        size_t olen = 0;
+
+        SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
+                            "including %d bytes of padding",
+                       ssl->out_msglen, 0 ) );
+
+        SSL_DEBUG_BUF( 4, "before encrypt: output payload",
+                       ssl->out_msg, ssl->out_msglen );
+
+        if( ( ret = cipher_reset( &ssl->transform_out->cipher_ctx_enc ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_reset", ret );
+            return( ret );
+        }
+
+        if( ( ret = cipher_set_iv( &ssl->transform_out->cipher_ctx_enc,
+                                   ssl->transform_out->iv_enc,
+                                   ssl->transform_out->ivlen ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_set_iv", ret );
+            return( ret );
+        }
+
+        if( ( ret = cipher_update( &ssl->transform_out->cipher_ctx_enc,
+                                   ssl->out_msg, ssl->out_msglen, ssl->out_msg,
+                                   &olen ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_update", ret );
+            return( ret );
+        }
+
+        if( ssl->out_msglen != olen )
+        {
+            SSL_DEBUG_MSG( 1, ( "total encrypted length incorrect %d %d",
+                                ssl->out_msglen, olen ) );
+            return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
+        }
+
+        if( ( ret = cipher_finish( &ssl->transform_out->cipher_ctx_enc,
+                                   ssl->out_msg + olen, &olen ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_finish", ret );
+            return( ret );
+        }
+
+        if( 0 != olen )
+        {
+            SSL_DEBUG_MSG( 1, ( "total encrypted length incorrect %d %d",
+                                0, olen ) );
+            return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
+        }
+    }
+    else
+#endif /* POLARSSL_ARC4_C || POLARSSL_CIPHER_NULL_CIPHER */
+#if defined(POLARSSL_GCM_C)
+    if( ssl->transform_out->cipher_ctx_enc.cipher_info->mode ==
+                                                        POLARSSL_MODE_GCM )
+    {
+        size_t enc_msglen, olen, totlen;
+        unsigned char *enc_msg;
+        unsigned char add_data[13];
+        int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
+
+        memcpy( add_data, ssl->out_ctr, 8 );
+        add_data[8]  = ssl->out_msgtype;
+        add_data[9]  = ssl->major_ver;
+        add_data[10] = ssl->minor_ver;
+        add_data[11] = ( ssl->out_msglen >> 8 ) & 0xFF;
+        add_data[12] = ssl->out_msglen & 0xFF;
+
+        SSL_DEBUG_BUF( 4, "additional data used for AEAD",
+                       add_data, 13 );
+
+        /*
+         * Generate IV
+         */
+        ret = ssl->f_rng( ssl->p_rng,
+                ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen,
+                ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen );
+        if( ret != 0 )
+            return( ret );
+
+        memcpy( ssl->out_iv,
+                ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen,
+                ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen );
+
+        SSL_DEBUG_BUF( 4, "IV used", ssl->out_iv,
+                ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen );
+
+        /*
+         * Fix pointer positions and message length with added IV
+         */
+        enc_msg = ssl->out_msg;
+        enc_msglen = ssl->out_msglen;
+        ssl->out_msglen += ssl->transform_out->ivlen -
+                           ssl->transform_out->fixed_ivlen;
+
+        SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
+                            "including %d bytes of padding",
+                       ssl->out_msglen, 0 ) );
+
+        SSL_DEBUG_BUF( 4, "before encrypt: output payload",
+                       ssl->out_msg, ssl->out_msglen );
+
+        /*
+         * Encrypt
+         */
+        if( ( ret = cipher_set_iv( &ssl->transform_out->cipher_ctx_enc,
+                                    ssl->transform_out->iv_enc,
+                                    ssl->transform_out->ivlen ) ) != 0 ||
+            ( ret = cipher_reset( &ssl->transform_out->cipher_ctx_enc ) ) != 0 )
+        {
+            return( ret );
+        }
+
+        if( ( ret = cipher_update_ad( &ssl->transform_out->cipher_ctx_enc,
+                                      add_data, 13 ) ) != 0 )
+        {
+            return( ret );
+        }
+
+        if( ( ret = cipher_update( &ssl->transform_out->cipher_ctx_enc,
+                                   enc_msg, enc_msglen,
+                                   enc_msg, &olen ) ) != 0 )
+        {
+            return( ret );
+        }
+        totlen = olen;
+
+        if( ( ret = cipher_finish( &ssl->transform_out->cipher_ctx_enc,
+                                   enc_msg + olen, &olen ) ) != 0 )
+        {
+            return( ret );
+        }
+        totlen += olen;
+
+        if( totlen != enc_msglen )
+        {
+            SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+            return( -1 );
+        }
+
+        /*
+         * Authenticate
+         */
+        ssl->out_msglen += 16;
+
+        if( ( ret = cipher_write_tag( &ssl->transform_out->cipher_ctx_enc,
+                                      enc_msg + enc_msglen, 16 ) ) != 0 )
+        {
+            return( ret );
+        }
+
+        SSL_DEBUG_BUF( 4, "after encrypt: tag", enc_msg + enc_msglen, 16 );
+    }
+    else
+#endif /* POLARSSL_GCM_C */
+#if defined(POLARSSL_CIPHER_MODE_CBC) &&                                    \
+    ( defined(POLARSSL_AES_C) || defined(POLARSSL_CAMELLIA_C) )
+    if( ssl->transform_out->cipher_ctx_enc.cipher_info->mode ==
+                                                        POLARSSL_MODE_CBC )
+    {
+        int ret;
+        unsigned char *enc_msg;
+        size_t enc_msglen, padlen, olen = 0;
+
+        padlen = ssl->transform_out->ivlen - ( ssl->out_msglen + 1 ) %
+                 ssl->transform_out->ivlen;
+        if( padlen == ssl->transform_out->ivlen )
+            padlen = 0;
+
+        for( i = 0; i <= padlen; i++ )
+            ssl->out_msg[ssl->out_msglen + i] = (unsigned char) padlen;
+
+        ssl->out_msglen += padlen + 1;
+
+        enc_msglen = ssl->out_msglen;
+        enc_msg = ssl->out_msg;
+
+#if defined(POLARSSL_SSL_PROTO_TLS1_1) || defined(POLARSSL_SSL_PROTO_TLS1_2)
+        /*
+         * Prepend per-record IV for block cipher in TLS v1.1 and up as per
+         * Method 1 (6.2.3.2. in RFC4346 and RFC5246)
+         */
+        if( ssl->minor_ver >= SSL_MINOR_VERSION_2 )
+        {
+            /*
+             * Generate IV
+             */
+            int ret = ssl->f_rng( ssl->p_rng, ssl->transform_out->iv_enc,
+                                  ssl->transform_out->ivlen );
+            if( ret != 0 )
+                return( ret );
+
+            memcpy( ssl->out_iv, ssl->transform_out->iv_enc,
+                    ssl->transform_out->ivlen );
+
+            /*
+             * Fix pointer positions and message length with added IV
+             */
+            enc_msg = ssl->out_msg;
+            enc_msglen = ssl->out_msglen;
+            ssl->out_msglen += ssl->transform_out->ivlen;
+        }
+#endif /* POLARSSL_SSL_PROTO_TLS1_1 || POLARSSL_SSL_PROTO_TLS1_2 */
+
+        SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
+                            "including %d bytes of IV and %d bytes of padding",
+                            ssl->out_msglen, ssl->transform_out->ivlen,
+                            padlen + 1 ) );
+
+        SSL_DEBUG_BUF( 4, "before encrypt: output payload",
+                       ssl->out_iv, ssl->out_msglen );
+
+        if( ( ret = cipher_reset( &ssl->transform_out->cipher_ctx_enc ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_reset", ret );
+            return( ret );
+        }
+
+        if( ( ret = cipher_set_iv( &ssl->transform_out->cipher_ctx_enc,
+                                   ssl->transform_out->iv_enc,
+                                   ssl->transform_out->ivlen ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_set_iv", ret );
+            return( ret );
+        }
+
+        if( ( ret = cipher_update( &ssl->transform_out->cipher_ctx_enc,
+                                   enc_msg, enc_msglen, enc_msg,
+                                   &olen ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_update", ret );
+            return( ret );
+        }
+
+        enc_msglen -= olen;
+
+        if( ( ret = cipher_finish( &ssl->transform_out->cipher_ctx_enc,
+                                   enc_msg + olen, &olen ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_finish", ret );
+            return( ret );
+        }
+
+        if( enc_msglen != olen )
+        {
+            SSL_DEBUG_MSG( 1, ( "total encrypted length incorrect %d %d",
+                                enc_msglen, olen ) );
+            return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
+        }
+
+#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1)
+        if( ssl->minor_ver < SSL_MINOR_VERSION_2 )
+        {
+            /*
+             * Save IV in SSL3 and TLS1
+             */
+            memcpy( ssl->transform_out->iv_enc,
+                    ssl->transform_out->cipher_ctx_enc.iv,
+                    ssl->transform_out->ivlen );
+        }
+#endif
+    }
+    else
+#endif /* POLARSSL_CIPHER_MODE_CBC &&
+          ( POLARSSL_AES_C || POLARSSL_CAMELLIA_C ) */
+    {
+        SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+        return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+    }
+
+    for( i = 8; i > 0; i-- )
+        if( ++ssl->out_ctr[i - 1] != 0 )
+            break;
+
+    /* The loops goes to its end iff the counter is wrapping */
+    if( i == 0 )
+    {
+        SSL_DEBUG_MSG( 1, ( "outgoing message counter would wrap" ) );
+        return( POLARSSL_ERR_SSL_COUNTER_WRAPPING );
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= encrypt buf" ) );
+
+    return( 0 );
+}
+
+#define POLARSSL_SSL_MAX_MAC_SIZE   48
+
+static int ssl_decrypt_buf( ssl_context *ssl )
+{
+    size_t i;
+#if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER) ||     \
+    ( defined(POLARSSL_CIPHER_MODE_CBC) &&                                  \
+      ( defined(POLARSSL_AES_C) || defined(POLARSSL_CAMELLIA_C) ) )
+    size_t padlen = 0, correct = 1;
+#endif
+
+    SSL_DEBUG_MSG( 2, ( "=> decrypt buf" ) );
+
+    if( ssl->in_msglen < ssl->transform_in->minlen )
+    {
+        SSL_DEBUG_MSG( 1, ( "in_msglen (%d) < minlen (%d)",
+                       ssl->in_msglen, ssl->transform_in->minlen ) );
+        return( POLARSSL_ERR_SSL_INVALID_MAC );
+    }
+
+#if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER)
+    if( ssl->transform_in->cipher_ctx_dec.cipher_info->mode ==
+                                                       POLARSSL_MODE_STREAM )
+    {
+        int ret;
+        size_t olen = 0;
+
+        padlen = 0;
+
+        if( ( ret = cipher_reset( &ssl->transform_in->cipher_ctx_dec ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_reset", ret );
+            return( ret );
+        }
+
+        if( ( ret = cipher_set_iv( &ssl->transform_in->cipher_ctx_dec,
+                                   ssl->transform_in->iv_dec,
+                                   ssl->transform_in->ivlen ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_set_iv", ret );
+            return( ret );
+        }
+
+        if( ( ret = cipher_update( &ssl->transform_in->cipher_ctx_dec,
+                                   ssl->in_msg, ssl->in_msglen, ssl->in_msg,
+                                   &olen ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_update", ret );
+            return( ret );
+        }
+
+        if( ssl->in_msglen != olen )
+        {
+            SSL_DEBUG_MSG( 1, ( "total encrypted length incorrect" ) );
+            return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
+        }
+
+        if( ( ret = cipher_finish( &ssl->transform_in->cipher_ctx_dec,
+                                   ssl->in_msg + olen, &olen ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_finish", ret );
+            return( ret );
+        }
+
+        if( 0 != olen )
+        {
+            SSL_DEBUG_MSG( 1, ( "total encrypted length incorrect" ) );
+            return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
+        }
+    }
+    else
+#endif /* POLARSSL_ARC4_C || POLARSSL_CIPHER_NULL_CIPHER */
+#if defined(POLARSSL_GCM_C)
+    if( ssl->transform_in->cipher_ctx_dec.cipher_info->mode ==
+                                                       POLARSSL_MODE_GCM )
+    {
+        unsigned char *dec_msg;
+        unsigned char *dec_msg_result;
+        size_t dec_msglen, olen, totlen;
+        unsigned char add_data[13];
+        int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
+
+        dec_msglen = ssl->in_msglen - ( ssl->transform_in->ivlen -
+                                        ssl->transform_in->fixed_ivlen );
+        dec_msglen -= 16;
+        dec_msg = ssl->in_msg;
+        dec_msg_result = ssl->in_msg;
+        ssl->in_msglen = dec_msglen;
+
+        memcpy( add_data, ssl->in_ctr, 8 );
+        add_data[8]  = ssl->in_msgtype;
+        add_data[9]  = ssl->major_ver;
+        add_data[10] = ssl->minor_ver;
+        add_data[11] = ( ssl->in_msglen >> 8 ) & 0xFF;
+        add_data[12] = ssl->in_msglen & 0xFF;
+
+        SSL_DEBUG_BUF( 4, "additional data used for AEAD",
+                       add_data, 13 );
+
+        memcpy( ssl->transform_in->iv_dec + ssl->transform_in->fixed_ivlen,
+                ssl->in_iv,
+                ssl->transform_in->ivlen - ssl->transform_in->fixed_ivlen );
+
+        SSL_DEBUG_BUF( 4, "IV used", ssl->transform_in->iv_dec,
+                                     ssl->transform_in->ivlen );
+        SSL_DEBUG_BUF( 4, "TAG used", dec_msg + dec_msglen, 16 );
+
+        /*
+         * Decrypt
+         */
+        if( ( ret = cipher_set_iv( &ssl->transform_in->cipher_ctx_dec,
+                                    ssl->transform_in->iv_dec,
+                                    ssl->transform_in->ivlen ) ) != 0 ||
+            ( ret = cipher_reset( &ssl->transform_in->cipher_ctx_dec ) ) != 0 )
+        {
+            return( ret );
+        }
+
+        if( ( ret = cipher_update_ad( &ssl->transform_in->cipher_ctx_dec,
+                                      add_data, 13 ) ) != 0 )
+        {
+            return( ret );
+        }
+
+        if( ( ret = cipher_update( &ssl->transform_in->cipher_ctx_dec,
+                                   dec_msg, dec_msglen,
+                                   dec_msg_result, &olen ) ) != 0 )
+        {
+            return( ret );
+        }
+        totlen = olen;
+
+        if( ( ret = cipher_finish( &ssl->transform_in->cipher_ctx_dec,
+                                   dec_msg_result + olen, &olen ) ) != 0 )
+        {
+            return( ret );
+        }
+        totlen += olen;
+
+        if( totlen != dec_msglen )
+        {
+            SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+            return( -1 );
+        }
+
+        /*
+         * Authenticate
+         */
+        if( ( ret = cipher_check_tag( &ssl->transform_in->cipher_ctx_dec,
+                                      dec_msg + dec_msglen, 16 ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_check_tag", ret );
+            return( POLARSSL_ERR_SSL_INVALID_MAC );
+        }
+
+    }
+    else
+#endif /* POLARSSL_GCM_C */
+#if defined(POLARSSL_CIPHER_MODE_CBC) &&                                    \
+    ( defined(POLARSSL_AES_C) || defined(POLARSSL_CAMELLIA_C) )
+    if( ssl->transform_in->cipher_ctx_dec.cipher_info->mode ==
+                                                       POLARSSL_MODE_CBC )
+    {
+        /*
+         * Decrypt and check the padding
+         */
+        int ret;
+        unsigned char *dec_msg;
+        unsigned char *dec_msg_result;
+        size_t dec_msglen;
+        size_t minlen = 0;
+        size_t olen = 0;
+
+        /*
+         * Check immediate ciphertext sanity
+         */
+        if( ssl->in_msglen % ssl->transform_in->ivlen != 0 )
+        {
+            SSL_DEBUG_MSG( 1, ( "msglen (%d) %% ivlen (%d) != 0",
+                           ssl->in_msglen, ssl->transform_in->ivlen ) );
+            return( POLARSSL_ERR_SSL_INVALID_MAC );
+        }
+
+#if defined(POLARSSL_SSL_PROTO_TLS1_1) || defined(POLARSSL_SSL_PROTO_TLS1_2)
+        if( ssl->minor_ver >= SSL_MINOR_VERSION_2 )
+            minlen += ssl->transform_in->ivlen;
+#endif
+
+        if( ssl->in_msglen < minlen + ssl->transform_in->ivlen ||
+            ssl->in_msglen < minlen + ssl->transform_in->maclen + 1 )
+        {
+            SSL_DEBUG_MSG( 1, ( "msglen (%d) < max( ivlen(%d), maclen (%d) "
+                                "+ 1 ) ( + expl IV )", ssl->in_msglen,
+                                ssl->transform_in->ivlen,
+                                ssl->transform_in->maclen ) );
+            return( POLARSSL_ERR_SSL_INVALID_MAC );
+        }
+
+        dec_msglen = ssl->in_msglen;
+        dec_msg = ssl->in_msg;
+        dec_msg_result = ssl->in_msg;
+
+#if defined(POLARSSL_SSL_PROTO_TLS1_1) || defined(POLARSSL_SSL_PROTO_TLS1_2)
+        /*
+         * Initialize for prepended IV for block cipher in TLS v1.1 and up
+         */
+        if( ssl->minor_ver >= SSL_MINOR_VERSION_2 )
+        {
+            dec_msglen -= ssl->transform_in->ivlen;
+            ssl->in_msglen -= ssl->transform_in->ivlen;
+
+            for( i = 0; i < ssl->transform_in->ivlen; i++ )
+                ssl->transform_in->iv_dec[i] = ssl->in_iv[i];
+        }
+#endif /* POLARSSL_SSL_PROTO_TLS1_1 || POLARSSL_SSL_PROTO_TLS1_2 */
+
+        if( ( ret = cipher_reset( &ssl->transform_in->cipher_ctx_dec ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_reset", ret );
+            return( ret );
+        }
+
+        if( ( ret = cipher_set_iv( &ssl->transform_in->cipher_ctx_dec,
+                                   ssl->transform_in->iv_dec,
+                                   ssl->transform_in->ivlen ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_set_iv", ret );
+            return( ret );
+        }
+
+        if( ( ret = cipher_update( &ssl->transform_in->cipher_ctx_dec,
+                                   dec_msg, dec_msglen, dec_msg_result,
+                                   &olen ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_update", ret );
+            return( ret );
+        }
+
+        dec_msglen -= olen;
+        if( ( ret = cipher_finish( &ssl->transform_in->cipher_ctx_dec,
+                                   dec_msg_result + olen, &olen ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_finish", ret );
+            return( ret );
+        }
+
+        if( dec_msglen != olen )
+        {
+            SSL_DEBUG_MSG( 1, ( "total encrypted length incorrect" ) );
+            return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
+        }
+
+#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1)
+        if( ssl->minor_ver < SSL_MINOR_VERSION_2 )
+        {
+            /*
+             * Save IV in SSL3 and TLS1
+             */
+            memcpy( ssl->transform_in->iv_dec,
+                    ssl->transform_in->cipher_ctx_dec.iv,
+                    ssl->transform_in->ivlen );
+        }
+#endif
+
+        padlen = 1 + ssl->in_msg[ssl->in_msglen - 1];
+
+        if( ssl->in_msglen < ssl->transform_in->maclen + padlen )
+        {
+#if defined(POLARSSL_SSL_DEBUG_ALL)
+            SSL_DEBUG_MSG( 1, ( "msglen (%d) < maclen (%d) + padlen (%d)",
+                        ssl->in_msglen, ssl->transform_in->maclen, padlen ) );
+#endif
+            padlen = 0;
+            correct = 0;
+        }
+
+#if defined(POLARSSL_SSL_PROTO_SSL3)
+        if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
+        {
+            if( padlen > ssl->transform_in->ivlen )
+            {
+#if defined(POLARSSL_SSL_DEBUG_ALL)
+                SSL_DEBUG_MSG( 1, ( "bad padding length: is %d, "
+                                    "should be no more than %d",
+                               padlen, ssl->transform_in->ivlen ) );
+#endif
+                correct = 0;
+            }
+        }
+        else
+#endif /* POLARSSL_SSL_PROTO_SSL3 */
+#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_2)
+        if( ssl->minor_ver > SSL_MINOR_VERSION_0 )
+        {
+            /*
+             * TLSv1+: always check the padding up to the first failure
+             * and fake check up to 256 bytes of padding
+             */
+            size_t pad_count = 0, real_count = 1;
+            size_t padding_idx = ssl->in_msglen - padlen - 1;
+
+            /*
+             * Padding is guaranteed to be incorrect if:
+             *   1. padlen >= ssl->in_msglen
+             *
+             *   2. padding_idx >= SSL_MAX_CONTENT_LEN +
+             *                     ssl->transform_in->maclen
+             *
+             * In both cases we reset padding_idx to a safe value (0) to
+             * prevent out-of-buffer reads.
+             */
+            correct &= ( ssl->in_msglen >= padlen + 1 );
+            correct &= ( padding_idx < SSL_MAX_CONTENT_LEN +
+                                       ssl->transform_in->maclen );
+
+            padding_idx *= correct;
+
+            for( i = 1; i <= 256; i++ )
+            {
+                real_count &= ( i <= padlen );
+                pad_count += real_count *
+                             ( ssl->in_msg[padding_idx + i] == padlen - 1 );
+            }
+
+            correct &= ( pad_count == padlen ); /* Only 1 on correct padding */
+
+#if defined(POLARSSL_SSL_DEBUG_ALL)
+            if( padlen > 0 && correct == 0)
+                SSL_DEBUG_MSG( 1, ( "bad padding byte detected" ) );
+#endif
+            padlen &= correct * 0x1FF;
+        }
+        else
+#endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 || \
+          POLARSSL_SSL_PROTO_TLS1_2 */
+        {
+            SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+            return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+        }
+    }
+    else
+#endif /* POLARSSL_CIPHER_MODE_CBC &&
+          ( POLARSSL_AES_C || POLARSSL_CAMELLIA_C ) */
+    {
+        SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+        return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+    }
+
+    SSL_DEBUG_BUF( 4, "raw buffer after decryption",
+                   ssl->in_msg, ssl->in_msglen );
+
+    /*
+     * Always compute the MAC (RFC4346, CBCTIME), except for GCM of course
+     */
+#if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER) ||     \
+    ( defined(POLARSSL_CIPHER_MODE_CBC) &&                                  \
+      ( defined(POLARSSL_AES_C) || defined(POLARSSL_CAMELLIA_C) ) )
+    if( ssl->transform_in->cipher_ctx_dec.cipher_info->mode !=
+                                                        POLARSSL_MODE_GCM )
+    {
+        unsigned char tmp[POLARSSL_SSL_MAX_MAC_SIZE];
+
+        ssl->in_msglen -= ( ssl->transform_in->maclen + padlen );
+
+        ssl->in_hdr[3] = (unsigned char)( ssl->in_msglen >> 8 );
+        ssl->in_hdr[4] = (unsigned char)( ssl->in_msglen      );
+
+        memcpy( tmp, ssl->in_msg + ssl->in_msglen, ssl->transform_in->maclen );
+
+#if defined(POLARSSL_SSL_PROTO_SSL3)
+        if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
+        {
+            ssl_mac( &ssl->transform_in->md_ctx_dec,
+                      ssl->transform_in->mac_dec,
+                      ssl->in_msg, ssl->in_msglen,
+                      ssl->in_ctr, ssl->in_msgtype );
+        }
+        else
+#endif /* POLARSSL_SSL_PROTO_SSL3 */
+#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \
+        defined(POLARSSL_SSL_PROTO_TLS1_2)
+        if( ssl->minor_ver > SSL_MINOR_VERSION_0 )
+        {
+            /*
+             * Process MAC and always update for padlen afterwards to make
+             * total time independent of padlen
+             *
+             * extra_run compensates MAC check for padlen
+             *
+             * Known timing attacks:
+             *  - Lucky Thirteen (http://www.isg.rhul.ac.uk/tls/TLStiming.pdf)
+             *
+             * We use ( ( Lx + 8 ) / 64 ) to handle 'negative Lx' values
+             * correctly. (We round down instead of up, so -56 is the correct
+             * value for our calculations instead of -55)
+             */
+            size_t j, extra_run = 0;
+            extra_run = ( 13 + ssl->in_msglen + padlen + 8 ) / 64 -
+                        ( 13 + ssl->in_msglen          + 8 ) / 64;
+
+            extra_run &= correct * 0xFF;
+
+            md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_ctr, 13 );
+            md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_msg,
+                             ssl->in_msglen );
+            md_hmac_finish( &ssl->transform_in->md_ctx_dec,
+                             ssl->in_msg + ssl->in_msglen );
+            for( j = 0; j < extra_run; j++ )
+                md_process( &ssl->transform_in->md_ctx_dec, ssl->in_msg );
+
+            md_hmac_reset( &ssl->transform_in->md_ctx_dec );
+        }
+        else
+#endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 || \
+              POLARSSL_SSL_PROTO_TLS1_2 */
+        {
+            SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+            return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+        }
+
+        SSL_DEBUG_BUF( 4, "message  mac", tmp, ssl->transform_in->maclen );
+        SSL_DEBUG_BUF( 4, "computed mac", ssl->in_msg + ssl->in_msglen,
+                       ssl->transform_in->maclen );
+
+        if( safer_memcmp( tmp, ssl->in_msg + ssl->in_msglen,
+                         ssl->transform_in->maclen ) != 0 )
+        {
+#if defined(POLARSSL_SSL_DEBUG_ALL)
+            SSL_DEBUG_MSG( 1, ( "message mac does not match" ) );
+#endif
+            correct = 0;
+        }
+
+        /*
+         * Finally check the correct flag
+         */
+        if( correct == 0 )
+            return( POLARSSL_ERR_SSL_INVALID_MAC );
+    }
+#endif /* GCM not the only option */
+
+    if( ssl->in_msglen == 0 )
+    {
+        ssl->nb_zero++;
+
+        /*
+         * Three or more empty messages may be a DoS attack
+         * (excessive CPU consumption).
+         */
+        if( ssl->nb_zero > 3 )
+        {
+            SSL_DEBUG_MSG( 1, ( "received four consecutive empty "
+                                "messages, possible DoS attack" ) );
+            return( POLARSSL_ERR_SSL_INVALID_MAC );
+        }
+    }
+    else
+        ssl->nb_zero = 0;
+
+    for( i = 8; i > 0; i-- )
+        if( ++ssl->in_ctr[i - 1] != 0 )
+            break;
+
+    /* The loops goes to its end iff the counter is wrapping */
+    if( i == 0 )
+    {
+        SSL_DEBUG_MSG( 1, ( "incoming message counter would wrap" ) );
+        return( POLARSSL_ERR_SSL_COUNTER_WRAPPING );
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= decrypt buf" ) );
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_ZLIB_SUPPORT)
+/*
+ * Compression/decompression functions
+ */
+static int ssl_compress_buf( ssl_context *ssl )
+{
+    int ret;
+    unsigned char *msg_post = ssl->out_msg;
+    size_t len_pre = ssl->out_msglen;
+    unsigned char *msg_pre = ssl->compress_buf;
+
+    SSL_DEBUG_MSG( 2, ( "=> compress buf" ) );
+
+    if( len_pre == 0 )
+        return( 0 );
+
+    memcpy( msg_pre, ssl->out_msg, len_pre );
+
+    SSL_DEBUG_MSG( 3, ( "before compression: msglen = %d, ",
+                   ssl->out_msglen ) );
+
+    SSL_DEBUG_BUF( 4, "before compression: output payload",
+                   ssl->out_msg, ssl->out_msglen );
+
+    ssl->transform_out->ctx_deflate.next_in = msg_pre;
+    ssl->transform_out->ctx_deflate.avail_in = len_pre;
+    ssl->transform_out->ctx_deflate.next_out = msg_post;
+    ssl->transform_out->ctx_deflate.avail_out = SSL_BUFFER_LEN;
+
+    ret = deflate( &ssl->transform_out->ctx_deflate, Z_SYNC_FLUSH );
+    if( ret != Z_OK )
+    {
+        SSL_DEBUG_MSG( 1, ( "failed to perform compression (%d)", ret ) );
+        return( POLARSSL_ERR_SSL_COMPRESSION_FAILED );
+    }
+
+    ssl->out_msglen = SSL_BUFFER_LEN -
+                      ssl->transform_out->ctx_deflate.avail_out;
+
+    SSL_DEBUG_MSG( 3, ( "after compression: msglen = %d, ",
+                   ssl->out_msglen ) );
+
+    SSL_DEBUG_BUF( 4, "after compression: output payload",
+                   ssl->out_msg, ssl->out_msglen );
+
+    SSL_DEBUG_MSG( 2, ( "<= compress buf" ) );
+
+    return( 0 );
+}
+
+static int ssl_decompress_buf( ssl_context *ssl )
+{
+    int ret;
+    unsigned char *msg_post = ssl->in_msg;
+    size_t len_pre = ssl->in_msglen;
+    unsigned char *msg_pre = ssl->compress_buf;
+
+    SSL_DEBUG_MSG( 2, ( "=> decompress buf" ) );
+
+    if( len_pre == 0 )
+        return( 0 );
+
+    memcpy( msg_pre, ssl->in_msg, len_pre );
+
+    SSL_DEBUG_MSG( 3, ( "before decompression: msglen = %d, ",
+                   ssl->in_msglen ) );
+
+    SSL_DEBUG_BUF( 4, "before decompression: input payload",
+                   ssl->in_msg, ssl->in_msglen );
+
+    ssl->transform_in->ctx_inflate.next_in = msg_pre;
+    ssl->transform_in->ctx_inflate.avail_in = len_pre;
+    ssl->transform_in->ctx_inflate.next_out = msg_post;
+    ssl->transform_in->ctx_inflate.avail_out = SSL_MAX_CONTENT_LEN;
+
+    ret = inflate( &ssl->transform_in->ctx_inflate, Z_SYNC_FLUSH );
+    if( ret != Z_OK )
+    {
+        SSL_DEBUG_MSG( 1, ( "failed to perform decompression (%d)", ret ) );
+        return( POLARSSL_ERR_SSL_COMPRESSION_FAILED );
+    }
+
+    ssl->in_msglen = SSL_MAX_CONTENT_LEN -
+                     ssl->transform_in->ctx_inflate.avail_out;
+
+    SSL_DEBUG_MSG( 3, ( "after decompression: msglen = %d, ",
+                   ssl->in_msglen ) );
+
+    SSL_DEBUG_BUF( 4, "after decompression: input payload",
+                   ssl->in_msg, ssl->in_msglen );
+
+    SSL_DEBUG_MSG( 2, ( "<= decompress buf" ) );
+
+    return( 0 );
+}
+#endif /* POLARSSL_ZLIB_SUPPORT */
+
+/*
+ * Fill the input message buffer
+ */
+int ssl_fetch_input( ssl_context *ssl, size_t nb_want )
+{
+    int ret;
+    size_t len;
+
+    SSL_DEBUG_MSG( 2, ( "=> fetch input" ) );
+
+    if( nb_want > SSL_BUFFER_LEN - 8 )
+    {
+        SSL_DEBUG_MSG( 1, ( "requesting more data than fits" ) );
+        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+    }
+
+    while( ssl->in_left < nb_want )
+    {
+        len = nb_want - ssl->in_left;
+        ret = ssl->f_recv( ssl->p_recv, ssl->in_hdr + ssl->in_left, len );
+
+        SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d",
+                       ssl->in_left, nb_want ) );
+        SSL_DEBUG_RET( 2, "ssl->f_recv", ret );
+
+        if( ret == 0 )
+            return( POLARSSL_ERR_SSL_CONN_EOF );
+
+        if( ret < 0 )
+            return( ret );
+
+        ssl->in_left += ret;
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= fetch input" ) );
+
+    return( 0 );
+}
+
+/*
+ * Flush any data not yet written
+ */
+int ssl_flush_output( ssl_context *ssl )
+{
+    int ret;
+    unsigned char *buf;
+
+    SSL_DEBUG_MSG( 2, ( "=> flush output" ) );
+
+    while( ssl->out_left > 0 )
+    {
+        SSL_DEBUG_MSG( 2, ( "message length: %d, out_left: %d",
+                       5 + ssl->out_msglen, ssl->out_left ) );
+
+        buf = ssl->out_hdr + 5 + ssl->out_msglen - ssl->out_left;
+        ret = ssl->f_send( ssl->p_send, buf, ssl->out_left );
+
+        SSL_DEBUG_RET( 2, "ssl->f_send", ret );
+
+        if( ret <= 0 )
+            return( ret );
+
+        ssl->out_left -= ret;
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= flush output" ) );
+
+    return( 0 );
+}
+
+/*
+ * Record layer functions
+ */
+int ssl_write_record( ssl_context *ssl )
+{
+    int ret, done = 0;
+    size_t len = ssl->out_msglen;
+
+    SSL_DEBUG_MSG( 2, ( "=> write record" ) );
+
+    if( ssl->out_msgtype == SSL_MSG_HANDSHAKE )
+    {
+        ssl->out_msg[1] = (unsigned char)( ( len - 4 ) >> 16 );
+        ssl->out_msg[2] = (unsigned char)( ( len - 4 ) >>  8 );
+        ssl->out_msg[3] = (unsigned char)( ( len - 4 )       );
+
+        if( ssl->out_msg[0] != SSL_HS_HELLO_REQUEST )
+            ssl->handshake->update_checksum( ssl, ssl->out_msg, len );
+    }
+
+#if defined(POLARSSL_ZLIB_SUPPORT)
+    if( ssl->transform_out != NULL &&
+        ssl->session_out->compression == SSL_COMPRESS_DEFLATE )
+    {
+        if( ( ret = ssl_compress_buf( ssl ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_compress_buf", ret );
+            return( ret );
+        }
+
+        len = ssl->out_msglen;
+    }
+#endif /*POLARSSL_ZLIB_SUPPORT */
+
+#if defined(POLARSSL_SSL_HW_RECORD_ACCEL)
+    if( ssl_hw_record_write != NULL)
+    {
+        SSL_DEBUG_MSG( 2, ( "going for ssl_hw_record_write()" ) );
+
+        ret = ssl_hw_record_write( ssl );
+        if( ret != 0 && ret != POLARSSL_ERR_SSL_HW_ACCEL_FALLTHROUGH )
+        {
+            SSL_DEBUG_RET( 1, "ssl_hw_record_write", ret );
+            return POLARSSL_ERR_SSL_HW_ACCEL_FAILED;
+        }
+
+        if( ret == 0 )
+            done = 1;
+    }
+#endif /* POLARSSL_SSL_HW_RECORD_ACCEL */
+    if( !done )
+    {
+        ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype;
+        ssl->out_hdr[1] = (unsigned char) ssl->major_ver;
+        ssl->out_hdr[2] = (unsigned char) ssl->minor_ver;
+        ssl->out_hdr[3] = (unsigned char)( len >> 8 );
+        ssl->out_hdr[4] = (unsigned char)( len      );
+
+        if( ssl->transform_out != NULL )
+        {
+            if( ( ret = ssl_encrypt_buf( ssl ) ) != 0 )
+            {
+                SSL_DEBUG_RET( 1, "ssl_encrypt_buf", ret );
+                return( ret );
+            }
+
+            len = ssl->out_msglen;
+            ssl->out_hdr[3] = (unsigned char)( len >> 8 );
+            ssl->out_hdr[4] = (unsigned char)( len      );
+        }
+
+        ssl->out_left = 5 + ssl->out_msglen;
+
+        SSL_DEBUG_MSG( 3, ( "output record: msgtype = %d, "
+                            "version = [%d:%d], msglen = %d",
+                       ssl->out_hdr[0], ssl->out_hdr[1], ssl->out_hdr[2],
+                     ( ssl->out_hdr[3] << 8 ) | ssl->out_hdr[4] ) );
+
+        SSL_DEBUG_BUF( 4, "output record sent to network",
+                       ssl->out_hdr, 5 + ssl->out_msglen );
+    }
+
+    if( ( ret = ssl_flush_output( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_flush_output", ret );
+        return( ret );
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= write record" ) );
+
+    return( 0 );
+}
+
+int ssl_read_record( ssl_context *ssl )
+{
+    int ret, done = 0;
+
+    SSL_DEBUG_MSG( 2, ( "=> read record" ) );
+
+    SSL_DEBUG_BUF( 4, "input record from network",
+                   ssl->in_hdr, 5 + ssl->in_msglen );
+
+    if( ssl->in_hslen != 0 &&
+        ssl->in_hslen < ssl->in_msglen )
+    {
+        /*
+         * Get next Handshake message in the current record
+         */
+        ssl->in_msglen -= ssl->in_hslen;
+
+        memmove( ssl->in_msg, ssl->in_msg + ssl->in_hslen,
+                 ssl->in_msglen );
+
+        ssl->in_hslen  = 4;
+        ssl->in_hslen += ( ssl->in_msg[2] << 8 ) | ssl->in_msg[3];
+
+        SSL_DEBUG_MSG( 3, ( "handshake message: msglen ="
+                            " %d, type = %d, hslen = %d",
+                       ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) );
+
+        if( ssl->in_msglen < 4 || ssl->in_msg[1] != 0 )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad handshake length" ) );
+            return( POLARSSL_ERR_SSL_INVALID_RECORD );
+        }
+
+        if( ssl->in_msglen < ssl->in_hslen )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad handshake length" ) );
+            return( POLARSSL_ERR_SSL_INVALID_RECORD );
+        }
+
+        if( ssl->state != SSL_HANDSHAKE_OVER )
+            ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen );
+
+        return( 0 );
+    }
+
+    ssl->in_hslen = 0;
+
+    /*
+     * Read the record header and validate it
+     */
+    if( ( ret = ssl_fetch_input( ssl, 5 ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_fetch_input", ret );
+        return( ret );
+    }
+
+    ssl->in_msgtype =  ssl->in_hdr[0];
+    ssl->in_msglen = ( ssl->in_hdr[3] << 8 ) | ssl->in_hdr[4];
+
+    SSL_DEBUG_MSG( 3, ( "input record: msgtype = %d, "
+                        "version = [%d:%d], msglen = %d",
+                     ssl->in_hdr[0], ssl->in_hdr[1], ssl->in_hdr[2],
+                   ( ssl->in_hdr[3] << 8 ) | ssl->in_hdr[4] ) );
+
+    if( ssl->in_hdr[1] != ssl->major_ver )
+    {
+        SSL_DEBUG_MSG( 1, ( "major version mismatch" ) );
+        return( POLARSSL_ERR_SSL_INVALID_RECORD );
+    }
+
+    if( ssl->in_hdr[2] > ssl->max_minor_ver )
+    {
+        SSL_DEBUG_MSG( 1, ( "minor version mismatch" ) );
+        return( POLARSSL_ERR_SSL_INVALID_RECORD );
+    }
+
+    /* Sanity check (outer boundaries) */
+    if( ssl->in_msglen < 1 || ssl->in_msglen > SSL_BUFFER_LEN - 13 )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad message length" ) );
+        return( POLARSSL_ERR_SSL_INVALID_RECORD );
+    }
+
+    /*
+     * Make sure the message length is acceptable for the current transform
+     * and protocol version.
+     */
+    if( ssl->transform_in == NULL )
+    {
+        if( ssl->in_msglen > SSL_MAX_CONTENT_LEN )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad message length" ) );
+            return( POLARSSL_ERR_SSL_INVALID_RECORD );
+        }
+    }
+    else
+    {
+        if( ssl->in_msglen < ssl->transform_in->minlen )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad message length" ) );
+            return( POLARSSL_ERR_SSL_INVALID_RECORD );
+        }
+
+#if defined(POLARSSL_SSL_PROTO_SSL3)
+        if( ssl->minor_ver == SSL_MINOR_VERSION_0 &&
+            ssl->in_msglen > ssl->transform_in->minlen + SSL_MAX_CONTENT_LEN )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad message length" ) );
+            return( POLARSSL_ERR_SSL_INVALID_RECORD );
+        }
+#endif
+
+#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_2)
+        /*
+         * TLS encrypted messages can have up to 256 bytes of padding
+         */
+        if( ssl->minor_ver >= SSL_MINOR_VERSION_1 &&
+            ssl->in_msglen > ssl->transform_in->minlen +
+                             SSL_MAX_CONTENT_LEN + 256 )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad message length" ) );
+            return( POLARSSL_ERR_SSL_INVALID_RECORD );
+        }
+#endif
+    }
+
+    /*
+     * Read and optionally decrypt the message contents
+     */
+    if( ( ret = ssl_fetch_input( ssl, 5 + ssl->in_msglen ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_fetch_input", ret );
+        return( ret );
+    }
+
+    SSL_DEBUG_BUF( 4, "input record from network",
+                   ssl->in_hdr, 5 + ssl->in_msglen );
+
+#if defined(POLARSSL_SSL_HW_RECORD_ACCEL)
+    if( ssl_hw_record_read != NULL)
+    {
+        SSL_DEBUG_MSG( 2, ( "going for ssl_hw_record_read()" ) );
+
+        ret = ssl_hw_record_read( ssl );
+        if( ret != 0 && ret != POLARSSL_ERR_SSL_HW_ACCEL_FALLTHROUGH )
+        {
+            SSL_DEBUG_RET( 1, "ssl_hw_record_read", ret );
+            return POLARSSL_ERR_SSL_HW_ACCEL_FAILED;
+        }
+
+        if( ret == 0 )
+            done = 1;
+    }
+#endif /* POLARSSL_SSL_HW_RECORD_ACCEL */
+    if( !done && ssl->transform_in != NULL )
+    {
+        if( ( ret = ssl_decrypt_buf( ssl ) ) != 0 )
+        {
+#if defined(POLARSSL_SSL_ALERT_MESSAGES)
+            if( ret == POLARSSL_ERR_SSL_INVALID_MAC )
+            {
+                ssl_send_alert_message( ssl,
+                                        SSL_ALERT_LEVEL_FATAL,
+                                        SSL_ALERT_MSG_BAD_RECORD_MAC );
+            }
+#endif
+            SSL_DEBUG_RET( 1, "ssl_decrypt_buf", ret );
+            return( ret );
+        }
+
+        SSL_DEBUG_BUF( 4, "input payload after decrypt",
+                       ssl->in_msg, ssl->in_msglen );
+
+        if( ssl->in_msglen > SSL_MAX_CONTENT_LEN )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad message length" ) );
+            return( POLARSSL_ERR_SSL_INVALID_RECORD );
+        }
+    }
+
+#if defined(POLARSSL_ZLIB_SUPPORT)
+    if( ssl->transform_in != NULL &&
+        ssl->session_in->compression == SSL_COMPRESS_DEFLATE )
+    {
+        if( ( ret = ssl_decompress_buf( ssl ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_decompress_buf", ret );
+            return( ret );
+        }
+
+        ssl->in_hdr[3] = (unsigned char)( ssl->in_msglen >> 8 );
+        ssl->in_hdr[4] = (unsigned char)( ssl->in_msglen      );
+    }
+#endif /* POLARSSL_ZLIB_SUPPORT */
+
+    if( ssl->in_msgtype != SSL_MSG_HANDSHAKE &&
+        ssl->in_msgtype != SSL_MSG_ALERT &&
+        ssl->in_msgtype != SSL_MSG_CHANGE_CIPHER_SPEC &&
+        ssl->in_msgtype != SSL_MSG_APPLICATION_DATA )
+    {
+        SSL_DEBUG_MSG( 1, ( "unknown record type" ) );
+
+        if( ( ret = ssl_send_alert_message( ssl,
+                        SSL_ALERT_LEVEL_FATAL,
+                        SSL_ALERT_MSG_UNEXPECTED_MESSAGE ) ) != 0 )
+        {
+            return( ret );
+        }
+
+        return( POLARSSL_ERR_SSL_INVALID_RECORD );
+    }
+
+    if( ssl->in_msgtype == SSL_MSG_HANDSHAKE )
+    {
+        ssl->in_hslen  = 4;
+        ssl->in_hslen += ( ssl->in_msg[2] << 8 ) | ssl->in_msg[3];
+
+        SSL_DEBUG_MSG( 3, ( "handshake message: msglen ="
+                            " %d, type = %d, hslen = %d",
+                       ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) );
+
+        /*
+         * Additional checks to validate the handshake header
+         */
+        if( ssl->in_msglen < 4 || ssl->in_msg[1] != 0 )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad handshake length" ) );
+            return( POLARSSL_ERR_SSL_INVALID_RECORD );
+        }
+
+        if( ssl->in_msglen < ssl->in_hslen )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad handshake length" ) );
+            return( POLARSSL_ERR_SSL_INVALID_RECORD );
+        }
+
+        if( ssl->state != SSL_HANDSHAKE_OVER )
+            ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen );
+    }
+
+    if( ssl->in_msgtype == SSL_MSG_ALERT )
+    {
+        SSL_DEBUG_MSG( 2, ( "got an alert message, type: [%d:%d]",
+                       ssl->in_msg[0], ssl->in_msg[1] ) );
+
+        /*
+         * Ignore non-fatal alerts, except close_notify
+         */
+        if( ssl->in_msg[0] == SSL_ALERT_LEVEL_FATAL )
+        {
+            SSL_DEBUG_MSG( 1, ( "is a fatal alert message (msg %d)",
+                           ssl->in_msg[1] ) );
+            /**
+             * Subtract from error code as ssl->in_msg[1] is 7-bit positive
+             * error identifier.
+             */
+            return( POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE );
+        }
+
+        if( ssl->in_msg[0] == SSL_ALERT_LEVEL_WARNING &&
+            ssl->in_msg[1] == SSL_ALERT_MSG_CLOSE_NOTIFY )
+        {
+            SSL_DEBUG_MSG( 2, ( "is a close notify message" ) );
+            return( POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY );
+        }
+    }
+
+    ssl->in_left = 0;
+
+    SSL_DEBUG_MSG( 2, ( "<= read record" ) );
+
+    return( 0 );
+}
+
+int ssl_send_fatal_handshake_failure( ssl_context *ssl )
+{
+    int ret;
+
+    if( ( ret = ssl_send_alert_message( ssl,
+                    SSL_ALERT_LEVEL_FATAL,
+                    SSL_ALERT_MSG_HANDSHAKE_FAILURE ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    return( 0 );
+}
+
+int ssl_send_alert_message( ssl_context *ssl,
+                            unsigned char level,
+                            unsigned char message )
+{
+    int ret;
+
+    SSL_DEBUG_MSG( 2, ( "=> send alert message" ) );
+
+    ssl->out_msgtype = SSL_MSG_ALERT;
+    ssl->out_msglen = 2;
+    ssl->out_msg[0] = level;
+    ssl->out_msg[1] = message;
+
+    if( ( ret = ssl_write_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+        return( ret );
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= send alert message" ) );
+
+    return( 0 );
+}
+
+/*
+ * Handshake functions
+ */
+#if !defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED)         && \
+    !defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED)     && \
+    !defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED)     && \
+    !defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED)   && \
+    !defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \
+    !defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED)    && \
+    !defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+int ssl_write_certificate( ssl_context *ssl )
+{
+    int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
+    const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
+
+    SSL_DEBUG_MSG( 2, ( "=> write certificate" ) );
+
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK )
+    {
+        SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) );
+        ssl->state++;
+        return( 0 );
+    }
+
+    SSL_DEBUG_MSG( 1, ( "should not happen" ) );
+    return( ret );
+}
+
+int ssl_parse_certificate( ssl_context *ssl )
+{
+    int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
+    const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
+
+    SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) );
+
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK )
+    {
+        SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
+        ssl->state++;
+        return( 0 );
+    }
+
+    SSL_DEBUG_MSG( 1, ( "should not happen" ) );
+    return( ret );
+}
+#else
+int ssl_write_certificate( ssl_context *ssl )
+{
+    int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
+    size_t i, n;
+    const x509_crt *crt;
+    const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
+
+    SSL_DEBUG_MSG( 2, ( "=> write certificate" ) );
+
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK )
+    {
+        SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) );
+        ssl->state++;
+        return( 0 );
+    }
+
+    if( ssl->endpoint == SSL_IS_CLIENT )
+    {
+        if( ssl->client_auth == 0 )
+        {
+            SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) );
+            ssl->state++;
+            return( 0 );
+        }
+
+#if defined(POLARSSL_SSL_PROTO_SSL3)
+        /*
+         * If using SSLv3 and got no cert, send an Alert message
+         * (otherwise an empty Certificate message will be sent).
+         */
+        if( ssl_own_cert( ssl )  == NULL &&
+            ssl->minor_ver == SSL_MINOR_VERSION_0 )
+        {
+            ssl->out_msglen  = 2;
+            ssl->out_msgtype = SSL_MSG_ALERT;
+            ssl->out_msg[0]  = SSL_ALERT_LEVEL_WARNING;
+            ssl->out_msg[1]  = SSL_ALERT_MSG_NO_CERT;
+
+            SSL_DEBUG_MSG( 2, ( "got no certificate to send" ) );
+            goto write_msg;
+        }
+#endif /* POLARSSL_SSL_PROTO_SSL3 */
+    }
+    else /* SSL_IS_SERVER */
+    {
+        if( ssl_own_cert( ssl ) == NULL )
+        {
+            SSL_DEBUG_MSG( 1, ( "got no certificate to send" ) );
+            return( POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED );
+        }
+    }
+
+    SSL_DEBUG_CRT( 3, "own certificate", ssl_own_cert( ssl ) );
+
+    /*
+     *     0  .  0    handshake type
+     *     1  .  3    handshake length
+     *     4  .  6    length of all certs
+     *     7  .  9    length of cert. 1
+     *    10  . n-1   peer certificate
+     *     n  . n+2   length of cert. 2
+     *    n+3 . ...   upper level cert, etc.
+     */
+    i = 7;
+    crt = ssl_own_cert( ssl );
+
+    while( crt != NULL )
+    {
+        n = crt->raw.len;
+        if( n > SSL_MAX_CONTENT_LEN - 3 - i )
+        {
+            SSL_DEBUG_MSG( 1, ( "certificate too large, %d > %d",
+                           i + 3 + n, SSL_MAX_CONTENT_LEN ) );
+            return( POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE );
+        }
+
+        ssl->out_msg[i    ] = (unsigned char)( n >> 16 );
+        ssl->out_msg[i + 1] = (unsigned char)( n >>  8 );
+        ssl->out_msg[i + 2] = (unsigned char)( n       );
+
+        i += 3; memcpy( ssl->out_msg + i, crt->raw.p, n );
+        i += n; crt = crt->next;
+    }
+
+    ssl->out_msg[4]  = (unsigned char)( ( i - 7 ) >> 16 );
+    ssl->out_msg[5]  = (unsigned char)( ( i - 7 ) >>  8 );
+    ssl->out_msg[6]  = (unsigned char)( ( i - 7 )       );
+
+    ssl->out_msglen  = i;
+    ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+    ssl->out_msg[0]  = SSL_HS_CERTIFICATE;
+
+#if defined(POLARSSL_SSL_PROTO_SSL3)
+write_msg:
+#endif
+
+    ssl->state++;
+
+    if( ( ret = ssl_write_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+        return( ret );
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= write certificate" ) );
+
+    return( ret );
+}
+
+int ssl_parse_certificate( ssl_context *ssl )
+{
+    int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
+    size_t i, n;
+    const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
+
+    SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) );
+
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK )
+    {
+        SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
+        ssl->state++;
+        return( 0 );
+    }
+
+    if( ssl->endpoint == SSL_IS_SERVER &&
+        ( ssl->authmode == SSL_VERIFY_NONE ||
+          ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ) )
+    {
+        ssl->session_negotiate->verify_result = BADCERT_SKIP_VERIFY;
+        SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
+        ssl->state++;
+        return( 0 );
+    }
+
+    if( ( ret = ssl_read_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+        return( ret );
+    }
+
+    ssl->state++;
+
+#if defined(POLARSSL_SSL_PROTO_SSL3)
+    /*
+     * Check if the client sent an empty certificate
+     */
+    if( ssl->endpoint  == SSL_IS_SERVER &&
+        ssl->minor_ver == SSL_MINOR_VERSION_0 )
+    {
+        if( ssl->in_msglen  == 2                        &&
+            ssl->in_msgtype == SSL_MSG_ALERT            &&
+            ssl->in_msg[0]  == SSL_ALERT_LEVEL_WARNING  &&
+            ssl->in_msg[1]  == SSL_ALERT_MSG_NO_CERT )
+        {
+            SSL_DEBUG_MSG( 1, ( "SSLv3 client has no certificate" ) );
+
+            ssl->session_negotiate->verify_result = BADCERT_MISSING;
+            if( ssl->authmode == SSL_VERIFY_OPTIONAL )
+                return( 0 );
+            else
+                return( POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE );
+        }
+    }
+#endif /* POLARSSL_SSL_PROTO_SSL3 */
+
+#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_2)
+    if( ssl->endpoint  == SSL_IS_SERVER &&
+        ssl->minor_ver != SSL_MINOR_VERSION_0 )
+    {
+        if( ssl->in_hslen   == 7                    &&
+            ssl->in_msgtype == SSL_MSG_HANDSHAKE    &&
+            ssl->in_msg[0]  == SSL_HS_CERTIFICATE   &&
+            memcmp( ssl->in_msg + 4, "\0\0\0", 3 ) == 0 )
+        {
+            SSL_DEBUG_MSG( 1, ( "TLSv1 client has no certificate" ) );
+
+            ssl->session_negotiate->verify_result = BADCERT_MISSING;
+            if( ssl->authmode == SSL_VERIFY_REQUIRED )
+                return( POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE );
+            else
+                return( 0 );
+        }
+    }
+#endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 || \
+          POLARSSL_SSL_PROTO_TLS1_2 */
+
+    if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
+        return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+    }
+
+    if( ssl->in_msg[0] != SSL_HS_CERTIFICATE || ssl->in_hslen < 10 )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE );
+    }
+
+    /*
+     * Same message structure as in ssl_write_certificate()
+     */
+    n = ( ssl->in_msg[5] << 8 ) | ssl->in_msg[6];
+
+    if( ssl->in_msg[4] != 0 || ssl->in_hslen != 7 + n )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE );
+    }
+
+    /* In case we tried to reuse a session but it failed */
+    if( ssl->session_negotiate->peer_cert != NULL )
+    {
+        x509_crt_free( ssl->session_negotiate->peer_cert );
+        polarssl_free( ssl->session_negotiate->peer_cert );
+    }
+
+    if( ( ssl->session_negotiate->peer_cert = (x509_crt *) polarssl_malloc(
+                    sizeof( x509_crt ) ) ) == NULL )
+    {
+        SSL_DEBUG_MSG( 1, ( "malloc(%d bytes) failed",
+                       sizeof( x509_crt ) ) );
+        return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+    }
+
+    x509_crt_init( ssl->session_negotiate->peer_cert );
+
+    i = 7;
+
+    while( i < ssl->in_hslen )
+    {
+        if( ssl->in_msg[i] != 0 )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE );
+        }
+
+        n = ( (unsigned int) ssl->in_msg[i + 1] << 8 )
+            | (unsigned int) ssl->in_msg[i + 2];
+        i += 3;
+
+        if( n < 128 || i + n > ssl->in_hslen )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE );
+        }
+
+        ret = x509_crt_parse_der( ssl->session_negotiate->peer_cert,
+                                  ssl->in_msg + i, n );
+        if( ret != 0 )
+        {
+            SSL_DEBUG_RET( 1, " x509_crt_parse_der", ret );
+            return( ret );
+        }
+
+        i += n;
+    }
+
+    SSL_DEBUG_CRT( 3, "peer certificate", ssl->session_negotiate->peer_cert );
+
+    /*
+     * On client, make sure the server cert doesn't change during renego to
+     * avoid "triple handshake" attack: https://secure-resumption.com/
+     */
+    if( ssl->endpoint == SSL_IS_CLIENT &&
+        ssl->renegotiation == SSL_RENEGOTIATION )
+    {
+        if( ssl->session->peer_cert == NULL )
+        {
+            SSL_DEBUG_MSG( 1, ( "new server cert during renegotiation" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE );
+        }
+
+        if( ssl->session->peer_cert->raw.len !=
+            ssl->session_negotiate->peer_cert->raw.len ||
+            memcmp( ssl->session->peer_cert->raw.p,
+                    ssl->session_negotiate->peer_cert->raw.p,
+                    ssl->session->peer_cert->raw.len ) != 0 )
+        {
+            SSL_DEBUG_MSG( 1, ( "server cert changed during renegotiation" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE );
+        }
+    }
+
+    if( ssl->authmode != SSL_VERIFY_NONE )
+    {
+        if( ssl->ca_chain == NULL )
+        {
+            SSL_DEBUG_MSG( 1, ( "got no CA chain" ) );
+            return( POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED );
+        }
+
+        /*
+         * Main check: verify certificate
+         */
+        ret = x509_crt_verify( ssl->session_negotiate->peer_cert,
+                               ssl->ca_chain, ssl->ca_crl, ssl->peer_cn,
+                              &ssl->session_negotiate->verify_result,
+                               ssl->f_vrfy, ssl->p_vrfy );
+
+        if( ret != 0 )
+        {
+            SSL_DEBUG_RET( 1, "x509_verify_cert", ret );
+        }
+
+        /*
+         * Secondary checks: always done, but change 'ret' only if it was 0
+         */
+
+#if defined(POLARSSL_SSL_SET_CURVES)
+        {
+            pk_context *pk = &ssl->session_negotiate->peer_cert->pk;
+
+            /* If certificate uses an EC key, make sure the curve is OK */
+            if( pk_can_do( pk, POLARSSL_PK_ECKEY ) &&
+                ! ssl_curve_is_acceptable( ssl, pk_ec( *pk )->grp.id ) )
+            {
+                SSL_DEBUG_MSG( 1, ( "bad certificate (EC key curve)" ) );
+                if( ret == 0 )
+                    ret = POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE;
+            }
+        }
+#endif /* POLARSSL_SSL_SET_CURVES */
+
+        if( ssl_check_cert_usage( ssl->session_negotiate->peer_cert,
+                                  ciphersuite_info,
+                                  ! ssl->endpoint ) != 0 )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad certificate (usage extensions)" ) );
+            if( ret == 0 )
+                ret = POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE;
+        }
+
+        if( ssl->authmode != SSL_VERIFY_REQUIRED )
+            ret = 0;
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) );
+
+    return( ret );
+}
+#endif /* !POLARSSL_KEY_EXCHANGE_RSA_ENABLED
+          !POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED
+          !POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED
+          !POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED
+          !POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+          !POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED
+          !POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
+
+int ssl_write_change_cipher_spec( ssl_context *ssl )
+{
+    int ret;
+
+    SSL_DEBUG_MSG( 2, ( "=> write change cipher spec" ) );
+
+    ssl->out_msgtype = SSL_MSG_CHANGE_CIPHER_SPEC;
+    ssl->out_msglen  = 1;
+    ssl->out_msg[0]  = 1;
+
+    ssl->state++;
+
+    if( ( ret = ssl_write_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+        return( ret );
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= write change cipher spec" ) );
+
+    return( 0 );
+}
+
+int ssl_parse_change_cipher_spec( ssl_context *ssl )
+{
+    int ret;
+
+    SSL_DEBUG_MSG( 2, ( "=> parse change cipher spec" ) );
+
+    if( ( ret = ssl_read_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+        return( ret );
+    }
+
+    if( ssl->in_msgtype != SSL_MSG_CHANGE_CIPHER_SPEC )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) );
+        return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+    }
+
+    if( ssl->in_msglen != 1 || ssl->in_msg[0] != 1 )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC );
+    }
+
+    ssl->state++;
+
+    SSL_DEBUG_MSG( 2, ( "<= parse change cipher spec" ) );
+
+    return( 0 );
+}
+
+void ssl_optimize_checksum( ssl_context *ssl,
+                            const ssl_ciphersuite_t *ciphersuite_info )
+{
+    ((void) ciphersuite_info);
+
+#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_1)
+    if( ssl->minor_ver < SSL_MINOR_VERSION_3 )
+        ssl->handshake->update_checksum = ssl_update_checksum_md5sha1;
+    else
+#endif
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+#if defined(POLARSSL_SHA512_C)
+    if( ciphersuite_info->mac == POLARSSL_MD_SHA384 )
+        ssl->handshake->update_checksum = ssl_update_checksum_sha384;
+    else
+#endif
+#if defined(POLARSSL_SHA256_C)
+    if( ciphersuite_info->mac != POLARSSL_MD_SHA384 )
+        ssl->handshake->update_checksum = ssl_update_checksum_sha256;
+    else
+#endif
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
+        /* Should never happen */
+        return;
+}
+
+static void ssl_update_checksum_start( ssl_context *ssl,
+                                       const unsigned char *buf, size_t len )
+{
+#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_1)
+     md5_update( &ssl->handshake->fin_md5 , buf, len );
+    sha1_update( &ssl->handshake->fin_sha1, buf, len );
+#endif
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+#if defined(POLARSSL_SHA256_C)
+    sha256_update( &ssl->handshake->fin_sha256, buf, len );
+#endif
+#if defined(POLARSSL_SHA512_C)
+    sha512_update( &ssl->handshake->fin_sha512, buf, len );
+#endif
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
+}
+
+#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_1)
+static void ssl_update_checksum_md5sha1( ssl_context *ssl,
+                                         const unsigned char *buf, size_t len )
+{
+     md5_update( &ssl->handshake->fin_md5 , buf, len );
+    sha1_update( &ssl->handshake->fin_sha1, buf, len );
+}
+#endif
+
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+#if defined(POLARSSL_SHA256_C)
+static void ssl_update_checksum_sha256( ssl_context *ssl,
+                                        const unsigned char *buf, size_t len )
+{
+    sha256_update( &ssl->handshake->fin_sha256, buf, len );
+}
+#endif
+
+#if defined(POLARSSL_SHA512_C)
+static void ssl_update_checksum_sha384( ssl_context *ssl,
+                                        const unsigned char *buf, size_t len )
+{
+    sha512_update( &ssl->handshake->fin_sha512, buf, len );
+}
+#endif
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
+
+#if defined(POLARSSL_SSL_PROTO_SSL3)
+static void ssl_calc_finished_ssl(
+                ssl_context *ssl, unsigned char *buf, int from )
+{
+    const char *sender;
+    md5_context  md5;
+    sha1_context sha1;
+
+    unsigned char padbuf[48];
+    unsigned char md5sum[16];
+    unsigned char sha1sum[20];
+
+    ssl_session *session = ssl->session_negotiate;
+    if( !session )
+        session = ssl->session;
+
+    SSL_DEBUG_MSG( 2, ( "=> calc  finished ssl" ) );
+
+    memcpy( &md5 , &ssl->handshake->fin_md5 , sizeof(md5_context)  );
+    memcpy( &sha1, &ssl->handshake->fin_sha1, sizeof(sha1_context) );
+
+    /*
+     * SSLv3:
+     *   hash =
+     *      MD5( master + pad2 +
+     *          MD5( handshake + sender + master + pad1 ) )
+     *   + SHA1( master + pad2 +
+     *         SHA1( handshake + sender + master + pad1 ) )
+     */
+
+#if !defined(POLARSSL_MD5_ALT)
+    SSL_DEBUG_BUF( 4, "finished  md5 state", (unsigned char *)
+                    md5.state, sizeof(  md5.state ) );
+#endif
+
+#if !defined(POLARSSL_SHA1_ALT)
+    SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *)
+                   sha1.state, sizeof( sha1.state ) );
+#endif
+
+    sender = ( from == SSL_IS_CLIENT ) ? "CLNT"
+                                       : "SRVR";
+
+    memset( padbuf, 0x36, 48 );
+
+    md5_update( &md5, (const unsigned char *) sender, 4 );
+    md5_update( &md5, session->master, 48 );
+    md5_update( &md5, padbuf, 48 );
+    md5_finish( &md5, md5sum );
+
+    sha1_update( &sha1, (const unsigned char *) sender, 4 );
+    sha1_update( &sha1, session->master, 48 );
+    sha1_update( &sha1, padbuf, 40 );
+    sha1_finish( &sha1, sha1sum );
+
+    memset( padbuf, 0x5C, 48 );
+
+    md5_starts( &md5 );
+    md5_update( &md5, session->master, 48 );
+    md5_update( &md5, padbuf, 48 );
+    md5_update( &md5, md5sum, 16 );
+    md5_finish( &md5, buf );
+
+    sha1_starts( &sha1 );
+    sha1_update( &sha1, session->master, 48 );
+    sha1_update( &sha1, padbuf , 40 );
+    sha1_update( &sha1, sha1sum, 20 );
+    sha1_finish( &sha1, buf + 16 );
+
+    SSL_DEBUG_BUF( 3, "calc finished result", buf, 36 );
+
+    memset(  &md5, 0, sizeof(  md5_context ) );
+    memset( &sha1, 0, sizeof( sha1_context ) );
+
+    memset(  padbuf, 0, sizeof(  padbuf ) );
+    memset(  md5sum, 0, sizeof(  md5sum ) );
+    memset( sha1sum, 0, sizeof( sha1sum ) );
+
+    SSL_DEBUG_MSG( 2, ( "<= calc  finished" ) );
+}
+#endif /* POLARSSL_SSL_PROTO_SSL3 */
+
+#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1)
+static void ssl_calc_finished_tls(
+                ssl_context *ssl, unsigned char *buf, int from )
+{
+    int len = 12;
+    const char *sender;
+    md5_context  md5;
+    sha1_context sha1;
+    unsigned char padbuf[36];
+
+    ssl_session *session = ssl->session_negotiate;
+    if( !session )
+        session = ssl->session;
+
+    SSL_DEBUG_MSG( 2, ( "=> calc  finished tls" ) );
+
+    memcpy( &md5 , &ssl->handshake->fin_md5 , sizeof(md5_context)  );
+    memcpy( &sha1, &ssl->handshake->fin_sha1, sizeof(sha1_context) );
+
+    /*
+     * TLSv1:
+     *   hash = PRF( master, finished_label,
+     *               MD5( handshake ) + SHA1( handshake ) )[0..11]
+     */
+
+#if !defined(POLARSSL_MD5_ALT)
+    SSL_DEBUG_BUF( 4, "finished  md5 state", (unsigned char *)
+                    md5.state, sizeof(  md5.state ) );
+#endif
+
+#if !defined(POLARSSL_SHA1_ALT)
+    SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *)
+                   sha1.state, sizeof( sha1.state ) );
+#endif
+
+    sender = ( from == SSL_IS_CLIENT )
+             ? "client finished"
+             : "server finished";
+
+    md5_finish(  &md5, padbuf );
+    sha1_finish( &sha1, padbuf + 16 );
+
+    ssl->handshake->tls_prf( session->master, 48, sender,
+                             padbuf, 36, buf, len );
+
+    SSL_DEBUG_BUF( 3, "calc finished result", buf, len );
+
+    memset(  &md5, 0, sizeof(  md5_context ) );
+    memset( &sha1, 0, sizeof( sha1_context ) );
+
+    memset(  padbuf, 0, sizeof(  padbuf ) );
+
+    SSL_DEBUG_MSG( 2, ( "<= calc  finished" ) );
+}
+#endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 */
+
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+#if defined(POLARSSL_SHA256_C)
+static void ssl_calc_finished_tls_sha256(
+                ssl_context *ssl, unsigned char *buf, int from )
+{
+    int len = 12;
+    const char *sender;
+    sha256_context sha256;
+    unsigned char padbuf[32];
+
+    ssl_session *session = ssl->session_negotiate;
+    if( !session )
+        session = ssl->session;
+
+    SSL_DEBUG_MSG( 2, ( "=> calc  finished tls sha256" ) );
+
+    memcpy( &sha256, &ssl->handshake->fin_sha256, sizeof(sha256_context) );
+
+    /*
+     * TLSv1.2:
+     *   hash = PRF( master, finished_label,
+     *               Hash( handshake ) )[0.11]
+     */
+
+#if !defined(POLARSSL_SHA256_ALT)
+    SSL_DEBUG_BUF( 4, "finished sha2 state", (unsigned char *)
+                   sha256.state, sizeof( sha256.state ) );
+#endif
+
+    sender = ( from == SSL_IS_CLIENT )
+             ? "client finished"
+             : "server finished";
+
+    sha256_finish( &sha256, padbuf );
+
+    ssl->handshake->tls_prf( session->master, 48, sender,
+                             padbuf, 32, buf, len );
+
+    SSL_DEBUG_BUF( 3, "calc finished result", buf, len );
+
+    memset( &sha256, 0, sizeof( sha256_context ) );
+
+    memset(  padbuf, 0, sizeof(  padbuf ) );
+
+    SSL_DEBUG_MSG( 2, ( "<= calc  finished" ) );
+}
+#endif /* POLARSSL_SHA256_C */
+
+#if defined(POLARSSL_SHA512_C)
+static void ssl_calc_finished_tls_sha384(
+                ssl_context *ssl, unsigned char *buf, int from )
+{
+    int len = 12;
+    const char *sender;
+    sha512_context sha512;
+    unsigned char padbuf[48];
+
+    ssl_session *session = ssl->session_negotiate;
+    if( !session )
+        session = ssl->session;
+
+    SSL_DEBUG_MSG( 2, ( "=> calc  finished tls sha384" ) );
+
+    memcpy( &sha512, &ssl->handshake->fin_sha512, sizeof(sha512_context) );
+
+    /*
+     * TLSv1.2:
+     *   hash = PRF( master, finished_label,
+     *               Hash( handshake ) )[0.11]
+     */
+
+#if !defined(POLARSSL_SHA512_ALT)
+    SSL_DEBUG_BUF( 4, "finished sha512 state", (unsigned char *)
+                   sha512.state, sizeof( sha512.state ) );
+#endif
+
+    sender = ( from == SSL_IS_CLIENT )
+             ? "client finished"
+             : "server finished";
+
+    sha512_finish( &sha512, padbuf );
+
+    ssl->handshake->tls_prf( session->master, 48, sender,
+                             padbuf, 48, buf, len );
+
+    SSL_DEBUG_BUF( 3, "calc finished result", buf, len );
+
+    memset( &sha512, 0, sizeof( sha512_context ) );
+
+    memset(  padbuf, 0, sizeof(  padbuf ) );
+
+    SSL_DEBUG_MSG( 2, ( "<= calc  finished" ) );
+}
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
+
+void ssl_handshake_wrapup( ssl_context *ssl )
+{
+    int resume = ssl->handshake->resume;
+
+    SSL_DEBUG_MSG( 3, ( "=> handshake wrapup" ) );
+
+    /*
+     * Free our handshake params
+     */
+    ssl_handshake_free( ssl->handshake );
+    polarssl_free( ssl->handshake );
+    ssl->handshake = NULL;
+
+    if( ssl->renegotiation == SSL_RENEGOTIATION )
+        ssl->renegotiation =  SSL_RENEGOTIATION_DONE;
+
+    /*
+     * Switch in our now active transform context
+     */
+    if( ssl->transform )
+    {
+        ssl_transform_free( ssl->transform );
+        polarssl_free( ssl->transform );
+    }
+    ssl->transform = ssl->transform_negotiate;
+    ssl->transform_negotiate = NULL;
+
+    if( ssl->session )
+    {
+        ssl_session_free( ssl->session );
+        polarssl_free( ssl->session );
+    }
+    ssl->session = ssl->session_negotiate;
+    ssl->session_negotiate = NULL;
+
+    /*
+     * Add cache entry
+     */
+    if( ssl->f_set_cache != NULL &&
+        ssl->session->length != 0 &&
+        resume == 0 )
+    {
+        if( ssl->f_set_cache( ssl->p_set_cache, ssl->session ) != 0 )
+            SSL_DEBUG_MSG( 1, ( "cache did not store session" ) );
+    }
+
+    ssl->state++;
+
+    SSL_DEBUG_MSG( 3, ( "<= handshake wrapup" ) );
+}
+
+int ssl_write_finished( ssl_context *ssl )
+{
+    int ret, hash_len;
+
+    SSL_DEBUG_MSG( 2, ( "=> write finished" ) );
+
+    /*
+     * Set the out_msg pointer to the correct location based on IV length
+     */
+    if( ssl->minor_ver >= SSL_MINOR_VERSION_2 )
+    {
+        ssl->out_msg = ssl->out_iv + ssl->transform_negotiate->ivlen -
+                       ssl->transform_negotiate->fixed_ivlen;
+    }
+    else
+        ssl->out_msg = ssl->out_iv;
+
+    ssl->handshake->calc_finished( ssl, ssl->out_msg + 4, ssl->endpoint );
+
+    // TODO TLS/1.2 Hash length is determined by cipher suite (Page 63)
+    hash_len = ( ssl->minor_ver == SSL_MINOR_VERSION_0 ) ? 36 : 12;
+
+    ssl->verify_data_len = hash_len;
+    memcpy( ssl->own_verify_data, ssl->out_msg + 4, hash_len );
+
+    ssl->out_msglen  = 4 + hash_len;
+    ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+    ssl->out_msg[0]  = SSL_HS_FINISHED;
+
+    /*
+     * In case of session resuming, invert the client and server
+     * ChangeCipherSpec messages order.
+     */
+    if( ssl->handshake->resume != 0 )
+    {
+        if( ssl->endpoint == SSL_IS_CLIENT )
+            ssl->state = SSL_HANDSHAKE_WRAPUP;
+        else
+            ssl->state = SSL_CLIENT_CHANGE_CIPHER_SPEC;
+    }
+    else
+        ssl->state++;
+
+    /*
+     * Switch to our negotiated transform and session parameters for outbound
+     * data.
+     */
+    SSL_DEBUG_MSG( 3, ( "switching to new transform spec for outbound data" ) );
+    ssl->transform_out = ssl->transform_negotiate;
+    ssl->session_out = ssl->session_negotiate;
+    memset( ssl->out_ctr, 0, 8 );
+
+#if defined(POLARSSL_SSL_HW_RECORD_ACCEL)
+    if( ssl_hw_record_activate != NULL)
+    {
+        if( ( ret = ssl_hw_record_activate( ssl, SSL_CHANNEL_OUTBOUND ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_hw_record_activate", ret );
+            return( POLARSSL_ERR_SSL_HW_ACCEL_FAILED );
+        }
+    }
+#endif
+
+    if( ( ret = ssl_write_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+        return( ret );
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= write finished" ) );
+
+    return( 0 );
+}
+
+int ssl_parse_finished( ssl_context *ssl )
+{
+    int ret;
+    unsigned int hash_len;
+    unsigned char buf[36];
+
+    SSL_DEBUG_MSG( 2, ( "=> parse finished" ) );
+
+    ssl->handshake->calc_finished( ssl, buf, ssl->endpoint ^ 1 );
+
+    /*
+     * Switch to our negotiated transform and session parameters for inbound
+     * data.
+     */
+    SSL_DEBUG_MSG( 3, ( "switching to new transform spec for inbound data" ) );
+    ssl->transform_in = ssl->transform_negotiate;
+    ssl->session_in = ssl->session_negotiate;
+    memset( ssl->in_ctr, 0, 8 );
+
+    /*
+     * Set the in_msg pointer to the correct location based on IV length
+     */
+    if( ssl->minor_ver >= SSL_MINOR_VERSION_2 )
+    {
+        ssl->in_msg = ssl->in_iv + ssl->transform_negotiate->ivlen -
+                      ssl->transform_negotiate->fixed_ivlen;
+    }
+    else
+        ssl->in_msg = ssl->in_iv;
+
+#if defined(POLARSSL_SSL_HW_RECORD_ACCEL)
+    if( ssl_hw_record_activate != NULL)
+    {
+        if( ( ret = ssl_hw_record_activate( ssl, SSL_CHANNEL_INBOUND ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_hw_record_activate", ret );
+            return( POLARSSL_ERR_SSL_HW_ACCEL_FAILED );
+        }
+    }
+#endif
+
+    if( ( ret = ssl_read_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+        return( ret );
+    }
+
+    if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad finished message" ) );
+        return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+    }
+
+    // TODO TLS/1.2 Hash length is determined by cipher suite (Page 63)
+    hash_len = ( ssl->minor_ver == SSL_MINOR_VERSION_0 ) ? 36 : 12;
+
+    if( ssl->in_msg[0] != SSL_HS_FINISHED ||
+        ssl->in_hslen  != 4 + hash_len )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad finished message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_FINISHED );
+    }
+
+    if( safer_memcmp( ssl->in_msg + 4, buf, hash_len ) != 0 )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad finished message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_FINISHED );
+    }
+
+    ssl->verify_data_len = hash_len;
+    memcpy( ssl->peer_verify_data, buf, hash_len );
+
+    if( ssl->handshake->resume != 0 )
+    {
+        if( ssl->endpoint == SSL_IS_CLIENT )
+            ssl->state = SSL_CLIENT_CHANGE_CIPHER_SPEC;
+
+        if( ssl->endpoint == SSL_IS_SERVER )
+            ssl->state = SSL_HANDSHAKE_WRAPUP;
+    }
+    else
+        ssl->state++;
+
+    SSL_DEBUG_MSG( 2, ( "<= parse finished" ) );
+
+    return( 0 );
+}
+
+static int ssl_handshake_init( ssl_context *ssl )
+{
+    if( ssl->transform_negotiate )
+        ssl_transform_free( ssl->transform_negotiate );
+    else
+    {
+        ssl->transform_negotiate =
+            (ssl_transform *) polarssl_malloc( sizeof(ssl_transform) );
+
+        if( ssl->transform_negotiate != NULL )
+            memset( ssl->transform_negotiate, 0, sizeof(ssl_transform) );
+    }
+
+    if( ssl->session_negotiate )
+        ssl_session_free( ssl->session_negotiate );
+    else
+    {
+        ssl->session_negotiate =
+            (ssl_session *) polarssl_malloc( sizeof(ssl_session) );
+
+        if( ssl->session_negotiate != NULL )
+            memset( ssl->session_negotiate, 0, sizeof(ssl_session) );
+    }
+
+    if( ssl->handshake )
+        ssl_handshake_free( ssl->handshake );
+    else
+    {
+        ssl->handshake = (ssl_handshake_params *)
+            polarssl_malloc( sizeof(ssl_handshake_params) );
+
+        if( ssl->handshake != NULL )
+            memset( ssl->handshake, 0, sizeof(ssl_handshake_params) );
+    }
+
+    if( ssl->handshake == NULL ||
+        ssl->transform_negotiate == NULL ||
+        ssl->session_negotiate == NULL )
+    {
+        SSL_DEBUG_MSG( 1, ( "malloc() of ssl sub-contexts failed" ) );
+        return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+    }
+
+#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_1)
+     md5_starts( &ssl->handshake->fin_md5 );
+    sha1_starts( &ssl->handshake->fin_sha1 );
+#endif
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+#if defined(POLARSSL_SHA256_C)
+    sha256_starts( &ssl->handshake->fin_sha256, 0 );
+#endif
+#if defined(POLARSSL_SHA512_C)
+    sha512_starts( &ssl->handshake->fin_sha512, 1 );
+#endif
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
+
+    ssl->handshake->update_checksum = ssl_update_checksum_start;
+    ssl->handshake->sig_alg = SSL_HASH_SHA1;
+
+#if defined(POLARSSL_ECDH_C)
+    ecdh_init( &ssl->handshake->ecdh_ctx );
+#endif
+
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+    ssl->handshake->key_cert = ssl->key_cert;
+#endif
+
+    return( 0 );
+}
+
+/*
+ * Initialize an SSL context
+ */
+int ssl_init( ssl_context *ssl )
+{
+    int ret;
+    int len = SSL_BUFFER_LEN;
+    
+    void *sptr1 = ssl->f_dbg;
+    void *sptr2 = ssl->f_rng;
+
+//    SSL_DEBUG_MSG( 1, ( "ssl_init" ) );
+    memset( ssl, 0, sizeof( ssl_context ) );
+    
+    ssl->f_dbg = sptr1;
+    ssl->f_rng = sptr2;
+
+    /*
+     * Sane defaults
+     */
+    ssl->min_major_ver = SSL_MIN_MAJOR_VERSION;
+    ssl->min_minor_ver = SSL_MIN_MINOR_VERSION;
+    ssl->max_major_ver = SSL_MAX_MAJOR_VERSION;
+    ssl->max_minor_ver = SSL_MAX_MINOR_VERSION;
+
+    ssl_set_ciphersuites( ssl, ssl_list_ciphersuites() );
+
+#if defined(POLARSSL_DHM_C)
+    if( ( ret = mpi_read_string( &ssl->dhm_P, 16,
+                                 POLARSSL_DHM_RFC5114_MODP_1024_P) ) != 0 ||
+        ( ret = mpi_read_string( &ssl->dhm_G, 16,
+                                 POLARSSL_DHM_RFC5114_MODP_1024_G) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "mpi_read_string", ret );
+        return( ret );
+    }
+#endif
+
+    /*
+     * Prepare base structures
+     */
+    ssl->in_ctr = (unsigned char *) polarssl_malloc( len );
+    ssl->in_hdr = ssl->in_ctr +  8;
+    ssl->in_iv  = ssl->in_ctr + 13;
+    ssl->in_msg = ssl->in_ctr + 13;
+
+    if( ssl->in_ctr == NULL )
+    {
+        SSL_DEBUG_MSG( 1, ( "malloc(%d bytes) failed", len ) );
+        return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+    }
+
+    ssl->out_ctr = (unsigned char *) polarssl_malloc( len );
+    ssl->out_hdr = ssl->out_ctr +  8;
+    ssl->out_iv  = ssl->out_ctr + 13;
+    ssl->out_msg = ssl->out_ctr + 13;
+
+    if( ssl->out_ctr == NULL )
+    {
+        SSL_DEBUG_MSG( 1, ( "malloc(%d bytes) failed", len ) );
+        polarssl_free( ssl->in_ctr );
+        ssl->in_ctr = NULL;
+        return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+    }
+
+    memset( ssl-> in_ctr, 0, SSL_BUFFER_LEN );
+    memset( ssl->out_ctr, 0, SSL_BUFFER_LEN );
+
+#if defined(POLARSSL_SSL_SESSION_TICKETS)
+    ssl->ticket_lifetime = SSL_DEFAULT_TICKET_LIFETIME;
+#endif
+
+#if defined(POLARSSL_SSL_SET_CURVES)
+    ssl->curve_list = ecp_grp_id_list( );
+#endif
+
+    if( ( ret = ssl_handshake_init( ssl ) ) != 0 )
+        return( ret );
+
+    return( 0 );
+}
+
+/*
+ * Reset an initialized and used SSL context for re-use while retaining
+ * all application-set variables, function pointers and data.
+ */
+int ssl_session_reset( ssl_context *ssl )
+{
+    int ret;
+
+    ssl->state = SSL_HELLO_REQUEST;
+    ssl->renegotiation = SSL_INITIAL_HANDSHAKE;
+    ssl->secure_renegotiation = SSL_LEGACY_RENEGOTIATION;
+
+    ssl->verify_data_len = 0;
+    memset( ssl->own_verify_data, 0, 36 );
+    memset( ssl->peer_verify_data, 0, 36 );
+
+    ssl->in_offt = NULL;
+
+    ssl->in_msg = ssl->in_ctr + 13;
+    ssl->in_msgtype = 0;
+    ssl->in_msglen = 0;
+    ssl->in_left = 0;
+
+    ssl->in_hslen = 0;
+    ssl->nb_zero = 0;
+    ssl->record_read = 0;
+
+    ssl->out_msg = ssl->out_ctr + 13;
+    ssl->out_msgtype = 0;
+    ssl->out_msglen = 0;
+    ssl->out_left = 0;
+
+    ssl->transform_in = NULL;
+    ssl->transform_out = NULL;
+
+    memset( ssl->out_ctr, 0, SSL_BUFFER_LEN );
+    memset( ssl->in_ctr, 0, SSL_BUFFER_LEN );
+
+#if defined(POLARSSL_SSL_HW_RECORD_ACCEL)
+    if( ssl_hw_record_reset != NULL)
+    {
+        SSL_DEBUG_MSG( 2, ( "going for ssl_hw_record_reset()" ) );
+        if( ( ret = ssl_hw_record_reset( ssl ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_hw_record_reset", ret );
+            return( POLARSSL_ERR_SSL_HW_ACCEL_FAILED );
+        }
+    }
+#endif
+
+    if( ssl->transform )
+    {
+        ssl_transform_free( ssl->transform );
+        polarssl_free( ssl->transform );
+        ssl->transform = NULL;
+    }
+
+    if( ssl->session )
+    {
+        ssl_session_free( ssl->session );
+        polarssl_free( ssl->session );
+        ssl->session = NULL;
+    }
+
+#if defined(POLARSSL_SSL_ALPN)
+    ssl->alpn_chosen = NULL;
+#endif
+
+    if( ( ret = ssl_handshake_init( ssl ) ) != 0 )
+        return( ret );
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_SSL_SESSION_TICKETS)
+/*
+ * Allocate and initialize ticket keys
+ */
+static int ssl_ticket_keys_init( ssl_context *ssl )
+{
+    int ret;
+    ssl_ticket_keys *tkeys;
+    unsigned char buf[16];
+
+    if( ssl->ticket_keys != NULL )
+        return( 0 );
+
+    tkeys = (ssl_ticket_keys *) polarssl_malloc( sizeof(ssl_ticket_keys) );
+    if( tkeys == NULL )
+        return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+
+    if( ( ret = ssl->f_rng( ssl->p_rng, tkeys->key_name, 16 ) ) != 0 )
+    {
+        polarssl_free( tkeys );
+        return( ret );
+    }
+
+    if( ( ret = ssl->f_rng( ssl->p_rng, buf, 16 ) ) != 0 ||
+        ( ret = aes_setkey_enc( &tkeys->enc, buf, 128 ) ) != 0 ||
+        ( ret = aes_setkey_dec( &tkeys->dec, buf, 128 ) ) != 0 )
+    {
+        polarssl_free( tkeys );
+        return( ret );
+    }
+
+    if( ( ret = ssl->f_rng( ssl->p_rng, tkeys->mac_key, 16 ) ) != 0 )
+    {
+        polarssl_free( tkeys );
+        return( ret );
+    }
+
+    ssl->ticket_keys = tkeys;
+
+    return( 0 );
+}
+#endif /* POLARSSL_SSL_SESSION_TICKETS */
+
+/*
+ * SSL set accessors
+ */
+void ssl_set_endpoint( ssl_context *ssl, int endpoint )
+{
+    ssl->endpoint   = endpoint;
+
+#if defined(POLARSSL_SSL_SESSION_TICKETS)
+    if( endpoint == SSL_IS_CLIENT )
+        ssl->session_tickets = SSL_SESSION_TICKETS_ENABLED;
+#endif
+}
+
+void ssl_set_authmode( ssl_context *ssl, int authmode )
+{
+    ssl->authmode   = authmode;
+}
+
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+void ssl_set_verify( ssl_context *ssl,
+                     int (*f_vrfy)(void *, x509_crt *, int, int *),
+                     void *p_vrfy )
+{
+    ssl->f_vrfy      = f_vrfy;
+    ssl->p_vrfy      = p_vrfy;
+}
+#endif /* POLARSSL_X509_CRT_PARSE_C */
+
+void ssl_set_rng( ssl_context *ssl,
+                  int (*f_rng)(void *, unsigned char *, size_t),
+                  void *p_rng )
+{
+    ssl->f_rng      = f_rng;
+    ssl->p_rng      = p_rng;
+}
+
+void ssl_set_dbg( ssl_context *ssl,
+                  void (*f_dbg)(void *, int, const char *),
+                  void  *p_dbg )
+{
+    ssl->f_dbg      = f_dbg;
+    ssl->p_dbg      = p_dbg;
+}
+
+void ssl_set_bio( ssl_context *ssl,
+            int (*f_recv)(void *, unsigned char *, size_t), void *p_recv,
+            int (*f_send)(void *, const unsigned char *, size_t), void *p_send )
+{
+    ssl->f_recv     = f_recv;
+    ssl->f_send     = f_send;
+    ssl->p_recv     = p_recv;
+    ssl->p_send     = p_send;
+}
+
+void ssl_set_session_cache( ssl_context *ssl,
+        int (*f_get_cache)(void *, ssl_session *), void *p_get_cache,
+        int (*f_set_cache)(void *, const ssl_session *), void *p_set_cache )
+{
+    ssl->f_get_cache = f_get_cache;
+    ssl->p_get_cache = p_get_cache;
+    ssl->f_set_cache = f_set_cache;
+    ssl->p_set_cache = p_set_cache;
+}
+
+int ssl_set_session( ssl_context *ssl, const ssl_session *session )
+{
+    int ret;
+
+    if( ssl == NULL ||
+        session == NULL ||
+        ssl->session_negotiate == NULL ||
+        ssl->endpoint != SSL_IS_CLIENT )
+    {
+        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+    }
+
+    if( ( ret = ssl_session_copy( ssl->session_negotiate, session ) ) != 0 )
+        return( ret );
+
+    ssl->handshake->resume = 1;
+
+    return( 0 );
+}
+
+void ssl_set_ciphersuites( ssl_context *ssl, const int *ciphersuites )
+{
+    ssl->ciphersuite_list[SSL_MINOR_VERSION_0] = ciphersuites;
+    ssl->ciphersuite_list[SSL_MINOR_VERSION_1] = ciphersuites;
+    ssl->ciphersuite_list[SSL_MINOR_VERSION_2] = ciphersuites;
+    ssl->ciphersuite_list[SSL_MINOR_VERSION_3] = ciphersuites;
+}
+
+void ssl_set_ciphersuites_for_version( ssl_context *ssl,
+                                       const int *ciphersuites,
+                                       int major, int minor )
+{
+    if( major != SSL_MAJOR_VERSION_3 )
+        return;
+
+    if( minor < SSL_MINOR_VERSION_0 || minor > SSL_MINOR_VERSION_3 )
+        return;
+
+    ssl->ciphersuite_list[minor] = ciphersuites;
+}
+
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+/* Add a new (empty) key_cert entry an return a pointer to it */
+static ssl_key_cert *ssl_add_key_cert( ssl_context *ssl )
+{
+    ssl_key_cert *key_cert, *last;
+
+    key_cert = (ssl_key_cert *) polarssl_malloc( sizeof(ssl_key_cert) );
+    if( key_cert == NULL )
+        return( NULL );
+
+    memset( key_cert, 0, sizeof( ssl_key_cert ) );
+
+    /* Append the new key_cert to the (possibly empty) current list */
+    if( ssl->key_cert == NULL )
+    {
+        ssl->key_cert = key_cert;
+        if( ssl->handshake != NULL )
+            ssl->handshake->key_cert = key_cert;
+    }
+    else
+    {
+        last = ssl->key_cert;
+        while( last->next != NULL )
+            last = last->next;
+        last->next = key_cert;
+    }
+
+    return key_cert;
+}
+
+void ssl_set_ca_chain( ssl_context *ssl, x509_crt *ca_chain,
+                       x509_crl *ca_crl, const char *peer_cn )
+{
+    ssl->ca_chain   = ca_chain;
+    ssl->ca_crl     = ca_crl;
+    ssl->peer_cn    = peer_cn;
+}
+
+int ssl_set_own_cert( ssl_context *ssl, x509_crt *own_cert,
+                       pk_context *pk_key )
+{
+    ssl_key_cert *key_cert = ssl_add_key_cert( ssl );
+
+    if( key_cert == NULL )
+        return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+
+    key_cert->cert = own_cert;
+    key_cert->key  = pk_key;
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_RSA_C)
+int ssl_set_own_cert_rsa( ssl_context *ssl, x509_crt *own_cert,
+                           rsa_context *rsa_key )
+{
+    int ret;
+    ssl_key_cert *key_cert = ssl_add_key_cert( ssl );
+
+    if( key_cert == NULL )
+        return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+
+    key_cert->key = (pk_context *) polarssl_malloc( sizeof(pk_context) );
+    if( key_cert->key == NULL )
+        return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+
+    pk_init( key_cert->key );
+
+    ret = pk_init_ctx( key_cert->key, pk_info_from_type( POLARSSL_PK_RSA ) );
+    if( ret != 0 )
+        return( ret );
+
+    if( ( ret = rsa_copy( pk_rsa( *key_cert->key ), rsa_key ) ) != 0 )
+        return( ret );
+
+    key_cert->cert = own_cert;
+    key_cert->key_own_alloc = 1;
+
+    return( 0 );
+}
+#endif /* POLARSSL_RSA_C */
+
+int ssl_set_own_cert_alt( ssl_context *ssl, x509_crt *own_cert,
+                          void *rsa_key,
+                          rsa_decrypt_func rsa_decrypt,
+                          rsa_sign_func rsa_sign,
+                          rsa_key_len_func rsa_key_len )
+{
+    int ret;
+    ssl_key_cert *key_cert = ssl_add_key_cert( ssl );
+
+    if( key_cert == NULL )
+        return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+
+    key_cert->key = (pk_context *) polarssl_malloc( sizeof(pk_context) );
+    if( key_cert->key == NULL )
+        return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+
+    pk_init( key_cert->key );
+
+    if( ( ret = pk_init_ctx_rsa_alt( key_cert->key, rsa_key,
+                                 rsa_decrypt, rsa_sign, rsa_key_len ) ) != 0 )
+        return( ret );
+
+    key_cert->cert = own_cert;
+    key_cert->key_own_alloc = 1;
+
+    return( 0 );
+}
+#endif /* POLARSSL_X509_CRT_PARSE_C */
+
+#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
+int ssl_set_psk( ssl_context *ssl, const unsigned char *psk, size_t psk_len,
+                 const unsigned char *psk_identity, size_t psk_identity_len )
+{
+    if( psk == NULL || psk_identity == NULL )
+        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+    /*
+     * The length will be check later anyway, but in case it is obviously
+     * too large, better abort now. The PMS is as follows:
+     * other_len (2 bytes) + other + psk_len (2 bytes) + psk
+     */
+    if( psk_len + 4 > POLARSSL_PREMASTER_SIZE )
+        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+    if( ssl->psk != NULL )
+    {
+        polarssl_free( ssl->psk );
+        polarssl_free( ssl->psk_identity );
+    }
+
+    ssl->psk_len = psk_len;
+    ssl->psk_identity_len = psk_identity_len;
+
+    ssl->psk = (unsigned char *) polarssl_malloc( ssl->psk_len );
+    ssl->psk_identity = (unsigned char *)
+                                polarssl_malloc( ssl->psk_identity_len );
+
+    if( ssl->psk == NULL || ssl->psk_identity == NULL )
+        return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+
+    memcpy( ssl->psk, psk, ssl->psk_len );
+    memcpy( ssl->psk_identity, psk_identity, ssl->psk_identity_len );
+
+    return( 0 );
+}
+
+void ssl_set_psk_cb( ssl_context *ssl,
+                     int (*f_psk)(void *, ssl_context *, const unsigned char *,
+                     size_t),
+                     void *p_psk )
+{
+    ssl->f_psk = f_psk;
+    ssl->p_psk = p_psk;
+}
+#endif /* POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED */
+
+#if defined(POLARSSL_DHM_C)
+int ssl_set_dh_param( ssl_context *ssl, const char *dhm_P, const char *dhm_G )
+{
+    int ret;
+
+    if( ( ret = mpi_read_string( &ssl->dhm_P, 16, dhm_P ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "mpi_read_string", ret );
+        return( ret );
+    }
+
+    if( ( ret = mpi_read_string( &ssl->dhm_G, 16, dhm_G ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "mpi_read_string", ret );
+        return( ret );
+    }
+
+    return( 0 );
+}
+
+int ssl_set_dh_param_ctx( ssl_context *ssl, dhm_context *dhm_ctx )
+{
+    int ret;
+
+    if( ( ret = mpi_copy(&ssl->dhm_P, &dhm_ctx->P) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "mpi_copy", ret );
+        return( ret );
+    }
+
+    if( ( ret = mpi_copy(&ssl->dhm_G, &dhm_ctx->G) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "mpi_copy", ret );
+        return( ret );
+    }
+
+    return( 0 );
+}
+#endif /* POLARSSL_DHM_C */
+
+#if defined(POLARSSL_SSL_SET_CURVES)
+/*
+ * Set the allowed elliptic curves
+ */
+void ssl_set_curves( ssl_context *ssl, const ecp_group_id *curve_list )
+{
+  ssl->curve_list = curve_list;
+}
+#endif
+
+#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
+int ssl_set_hostname( ssl_context *ssl, const char *hostname )
+{
+    if( hostname == NULL )
+        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+    ssl->hostname_len = strlen( hostname );
+
+    if( ssl->hostname_len + 1 == 0 )
+        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+    ssl->hostname = (unsigned char *) polarssl_malloc( ssl->hostname_len + 1 );
+
+    if( ssl->hostname == NULL )
+        return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+
+    memcpy( ssl->hostname, (const unsigned char *) hostname,
+            ssl->hostname_len );
+
+    ssl->hostname[ssl->hostname_len] = '\0';
+
+    return( 0 );
+}
+
+void ssl_set_sni( ssl_context *ssl,
+                  int (*f_sni)(void *, ssl_context *,
+                                const unsigned char *, size_t),
+                  void *p_sni )
+{
+    ssl->f_sni = f_sni;
+    ssl->p_sni = p_sni;
+}
+#endif /* POLARSSL_SSL_SERVER_NAME_INDICATION */
+
+#if defined(POLARSSL_SSL_ALPN)
+int ssl_set_alpn_protocols( ssl_context *ssl, const char **protos )
+{
+    size_t cur_len, tot_len;
+    const char **p;
+
+    /*
+     * "Empty strings MUST NOT be included and byte strings MUST NOT be
+     * truncated". Check lengths now rather than later.
+     */
+    tot_len = 0;
+    for( p = protos; *p != NULL; p++ )
+    {
+        cur_len = strlen( *p );
+        tot_len += cur_len;
+
+        if( cur_len == 0 || cur_len > 255 || tot_len > 65535 )
+            return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+    }
+
+    ssl->alpn_list = protos;
+
+    return( 0 );
+}
+
+const char *ssl_get_alpn_protocol( const ssl_context *ssl )
+{
+    return ssl->alpn_chosen;
+}
+#endif /* POLARSSL_SSL_ALPN */
+
+void ssl_set_max_version( ssl_context *ssl, int major, int minor )
+{
+    if( major >= SSL_MIN_MAJOR_VERSION && major <= SSL_MAX_MAJOR_VERSION &&
+        minor >= SSL_MIN_MINOR_VERSION && minor <= SSL_MAX_MINOR_VERSION )
+    {
+        ssl->max_major_ver = major;
+        ssl->max_minor_ver = minor;
+    }
+}
+
+void ssl_set_min_version( ssl_context *ssl, int major, int minor )
+{
+    if( major >= SSL_MIN_MAJOR_VERSION && major <= SSL_MAX_MAJOR_VERSION &&
+        minor >= SSL_MIN_MINOR_VERSION && minor <= SSL_MAX_MINOR_VERSION )
+    {
+        ssl->min_major_ver = major;
+        ssl->min_minor_ver = minor;
+    }
+}
+
+#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH)
+int ssl_set_max_frag_len( ssl_context *ssl, unsigned char mfl_code )
+{
+    if( mfl_code >= SSL_MAX_FRAG_LEN_INVALID ||
+        mfl_code_to_length[mfl_code] > SSL_MAX_CONTENT_LEN )
+    {
+        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+    }
+
+    ssl->mfl_code = mfl_code;
+
+    return( 0 );
+}
+#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */
+
+#if defined(POLARSSL_SSL_TRUNCATED_HMAC)
+int ssl_set_truncated_hmac( ssl_context *ssl, int truncate )
+{
+    if( ssl->endpoint != SSL_IS_CLIENT )
+        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+    ssl->trunc_hmac = truncate;
+
+    return( 0 );
+}
+#endif /* POLARSSL_SSL_TRUNCATED_HMAC */
+
+void ssl_set_renegotiation( ssl_context *ssl, int renegotiation )
+{
+    ssl->disable_renegotiation = renegotiation;
+}
+
+void ssl_legacy_renegotiation( ssl_context *ssl, int allow_legacy )
+{
+    ssl->allow_legacy_renegotiation = allow_legacy;
+}
+
+#if defined(POLARSSL_SSL_SESSION_TICKETS)
+int ssl_set_session_tickets( ssl_context *ssl, int use_tickets )
+{
+    ssl->session_tickets = use_tickets;
+
+    if( ssl->endpoint == SSL_IS_CLIENT )
+        return( 0 );
+
+    if( ssl->f_rng == NULL )
+        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+    return( ssl_ticket_keys_init( ssl ) );
+}
+
+void ssl_set_session_ticket_lifetime( ssl_context *ssl, int lifetime )
+{
+    ssl->ticket_lifetime = lifetime;
+}
+#endif /* POLARSSL_SSL_SESSION_TICKETS */
+
+/*
+ * SSL get accessors
+ */
+size_t ssl_get_bytes_avail( const ssl_context *ssl )
+{
+    return( ssl->in_offt == NULL ? 0 : ssl->in_msglen );
+}
+
+int ssl_get_verify_result( const ssl_context *ssl )
+{
+    return( ssl->session->verify_result );
+}
+
+const char *ssl_get_ciphersuite( const ssl_context *ssl )
+{
+    if( ssl == NULL || ssl->session == NULL )
+        return NULL;
+
+    return ssl_get_ciphersuite_name( ssl->session->ciphersuite );
+}
+
+const char *ssl_get_version( const ssl_context *ssl )
+{
+    switch( ssl->minor_ver )
+    {
+        case SSL_MINOR_VERSION_0:
+            return( "SSLv3.0" );
+
+        case SSL_MINOR_VERSION_1:
+            return( "TLSv1.0" );
+
+        case SSL_MINOR_VERSION_2:
+            return( "TLSv1.1" );
+
+        case SSL_MINOR_VERSION_3:
+            return( "TLSv1.2" );
+
+        default:
+            break;
+    }
+    return( "unknown" );
+}
+
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+const x509_crt *ssl_get_peer_cert( const ssl_context *ssl )
+{
+    if( ssl == NULL || ssl->session == NULL )
+        return NULL;
+
+    return ssl->session->peer_cert;
+}
+#endif /* POLARSSL_X509_CRT_PARSE_C */
+
+int ssl_get_session( const ssl_context *ssl, ssl_session *dst )
+{
+    if( ssl == NULL ||
+        dst == NULL ||
+        ssl->session == NULL ||
+        ssl->endpoint != SSL_IS_CLIENT )
+    {
+        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+    }
+
+    return( ssl_session_copy( dst, ssl->session ) );
+}
+
+/*
+ * Perform a single step of the SSL handshake
+ */
+int ssl_handshake_step( ssl_context *ssl )
+{
+    int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
+
+#if defined(POLARSSL_SSL_CLI_C)
+    if( ssl->endpoint == SSL_IS_CLIENT )
+        ret = ssl_handshake_client_step( ssl );
+#endif
+
+#if defined(POLARSSL_SSL_SRV_C)
+    if( ssl->endpoint == SSL_IS_SERVER )
+        ret = ssl_handshake_server_step( ssl );
+#endif
+
+    return( ret );
+}
+
+/*
+ * Perform the SSL handshake
+ */
+int ssl_handshake( ssl_context *ssl )
+{
+    int ret = 0;
+
+    SSL_DEBUG_MSG( 2, ( "=> handshake" ) );
+
+    while( ssl->state != SSL_HANDSHAKE_OVER )
+    {
+        ret = ssl_handshake_step( ssl );
+
+        if( ret != 0 )
+            break;
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= handshake" ) );
+
+    return( ret );
+}
+
+#if defined(POLARSSL_SSL_SRV_C)
+/*
+ * Write HelloRequest to request renegotiation on server
+ */
+static int ssl_write_hello_request( ssl_context *ssl )
+{
+    int ret;
+
+    SSL_DEBUG_MSG( 2, ( "=> write hello request" ) );
+
+    ssl->out_msglen  = 4;
+    ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+    ssl->out_msg[0]  = SSL_HS_HELLO_REQUEST;
+
+    if( ( ret = ssl_write_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+        return( ret );
+    }
+
+    ssl->renegotiation = SSL_RENEGOTIATION_PENDING;
+
+    SSL_DEBUG_MSG( 2, ( "<= write hello request" ) );
+
+    return( 0 );
+}
+#endif /* POLARSSL_SSL_SRV_C */
+
+/*
+ * Actually renegotiate current connection, triggered by either:
+ * - calling ssl_renegotiate() on client,
+ * - receiving a HelloRequest on client during ssl_read(),
+ * - receiving any handshake message on server during ssl_read() after the
+ *   initial handshake is completed
+ * If the handshake doesn't complete due to waiting for I/O, it will continue
+ * during the next calls to ssl_renegotiate() or ssl_read() respectively.
+ */
+static int ssl_start_renegotiation( ssl_context *ssl )
+{
+    int ret;
+
+    SSL_DEBUG_MSG( 2, ( "=> renegotiate" ) );
+
+    if( ( ret = ssl_handshake_init( ssl ) ) != 0 )
+        return( ret );
+
+    ssl->state = SSL_HELLO_REQUEST;
+    ssl->renegotiation = SSL_RENEGOTIATION;
+
+    if( ( ret = ssl_handshake( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_handshake", ret );
+        return( ret );
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= renegotiate" ) );
+
+    return( 0 );
+}
+
+/*
+ * Renegotiate current connection on client,
+ * or request renegotiation on server
+ */
+int ssl_renegotiate( ssl_context *ssl )
+{
+    int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
+
+#if defined(POLARSSL_SSL_SRV_C)
+    /* On server, just send the request */
+    if( ssl->endpoint == SSL_IS_SERVER )
+    {
+        if( ssl->state != SSL_HANDSHAKE_OVER )
+            return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+        return( ssl_write_hello_request( ssl ) );
+    }
+#endif /* POLARSSL_SSL_SRV_C */
+
+#if defined(POLARSSL_SSL_CLI_C)
+    /*
+     * On client, either start the renegotiation process or,
+     * if already in progress, continue the handshake
+     */
+    if( ssl->renegotiation != SSL_RENEGOTIATION )
+    {
+        if( ssl->state != SSL_HANDSHAKE_OVER )
+            return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+        if( ( ret = ssl_start_renegotiation( ssl ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret );
+            return( ret );
+        }
+    }
+    else
+    {
+        if( ( ret = ssl_handshake( ssl ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_handshake", ret );
+            return( ret );
+        }
+    }
+#endif /* POLARSSL_SSL_CLI_C */
+
+    return( ret );
+}
+
+/*
+ * Receive application data decrypted from the SSL layer
+ */
+int ssl_read( ssl_context *ssl, unsigned char *buf, size_t len )
+{
+    int ret;
+    size_t n;
+
+    SSL_DEBUG_MSG( 2, ( "=> read" ) );
+
+    if( ssl->state != SSL_HANDSHAKE_OVER )
+    {
+        if( ( ret = ssl_handshake( ssl ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_handshake", ret );
+            return( ret );
+        }
+    }
+
+    if( ssl->in_offt == NULL )
+    {
+        if( ( ret = ssl_read_record( ssl ) ) != 0 )
+        {
+            if( ret == POLARSSL_ERR_SSL_CONN_EOF )
+                return( 0 );
+
+            SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+            return( ret );
+        }
+
+        if( ssl->in_msglen  == 0 &&
+            ssl->in_msgtype == SSL_MSG_APPLICATION_DATA )
+        {
+            /*
+             * OpenSSL sends empty messages to randomize the IV
+             */
+            if( ( ret = ssl_read_record( ssl ) ) != 0 )
+            {
+                if( ret == POLARSSL_ERR_SSL_CONN_EOF )
+                    return( 0 );
+
+                SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+                return( ret );
+            }
+        }
+
+        if( ssl->in_msgtype == SSL_MSG_HANDSHAKE )
+        {
+            SSL_DEBUG_MSG( 1, ( "received handshake message" ) );
+
+            if( ssl->endpoint == SSL_IS_CLIENT &&
+                ( ssl->in_msg[0] != SSL_HS_HELLO_REQUEST ||
+                  ssl->in_hslen != 4 ) )
+            {
+                SSL_DEBUG_MSG( 1, ( "handshake received (not HelloRequest)" ) );
+                return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+            }
+
+            if( ssl->disable_renegotiation == SSL_RENEGOTIATION_DISABLED ||
+                ( ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION &&
+                  ssl->allow_legacy_renegotiation ==
+                                                SSL_LEGACY_NO_RENEGOTIATION ) )
+            {
+                SSL_DEBUG_MSG( 3, ( "ignoring renegotiation, sending alert" ) );
+
+#if defined(POLARSSL_SSL_PROTO_SSL3)
+                if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
+                {
+                    /*
+                     * SSLv3 does not have a "no_renegotiation" alert
+                     */
+                    if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
+                        return( ret );
+                }
+                else
+#endif /* POLARSSL_SSL_PROTO_SSL3 */
+#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_2)
+                if( ssl->minor_ver >= SSL_MINOR_VERSION_1 )
+                {
+                    if( ( ret = ssl_send_alert_message( ssl,
+                                    SSL_ALERT_LEVEL_WARNING,
+                                    SSL_ALERT_MSG_NO_RENEGOTIATION ) ) != 0 )
+                    {
+                        return( ret );
+                    }
+                }
+                else
+#endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 ||
+          POLARSSL_SSL_PROTO_TLS1_2 */
+                {
+                    SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+                    return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+                }
+            }
+            else
+            {
+                if( ( ret = ssl_start_renegotiation( ssl ) ) != 0 )
+                {
+                    SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret );
+                    return( ret );
+                }
+
+                return( POLARSSL_ERR_NET_WANT_READ );
+            }
+        }
+        else if( ssl->renegotiation == SSL_RENEGOTIATION_PENDING )
+        {
+            SSL_DEBUG_MSG( 1, ( "renegotiation requested, "
+                                "but not honored by client" ) );
+            return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+        }
+        else if( ssl->in_msgtype != SSL_MSG_APPLICATION_DATA )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad application data message" ) );
+            return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+        }
+
+        ssl->in_offt = ssl->in_msg;
+    }
+
+    n = ( len < ssl->in_msglen )
+        ? len : ssl->in_msglen;
+
+    memcpy( buf, ssl->in_offt, n );
+    ssl->in_msglen -= n;
+
+    if( ssl->in_msglen == 0 )
+        /* all bytes consumed  */
+        ssl->in_offt = NULL;
+    else
+        /* more data available */
+        ssl->in_offt += n;
+
+    SSL_DEBUG_MSG( 2, ( "<= read" ) );
+
+    return( (int) n );
+}
+
+/*
+ * Send application data to be encrypted by the SSL layer
+ */
+int ssl_write( ssl_context *ssl, const unsigned char *buf, size_t len )
+{
+    int ret;
+    size_t n;
+    unsigned int max_len = SSL_MAX_CONTENT_LEN;
+
+    SSL_DEBUG_MSG( 2, ( "=> write" ) );
+
+    if( ssl->state != SSL_HANDSHAKE_OVER )
+    {
+        if( ( ret = ssl_handshake( ssl ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_handshake", ret );
+            return( ret );
+        }
+    }
+
+#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH)
+    /*
+     * Assume mfl_code is correct since it was checked when set
+     */
+    max_len = mfl_code_to_length[ssl->mfl_code];
+
+    /*
+     * Check if a smaller max length was negotiated
+     */
+    if( ssl->session_out != NULL &&
+        mfl_code_to_length[ssl->session_out->mfl_code] < max_len )
+    {
+        max_len = mfl_code_to_length[ssl->session_out->mfl_code];
+    }
+#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */
+
+    n = ( len < max_len) ? len : max_len;
+
+    if( ssl->out_left != 0 )
+    {
+        if( ( ret = ssl_flush_output( ssl ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_flush_output", ret );
+            return( ret );
+        }
+    }
+    else
+    {
+        ssl->out_msglen  = n;
+        ssl->out_msgtype = SSL_MSG_APPLICATION_DATA;
+        memcpy( ssl->out_msg, buf, n );
+
+        if( ( ret = ssl_write_record( ssl ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+            return( ret );
+        }
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= write" ) );
+
+    return( (int) n );
+}
+
+/*
+ * Notify the peer that the connection is being closed
+ */
+int ssl_close_notify( ssl_context *ssl )
+{
+    int ret;
+
+    SSL_DEBUG_MSG( 2, ( "=> write close notify" ) );
+
+    if( ( ret = ssl_flush_output( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_flush_output", ret );
+        return( ret );
+    }
+
+    if( ssl->state == SSL_HANDSHAKE_OVER )
+    {
+        if( ( ret = ssl_send_alert_message( ssl,
+                        SSL_ALERT_LEVEL_WARNING,
+                        SSL_ALERT_MSG_CLOSE_NOTIFY ) ) != 0 )
+        {
+            return( ret );
+        }
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= write close notify" ) );
+
+    return( ret );
+}
+
+void ssl_transform_free( ssl_transform *transform )
+{
+#if defined(POLARSSL_ZLIB_SUPPORT)
+    deflateEnd( &transform->ctx_deflate );
+    inflateEnd( &transform->ctx_inflate );
+#endif
+
+    cipher_free_ctx( &transform->cipher_ctx_enc );
+    cipher_free_ctx( &transform->cipher_ctx_dec );
+
+    md_free_ctx( &transform->md_ctx_enc );
+    md_free_ctx( &transform->md_ctx_dec );
+
+    memset( transform, 0, sizeof( ssl_transform ) );
+}
+
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+static void ssl_key_cert_free( ssl_key_cert *key_cert )
+{
+    ssl_key_cert *cur = key_cert, *next;
+
+    while( cur != NULL )
+    {
+        next = cur->next;
+
+        if( cur->key_own_alloc )
+        {
+            pk_free( cur->key );
+            polarssl_free( cur->key );
+        }
+        polarssl_free( cur );
+
+        cur = next;
+    }
+}
+#endif /* POLARSSL_X509_CRT_PARSE_C */
+
+void ssl_handshake_free( ssl_handshake_params *handshake )
+{
+#if defined(POLARSSL_DHM_C)
+    dhm_free( &handshake->dhm_ctx );
+#endif
+#if defined(POLARSSL_ECDH_C)
+    ecdh_free( &handshake->ecdh_ctx );
+#endif
+
+#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C)
+    /* explicit void pointer cast for buggy MS compiler */
+    polarssl_free( (void *) handshake->curves );
+#endif
+
+#if defined(POLARSSL_X509_CRT_PARSE_C) && \
+    defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
+    /*
+     * Free only the linked list wrapper, not the keys themselves
+     * since the belong to the SNI callback
+     */
+    if( handshake->sni_key_cert != NULL )
+    {
+        ssl_key_cert *cur = handshake->sni_key_cert, *next;
+
+        while( cur != NULL )
+        {
+            next = cur->next;
+            polarssl_free( cur );
+            cur = next;
+        }
+    }
+#endif /* POLARSSL_X509_CRT_PARSE_C && POLARSSL_SSL_SERVER_NAME_INDICATION */
+
+    memset( handshake, 0, sizeof( ssl_handshake_params ) );
+}
+
+void ssl_session_free( ssl_session *session )
+{
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+    if( session->peer_cert != NULL )
+    {
+        x509_crt_free( session->peer_cert );
+        polarssl_free( session->peer_cert );
+    }
+#endif
+
+#if defined(POLARSSL_SSL_SESSION_TICKETS)
+    polarssl_free( session->ticket );
+#endif
+
+    memset( session, 0, sizeof( ssl_session ) );
+}
+
+/*
+ * Free an SSL context
+ */
+void ssl_free( ssl_context *ssl )
+{
+    SSL_DEBUG_MSG( 2, ( "=> free" ) );
+
+    if( ssl->out_ctr != NULL )
+    {
+        memset( ssl->out_ctr, 0, SSL_BUFFER_LEN );
+        polarssl_free( ssl->out_ctr );
+    }
+
+    if( ssl->in_ctr != NULL )
+    {
+        memset( ssl->in_ctr, 0, SSL_BUFFER_LEN );
+        polarssl_free( ssl->in_ctr );
+    }
+
+#if defined(POLARSSL_ZLIB_SUPPORT)
+    if( ssl->compress_buf != NULL )
+    {
+        memset( ssl->compress_buf, 0, SSL_BUFFER_LEN );
+        polarssl_free( ssl->compress_buf );
+    }
+#endif
+
+#if defined(POLARSSL_DHM_C)
+    mpi_free( &ssl->dhm_P );
+    mpi_free( &ssl->dhm_G );
+#endif
+
+    if( ssl->transform )
+    {
+        ssl_transform_free( ssl->transform );
+        polarssl_free( ssl->transform );
+    }
+
+    if( ssl->handshake )
+    {
+        ssl_handshake_free( ssl->handshake );
+        ssl_transform_free( ssl->transform_negotiate );
+        ssl_session_free( ssl->session_negotiate );
+
+        polarssl_free( ssl->handshake );
+        polarssl_free( ssl->transform_negotiate );
+        polarssl_free( ssl->session_negotiate );
+    }
+
+    if( ssl->session )
+    {
+        ssl_session_free( ssl->session );
+        polarssl_free( ssl->session );
+    }
+
+#if defined(POLARSSL_SSL_SESSION_TICKETS)
+    polarssl_free( ssl->ticket_keys );
+#endif
+
+#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
+    if ( ssl->hostname != NULL )
+    {
+        memset( ssl->hostname, 0, ssl->hostname_len );
+        polarssl_free( ssl->hostname );
+        ssl->hostname_len = 0;
+    }
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
+    if( ssl->psk != NULL )
+    {
+        memset( ssl->psk, 0, ssl->psk_len );
+        memset( ssl->psk_identity, 0, ssl->psk_identity_len );
+        polarssl_free( ssl->psk );
+        polarssl_free( ssl->psk_identity );
+        ssl->psk_len = 0;
+        ssl->psk_identity_len = 0;
+    }
+#endif
+
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+    ssl_key_cert_free( ssl->key_cert );
+#endif
+
+#if defined(POLARSSL_SSL_HW_RECORD_ACCEL)
+    if( ssl_hw_record_finish != NULL )
+    {
+        SSL_DEBUG_MSG( 2, ( "going for ssl_hw_record_finish()" ) );
+        ssl_hw_record_finish( ssl );
+    }
+#endif
+
+    SSL_DEBUG_MSG( 2, ( "<= free" ) );
+
+    /* Actually clear after last debug message */
+    memset( ssl, 0, sizeof( ssl_context ) );
+}
+
+#if defined(POLARSSL_PK_C)
+/*
+ * Convert between POLARSSL_PK_XXX and SSL_SIG_XXX
+ */
+unsigned char ssl_sig_from_pk( pk_context *pk )
+{
+#if defined(POLARSSL_RSA_C)
+    if( pk_can_do( pk, POLARSSL_PK_RSA ) )
+        return( SSL_SIG_RSA );
+#endif
+#if defined(POLARSSL_ECDSA_C)
+    if( pk_can_do( pk, POLARSSL_PK_ECDSA ) )
+        return( SSL_SIG_ECDSA );
+#endif
+    return( SSL_SIG_ANON );
+}
+
+pk_type_t ssl_pk_alg_from_sig( unsigned char sig )
+{
+    switch( sig )
+    {
+#if defined(POLARSSL_RSA_C)
+        case SSL_SIG_RSA:
+            return( POLARSSL_PK_RSA );
+#endif
+#if defined(POLARSSL_ECDSA_C)
+        case SSL_SIG_ECDSA:
+            return( POLARSSL_PK_ECDSA );
+#endif
+        default:
+            return( POLARSSL_PK_NONE );
+    }
+}
+#endif /* POLARSSL_PK_C */
+
+/*
+ * Convert between SSL_HASH_XXX and POLARSSL_MD_XXX
+ */
+md_type_t ssl_md_alg_from_hash( unsigned char hash )
+{
+    switch( hash )
+    {
+#if defined(POLARSSL_MD5_C)
+        case SSL_HASH_MD5:
+            return( POLARSSL_MD_MD5 );
+#endif
+#if defined(POLARSSL_SHA1_C)
+        case SSL_HASH_SHA1:
+            return( POLARSSL_MD_SHA1 );
+#endif
+#if defined(POLARSSL_SHA256_C)
+        case SSL_HASH_SHA224:
+            return( POLARSSL_MD_SHA224 );
+        case SSL_HASH_SHA256:
+            return( POLARSSL_MD_SHA256 );
+#endif
+#if defined(POLARSSL_SHA512_C)
+        case SSL_HASH_SHA384:
+            return( POLARSSL_MD_SHA384 );
+        case SSL_HASH_SHA512:
+            return( POLARSSL_MD_SHA512 );
+#endif
+        default:
+            return( POLARSSL_MD_NONE );
+    }
+}
+
+#if defined(POLARSSL_SSL_SET_CURVES)
+/*
+ * Check is a curve proposed by the peer is in our list.
+ * Return 1 if we're willing to use it, 0 otherwise.
+ */
+int ssl_curve_is_acceptable( const ssl_context *ssl, ecp_group_id grp_id )
+{
+    const ecp_group_id *gid;
+
+    for( gid = ssl->curve_list; *gid != POLARSSL_ECP_DP_NONE; gid++ )
+        if( *gid == grp_id )
+            return( 1 );
+
+    return( 0 );
+}
+#endif /* POLARSSL_SSL_SET_CURVES */
+
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+int ssl_check_cert_usage( const x509_crt *cert,
+                          const ssl_ciphersuite_t *ciphersuite,
+                          int cert_endpoint )
+{
+#if defined(POLARSSL_X509_CHECK_KEY_USAGE)
+    int usage = 0;
+#endif
+#if defined(POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE)
+    const char *ext_oid;
+    size_t ext_len;
+#endif
+
+#if !defined(POLARSSL_X509_CHECK_KEY_USAGE) &&          \
+    !defined(POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE)
+    ((void) cert);
+    ((void) cert_endpoint);
+#endif
+
+#if defined(POLARSSL_X509_CHECK_KEY_USAGE)
+    if( cert_endpoint == SSL_IS_SERVER )
+    {
+        /* Server part of the key exchange */
+        switch( ciphersuite->key_exchange )
+        {
+            case POLARSSL_KEY_EXCHANGE_RSA:
+            case POLARSSL_KEY_EXCHANGE_RSA_PSK:
+                usage = KU_KEY_ENCIPHERMENT;
+                break;
+
+            case POLARSSL_KEY_EXCHANGE_DHE_RSA:
+            case POLARSSL_KEY_EXCHANGE_ECDHE_RSA:
+            case POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA:
+                usage = KU_DIGITAL_SIGNATURE;
+                break;
+
+            case POLARSSL_KEY_EXCHANGE_ECDH_RSA:
+            case POLARSSL_KEY_EXCHANGE_ECDH_ECDSA:
+                usage = KU_KEY_AGREEMENT;
+                break;
+
+            /* Don't use default: we want warnings when adding new values */
+            case POLARSSL_KEY_EXCHANGE_NONE:
+            case POLARSSL_KEY_EXCHANGE_PSK:
+            case POLARSSL_KEY_EXCHANGE_DHE_PSK:
+            case POLARSSL_KEY_EXCHANGE_ECDHE_PSK:
+                usage = 0;
+        }
+    }
+    else
+    {
+        /* Client auth: we only implement rsa_sign and ecdsa_sign for now */
+        usage = KU_DIGITAL_SIGNATURE;
+    }
+
+    if( x509_crt_check_key_usage( cert, usage ) != 0 )
+        return( -1 );
+#else
+    ((void) ciphersuite);
+#endif /* POLARSSL_X509_CHECK_KEY_USAGE */
+
+#if defined(POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE)
+    if( cert_endpoint == SSL_IS_SERVER )
+    {
+        ext_oid = OID_SERVER_AUTH;
+        ext_len = OID_SIZE( OID_SERVER_AUTH );
+    }
+    else
+    {
+        ext_oid = OID_CLIENT_AUTH;
+        ext_len = OID_SIZE( OID_CLIENT_AUTH );
+    }
+
+    if( x509_crt_check_extended_key_usage( cert, ext_oid, ext_len ) != 0 )
+        return( -1 );
+#endif /* POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE */
+
+    return( 0 );
+}
+#endif /* POLARSSL_X509_CRT_PARSE_C */
+
+#endif /* POLARSSL_SSL_TLS_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/threading.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,115 @@
+/*
+ *  Threading abstraction layer
+ *
+ *  Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_THREADING_C)
+
+#include "polarssl/threading.h"
+
+#if defined(POLARSSL_THREADING_PTHREAD)
+static int threading_mutex_init_pthread( threading_mutex_t *mutex )
+{
+    if( mutex == NULL )
+        return( POLARSSL_ERR_THREADING_BAD_INPUT_DATA );
+
+    if( pthread_mutex_init( mutex, NULL ) != 0 )
+        return( POLARSSL_ERR_THREADING_MUTEX_ERROR );
+
+    return( 0 );
+}
+
+static int threading_mutex_free_pthread( threading_mutex_t *mutex )
+{
+    if( mutex == NULL )
+        return( POLARSSL_ERR_THREADING_BAD_INPUT_DATA );
+
+    if( pthread_mutex_destroy( mutex ) != 0 )
+        return( POLARSSL_ERR_THREADING_MUTEX_ERROR );
+
+    return( 0 );
+}
+
+static int threading_mutex_lock_pthread( threading_mutex_t *mutex )
+{
+    if( mutex == NULL )
+        return( POLARSSL_ERR_THREADING_BAD_INPUT_DATA );
+
+    if( pthread_mutex_lock( mutex ) != 0 )
+        return( POLARSSL_ERR_THREADING_MUTEX_ERROR );
+
+    return( 0 );
+}
+
+static int threading_mutex_unlock_pthread( threading_mutex_t *mutex )
+{
+    if( mutex == NULL )
+        return( POLARSSL_ERR_THREADING_BAD_INPUT_DATA );
+
+    if( pthread_mutex_unlock( mutex ) != 0 )
+        return( POLARSSL_ERR_THREADING_MUTEX_ERROR );
+
+    return( 0 );
+}
+
+int (*polarssl_mutex_init)( threading_mutex_t * ) = threading_mutex_init_pthread;
+int (*polarssl_mutex_free)( threading_mutex_t * ) = threading_mutex_free_pthread;
+int (*polarssl_mutex_lock)( threading_mutex_t * ) = threading_mutex_lock_pthread;
+int (*polarssl_mutex_unlock)( threading_mutex_t * ) = threading_mutex_unlock_pthread;
+#endif /* POLARSSL_THREADING_PTHREAD */
+
+#if defined(POLARSSL_THREADING_ALT)
+static int threading_mutex_fail( threading_mutex_t *mutex )
+{
+    ((void) mutex );
+    return( POLARSSL_ERR_THREADING_BAD_INPUT_DATA );
+}
+
+int (*polarssl_mutex_init)( threading_mutex_t * ) = threading_mutex_fail;
+int (*polarssl_mutex_free)( threading_mutex_t * ) = threading_mutex_fail;
+int (*polarssl_mutex_lock)( threading_mutex_t * ) = threading_mutex_fail;
+int (*polarssl_mutex_unlock)( threading_mutex_t * ) = threading_mutex_fail;
+
+int threading_set_alt( int (*mutex_init)( threading_mutex_t * ),
+                       int (*mutex_free)( threading_mutex_t * ),
+                       int (*mutex_lock)( threading_mutex_t * ),
+                       int (*mutex_unlock)( threading_mutex_t * ) )
+{
+    polarssl_mutex_init = mutex_init;
+    polarssl_mutex_free = mutex_free;
+    polarssl_mutex_lock = mutex_lock;
+    polarssl_mutex_unlock = mutex_unlock;
+
+    return( 0 );
+}
+#endif /* POLARSSL_THREADING_ALT_C */
+
+#endif /* POLARSSL_THREADING_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/timing.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,481 @@
+/*
+ *  Portable interface to the CPU cycle counter
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdio.h>
+#define polarssl_printf     printf
+#endif
+
+#if defined(POLARSSL_TIMING_C) && !defined(POLARSSL_TIMING_ALT)
+
+#include "polarssl/timing.h"
+
+#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
+
+#include <windows.h>
+#include <winbase.h>
+
+struct _hr_time
+{
+    LARGE_INTEGER start;
+};
+
+#else
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <time.h>
+
+struct _hr_time
+{
+    struct timeval start;
+};
+
+#endif /* _WIN32 && !EFIX64 && !EFI32 */
+
+#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) &&  \
+    (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
+
+#define POLARSSL_HAVE_HARDCLOCK
+
+unsigned long hardclock( void )
+{
+    unsigned long tsc;
+    __asm   rdtsc
+    __asm   mov  [tsc], eax
+    return( tsc );
+}
+#endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM &&
+          ( _MSC_VER && _M_IX86 ) || __WATCOMC__ */
+
+#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) &&  \
+    defined(__GNUC__) && defined(__i386__)
+
+#define POLARSSL_HAVE_HARDCLOCK
+
+unsigned long hardclock( void )
+{
+    unsigned long lo, hi;
+    asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) );
+    return( lo );
+}
+#endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM &&
+          __GNUC__ && __i386__ */
+
+#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) &&  \
+    defined(__GNUC__) && (defined(__amd64__) || defined(__x86_64__))
+
+#define POLARSSL_HAVE_HARDCLOCK
+
+unsigned long hardclock( void )
+{
+    unsigned long lo, hi;
+    asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) );
+    return( lo | (hi << 32) );
+}
+#endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM &&
+          __GNUC__ && ( __amd64__ || __x86_64__ ) */
+
+#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) &&  \
+    defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__))
+
+#define POLARSSL_HAVE_HARDCLOCK
+
+unsigned long hardclock( void )
+{
+    unsigned long tbl, tbu0, tbu1;
+
+    do
+    {
+        asm volatile( "mftbu %0" : "=r" (tbu0) );
+        asm volatile( "mftb  %0" : "=r" (tbl ) );
+        asm volatile( "mftbu %0" : "=r" (tbu1) );
+    }
+    while( tbu0 != tbu1 );
+
+    return( tbl );
+}
+#endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM &&
+          __GNUC__ && ( __powerpc__ || __ppc__ ) */
+
+#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) &&  \
+    defined(__GNUC__) && defined(__sparc64__)
+
+#if defined(__OpenBSD__)
+#warning OpenBSD does not allow access to tick register using software version instead
+#else
+#define POLARSSL_HAVE_HARDCLOCK
+
+unsigned long hardclock( void )
+{
+    unsigned long tick;
+    asm volatile( "rdpr %%tick, %0;" : "=&r" (tick) );
+    return( tick );
+}
+#endif /* __OpenBSD__ */
+#endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM &&
+          __GNUC__ && __sparc64__ */
+
+#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) &&  \
+    defined(__GNUC__) && defined(__sparc__) && !defined(__sparc64__)
+
+#define POLARSSL_HAVE_HARDCLOCK
+
+unsigned long hardclock( void )
+{
+    unsigned long tick;
+    asm volatile( ".byte 0x83, 0x41, 0x00, 0x00" );
+    asm volatile( "mov   %%g1, %0" : "=r" (tick) );
+    return( tick );
+}
+#endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM &&
+          __GNUC__ && __sparc__ && !__sparc64__ */
+
+#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) &&      \
+    defined(__GNUC__) && defined(__alpha__)
+
+#define POLARSSL_HAVE_HARDCLOCK
+
+unsigned long hardclock( void )
+{
+    unsigned long cc;
+    asm volatile( "rpcc %0" : "=r" (cc) );
+    return( cc & 0xFFFFFFFF );
+}
+#endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM &&
+          __GNUC__ && __alpha__ */
+
+#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) &&      \
+    defined(__GNUC__) && defined(__ia64__)
+
+#define POLARSSL_HAVE_HARDCLOCK
+
+unsigned long hardclock( void )
+{
+    unsigned long itc;
+    asm volatile( "mov %0 = ar.itc" : "=r" (itc) );
+    return( itc );
+}
+#endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM &&
+          __GNUC__ && __ia64__ */
+
+#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(_MSC_VER) && \
+    !defined(EFIX64) && !defined(EFI32)
+
+#define POLARSSL_HAVE_HARDCLOCK
+
+unsigned long hardclock( void )
+{
+    LARGE_INTEGER offset;
+
+    QueryPerformanceCounter( &offset );
+
+    return (unsigned long)( offset.QuadPart );
+}
+#endif /* !POLARSSL_HAVE_HARDCLOCK && _MSC_VER && !EFIX64 && !EFI32 */
+
+#if !defined(POLARSSL_HAVE_HARDCLOCK)
+
+#define POLARSSL_HAVE_HARDCLOCK
+
+static int hardclock_init = 0;
+static struct timeval tv_init;
+
+unsigned long hardclock( void )
+{
+    struct timeval tv_cur;
+
+    if( hardclock_init == 0 )
+    {
+        gettimeofday( &tv_init, NULL );
+        hardclock_init = 1;
+    }
+
+    gettimeofday( &tv_cur, NULL );
+    return( ( tv_cur.tv_sec  - tv_init.tv_sec  ) * 1000000
+          + ( tv_cur.tv_usec - tv_init.tv_usec ) );
+}
+#endif /* !POLARSSL_HAVE_HARDCLOCK */
+
+volatile int alarmed = 0;
+
+#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
+
+unsigned long get_timer( struct hr_time *val, int reset )
+{
+    unsigned long delta;
+    LARGE_INTEGER offset, hfreq;
+    struct _hr_time *t = (struct _hr_time *) val;
+
+    QueryPerformanceCounter(  &offset );
+    QueryPerformanceFrequency( &hfreq );
+
+    delta = (unsigned long)( ( 1000 *
+        ( offset.QuadPart - t->start.QuadPart ) ) /
+           hfreq.QuadPart );
+
+    if( reset )
+        QueryPerformanceCounter( &t->start );
+
+    return( delta );
+}
+
+DWORD WINAPI TimerProc( LPVOID uElapse )
+{
+    Sleep( (DWORD) uElapse );
+    alarmed = 1;
+    return( TRUE );
+}
+
+void set_alarm( int seconds )
+{
+    DWORD ThreadId;
+
+    alarmed = 0;
+    CloseHandle( CreateThread( NULL, 0, TimerProc,
+        (LPVOID) ( seconds * 1000 ), 0, &ThreadId ) );
+}
+
+void m_sleep( int milliseconds )
+{
+    Sleep( milliseconds );
+}
+
+#else /* _WIN32 && !EFIX64 && !EFI32 */
+
+unsigned long get_timer( struct hr_time *val, int reset )
+{
+    unsigned long delta;
+    struct timeval offset;
+    struct _hr_time *t = (struct _hr_time *) val;
+
+    gettimeofday( &offset, NULL );
+
+    delta = ( offset.tv_sec  - t->start.tv_sec  ) * 1000
+          + ( offset.tv_usec - t->start.tv_usec ) / 1000;
+
+    if( reset )
+    {
+        t->start.tv_sec  = offset.tv_sec;
+        t->start.tv_usec = offset.tv_usec;
+    }
+
+    return( delta );
+}
+
+#if defined(INTEGRITY)
+void m_sleep( int milliseconds )
+{
+    usleep( milliseconds * 1000 );
+}
+
+#else /* INTEGRITY */
+
+static void sighandler( int signum )
+{
+    alarmed = 1;
+    signal( signum, sighandler );
+}
+
+void set_alarm( int seconds )
+{
+    alarmed = 0;
+    signal( SIGALRM, sighandler );
+    alarm( seconds );
+}
+
+void m_sleep( int milliseconds )
+{
+    struct timeval tv;
+
+    tv.tv_sec  = milliseconds / 1000;
+    tv.tv_usec = ( milliseconds % 1000 ) * 1000;
+
+    select( 0, NULL, NULL, NULL, &tv );
+}
+#endif /* INTEGRITY */
+
+#endif /* _WIN32 && !EFIX64 && !EFI32 */
+
+#if defined(POLARSSL_SELF_TEST)
+
+/* To test net_usleep against our functions */
+#if defined(POLARSSL_NET_C)
+#include "polarssl/net.h"
+#endif
+
+/*
+ * Checkup routine
+ *
+ * Warning: this is work in progress, some tests may not be reliable enough
+ * yet! False positives may happen.
+ */
+int timing_self_test( int verbose )
+{
+    unsigned long cycles, ratio;
+    unsigned long millisecs, secs;
+    int hardfail;
+    struct hr_time hires;
+
+    if( verbose != 0)
+        polarssl_printf( "  TIMING tests warning: will take some time!\n" );
+
+    if( verbose != 0 )
+        polarssl_printf( "  TIMING test #1 (m_sleep   / get_timer): " );
+
+    for( secs = 1; secs <= 3; secs++ )
+    {
+        (void) get_timer( &hires, 1 );
+
+        m_sleep( 500 * secs );
+
+        millisecs = get_timer( &hires, 0 );
+
+        if( millisecs < 450 * secs || millisecs > 550 * secs )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed\n" );
+
+            return( 1 );
+        }
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n" );
+
+    if( verbose != 0 )
+        polarssl_printf( "  TIMING test #2 (set_alarm / get_timer): " );
+
+    for( secs = 1; secs <= 3; secs++ )
+    {
+        (void) get_timer( &hires, 1 );
+
+        set_alarm( secs );
+        while( !alarmed )
+            ;
+
+        millisecs = get_timer( &hires, 0 );
+
+        if( millisecs < 900 * secs || millisecs > 1100 * secs )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed\n" );
+
+            return( 1 );
+        }
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n" );
+
+    if( verbose != 0 )
+        polarssl_printf( "  TIMING test #3 (hardclock / m_sleep  ): " );
+
+    /*
+     * Allow one failure for possible counter wrapping.
+     * On a 4Ghz 32-bit machine the cycle counter wraps about once per second;
+     * since the whole test is about 10ms, it shouldn't happen twice in a row.
+     */
+    hardfail = 0;
+
+hard_test:
+    if( hardfail > 1 )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "failed\n" );
+
+        return( 1 );
+    }
+
+    /* Get a reference ratio cycles/ms */
+    cycles = hardclock();
+    m_sleep( 1 );
+    cycles = hardclock() - cycles;
+    ratio = cycles / 1;
+
+    for( millisecs = 2; millisecs <= 4; millisecs++ )
+    {
+        cycles = hardclock();
+        m_sleep( millisecs );
+        cycles = hardclock() - cycles;
+
+        /* Allow variation up to 20% */
+        if( cycles / millisecs < ratio - ratio / 5 ||
+            cycles / millisecs > ratio + ratio / 5 )
+        {
+            hardfail++;
+            goto hard_test;
+        }
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n" );
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+#if defined(POLARSSL_NET_C)
+    if( verbose != 0 )
+        polarssl_printf( "  TIMING test #4 (net_usleep/ get_timer): " );
+
+    for( secs = 1; secs <= 3; secs++ )
+    {
+        (void) get_timer( &hires, 1 );
+
+        net_usleep( 500000 * secs );
+
+        millisecs = get_timer( &hires, 0 );
+
+        if( millisecs < 450 * secs || millisecs > 550 * secs )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed\n" );
+
+            return( 1 );
+        }
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n" );
+#endif /* POLARSSL_NET_C */
+
+    return( 0 );
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_TIMING_C && !POLARSSL_TIMING_ALT */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/version.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,58 @@
+/*
+ *  Version information
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_VERSION_C)
+
+#include "polarssl/version.h"
+#include <string.h>
+
+const char version[] = POLARSSL_VERSION_STRING;
+
+unsigned int version_get_number()
+{
+    return POLARSSL_VERSION_NUMBER;
+}
+
+void version_get_string( char *string )
+{
+    memcpy( string, POLARSSL_VERSION_STRING,
+            sizeof( POLARSSL_VERSION_STRING ) );
+}
+
+void version_get_string_full( char *string )
+{
+    memcpy( string, POLARSSL_VERSION_STRING_FULL,
+            sizeof( POLARSSL_VERSION_STRING_FULL ) );
+}
+
+#endif /* POLARSSL_VERSION_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/version_features.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,553 @@
+/*
+ *  Version feature information
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_VERSION_C)
+
+#include "polarssl/version.h"
+
+#include <string.h>
+
+#if defined(_MSC_VER) && !defined strcasecmp && !defined(EFIX64) && \
+    !defined(EFI32)
+#define strcasecmp _stricmp
+#endif
+
+const char *features[] = {
+#if defined(POLARSSL_VERSION_FEATURES)
+#if defined(POLARSSL_HAVE_INT8)
+    "POLARSSL_HAVE_INT8",
+#endif /* POLARSSL_HAVE_INT8 */
+#if defined(POLARSSL_HAVE_INT16)
+    "POLARSSL_HAVE_INT16",
+#endif /* POLARSSL_HAVE_INT16 */
+#if defined(POLARSSL_HAVE_LONGLONG)
+    "POLARSSL_HAVE_LONGLONG",
+#endif /* POLARSSL_HAVE_LONGLONG */
+#if defined(POLARSSL_HAVE_ASM)
+    "POLARSSL_HAVE_ASM",
+#endif /* POLARSSL_HAVE_ASM */
+#if defined(POLARSSL_HAVE_SSE2)
+    "POLARSSL_HAVE_SSE2",
+#endif /* POLARSSL_HAVE_SSE2 */
+#if defined(POLARSSL_HAVE_TIME)
+    "POLARSSL_HAVE_TIME",
+#endif /* POLARSSL_HAVE_TIME */
+#if defined(POLARSSL_HAVE_IPV6)
+    "POLARSSL_HAVE_IPV6",
+#endif /* POLARSSL_HAVE_IPV6 */
+#if defined(POLARSSL_PLATFORM_MEMORY)
+    "POLARSSL_PLATFORM_MEMORY",
+#endif /* POLARSSL_PLATFORM_MEMORY */
+#if defined(POLARSSL_PLATFORM_NO_STD_FUNCTIONS)
+    "POLARSSL_PLATFORM_NO_STD_FUNCTIONS",
+#endif /* POLARSSL_PLATFORM_NO_STD_FUNCTIONS */
+#if defined(POLARSSL_PLATFORM_PRINTF_ALT)
+    "POLARSSL_PLATFORM_PRINTF_ALT",
+#endif /* POLARSSL_PLATFORM_PRINTF_ALT */
+#if defined(POLARSSL_PLATFORM_FPRINTF_ALT)
+    "POLARSSL_PLATFORM_FPRINTF_ALT",
+#endif /* POLARSSL_PLATFORM_FPRINTF_ALT */
+#if defined(POLARSSL_TIMING_ALT)
+    "POLARSSL_TIMING_ALT",
+#endif /* POLARSSL_TIMING_ALT */
+#if defined(POLARSSL_AES_ALT)
+    "POLARSSL_AES_ALT",
+#endif /* POLARSSL_AES_ALT */
+#if defined(POLARSSL_ARC4_ALT)
+    "POLARSSL_ARC4_ALT",
+#endif /* POLARSSL_ARC4_ALT */
+#if defined(POLARSSL_BLOWFISH_ALT)
+    "POLARSSL_BLOWFISH_ALT",
+#endif /* POLARSSL_BLOWFISH_ALT */
+#if defined(POLARSSL_CAMELLIA_ALT)
+    "POLARSSL_CAMELLIA_ALT",
+#endif /* POLARSSL_CAMELLIA_ALT */
+#if defined(POLARSSL_DES_ALT)
+    "POLARSSL_DES_ALT",
+#endif /* POLARSSL_DES_ALT */
+#if defined(POLARSSL_XTEA_ALT)
+    "POLARSSL_XTEA_ALT",
+#endif /* POLARSSL_XTEA_ALT */
+#if defined(POLARSSL_MD2_ALT)
+    "POLARSSL_MD2_ALT",
+#endif /* POLARSSL_MD2_ALT */
+#if defined(POLARSSL_MD4_ALT)
+    "POLARSSL_MD4_ALT",
+#endif /* POLARSSL_MD4_ALT */
+#if defined(POLARSSL_MD5_ALT)
+    "POLARSSL_MD5_ALT",
+#endif /* POLARSSL_MD5_ALT */
+#if defined(POLARSSL_RIPEMD160_ALT)
+    "POLARSSL_RIPEMD160_ALT",
+#endif /* POLARSSL_RIPEMD160_ALT */
+#if defined(POLARSSL_SHA1_ALT)
+    "POLARSSL_SHA1_ALT",
+#endif /* POLARSSL_SHA1_ALT */
+#if defined(POLARSSL_SHA256_ALT)
+    "POLARSSL_SHA256_ALT",
+#endif /* POLARSSL_SHA256_ALT */
+#if defined(POLARSSL_SHA512_ALT)
+    "POLARSSL_SHA512_ALT",
+#endif /* POLARSSL_SHA512_ALT */
+#if defined(POLARSSL_AES_ROM_TABLES)
+    "POLARSSL_AES_ROM_TABLES",
+#endif /* POLARSSL_AES_ROM_TABLES */
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    "POLARSSL_CIPHER_MODE_CBC",
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+    "POLARSSL_CIPHER_MODE_CFB",
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+    "POLARSSL_CIPHER_MODE_CTR",
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+    "POLARSSL_CIPHER_NULL_CIPHER",
+#endif /* POLARSSL_CIPHER_NULL_CIPHER */
+#if defined(POLARSSL_CIPHER_PADDING_PKCS7)
+    "POLARSSL_CIPHER_PADDING_PKCS7",
+#endif /* POLARSSL_CIPHER_PADDING_PKCS7 */
+#if defined(POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS)
+    "POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS",
+#endif /* POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS */
+#if defined(POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN)
+    "POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN",
+#endif /* POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN */
+#if defined(POLARSSL_CIPHER_PADDING_ZEROS)
+    "POLARSSL_CIPHER_PADDING_ZEROS",
+#endif /* POLARSSL_CIPHER_PADDING_ZEROS */
+#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES)
+    "POLARSSL_ENABLE_WEAK_CIPHERSUITES",
+#endif /* POLARSSL_ENABLE_WEAK_CIPHERSUITES */
+#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED)
+    "POLARSSL_ECP_DP_SECP192R1_ENABLED",
+#endif /* POLARSSL_ECP_DP_SECP192R1_ENABLED */
+#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED)
+    "POLARSSL_ECP_DP_SECP224R1_ENABLED",
+#endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED */
+#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED)
+    "POLARSSL_ECP_DP_SECP256R1_ENABLED",
+#endif /* POLARSSL_ECP_DP_SECP256R1_ENABLED */
+#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED)
+    "POLARSSL_ECP_DP_SECP384R1_ENABLED",
+#endif /* POLARSSL_ECP_DP_SECP384R1_ENABLED */
+#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED)
+    "POLARSSL_ECP_DP_SECP521R1_ENABLED",
+#endif /* POLARSSL_ECP_DP_SECP521R1_ENABLED */
+#if defined(POLARSSL_ECP_DP_SECP192K1_ENABLED)
+    "POLARSSL_ECP_DP_SECP192K1_ENABLED",
+#endif /* POLARSSL_ECP_DP_SECP192K1_ENABLED */
+#if defined(POLARSSL_ECP_DP_SECP224K1_ENABLED)
+    "POLARSSL_ECP_DP_SECP224K1_ENABLED",
+#endif /* POLARSSL_ECP_DP_SECP224K1_ENABLED */
+#if defined(POLARSSL_ECP_DP_SECP256K1_ENABLED)
+    "POLARSSL_ECP_DP_SECP256K1_ENABLED",
+#endif /* POLARSSL_ECP_DP_SECP256K1_ENABLED */
+#if defined(POLARSSL_ECP_DP_BP256R1_ENABLED)
+    "POLARSSL_ECP_DP_BP256R1_ENABLED",
+#endif /* POLARSSL_ECP_DP_BP256R1_ENABLED */
+#if defined(POLARSSL_ECP_DP_BP384R1_ENABLED)
+    "POLARSSL_ECP_DP_BP384R1_ENABLED",
+#endif /* POLARSSL_ECP_DP_BP384R1_ENABLED */
+#if defined(POLARSSL_ECP_DP_BP512R1_ENABLED)
+    "POLARSSL_ECP_DP_BP512R1_ENABLED",
+#endif /* POLARSSL_ECP_DP_BP512R1_ENABLED */
+#if defined(POLARSSL_ECP_DP_M221_ENABLED)
+    "POLARSSL_ECP_DP_M221_ENABLED",
+#endif /* POLARSSL_ECP_DP_M221_ENABLED */
+#if defined(POLARSSL_ECP_DP_M255_ENABLED)
+    "POLARSSL_ECP_DP_M255_ENABLED",
+#endif /* POLARSSL_ECP_DP_M255_ENABLED */
+#if defined(POLARSSL_ECP_DP_M383_ENABLED)
+    "POLARSSL_ECP_DP_M383_ENABLED",
+#endif /* POLARSSL_ECP_DP_M383_ENABLED */
+#if defined(POLARSSL_ECP_DP_M511_ENABLED)
+    "POLARSSL_ECP_DP_M511_ENABLED",
+#endif /* POLARSSL_ECP_DP_M511_ENABLED */
+#if defined(POLARSSL_ECP_NIST_OPTIM)
+    "POLARSSL_ECP_NIST_OPTIM",
+#endif /* POLARSSL_ECP_NIST_OPTIM */
+#if defined(POLARSSL_ECDSA_DETERMINISTIC)
+    "POLARSSL_ECDSA_DETERMINISTIC",
+#endif /* POLARSSL_ECDSA_DETERMINISTIC */
+#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED)
+    "POLARSSL_KEY_EXCHANGE_PSK_ENABLED",
+#endif /* POLARSSL_KEY_EXCHANGE_PSK_ENABLED */
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED)
+    "POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED",
+#endif /* POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
+    "POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED",
+#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
+#if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED)
+    "POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED",
+#endif /* POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED */
+#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED)
+    "POLARSSL_KEY_EXCHANGE_RSA_ENABLED",
+#endif /* POLARSSL_KEY_EXCHANGE_RSA_ENABLED */
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED)
+    "POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED",
+#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED */
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED)
+    "POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED",
+#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED */
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+    "POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED",
+#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
+#if defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+    "POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED",
+#endif /* POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
+#if defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED)
+    "POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED",
+#endif /* POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED */
+#if defined(POLARSSL_PK_PARSE_EC_EXTENDED)
+    "POLARSSL_PK_PARSE_EC_EXTENDED",
+#endif /* POLARSSL_PK_PARSE_EC_EXTENDED */
+#if defined(POLARSSL_ERROR_STRERROR_BC)
+    "POLARSSL_ERROR_STRERROR_BC",
+#endif /* POLARSSL_ERROR_STRERROR_BC */
+#if defined(POLARSSL_ERROR_STRERROR_DUMMY)
+    "POLARSSL_ERROR_STRERROR_DUMMY",
+#endif /* POLARSSL_ERROR_STRERROR_DUMMY */
+#if defined(POLARSSL_GENPRIME)
+    "POLARSSL_GENPRIME",
+#endif /* POLARSSL_GENPRIME */
+#if defined(POLARSSL_FS_IO)
+    "POLARSSL_FS_IO",
+#endif /* POLARSSL_FS_IO */
+#if defined(POLARSSL_NO_DEFAULT_ENTROPY_SOURCES)
+    "POLARSSL_NO_DEFAULT_ENTROPY_SOURCES",
+#endif /* POLARSSL_NO_DEFAULT_ENTROPY_SOURCES */
+#if defined(POLARSSL_NO_PLATFORM_ENTROPY)
+    "POLARSSL_NO_PLATFORM_ENTROPY",
+#endif /* POLARSSL_NO_PLATFORM_ENTROPY */
+#if defined(POLARSSL_ENTROPY_FORCE_SHA256)
+    "POLARSSL_ENTROPY_FORCE_SHA256",
+#endif /* POLARSSL_ENTROPY_FORCE_SHA256 */
+#if defined(POLARSSL_MEMORY_DEBUG)
+    "POLARSSL_MEMORY_DEBUG",
+#endif /* POLARSSL_MEMORY_DEBUG */
+#if defined(POLARSSL_MEMORY_BACKTRACE)
+    "POLARSSL_MEMORY_BACKTRACE",
+#endif /* POLARSSL_MEMORY_BACKTRACE */
+#if defined(POLARSSL_PKCS1_V15)
+    "POLARSSL_PKCS1_V15",
+#endif /* POLARSSL_PKCS1_V15 */
+#if defined(POLARSSL_PKCS1_V21)
+    "POLARSSL_PKCS1_V21",
+#endif /* POLARSSL_PKCS1_V21 */
+#if defined(POLARSSL_RSA_NO_CRT)
+    "POLARSSL_RSA_NO_CRT",
+#endif /* POLARSSL_RSA_NO_CRT */
+#if defined(POLARSSL_SELF_TEST)
+    "POLARSSL_SELF_TEST",
+#endif /* POLARSSL_SELF_TEST */
+#if defined(POLARSSL_SSL_ALERT_MESSAGES)
+    "POLARSSL_SSL_ALERT_MESSAGES",
+#endif /* POLARSSL_SSL_ALERT_MESSAGES */
+#if defined(POLARSSL_SSL_DEBUG_ALL)
+    "POLARSSL_SSL_DEBUG_ALL",
+#endif /* POLARSSL_SSL_DEBUG_ALL */
+#if defined(POLARSSL_SSL_HW_RECORD_ACCEL)
+    "POLARSSL_SSL_HW_RECORD_ACCEL",
+#endif /* POLARSSL_SSL_HW_RECORD_ACCEL */
+#if defined(POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO)
+    "POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO",
+#endif /* POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */
+#if defined(POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE)
+    "POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE",
+#endif /* POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE */
+#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH)
+    "POLARSSL_SSL_MAX_FRAGMENT_LENGTH",
+#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */
+#if defined(POLARSSL_SSL_PROTO_SSL3)
+    "POLARSSL_SSL_PROTO_SSL3",
+#endif /* POLARSSL_SSL_PROTO_SSL3 */
+#if defined(POLARSSL_SSL_PROTO_TLS1)
+    "POLARSSL_SSL_PROTO_TLS1",
+#endif /* POLARSSL_SSL_PROTO_TLS1 */
+#if defined(POLARSSL_SSL_PROTO_TLS1_1)
+    "POLARSSL_SSL_PROTO_TLS1_1",
+#endif /* POLARSSL_SSL_PROTO_TLS1_1 */
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+    "POLARSSL_SSL_PROTO_TLS1_2",
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
+#if defined(POLARSSL_SSL_ALPN)
+    "POLARSSL_SSL_ALPN",
+#endif /* POLARSSL_SSL_ALPN */
+#if defined(POLARSSL_SSL_SESSION_TICKETS)
+    "POLARSSL_SSL_SESSION_TICKETS",
+#endif /* POLARSSL_SSL_SESSION_TICKETS */
+#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
+    "POLARSSL_SSL_SERVER_NAME_INDICATION",
+#endif /* POLARSSL_SSL_SERVER_NAME_INDICATION */
+#if defined(POLARSSL_SSL_TRUNCATED_HMAC)
+    "POLARSSL_SSL_TRUNCATED_HMAC",
+#endif /* POLARSSL_SSL_TRUNCATED_HMAC */
+#if defined(POLARSSL_SSL_SET_CURVES)
+    "POLARSSL_SSL_SET_CURVES",
+#endif /* POLARSSL_SSL_SET_CURVES */
+#if defined(POLARSSL_THREADING_ALT)
+    "POLARSSL_THREADING_ALT",
+#endif /* POLARSSL_THREADING_ALT */
+#if defined(POLARSSL_THREADING_PTHREAD)
+    "POLARSSL_THREADING_PTHREAD",
+#endif /* POLARSSL_THREADING_PTHREAD */
+#if defined(POLARSSL_VERSION_FEATURES)
+    "POLARSSL_VERSION_FEATURES",
+#endif /* POLARSSL_VERSION_FEATURES */
+#if defined(POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3)
+    "POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3",
+#endif /* POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3 */
+#if defined(POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
+    "POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION",
+#endif /* POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION */
+#if defined(POLARSSL_X509_CHECK_KEY_USAGE)
+    "POLARSSL_X509_CHECK_KEY_USAGE",
+#endif /* POLARSSL_X509_CHECK_KEY_USAGE */
+#if defined(POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE)
+    "POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE",
+#endif /* POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE */
+#if defined(POLARSSL_ZLIB_SUPPORT)
+    "POLARSSL_ZLIB_SUPPORT",
+#endif /* POLARSSL_ZLIB_SUPPORT */
+#if defined(POLARSSL_AESNI_C)
+    "POLARSSL_AESNI_C",
+#endif /* POLARSSL_AESNI_C */
+#if defined(POLARSSL_AES_C)
+    "POLARSSL_AES_C",
+#endif /* POLARSSL_AES_C */
+#if defined(POLARSSL_ARC4_C)
+    "POLARSSL_ARC4_C",
+#endif /* POLARSSL_ARC4_C */
+#if defined(POLARSSL_ASN1_PARSE_C)
+    "POLARSSL_ASN1_PARSE_C",
+#endif /* POLARSSL_ASN1_PARSE_C */
+#if defined(POLARSSL_ASN1_WRITE_C)
+    "POLARSSL_ASN1_WRITE_C",
+#endif /* POLARSSL_ASN1_WRITE_C */
+#if defined(POLARSSL_BASE64_C)
+    "POLARSSL_BASE64_C",
+#endif /* POLARSSL_BASE64_C */
+#if defined(POLARSSL_BIGNUM_C)
+    "POLARSSL_BIGNUM_C",
+#endif /* POLARSSL_BIGNUM_C */
+#if defined(POLARSSL_BLOWFISH_C)
+    "POLARSSL_BLOWFISH_C",
+#endif /* POLARSSL_BLOWFISH_C */
+#if defined(POLARSSL_CAMELLIA_C)
+    "POLARSSL_CAMELLIA_C",
+#endif /* POLARSSL_CAMELLIA_C */
+#if defined(POLARSSL_CERTS_C)
+    "POLARSSL_CERTS_C",
+#endif /* POLARSSL_CERTS_C */
+#if defined(POLARSSL_CIPHER_C)
+    "POLARSSL_CIPHER_C",
+#endif /* POLARSSL_CIPHER_C */
+#if defined(POLARSSL_CTR_DRBG_C)
+    "POLARSSL_CTR_DRBG_C",
+#endif /* POLARSSL_CTR_DRBG_C */
+#if defined(POLARSSL_DEBUG_C)
+    "POLARSSL_DEBUG_C",
+#endif /* POLARSSL_DEBUG_C */
+#if defined(POLARSSL_DES_C)
+    "POLARSSL_DES_C",
+#endif /* POLARSSL_DES_C */
+#if defined(POLARSSL_DHM_C)
+    "POLARSSL_DHM_C",
+#endif /* POLARSSL_DHM_C */
+#if defined(POLARSSL_ECDH_C)
+    "POLARSSL_ECDH_C",
+#endif /* POLARSSL_ECDH_C */
+#if defined(POLARSSL_ECDSA_C)
+    "POLARSSL_ECDSA_C",
+#endif /* POLARSSL_ECDSA_C */
+#if defined(POLARSSL_ECP_C)
+    "POLARSSL_ECP_C",
+#endif /* POLARSSL_ECP_C */
+#if defined(POLARSSL_ENTROPY_C)
+    "POLARSSL_ENTROPY_C",
+#endif /* POLARSSL_ENTROPY_C */
+#if defined(POLARSSL_ERROR_C)
+    "POLARSSL_ERROR_C",
+#endif /* POLARSSL_ERROR_C */
+#if defined(POLARSSL_GCM_C)
+    "POLARSSL_GCM_C",
+#endif /* POLARSSL_GCM_C */
+#if defined(POLARSSL_HAVEGE_C)
+    "POLARSSL_HAVEGE_C",
+#endif /* POLARSSL_HAVEGE_C */
+#if defined(POLARSSL_HMAC_DRBG_C)
+    "POLARSSL_HMAC_DRBG_C",
+#endif /* POLARSSL_HMAC_DRBG_C */
+#if defined(POLARSSL_MD_C)
+    "POLARSSL_MD_C",
+#endif /* POLARSSL_MD_C */
+#if defined(POLARSSL_MD2_C)
+    "POLARSSL_MD2_C",
+#endif /* POLARSSL_MD2_C */
+#if defined(POLARSSL_MD4_C)
+    "POLARSSL_MD4_C",
+#endif /* POLARSSL_MD4_C */
+#if defined(POLARSSL_MD5_C)
+    "POLARSSL_MD5_C",
+#endif /* POLARSSL_MD5_C */
+#if defined(POLARSSL_MEMORY_C)
+    "POLARSSL_MEMORY_C",
+#endif /* POLARSSL_MEMORY_C */
+#if defined(POLARSSL_MEMORY_BUFFER_ALLOC_C)
+    "POLARSSL_MEMORY_BUFFER_ALLOC_C",
+#endif /* POLARSSL_MEMORY_BUFFER_ALLOC_C */
+#if defined(POLARSSL_NET_C)
+    "POLARSSL_NET_C",
+#endif /* POLARSSL_NET_C */
+#if defined(POLARSSL_OID_C)
+    "POLARSSL_OID_C",
+#endif /* POLARSSL_OID_C */
+#if defined(POLARSSL_PADLOCK_C)
+    "POLARSSL_PADLOCK_C",
+#endif /* POLARSSL_PADLOCK_C */
+#if defined(POLARSSL_PBKDF2_C)
+    "POLARSSL_PBKDF2_C",
+#endif /* POLARSSL_PBKDF2_C */
+#if defined(POLARSSL_PEM_PARSE_C)
+    "POLARSSL_PEM_PARSE_C",
+#endif /* POLARSSL_PEM_PARSE_C */
+#if defined(POLARSSL_PEM_WRITE_C)
+    "POLARSSL_PEM_WRITE_C",
+#endif /* POLARSSL_PEM_WRITE_C */
+#if defined(POLARSSL_PK_C)
+    "POLARSSL_PK_C",
+#endif /* POLARSSL_PK_C */
+#if defined(POLARSSL_PK_PARSE_C)
+    "POLARSSL_PK_PARSE_C",
+#endif /* POLARSSL_PK_PARSE_C */
+#if defined(POLARSSL_PK_WRITE_C)
+    "POLARSSL_PK_WRITE_C",
+#endif /* POLARSSL_PK_WRITE_C */
+#if defined(POLARSSL_PKCS5_C)
+    "POLARSSL_PKCS5_C",
+#endif /* POLARSSL_PKCS5_C */
+#if defined(POLARSSL_PKCS11_C)
+    "POLARSSL_PKCS11_C",
+#endif /* POLARSSL_PKCS11_C */
+#if defined(POLARSSL_PKCS12_C)
+    "POLARSSL_PKCS12_C",
+#endif /* POLARSSL_PKCS12_C */
+#if defined(POLARSSL_PLATFORM_C)
+    "POLARSSL_PLATFORM_C",
+#endif /* POLARSSL_PLATFORM_C */
+#if defined(POLARSSL_RIPEMD160_C)
+    "POLARSSL_RIPEMD160_C",
+#endif /* POLARSSL_RIPEMD160_C */
+#if defined(POLARSSL_RSA_C)
+    "POLARSSL_RSA_C",
+#endif /* POLARSSL_RSA_C */
+#if defined(POLARSSL_SHA1_C)
+    "POLARSSL_SHA1_C",
+#endif /* POLARSSL_SHA1_C */
+#if defined(POLARSSL_SHA256_C)
+    "POLARSSL_SHA256_C",
+#endif /* POLARSSL_SHA256_C */
+#if defined(POLARSSL_SHA512_C)
+    "POLARSSL_SHA512_C",
+#endif /* POLARSSL_SHA512_C */
+#if defined(POLARSSL_SSL_CACHE_C)
+    "POLARSSL_SSL_CACHE_C",
+#endif /* POLARSSL_SSL_CACHE_C */
+#if defined(POLARSSL_SSL_CLI_C)
+    "POLARSSL_SSL_CLI_C",
+#endif /* POLARSSL_SSL_CLI_C */
+#if defined(POLARSSL_SSL_SRV_C)
+    "POLARSSL_SSL_SRV_C",
+#endif /* POLARSSL_SSL_SRV_C */
+#if defined(POLARSSL_SSL_TLS_C)
+    "POLARSSL_SSL_TLS_C",
+#endif /* POLARSSL_SSL_TLS_C */
+#if defined(POLARSSL_THREADING_C)
+    "POLARSSL_THREADING_C",
+#endif /* POLARSSL_THREADING_C */
+#if defined(POLARSSL_TIMING_C)
+    "POLARSSL_TIMING_C",
+#endif /* POLARSSL_TIMING_C */
+#if defined(POLARSSL_VERSION_C)
+    "POLARSSL_VERSION_C",
+#endif /* POLARSSL_VERSION_C */
+#if defined(POLARSSL_X509_USE_C)
+    "POLARSSL_X509_USE_C",
+#endif /* POLARSSL_X509_USE_C */
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+    "POLARSSL_X509_CRT_PARSE_C",
+#endif /* POLARSSL_X509_CRT_PARSE_C */
+#if defined(POLARSSL_X509_CRL_PARSE_C)
+    "POLARSSL_X509_CRL_PARSE_C",
+#endif /* POLARSSL_X509_CRL_PARSE_C */
+#if defined(POLARSSL_X509_CSR_PARSE_C)
+    "POLARSSL_X509_CSR_PARSE_C",
+#endif /* POLARSSL_X509_CSR_PARSE_C */
+#if defined(POLARSSL_X509_CREATE_C)
+    "POLARSSL_X509_CREATE_C",
+#endif /* POLARSSL_X509_CREATE_C */
+#if defined(POLARSSL_X509_CRT_WRITE_C)
+    "POLARSSL_X509_CRT_WRITE_C",
+#endif /* POLARSSL_X509_CRT_WRITE_C */
+#if defined(POLARSSL_X509_CSR_WRITE_C)
+    "POLARSSL_X509_CSR_WRITE_C",
+#endif /* POLARSSL_X509_CSR_WRITE_C */
+#if defined(POLARSSL_XTEA_C)
+    "POLARSSL_XTEA_C",
+#endif /* POLARSSL_XTEA_C */
+#endif /* POLARSSL_VERSION_FEATURES */
+    NULL
+};
+
+int version_check_feature( const char *feature )
+{
+    const char **idx = features;
+
+    if( *idx == NULL )
+        return( -2 );
+
+    if( feature == NULL )
+        return( -1 );
+
+    while( *idx != NULL )
+    {
+        if( !strcasecmp( *idx, feature ) )
+            return( 0 );
+        idx++;
+    }
+    return( -1 );
+}
+
+#endif /* POLARSSL_VERSION_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/x509.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,806 @@
+/*
+ *  X.509 certificate and private key decoding
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  The ITU-T X.509 standard defines a certificate format for PKI.
+ *
+ *  http://www.ietf.org/rfc/rfc3279.txt
+ *  http://www.ietf.org/rfc/rfc3280.txt
+ *
+ *  ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc
+ *
+ *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
+ *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_X509_USE_C)
+
+#include "polarssl/x509.h"
+#include "polarssl/asn1.h"
+#include "polarssl/oid.h"
+#if defined(POLARSSL_PEM_PARSE_C)
+#include "polarssl/pem.h"
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf     printf
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
+#include <windows.h>
+#else
+#include <time.h>
+#endif
+
+#if defined(EFIX64) || defined(EFI32)
+#include <stdio.h>
+#endif
+
+#if defined(POLARSSL_FS_IO)
+#include <stdio.h>
+#if !defined(_WIN32)
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#endif
+#endif
+
+/*
+ *  CertificateSerialNumber  ::=  INTEGER
+ */
+int x509_get_serial( unsigned char **p, const unsigned char *end,
+                     x509_buf *serial )
+{
+    int ret;
+
+    if( ( end - *p ) < 1 )
+        return( POLARSSL_ERR_X509_INVALID_SERIAL +
+                POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+    if( **p != ( ASN1_CONTEXT_SPECIFIC | ASN1_PRIMITIVE | 2 ) &&
+        **p !=   ASN1_INTEGER )
+        return( POLARSSL_ERR_X509_INVALID_SERIAL +
+                POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
+
+    serial->tag = *(*p)++;
+
+    if( ( ret = asn1_get_len( p, end, &serial->len ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_SERIAL + ret );
+
+    serial->p = *p;
+    *p += serial->len;
+
+    return( 0 );
+}
+
+/* Get an algorithm identifier without parameters (eg for signatures)
+ *
+ *  AlgorithmIdentifier  ::=  SEQUENCE  {
+ *       algorithm               OBJECT IDENTIFIER,
+ *       parameters              ANY DEFINED BY algorithm OPTIONAL  }
+ */
+int x509_get_alg_null( unsigned char **p, const unsigned char *end,
+                       x509_buf *alg )
+{
+    int ret;
+
+    if( ( ret = asn1_get_alg_null( p, end, alg ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_ALG + ret );
+
+    return( 0 );
+}
+
+/*
+ *  AttributeTypeAndValue ::= SEQUENCE {
+ *    type     AttributeType,
+ *    value    AttributeValue }
+ *
+ *  AttributeType ::= OBJECT IDENTIFIER
+ *
+ *  AttributeValue ::= ANY DEFINED BY AttributeType
+ */
+static int x509_get_attr_type_value( unsigned char **p,
+                                     const unsigned char *end,
+                                     x509_name *cur )
+{
+    int ret;
+    size_t len;
+    x509_buf *oid;
+    x509_buf *val;
+
+    if( ( ret = asn1_get_tag( p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_NAME + ret );
+
+    if( ( end - *p ) < 1 )
+        return( POLARSSL_ERR_X509_INVALID_NAME +
+                POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+    oid = &cur->oid;
+    oid->tag = **p;
+
+    if( ( ret = asn1_get_tag( p, end, &oid->len, ASN1_OID ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_NAME + ret );
+
+    oid->p = *p;
+    *p += oid->len;
+
+    if( ( end - *p ) < 1 )
+        return( POLARSSL_ERR_X509_INVALID_NAME +
+                POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+    if( **p != ASN1_BMP_STRING && **p != ASN1_UTF8_STRING      &&
+        **p != ASN1_T61_STRING && **p != ASN1_PRINTABLE_STRING &&
+        **p != ASN1_IA5_STRING && **p != ASN1_UNIVERSAL_STRING )
+        return( POLARSSL_ERR_X509_INVALID_NAME +
+                POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
+
+    val = &cur->val;
+    val->tag = *(*p)++;
+
+    if( ( ret = asn1_get_len( p, end, &val->len ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_NAME + ret );
+
+    val->p = *p;
+    *p += val->len;
+
+    cur->next = NULL;
+
+    return( 0 );
+}
+
+/*
+ *  RelativeDistinguishedName ::=
+ *    SET OF AttributeTypeAndValue
+ *
+ *  AttributeTypeAndValue ::= SEQUENCE {
+ *    type     AttributeType,
+ *    value    AttributeValue }
+ *
+ *  AttributeType ::= OBJECT IDENTIFIER
+ *
+ *  AttributeValue ::= ANY DEFINED BY AttributeType
+ */
+int x509_get_name( unsigned char **p, const unsigned char *end,
+                   x509_name *cur )
+{
+    int ret;
+    size_t len;
+    const unsigned char *end2;
+    x509_name *use;
+
+    if( ( ret = asn1_get_tag( p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SET ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_NAME + ret );
+
+    end2 = end;
+    end  = *p + len;
+    use = cur;
+
+    do
+    {
+        if( ( ret = x509_get_attr_type_value( p, end, use ) ) != 0 )
+            return( ret );
+
+        if( *p != end )
+        {
+            use->next = (x509_name *) polarssl_malloc(
+                    sizeof( x509_name ) );
+
+            if( use->next == NULL )
+                return( POLARSSL_ERR_X509_MALLOC_FAILED );
+
+            memset( use->next, 0, sizeof( x509_name ) );
+
+            use = use->next;
+        }
+    }
+    while( *p != end );
+
+    /*
+     * recurse until end of SEQUENCE is reached
+     */
+    if( *p == end2 )
+        return( 0 );
+
+    cur->next = (x509_name *) polarssl_malloc(
+         sizeof( x509_name ) );
+
+    if( cur->next == NULL )
+        return( POLARSSL_ERR_X509_MALLOC_FAILED );
+
+    memset( cur->next, 0, sizeof( x509_name ) );
+
+    return( x509_get_name( p, end2, cur->next ) );
+}
+
+/*
+ *  Time ::= CHOICE {
+ *       utcTime        UTCTime,
+ *       generalTime    GeneralizedTime }
+ */
+int x509_get_time( unsigned char **p, const unsigned char *end,
+                   x509_time *time )
+{
+    int ret;
+    size_t len;
+    char date[64];
+    unsigned char tag;
+
+    if( ( end - *p ) < 1 )
+        return( POLARSSL_ERR_X509_INVALID_DATE +
+                POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+    tag = **p;
+
+    if ( tag == ASN1_UTC_TIME )
+    {
+        (*p)++;
+        ret = asn1_get_len( p, end, &len );
+
+        if( ret != 0 )
+            return( POLARSSL_ERR_X509_INVALID_DATE + ret );
+
+        memset( date,  0, sizeof( date ) );
+        memcpy( date, *p, ( len < sizeof( date ) - 1 ) ?
+                len : sizeof( date ) - 1 );
+
+        if( sscanf( date, "%2d%2d%2d%2d%2d%2dZ",
+                    &time->year, &time->mon, &time->day,
+                    &time->hour, &time->min, &time->sec ) < 5 )
+            return( POLARSSL_ERR_X509_INVALID_DATE );
+
+        time->year +=  100 * ( time->year < 50 );
+        time->year += 1900;
+
+        *p += len;
+
+        return( 0 );
+    }
+    else if ( tag == ASN1_GENERALIZED_TIME )
+    {
+        (*p)++;
+        ret = asn1_get_len( p, end, &len );
+
+        if( ret != 0 )
+            return( POLARSSL_ERR_X509_INVALID_DATE + ret );
+
+        memset( date,  0, sizeof( date ) );
+        memcpy( date, *p, ( len < sizeof( date ) - 1 ) ?
+                len : sizeof( date ) - 1 );
+
+        if( sscanf( date, "%4d%2d%2d%2d%2d%2dZ",
+                    &time->year, &time->mon, &time->day,
+                    &time->hour, &time->min, &time->sec ) < 5 )
+            return( POLARSSL_ERR_X509_INVALID_DATE );
+
+        *p += len;
+
+        return( 0 );
+    }
+    else
+        return( POLARSSL_ERR_X509_INVALID_DATE +
+                POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
+}
+
+int x509_get_sig( unsigned char **p, const unsigned char *end, x509_buf *sig )
+{
+    int ret;
+    size_t len;
+
+    if( ( end - *p ) < 1 )
+        return( POLARSSL_ERR_X509_INVALID_SIGNATURE +
+                POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+    sig->tag = **p;
+
+    if( ( ret = asn1_get_bitstring_null( p, end, &len ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_SIGNATURE + ret );
+
+    sig->len = len;
+    sig->p = *p;
+
+    *p += len;
+
+    return( 0 );
+}
+
+int x509_get_sig_alg( const x509_buf *sig_oid, md_type_t *md_alg,
+                      pk_type_t *pk_alg )
+{
+    int ret = oid_get_sig_alg( sig_oid, md_alg, pk_alg );
+
+    if( ret != 0 )
+        return( POLARSSL_ERR_X509_UNKNOWN_SIG_ALG + ret );
+
+    return( 0 );
+}
+
+/*
+ * X.509 Extensions (No parsing of extensions, pointer should
+ * be either manually updated or extensions should be parsed!
+ */
+int x509_get_ext( unsigned char **p, const unsigned char *end,
+                  x509_buf *ext, int tag )
+{
+    int ret;
+    size_t len;
+
+    if( *p == end )
+        return( 0 );
+
+    ext->tag = **p;
+
+    if( ( ret = asn1_get_tag( p, end, &ext->len,
+            ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | tag ) ) != 0 )
+        return( ret );
+
+    ext->p = *p;
+    end = *p + ext->len;
+
+    /*
+     * Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
+     *
+     * Extension  ::=  SEQUENCE  {
+     *      extnID      OBJECT IDENTIFIER,
+     *      critical    BOOLEAN DEFAULT FALSE,
+     *      extnValue   OCTET STRING  }
+     */
+    if( ( ret = asn1_get_tag( p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
+
+    if( end != *p + len )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * Load all data from a file into a given buffer.
+ */
+int x509_load_file( const char *path, unsigned char **buf, size_t *n )
+{
+    FILE *f;
+    long size;
+
+    if( ( f = fopen( path, "rb" ) ) == NULL )
+        return( POLARSSL_ERR_X509_FILE_IO_ERROR );
+
+    fseek( f, 0, SEEK_END );
+    if( ( size = ftell( f ) ) == -1 )
+    {
+        fclose( f );
+        return( POLARSSL_ERR_X509_FILE_IO_ERROR );
+    }
+    fseek( f, 0, SEEK_SET );
+
+    *n = (size_t) size;
+
+    if( *n + 1 == 0 ||
+        ( *buf = (unsigned char *) polarssl_malloc( *n + 1 ) ) == NULL )
+    {
+        fclose( f );
+        return( POLARSSL_ERR_X509_MALLOC_FAILED );
+    }
+
+    if( fread( *buf, 1, *n, f ) != *n )
+    {
+        fclose( f );
+        polarssl_free( *buf );
+        return( POLARSSL_ERR_X509_FILE_IO_ERROR );
+    }
+
+    fclose( f );
+
+    (*buf)[*n] = '\0';
+
+    return( 0 );
+}
+#endif /* POLARSSL_FS_IO */
+
+#if defined(_MSC_VER) && !defined snprintf && !defined(EFIX64) && \
+    !defined(EFI32)
+#include <stdarg.h>
+
+#if !defined vsnprintf
+#define vsnprintf _vsnprintf
+#endif // vsnprintf
+
+/*
+ * Windows _snprintf and _vsnprintf are not compatible to linux versions.
+ * Result value is not size of buffer needed, but -1 if no fit is possible.
+ *
+ * This fuction tries to 'fix' this by at least suggesting enlarging the
+ * size by 20.
+ */
+static int compat_snprintf(char *str, size_t size, const char *format, ...)
+{
+    va_list ap;
+    int res = -1;
+
+    va_start( ap, format );
+
+    res = vsnprintf( str, size, format, ap );
+
+    va_end( ap );
+
+    // No quick fix possible
+    if ( res < 0 )
+        return( (int) size + 20 );
+
+    return res;
+}
+
+#define snprintf compat_snprintf
+#endif /* _MSC_VER && !snprintf && !EFIX64 && !EFI32 */
+
+#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL    -2
+
+#define SAFE_SNPRINTF()                         \
+{                                               \
+    if( ret == -1 )                             \
+        return( -1 );                           \
+                                                \
+    if ( (unsigned int) ret > n ) {             \
+        p[n - 1] = '\0';                        \
+        return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\
+    }                                           \
+                                                \
+    n -= (unsigned int) ret;                    \
+    p += (unsigned int) ret;                    \
+}
+
+/*
+ * Store the name in printable form into buf; no more
+ * than size characters will be written
+ */
+int x509_dn_gets( char *buf, size_t size, const x509_name *dn )
+{
+    int ret;
+    size_t i, n;
+    unsigned char c;
+    const x509_name *name;
+    const char *short_name = NULL;
+    char s[128], *p;
+
+    memset( s, 0, sizeof( s ) );
+
+    name = dn;
+    p = buf;
+    n = size;
+
+    while( name != NULL )
+    {
+        if( !name->oid.p )
+        {
+            name = name->next;
+            continue;
+        }
+
+        if( name != dn )
+        {
+            ret = snprintf( p, n, ", " );
+            SAFE_SNPRINTF();
+        }
+
+        ret = oid_get_attr_short_name( &name->oid, &short_name );
+
+        if( ret == 0 )
+            ret = snprintf( p, n, "%s=", short_name );
+        else
+            ret = snprintf( p, n, "\?\?=" );
+        SAFE_SNPRINTF();
+
+        for( i = 0; i < name->val.len; i++ )
+        {
+            if( i >= sizeof( s ) - 1 )
+                break;
+
+            c = name->val.p[i];
+            if( c < 32 || c == 127 || ( c > 128 && c < 160 ) )
+                 s[i] = '?';
+            else s[i] = c;
+        }
+        s[i] = '\0';
+        ret = snprintf( p, n, "%s", s );
+        SAFE_SNPRINTF();
+        name = name->next;
+    }
+
+    return( (int) ( size - n ) );
+}
+
+/*
+ * Store the serial in printable form into buf; no more
+ * than size characters will be written
+ */
+int x509_serial_gets( char *buf, size_t size, const x509_buf *serial )
+{
+    int ret;
+    size_t i, n, nr;
+    char *p;
+
+    p = buf;
+    n = size;
+
+    nr = ( serial->len <= 32 )
+        ? serial->len  : 28;
+
+    for( i = 0; i < nr; i++ )
+    {
+        if( i == 0 && nr > 1 && serial->p[i] == 0x0 )
+            continue;
+
+        ret = snprintf( p, n, "%02X%s",
+                serial->p[i], ( i < nr - 1 ) ? ":" : "" );
+        SAFE_SNPRINTF();
+    }
+
+    if( nr != serial->len )
+    {
+        ret = snprintf( p, n, "...." );
+        SAFE_SNPRINTF();
+    }
+
+    return( (int) ( size - n ) );
+}
+
+/*
+ * Helper for writing "RSA key size", "EC key size", etc
+ */
+int x509_key_size_helper( char *buf, size_t size, const char *name )
+{
+    char *p = buf;
+    size_t n = size;
+    int ret;
+
+    if( strlen( name ) + sizeof( " key size" ) > size )
+        return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;
+
+    ret = snprintf( p, n, "%s key size", name );
+    SAFE_SNPRINTF();
+
+    return( 0 );
+}
+
+/*
+ * Return an informational string describing the given OID
+ */
+const char *x509_oid_get_description( x509_buf *oid )
+{
+    const char *desc = NULL;
+    int ret;
+
+    ret = oid_get_extended_key_usage( oid, &desc );
+
+    if( ret != 0 )
+        return( NULL );
+
+    return( desc );
+}
+
+/* Return the x.y.z.... style numeric string for the given OID */
+int x509_oid_get_numeric_string( char *buf, size_t size, x509_buf *oid )
+{
+    return oid_get_numeric_string( buf, size, oid );
+}
+
+/*
+ * Return 0 if the x509_time is still valid, or 1 otherwise.
+ */
+#if defined(POLARSSL_HAVE_TIME)
+
+static void x509_get_current_time( x509_time *now )
+{
+#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
+    SYSTEMTIME st;
+
+    GetSystemTime(&st);
+
+    now->year = st.wYear;
+    now->mon = st.wMonth;
+    now->day = st.wDay;
+    now->hour = st.wHour;
+    now->min = st.wMinute;
+    now->sec = st.wSecond;
+#else
+    struct tm lt;
+    time_t tt;
+
+    tt = time( NULL );
+    gmtime_r( &tt, &lt );
+
+    now->year = lt.tm_year + 1900;
+    now->mon = lt.tm_mon + 1;
+    now->day = lt.tm_mday;
+    now->hour = lt.tm_hour;
+    now->min = lt.tm_min;
+    now->sec = lt.tm_sec;
+#endif /* _WIN32 && !EFIX64 && !EFI32 */
+}
+
+/*
+ * Return 0 if before <= after, 1 otherwise
+ */
+static int x509_check_time( const x509_time *before, const x509_time *after )
+{
+    if( before->year  > after->year )
+        return( 1 );
+
+    if( before->year == after->year &&
+        before->mon   > after->mon )
+        return( 1 );
+
+    if( before->year == after->year &&
+        before->mon  == after->mon  &&
+        before->day   > after->day )
+        return( 1 );
+
+    if( before->year == after->year &&
+        before->mon  == after->mon  &&
+        before->day  == after->day  &&
+        before->hour  > after->hour )
+        return( 1 );
+
+    if( before->year == after->year &&
+        before->mon  == after->mon  &&
+        before->day  == after->day  &&
+        before->hour == after->hour &&
+        before->min   > after->min  )
+        return( 1 );
+
+    if( before->year == after->year &&
+        before->mon  == after->mon  &&
+        before->day  == after->day  &&
+        before->hour == after->hour &&
+        before->min  == after->min  &&
+        before->sec   > after->sec  )
+        return( 1 );
+
+    return( 0 );
+}
+
+int x509_time_expired( const x509_time *to )
+{
+    x509_time now;
+
+    x509_get_current_time( &now );
+
+    return( x509_check_time( &now, to ) );
+}
+
+int x509_time_future( const x509_time *from )
+{
+    x509_time now;
+
+    x509_get_current_time( &now );
+
+    return( x509_check_time( from, &now ) );
+}
+
+#else  /* POLARSSL_HAVE_TIME */
+
+int x509_time_expired( const x509_time *to )
+{
+    ((void) to);
+    return( 0 );
+}
+
+int x509_time_future( const x509_time *from )
+{
+    ((void) from);
+    return( 0 );
+}
+#endif /* POLARSSL_HAVE_TIME */
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include "polarssl/x509_crt.h"
+#include "polarssl/certs.h"
+
+/*
+ * Checkup routine
+ */
+int x509_self_test( int verbose )
+{
+#if defined(POLARSSL_CERTS_C) && defined(POLARSSL_SHA1_C)
+    int ret;
+    int flags;
+    x509_crt cacert;
+    x509_crt clicert;
+
+    if( verbose != 0 )
+        polarssl_printf( "  X.509 certificate load: " );
+
+    x509_crt_init( &clicert );
+
+    ret = x509_crt_parse( &clicert, (const unsigned char *) test_cli_crt,
+                          strlen( test_cli_crt ) );
+    if( ret != 0 )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "failed\n" );
+
+        return( ret );
+    }
+
+    x509_crt_init( &cacert );
+
+    ret = x509_crt_parse( &cacert, (const unsigned char *) test_ca_crt,
+                          strlen( test_ca_crt ) );
+    if( ret != 0 )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "failed\n" );
+
+        return( ret );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n  X.509 signature verify: ");
+
+    ret = x509_crt_verify( &clicert, &cacert, NULL, NULL, &flags, NULL, NULL );
+    if( ret != 0 )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "failed\n" );
+
+        polarssl_printf("ret = %d, &flags = %04x\n", ret, flags);
+
+        return( ret );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n\n");
+
+    x509_crt_free( &cacert  );
+    x509_crt_free( &clicert );
+
+    return( 0 );
+#else
+    ((void) verbose);
+    return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
+#endif /* POLARSSL_CERTS_C && POLARSSL_SHA1_C */
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_X509_USE_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/x509_create.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,328 @@
+/*
+ *  X.509 base functions for creating certificates / CSRs
+ *
+ *  Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_X509_CREATE_C)
+
+#include "polarssl/x509.h"
+#include "polarssl/asn1write.h"
+#include "polarssl/oid.h"
+
+#if defined(_MSC_VER) && !defined strncasecmp && !defined(EFIX64) && \
+    !defined(EFI32)
+#define strncasecmp _strnicmp
+#endif
+
+int x509_string_to_names( asn1_named_data **head, const char *name )
+{
+    int ret = 0;
+    const char *s = name, *c = s;
+    const char *end = s + strlen( s );
+    const char *oid = NULL;
+    int in_tag = 1;
+
+    /* Clear existing chain if present */
+    asn1_free_named_data_list( head );
+
+    while( c <= end )
+    {
+        if( in_tag && *c == '=' )
+        {
+            if( c - s == 2 && strncasecmp( s, "CN", 2 ) == 0 )
+                oid = OID_AT_CN;
+            else if( c - s == 10 && strncasecmp( s, "commonName", 10 ) == 0 )
+                oid = OID_AT_CN;
+            else if( c - s == 1 && strncasecmp( s, "C", 1 ) == 0 )
+                oid = OID_AT_COUNTRY;
+            else if( c - s == 11 && strncasecmp( s, "countryName", 11 ) == 0 )
+                oid = OID_AT_COUNTRY;
+            else if( c - s == 1 && strncasecmp( s, "O", 1 ) == 0 )
+                oid = OID_AT_ORGANIZATION;
+            else if( c - s == 16 &&
+                     strncasecmp( s, "organizationName", 16 ) == 0 )
+                oid = OID_AT_ORGANIZATION;
+            else if( c - s == 1 && strncasecmp( s, "L", 1 ) == 0 )
+                oid = OID_AT_LOCALITY;
+            else if( c - s == 8 && strncasecmp( s, "locality", 8 ) == 0 )
+                oid = OID_AT_LOCALITY;
+            else if( c - s == 1 && strncasecmp( s, "R", 1 ) == 0 )
+                oid = OID_PKCS9_EMAIL;
+            else if( c - s == 2 && strncasecmp( s, "OU", 2 ) == 0 )
+                oid = OID_AT_ORG_UNIT;
+            else if( c - s == 22 &&
+                     strncasecmp( s, "organizationalUnitName", 22 ) == 0 )
+                oid = OID_AT_ORG_UNIT;
+            else if( c - s == 2 && strncasecmp( s, "ST", 2 ) == 0 )
+                oid = OID_AT_STATE;
+            else if( c - s == 19 &&
+                     strncasecmp( s, "stateOrProvinceName", 19 ) == 0 )
+                oid = OID_AT_STATE;
+            else if( c - s == 12 && strncasecmp( s, "emailAddress", 12 ) == 0 )
+                oid = OID_PKCS9_EMAIL;
+            else if( c - s == 12 && strncasecmp( s, "serialNumber", 12 ) == 0 )
+                oid = OID_AT_SERIAL_NUMBER;
+            else if( c - s == 13 && strncasecmp( s, "postalAddress", 13 ) == 0 )
+                oid = OID_AT_POSTAL_ADDRESS;
+            else if( c - s == 10 && strncasecmp( s, "postalCode", 10 ) == 0 )
+                oid = OID_AT_POSTAL_CODE;
+            else if( c - s == 11 && strncasecmp( s, "dnQualifier", 11 ) == 0 )
+                oid = OID_AT_DN_QUALIFIER;
+            else if( c - s == 5 && strncasecmp( s, "title", 5 ) == 0 )
+                oid = OID_AT_TITLE;
+            else if( c - s == 7 && strncasecmp( s, "surName", 7 ) == 0 )
+                oid = OID_AT_SUR_NAME;
+            else if( c - s == 2 && strncasecmp( s, "SN", 2 ) == 0 )
+                oid = OID_AT_SUR_NAME;
+            else if( c - s == 9 && strncasecmp( s, "givenName", 9 ) == 0 )
+                oid = OID_AT_GIVEN_NAME;
+            else if( c - s == 2 && strncasecmp( s, "GN", 2 ) == 0 )
+                oid = OID_AT_GIVEN_NAME;
+            else if( c - s == 8 && strncasecmp( s, "initials", 8 ) == 0 )
+                oid = OID_AT_INITIALS;
+            else if( c - s == 9 && strncasecmp( s, "pseudonym", 9 ) == 0 )
+                oid = OID_AT_PSEUDONYM;
+            else if( c - s == 19 &&
+                     strncasecmp( s, "generationQualifier", 19 ) == 0 )
+                oid = OID_AT_GENERATION_QUALIFIER;
+            else if( c - s == 15 &&
+                     strncasecmp( s, "domainComponent", 15 ) == 0 )
+                oid = OID_DOMAIN_COMPONENT;
+            else if( c - s == 2 && strncasecmp( s, "DC", 2 ) == 0 )
+                oid = OID_DOMAIN_COMPONENT;
+            else
+            {
+                ret = POLARSSL_ERR_X509_UNKNOWN_OID;
+                goto exit;
+            }
+
+            s = c + 1;
+            in_tag = 0;
+        }
+
+        if( !in_tag && ( *c == ',' || c == end ) )
+        {
+            if( asn1_store_named_data( head, oid, strlen( oid ),
+                                       (unsigned char *) s,
+                                       c - s ) == NULL )
+            {
+                return( POLARSSL_ERR_X509_MALLOC_FAILED );
+            }
+
+            while( c < end && *(c + 1) == ' ' )
+                c++;
+
+            s = c + 1;
+            in_tag = 1;
+        }
+        c++;
+    }
+
+exit:
+
+    return( ret );
+}
+
+/* The first byte of the value in the asn1_named_data structure is reserved
+ * to store the critical boolean for us
+ */
+int x509_set_extension( asn1_named_data **head, const char *oid, size_t oid_len,
+                        int critical, const unsigned char *val, size_t val_len )
+{
+    asn1_named_data *cur;
+
+    if( ( cur = asn1_store_named_data( head, oid, oid_len,
+                                       NULL, val_len + 1 ) ) == NULL )
+    {
+        return( POLARSSL_ERR_X509_MALLOC_FAILED );
+    }
+
+    cur->val.p[0] = critical;
+    memcpy( cur->val.p + 1, val, val_len );
+
+    return( 0 );
+}
+
+/*
+ *  RelativeDistinguishedName ::=
+ *    SET OF AttributeTypeAndValue
+ *
+ *  AttributeTypeAndValue ::= SEQUENCE {
+ *    type     AttributeType,
+ *    value    AttributeValue }
+ *
+ *  AttributeType ::= OBJECT IDENTIFIER
+ *
+ *  AttributeValue ::= ANY DEFINED BY AttributeType
+ */
+static int x509_write_name( unsigned char **p, unsigned char *start,
+                            const char *oid, size_t oid_len,
+                            const unsigned char *name, size_t name_len )
+{
+    int ret;
+    size_t len = 0;
+
+    // Write PrintableString for all except OID_PKCS9_EMAIL
+    //
+    if( OID_SIZE( OID_PKCS9_EMAIL ) == oid_len &&
+        memcmp( oid, OID_PKCS9_EMAIL, oid_len ) == 0 )
+    {
+        ASN1_CHK_ADD( len, asn1_write_ia5_string( p, start,
+                                                  (const char *) name,
+                                                  name_len ) );
+    }
+    else
+    {
+        ASN1_CHK_ADD( len, asn1_write_printable_string( p, start,
+                                                        (const char *) name,
+                                                        name_len ) );
+    }
+
+    // Write OID
+    //
+    ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) );
+
+    ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED |
+                                                 ASN1_SEQUENCE ) );
+
+    ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED |
+                                                 ASN1_SET ) );
+
+    return( (int) len );
+}
+
+int x509_write_names( unsigned char **p, unsigned char *start,
+                      asn1_named_data *first )
+{
+    int ret;
+    size_t len = 0;
+    asn1_named_data *cur = first;
+
+    while( cur != NULL )
+    {
+        ASN1_CHK_ADD( len, x509_write_name( p, start, (char *) cur->oid.p,
+                                            cur->oid.len,
+                                            cur->val.p, cur->val.len ) );
+        cur = cur->next;
+    }
+
+    ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED |
+                                                 ASN1_SEQUENCE ) );
+
+    return( (int) len );
+}
+
+int x509_write_sig( unsigned char **p, unsigned char *start,
+                    const char *oid, size_t oid_len,
+                    unsigned char *sig, size_t size )
+{
+    int ret;
+    size_t len = 0;
+
+    if( *p - start < (int) size + 1 )
+        return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+    len = size;
+    (*p) -= len;
+    memcpy( *p, sig, len );
+
+    *--(*p) = 0;
+    len += 1;
+
+    ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BIT_STRING ) );
+
+    // Write OID
+    //
+    ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( p, start, oid,
+                                                        oid_len, 0 ) );
+
+    return( (int) len );
+}
+
+static int x509_write_extension( unsigned char **p, unsigned char *start,
+                                 asn1_named_data *ext )
+{
+    int ret;
+    size_t len = 0;
+
+    ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->val.p + 1,
+                                              ext->val.len - 1 ) );
+    ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->val.len - 1 ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OCTET_STRING ) );
+
+    if( ext->val.p[0] != 0 )
+    {
+        ASN1_CHK_ADD( len, asn1_write_bool( p, start, 1 ) );
+    }
+
+    ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->oid.p,
+                                              ext->oid.len ) );
+    ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->oid.len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OID ) );
+
+    ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED |
+                                                 ASN1_SEQUENCE ) );
+
+    return( (int) len );
+}
+
+/*
+ * Extension  ::=  SEQUENCE  {
+ *     extnID      OBJECT IDENTIFIER,
+ *     critical    BOOLEAN DEFAULT FALSE,
+ *     extnValue   OCTET STRING
+ *                 -- contains the DER encoding of an ASN.1 value
+ *                 -- corresponding to the extension type identified
+ *                 -- by extnID
+ *     }
+ */
+int x509_write_extensions( unsigned char **p, unsigned char *start,
+                           asn1_named_data *first )
+{
+    int ret;
+    size_t len = 0;
+    asn1_named_data *cur_ext = first;
+
+    while( cur_ext != NULL )
+    {
+        ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) );
+        cur_ext = cur_ext->next;
+    }
+
+    return( (int) len );
+}
+
+#endif /* POLARSSL_X509_CREATE_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/x509_crl.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,758 @@
+/*
+ *  X.509 certificate and private key decoding
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  The ITU-T X.509 standard defines a certificate format for PKI.
+ *
+ *  http://www.ietf.org/rfc/rfc3279.txt
+ *  http://www.ietf.org/rfc/rfc3280.txt
+ *
+ *  ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc
+ *
+ *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
+ *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_X509_CRL_PARSE_C)
+
+#include "polarssl/x509_crl.h"
+#include "polarssl/oid.h"
+#if defined(POLARSSL_PEM_PARSE_C)
+#include "polarssl/pem.h"
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
+
+#include <windows.h>
+#else
+#include <time.h>
+#endif
+
+#if defined(POLARSSL_FS_IO) || defined(EFIX64) || defined(EFI32)
+#include <stdio.h>
+#endif
+
+/*
+ *  Version  ::=  INTEGER  {  v1(0), v2(1)  }
+ */
+static int x509_crl_get_version( unsigned char **p,
+                             const unsigned char *end,
+                             int *ver )
+{
+    int ret;
+
+    if( ( ret = asn1_get_int( p, end, ver ) ) != 0 )
+    {
+        if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+        {
+            *ver = 0;
+            return( 0 );
+        }
+
+        return( POLARSSL_ERR_X509_INVALID_VERSION + ret );
+    }
+
+    return( 0 );
+}
+
+/*
+ * X.509 CRL v2 extensions (no extensions parsed yet.)
+ */
+static int x509_get_crl_ext( unsigned char **p,
+                             const unsigned char *end,
+                             x509_buf *ext )
+{
+    int ret;
+    size_t len = 0;
+
+    /* Get explicit tag */
+    if( ( ret = x509_get_ext( p, end, ext, 0) ) != 0 )
+    {
+        if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+            return( 0 );
+
+        return( ret );
+    }
+
+    while( *p < end )
+    {
+        if( ( ret = asn1_get_tag( p, end, &len,
+                ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+            return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
+
+        *p += len;
+    }
+
+    if( *p != end )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    return( 0 );
+}
+
+/*
+ * X.509 CRL v2 entry extensions (no extensions parsed yet.)
+ */
+static int x509_get_crl_entry_ext( unsigned char **p,
+                             const unsigned char *end,
+                             x509_buf *ext )
+{
+    int ret;
+    size_t len = 0;
+
+    /* OPTIONAL */
+    if (end <= *p)
+        return( 0 );
+
+    ext->tag = **p;
+    ext->p = *p;
+
+    /*
+     * Get CRL-entry extension sequence header
+     * crlEntryExtensions      Extensions OPTIONAL  -- if present, MUST be v2
+     */
+    if( ( ret = asn1_get_tag( p, end, &ext->len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+        {
+            ext->p = NULL;
+            return( 0 );
+        }
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
+    }
+
+    end = *p + ext->len;
+
+    if( end != *p + ext->len )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    while( *p < end )
+    {
+        if( ( ret = asn1_get_tag( p, end, &len,
+                ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+            return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
+
+        *p += len;
+    }
+
+    if( *p != end )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    return( 0 );
+}
+
+/*
+ * X.509 CRL Entries
+ */
+static int x509_get_entries( unsigned char **p,
+                             const unsigned char *end,
+                             x509_crl_entry *entry )
+{
+    int ret;
+    size_t entry_len;
+    x509_crl_entry *cur_entry = entry;
+
+    if( *p == end )
+        return( 0 );
+
+    if( ( ret = asn1_get_tag( p, end, &entry_len,
+            ASN1_SEQUENCE | ASN1_CONSTRUCTED ) ) != 0 )
+    {
+        if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+            return( 0 );
+
+        return( ret );
+    }
+
+    end = *p + entry_len;
+
+    while( *p < end )
+    {
+        size_t len2;
+        const unsigned char *end2;
+
+        if( ( ret = asn1_get_tag( p, end, &len2,
+                ASN1_SEQUENCE | ASN1_CONSTRUCTED ) ) != 0 )
+        {
+            return( ret );
+        }
+
+        cur_entry->raw.tag = **p;
+        cur_entry->raw.p = *p;
+        cur_entry->raw.len = len2;
+        end2 = *p + len2;
+
+        if( ( ret = x509_get_serial( p, end2, &cur_entry->serial ) ) != 0 )
+            return( ret );
+
+        if( ( ret = x509_get_time( p, end2,
+                                   &cur_entry->revocation_date ) ) != 0 )
+            return( ret );
+
+        if( ( ret = x509_get_crl_entry_ext( p, end2,
+                                            &cur_entry->entry_ext ) ) != 0 )
+            return( ret );
+
+        if ( *p < end )
+        {
+            cur_entry->next = polarssl_malloc( sizeof( x509_crl_entry ) );
+
+            if( cur_entry->next == NULL )
+                return( POLARSSL_ERR_X509_MALLOC_FAILED );
+
+            cur_entry = cur_entry->next;
+            memset( cur_entry, 0, sizeof( x509_crl_entry ) );
+        }
+    }
+
+    return( 0 );
+}
+
+/*
+ * Parse one or more CRLs and add them to the chained list
+ */
+int x509_crl_parse( x509_crl *chain, const unsigned char *buf, size_t buflen )
+{
+    int ret;
+    size_t len;
+    unsigned char *p, *end;
+    x509_crl *crl;
+#if defined(POLARSSL_PEM_PARSE_C)
+    size_t use_len;
+    pem_context pem;
+#endif
+
+    crl = chain;
+
+    /*
+     * Check for valid input
+     */
+    if( crl == NULL || buf == NULL )
+        return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
+
+    while( crl->version != 0 && crl->next != NULL )
+        crl = crl->next;
+
+    /*
+     * Add new CRL on the end of the chain if needed.
+     */
+    if ( crl->version != 0 && crl->next == NULL)
+    {
+        crl->next = (x509_crl *) polarssl_malloc( sizeof( x509_crl ) );
+
+        if( crl->next == NULL )
+        {
+            x509_crl_free( crl );
+            return( POLARSSL_ERR_X509_MALLOC_FAILED );
+        }
+
+        crl = crl->next;
+        x509_crl_init( crl );
+    }
+
+#if defined(POLARSSL_PEM_PARSE_C)
+    pem_init( &pem );
+    ret = pem_read_buffer( &pem,
+                           "-----BEGIN X509 CRL-----",
+                           "-----END X509 CRL-----",
+                           buf, NULL, 0, &use_len );
+
+    if( ret == 0 )
+    {
+        /*
+         * Was PEM encoded
+         */
+        buflen -= use_len;
+        buf += use_len;
+
+        /*
+         * Steal PEM buffer
+         */
+        p = pem.buf;
+        pem.buf = NULL;
+        len = pem.buflen;
+        pem_free( &pem );
+    }
+    else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
+    {
+        pem_free( &pem );
+        return( ret );
+    }
+    else
+#endif /* POLARSSL_PEM_PARSE_C */
+    {
+        /*
+         * nope, copy the raw DER data
+         */
+        p = (unsigned char *) polarssl_malloc( len = buflen );
+
+        if( p == NULL )
+            return( POLARSSL_ERR_X509_MALLOC_FAILED );
+
+        memcpy( p, buf, buflen );
+
+        buflen = 0;
+    }
+
+    crl->raw.p = p;
+    crl->raw.len = len;
+    end = p + len;
+
+    /*
+     * CertificateList  ::=  SEQUENCE  {
+     *      tbsCertList          TBSCertList,
+     *      signatureAlgorithm   AlgorithmIdentifier,
+     *      signatureValue       BIT STRING  }
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        x509_crl_free( crl );
+        return( POLARSSL_ERR_X509_INVALID_FORMAT );
+    }
+
+    if( len != (size_t) ( end - p ) )
+    {
+        x509_crl_free( crl );
+        return( POLARSSL_ERR_X509_INVALID_FORMAT +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+    }
+
+    /*
+     * TBSCertList  ::=  SEQUENCE  {
+     */
+    crl->tbs.p = p;
+
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        x509_crl_free( crl );
+        return( POLARSSL_ERR_X509_INVALID_FORMAT + ret );
+    }
+
+    end = p + len;
+    crl->tbs.len = end - crl->tbs.p;
+
+    /*
+     * Version  ::=  INTEGER  OPTIONAL {  v1(0), v2(1)  }
+     *               -- if present, MUST be v2
+     *
+     * signature            AlgorithmIdentifier
+     */
+    if( ( ret = x509_crl_get_version( &p, end, &crl->version ) ) != 0 ||
+        ( ret = x509_get_alg_null( &p, end, &crl->sig_oid1   ) ) != 0 )
+    {
+        x509_crl_free( crl );
+        return( ret );
+    }
+
+    crl->version++;
+
+    if( crl->version > 2 )
+    {
+        x509_crl_free( crl );
+        return( POLARSSL_ERR_X509_UNKNOWN_VERSION );
+    }
+
+    if( ( ret = x509_get_sig_alg( &crl->sig_oid1, &crl->sig_md,
+                                  &crl->sig_pk ) ) != 0 )
+    {
+        x509_crl_free( crl );
+        return( POLARSSL_ERR_X509_UNKNOWN_SIG_ALG );
+    }
+
+    /*
+     * issuer               Name
+     */
+    crl->issuer_raw.p = p;
+
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        x509_crl_free( crl );
+        return( POLARSSL_ERR_X509_INVALID_FORMAT + ret );
+    }
+
+    if( ( ret = x509_get_name( &p, p + len, &crl->issuer ) ) != 0 )
+    {
+        x509_crl_free( crl );
+        return( ret );
+    }
+
+    crl->issuer_raw.len = p - crl->issuer_raw.p;
+
+    /*
+     * thisUpdate          Time
+     * nextUpdate          Time OPTIONAL
+     */
+    if( ( ret = x509_get_time( &p, end, &crl->this_update ) ) != 0 )
+    {
+        x509_crl_free( crl );
+        return( ret );
+    }
+
+    if( ( ret = x509_get_time( &p, end, &crl->next_update ) ) != 0 )
+    {
+        if ( ret != ( POLARSSL_ERR_X509_INVALID_DATE +
+                        POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) &&
+             ret != ( POLARSSL_ERR_X509_INVALID_DATE +
+                        POLARSSL_ERR_ASN1_OUT_OF_DATA ) )
+        {
+            x509_crl_free( crl );
+            return( ret );
+        }
+    }
+
+    /*
+     * revokedCertificates    SEQUENCE OF SEQUENCE   {
+     *      userCertificate        CertificateSerialNumber,
+     *      revocationDate         Time,
+     *      crlEntryExtensions     Extensions OPTIONAL
+     *                                   -- if present, MUST be v2
+     *                        } OPTIONAL
+     */
+    if( ( ret = x509_get_entries( &p, end, &crl->entry ) ) != 0 )
+    {
+        x509_crl_free( crl );
+        return( ret );
+    }
+
+    /*
+     * crlExtensions          EXPLICIT Extensions OPTIONAL
+     *                              -- if present, MUST be v2
+     */
+    if( crl->version == 2 )
+    {
+        ret = x509_get_crl_ext( &p, end, &crl->crl_ext );
+
+        if( ret != 0 )
+        {
+            x509_crl_free( crl );
+            return( ret );
+        }
+    }
+
+    if( p != end )
+    {
+        x509_crl_free( crl );
+        return( POLARSSL_ERR_X509_INVALID_FORMAT +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+    }
+
+    end = crl->raw.p + crl->raw.len;
+
+    /*
+     *  signatureAlgorithm   AlgorithmIdentifier,
+     *  signatureValue       BIT STRING
+     */
+    if( ( ret = x509_get_alg_null( &p, end, &crl->sig_oid2 ) ) != 0 )
+    {
+        x509_crl_free( crl );
+        return( ret );
+    }
+
+    if( crl->sig_oid1.len != crl->sig_oid2.len ||
+        memcmp( crl->sig_oid1.p, crl->sig_oid2.p, crl->sig_oid1.len ) != 0 )
+    {
+        x509_crl_free( crl );
+        return( POLARSSL_ERR_X509_SIG_MISMATCH );
+    }
+
+    if( ( ret = x509_get_sig( &p, end, &crl->sig ) ) != 0 )
+    {
+        x509_crl_free( crl );
+        return( ret );
+    }
+
+    if( p != end )
+    {
+        x509_crl_free( crl );
+        return( POLARSSL_ERR_X509_INVALID_FORMAT +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+    }
+
+    if( buflen > 0 )
+    {
+        crl->next = (x509_crl *) polarssl_malloc( sizeof( x509_crl ) );
+
+        if( crl->next == NULL )
+        {
+            x509_crl_free( crl );
+            return( POLARSSL_ERR_X509_MALLOC_FAILED );
+        }
+
+        crl = crl->next;
+        x509_crl_init( crl );
+
+        return( x509_crl_parse( crl, buf, buflen ) );
+    }
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * Load one or more CRLs and add them to the chained list
+ */
+int x509_crl_parse_file( x509_crl *chain, const char *path )
+{
+    int ret;
+    size_t n;
+    unsigned char *buf;
+
+    if ( ( ret = x509_load_file( path, &buf, &n ) ) != 0 )
+        return( ret );
+
+    ret = x509_crl_parse( chain, buf, n );
+
+    memset( buf, 0, n + 1 );
+    polarssl_free( buf );
+
+    return( ret );
+}
+#endif /* POLARSSL_FS_IO */
+
+#if defined(_MSC_VER) && !defined snprintf && !defined(EFIX64) && \
+    !defined(EFI32)
+#include <stdarg.h>
+
+#if !defined vsnprintf
+#define vsnprintf _vsnprintf
+#endif // vsnprintf
+
+/*
+ * Windows _snprintf and _vsnprintf are not compatible to linux versions.
+ * Result value is not size of buffer needed, but -1 if no fit is possible.
+ *
+ * This fuction tries to 'fix' this by at least suggesting enlarging the
+ * size by 20.
+ */
+static int compat_snprintf(char *str, size_t size, const char *format, ...)
+{
+    va_list ap;
+    int res = -1;
+
+    va_start( ap, format );
+
+    res = vsnprintf( str, size, format, ap );
+
+    va_end( ap );
+
+    // No quick fix possible
+    if ( res < 0 )
+        return( (int) size + 20 );
+
+    return res;
+}
+
+#define snprintf compat_snprintf
+#endif /* _MSC_VER && !snprintf && !EFIX64 && !EFI32 */
+
+#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL    -2
+
+#define SAFE_SNPRINTF()                         \
+{                                               \
+    if( ret == -1 )                             \
+        return( -1 );                           \
+                                                \
+    if ( (unsigned int) ret > n ) {             \
+        p[n - 1] = '\0';                        \
+        return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\
+    }                                           \
+                                                \
+    n -= (unsigned int) ret;                    \
+    p += (unsigned int) ret;                    \
+}
+
+/*
+ * Return an informational string about the certificate.
+ */
+#define BEFORE_COLON    14
+#define BC              "14"
+/*
+ * Return an informational string about the CRL.
+ */
+int x509_crl_info( char *buf, size_t size, const char *prefix,
+                   const x509_crl *crl )
+{
+    int ret;
+    size_t n;
+    char *p;
+    const char *desc;
+    const x509_crl_entry *entry;
+
+    p = buf;
+    n = size;
+
+    ret = snprintf( p, n, "%sCRL version   : %d",
+                               prefix, crl->version );
+    SAFE_SNPRINTF();
+
+    ret = snprintf( p, n, "\n%sissuer name   : ", prefix );
+    SAFE_SNPRINTF();
+    ret = x509_dn_gets( p, n, &crl->issuer );
+    SAFE_SNPRINTF();
+
+    ret = snprintf( p, n, "\n%sthis update   : " \
+                   "%04d-%02d-%02d %02d:%02d:%02d", prefix,
+                   crl->this_update.year, crl->this_update.mon,
+                   crl->this_update.day,  crl->this_update.hour,
+                   crl->this_update.min,  crl->this_update.sec );
+    SAFE_SNPRINTF();
+
+    ret = snprintf( p, n, "\n%snext update   : " \
+                   "%04d-%02d-%02d %02d:%02d:%02d", prefix,
+                   crl->next_update.year, crl->next_update.mon,
+                   crl->next_update.day,  crl->next_update.hour,
+                   crl->next_update.min,  crl->next_update.sec );
+    SAFE_SNPRINTF();
+
+    entry = &crl->entry;
+
+    ret = snprintf( p, n, "\n%sRevoked certificates:",
+                               prefix );
+    SAFE_SNPRINTF();
+
+    while( entry != NULL && entry->raw.len != 0 )
+    {
+        ret = snprintf( p, n, "\n%sserial number: ",
+                               prefix );
+        SAFE_SNPRINTF();
+
+        ret = x509_serial_gets( p, n, &entry->serial);
+        SAFE_SNPRINTF();
+
+        ret = snprintf( p, n, " revocation date: " \
+                   "%04d-%02d-%02d %02d:%02d:%02d",
+                   entry->revocation_date.year, entry->revocation_date.mon,
+                   entry->revocation_date.day,  entry->revocation_date.hour,
+                   entry->revocation_date.min,  entry->revocation_date.sec );
+        SAFE_SNPRINTF();
+
+        entry = entry->next;
+    }
+
+    ret = snprintf( p, n, "\n%ssigned using  : ", prefix );
+    SAFE_SNPRINTF();
+
+    ret = oid_get_sig_alg_desc( &crl->sig_oid1, &desc );
+    if( ret != 0 )
+        ret = snprintf( p, n, "???"  );
+    else
+        ret = snprintf( p, n, "%s", desc );
+    SAFE_SNPRINTF();
+
+    ret = snprintf( p, n, "\n" );
+    SAFE_SNPRINTF();
+
+    return( (int) ( size - n ) );
+}
+
+/*
+ * Initialize a CRL chain
+ */
+void x509_crl_init( x509_crl *crl )
+{
+    memset( crl, 0, sizeof(x509_crl) );
+}
+
+/*
+ * Unallocate all CRL data
+ */
+void x509_crl_free( x509_crl *crl )
+{
+    x509_crl *crl_cur = crl;
+    x509_crl *crl_prv;
+    x509_name *name_cur;
+    x509_name *name_prv;
+    x509_crl_entry *entry_cur;
+    x509_crl_entry *entry_prv;
+
+    if( crl == NULL )
+        return;
+
+    do
+    {
+        name_cur = crl_cur->issuer.next;
+        while( name_cur != NULL )
+        {
+            name_prv = name_cur;
+            name_cur = name_cur->next;
+            memset( name_prv, 0, sizeof( x509_name ) );
+            polarssl_free( name_prv );
+        }
+
+        entry_cur = crl_cur->entry.next;
+        while( entry_cur != NULL )
+        {
+            entry_prv = entry_cur;
+            entry_cur = entry_cur->next;
+            memset( entry_prv, 0, sizeof( x509_crl_entry ) );
+            polarssl_free( entry_prv );
+        }
+
+        if( crl_cur->raw.p != NULL )
+        {
+            memset( crl_cur->raw.p, 0, crl_cur->raw.len );
+            polarssl_free( crl_cur->raw.p );
+        }
+
+        crl_cur = crl_cur->next;
+    }
+    while( crl_cur != NULL );
+
+    crl_cur = crl;
+    do
+    {
+        crl_prv = crl_cur;
+        crl_cur = crl_cur->next;
+
+        memset( crl_prv, 0, sizeof( x509_crl ) );
+        if( crl_prv != crl )
+            polarssl_free( crl_prv );
+    }
+    while( crl_cur != NULL );
+}
+
+#endif /* POLARSSL_X509_CRL_PARSE_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/x509_crt.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,1981 @@
+/*
+ *  X.509 certificate and private key decoding
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  The ITU-T X.509 standard defines a certificate format for PKI.
+ *
+ *  http://www.ietf.org/rfc/rfc3279.txt
+ *  http://www.ietf.org/rfc/rfc3280.txt
+ *
+ *  ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc
+ *
+ *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
+ *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+
+#include "polarssl/x509_crt.h"
+#include "polarssl/oid.h"
+#if defined(POLARSSL_PEM_PARSE_C)
+#include "polarssl/pem.h"
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+#if defined(POLARSSL_THREADING_C)
+#include "polarssl/threading.h"
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
+#include <windows.h>
+#else
+#include <time.h>
+#endif
+
+#if defined(EFIX64) || defined(EFI32)
+#include <stdio.h>
+#endif
+
+#if defined(POLARSSL_FS_IO)
+#include <stdio.h>
+#if !defined(_WIN32) || defined(EFIX64) || defined(EFI32)
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#endif
+#endif
+
+/*
+ *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
+ */
+static int x509_get_version( unsigned char **p,
+                             const unsigned char *end,
+                             int *ver )
+{
+    int ret;
+    size_t len;
+
+    if( ( ret = asn1_get_tag( p, end, &len,
+            ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) != 0 )
+    {
+        if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+        {
+            *ver = 0;
+            return( 0 );
+        }
+
+        return( ret );
+    }
+
+    end = *p + len;
+
+    if( ( ret = asn1_get_int( p, end, ver ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_VERSION + ret );
+
+    if( *p != end )
+        return( POLARSSL_ERR_X509_INVALID_VERSION +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    return( 0 );
+}
+
+/*
+ *  Validity ::= SEQUENCE {
+ *       notBefore      Time,
+ *       notAfter       Time }
+ */
+static int x509_get_dates( unsigned char **p,
+                           const unsigned char *end,
+                           x509_time *from,
+                           x509_time *to )
+{
+    int ret;
+    size_t len;
+
+    if( ( ret = asn1_get_tag( p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_DATE + ret );
+
+    end = *p + len;
+
+    if( ( ret = x509_get_time( p, end, from ) ) != 0 )
+        return( ret );
+
+    if( ( ret = x509_get_time( p, end, to ) ) != 0 )
+        return( ret );
+
+    if( *p != end )
+        return( POLARSSL_ERR_X509_INVALID_DATE +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    return( 0 );
+}
+
+/*
+ * X.509 v2/v3 unique identifier (not parsed)
+ */
+static int x509_get_uid( unsigned char **p,
+                         const unsigned char *end,
+                         x509_buf *uid, int n )
+{
+    int ret;
+
+    if( *p == end )
+        return( 0 );
+
+    uid->tag = **p;
+
+    if( ( ret = asn1_get_tag( p, end, &uid->len,
+            ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | n ) ) != 0 )
+    {
+        if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+            return( 0 );
+
+        return( ret );
+    }
+
+    uid->p = *p;
+    *p += uid->len;
+
+    return( 0 );
+}
+
+static int x509_get_basic_constraints( unsigned char **p,
+                                       const unsigned char *end,
+                                       int *ca_istrue,
+                                       int *max_pathlen )
+{
+    int ret;
+    size_t len;
+
+    /*
+     * BasicConstraints ::= SEQUENCE {
+     *      cA                      BOOLEAN DEFAULT FALSE,
+     *      pathLenConstraint       INTEGER (0..MAX) OPTIONAL }
+     */
+    *ca_istrue = 0; /* DEFAULT FALSE */
+    *max_pathlen = 0; /* endless */
+
+    if( ( ret = asn1_get_tag( p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
+
+    if( *p == end )
+        return 0;
+
+    if( ( ret = asn1_get_bool( p, end, ca_istrue ) ) != 0 )
+    {
+        if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+            ret = asn1_get_int( p, end, ca_istrue );
+
+        if( ret != 0 )
+            return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
+
+        if( *ca_istrue != 0 )
+            *ca_istrue = 1;
+    }
+
+    if( *p == end )
+        return 0;
+
+    if( ( ret = asn1_get_int( p, end, max_pathlen ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
+
+    if( *p != end )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    (*max_pathlen)++;
+
+    return 0;
+}
+
+static int x509_get_ns_cert_type( unsigned char **p,
+                                       const unsigned char *end,
+                                       unsigned char *ns_cert_type)
+{
+    int ret;
+    x509_bitstring bs = { 0, 0, NULL };
+
+    if( ( ret = asn1_get_bitstring( p, end, &bs ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
+
+    if( bs.len != 1 )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                POLARSSL_ERR_ASN1_INVALID_LENGTH );
+
+    /* Get actual bitstring */
+    *ns_cert_type = *bs.p;
+    return 0;
+}
+
+static int x509_get_key_usage( unsigned char **p,
+                               const unsigned char *end,
+                               unsigned char *key_usage)
+{
+    int ret;
+    x509_bitstring bs = { 0, 0, NULL };
+
+    if( ( ret = asn1_get_bitstring( p, end, &bs ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
+
+    if( bs.len < 1 )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                POLARSSL_ERR_ASN1_INVALID_LENGTH );
+
+    /* Get actual bitstring */
+    *key_usage = *bs.p;
+    return 0;
+}
+
+/*
+ * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
+ *
+ * KeyPurposeId ::= OBJECT IDENTIFIER
+ */
+static int x509_get_ext_key_usage( unsigned char **p,
+                               const unsigned char *end,
+                               x509_sequence *ext_key_usage)
+{
+    int ret;
+
+    if( ( ret = asn1_get_sequence_of( p, end, ext_key_usage, ASN1_OID ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
+
+    /* Sequence length must be >= 1 */
+    if( ext_key_usage->buf.p == NULL )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                POLARSSL_ERR_ASN1_INVALID_LENGTH );
+
+    return 0;
+}
+
+/*
+ * SubjectAltName ::= GeneralNames
+ *
+ * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
+ *
+ * GeneralName ::= CHOICE {
+ *      otherName                       [0]     OtherName,
+ *      rfc822Name                      [1]     IA5String,
+ *      dNSName                         [2]     IA5String,
+ *      x400Address                     [3]     ORAddress,
+ *      directoryName                   [4]     Name,
+ *      ediPartyName                    [5]     EDIPartyName,
+ *      uniformResourceIdentifier       [6]     IA5String,
+ *      iPAddress                       [7]     OCTET STRING,
+ *      registeredID                    [8]     OBJECT IDENTIFIER }
+ *
+ * OtherName ::= SEQUENCE {
+ *      type-id    OBJECT IDENTIFIER,
+ *      value      [0] EXPLICIT ANY DEFINED BY type-id }
+ *
+ * EDIPartyName ::= SEQUENCE {
+ *      nameAssigner            [0]     DirectoryString OPTIONAL,
+ *      partyName               [1]     DirectoryString }
+ *
+ * NOTE: PolarSSL only parses and uses dNSName at this point.
+ */
+static int x509_get_subject_alt_name( unsigned char **p,
+                                      const unsigned char *end,
+                                      x509_sequence *subject_alt_name )
+{
+    int ret;
+    size_t len, tag_len;
+    asn1_buf *buf;
+    unsigned char tag;
+    asn1_sequence *cur = subject_alt_name;
+
+    /* Get main sequence tag */
+    if( ( ret = asn1_get_tag( p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
+
+    if( *p + len != end )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    while( *p < end )
+    {
+        if( ( end - *p ) < 1 )
+            return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                    POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+        tag = **p;
+        (*p)++;
+        if( ( ret = asn1_get_len( p, end, &tag_len ) ) != 0 )
+            return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
+
+        if( ( tag & ASN1_CONTEXT_SPECIFIC ) != ASN1_CONTEXT_SPECIFIC )
+            return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                    POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
+
+        /* Skip everything but DNS name */
+        if( tag != ( ASN1_CONTEXT_SPECIFIC | 2 ) )
+        {
+            *p += tag_len;
+            continue;
+        }
+
+        /* Allocate and assign next pointer */
+        if( cur->buf.p != NULL )
+        {
+            cur->next = (asn1_sequence *) polarssl_malloc(
+                 sizeof( asn1_sequence ) );
+
+            if( cur->next == NULL )
+                return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                        POLARSSL_ERR_ASN1_MALLOC_FAILED );
+
+            memset( cur->next, 0, sizeof( asn1_sequence ) );
+            cur = cur->next;
+        }
+
+        buf = &(cur->buf);
+        buf->tag = tag;
+        buf->p = *p;
+        buf->len = tag_len;
+        *p += buf->len;
+    }
+
+    /* Set final sequence entry's next pointer to NULL */
+    cur->next = NULL;
+
+    if( *p != end )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    return( 0 );
+}
+
+/*
+ * X.509 v3 extensions
+ *
+ * TODO: Perform all of the basic constraints tests required by the RFC
+ * TODO: Set values for undetected extensions to a sane default?
+ *
+ */
+static int x509_get_crt_ext( unsigned char **p,
+                             const unsigned char *end,
+                             x509_crt *crt )
+{
+    int ret;
+    size_t len;
+    unsigned char *end_ext_data, *end_ext_octet;
+
+    if( ( ret = x509_get_ext( p, end, &crt->v3_ext, 3 ) ) != 0 )
+    {
+        if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+            return( 0 );
+
+        return( ret );
+    }
+
+    while( *p < end )
+    {
+        /*
+         * Extension  ::=  SEQUENCE  {
+         *      extnID      OBJECT IDENTIFIER,
+         *      critical    BOOLEAN DEFAULT FALSE,
+         *      extnValue   OCTET STRING  }
+         */
+        x509_buf extn_oid = {0, 0, NULL};
+        int is_critical = 0; /* DEFAULT FALSE */
+        int ext_type = 0;
+
+        if( ( ret = asn1_get_tag( p, end, &len,
+                ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+            return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
+
+        end_ext_data = *p + len;
+
+        /* Get extension ID */
+        extn_oid.tag = **p;
+
+        if( ( ret = asn1_get_tag( p, end, &extn_oid.len, ASN1_OID ) ) != 0 )
+            return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
+
+        extn_oid.p = *p;
+        *p += extn_oid.len;
+
+        if( ( end - *p ) < 1 )
+            return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                    POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+        /* Get optional critical */
+        if( ( ret = asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 &&
+            ( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) )
+            return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
+
+        /* Data should be octet string type */
+        if( ( ret = asn1_get_tag( p, end_ext_data, &len,
+                ASN1_OCTET_STRING ) ) != 0 )
+            return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
+
+        end_ext_octet = *p + len;
+
+        if( end_ext_octet != end_ext_data )
+            return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                    POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+        /*
+         * Detect supported extensions
+         */
+        ret = oid_get_x509_ext_type( &extn_oid, &ext_type );
+
+        if( ret != 0 )
+        {
+            /* No parser found, skip extension */
+            *p = end_ext_octet;
+
+#if !defined(POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
+            if( is_critical )
+            {
+                /* Data is marked as critical: fail */
+                return ( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                        POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
+            }
+#endif
+            continue;
+        }
+
+        crt->ext_types |= ext_type;
+
+        switch( ext_type )
+        {
+        case EXT_BASIC_CONSTRAINTS:
+            /* Parse basic constraints */
+            if( ( ret = x509_get_basic_constraints( p, end_ext_octet,
+                    &crt->ca_istrue, &crt->max_pathlen ) ) != 0 )
+                return ( ret );
+            break;
+
+        case EXT_KEY_USAGE:
+            /* Parse key usage */
+            if( ( ret = x509_get_key_usage( p, end_ext_octet,
+                    &crt->key_usage ) ) != 0 )
+                return ( ret );
+            break;
+
+        case EXT_EXTENDED_KEY_USAGE:
+            /* Parse extended key usage */
+            if( ( ret = x509_get_ext_key_usage( p, end_ext_octet,
+                    &crt->ext_key_usage ) ) != 0 )
+                return ( ret );
+            break;
+
+        case EXT_SUBJECT_ALT_NAME:
+            /* Parse subject alt name */
+            if( ( ret = x509_get_subject_alt_name( p, end_ext_octet,
+                    &crt->subject_alt_names ) ) != 0 )
+                return ( ret );
+            break;
+
+        case EXT_NS_CERT_TYPE:
+            /* Parse netscape certificate type */
+            if( ( ret = x509_get_ns_cert_type( p, end_ext_octet,
+                    &crt->ns_cert_type ) ) != 0 )
+                return ( ret );
+            break;
+
+        default:
+            return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
+        }
+    }
+
+    if( *p != end )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    return( 0 );
+}
+
+/*
+ * Parse and fill a single X.509 certificate in DER format
+ */
+static int x509_crt_parse_der_core( x509_crt *crt, const unsigned char *buf,
+                                    size_t buflen )
+{
+    int ret;
+    size_t len;
+    unsigned char *p, *end, *crt_end;
+
+    /*
+     * Check for valid input
+     */
+    if( crt == NULL || buf == NULL )
+        return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
+
+    p = (unsigned char *) polarssl_malloc( len = buflen );
+
+    if( p == NULL )
+        return( POLARSSL_ERR_X509_MALLOC_FAILED );
+
+    memcpy( p, buf, buflen );
+
+    crt->raw.p = p;
+    crt->raw.len = len;
+    end = p + len;
+
+    /*
+     * Certificate  ::=  SEQUENCE  {
+     *      tbsCertificate       TBSCertificate,
+     *      signatureAlgorithm   AlgorithmIdentifier,
+     *      signatureValue       BIT STRING  }
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        x509_crt_free( crt );
+        return( POLARSSL_ERR_X509_INVALID_FORMAT );
+    }
+
+    if( len > (size_t) ( end - p ) )
+    {
+        x509_crt_free( crt );
+        return( POLARSSL_ERR_X509_INVALID_FORMAT +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+    }
+    crt_end = p + len;
+
+    /*
+     * TBSCertificate  ::=  SEQUENCE  {
+     */
+    crt->tbs.p = p;
+
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        x509_crt_free( crt );
+        return( POLARSSL_ERR_X509_INVALID_FORMAT + ret );
+    }
+
+    end = p + len;
+    crt->tbs.len = end - crt->tbs.p;
+
+    /*
+     * Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
+     *
+     * CertificateSerialNumber  ::=  INTEGER
+     *
+     * signature            AlgorithmIdentifier
+     */
+    if( ( ret = x509_get_version(  &p, end, &crt->version  ) ) != 0 ||
+        ( ret = x509_get_serial(   &p, end, &crt->serial   ) ) != 0 ||
+        ( ret = x509_get_alg_null( &p, end, &crt->sig_oid1 ) ) != 0 )
+    {
+        x509_crt_free( crt );
+        return( ret );
+    }
+
+    crt->version++;
+
+    if( crt->version > 3 )
+    {
+        x509_crt_free( crt );
+        return( POLARSSL_ERR_X509_UNKNOWN_VERSION );
+    }
+
+    if( ( ret = x509_get_sig_alg( &crt->sig_oid1, &crt->sig_md,
+                                  &crt->sig_pk ) ) != 0 )
+    {
+        x509_crt_free( crt );
+        return( ret );
+    }
+
+    /*
+     * issuer               Name
+     */
+    crt->issuer_raw.p = p;
+
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        x509_crt_free( crt );
+        return( POLARSSL_ERR_X509_INVALID_FORMAT + ret );
+    }
+
+    if( ( ret = x509_get_name( &p, p + len, &crt->issuer ) ) != 0 )
+    {
+        x509_crt_free( crt );
+        return( ret );
+    }
+
+    crt->issuer_raw.len = p - crt->issuer_raw.p;
+
+    /*
+     * Validity ::= SEQUENCE {
+     *      notBefore      Time,
+     *      notAfter       Time }
+     *
+     */
+    if( ( ret = x509_get_dates( &p, end, &crt->valid_from,
+                                         &crt->valid_to ) ) != 0 )
+    {
+        x509_crt_free( crt );
+        return( ret );
+    }
+
+    /*
+     * subject              Name
+     */
+    crt->subject_raw.p = p;
+
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        x509_crt_free( crt );
+        return( POLARSSL_ERR_X509_INVALID_FORMAT + ret );
+    }
+
+    if( len && ( ret = x509_get_name( &p, p + len, &crt->subject ) ) != 0 )
+    {
+        x509_crt_free( crt );
+        return( ret );
+    }
+
+    crt->subject_raw.len = p - crt->subject_raw.p;
+
+    /*
+     * SubjectPublicKeyInfo
+     */
+    if( ( ret = pk_parse_subpubkey( &p, end, &crt->pk ) ) != 0 )
+    {
+        x509_crt_free( crt );
+        return( ret );
+    }
+
+    /*
+     *  issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
+     *                       -- If present, version shall be v2 or v3
+     *  subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
+     *                       -- If present, version shall be v2 or v3
+     *  extensions      [3]  EXPLICIT Extensions OPTIONAL
+     *                       -- If present, version shall be v3
+     */
+    if( crt->version == 2 || crt->version == 3 )
+    {
+        ret = x509_get_uid( &p, end, &crt->issuer_id,  1 );
+        if( ret != 0 )
+        {
+            x509_crt_free( crt );
+            return( ret );
+        }
+    }
+
+    if( crt->version == 2 || crt->version == 3 )
+    {
+        ret = x509_get_uid( &p, end, &crt->subject_id,  2 );
+        if( ret != 0 )
+        {
+            x509_crt_free( crt );
+            return( ret );
+        }
+    }
+
+#if !defined(POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3)
+    if( crt->version == 3 )
+    {
+#endif
+        ret = x509_get_crt_ext( &p, end, crt);
+        if( ret != 0 )
+        {
+            x509_crt_free( crt );
+            return( ret );
+        }
+#if !defined(POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3)
+    }
+#endif
+
+    if( p != end )
+    {
+        x509_crt_free( crt );
+        return( POLARSSL_ERR_X509_INVALID_FORMAT +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+    }
+
+    end = crt_end;
+
+    /*
+     *  }
+     *  -- end of TBSCertificate
+     *
+     *  signatureAlgorithm   AlgorithmIdentifier,
+     *  signatureValue       BIT STRING
+     */
+    if( ( ret = x509_get_alg_null( &p, end, &crt->sig_oid2 ) ) != 0 )
+    {
+        x509_crt_free( crt );
+        return( ret );
+    }
+
+    if( crt->sig_oid1.len != crt->sig_oid2.len ||
+        memcmp( crt->sig_oid1.p, crt->sig_oid2.p, crt->sig_oid1.len ) != 0 )
+    {
+        x509_crt_free( crt );
+        return( POLARSSL_ERR_X509_SIG_MISMATCH );
+    }
+
+    if( ( ret = x509_get_sig( &p, end, &crt->sig ) ) != 0 )
+    {
+        x509_crt_free( crt );
+        return( ret );
+    }
+
+    if( p != end )
+    {
+        x509_crt_free( crt );
+        return( POLARSSL_ERR_X509_INVALID_FORMAT +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+    }
+
+    return( 0 );
+}
+
+/*
+ * Parse one X.509 certificate in DER format from a buffer and add them to a
+ * chained list
+ */
+int x509_crt_parse_der( x509_crt *chain, const unsigned char *buf,
+                        size_t buflen )
+{
+    int ret;
+    x509_crt *crt = chain, *prev = NULL;
+
+    /*
+     * Check for valid input
+     */
+    if( crt == NULL || buf == NULL )
+        return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
+
+    while( crt->version != 0 && crt->next != NULL )
+    {
+        prev = crt;
+        crt = crt->next;
+    }
+
+    /*
+     * Add new certificate on the end of the chain if needed.
+     */
+    if ( crt->version != 0 && crt->next == NULL)
+    {
+        crt->next = (x509_crt *) polarssl_malloc( sizeof( x509_crt ) );
+
+        if( crt->next == NULL )
+            return( POLARSSL_ERR_X509_MALLOC_FAILED );
+
+        prev = crt;
+        crt = crt->next;
+        x509_crt_init( crt );
+    }
+
+    if( ( ret = x509_crt_parse_der_core( crt, buf, buflen ) ) != 0 )
+    {
+        if( prev )
+            prev->next = NULL;
+
+        if( crt != chain )
+            polarssl_free( crt );
+
+        return( ret );
+    }
+
+    return( 0 );
+}
+
+/*
+ * Parse one or more PEM certificates from a buffer and add them to the chained
+ * list
+ */
+int x509_crt_parse( x509_crt *chain, const unsigned char *buf, size_t buflen )
+{
+    int success = 0, first_error = 0, total_failed = 0;
+    int buf_format = X509_FORMAT_DER;
+
+    /*
+     * Check for valid input
+     */
+    if( chain == NULL || buf == NULL )
+        return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
+
+    /*
+     * Determine buffer content. Buffer contains either one DER certificate or
+     * one or more PEM certificates.
+     */
+#if defined(POLARSSL_PEM_PARSE_C)
+    if( strstr( (const char *) buf, "-----BEGIN CERTIFICATE-----" ) != NULL )
+        buf_format = X509_FORMAT_PEM;
+#endif
+
+    if( buf_format == X509_FORMAT_DER )
+        return x509_crt_parse_der( chain, buf, buflen );
+
+#if defined(POLARSSL_PEM_PARSE_C)
+    if( buf_format == X509_FORMAT_PEM )
+    {
+        int ret;
+        pem_context pem;
+
+        while( buflen > 0 )
+        {
+            size_t use_len;
+            pem_init( &pem );
+
+            ret = pem_read_buffer( &pem,
+                           "-----BEGIN CERTIFICATE-----",
+                           "-----END CERTIFICATE-----",
+                           buf, NULL, 0, &use_len );
+
+            if( ret == 0 )
+            {
+                /*
+                 * Was PEM encoded
+                 */
+                buflen -= use_len;
+                buf += use_len;
+            }
+            else if( ret == POLARSSL_ERR_PEM_BAD_INPUT_DATA )
+            {
+                return( ret );
+            }
+            else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
+            {
+                pem_free( &pem );
+
+                /*
+                 * PEM header and footer were found
+                 */
+                buflen -= use_len;
+                buf += use_len;
+
+                if( first_error == 0 )
+                    first_error = ret;
+
+                continue;
+            }
+            else
+                break;
+
+            ret = x509_crt_parse_der( chain, pem.buf, pem.buflen );
+
+            pem_free( &pem );
+
+            if( ret != 0 )
+            {
+                /*
+                 * Quit parsing on a memory error
+                 */
+                if( ret == POLARSSL_ERR_X509_MALLOC_FAILED )
+                    return( ret );
+
+                if( first_error == 0 )
+                    first_error = ret;
+
+                total_failed++;
+                continue;
+            }
+
+            success = 1;
+        }
+    }
+#endif /* POLARSSL_PEM_PARSE_C */
+
+    if( success )
+        return( total_failed );
+    else if( first_error )
+        return( first_error );
+    else
+        return( POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * Load one or more certificates and add them to the chained list
+ */
+int x509_crt_parse_file( x509_crt *chain, const char *path )
+{
+    int ret;
+    size_t n;
+    unsigned char *buf;
+
+    if ( ( ret = x509_load_file( path, &buf, &n ) ) != 0 )
+        return( ret );
+
+    ret = x509_crt_parse( chain, buf, n );
+
+    memset( buf, 0, n + 1 );
+    polarssl_free( buf );
+
+    return( ret );
+}
+
+#if defined(POLARSSL_THREADING_PTHREAD)
+static threading_mutex_t readdir_mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+int x509_crt_parse_path( x509_crt *chain, const char *path )
+{
+    int ret = 0;
+#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
+    int w_ret;
+    WCHAR szDir[MAX_PATH];
+    char filename[MAX_PATH];
+    char *p;
+    int len = (int) strlen( path );
+
+    WIN32_FIND_DATAW file_data;
+    HANDLE hFind;
+
+    if( len > MAX_PATH - 3 )
+        return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
+
+    memset( szDir, 0, sizeof(szDir) );
+    memset( filename, 0, MAX_PATH );
+    memcpy( filename, path, len );
+    filename[len++] = '\\';
+    p = filename + len;
+    filename[len++] = '*';
+
+    w_ret = MultiByteToWideChar( CP_ACP, 0, filename, len, szDir,
+                                 MAX_PATH - 3 );
+
+    hFind = FindFirstFileW( szDir, &file_data );
+    if (hFind == INVALID_HANDLE_VALUE)
+        return( POLARSSL_ERR_X509_FILE_IO_ERROR );
+
+    len = MAX_PATH - len;
+    do
+    {
+        memset( p, 0, len );
+
+        if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
+            continue;
+
+        w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName,
+                                     lstrlenW(file_data.cFileName),
+                                     p, len - 1,
+                                     NULL, NULL );
+
+        w_ret = x509_crt_parse_file( chain, filename );
+        if( w_ret < 0 )
+            ret++;
+        else
+            ret += w_ret;
+    }
+    while( FindNextFileW( hFind, &file_data ) != 0 );
+
+    if (GetLastError() != ERROR_NO_MORE_FILES)
+        ret = POLARSSL_ERR_X509_FILE_IO_ERROR;
+
+    FindClose( hFind );
+#else /* _WIN32 */
+    int t_ret;
+    struct stat sb;
+    struct dirent *entry;
+    char entry_name[255];
+    DIR *dir = opendir( path );
+
+    if( dir == NULL)
+        return( POLARSSL_ERR_X509_FILE_IO_ERROR );
+
+#if defined(POLARSSL_THREADING_PTHREAD)
+    if( ( ret = polarssl_mutex_lock( &readdir_mutex ) ) != 0 )
+        return( ret );
+#endif
+
+    while( ( entry = readdir( dir ) ) != NULL )
+    {
+        snprintf( entry_name, sizeof entry_name, "%s/%s", path, entry->d_name );
+
+        if( stat( entry_name, &sb ) == -1 )
+        {
+            closedir( dir );
+            ret = POLARSSL_ERR_X509_FILE_IO_ERROR;
+            goto cleanup;
+        }
+
+        if( !S_ISREG( sb.st_mode ) )
+            continue;
+
+        // Ignore parse errors
+        //
+        t_ret = x509_crt_parse_file( chain, entry_name );
+        if( t_ret < 0 )
+            ret++;
+        else
+            ret += t_ret;
+    }
+    closedir( dir );
+
+cleanup:
+#if defined(POLARSSL_THREADING_PTHREAD)
+    if( polarssl_mutex_unlock( &readdir_mutex ) != 0 )
+        ret = POLARSSL_ERR_THREADING_MUTEX_ERROR;
+#endif
+
+#endif /* _WIN32 */
+
+    return( ret );
+}
+#endif /* POLARSSL_FS_IO */
+
+#if defined(_MSC_VER) && !defined snprintf && !defined(EFIX64) && \
+    !defined(EFI32)
+#include <stdarg.h>
+
+#if !defined vsnprintf
+#define vsnprintf _vsnprintf
+#endif // vsnprintf
+
+/*
+ * Windows _snprintf and _vsnprintf are not compatible to linux versions.
+ * Result value is not size of buffer needed, but -1 if no fit is possible.
+ *
+ * This fuction tries to 'fix' this by at least suggesting enlarging the
+ * size by 20.
+ */
+static int compat_snprintf(char *str, size_t size, const char *format, ...)
+{
+    va_list ap;
+    int res = -1;
+
+    va_start( ap, format );
+
+    res = vsnprintf( str, size, format, ap );
+
+    va_end( ap );
+
+    // No quick fix possible
+    if ( res < 0 )
+        return( (int) size + 20 );
+
+    return res;
+}
+
+#define snprintf compat_snprintf
+#endif /* _MSC_VER  && !snprintf && !EFIX64 && !EFI32 */
+
+#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL    -2
+
+#define SAFE_SNPRINTF()                         \
+{                                               \
+    if( ret == -1 )                             \
+        return( -1 );                           \
+                                                \
+    if ( (unsigned int) ret > n ) {             \
+        p[n - 1] = '\0';                        \
+        return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\
+    }                                           \
+                                                \
+    n -= (unsigned int) ret;                    \
+    p += (unsigned int) ret;                    \
+}
+
+static int x509_info_subject_alt_name( char **buf, size_t *size,
+                                       const x509_sequence *subject_alt_name )
+{
+    size_t i;
+    size_t n = *size;
+    char *p = *buf;
+    const x509_sequence *cur = subject_alt_name;
+    const char *sep = "";
+    size_t sep_len = 0;
+
+    while( cur != NULL )
+    {
+        if( cur->buf.len + sep_len >= n )
+        {
+            *p = '\0';
+            return( POLARSSL_ERR_DEBUG_BUF_TOO_SMALL );
+        }
+
+        n -= cur->buf.len + sep_len;
+        for( i = 0; i < sep_len; i++ )
+            *p++ = sep[i];
+        for( i = 0; i < cur->buf.len; i++ )
+            *p++ = cur->buf.p[i];
+
+        sep = ", ";
+        sep_len = 2;
+
+        cur = cur->next;
+    }
+
+    *p = '\0';
+
+    *size = n;
+    *buf = p;
+
+    return( 0 );
+}
+
+#define PRINT_ITEM(i)                           \
+    {                                           \
+        ret = snprintf( p, n, "%s" i, sep );    \
+        SAFE_SNPRINTF();                        \
+        sep = ", ";                             \
+    }
+
+#define CERT_TYPE(type,name)                    \
+    if( ns_cert_type & type )                   \
+        PRINT_ITEM( name );
+
+static int x509_info_cert_type( char **buf, size_t *size,
+                                unsigned char ns_cert_type )
+{
+    int ret;
+    size_t n = *size;
+    char *p = *buf;
+    const char *sep = "";
+
+    CERT_TYPE( NS_CERT_TYPE_SSL_CLIENT,         "SSL Client" );
+    CERT_TYPE( NS_CERT_TYPE_SSL_SERVER,         "SSL Server" );
+    CERT_TYPE( NS_CERT_TYPE_EMAIL,              "Email" );
+    CERT_TYPE( NS_CERT_TYPE_OBJECT_SIGNING,     "Object Signing" );
+    CERT_TYPE( NS_CERT_TYPE_RESERVED,           "Reserved" );
+    CERT_TYPE( NS_CERT_TYPE_SSL_CA,             "SSL CA" );
+    CERT_TYPE( NS_CERT_TYPE_EMAIL_CA,           "Email CA" );
+    CERT_TYPE( NS_CERT_TYPE_OBJECT_SIGNING_CA,  "Object Signing CA" );
+
+    *size = n;
+    *buf = p;
+
+    return( 0 );
+}
+
+#define KEY_USAGE(code,name)    \
+    if( key_usage & code )      \
+        PRINT_ITEM( name );
+
+static int x509_info_key_usage( char **buf, size_t *size,
+                                unsigned char key_usage )
+{
+    int ret;
+    size_t n = *size;
+    char *p = *buf;
+    const char *sep = "";
+
+    KEY_USAGE( KU_DIGITAL_SIGNATURE,    "Digital Signature" );
+    KEY_USAGE( KU_NON_REPUDIATION,      "Non Repudiation" );
+    KEY_USAGE( KU_KEY_ENCIPHERMENT,     "Key Encipherment" );
+    KEY_USAGE( KU_DATA_ENCIPHERMENT,    "Data Encipherment" );
+    KEY_USAGE( KU_KEY_AGREEMENT,        "Key Agreement" );
+    KEY_USAGE( KU_KEY_CERT_SIGN,        "Key Cert Sign" );
+    KEY_USAGE( KU_CRL_SIGN,             "CRL Sign" );
+
+    *size = n;
+    *buf = p;
+
+    return( 0 );
+}
+
+static int x509_info_ext_key_usage( char **buf, size_t *size,
+                                    const x509_sequence *extended_key_usage )
+{
+    int ret;
+    const char *desc;
+    size_t n = *size;
+    char *p = *buf;
+    const x509_sequence *cur = extended_key_usage;
+    const char *sep = "";
+
+    while( cur != NULL )
+    {
+        if( oid_get_extended_key_usage( &cur->buf, &desc ) != 0 )
+            desc = "???";
+
+        ret = snprintf( p, n, "%s%s", sep, desc );
+        SAFE_SNPRINTF();
+
+        sep = ", ";
+
+        cur = cur->next;
+    }
+
+    *size = n;
+    *buf = p;
+
+    return( 0 );
+}
+
+/*
+ * Return an informational string about the certificate.
+ */
+#define BEFORE_COLON    18
+#define BC              "18"
+int x509_crt_info( char *buf, size_t size, const char *prefix,
+                   const x509_crt *crt )
+{
+    int ret;
+    size_t n;
+    char *p;
+    const char *desc = NULL;
+    char key_size_str[BEFORE_COLON];
+
+    p = buf;
+    n = size;
+
+    ret = snprintf( p, n, "%scert. version     : %d\n",
+                               prefix, crt->version );
+    SAFE_SNPRINTF();
+    ret = snprintf( p, n, "%sserial number     : ",
+                               prefix );
+    SAFE_SNPRINTF();
+
+    ret = x509_serial_gets( p, n, &crt->serial);
+    SAFE_SNPRINTF();
+
+    ret = snprintf( p, n, "\n%sissuer name       : ", prefix );
+    SAFE_SNPRINTF();
+    ret = x509_dn_gets( p, n, &crt->issuer  );
+    SAFE_SNPRINTF();
+
+    ret = snprintf( p, n, "\n%ssubject name      : ", prefix );
+    SAFE_SNPRINTF();
+    ret = x509_dn_gets( p, n, &crt->subject );
+    SAFE_SNPRINTF();
+
+    ret = snprintf( p, n, "\n%sissued  on        : " \
+                   "%04d-%02d-%02d %02d:%02d:%02d", prefix,
+                   crt->valid_from.year, crt->valid_from.mon,
+                   crt->valid_from.day,  crt->valid_from.hour,
+                   crt->valid_from.min,  crt->valid_from.sec );
+    SAFE_SNPRINTF();
+
+    ret = snprintf( p, n, "\n%sexpires on        : " \
+                   "%04d-%02d-%02d %02d:%02d:%02d", prefix,
+                   crt->valid_to.year, crt->valid_to.mon,
+                   crt->valid_to.day,  crt->valid_to.hour,
+                   crt->valid_to.min,  crt->valid_to.sec );
+    SAFE_SNPRINTF();
+
+    ret = snprintf( p, n, "\n%ssigned using      : ", prefix );
+    SAFE_SNPRINTF();
+
+    ret = oid_get_sig_alg_desc( &crt->sig_oid1, &desc );
+    if( ret != 0 )
+        ret = snprintf( p, n, "???"  );
+    else
+        ret = snprintf( p, n, "%s", desc );
+    SAFE_SNPRINTF();
+
+    /* Key size */
+    if( ( ret = x509_key_size_helper( key_size_str, BEFORE_COLON,
+                                      pk_get_name( &crt->pk ) ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    ret = snprintf( p, n, "\n%s%-" BC "s: %d bits", prefix, key_size_str,
+                          (int) pk_get_size( &crt->pk ) );
+    SAFE_SNPRINTF();
+
+    /*
+     * Optional extensions
+     */
+
+    if( crt->ext_types & EXT_BASIC_CONSTRAINTS )
+    {
+        ret = snprintf( p, n, "\n%sbasic constraints : CA=%s", prefix,
+                        crt->ca_istrue ? "true" : "false" );
+        SAFE_SNPRINTF();
+
+        if( crt->max_pathlen > 0 )
+        {
+            ret = snprintf( p, n, ", max_pathlen=%d", crt->max_pathlen - 1 );
+            SAFE_SNPRINTF();
+        }
+    }
+
+    if( crt->ext_types & EXT_SUBJECT_ALT_NAME )
+    {
+        ret = snprintf( p, n, "\n%ssubject alt name  : ", prefix );
+        SAFE_SNPRINTF();
+
+        if( ( ret = x509_info_subject_alt_name( &p, &n,
+                                            &crt->subject_alt_names ) ) != 0 )
+            return( ret );
+    }
+
+    if( crt->ext_types & EXT_NS_CERT_TYPE )
+    {
+        ret = snprintf( p, n, "\n%scert. type        : ", prefix );
+        SAFE_SNPRINTF();
+
+        if( ( ret = x509_info_cert_type( &p, &n, crt->ns_cert_type ) ) != 0 )
+            return( ret );
+    }
+
+    if( crt->ext_types & EXT_KEY_USAGE )
+    {
+        ret = snprintf( p, n, "\n%skey usage         : ", prefix );
+        SAFE_SNPRINTF();
+
+        if( ( ret = x509_info_key_usage( &p, &n, crt->key_usage ) ) != 0 )
+            return( ret );
+    }
+
+    if( crt->ext_types & EXT_EXTENDED_KEY_USAGE )
+    {
+        ret = snprintf( p, n, "\n%sext key usage     : ", prefix );
+        SAFE_SNPRINTF();
+
+        if( ( ret = x509_info_ext_key_usage( &p, &n,
+                                             &crt->ext_key_usage ) ) != 0 )
+            return( ret );
+    }
+
+    ret = snprintf( p, n, "\n" );
+    SAFE_SNPRINTF();
+
+    return( (int) ( size - n ) );
+}
+
+#if defined(POLARSSL_X509_CHECK_KEY_USAGE)
+int x509_crt_check_key_usage( const x509_crt *crt, int usage )
+{
+    if( ( crt->ext_types & EXT_KEY_USAGE ) != 0 &&
+        ( crt->key_usage & usage ) != usage )
+        return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
+
+    return( 0 );
+}
+#endif
+
+#if defined(POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE)
+int x509_crt_check_extended_key_usage( const x509_crt *crt,
+                                       const char *usage_oid,
+                                       size_t usage_len )
+{
+    const x509_sequence *cur;
+
+    /* Extension is not mandatory, absent means no restriction */
+    if( ( crt->ext_types & EXT_EXTENDED_KEY_USAGE ) == 0 )
+        return( 0 );
+
+    /*
+     * Look for the requested usage (or wildcard ANY) in our list
+     */
+    for( cur = &crt->ext_key_usage; cur != NULL; cur = cur->next )
+    {
+        const x509_buf *cur_oid = &cur->buf;
+
+        if( cur_oid->len == usage_len &&
+            memcmp( cur_oid->p, usage_oid, usage_len ) == 0 )
+        {
+            return( 0 );
+        }
+
+        if( OID_CMP( OID_ANY_EXTENDED_KEY_USAGE, cur_oid ) )
+            return( 0 );
+    }
+
+    return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
+}
+#endif /* POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE */
+
+#if defined(POLARSSL_X509_CRL_PARSE_C)
+/*
+ * Return 1 if the certificate is revoked, or 0 otherwise.
+ */
+int x509_crt_revoked( const x509_crt *crt, const x509_crl *crl )
+{
+    const x509_crl_entry *cur = &crl->entry;
+
+    while( cur != NULL && cur->serial.len != 0 )
+    {
+        if( crt->serial.len == cur->serial.len &&
+            memcmp( crt->serial.p, cur->serial.p, crt->serial.len ) == 0 )
+        {
+            if( x509_time_expired( &cur->revocation_date ) )
+                return( 1 );
+        }
+
+        cur = cur->next;
+    }
+
+    return( 0 );
+}
+
+/*
+ * Check that the given certificate is valid according to the CRL.
+ */
+static int x509_crt_verifycrl( x509_crt *crt, x509_crt *ca,
+                               x509_crl *crl_list)
+{
+    int flags = 0;
+    unsigned char hash[POLARSSL_MD_MAX_SIZE];
+    const md_info_t *md_info;
+
+    if( ca == NULL )
+        return( flags );
+
+    /*
+     * TODO: What happens if no CRL is present?
+     * Suggestion: Revocation state should be unknown if no CRL is present.
+     * For backwards compatibility this is not yet implemented.
+     */
+
+    while( crl_list != NULL )
+    {
+        if( crl_list->version == 0 ||
+            crl_list->issuer_raw.len != ca->subject_raw.len ||
+            memcmp( crl_list->issuer_raw.p, ca->subject_raw.p,
+                    crl_list->issuer_raw.len ) != 0 )
+        {
+            crl_list = crl_list->next;
+            continue;
+        }
+
+        /*
+         * Check if the CA is configured to sign CRLs
+         */
+#if defined(POLARSSL_X509_CHECK_KEY_USAGE)
+        if( x509_crt_check_key_usage( ca, KU_CRL_SIGN ) != 0 )
+        {
+            flags |= BADCRL_NOT_TRUSTED;
+            break;
+        }
+#endif
+
+        /*
+         * Check if CRL is correctly signed by the trusted CA
+         */
+        md_info = md_info_from_type( crl_list->sig_md );
+        if( md_info == NULL )
+        {
+            /*
+             * Cannot check 'unknown' hash
+             */
+            flags |= BADCRL_NOT_TRUSTED;
+            break;
+        }
+
+        md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash );
+
+        if( pk_can_do( &ca->pk, crl_list->sig_pk ) == 0 ||
+            pk_verify( &ca->pk, crl_list->sig_md, hash, md_info->size,
+                       crl_list->sig.p, crl_list->sig.len ) != 0 )
+        {
+            flags |= BADCRL_NOT_TRUSTED;
+            break;
+        }
+
+        /*
+         * Check for validity of CRL (Do not drop out)
+         */
+        if( x509_time_expired( &crl_list->next_update ) )
+            flags |= BADCRL_EXPIRED;
+
+        if( x509_time_future( &crl_list->this_update ) )
+            flags |= BADCRL_FUTURE;
+
+        /*
+         * Check if certificate is revoked
+         */
+        if( x509_crt_revoked(crt, crl_list) )
+        {
+            flags |= BADCERT_REVOKED;
+            break;
+        }
+
+        crl_list = crl_list->next;
+    }
+    return flags;
+}
+#endif /* POLARSSL_X509_CRL_PARSE_C */
+
+// Equal == 0, inequal == 1
+static int x509_name_cmp( const void *s1, const void *s2, size_t len )
+{
+    size_t i;
+    unsigned char diff;
+    const unsigned char *n1 = s1, *n2 = s2;
+
+    for( i = 0; i < len; i++ )
+    {
+        diff = n1[i] ^ n2[i];
+
+        if( diff == 0 )
+            continue;
+
+        if( diff == 32 &&
+            ( ( n1[i] >= 'a' && n1[i] <= 'z' ) ||
+              ( n1[i] >= 'A' && n1[i] <= 'Z' ) ) )
+        {
+            continue;
+        }
+
+        return( 1 );
+    }
+
+    return( 0 );
+}
+
+static int x509_wildcard_verify( const char *cn, x509_buf *name )
+{
+    size_t i;
+    size_t cn_idx = 0;
+
+    if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' )
+        return( 0 );
+
+    for( i = 0; i < strlen( cn ); ++i )
+    {
+        if( cn[i] == '.' )
+        {
+            cn_idx = i;
+            break;
+        }
+    }
+
+    if( cn_idx == 0 )
+        return( 0 );
+
+    if( strlen( cn ) - cn_idx == name->len - 1 &&
+        x509_name_cmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 )
+    {
+        return( 1 );
+    }
+
+    return( 0 );
+}
+
+/*
+ * Check if 'parent' is a suitable parent (signing CA) for 'child'.
+ * Return 0 if yes, -1 if not.
+ */
+static int x509_crt_check_parent( const x509_crt *child,
+                                  const x509_crt *parent )
+{
+    if( parent->version == 0 ||
+        parent->ca_istrue == 0 ||
+        child->issuer_raw.len != parent->subject_raw.len ||
+        memcmp( child->issuer_raw.p, parent->subject_raw.p,
+                child->issuer_raw.len ) != 0 )
+    {
+        return( -1 );
+    }
+
+#if defined(POLARSSL_X509_CHECK_KEY_USAGE)
+    if( x509_crt_check_key_usage( parent, KU_KEY_CERT_SIGN ) != 0 )
+        return( -1 );
+#endif
+
+    return( 0 );
+}
+
+static int x509_crt_verify_top(
+                x509_crt *child, x509_crt *trust_ca,
+                x509_crl *ca_crl, int path_cnt, int *flags,
+                int (*f_vrfy)(void *, x509_crt *, int, int *),
+                void *p_vrfy )
+{
+    int ret;
+    int ca_flags = 0, check_path_cnt = path_cnt + 1;
+    unsigned char hash[POLARSSL_MD_MAX_SIZE];
+    const md_info_t *md_info;
+
+    if( x509_time_expired( &child->valid_to ) )
+        *flags |= BADCERT_EXPIRED;
+
+    if( x509_time_future( &child->valid_from ) )
+        *flags |= BADCERT_FUTURE;
+
+    /*
+     * Child is the top of the chain. Check against the trust_ca list.
+     */
+    *flags |= BADCERT_NOT_TRUSTED;
+
+    md_info = md_info_from_type( child->sig_md );
+    if( md_info == NULL )
+    {
+        /*
+         * Cannot check 'unknown', no need to try any CA
+         */
+        trust_ca = NULL;
+    }
+    else
+        md( md_info, child->tbs.p, child->tbs.len, hash );
+
+    for( /* trust_ca */ ; trust_ca != NULL; trust_ca = trust_ca->next )
+    {
+        if( x509_crt_check_parent( child, trust_ca ) != 0 )
+            continue;
+
+        /*
+         * Reduce path_len to check against if top of the chain is
+         * the same as the trusted CA
+         */
+        if( child->subject_raw.len == trust_ca->subject_raw.len &&
+            memcmp( child->subject_raw.p, trust_ca->subject_raw.p,
+                            child->issuer_raw.len ) == 0 )
+        {
+            check_path_cnt--;
+        }
+
+        if( trust_ca->max_pathlen > 0 &&
+            trust_ca->max_pathlen < check_path_cnt )
+        {
+            continue;
+        }
+
+        if( pk_can_do( &trust_ca->pk, child->sig_pk ) == 0 ||
+            pk_verify( &trust_ca->pk, child->sig_md, hash, md_info->size,
+                       child->sig.p, child->sig.len ) != 0 )
+        {
+            continue;
+        }
+
+        /*
+         * Top of chain is signed by a trusted CA
+         */
+        *flags &= ~BADCERT_NOT_TRUSTED;
+        break;
+    }
+
+    /*
+     * If top of chain is not the same as the trusted CA send a verify request
+     * to the callback for any issues with validity and CRL presence for the
+     * trusted CA certificate.
+     */
+    if( trust_ca != NULL &&
+        ( child->subject_raw.len != trust_ca->subject_raw.len ||
+          memcmp( child->subject_raw.p, trust_ca->subject_raw.p,
+                            child->issuer_raw.len ) != 0 ) )
+    {
+#if defined(POLARSSL_X509_CRL_PARSE_C)
+        /* Check trusted CA's CRL for the chain's top crt */
+        *flags |= x509_crt_verifycrl( child, trust_ca, ca_crl );
+#else
+        ((void) ca_crl);
+#endif
+
+        if( x509_time_expired( &trust_ca->valid_to ) )
+            ca_flags |= BADCERT_EXPIRED;
+
+        if( x509_time_future( &trust_ca->valid_from ) )
+            ca_flags |= BADCERT_FUTURE;
+
+        if( NULL != f_vrfy )
+        {
+            if( ( ret = f_vrfy( p_vrfy, trust_ca, path_cnt + 1,
+                                &ca_flags ) ) != 0 )
+            {
+                return( ret );
+            }
+        }
+    }
+
+    /* Call callback on top cert */
+    if( NULL != f_vrfy )
+    {
+        if( ( ret = f_vrfy(p_vrfy, child, path_cnt, flags ) ) != 0 )
+            return( ret );
+    }
+
+    *flags |= ca_flags;
+
+    return( 0 );
+}
+
+static int x509_crt_verify_child(
+                x509_crt *child, x509_crt *parent, x509_crt *trust_ca,
+                x509_crl *ca_crl, int path_cnt, int *flags,
+                int (*f_vrfy)(void *, x509_crt *, int, int *),
+                void *p_vrfy )
+{
+    int ret;
+    int parent_flags = 0;
+    unsigned char hash[POLARSSL_MD_MAX_SIZE];
+    x509_crt *grandparent;
+    const md_info_t *md_info;
+
+    if( x509_time_expired( &child->valid_to ) )
+        *flags |= BADCERT_EXPIRED;
+
+    if( x509_time_future( &child->valid_from ) )
+        *flags |= BADCERT_FUTURE;
+
+    md_info = md_info_from_type( child->sig_md );
+    if( md_info == NULL )
+    {
+        /*
+         * Cannot check 'unknown' hash
+         */
+        *flags |= BADCERT_NOT_TRUSTED;
+    }
+    else
+    {
+        md( md_info, child->tbs.p, child->tbs.len, hash );
+
+        if( pk_can_do( &parent->pk, child->sig_pk ) == 0 ||
+            pk_verify( &parent->pk, child->sig_md, hash, md_info->size,
+                       child->sig.p, child->sig.len ) != 0 )
+        {
+            *flags |= BADCERT_NOT_TRUSTED;
+        }
+    }
+
+#if defined(POLARSSL_X509_CRL_PARSE_C)
+    /* Check trusted CA's CRL for the given crt */
+    *flags |= x509_crt_verifycrl(child, parent, ca_crl);
+#endif
+
+    /* Look for a grandparent upwards the chain */
+    for( grandparent = parent->next;
+         grandparent != NULL;
+         grandparent = grandparent->next )
+    {
+        if( x509_crt_check_parent( parent, grandparent ) == 0 )
+            break;
+    }
+
+    /* Is our parent part of the chain or at the top? */
+    if( grandparent != NULL )
+    {
+        ret = x509_crt_verify_child( parent, grandparent, trust_ca, ca_crl,
+                                path_cnt + 1, &parent_flags, f_vrfy, p_vrfy );
+        if( ret != 0 )
+            return( ret );
+    }
+    else
+    {
+        ret = x509_crt_verify_top( parent, trust_ca, ca_crl,
+                                path_cnt + 1, &parent_flags, f_vrfy, p_vrfy );
+        if( ret != 0 )
+            return( ret );
+    }
+
+    /* child is verified to be a child of the parent, call verify callback */
+    if( NULL != f_vrfy )
+        if( ( ret = f_vrfy( p_vrfy, child, path_cnt, flags ) ) != 0 )
+            return( ret );
+
+    *flags |= parent_flags;
+
+    return( 0 );
+}
+
+/*
+ * Verify the certificate validity
+ */
+int x509_crt_verify( x509_crt *crt,
+                     x509_crt *trust_ca,
+                     x509_crl *ca_crl,
+                     const char *cn, int *flags,
+                     int (*f_vrfy)(void *, x509_crt *, int, int *),
+                     void *p_vrfy )
+{
+    size_t cn_len;
+    int ret;
+    int pathlen = 0;
+    x509_crt *parent;
+    x509_name *name;
+    x509_sequence *cur = NULL;
+
+    *flags = 0;
+
+    if( cn != NULL )
+    {
+        name = &crt->subject;
+        cn_len = strlen( cn );
+
+        if( crt->ext_types & EXT_SUBJECT_ALT_NAME )
+        {
+            cur = &crt->subject_alt_names;
+
+            while( cur != NULL )
+            {
+                if( cur->buf.len == cn_len &&
+                    x509_name_cmp( cn, cur->buf.p, cn_len ) == 0 )
+                    break;
+
+                if( cur->buf.len > 2 &&
+                    memcmp( cur->buf.p, "*.", 2 ) == 0 &&
+                            x509_wildcard_verify( cn, &cur->buf ) )
+                    break;
+
+                cur = cur->next;
+            }
+
+            if( cur == NULL )
+                *flags |= BADCERT_CN_MISMATCH;
+        }
+        else
+        {
+            while( name != NULL )
+            {
+                if( OID_CMP( OID_AT_CN, &name->oid ) )
+                {
+                    if( name->val.len == cn_len &&
+                        x509_name_cmp( name->val.p, cn, cn_len ) == 0 )
+                        break;
+
+                    if( name->val.len > 2 &&
+                        memcmp( name->val.p, "*.", 2 ) == 0 &&
+                                x509_wildcard_verify( cn, &name->val ) )
+                        break;
+                }
+
+                name = name->next;
+            }
+
+            if( name == NULL )
+                *flags |= BADCERT_CN_MISMATCH;
+        }
+    }
+
+    /* Look for a parent upwards the chain */
+    for( parent = crt->next; parent != NULL; parent = parent->next )
+    {
+        if( x509_crt_check_parent( crt, parent ) == 0 )
+            break;
+    }
+
+    /* Are we part of the chain or at the top? */
+    if( parent != NULL )
+    {
+        ret = x509_crt_verify_child( crt, parent, trust_ca, ca_crl,
+                                     pathlen, flags, f_vrfy, p_vrfy );
+        if( ret != 0 )
+            return( ret );
+    }
+    else
+    {
+        ret = x509_crt_verify_top( crt, trust_ca, ca_crl,
+                                   pathlen, flags, f_vrfy, p_vrfy );
+        if( ret != 0 )
+            return( ret );
+    }
+
+    if( *flags != 0 )
+        return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
+
+    return( 0 );
+}
+
+/*
+ * Initialize a certificate chain
+ */
+void x509_crt_init( x509_crt *crt )
+{
+    memset( crt, 0, sizeof(x509_crt) );
+}
+
+/*
+ * Unallocate all certificate data
+ */
+void x509_crt_free( x509_crt *crt )
+{
+    x509_crt *cert_cur = crt;
+    x509_crt *cert_prv;
+    x509_name *name_cur;
+    x509_name *name_prv;
+    x509_sequence *seq_cur;
+    x509_sequence *seq_prv;
+
+    if( crt == NULL )
+        return;
+
+    do
+    {
+        pk_free( &cert_cur->pk );
+
+        name_cur = cert_cur->issuer.next;
+        while( name_cur != NULL )
+        {
+            name_prv = name_cur;
+            name_cur = name_cur->next;
+            memset( name_prv, 0, sizeof( x509_name ) );
+            polarssl_free( name_prv );
+        }
+
+        name_cur = cert_cur->subject.next;
+        while( name_cur != NULL )
+        {
+            name_prv = name_cur;
+            name_cur = name_cur->next;
+            memset( name_prv, 0, sizeof( x509_name ) );
+            polarssl_free( name_prv );
+        }
+
+        seq_cur = cert_cur->ext_key_usage.next;
+        while( seq_cur != NULL )
+        {
+            seq_prv = seq_cur;
+            seq_cur = seq_cur->next;
+            memset( seq_prv, 0, sizeof( x509_sequence ) );
+            polarssl_free( seq_prv );
+        }
+
+        seq_cur = cert_cur->subject_alt_names.next;
+        while( seq_cur != NULL )
+        {
+            seq_prv = seq_cur;
+            seq_cur = seq_cur->next;
+            memset( seq_prv, 0, sizeof( x509_sequence ) );
+            polarssl_free( seq_prv );
+        }
+
+        if( cert_cur->raw.p != NULL )
+        {
+            memset( cert_cur->raw.p, 0, cert_cur->raw.len );
+            polarssl_free( cert_cur->raw.p );
+        }
+
+        cert_cur = cert_cur->next;
+    }
+    while( cert_cur != NULL );
+
+    cert_cur = crt;
+    do
+    {
+        cert_prv = cert_cur;
+        cert_cur = cert_cur->next;
+
+        memset( cert_prv, 0, sizeof( x509_crt ) );
+        if( cert_prv != crt )
+            polarssl_free( cert_prv );
+    }
+    while( cert_cur != NULL );
+}
+
+#endif /* POLARSSL_X509_CRT_PARSE_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/x509_csr.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,443 @@
+/*
+ *  X.509 Certificate Signing Request (CSR) parsing
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  The ITU-T X.509 standard defines a certificate format for PKI.
+ *
+ *  http://www.ietf.org/rfc/rfc3279.txt
+ *  http://www.ietf.org/rfc/rfc3280.txt
+ *
+ *  ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc
+ *
+ *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
+ *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_X509_CSR_PARSE_C)
+
+#include "polarssl/x509_csr.h"
+#include "polarssl/oid.h"
+#if defined(POLARSSL_PEM_PARSE_C)
+#include "polarssl/pem.h"
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+
+#if defined(POLARSSL_FS_IO) || defined(EFIX64) || defined(EFI32)
+#include <stdio.h>
+#endif
+
+/*
+ *  Version  ::=  INTEGER  {  v1(0)  }
+ */
+static int x509_csr_get_version( unsigned char **p,
+                             const unsigned char *end,
+                             int *ver )
+{
+    int ret;
+
+    if( ( ret = asn1_get_int( p, end, ver ) ) != 0 )
+    {
+        if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+        {
+            *ver = 0;
+            return( 0 );
+        }
+
+        return( POLARSSL_ERR_X509_INVALID_VERSION + ret );
+    }
+
+    return( 0 );
+}
+
+/*
+ * Parse a CSR
+ */
+int x509_csr_parse( x509_csr *csr, const unsigned char *buf, size_t buflen )
+{
+    int ret;
+    size_t len;
+    unsigned char *p, *end;
+#if defined(POLARSSL_PEM_PARSE_C)
+    size_t use_len;
+    pem_context pem;
+#endif
+
+    /*
+     * Check for valid input
+     */
+    if( csr == NULL || buf == NULL )
+        return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
+
+    x509_csr_init( csr );
+
+#if defined(POLARSSL_PEM_PARSE_C)
+    pem_init( &pem );
+    ret = pem_read_buffer( &pem,
+                           "-----BEGIN CERTIFICATE REQUEST-----",
+                           "-----END CERTIFICATE REQUEST-----",
+                           buf, NULL, 0, &use_len );
+
+    if( ret == 0 )
+    {
+        /*
+         * Was PEM encoded, steal PEM buffer
+         */
+        p = pem.buf;
+        pem.buf = NULL;
+        len = pem.buflen;
+        pem_free( &pem );
+    }
+    else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
+    {
+        pem_free( &pem );
+        return( ret );
+    }
+    else
+#endif /* POLARSSL_PEM_PARSE_C */
+    {
+        /*
+         * nope, copy the raw DER data
+         */
+        p = (unsigned char *) polarssl_malloc( len = buflen );
+
+        if( p == NULL )
+            return( POLARSSL_ERR_X509_MALLOC_FAILED );
+
+        memcpy( p, buf, buflen );
+    }
+
+    csr->raw.p = p;
+    csr->raw.len = len;
+    end = p + len;
+
+    /*
+     *  CertificationRequest ::= SEQUENCE {
+     *       certificationRequestInfo CertificationRequestInfo,
+     *       signatureAlgorithm AlgorithmIdentifier,
+     *       signature          BIT STRING
+     *  }
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        x509_csr_free( csr );
+        return( POLARSSL_ERR_X509_INVALID_FORMAT );
+    }
+
+    if( len != (size_t) ( end - p ) )
+    {
+        x509_csr_free( csr );
+        return( POLARSSL_ERR_X509_INVALID_FORMAT +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+    }
+
+    /*
+     *  CertificationRequestInfo ::= SEQUENCE {
+     */
+    csr->cri.p = p;
+
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        x509_csr_free( csr );
+        return( POLARSSL_ERR_X509_INVALID_FORMAT + ret );
+    }
+
+    end = p + len;
+    csr->cri.len = end - csr->cri.p;
+
+    /*
+     *  Version  ::=  INTEGER {  v1(0) }
+     */
+    if( ( ret = x509_csr_get_version( &p, end, &csr->version ) ) != 0 )
+    {
+        x509_csr_free( csr );
+        return( ret );
+    }
+
+    csr->version++;
+
+    if( csr->version != 1 )
+    {
+        x509_csr_free( csr );
+        return( POLARSSL_ERR_X509_UNKNOWN_VERSION );
+    }
+
+    /*
+     *  subject               Name
+     */
+    csr->subject_raw.p = p;
+
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        x509_csr_free( csr );
+        return( POLARSSL_ERR_X509_INVALID_FORMAT + ret );
+    }
+
+    if( ( ret = x509_get_name( &p, p + len, &csr->subject ) ) != 0 )
+    {
+        x509_csr_free( csr );
+        return( ret );
+    }
+
+    csr->subject_raw.len = p - csr->subject_raw.p;
+
+    /*
+     *  subjectPKInfo SubjectPublicKeyInfo
+     */
+    if( ( ret = pk_parse_subpubkey( &p, end, &csr->pk ) ) != 0 )
+    {
+        x509_csr_free( csr );
+        return( ret );
+    }
+
+    /*
+     *  attributes    [0] Attributes
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) ) != 0 )
+    {
+        x509_csr_free( csr );
+        return( POLARSSL_ERR_X509_INVALID_FORMAT + ret );
+    }
+    // TODO Parse Attributes / extension requests
+
+    p += len;
+
+    end = csr->raw.p + csr->raw.len;
+
+    /*
+     *  signatureAlgorithm   AlgorithmIdentifier,
+     *  signature            BIT STRING
+     */
+    if( ( ret = x509_get_alg_null( &p, end, &csr->sig_oid ) ) != 0 )
+    {
+        x509_csr_free( csr );
+        return( ret );
+    }
+
+    if( ( ret = x509_get_sig_alg( &csr->sig_oid, &csr->sig_md,
+                                  &csr->sig_pk ) ) != 0 )
+    {
+        x509_csr_free( csr );
+        return( POLARSSL_ERR_X509_UNKNOWN_SIG_ALG );
+    }
+
+    if( ( ret = x509_get_sig( &p, end, &csr->sig ) ) != 0 )
+    {
+        x509_csr_free( csr );
+        return( ret );
+    }
+
+    if( p != end )
+    {
+        x509_csr_free( csr );
+        return( POLARSSL_ERR_X509_INVALID_FORMAT +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+    }
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * Load a CSR into the structure
+ */
+int x509_csr_parse_file( x509_csr *csr, const char *path )
+{
+    int ret;
+    size_t n;
+    unsigned char *buf;
+
+    if ( ( ret = x509_load_file( path, &buf, &n ) ) != 0 )
+        return( ret );
+
+    ret = x509_csr_parse( csr, buf, n );
+
+    memset( buf, 0, n + 1 );
+    polarssl_free( buf );
+
+    return( ret );
+}
+#endif /* POLARSSL_FS_IO */
+
+#if defined(_MSC_VER) && !defined snprintf && !defined(EFIX64) && \
+    !defined(EFI32)
+#include <stdarg.h>
+
+#if !defined vsnprintf
+#define vsnprintf _vsnprintf
+#endif // vsnprintf
+
+/*
+ * Windows _snprintf and _vsnprintf are not compatible to linux versions.
+ * Result value is not size of buffer needed, but -1 if no fit is possible.
+ *
+ * This fuction tries to 'fix' this by at least suggesting enlarging the
+ * size by 20.
+ */
+static int compat_snprintf(char *str, size_t size, const char *format, ...)
+{
+    va_list ap;
+    int res = -1;
+
+    va_start( ap, format );
+
+    res = vsnprintf( str, size, format, ap );
+
+    va_end( ap );
+
+    // No quick fix possible
+    if ( res < 0 )
+        return( (int) size + 20 );
+
+    return res;
+}
+
+#define snprintf compat_snprintf
+#endif /* _MSC_VER && !snprintf && !EFIX64 && !EFI32 */
+
+#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL    -2
+
+#define SAFE_SNPRINTF()                         \
+{                                               \
+    if( ret == -1 )                             \
+        return( -1 );                           \
+                                                \
+    if ( (unsigned int) ret > n ) {             \
+        p[n - 1] = '\0';                        \
+        return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\
+    }                                           \
+                                                \
+    n -= (unsigned int) ret;                    \
+    p += (unsigned int) ret;                    \
+}
+
+#define BEFORE_COLON    14
+#define BC              "14"
+/*
+ * Return an informational string about the CSR.
+ */
+int x509_csr_info( char *buf, size_t size, const char *prefix,
+                   const x509_csr *csr )
+{
+    int ret;
+    size_t n;
+    char *p;
+    const char *desc;
+    char key_size_str[BEFORE_COLON];
+
+    p = buf;
+    n = size;
+
+    ret = snprintf( p, n, "%sCSR version   : %d",
+                               prefix, csr->version );
+    SAFE_SNPRINTF();
+
+    ret = snprintf( p, n, "\n%ssubject name  : ", prefix );
+    SAFE_SNPRINTF();
+    ret = x509_dn_gets( p, n, &csr->subject );
+    SAFE_SNPRINTF();
+
+    ret = snprintf( p, n, "\n%ssigned using  : ", prefix );
+    SAFE_SNPRINTF();
+
+    ret = oid_get_sig_alg_desc( &csr->sig_oid, &desc );
+    if( ret != 0 )
+        ret = snprintf( p, n, "???"  );
+    else
+        ret = snprintf( p, n, "%s", desc );
+    SAFE_SNPRINTF();
+
+    if( ( ret = x509_key_size_helper( key_size_str, BEFORE_COLON,
+                                      pk_get_name( &csr->pk ) ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    ret = snprintf( p, n, "\n%s%-" BC "s: %d bits\n", prefix, key_size_str,
+                          (int) pk_get_size( &csr->pk ) );
+    SAFE_SNPRINTF();
+
+    return( (int) ( size - n ) );
+}
+
+/*
+ * Initialize a CSR
+ */
+void x509_csr_init( x509_csr *csr )
+{
+    memset( csr, 0, sizeof(x509_csr) );
+}
+
+/*
+ * Unallocate all CSR data
+ */
+void x509_csr_free( x509_csr *csr )
+{
+    x509_name *name_cur;
+    x509_name *name_prv;
+
+    if( csr == NULL )
+        return;
+
+    pk_free( &csr->pk );
+
+    name_cur = csr->subject.next;
+    while( name_cur != NULL )
+    {
+        name_prv = name_cur;
+        name_cur = name_cur->next;
+        memset( name_prv, 0, sizeof( x509_name ) );
+        polarssl_free( name_prv );
+    }
+
+    if( csr->raw.p != NULL )
+    {
+        memset( csr->raw.p, 0, csr->raw.len );
+        polarssl_free( csr->raw.p );
+    }
+
+    memset( csr, 0, sizeof( x509_csr ) );
+}
+
+#endif /* POLARSSL_X509_CSR_PARSE_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/x509write_crt.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,449 @@
+/*
+ *  X.509 certificate writing
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * References:
+ * - certificates: RFC 5280, updated by RFC 6818
+ * - CSRs: PKCS#10 v1.7 aka RFC 2986
+ * - attributes: PKCS#9 v2.0 aka RFC 2985
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_X509_CRT_WRITE_C)
+
+#include "polarssl/x509_crt.h"
+#include "polarssl/oid.h"
+#include "polarssl/asn1write.h"
+#include "polarssl/sha1.h"
+
+#if defined(POLARSSL_PEM_WRITE_C)
+#include "polarssl/pem.h"
+#endif /* POLARSSL_PEM_WRITE_C */
+
+void x509write_crt_init( x509write_cert *ctx )
+{
+    memset( ctx, 0, sizeof(x509write_cert) );
+
+    mpi_init( &ctx->serial );
+    ctx->version = X509_CRT_VERSION_3;
+}
+
+void x509write_crt_free( x509write_cert *ctx )
+{
+    mpi_free( &ctx->serial );
+
+    asn1_free_named_data_list( &ctx->subject );
+    asn1_free_named_data_list( &ctx->issuer );
+    asn1_free_named_data_list( &ctx->extensions );
+
+    memset( ctx, 0, sizeof(x509write_cert) );
+}
+
+void x509write_crt_set_version( x509write_cert *ctx, int version )
+{
+    ctx->version = version;
+}
+
+void x509write_crt_set_md_alg( x509write_cert *ctx, md_type_t md_alg )
+{
+    ctx->md_alg = md_alg;
+}
+
+void x509write_crt_set_subject_key( x509write_cert *ctx, pk_context *key )
+{
+    ctx->subject_key = key;
+}
+
+void x509write_crt_set_issuer_key( x509write_cert *ctx, pk_context *key )
+{
+    ctx->issuer_key = key;
+}
+
+int x509write_crt_set_subject_name( x509write_cert *ctx,
+                                    const char *subject_name )
+{
+    return x509_string_to_names( &ctx->subject, subject_name );
+}
+
+int x509write_crt_set_issuer_name( x509write_cert *ctx,
+                                   const char *issuer_name )
+{
+    return x509_string_to_names( &ctx->issuer, issuer_name );
+}
+
+int x509write_crt_set_serial( x509write_cert *ctx, const mpi *serial )
+{
+    int ret;
+
+    if( ( ret = mpi_copy( &ctx->serial, serial ) ) != 0 )
+        return( ret );
+
+    return( 0 );
+}
+
+int x509write_crt_set_validity( x509write_cert *ctx, const char *not_before,
+                                const char *not_after )
+{
+    if( strlen(not_before) != X509_RFC5280_UTC_TIME_LEN - 1 ||
+        strlen(not_after)  != X509_RFC5280_UTC_TIME_LEN - 1 )
+    {
+        return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
+    }
+    strncpy( ctx->not_before, not_before, X509_RFC5280_UTC_TIME_LEN );
+    strncpy( ctx->not_after , not_after , X509_RFC5280_UTC_TIME_LEN );
+    ctx->not_before[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
+    ctx->not_after[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
+
+    return( 0 );
+}
+
+int x509write_crt_set_extension( x509write_cert *ctx,
+                                 const char *oid, size_t oid_len,
+                                 int critical,
+                                 const unsigned char *val, size_t val_len )
+{
+    return x509_set_extension( &ctx->extensions, oid, oid_len,
+                               critical, val, val_len );
+}
+
+int x509write_crt_set_basic_constraints( x509write_cert *ctx,
+                                         int is_ca, int max_pathlen )
+{
+    int ret;
+    unsigned char buf[9];
+    unsigned char *c = buf + sizeof(buf);
+    size_t len = 0;
+
+    memset( buf, 0, sizeof(buf) );
+
+    if( is_ca && max_pathlen > 127 )
+        return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
+
+    if( is_ca )
+    {
+        if( max_pathlen >= 0 )
+        {
+            ASN1_CHK_ADD( len, asn1_write_int( &c, buf, max_pathlen ) );
+        }
+        ASN1_CHK_ADD( len, asn1_write_bool( &c, buf, 1 ) );
+    }
+
+    ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED |
+                                                ASN1_SEQUENCE ) );
+
+    return x509write_crt_set_extension( ctx, OID_BASIC_CONSTRAINTS,
+                                        OID_SIZE( OID_BASIC_CONSTRAINTS ),
+                                        0, buf + sizeof(buf) - len, len );
+}
+
+#if defined(POLARSSL_SHA1_C)
+int x509write_crt_set_subject_key_identifier( x509write_cert *ctx )
+{
+    int ret;
+    unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
+    unsigned char *c = buf + sizeof(buf);
+    size_t len = 0;
+
+    memset( buf, 0, sizeof(buf));
+    ASN1_CHK_ADD( len, pk_write_pubkey( &c, buf, ctx->subject_key ) );
+
+    sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
+    c = buf + sizeof(buf) - 20;
+    len = 20;
+
+    ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_OCTET_STRING ) );
+
+    return x509write_crt_set_extension( ctx, OID_SUBJECT_KEY_IDENTIFIER,
+                                        OID_SIZE( OID_SUBJECT_KEY_IDENTIFIER ),
+                                        0, buf + sizeof(buf) - len, len );
+}
+
+int x509write_crt_set_authority_key_identifier( x509write_cert *ctx )
+{
+    int ret;
+    unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
+    unsigned char *c = buf + sizeof(buf);
+    size_t len = 0;
+
+    memset( buf, 0, sizeof(buf));
+    ASN1_CHK_ADD( len, pk_write_pubkey( &c, buf, ctx->issuer_key ) );
+
+    sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
+    c = buf + sizeof(buf) - 20;
+    len = 20;
+
+    ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONTEXT_SPECIFIC | 0 ) );
+
+    ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED |
+                                                ASN1_SEQUENCE ) );
+
+    return x509write_crt_set_extension( ctx, OID_AUTHORITY_KEY_IDENTIFIER,
+                                   OID_SIZE( OID_AUTHORITY_KEY_IDENTIFIER ),
+                                   0, buf + sizeof(buf) - len, len );
+}
+#endif /* POLARSSL_SHA1_C */
+
+int x509write_crt_set_key_usage( x509write_cert *ctx, unsigned char key_usage )
+{
+    unsigned char buf[4];
+    unsigned char *c;
+    int ret;
+
+    c = buf + 4;
+
+    if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
+        return( ret );
+
+    ret = x509write_crt_set_extension( ctx, OID_KEY_USAGE,
+                                       OID_SIZE( OID_KEY_USAGE ),
+                                       1, buf, 4 );
+    if( ret != 0 )
+        return( ret );
+
+    return( 0 );
+}
+
+int x509write_crt_set_ns_cert_type( x509write_cert *ctx,
+                                    unsigned char ns_cert_type )
+{
+    unsigned char buf[4];
+    unsigned char *c;
+    int ret;
+
+    c = buf + 4;
+
+    if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
+        return( ret );
+
+    ret = x509write_crt_set_extension( ctx, OID_NS_CERT_TYPE,
+                                       OID_SIZE( OID_NS_CERT_TYPE ),
+                                       0, buf, 4 );
+    if( ret != 0 )
+        return( ret );
+
+    return( 0 );
+}
+
+static int x509_write_time( unsigned char **p, unsigned char *start,
+                            const char *time, size_t size )
+{
+    int ret;
+    size_t len = 0;
+
+    /*
+     * write ASN1_UTC_TIME if year < 2050 (2 bytes shorter)
+     */
+    if( time[0] == '2' && time[1] == '0' && time [2] < '5' )
+    {
+        ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
+                                             (const unsigned char *) time + 2,
+                                             size - 2 ) );
+        ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
+        ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_UTC_TIME ) );
+    }
+    else
+    {
+        ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
+                                                  (const unsigned char *) time,
+                                                  size ) );
+        ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
+        ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_GENERALIZED_TIME ) );
+    }
+
+    return( (int) len );
+}
+
+int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size,
+                       int (*f_rng)(void *, unsigned char *, size_t),
+                       void *p_rng )
+{
+    int ret;
+    const char *sig_oid;
+    size_t sig_oid_len = 0;
+    unsigned char *c, *c2;
+    unsigned char hash[64];
+    unsigned char sig[POLARSSL_MPI_MAX_SIZE];
+    unsigned char tmp_buf[2048];
+    size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len;
+    size_t len = 0;
+    pk_type_t pk_alg;
+
+    /*
+     * Prepare data to be signed in tmp_buf
+     */
+    c = tmp_buf + sizeof( tmp_buf );
+
+    /* Signature algorithm needed in TBS, and later for actual signature */
+    pk_alg = pk_get_type( ctx->issuer_key );
+    if( pk_alg == POLARSSL_PK_ECKEY )
+        pk_alg = POLARSSL_PK_ECDSA;
+
+    if( ( ret = oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,
+                                        &sig_oid, &sig_oid_len ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    /*
+     *  Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
+     */
+    ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
+    ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
+                                                    ASN1_SEQUENCE ) );
+    ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC |
+                                                    ASN1_CONSTRUCTED | 3 ) );
+
+    /*
+     *  SubjectPublicKeyInfo
+     */
+    ASN1_CHK_ADD( pub_len, pk_write_pubkey_der( ctx->subject_key,
+                                                tmp_buf, c - tmp_buf ) );
+    c -= pub_len;
+    len += pub_len;
+
+    /*
+     *  Subject  ::=  Name
+     */
+    ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
+
+    /*
+     *  Validity ::= SEQUENCE {
+     *       notBefore      Time,
+     *       notAfter       Time }
+     */
+    sub_len = 0;
+
+    ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after,
+                                            X509_RFC5280_UTC_TIME_LEN ) );
+
+    ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before,
+                                            X509_RFC5280_UTC_TIME_LEN ) );
+
+    len += sub_len;
+    ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
+                                                    ASN1_SEQUENCE ) );
+
+    /*
+     *  Issuer  ::=  Name
+     */
+    ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->issuer ) );
+
+    /*
+     *  Signature   ::=  AlgorithmIdentifier
+     */
+    ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, tmp_buf,
+                       sig_oid, strlen( sig_oid ), 0 ) );
+
+    /*
+     *  Serial   ::=  INTEGER
+     */
+    ASN1_CHK_ADD( len, asn1_write_mpi( &c, tmp_buf, &ctx->serial ) );
+
+    /*
+     *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
+     */
+    sub_len = 0;
+    ASN1_CHK_ADD( sub_len, asn1_write_int( &c, tmp_buf, ctx->version ) );
+    len += sub_len;
+    ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC |
+                                                    ASN1_CONSTRUCTED | 0 ) );
+
+    ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
+                                                    ASN1_SEQUENCE ) );
+
+    /*
+     * Make signature
+     */
+    md( md_info_from_type( ctx->md_alg ), c, len, hash );
+
+    if( ( ret = pk_sign( ctx->issuer_key, ctx->md_alg, hash, 0, sig, &sig_len,
+                         f_rng, p_rng ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    /*
+     * Write data to output buffer
+     */
+    c2 = buf + size;
+    ASN1_CHK_ADD( sig_and_oid_len, x509_write_sig( &c2, buf,
+                                        sig_oid, sig_oid_len, sig, sig_len ) );
+
+    c2 -= len;
+    memcpy( c2, c, len );
+
+    len += sig_and_oid_len;
+    ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED |
+                                                 ASN1_SEQUENCE ) );
+
+    return( (int) len );
+}
+
+#define PEM_BEGIN_CRT           "-----BEGIN CERTIFICATE-----\n"
+#define PEM_END_CRT             "-----END CERTIFICATE-----\n"
+
+#if defined(POLARSSL_PEM_WRITE_C)
+int x509write_crt_pem( x509write_cert *crt, unsigned char *buf, size_t size,
+                       int (*f_rng)(void *, unsigned char *, size_t),
+                       void *p_rng )
+{
+    int ret;
+    unsigned char output_buf[4096];
+    size_t olen = 0;
+
+    if( ( ret = x509write_crt_der( crt, output_buf, sizeof(output_buf),
+                                   f_rng, p_rng ) ) < 0 )
+    {
+        return( ret );
+    }
+
+    if( ( ret = pem_write_buffer( PEM_BEGIN_CRT, PEM_END_CRT,
+                                  output_buf + sizeof(output_buf) - ret,
+                                  ret, buf, size, &olen ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    return( 0 );
+}
+#endif /* POLARSSL_PEM_WRITE_C */
+
+#endif /* POLARSSL_X509_CRT_WRITE_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/x509write_csr.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,257 @@
+/*
+ *  X.509 Certificate Signing Request writing
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * References:
+ * - CSRs: PKCS#10 v1.7 aka RFC 2986
+ * - attributes: PKCS#9 v2.0 aka RFC 2985
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_X509_CSR_WRITE_C)
+
+#include "polarssl/x509_csr.h"
+#include "polarssl/oid.h"
+#include "polarssl/asn1write.h"
+
+#if defined(POLARSSL_PEM_WRITE_C)
+#include "polarssl/pem.h"
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+
+void x509write_csr_init( x509write_csr *ctx )
+{
+    memset( ctx, 0, sizeof(x509write_csr) );
+}
+
+void x509write_csr_free( x509write_csr *ctx )
+{
+    asn1_free_named_data_list( &ctx->subject );
+    asn1_free_named_data_list( &ctx->extensions );
+
+    memset( ctx, 0, sizeof(x509write_csr) );
+}
+
+void x509write_csr_set_md_alg( x509write_csr *ctx, md_type_t md_alg )
+{
+    ctx->md_alg = md_alg;
+}
+
+void x509write_csr_set_key( x509write_csr *ctx, pk_context *key )
+{
+    ctx->key = key;
+}
+
+int x509write_csr_set_subject_name( x509write_csr *ctx,
+                                    const char *subject_name )
+{
+    return x509_string_to_names( &ctx->subject, subject_name );
+}
+
+int x509write_csr_set_extension( x509write_csr *ctx,
+                                 const char *oid, size_t oid_len,
+                                 const unsigned char *val, size_t val_len )
+{
+    return x509_set_extension( &ctx->extensions, oid, oid_len,
+                               0, val, val_len );
+}
+
+int x509write_csr_set_key_usage( x509write_csr *ctx, unsigned char key_usage )
+{
+    unsigned char buf[4];
+    unsigned char *c;
+    int ret;
+
+    c = buf + 4;
+
+    if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
+        return( ret );
+
+    ret = x509write_csr_set_extension( ctx, OID_KEY_USAGE,
+                                       OID_SIZE( OID_KEY_USAGE ),
+                                       buf, 4 );
+    if( ret != 0 )
+        return( ret );
+
+    return( 0 );
+}
+
+int x509write_csr_set_ns_cert_type( x509write_csr *ctx,
+                                    unsigned char ns_cert_type )
+{
+    unsigned char buf[4];
+    unsigned char *c;
+    int ret;
+
+    c = buf + 4;
+
+    if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
+        return( ret );
+
+    ret = x509write_csr_set_extension( ctx, OID_NS_CERT_TYPE,
+                                       OID_SIZE( OID_NS_CERT_TYPE ),
+                                       buf, 4 );
+    if( ret != 0 )
+        return( ret );
+
+    return( 0 );
+}
+
+int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size,
+                       int (*f_rng)(void *, unsigned char *, size_t),
+                       void *p_rng )
+{
+    int ret;
+    const char *sig_oid;
+    size_t sig_oid_len = 0;
+    unsigned char *c, *c2;
+    unsigned char hash[64];
+    unsigned char sig[POLARSSL_MPI_MAX_SIZE];
+    unsigned char tmp_buf[2048];
+    size_t pub_len = 0, sig_and_oid_len = 0, sig_len;
+    size_t len = 0;
+    pk_type_t pk_alg;
+
+    /*
+     * Prepare data to be signed in tmp_buf
+     */
+    c = tmp_buf + sizeof( tmp_buf );
+
+    ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
+
+    if( len )
+    {
+        ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
+        ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
+                                                        ASN1_SEQUENCE ) );
+
+        ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
+        ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
+                                                        ASN1_SET ) );
+
+        ASN1_CHK_ADD( len, asn1_write_oid( &c, tmp_buf, OID_PKCS9_CSR_EXT_REQ,
+                                          OID_SIZE( OID_PKCS9_CSR_EXT_REQ ) ) );
+
+        ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
+        ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
+                                                        ASN1_SEQUENCE ) );
+    }
+
+    ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
+                                                    ASN1_CONTEXT_SPECIFIC ) );
+
+    ASN1_CHK_ADD( pub_len, pk_write_pubkey_der( ctx->key,
+                                                tmp_buf, c - tmp_buf ) );
+    c -= pub_len;
+    len += pub_len;
+
+    /*
+     *  Subject  ::=  Name
+     */
+    ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
+
+    /*
+     *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
+     */
+    ASN1_CHK_ADD( len, asn1_write_int( &c, tmp_buf, 0 ) );
+
+    ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
+                                                    ASN1_SEQUENCE ) );
+
+    /*
+     * Prepare signature
+     */
+    md( md_info_from_type( ctx->md_alg ), c, len, hash );
+
+    pk_alg = pk_get_type( ctx->key );
+    if( pk_alg == POLARSSL_PK_ECKEY )
+        pk_alg = POLARSSL_PK_ECDSA;
+
+    if( ( ret = pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len,
+                         f_rng, p_rng ) ) != 0 ||
+        ( ret = oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,
+                                        &sig_oid, &sig_oid_len ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    /*
+     * Write data to output buffer
+     */
+    c2 = buf + size;
+    ASN1_CHK_ADD( sig_and_oid_len, x509_write_sig( &c2, buf,
+                                        sig_oid, sig_oid_len, sig, sig_len ) );
+
+    c2 -= len;
+    memcpy( c2, c, len );
+
+    len += sig_and_oid_len;
+    ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED |
+                                                 ASN1_SEQUENCE ) );
+
+    return( (int) len );
+}
+
+#define PEM_BEGIN_CSR           "-----BEGIN CERTIFICATE REQUEST-----\n"
+#define PEM_END_CSR             "-----END CERTIFICATE REQUEST-----\n"
+
+#if defined(POLARSSL_PEM_WRITE_C)
+int x509write_csr_pem( x509write_csr *ctx, unsigned char *buf, size_t size,
+                       int (*f_rng)(void *, unsigned char *, size_t),
+                       void *p_rng )
+{
+    int ret;
+    unsigned char output_buf[4096];
+    size_t olen = 0;
+
+    if( ( ret = x509write_csr_der( ctx, output_buf, sizeof(output_buf),
+                                   f_rng, p_rng ) ) < 0 )
+    {
+        return( ret );
+    }
+
+    if( ( ret = pem_write_buffer( PEM_BEGIN_CSR, PEM_END_CSR,
+                                  output_buf + sizeof(output_buf) - ret,
+                                  ret, buf, size, &olen ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    return( 0 );
+}
+#endif /* POLARSSL_PEM_WRITE_C */
+
+#endif /* POLARSSL_X509_CSR_WRITE_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSL/library/xtea.c	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,262 @@
+/*
+ *  An 32-bit implementation of the XTEA algorithm
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_XTEA_C)
+
+#include "polarssl/xtea.h"
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
+#if !defined(POLARSSL_XTEA_ALT)
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i)                            \
+{                                                       \
+    (n) = ( (uint32_t) (b)[(i)    ] << 24 )             \
+        | ( (uint32_t) (b)[(i) + 1] << 16 )             \
+        | ( (uint32_t) (b)[(i) + 2] <<  8 )             \
+        | ( (uint32_t) (b)[(i) + 3]       );            \
+}
+#endif
+
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i)                            \
+{                                                       \
+    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
+    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
+    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
+    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
+}
+#endif
+
+/*
+ * XTEA key schedule
+ */
+void xtea_setup( xtea_context *ctx, const unsigned char key[16] )
+{
+    int i;
+
+    memset(ctx, 0, sizeof(xtea_context));
+
+    for( i = 0; i < 4; i++ )
+    {
+        GET_UINT32_BE( ctx->k[i], key, i << 2 );
+    }
+}
+
+/*
+ * XTEA encrypt function
+ */
+int xtea_crypt_ecb( xtea_context *ctx, int mode,
+                    const unsigned char input[8], unsigned char output[8])
+{
+    uint32_t *k, v0, v1, i;
+
+    k = ctx->k;
+
+    GET_UINT32_BE( v0, input, 0 );
+    GET_UINT32_BE( v1, input, 4 );
+
+    if( mode == XTEA_ENCRYPT )
+    {
+        uint32_t sum = 0, delta = 0x9E3779B9;
+
+        for( i = 0; i < 32; i++ )
+        {
+            v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]);
+            sum += delta;
+            v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]);
+        }
+    }
+    else /* XTEA_DECRYPT */
+    {
+        uint32_t delta = 0x9E3779B9, sum = delta * 32;
+
+        for( i = 0; i < 32; i++ )
+        {
+            v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]);
+            sum -= delta;
+            v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]);
+        }
+    }
+
+    PUT_UINT32_BE( v0, output, 0 );
+    PUT_UINT32_BE( v1, output, 4 );
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+/*
+ * XTEA-CBC buffer encryption/decryption
+ */
+int xtea_crypt_cbc( xtea_context *ctx, int mode, size_t length,
+                    unsigned char iv[8], const unsigned char *input,
+                    unsigned char *output)
+{
+    int i;
+    unsigned char temp[8];
+
+    if( length % 8 )
+        return( POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH );
+
+    if( mode == XTEA_DECRYPT )
+    {
+        while( length > 0 )
+        {
+            memcpy( temp, input, 8 );
+            xtea_crypt_ecb( ctx, mode, input, output );
+
+            for(i = 0; i < 8; i++)
+                output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+            memcpy( iv, temp, 8 );
+
+            input  += 8;
+            output += 8;
+            length -= 8;
+        }
+    }
+    else
+    {
+        while( length > 0 )
+        {
+            for( i = 0; i < 8; i++ )
+                output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+            xtea_crypt_ecb( ctx, mode, output, output );
+            memcpy( iv, output, 8 );
+
+            input  += 8;
+            output += 8;
+            length -= 8;
+        }
+    }
+
+    return( 0 );
+}
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#endif /* !POLARSSL_XTEA_ALT */
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include <string.h>
+#include <stdio.h>
+
+/*
+ * XTEA tests vectors (non-official)
+ */
+
+static const unsigned char xtea_test_key[6][16] =
+{
+   { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
+     0x0c, 0x0d, 0x0e, 0x0f },
+   { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
+     0x0c, 0x0d, 0x0e, 0x0f },
+   { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
+     0x0c, 0x0d, 0x0e, 0x0f },
+   { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00 },
+   { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00 },
+   { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00 }
+};
+
+static const unsigned char xtea_test_pt[6][8] =
+{
+    { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 },
+    { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 },
+    { 0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f },
+    { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 },
+    { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 },
+    { 0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55 }
+};
+
+static const unsigned char xtea_test_ct[6][8] =
+{
+    { 0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5 },
+    { 0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8 },
+    { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 },
+    { 0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5 },
+    { 0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d },
+    { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }
+};
+
+/*
+ * Checkup routine
+ */
+int xtea_self_test( int verbose )
+{
+    int i;
+    unsigned char buf[8];
+    xtea_context ctx;
+
+    for( i = 0; i < 6; i++ )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "  XTEA test #%d: ", i + 1 );
+
+        memcpy( buf, xtea_test_pt[i], 8 );
+
+        xtea_setup( &ctx, xtea_test_key[i] );
+        xtea_crypt_ecb( &ctx, XTEA_ENCRYPT, buf, buf );
+
+        if( memcmp( buf, xtea_test_ct[i], 8 ) != 0 )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+    return( 0 );
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_XTEA_C */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,868 @@
+#if !defined(POLARSSL_CONFIG_FILE)
+#include <polarssl/config.h>
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#include "mbed.h"
+#define TEST_SUITE_ACTIVE
+#ifdef POLARSSL_GCM_C
+
+#include <polarssl/gcm.h>
+#endif /* POLARSSL_GCM_C */
+
+
+#if defined(POLARSSL_MEMORY_BUFFER_ALLOC_C)
+#include "polarssl/memory.h"
+#endif
+
+#ifdef _MSC_VER
+#include <basetsd.h>
+typedef UINT32 uint32_t;
+#else
+#include <inttypes.h>
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i)                            \
+{                                                       \
+    (n) = ( (uint32_t) (b)[(i)    ] << 24 )             \
+        | ( (uint32_t) (b)[(i) + 1] << 16 )             \
+        | ( (uint32_t) (b)[(i) + 2] <<  8 )             \
+        | ( (uint32_t) (b)[(i) + 3]       );            \
+}
+#endif
+
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i)                            \
+{                                                       \
+    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
+    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
+    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
+    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
+}
+#endif
+
+static int unhexify(unsigned char *obuf, const char *ibuf)
+{
+    unsigned char c, c2;
+    int len = strlen(ibuf) / 2;
+    assert(!(strlen(ibuf) %1)); // must be even number of bytes
+
+    while (*ibuf != 0)
+    {
+        c = *ibuf++;
+        if( c >= '0' && c <= '9' )
+            c -= '0';
+        else if( c >= 'a' && c <= 'f' )
+            c -= 'a' - 10;
+        else if( c >= 'A' && c <= 'F' )
+            c -= 'A' - 10;
+        else
+            assert( 0 );
+
+        c2 = *ibuf++;
+        if( c2 >= '0' && c2 <= '9' )
+            c2 -= '0';
+        else if( c2 >= 'a' && c2 <= 'f' )
+            c2 -= 'a' - 10;
+        else if( c2 >= 'A' && c2 <= 'F' )
+            c2 -= 'A' - 10;
+        else
+            assert( 0 );
+
+        *obuf++ = ( c << 4 ) | c2;
+    }
+
+    return len;
+}
+
+static void hexify(unsigned char *obuf, const unsigned char *ibuf, int len)
+{
+    unsigned char l, h;
+
+    while (len != 0)
+    {
+        h = (*ibuf) / 16;
+        l = (*ibuf) % 16;
+
+        if( h < 10 )
+            *obuf++ = '0' + h;
+        else
+            *obuf++ = 'a' + h - 10;
+
+        if( l < 10 )
+            *obuf++ = '0' + l;
+        else
+            *obuf++ = 'a' + l - 10;
+
+        ++ibuf;
+        len--;
+    }
+}
+
+
+#include <stdio.h>
+#include <string.h>
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf     printf
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+static int test_errors = 0;
+
+#ifdef POLARSSL_GCM_C
+
+
+static int test_assert( int correct, const char *test )
+{
+    if( correct )
+        return( 0 );
+
+    test_errors++;
+    if( test_errors == 1 )
+        printf( "FAILED\n" );
+    printf( "  %s\n", test );
+
+    return( 1 );
+}
+
+#define TEST_ASSERT( TEST )                         \
+        do { test_assert( (TEST) ? 1 : 0, #TEST );  \
+             if( test_errors) return;               \
+        } while (0)
+
+int verify_string( char **str )
+{
+    if( (*str)[0] != '"' ||
+        (*str)[strlen( *str ) - 1] != '"' )
+    {
+        printf( "Expected string (with \"\") for parameter and got: %s\n", *str );
+        return( -1 );
+    }
+
+    (*str)++;
+    (*str)[strlen( *str ) - 1] = '\0';
+
+    return( 0 );
+}
+
+int verify_int( char *str, int *value )
+{
+    size_t i;
+    int minus = 0;
+    int digits = 1;
+    int hex = 0;
+
+    for( i = 0; i < strlen( str ); i++ )
+    {
+        if( i == 0 && str[i] == '-' )
+        {
+            minus = 1;
+            continue;
+        }
+
+        if( ( ( minus && i == 2 ) || ( !minus && i == 1 ) ) &&
+            str[i - 1] == '0' && str[i] == 'x' )
+        {
+            hex = 1;
+            continue;
+        }
+
+        if( ! ( ( str[i] >= '0' && str[i] <= '9' ) ||
+                ( hex && ( ( str[i] >= 'a' && str[i] <= 'f' ) ||
+                           ( str[i] >= 'A' && str[i] <= 'F' ) ) ) ) )
+        {
+            digits = 0;
+            break;
+        }
+    }
+
+    if( digits )
+    {
+        if( hex )
+            *value = strtol( str, NULL, 16 );
+        else
+            *value = strtol( str, NULL, 10 );
+
+        return( 0 );
+    }
+
+    if( strcmp( str, "POLARSSL_CIPHER_ID_AES" ) == 0 )
+    {
+        *value = ( POLARSSL_CIPHER_ID_AES );
+        return( 0 );
+    }
+
+
+    printf( "Expected integer for parameter and got: %s\n", str );
+    return( -1 );
+}
+
+void test_suite_gcm_encrypt_and_tag( int cipher_id,
+                          char *hex_key_string, char *hex_src_string,
+                          char *hex_iv_string, char *hex_add_string,
+                          char *hex_dst_string, int tag_len_bits,
+                          char *hex_tag_string, int  init_result )
+{
+    unsigned char key_str[128];
+    unsigned char src_str[128];
+    unsigned char dst_str[257];
+    unsigned char iv_str[128];
+    unsigned char add_str[128];
+    unsigned char tag_str[128];
+    unsigned char output[128];
+    unsigned char tag_output[16];
+    gcm_context ctx;
+    unsigned int key_len;
+    size_t pt_len, iv_len, add_len, tag_len = tag_len_bits / 8;
+
+    memset(key_str, 0x00, 128);
+    memset(src_str, 0x00, 128);
+    memset(dst_str, 0x00, 257);
+    memset(iv_str, 0x00, 128);
+    memset(add_str, 0x00, 128);
+    memset(tag_str, 0x00, 128);
+    memset(output, 0x00, 128);
+    memset(tag_output, 0x00, 16);
+
+    key_len = unhexify( key_str, hex_key_string );
+    pt_len = unhexify( src_str, hex_src_string );
+    iv_len = unhexify( iv_str, hex_iv_string );
+    add_len = unhexify( add_str, hex_add_string );
+
+    TEST_ASSERT( gcm_init( &ctx, (cipher_id_t) cipher_id, key_str, key_len * 8 ) ==0);
+    
+    TEST_ASSERT( gcm_crypt_and_tag( &ctx, GCM_ENCRYPT, pt_len, iv_str, iv_len, add_str, add_len, src_str, output, tag_len, tag_output ) == 0 );
+    hexify( dst_str, output, pt_len );
+    hexify( tag_str, tag_output, tag_len );
+
+    TEST_ASSERT( strcmp( (char *) dst_str, hex_dst_string ) == 0 );
+    TEST_ASSERT( strcmp( (char *) tag_str, hex_tag_string ) == 0 );
+    
+
+    gcm_free( &ctx );
+}
+
+void test_suite_gcm_decrypt_and_verify( int cipher_id,
+                             char *hex_key_string, char *hex_src_string,
+                             char *hex_iv_string, char *hex_add_string,
+                             int tag_len_bits, char *hex_tag_string,
+                             char *pt_result, int init_result )
+{
+    unsigned char key_str[128];
+    unsigned char src_str[128];
+    unsigned char dst_str[257];
+    unsigned char iv_str[128];
+    unsigned char add_str[128];
+    unsigned char tag_str[128];
+    unsigned char output[128];
+    gcm_context ctx;
+    unsigned int key_len;
+    size_t pt_len, iv_len, add_len, tag_len = tag_len_bits / 8;
+    int ret;
+
+    memset(key_str, 0x00, 128);
+    memset(src_str, 0x00, 128);
+    memset(dst_str, 0x00, 257);
+    memset(iv_str, 0x00, 128);
+    memset(add_str, 0x00, 128);
+    memset(tag_str, 0x00, 128);
+    memset(output, 0x00, 128);
+
+    key_len = unhexify( key_str, hex_key_string );
+    pt_len = unhexify( src_str, hex_src_string );
+    iv_len = unhexify( iv_str, hex_iv_string );
+    add_len = unhexify( add_str, hex_add_string );
+    unhexify( tag_str, hex_tag_string );
+
+    TEST_ASSERT( gcm_init( &ctx, (cipher_id_t) cipher_id, key_str, key_len * 8 ) == init_result );
+    if( init_result == 0 )
+    {
+        ret = gcm_auth_decrypt( &ctx, pt_len, iv_str, iv_len, add_str, add_len, tag_str, tag_len, src_str, output );
+
+        if( strcmp( "FAIL", pt_result ) == 0 )
+        {
+            TEST_ASSERT( ret == POLARSSL_ERR_GCM_AUTH_FAILED );
+        }
+        else
+        {
+            TEST_ASSERT( ret == 0 );
+            hexify( dst_str, output, pt_len );
+
+            TEST_ASSERT( strcmp( (char *) dst_str, pt_result ) == 0 );
+        }
+    }
+
+    gcm_free( &ctx );
+}
+
+#ifdef POLARSSL_SELF_TEST
+void test_suite_gcm_selftest()
+{
+    TEST_ASSERT( gcm_self_test( 0 ) == 0 );
+}
+#endif /* POLARSSL_SELF_TEST */
+
+
+#endif /* POLARSSL_GCM_C */
+
+
+int dep_check( char *str )
+{
+    if( str == NULL )
+        return( 1 );
+
+    if( strcmp( str, "POLARSSL_AES_C" ) == 0 )
+    {
+#if defined(POLARSSL_AES_C)
+        return( 0 );
+#else
+        return( 1 );
+#endif
+    }
+
+
+    return( 1 );
+}
+
+int dispatch_test(int cnt, char *params[50])
+{
+    int ret;
+    ((void) cnt);
+    ((void) params);
+
+#if defined(TEST_SUITE_ACTIVE)
+
+/* Structure of the parameters: 
+gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:"fb8094dd2eddb3d8004bb79134023ca2be4de9b668a9e4608abdf2130e8becb8":"":"491a14e13b591cf2f39da96b6882b5e5":"":"":128:"80883f2c925434a5edfcefd5b123d520":0
+
+*/
+
+       
+        /* 
+param 0 = function (encrypt/decrypt)        
+param 1 = cipher id 
+param 2 = key
+param 3 = src
+param 4 = iv 
+param 5 = add
+param 6 = dest
+param 7 = tag len in bits
+param 8 = tag 
+param 9 = result 
+   */
+   
+
+    if( strcmp( params[0], "gcm_encrypt_and_tag" ) == 0 )
+    {
+ 
+
+        int param1;
+        char *param2 = params[2];
+        char *param3 = params[3];
+        char *param4 = params[4];
+        char *param5 = params[5];
+        char *param6 = params[6];
+        int param7;
+        char *param8 = params[8];
+        int param9;
+
+        if( cnt != 10 )
+        {
+            fprintf( stderr, "\nIncorrect argument count (%d != %d)\n", cnt, 10 );
+            return( 2 );
+        }
+
+        if( verify_int( params[1], &param1 ) != 0 ) return( 2 );
+        if( verify_string( &param2 ) != 0 ) return( 2 );
+        if( verify_string( &param3 ) != 0 ) return( 2 );
+        if( verify_string( &param4 ) != 0 ) return( 2 );
+        if( verify_string( &param5 ) != 0 ) return( 2 );
+        if( verify_string( &param6 ) != 0 ) return( 2 );
+        if( verify_int( params[7], &param7 ) != 0 ) return( 2 );
+        if( verify_string( &param8 ) != 0 ) return( 2 );
+        if( verify_int( params[9], &param9 ) != 0 ) return( 2 );
+
+        fprintf( stdout, "\nExecuting the loaded test (encryption).");
+        test_suite_gcm_encrypt_and_tag( param1, param2, param3, param4, param5, param6, param7, param8, param9 );
+        return ( 0 );
+    }
+    else
+    if( strcmp( params[0], "gcm_decrypt_and_verify" ) == 0 )
+    {
+
+        int param1;
+        char *param2 = params[2];
+        char *param3 = params[3];
+        char *param4 = params[4];
+        char *param5 = params[5];
+        int param6;
+        char *param7 = params[7];
+        char *param8 = params[8];
+        int param9;
+
+        if( cnt != 10 )
+        {
+            fprintf( stderr, "\nIncorrect argument count (%d != %d)\n", cnt, 10 );
+            return( 2 );
+        }
+
+        if( verify_int( params[1], &param1 ) != 0 ) return( 2 );
+        if( verify_string( &param2 ) != 0 ) return( 2 );
+        if( verify_string( &param3 ) != 0 ) return( 2 );
+        if( verify_string( &param4 ) != 0 ) return( 2 );
+        if( verify_string( &param5 ) != 0 ) return( 2 );
+        if( verify_int( params[6], &param6 ) != 0 ) return( 2 );
+        if( verify_string( &param7 ) != 0 ) return( 2 );
+        if( verify_string( &param8 ) != 0 ) return( 2 );
+        if( verify_int( params[9], &param9 ) != 0 ) return( 2 );
+
+        fprintf( stdout, "\nExecuting the loaded test (decryption).");
+        test_suite_gcm_decrypt_and_verify( param1, param2, param3, param4, param5, param6, param7, param8, param9 );
+        return ( 0 );
+
+    }
+    else
+    if( strcmp( params[0], "gcm_selftest" ) == 0 )
+    {
+    #ifdef POLARSSL_SELF_TEST
+
+
+        if( cnt != 1 )
+        {
+            fprintf( stderr, "\nIncorrect argument count (%d != %d)\n", cnt, 1 );
+            return( 2 );
+        }
+
+
+        test_suite_gcm_selftest(  );
+        return ( 0 );
+    #endif /* POLARSSL_SELF_TEST */
+
+        return ( 3 );
+    }
+    else
+
+    {
+        fprintf( stdout, "FAILED\nSkipping unknown test function '%s'\n", params[0] );
+        fflush( stdout );
+        return( 1 );
+    }
+#else
+    return( 3 );
+#endif
+    return( ret );
+}
+
+#if defined(FILESYSTEM)
+int get_line( FILE *f, char *buf, size_t len )
+{
+    char *ret;
+
+    ret = fgets( buf, len, f );
+    if( ret == NULL )
+        return( -1 );
+
+    if( strlen( buf ) && buf[strlen(buf) - 1] == '\n' )
+        buf[strlen(buf) - 1] = '\0';
+    if( strlen( buf ) && buf[strlen(buf) - 1] == '\r' )
+        buf[strlen(buf) - 1] = '\0';
+
+    return( 0 );
+}
+#endif
+
+int parse_arguments( char *buf, size_t len, char *params[50] )
+{
+    int cnt = 0, i=0;
+    char *cur = buf;
+    char *p = buf, *q;
+
+    params[cnt++] = cur;
+
+    //fprintf(stdout, "parse_arguments - begin");
+
+    while( *p != '\0' && p < buf + len )
+//    while( i < len )
+    {
+        if( *p == '\\' )
+        {
+            p++;
+            p++;
+            continue;
+        }
+        if( *p == ':' )
+        {
+            if( p + 1 < buf + len )
+            {
+                cur = p + 1;
+                params[cnt++] = cur;
+            }
+            *p = '\0';
+        }
+
+        p++;
+    }
+    //fprintf(stdout, "parse_arguments - middle");
+    
+    // Replace newlines, question marks and colons in strings
+    for( i = 0; i < cnt; i++ )
+    {
+        p = params[i];
+        q = params[i];
+
+        while( *p != '\0' )
+        {
+            if( *p == '\\' && *(p + 1) == 'n' )
+            {
+                p += 2;
+                *(q++) = '\n';
+            }
+            else if( *p == '\\' && *(p + 1) == ':' )
+            {
+                p += 2;
+                *(q++) = ':';
+            }
+            else if( *p == '\\' && *(p + 1) == '?' )
+            {
+                p += 2;
+                *(q++) = '?';
+            }
+            else
+                *(q++) = *(p++);
+        }
+        *q = '\0';
+    }
+    //fprintf(stdout, "parse_arguments - end");
+
+    return( cnt );
+}
+
+
+int main()
+{
+#if defined(FILESYSTEM)
+    LocalFileSystem local("local"); 
+    const char *filename = "/local/test_suite_gcm.aes256_en.data";
+    FILE *file;
+    int i;
+#endif
+    
+    int ret, cnt, total_errors = 0, total_tests = 0, total_skipped = 0;
+
+#if defined(POLARSSL_MEMORY_BUFFER_ALLOC_C)
+    unsigned char alloc_buf[1000000];
+    memory_buffer_alloc_init( alloc_buf, sizeof(alloc_buf) );
+#endif
+
+    fprintf( stdout, "Starting tests...\n" );
+
+
+#if defined(FILESYSTEM)
+
+    char buf[5000];
+    char *params[50];
+
+    file = fopen( filename, "r" );
+    if( file == NULL )
+    {
+        fprintf( stderr, "Failed to open\n" );
+        return( 1 );
+    } else {
+        fprintf( stdout, "Opening test data file\n" );
+
+    }
+        
+
+    while( !feof( file ) )
+    {
+        int skip = 0;
+
+        if( ( ret = get_line( file, buf, sizeof(buf) ) ) != 0 )
+            break;
+        fprintf( stdout, "%s%.66s", test_errors ? "\n" : "", buf );
+        fprintf( stdout, " " );
+        for( i = strlen( buf ) + 1; i < 67; i++ )
+            fprintf( stdout, "." );
+        fprintf( stdout, " " );
+        fflush( stdout );
+
+        total_tests++;
+
+        if( ( ret = get_line( file, buf, sizeof(buf) ) ) != 0 )
+            break;
+        cnt = parse_arguments( buf, strlen(buf), params );
+
+        if( strcmp( params[0], "depends_on" ) == 0 )
+        {
+            for( i = 1; i < cnt; i++ )
+                if( dep_check( params[i] ) != 0 )
+                    skip = 1;
+
+            if( ( ret = get_line( file, buf, sizeof(buf) ) ) != 0 )
+                break;
+            cnt = parse_arguments( buf, strlen(buf), params );
+        }
+
+        if( skip == 0 )
+        {
+            test_errors = 0;
+            ret = dispatch_test( cnt, params );
+        }
+
+        if( skip == 1 || ret == 3 )
+        {
+            total_skipped++;
+            fprintf( stdout, "----\n" );
+            fflush( stdout );
+        }
+        else if( ret == 0 && test_errors == 0 )
+        {
+            fprintf( stdout, "PASS\n" );
+            fflush( stdout );
+        }
+        else if( ret == 2 )
+        {
+            fprintf( stderr, "FAILED: FATAL PARSE ERROR\n" );
+            fclose(file);
+            exit( 2 );
+        }
+        else
+            total_errors++;
+
+        if( ( ret = get_line( file, buf, sizeof(buf) ) ) != 0 )
+            break;
+        if( strlen(buf) != 0 )
+        {
+            fprintf( stderr, "Should be empty %d\n", (int) strlen(buf) );
+            return( 1 );
+        }
+    }
+    fclose(file);
+#else // NO FILESYSTEM
+    char *params[50];
+
+#define NR_TESTS 44 // 167
+
+char (*(tests[])) = {
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"fb8094dd2eddb3d8004bb79134023ca2be4de9b668a9e4608abdf2130e8becb8\":\"\":\"491a14e13b591cf2f39da96b6882b5e5\":\"\":\"\":128:\"80883f2c925434a5edfcefd5b123d520\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"725313f4cb3f6a0d29cefc174b7e4f43cef11b761ef75e1995cb64c1306795f1\":\"\":\"27d1ed08aba23d79fc49ad8d92a2a0ea\":\"\":\"\":128:\"d5d6637ba35ef2ad88e9725f938d3d2d\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"4e766584ce0e885e1bba1327e5335796de0831a40f74a5cec178081dd15bfd10\":\"\":\"cece0dea024ff47851af0500d146cbfe\":\"\":\"\":128:\"1abe16eeab56bd0fb1ab909b8d528771\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"ce7f2207f83a952451e714ba3807ddb3ed67c2739a628980411aa68366b1f2f5\":\"\":\"652fd951ace288db397020687135a5d1\":\"\":\"\":120:\"985227b14de16722987a3d34976442\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"855f8fa4ec6a1206173509d504d0b29dfbfbfa9aa528254b189cd72e6ebc1c1f\":\"\":\"1ad1507e6463e4e2e1a63155ac0e638f\":\"\":\"\":120:\"693146a8b833f324c1d4cbeeb8c146\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"ef8dd1294a85dd39e366f65e1076d53e046188c06c96b2c9e84ebc81f5c9f550\":\"\":\"9698a07447552d1a4ecd2b4c47858f06\":\"\":\"\":120:\"b00590cac6e398eeb3dcb98abe1912\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"25896e587570ff1823639e1e51e9c89192d551b573dd747e7c0c1c10916ece4c\":\"\":\"f0516457c09c372c358064eb6b470146\":\"\":\"\":112:\"5a7cadec600a180e696d946425b0\":0"}, 
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"02fc9cfffbe72e7954182993088e09d24ea8cad91a8ca9a336d9f1fe4156486d\":\"\":\"0e189e162e097eb2060b30c46d9afa70\":\"\":\"\":112:\"7d3d5cc55e6182ec5413ef622d4f\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"f24e3d631d8961d3d4b9912d4fa7a317db837a7b81cd52f90c703a4835c632e2\":\"\":\"510740bfa2562ce99ca3839229145a46\":\"\":\"\":112:\"1402ddc1854e5adb33664be85ad1\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"720ab5aceb80ff1f864379add9b0d63607227f7c3f58425dd6ec3d4cea3fe2ea\":\"\":\"58f2317afb64d894243c192ef5191300\":\"\":\"\":104:\"e8e772402cc6bfd96a140b24c1\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"f57dd16fa92a8f8c09d8f13cb5b6633a43b8762e90c670232f55949cdfdf700c\":\"\":\"3b7c14ee357b3c6b0dc09e3209ab69f2\":\"\":\"\":104:\"43e609664e48ad1f5478087f24\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"87c17ab919a4bc0d50343c0bb282a969283c2ada25f9a96d2858c7f89bc5139a\":\"\":\"02813d3faf30d3e186d119e89fe36574\":\"\":\"\":104:\"d1a1f82a8462c783b15c92b57e\":0"}, 
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"dd8d5b6c5c938c905c17eab9f5ab7cd68d27f3f09d75177119010d070b91e646\":\"\":\"1df1c3ad363c973bffe29975574ffdf6\":\"\":\"\":96:\"749ac7ffda825fc973475b83\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"4d60a14cb789099c77b8991e7b0b40f787d3458f448501e8108e4d76110f94ef\":\"\":\"ca6b3485eb5dcd9dbfa7cffcdb22daa5\":\"\":\"\":96:\"3f868b6510d64098adc1d640\":0"}, 
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"405b690717de993ad945d80159c2800848060de0b7d2b277efd0350a99ba609a\":\"\":\"63730acb957869f0c091f22d964cc6a3\":\"\":\"\":96:\"739688362337d61dab2591f0\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"ab5563a387e72d7d10468c99df590e1de25ec10363aa90d1448a9ffcd1de6867\":\"\":\"c511406701bad20a2fa29b1e76924d2f\":\"\":\"\":64:\"390291ed142ba760\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"abef7c24daaa21f308a5af03df936ba3f70aa525190af0d959d6e50d836f4624\":\"\":\"e9f15950130b9524e2b09f77be39109a\":\"\":\"\":64:\"db2fb2b004bc8dc4\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"6ca630b0b6779a8de7a19e5279eac94bf29f76f8b0cf8ecf8f11c4f8eb04aa0d\":\"\":\"7373befc2c8007f42eef47be1086842f\":\"\":\"\":64:\"e2b8620bcc7472a8\":0"}, 
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"acea7818a71df2c9840aef1c10ecbe2bac7e92216388416a2f36119a0745d883\":\"\":\"6d46aa39fb5a6117e9adf7ee72bc50ff\":\"\":\"\":32:\"fd5ff17b\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"b301036d4b2b28b8a4502925986861eba2b67c24cb0c79c63fd62195d9b67506\":\"\":\"bb6f398e5aed51590e3df02f5419e44d\":\"\":\"\":32:\"47f3a906\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"89576d2aac554c8982c7df0053be9ab19f4bd80ba9f3dd433c1c054d68e68795\":\"\":\"aedbd482a401a7c12d4755077c8dd26e\":\"\":\"\":32:\"506fa18d\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"43c9e209da3c1971d986a45b92f2fa0d2d155183730d21d71ed8e2284ec308e3\":\"\":\"78bef655dfd8990b04d2a25678d7086d\":\"9d8c6734546797c581b9b1d0d4f05b27fe0539bd01655d2d1a8a1489cdf804228753d77272bf6ded19d47a6abd6281ea9591d4bcc1be222305fdf689c5faa4c11331cffbf42215469b81f61b40415d81cc37161e5c0258a67642b9b8ac627d6e39f43e485e1ff522ac742a07defa3569aeb59990cb44c4f3d952f8119ff1111d\":\"\":128:\"f15ddf938bbf52c2977adabaf4120de8\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"fbe2d52b7f50bf23a16ff8cd864215034fdfbf4d1506ca3c1ffb015653efe33a\":\"\":\"b155f8ab1a8c0327789cfb8310051f19\":\"ed8d14adf1c362bbaf0d569c8083278e8225f883d75d237a4abcd775a49780603e50c00a1b5b5946c085e57a749b4946f6aca96eda04ac9944a7d3d47adc88326ed30a34d879dd02fb88182f9e2deefaeee1c306b897539fa9075bda03ba07b4ffff71ce732ef3c4befac0f18c85a0652d34524ccb1a4747ab8f72ed1c24d8fc\":\"\":128:\"c5fe27ca90e5c8b321cc391ee7f1f796\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"8e888721514fd01fb67513cb56bfd29af67a9ce525e3e697af47450f02053161\":\"\":\"9f6bd4a93e4f3f2f5f4a7c2c5b4790bf\":\"867d50923967535ce6f00395930083523c22f373cfb6c8817764f5623cd60b555572404e54f2fe7083ef32b9a4593a1f70a736d6e8fe61b77def51f3b1d8f679d3a8d50d0aad49e51ec1eb4d4a25f13d14f3e5253555c73eac759e484c6131cc868b46c18b26acd040c3e1cb27afecba7b7fc3f5ff4883f4eafc26c7f3084751\":\"\":128:\"ea269094330b6926627889fcdb06aab4\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"d8f82b07e7319ca607c9aa0352070ca883dd7b32af370a774f63b0270f44835a\":\"\":\"e89e4484497cb728f86585d8918b7fae\":\"42340d96e1852de3ed5e30eb4a05e1fb222480b450e2bf4e2cf0fb2a525eb6602ef43a896adc5c52ea5381c642b2175691c014e7a6dae91fa6ff5b95c18a2dd2e8838d3abd46ace0b305f3f22d30a0bd82a81bbf6753362b54b0624c76c0d753e30eb636365f0df7e1bf8bf130cf36062ec23f58a3f7ed0ae7bfbbd68460cd76\":\"\":120:\"b234b28917372374e7f304f1462b49\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"b49b04a54a08d28b077ea54c18bfa53e916723e91453b47f88e399046b9b4dcc\":\"\":\"6276c577c530f91b434ce5719e1c59de\":\"6b73f996c49e368fc4d21816153aefb081509f9dc0916dbe4fdf77f39867a2bd617b8a75f39f515b1bc1454009d5247efcd90ba0d4a6743c6f12a929b666584f3b55254c32e2bab2321f94fa843dc5124c341dd509788a158191ee141eb0bc4e1b96f6987bafe664a0f9ac6d85c59cee9564a27bcc37dffae80c57fbf7e748ce\":\"\":120:\"69dd5bdeb15fdbc3a70c44b150f70e\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"398bb37bb991898c7dad7bf5930dbad20d121f68d5ec6c56ffe66f23c0c37f8e\":\"\":\"0c3bd55b54c1221b0cf25d88ea4dfe24\":\"4c48b929f31180e697ea6199cd96c47cecc95c9ed4c442d6a23ca3a23d4b4833601ac4bbcdbc333cd1b3a0cd90338e1c88ef8561fed7ad0f4f54120b76281958995c95e4c9daabff75d71e2d5770420211c341c6b062b6c8b31b8fe8990588fbad1e651a49b0badd9a8d8042206337a1f2aa980b3ba3b5ee8e3396a2b9150a34\":\"\":120:\"8528950bd5371681a78176ae1ea5dc\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"8e8f7c317b22dea8eabe7eaa87413a98ff56570720985b6743a5f9af56387cca\":\"\":\"3a9a5a839045723afdfb2d5df968bfcb\":\"a87d95f8f47e45a1c7c5c58d16055b52b3256c52713fd092bcd6cbc44e2c84669f23ca2a19e34163ee297f592f6054dbc88863a896c2217e93a660d55a6cd9588a7275d05649940d96815c7ddfa5fc4394c75349f05f1bcaff804095783726c0eceb79833a48cefd346b223f4e5401789684e5caeda187a323962a1f32f63f02\":\"\":112:\"faad6a9731430e148ace27214e68\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"67c95e57197f0e0bbaaa866d337fcc37f3a10dc55a059f5ea498de204d2fff61\":\"\":\"5f171d203c653a316cac43df99f4033a\":\"84f281b388ca18bc97323657a723a56260731234720b02b6dde00ea134bd84a1893bec38af80214c4da01b93958ab00f3b648c975371e565d5b6bf2a8f63c0f3cfcd557c9f63574390b6ae533085aca51fa9d46cd2478b7648b6dcbbac7e61197a425778debe351ac2110ba510a17e2c351ba75d5a755ef547cf9acc54650222\":\"\":112:\"9ea9c716e06a274d15a3595a0c41\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"9143f00e31c72bd9fced31585d047f67f1004e6244c3d9c10c8ae005feeabc84\":\"\":\"e49cd6af9a2f0da2a7198317da92ab2f\":\"ab9193a155140d265aabfe2dd5efca7d3fa6129498532bccd77f09fa1a480702620b3ab53df91b01262122f1a6fc387b5fc55dadfcdb99ada83d4a5b0666c8526de309f41eb54d69b52595c43550a6bf7b4b8f0e0c48311b521762eaa567744c4c4704dd977f84068b59db98a67e33cc65302ba59360d600a22138c5ad3317f3\":\"\":112:\"8293e361fe0308a067f89aea393f\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"d0ba180075c373116bb037907b512add00ba9a4693a8ecc14ca0d79adada90e3\":\"\":\"5c1501b19cce5404dccc9217ac8253b7\":\"3a161605ec0055c479dd48cdaeed5981b8b60fb7b7781cc4e580218c7014c3060a9f706e6e16cf4021e4d38deb512534b484ff23b701975bdf901146ccaece9c3ffbbeeb172cfb64a915ae0dbe7a082b9077776a387b58559a881b9b79b90aa28ad1ac0f2bece314169a2f79ea4c08389f7f7dd10ee2d9a844fee79e7bf38bcf\":\"\":104:\"0541262fddfd5d01ff0f3c2fb4\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"c975c7e59133c231d1b84c696761c413ba20aff7fb7d854c6947e65db3cc57b4\":\"\":\"d8fedda4cccaf6b0818edcfa7b1f03fa\":\"cb4cc9171367d6422abfaf2b4452da267eb9ccf1c4c97d21a0a125de486997832d16c7e412cb109eb9ac90c81dfe1a1dd9f79af7a14e91669b47f94e07d4e9bd645d9daa703b493179ca05ddd45433def98cf499ff11849cc88b58befbdd388728632469d8b28df4451fc671f4a3d69526a80c2e53e4fdee6300d27d97baf5f4\":\"\":104:\"77ac205d959ec10ae8cee13eed\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"a86ec688222c50c07274ed2d2c8ae6f883e25f8f95d404a7538fd83224199327\":\"\":\"99c73fdb8f97f225f7a17cf79c011112\":\"cf5f707de0357262c0997fa3ebfe6e07192df8db5f029e418989e85e6b71e186b00c612ecedbfe3c847e58081847f39697337ae7c815d2cd0263986d06bf3a5d2db4e986dbe69071fd4b80a580f5a2cf734fc56c6d70202ea3494f67539797252d87cd7646296932959c99797a0446532f264d3089dd5f4bcceaaa7289a54380\":\"\":104:\"c2093ad4705e613b09eee74057\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"d3981f0aa1ed8cb369d9b0d7b0e529ec6089ff2d226c542885b1bff55276e891\":\"\":\"7331f91bd1a67c21c9dd336a2a922839\":\"406d9cf45fc8618d564154241dc9c006ecdcd847406e5a6e7127ac96e7bb93f4c339ff612c514b6f66df95a0845035d7535212a2aaeeb0ee512d1f4375c9a527e4e499389c2d7f7f7439c913ea91580e7303767b989c4d619df7888baf789efd489b08eda223f27da5e177cd704c638f5fc8bf1fecfcd1cab4f4adfbc9d1d8ba\":\"\":96:\"dbb7ec852c692c9a0e1a5acd\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"8436967f97c59ca73b760b73c6e088d1da4e76b712188ab4781d8d849505ae47\":\"\":\"9401dd0998914645668d06d518bfe7d7\":\"a5f40906177417097c19a0a21dbb457a694e173141837f695b09c8eb58ac2ce28aace4e59275b6266da9369a9905b389e968aefc64d78c7e1d2f034ef413d3458edcb955f5cd7971c28cd67dc9901ef3a2abc6121704bb5ecd87a6568d0506abbc87a2f10205dc8eb0cd1b5109158d0e743c2c3a342d60b8d55bbcb8d8507ed1\":\"\":96:\"dd6d988d352decc4e70375d8\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"ce6b846bcedc6ae747e66e72cd9f7664e6cad9627ba5f1f1923f3d3a6ed590d1\":\"\":\"ac865ff8a6255e501b347a6650510d05\":\"1658b9f8469af1dfa60458cf8107db1edd1e4bba70a0bd23e13e1bba0d397abf51af8348f983fcdfcc8315ef1ffc9a26371377c62ddba08363bd2bf0ff7d0c3b603fad10be24ecee97b36d2255a8b2efc63f037123cef4bb4fe384aa0c58548b2f317c36ef3ef204b24769de6ba3e9d89e159e2bf1f9d79aeb3eb80c42eb255e\":\"\":96:\"7ee87acd138c558455fff063\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"0038ecf1407bbf0d73afa5e010769b71e8649c4249345dcf923ef9da0254c6af\":\"\":\"74c6b98fc6ced3a59bd9c42d31d71095\":\"467f483c71c3404fe7f09d6f6b6b64c3b7613a0dd32470cf24bc590d3994a48f3e8cd5dc19ea8ca7d5366ad7c5ad31cc9612dafedaea109dde2aedfe5fc2a0db2c903dd1dc1a13949720a10babf37fba5a0ed7cb5f3dc9eb5a4d8331f218e98763e7794b3e63705d414ef332160b0b1799f1ff5cbe129a75e5c4e0a4ed35e382\":\"\":64:\"62fe088d9129450b\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"19fc4c22151ee8515036c38bc5926c0e0bbd93db5d0fc522b2a6bf6298fed391\":\"\":\"9547f056c6fb9ef72b908f527cb500c1\":\"511b15c25b2a324159e71c3b8e47f52d3e71e5bc35e774c39067250f4494c9c4eb184ecbe8638de9418672d9ae2c6a0e7f54c017879ffb2a371de1639693d654a43cb86e94a7350508490191790d1265b99e7b3253838b302aae33590949a8761a3bb2aeb1ba798cddeb00a53daad05a33389d4a19269d65116a84f12dba5830\":\"\":64:\"04623912bb70810e\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"3b5d3b1920b5a105b148153ae1f1027c6d48bc99640ea853f5955fed4eb3d625\":\"\":\"9a4091c2eb7e88759bd9169fee303485\":\"aa680d07143ba49a9099d555105fc3cfcb898cec11ade96776dc9778cc50fe972e1e83c52c837b71e27f81d1577f9bd09afe2260dfd9a5d9dfbd3b8b09a346a2ab48647f5dd2ff43700aecce7fa6f4aeea6ea01b2463c4e82ec116e4d92b309c5879fb4e2ca820d0183a2057ae4ad96f38a7d50643a835511aedd0442b290be3\":\"\":64:\"033bfee6b228d59b\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"f6c4ad8e27764157789252f4bc4a04145cb9721955330a2f6a2a3b65cacf22bc\":\"\":\"3de136cbd75061c888226efab136849d\":\"0f6951c127d6bc8970e2ad2799e26c7fb9ca31d223155f88374984b5660626c83276ffa6c160f75e0e1bcfa96616188f3945b15fc1b82a4e0ee44000a684b3c3840465aebe051208379ef3afe9f569ee94973d15f0a40c6f564fa4ba11d6e33cf8ae17854a9e12360a2b8495e2cceec463f5e3705c74069ba37ba6d725f458c0\":\"\":32:\"f658c689\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"30cd99fed9706c409e366d47fefc191f79bcc47a28be78f9890fd90d4864eb85\":\"\":\"8c7ce34691503bf14c776f8809f24e61\":\"4b6b10c2e2905ab356769b6453dd160a08e8623b0878fcc1c1d64822f0aea1f4f5b4698ded5d23ebafa11bc1e4ce9e5cd7d7c7b13de02d11a945ba8361b102ba49cdcfd6a416e3db774cd7bda024fccd1ad3087560dc15bbfe9b1a5c6c71fae17a329f104f6c2cba7eb6a7459535ca328146d0ccc0a9bd28a3d1c961947a3876\":\"\":32:\"7777c224\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"9472f2452933dcfac4bb22831ce83c6a1ddf25ef8d2d3ba59d72b0d173a986e8\":\"\":\"18fb2c34b0955d712960009617d300ef\":\"d283dd75cd4689c266c8e0b4b6586278aa2583c7c41bf12bd1cfdef21d349acbbabc0a2204dc4130f922949206c4fbdce3786ab8614e32908838a13b6990453abf14b84f5812e6093644accdd35f7ad611ea15aefae28b3cf1fc5da410bcea4f0a50d377fdcceffe488805bc5a71fab019b12fa8725d6e7c91e6faf12fbaf493\":\"\":32:\"c53b16a1\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"e06d5319210f4107ea7267fa2e8183fcbf74fd3b0579b856577177d9cb307d42\":\"2b9179d21cb884581b0e4f462455167f1f7899717245d4aed3d8db5983daccccebfc2130a20c284563bea5997cc0438c83d8fa7bb9e3588efed285a0fcc31456dc9a3122b97bb22f7edc36973475925828c323565e417ec95190db63b21881016b5332f2e400bb4724c86a8ee0247149370ee5412f743dc6bf7ca5bcc31afa0f\":\"f2b0564705430bc672964b049115e122\":\"\":\"3fa342a76cb5d501e6a6fade14aab54a76620e4ea2287147d4ca2b9d62d2a643591e5df570ef474ee88ad22401c1059e3130a904e9bf359c4a6151ff2f3e4f78ef27a67d527da8e448b0ef5cdcfec85f3525e35f8d024540387e4cdcb1018c281a1af7d4a3688a0fec4d9f473c816f7d4c4c369f70d7dfe8f1b7fa4f581098a1\":128:\"18f186ed1ee1f4f8b29db495587d0ab0\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"0dfa834e98b6c51ee925dd9edc9be72c209ddcd9099ded57b533f2236895a229\":\"7f4e4f11091bf51976c0fc71ecbcd0985cdad2135549c818c09567801d8a9a42c719aab7dc2cb58a10b5067d14c52cabe6bb9b939e7b9cd395eaf10ba6a53fd2e6446e1e501440134e04e662ef7ebb1c9c78bbd3fd7cb9de8b985418be1b43ebb5d7902ccb4c299c325c8a7cc1de9174f544bc60828c1eebad49287caa4108a0\":\"a101b13b238cfac6964fd6a43daea5a7\":\"\":\"bc60d2047fd8712144e95cb8de1ffd9f13de7fda995f845b1a4246a4403f61ca896bd635a1570d2eb5b8740d365225c3310bf8cea3f5597826c65876b0cbcfa0e2181575be8e4dd222d236d8a8064a10a56262056906c1ac3c4e7100a92f3f00dab5a9ba139c72519b136d387da71fefe2564d9f1aa85b206a205267b4cfa538\":128:\"c4cc1dbd1b7ff2e36f9f9f64e2385b9e\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"ce59144b114ac5587a7a8079dc0e26f1b203338bb3e4b1d1d987bddc24150a82\":\"bc7aa1b735a5f465cffeccd8dd4b0a33a571e9f006dc63b2a6f4df272a673bb2cc00e603248ab6be5627eebc10934fe4d1dc5cd120a475936eefa2c7bddea9f36c6c794d2c6bd2594094e56cac12d8f03e38f222a7ee4fc6c2adffe71c9c13003e301c31ff3a0405dde89bb213044d41782c4bb4eb3c262595d1c0e00522047c\":\"fdc5a40677110737febae4465b1a76cc\":\"\":\"084c31c8aef8c089867f6e0ce6e0aadafa3016c33c00ca520f28d45aac8f4d02a519b8ebafd13b9606ab9db4f2572f396091bc5a1d9910119ca662d476c2d875a4ab62d31ff5f875678f25a4775fa7fc85b1a3d442fb2c5047a3d349d56d85f85f172965e6477439045849a0b58014d9d442e2cae74709ed8594f0ec119d1d39\":128:\"4c39e0d17030a5f06ecd5f4c26e79b31\":0"}};
+/*(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"e7a6b459a5370ceec4d429bba9472a49db07697dc66dbc2f294d3e62ffc8aac1\":\"cb959e5611a636317feb5265d33b315c2f5af64159029f0032e338babbdb0a525ba6b92cb3be7db9f0077561e6cffe1247bad32dea8918f562dc3cd83225cdbcaed652b87c62fea8eff153638a3a14ef9f9a88bcc8c9a6b65fa9dcc53f63d1b14fb9bb0baf17e7bfb95690c25cca2c3097497e41f7e2299a8518d5d1c5f6264e\":\"92468d42ad377affa7e808d95d8c673a\":\"\":\"599dbc47e2f2e3b06b641c510b238417b01869f0e7d08619752f6d9f4b08585731deaeb439ff26e02d7e51b45ca5e3d4a779fe4cfc9572d1d6407f98de69a8fca60bf01d1a769130bb38a67933a2be3aa3ea1470d8f32a34dc863dc800feb7ef71588edd9489bd59a23685ff5358f9b562fc0bbad9e11db7a6fedbd79225539d\":120:\"e853262ed43e4d40fea6f3835d4381\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"9818904a99e3d80c95dc71a16483ade1b9b8e7df638ce6a4c1d709a24416cbe9\":\"2c073cdc11a8d58fb55e1dadbbc0372dde86c387fa99c9249bd04cb2f2d239de01bec8c8771a9fb33664ee06ea81c37a824525664054173b63a2894d8d7ffc60b9e93052802478a189be5835d979a28ce7025b219add0622f97c9bcf3ecf629b56408ed002a141061320400409345e94a7a7e3906611305f96f2abc9d62cc435\":\"96a301ab6bc0309be9735bd21cc9e10d\":\"\":\"4876e449b0cac09a37bb7e4b8da238f4c699af9714ec4fcf21a07c5aee8783311a13149d837a949c594a472dda01e8b6c064755b6328e3ef8d6063f8d8f19cfda3147b563b0f5fb8556ace49cb0f872822a63b06f261b6970f7c18be19372a852beadf02288c0b4079587c0f8eab1858eeec11c6ba8d64448282068fddd8a63d\":120:\"e1e8b62ce427e5192348b1f09183c9\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"9b34f137e3f37addad8a6573b8b6dac9a29e97db53c0a7610f37c72a0efaebfa\":\"c1e09c432c68a2c119aeb3b19c21180e3c8e428e12033f416a92862036f5e8a39a8893b10fe5476e388d079143ee0b79b183a3400db779cfbf1467d69887306b124a8578c173cd5308d4448eefcf1d57f117eb12bc28bd1d0ff5c3702139655197d7305bda70181c85376e1a90fb2c5b036d9ea5d318d3219132ea6c5edf7b7d\":\"50dddb2ebe4f8763509a63d07322277e\":\"\":\"793e1b06e1593b8c0ba13a38ff23afaa6007482262bc2d0de9fb910f349eff88d3dd05d56eb9a089eed801eae851676b7a401991b72bf45ac005c89e906a37ed7231df4aeeeb1fcf206ca1311117e7e7348faf1d58acc69c5702f802287083d3ed9e16cf87adcdfa1bb0c21c40c2102fd0def91985f92285e6ea1cdd550e7f50\":120:\"b3c6ae17274faaca657dcb172dc1fb\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"66b40e2e671bdf244b45644d1a5adc63011b32156ba9f5e03dffacc1a9165061\":\"985546ee12ba89d95988ad8a4153c4f9d3c91c0e3633a95b4f9b588bba0032006c93210514357c91d574b436da13dc9f68194a981e7b65eb79e56be9cf1dabfdf531407727c034a3c7743bb22aa02b26f159c2eff3c7ed52027de2e8b8b2fefb72c04fbf20a1ffe10d6dda790a9812cdbe9f2ed6706d7a2639e851a42870efb8\":\"4e090871e889b4be36db5e1df1ea283d\":\"\":\"f93eebffeddfd16b4618b893d57b459b704b894b38a5eaf6cce54026c80090be8328e12261e1b10e81c73ac8261c2982bb25603c12f5ffff5c70b2199515c17200db2d950a3f2064d7b362607adbf3686f27420ec15e18467e86faa1efa946a73c8888b8fdc825742b8fbec6e48cdabbb45f3cd2b6b6e536b6fbf3429aebe934\":112:\"ed88c856c41cac49f4767909ac79\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"18c5105a9651144ce965b4270398b982120b885850114571ef8e2cbc5d2f5e04\":\"00c5ea3d91248bfe30c5a6d26dbdf0609f977afcfa842b603c1061b2a473c9a79b421b2509550309e4be9c5015c51c6def9ee68c242f6e206b3027ce8e58b7ab96aaa50ced1d78c2dfcbc2589575bec2ce3b6a5066276fe7dca4f1118808d1e5cac062667053c15350289da03cd073377c2d66c01e3098ed01b75788c7e1f9e7\":\"a3a5f82748acc887e33328fd7f4ce1fd\":\"\":\"d91ed6886a269dc1eb0745dc4b97fc54cbea5e6857d10a303a3caf828b4e0e20bb742bca17021b7852d09a6d7d3a56ad82298c15a2082fed0e0e326bb16dd677ee262ead93a24147de3c07eb8a95b108abf17357155f1de79171689407b6545c9fdf8ab4486576490430c0e043e21e7c40ce88e752cb006cb3c59479a7e56cf7\":112:\"add4e086d612a119c6aae46ba9e5\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"4667cabeb3a644e371cbbe9195413daab025cc6efc12298bfaea0dd9bc028f9f\":\"9772ec47f3cd26f091bf117e085f2394db258c2c460dc3b1402edcb60a8f70517f82aa669607b78c2ad79c662c3b376cee1b9f34c4ec5d15319c33de78a440e7f2a4108c3c9da51604adde2025ff1dc336c49279c13a7153931df675df0e78f17a4d72973311af74fe755c85c7869baf3896bb738925942dc67f1b6e690c9d48\":\"7e8927c69951d901494539ab95ac5906\":\"\":\"5d62fa69cfbfdec30193408dad15cf983ad707ee921068b817676eca9f70f9ca4623a8c113df5fba86131415f4ec546c7f1a94ff9d02cb8ddcf421c7cc85ed87ce712fcd8d5f45460749ced0d900fe0368c59b1c082bd5811c1a648a51768d5e4bfbc23cada3791f289d8b61fd494398be1ad9ee9ff471abb547000ac2c1a5d1\":112:\"0ae6bd5e8c25d1585e4d4c266048\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"3d58cd514de36ca7848aad1bf4d314b3b3415cae1ce9a169021ae84a67d4ab69\":\"e1c2e79e3f64c5c64f853ac9ba1a853fbf1bfd3001d48f7e73e0e97aa1b8ed1f1a7066178e75df688c5edb1c42e270ea38ab0e246c6a47fde4c3141436fe4b34beb9033ba7eebfc53cf1f6c8ae1794e9bb536152d196e1b96803316a05f1dcb9016c8b35bf4da06cd18da6243acc3a3dc641d3a1332b1915932ca89937cb0327\":\"4a1c2e7a3f9788c3c2fdd0dcc0cfe84b\":\"\":\"50d63c660a2b4f8e87276c5f58556cdf15d0fbb2c8ea5e3266d28c515643109aa7fc950d6d48f504dad52457e16576b581d37574574cd8b7ac12b7d59b819992c941a27e23ef9f257ed0c4ea4eda6c1f3b28b44decb63a92fae84c3556dcb9d6458e729dad6a7db9f7411690fce971b3b240f8f9979ed992f87d76e227fd7384\":104:\"ac842579bdd1ac77c84dffac2d\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"b7e4cd80f03a7ed092c776b243dfad7776d9caf3e679939038e33ac94d8931de\":\"102e2d2c0d01dbc69733d2451d1ac1817d60418685d4ae8aa44e1ede1c1e08d2f71f0aef41a72bd9f052ea4a9a057330c95d964f8c3679b80fc9c0952b46f38e2ef055cb33703d686757400210fa5a39bc7e3bb9b8b9cc20c95d5607e2f10bb5501507680ef3aaad96553333b1d27bf2f7ac102c983eede2262a5c6237c1d754\":\"af160a983d674b7d19294f89c3c9307d\":\"\":\"6bdfae299d796ef36850327b091ba7bb02e29b643ca4c8bc199eb91ecbaf88426412cfd5570e0042cab735cc46ec648b0877955b3f9a5707d56c478aa77ae5510749beb1e44dbbb37791f18477123436a985e5e9f79fda0a057504847e4ecae841f24e1b53076d3efc6bdea2ebb336ee0e4b5e6ea973e3e50a27b5c2e6fee3e2\":104:\"fdf21e2ac356e507745a07fc96\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"3a0c46eacfe85cbc0c5f527b87cd075bdeb386d0ca6de816a87cfddcb8a87ae8\":\"6d1203dc8395e35a35e234203625ea9d37d1c009db2ac8b1d5b29021997b5421f1d172f4c9a7eb7dbb67f0002720fc412f5b1550c739a2d7ba4387a1f978bd548fe6169d9473893782b10fab99198cb8b4553dfe27583c017136fd8c95070d8d7f9a602d15248d38d728157a0b26404e662f9a5554d3e1582bc0e12f0054792f\":\"b1cde63ad2ad4b8a7bfb36ab78385c3d\":\"\":\"9de3a45c976d32ed2af5074ef13b1f86f35b1689b1c698b2e427d5dd62556eb14439f77cd8fcbe686a9a08a922e3f54a78e86fd284de493a740586360b63da09bc1d001777582969c679db54a0ddb8d7dfdb46750edc882804a1c00e417912b72b4cad54dffa1897eba6188b3e61ebf0c3dfab292c2686dcb9db3012e0788c7f\":104:\"641896daab917ea3c82524c194\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"4d540e0ba27103667eb4511ce9d243592bccb8515ab59896c9922cb5f1b47a02\":\"d79f9b1c74e3141f188704c8d5bdaaf6083642be50d00f20c97b56646863895250d131e00db0ecf4f035d42f08cfe20f401c2d3062a38daa0b9e7c19fa7c5d344680aff48d506daa181451f6b34ed9099b9a5b39c0166e93ac4463c9ad51f48e3063b1c16793615336f55d516d079f6c510c2891b97aaa95e5f621e3b5202620\":\"a2ed37daa797522a39b01dd206d06514\":\"\":\"6a891bd289ec05990424a2775287f4725aecefe1ab21fa0ca643f37829cae9fcbbf805b883f807102ff12f1a85964df818057daedd41c7349ef32b24642186c45d2858c3260d5b90594969e26b691963ac7fbd2eb4eef466ae690ca274d9194dfc4df1c3baec02abc38fbfc0e2c7c4fcafed227d4f6607329f57ee439435c714\":96:\"9074ecf66bbd582318495158\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"151d7e4db9e21c87bef65c2ac6aab5b6b045b7dadaf6424644a91e04ba810585\":\"0984c5d3f68beba1db4e6ade429cb8954cccaba9fcf4d852897ef69f8483428932c8f18a891f54b68f7d49a03c57f7144d802eb996d233cec930d5eb19f43d0faf9c94a2d7aaca40c8066a2882481f521bb5f6ba15b213810da373817eab3d52b5dd143a1521239482fbf4a07fe68c3d35c90c6ce27b55e40abcf432a261dc58\":\"49e0e0d089e3574fa5a33c963b403ccd\":\"\":\"6938d8a7625d1291f249ef1e086bb030ccdc844a9271fee16db60e7acfe4aedd720de76345109d5e6849fd1576c0fe0c34e73dca4011f8565cffccef427198c927f19f63b821f43844d008ceee0566f0d8062d7860e92ebdf21dcde80039a04504cd8ee94874b2eeb038962a74ac9902d9d7ce09afdac7aa706bf3892de19531\":96:\"48d3a8116213f92bfbe86bfe\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"3e9615515ca45109316cc02bbf3a23406eeeab2092dc6614db76e4e047a3b023\":\"46c4c6bad0f21172094ae07a47fd76477b69ca75cc08970e8dbf7b8644d4bcdce96f9d15dd3fba5fba3f851af145652ad004ee525d180d2f3e03bc0ec1c0e8ffebc1474c342732b7247f657ba87ffcef9333857123f29c4976b048c89c24107529dc5dd69004fd176eb0ca6ddae1df7be7d28b3b9da976413588f20c1fff488a\":\"c1facf73da64e16e4acee3fdc3cc6b10\":\"\":\"4415dc96d3daf703d392ba1318254143a58870e691570ca6b1be6074dd9c1feae12c72f9314fc3d19b6affb59b642ade6c4e64b7c99f850bff781de193cc0a321a29356addcb0918a282e53801541b5b01383fa7624c36d1f67423f02d2b54f58deca582b7031d192a4d32bc154ae1149cb3c5b48538c803a8d01fa7cfc1683f\":96:\"322d8d1b475a7fd3d0c45609\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"52c1a14b4ed57cbfa317fe0db87528f4c5551deb9ffc88932589e3255b1d3477\":\"eb9081e19b63c94b5f3a696c5fc2c0b7f434e1574394d0b41dd67dfac28a73d4ba26c86b3728b2802fb9d0930c89586b09602900d33eddc5a00a4e98881b5acd5597aae9b80b1569ede74042948f2cd66c3eeae227ae10241df001c85dfe8a5fda0aa21142ecade76290dfdd4a27b6ff3a932dacc0b5f461501239ae8d6d5f41\":\"36d02604b5b24f49b08bb01053a23425\":\"\":\"12fbea9e2830ba28551b681c3c0b04ac242dbbde318f79e1cb52dba6bdde58f28f75f2fb378b89f53cef2534a72870a1f526b41619c4b9f811333e8ee639be1250a5c7e47ecbee215b6927ecffaf7d714327b2c4e8b362b1a4f018ff96f67557ca25799adfac04dd980e8e33f993051f975f14e05be8b7342578d0c9d45b237a\":64:\"01e6af272386cf1a\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"4d08a07b3e94025523a4a6415029c8f9e11fbbfd72564964c53b8f56f865af0d\":\"4ac7c27b07a4aebe5caf1de0538d13a56e8c11bc73713bf78c7abbad3b9f6d690e00487267da108e2f2ae67c24b4657e77bb83e2d5e4b244cf34e924cf7bdb443f87ac8cdb374147449f8d06eb517a25dc86f03a389f34190aed5a7faace03ebf646fec2b173b2c15fd5cbe7c5affb6c3ee6d1cace8b00dd8f668a2336da5bfc\":\"98b745c7f231ba3515eddf68f7dc80f4\":\"\":\"337693c5c746d8fcdf7cd44d8f76a4db899402b891176e85b4c549c366ad709322874e986d6b939a350d2a0e3b77924d6d15454d882d1d3c94469d749a20d8f0116504cb31888a1e81d3abf25dbb7a7f9e7def26b9151ee649c059da1955f1716423c734dcd26a548844abb6b64c44383ec698e59361b6582c6883b77c338342\":64:\"7a9266c4e5ae48f1\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"b9d9fc42b58deafe9bc9734f4129dcad34a2e55ee5ad8abcc3f7bc42dd2c0e05\":\"11dbcd6cd53d2af766a1b6e4af2bc8bac2811ef818da2d1f81c140ab6e0298e958fef033736bc6e0dccd660b9a3e4222bdf3f89a95b206785d22852201e6dd00b44232ef3c03393893813dccf1960410b50cf50602ead8bd246fad88e66c88b50821578004779b6c45c13d8211df1cfc0fb2d7a342f58e4f2f3623fd31b12c30\":\"67931493096f4550633c322622bc1376\":\"\":\"66ab6e7a547705d8ae8ac3cb9bc5fbbc18cd220f89aec7dfbf4f72e7bc59b483c50c9471523c3772efc5deee3a9c34c96b098842cc42f9b7d7c0d2530f45900eeb9502e4dd15363b0543c91765121fd82fcc9db88fe6a531b718c1fe94b96a27856d07707fced3021cca9cf4740833d47091797cc87f57f5388b48e2296ff352\":64:\"0de60d4126733404\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"97e736a63870546ec9c2325a8e367c8ea17a7ffa71f6cadd6909a5bb9eb12814\":\"608280a9dcbd6dd66100a9fdd00e6dac2183e32c945b2b4d255c048243bfea15aad1a10ff3eec0ba79c531239b489a5dc155dc2775519f8d3d2ed82fa7ac653fb7c77e0dfad1c175b6c69963f5c12ff9840f18e0202502e9d1e3b170965cd86ae411af20e6d69a608c99ca8dae3cb3bcce666841132a99429bcde490d9f0b6b5\":\"d35192b4d233507b70c6d32f8e224577\":\"\":\"568a0d584fc66c876b7beb9ef8709954a2c426fb8c1936b9024181ca2cd3a7684c412715c11eab80a181be0238e32a2b689e9db36a2ac87db651058080531e7b1110938dcb09615e385d7b224b11222469145f6fb5f4c0e87b08bb3006bc5b6d2ce0a15be7fc29b27c10c645afd9d8253c094fc0f775086bdf2adac265b474d7\":32:\"af18c065\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"6d05193cc0885f7b74057ead3a0738b74eb3118b1a7e74c5c941ce0011197122\":\"c58f51bad815a43a5705c311de4a846ea2a70cbdd2c30d709a2ae0ddf82b7c889dc599fb6e0328fad21555a99530be6deeeb5b1beb333322c2b747288e52fad008513f8040a4735cab3c8cf32c4e18bd57339c85cf5dd71e382067bee7e9ccaf68e767d77fb005a3b73a51acf942fc3b2c5c9eec6189d01a26c6ffb070165874\":\"5160b65bf7a2ccf77fa2e3e0b3866f26\":\"\":\"64dc5834a63be414c3714f1b34feddbacd568c6466cbd06f665aa269187a160db79306a53b629fedc1247bd892998fe3208b3105f6273676bbdbff6e254de332d02bc8842ef98d6b79994792eeb5be3a807452b14ae5b5027db81421cc22936ccaa7ae1b77a145462634e424ccf2dfaf001ed4477b804e204120a1416b449b8c\":32:\"364ef0b5\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"6e8006983712ddfedfebf95e6cc3b0aadc23077055e500ae49fae7705787f2e3\":\"e3ba14c4e39ebad925997649872b8331f1700c8f98f80e58d92c85a84f2a427094d9d771b276a0d35b17c0c030734399070a57345d4dcf082b96c7eb580618f7af8bdf036296e20379e74e29f905b52a0c46fe7d46201a075e7de7e1a523a0492c1f228102fdb89f019bcd4571e041c5d37159dc487ec139fa37d33142fc8082\":\"e36e39d787394f1401fc4b173e247db0\":\"\":\"4d5db4b65a1ca31f3d980cc30037b5d79d28280a31cc5d0274be77dad70dcd37f652f2ca999c9aecf08fd2a02d382457a277002a1a286ab66f9e437adee00c3bab04f831dd52147005a989606171b6017d28970c8986899fb58900e23d1bc6a9ac0bd4d8b5d6e3fcaebc9903923e68adae7d61cf929388e0e357c7223523d1ff\":32:\"d21637c0\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"cd8ec237009eab590dbd9b31e76513dfa3501701b1a706982944441d996e1839\":\"9eef7c9a0fa3e9a7fcc4b2f9d210a97d6653ded7913f2fb2de825a0dfd78ae1cca68c040f2328009fffe62937d630ee9d6e0e67bc12c38c0b3d035697d4c2311371aacf41cce0d523016ee436a47d93af0df77011131856d072c718c310f0995b71530d70a3da881481f46f21dda62e3e4c898bb9f819b22f816b7c4e2fb6729\":\"a3cae7aa59edb5f91ee21231002db8e2\":\"45fa52a0e8321d82caea95bd9506f7331923e2aa95e9238908f3ff30e17a96389dfea75e225e34e1605354eaaf999a950f469c6e2e8722da5ad9daded6722baca00e5d1b8e63266ad1b42cae161b9c089f4ffdfbbaa2f1fb0245d1a4c306d46e215e8c6c6ae37652a8f6016f92adb7695d40bde8c202ab9c2d70a96220b4b01b\":\"833d58f0bbd735c6164ecaa295e95ad1143c564d24817d5f6dded5d2d9b2bed2dc05da4a8a16e20fdf90f839370832f9ddc94e4e564db3ae647068537669b168cc418ea7d0e55b2bb8fd861f9f893a3fdba6aace498bc6afe400fea6b2a8c58924c71ce5db98cfce835161a5cf6187870aa32f522d406c52f91c30543ea6aa16\":128:\"c1df4ee60b10f79173032e9baaf04d3f\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"5f0b24f054f7455f5821fdc6e9ca728d680e8004fe59b131bb9c7cddb0effa51\":\"d406138587fbcb498e8ec37f0f3d7f6b2faa02e6880424e74cdba67ae3468b6823d37fd917a7fede6b34a2f0fc47c520e4088766ba82a989f0d8051a3a80cc8b1e3e1e2b1c6620b90e99b27e65951aeb3936263fc2f76c1c8effa742f53987f8a38c731a411fa53b9f6c81340e0d7ce395c4190b364d9188dc5923f3126546c3\":\"f52f7a2051047f45ec6183b7c66e8b98\":\"756cf485b6a8e672d90d930a653c69fdbf260d3ea18cd3d0c02175d3966a88b70ab8235d998b745a0eb6a5c92899f41e8c0b7aa4ec132c8cbb1bac97a45766a03923c9b93c2a055abd0127a83f81e6df603a375ca8cc1a2ee0a8b7fd226226b0b19bd2e81f73c34dfafa4fcea08dd93dd4ab7e4b437408af91bff566068a5f34\":\"e58a03f664003d0ef5bdb28931afd16e7747cff62dcc85bf4eed6e573ea973cf615e4ebee40f35d44e18e391b391e98dca5669a5b0abbfa67834836b122d1909b53acd50e053d5ca836894414bb865b1fb811d8af68b88b4a302fdedf27fdd27456e9aaf34a8d53c9c8587e75843e09776392dbb0501ef41359c01e8980e5221\":128:\"258492b9f549d1b90555eafbe5292806\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"6f50efb3946f6a6dfe63f12780f764bb6ebcf2127d3804610e11f0bd9b68ce0f\":\"bfc89d5049a5b4015c9eb64fdaf9fe9f4be7229e67c713a7b368f0550b3a5e12ba3a4399c64f60b7157e1b289b154a494deadecff0d0686ab44fae2a34ae4cb120a7f00268ab551f41c16a05f8999157be1103464127a8a9bccf736c32db045124178c90472e664d8e67a2ade0efe9a3b048c453d2fb5292dd8d29e62d52c5b5\":\"63c1192ab7fc75c17e7812fd960f296e\":\"335cc5c8fb5920b09e0263133eb481fd97f8d9f29db8689fb63034bc40959a176ccdca6725e1f94f822e4d871138fc39776fbe062f07bf80e5c8891c2e1007efeb77c158ced8d6c002b04442ed35c40a2187a59c02339c05762942208e3be964736a431017f472dfd5fdaf8fb8c645cdb684f9632057b9eb755253b4b75e3688\":\"ca974942ae0f4955ca0736218e4e356145c1ef42135b1142b55ccb3fc5caeec630eb50e69b5a6f97c11d4b604189b27496623bb0365ae69f4150e201e72bad8e7b883185588d0a31c44273bae87194b1610114a83ec47ba68a02e29891de43204977fcd0d551778335fc77fcfdf3fd63e9e5e0c02930a0321ffb093c521cd0ed\":128:\"2f11a01cb0ef8dcefad9233bec44d6f0\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"ec566324ad9d4cd015821e2cd4ed4d3d507bdb3c65bd50acc85f690ef06740fa\":\"348d35768d7192415cbb92c5625f10edd79f24c56d4b821aaf80d7dc83e901ede6be94d1efe11a3acd16ac00aea8d0d4875c47522332fed11cdf0816b26978de431c89d2fe6d122b2d4980f1d53a97edc15e490a44e73cba9394ca4bbb871675c729c39de80d6678c71b1bd220e4647bfd20a7ddbefe2b7eec7276b87c92ba77\":\"95c8a544c4b94e9fbfd76e66f40bb975\":\"fa6f38f8e562a54bb2281dc9a7cbe0b981292fb00dc0053185550a300661852179d0f2beb4e7759b81316fbfead5c858e6fce73f3cd2c2462925dbb199a4e6c121d051b1b5ebf60e16d1e30f6973b19cf31830da30588fdfff6115a4a1f6d977a72583379a56055724581be5232b0d1b0ae88bab5d4a031b058bc8d03078dcd5\":\"8b4da79f3ae1ea35a80af2f52fc640055e6a3b92617ddfa79fe5d8a49f28ddf36a82a17ca0b3cdf1726700f7ffc09ae5b412d064fd52a90a76bacc74a0b89e38dc474e880a2b768ffa91fef34c47759a7b8fd7faa32a4fcb258349495e4438c7b2055a8f462729fa4e7223aa9b47087695e3aabf43afb32e272d536b257b748a\":120:\"b1faec277697add8f756391dd9c7f4\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"dd6aa4ff63efad53772e07e0fa7d6eda5e73be167620fd7c9f3997cf46cd25a9\":\"592b3a6f09841483770b767bed73498c286896d2ad3d8bd91f83f92f489b1e83b0456a54e067a79e1bf59eefc1d3bd35cecfba940811d06a06e9b8f774bfeff557bd7e3f0864cb6bd3f867efbe3f040d2384ae8e1a0e20ed38caa668159d3e33c4669478d00963a1152305aa2037a5e06cac52d84021234a7f5d46ab060bd03a\":\"6386e03bcb6ac98140ee0706b54c8492\":\"0ccdaa4f54cfea1026a4d26338b1e6d50a70b00c46147fe906c95f0a2fb5d92456ca3aa28a257c079eceb852b819e46646997df87b873bc567f69a2fae471df03b0e5b94511189eaeedd238a991b326963c46d53080f420ec9fd1a74145a0b155cbcc0b5e47fa69450c7eb447080e34868d640f923923b91a9e13a05c73550ca\":\"c1be540448f1e3f432a10b3cc1a913cc4046595f5a57bf57c9d856cdf381832e914088d3388199018ff26327e3001678ab363da9457ba2084f5aa81320f1a0343491e0b44424018765861c5db917ce14e91a77f7e805d7a97a17a288ee66567c5c01ee61dc46a9aa8b281438ed377b792e9539e311676f81c567339cf92b8e1e\":120:\"ce7e361713630ecaff81866c20fce6\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"ad3990cd57ce4e95342cdca4f07d7e35d575eb19f224a7c821b1f5a8c54d4bc3\":\"732809c29b5eeda974039b122b875aec2823e082ef637294658cc54f9bca88eb7eea87a366234f89919975d0e7dd2f8ea83198d5a6e349149a016a4b177ba43df2f3ca28e27b8566591d225ac25dfd9ea431cf1fb3ea530d65dac93aad47764a6aef8ec6903b6d145ea9a2663034d2a320690b92afd8032084b754be97604382\":\"fd4ed75d861da2cc14fd1054976c8566\":\"ab44689839fdf47e887b70fc1b0422dbbe5c1b50f4e704f9a435967ba8b70cf1e144a025d37292f628f9f7dd9d05557b65340090503201e8cf2cea2d6a73ea4850bd0931b90fd4a4306ba84b8aec99fed47ca1b16daee6c95c97e4ba0dd1fb130cd13f5ef77c5af96f61fa05305a3aca3775e927f72f08fc34bc994e69abaad8\":\"f48721b08101b35cde1c4ce08a8ba0049185b9dd48b66ab9971fd67dee24f89b456e9ca19ac8a9b5b3b088cbd53898a8c2ac1129752fb7fc55a0c3e2e7266ff40f7a9d63ebc4ab65f47422fc17cbe07fcfda582fd1b8f50e840ae89837e84add8be17d4cac3d2be26bef4aa8438daec9d2b139e442f99c32f2789378c8029ad9\":120:\"da6da2af0fc14b591a86359b552e20\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"30823396ac90db573b6587676564d09fa680906bd6eaa6b8597e2e7549c9d848\":\"c55be5a0b8559e02de4667ba5656f7e46f5627af13fd34d327f6fbfc4f3a9273036fce2fb21232f8e2ed115b39b0ecb9a119c8fc17070bbe4e34d3544d7117ffda5e1ef05e063b5a8fceb23158d7824d6a1eb4d90a1d0360c6bd78fb24fdd4cfa35924beb4e090891d06f53fc52cdcaa6b8bba6772d549eb95b64ebf3756ae45\":\"496ac734afadcd54f1a4372ceb5645fc\":\"2d582131f7071e80cde1b11106b7d79bb208743de759d40b897efdab018f4eff1f91d2fe67e27af25a13f201bbe4446f20ac6b942ff7b32cf10ad1cea36945b67ac08b114fc616175a87437ee05f3a8b6566e9edfbc1beec0ed8696b5d5c41a25ac43bf3ce2920dd262233ab3405d46f523894dcbfb6c90b6e911ceb93bb7fa6\":\"c9da3df66111dcbabf731c6891eb698ac3283780f526e81383e201244efe4eca7a1c84a3bfa9ba5616afb15c1f1af0f3af2e071df6c1d34a343c3e3440f1a3e1b6620243d9e7d9a4dbda5981c3e876fd07f392d44bf3e0a4edbd884462ec2f71d36bde4a1b5792629da09a1fb01bfdbd532fbac71887a05a7077fc119a4638d4\":112:\"cec973a27c42e31b779a6a91aa34\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"815f2b2f0b1621aa198eef2761380f10ac9872a5adbdf6286bdf3386e56aae4e\":\"d16930c570414bb620e0eaa2e9b5d96e4424127e16461aaa5885c616a02ae974fb2890e73bade9ffa5066eb88a46ac7fcf258d55733d315951b1b71c5e3c13d78d60344ce921966297a0f6361cfeab03b346a7fa4f83a7a0eaf37576fa33a496102446f9f31b06ed91b51672c879cb18d4e38fa86e156d5b1dbff27925922470\":\"0843984bbaa565ca24f148e57a7d9c57\":\"1514b99c0ad3493c36fe1216d1a887a69ea0340101aebb03f60d7ed26893119e81e8b8c3f0bb4af5e10a3bf4edcf257473be9dcebb44a9d912f04d97a556ecf020c0bed7ccef2bfd5580f1fc74b706fea45f8c63d8de6f8deccc47a02dc86d3f0624e52f6f1dcd09de8000f2d98a4cc0896da6a564b92263673adf390ed909fa\":\"7506175acd64224b39f890e498ee5013bb46fc571dc2b125ed5891b8ce8bcf42342f015fd2df5f4b9cc220aab52386bf2247d4163951e86467633f96c28bdda166d778855a7f60465dd2983232c9e53d5f89432407807b0402a10f155f80055c339451a106ac54438ae4a945e60d5320eab0adad9a1e66d59b9d3cc53887811d\":112:\"28d9d780052b36dbe80a25d41d5b\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"d1325ecedb8fc0fe449de558fbc11ddebef660e47aabb84edfe69837a6a9066c\":\"f9a4f7029feae5cf5bdb8385d6ad7d7da6a243c5026818e5a794c6cffb8dad3227964501c5a049b5a94a7ea2e24434e086800094118444c5a971bbe575324fb6b51c5939f81e78bb11d85d324742b462ce8d13584b3882617d0c94776f328a554f9d532b6515ade9fbbd2de1c12ab53671b7f7edaa7e20223f4c371c1f229568\":\"8aff702c40a8c974cf24bf3c645169a5\":\"9ec2e851dee3834d4843aafa740f3aac4cfb1e4d3a7e3e77349113f5200768c3e9dc37481d6292ebeebd2372db02ef8ac7180830c7187995c815d1d1520c3e2f8cf2a94993b18c828b53485073c8a845066772615b26d7a3d7d3e7d81ad1725797153f7ba5e313bdec582c5482adf76b31c871cd42a313018f40d7e23f1a7f33\":\"3a93663aab93c6cd236cba4db2c03942d9ebc669633936370c2834357e76f6555c34d40dfaab1e78a105da9092acdba8be89e2dbf72e89518d55e09eb2fa1ea7da505484ad4531dba3eb853d1ae1a477355ea9448067b0adbc782d64ec342c7cb781d9dd8dc2b14dc1c9ab5542b679782b8bb9b45ff6a4e36c513df169c8eddc\":112:\"7e682b0ddbe6c55091838616c352\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"4b92242268e598ddcf3a5a0de26d74356693c4dbca354e44be401f3d6804ea1e\":\"72dc75bc4c8f5bbbd9c639fbdb34afbb84706404c9e67eaee1959aa4b51eac0db4f975cb3ed8d8ca27f72f61c8562ec953a7b8745826121a7016e60e877dcdb046f236af3826c1ddf5b929c5bd9a92b0d5c23cf8983bf2459ced6595882b3dd0cd25da7eba981bba122623dae22dbdce05cf4e5d82d2cc54eb4f68e9e8eff02b\":\"3c292bbcc16c94b0a263f4d22f328915\":\"167dfab08aac8350574693b31210138f6b99cfb61ba7ade2e2abffe2255837a913c9afe332e8fc4b2463310df46492e7d982dcb70fdda2a8b03911e6be9a5c5621d0ae8ecd1cb390910b6702aad33394c25d1160b86687e25bb6cdc4811e3158bb85ba75548329dacc19287d9c004a0473029b77ca290fc47c1f96d9583bcd67\":\"c2dd42ab9bf3fda78032f73cbf7d28dd8e32c582a3b7ee79795551f133234d62ea6571a466b8e1af0b3d354b71a6582c9c8013d5f8a2c34eb3e848360adac1d5005cede58eae7784f32a31c40eec5a3f03cc1e7263d8515b36225b3515ebcf8dca2a77172c797d347ed3921ca0bc73e8ae56347134a6a2a06ae084f1ebb7b0fe\":104:\"02fb002d8e4a1d11bb0f0b64d7\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"c5c50059a61692a8f1ffae1c616158c67d276dcd4a029ce197ed48567e5ff889\":\"ab7e13923e66d0f600accd2462af74192c3de6c718a27052ef7c1302239c7fb2413df7c662657ca18228575ed138bc54f31663df548618e98d64402feab529d5bf6a678431c714df1fe24ea80017f455a8312bb5b710df8dd3571970404a806ec493dcb1f3f1ac980663f0b9c9823e0d0304ed90689f70d4a24da7d8504c5b0b\":\"920d82c6b97a7bea121f64f83b75dc65\":\"a9bd57db2bbe83177287e5f614dab977071abfe0b538067f7d0c5acd59bfba95dfb725b8e1af4573ff10ce135148a3bab044552348378d5ff0c4f8be1aef7ed60bb9a374a6c7b8097d7c1804fdf078f212e63e9f11d7404ad0d1a9cb28d5ba199aec3a6c41b9e523b541ad38cea763159836ede6371357ab1aeaedaaf4481c29\":\"8f7e87e3ff4f7ccd1cedc1df125199cfb588339119a5ea5f9bdb918f89ca35f9dc16c6465fb25ea250eaaa8e7f00aca2199f92a2c244642bd15cbc9b62caa58115ef01d0b4a9e02527e035744b20892f79b07aa47b6c6db1332f82434764c43124b27148f2f611766781df8e4cc0b5ba99b858c13c233646dcb2b8749a194f08\":104:\"65da88676d2ab3f9c6d590eb80\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"4c7cc3588436ad9e877de72578d30026d32746817ca7a8fb7df9870650aa48d8\":\"00c2845fc495b89f870bce714f8604a7e7a96ede92c4b9bdcf044c9a176f66a28761089c083d5e2d613c746711238477c0efdf475e18af99e88cf76d04d4e40495ea16c462801443cd7f69c5d36ac9f337e828c308f1d1938b1fac732274459827cf9806c1661a247167948a93eb6e998a4cea76bb825baa27e4180e52633bb3\":\"5e82285a3b332c693e427f9410564489\":\"9971b8e234fc3e1e9644545e383eb065e1866e2faa6513278d3972add5ec0e71b1558329fe1ee038a27919e43bfdac8cf08141ab540528f74f9d5bc8c400bb6ee7867e4dbc2aa081d9126ac374dc62b10004d0e233dc93376b93c0da415e7d3e09851f2084a99feeb25939e21893056870cefe7cdfaf49f728a91ea0eef605af\":\"ab7bac4ddede796576e1fc265c3c598055827be74dc7ed8ef172d00a648da56727767d68fcbe6c44e7272dc8cb15f03a26dc439178849b0e9ad6c7410dd4cca3f9ef40ec7c280042bbc199155c7341e88d35e5e8d0b42856e618c6c30e43d49506ccc3518585c951a3898409315e8b3b4d0adccdb561ddcf1b9d3b2cf3de9750\":104:\"2474c830c6ebe9c6dcb393a32d\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"9d73aec506e022c0692892f6dbc3b4d41e86b97fb377c1956ee27b9c9ab3b32a\":\"f02bf60f10ed876a803a96e75f3fe17b4e355246135a0cd5497baad2a40a523c27e27bf848f0cb5d0c6428d08bec9590b17fca5e697990d2a6f7d21080ab614f378a07461e7a6207229e0a087e285841ef2f119cac7d8a2d3abbb1e7272a0d7dd493c8c4f797e160c36e086227ceae4923658365b2d3a3fbea11aa2fab3499cb\":\"bbacc081a6107364dcdac83abceddbfb\":\"77e1da090e4d3a892baf1afbc12a56201a4362d8f09cda5e9bdb23411e6908915301d66403acb3524898c1c51d6970a71878accd0048cb6cfbd4bf941c174ee05eca2c4a29f1c24e936d3a63cb6cfa710617af1bbb41d755b2f79e135db914a7dd00c590cf741078eb72c3ab559787213202dcc0a4734bdd612b917e372f0e61\":\"d78fa4024b8d073899ac09b8151c29b10a37793b76f04921bdc7dd3d2ef530a831e53cf6a7ddeec0e033ceeabb525bf5ef57bf9b3661ffb57d3bd4024252fa11dd569102c787c2d8489a1ad1290dca2e8edf82fbe6b5f83bcc0e888045b895e20c8556ee80430cc8640fc070491d2bb81a1209428938cd8e7a27e0e858029421\":96:\"2235d00a47d57cfbd383b69d\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"73198dfd92d26283637e451af6e26ff56e3b7d355ed7ab8b2059c1022e0ea904\":\"2471b3c4cc1d6884d333d1c998c7c441808ca884cb88173a225569e1689ef39e266e9ad381926adeafc2daccbdd3c9457ea1bdc3bb05168ef1eead1504d1d44dde34f96e1a7f2a5d3fb33cf5292d52fa9412800419570db0eb24fb74d55de202f5df74073c5a2eb9eb726393996eaeb32072bebb00593de41b97ecbab2554186\":\"e36403ce1acc63bf50b47387250ef533\":\"cad023cfb73d08e5b082c3061f3a6502a1c1d53038cfb19074d0ec26c9b272db93094147ef0ab2bdce440a2b3233bb0429add47601f011df679698264c0f81444aba14576a1a565e5c169f967c7571bfb32a2a4d7fcae897863d78964c5b1a040cc845494c0ad8ff4353317b28ca3798e6252d5015b58e99354ce6dfbe8b7a95\":\"32afd6d6fdab2019ce40771b5298aaadf753d1c4cb221f01e4dfc8b1968f898188fa4d448d8364510a7e68c7393168efb4b4ead1db1c254c5cea568a84a997a76dbc925a6c19a9092002629f1d9c52737005232e5c7620b95ed64741598a65a9ec95f2c97b6b78bd85380811c11386074b1e1e63b9a7e99d1cb2807bfaa17f0e\":96:\"e22deb1276a73e05feb1c6a0\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"1dcbd278480434135fb838ffcdc8e7716e95ea99a1cc36d544096dff9e9aeba0\":\"da3b8c9e4aa8443535b321c3e9bde3c6742cd9f228c971257430b27293ebeb635917d6cba976c81934c3077902911169e8c6197b2d56a046b7ff03b482c38172accac98aacc90076370df28bc8a2044c393c7541b7b69b0fb852746dcf3140ace4e76861975814d2b5966f7714fb6cfe3e4299d79182fc63a345067a0aa54d8b\":\"b737bcdee4ef83aa83f124cf7208a671\":\"49a544aae76b04e62211428a2cc3719e4451f3dbf9a23b6ac824fc472e95e38386d267415c1472a8b0707b0573b9eb2a39a5d5a13464947cc3a7a7dd3b7196f11e87ab5233944f7cea3f4d62b088febf8b82a44d4ca6148be1ba24905432b7ac2bb4ebaf22d3bce97ac2bd34158b6011fbac77ee1fa96ca0c9c9e0207044fbbd\":\"061b491b73f9250798a0fb1fdcd72a70eddc9cb48c1f10119387d45c50d5fbb8b85592a7977487e45342fddeb8d481eef3b99463972f66acb38fe04953c223c5f3e02611c8f33cb9ad7466860895fae585d40bc78ec14d1cf17b4c5b75e4d8c6341f1eaf80da4a78aaaa30d3bc8bff15f234aacbee4067a947e42275b12e0bdb\":96:\"b897da3061c77aab5eb54622\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"2e00467f18536ea6b4d582b2480ebee883e4f56bd91af3ad7a47ceea3ece9acc\":\"d5334398318ade59e6bda5cfce8e11b25c9ccefa2f651eb16f66c03d84dcc900dc7c85e6d2b778b155ae4591af0698df7f3b8b9f64d4442ecc82035f7d8e71a5f61c515a963f2fba077f3cb8276e91b31b3f8aa193988a16a86ccaec4a688ad68b5146925ec21d55ded407709d34d140f37e1f87d955619453c3704e83918088\":\"aa6716e6b7107876a3321d807a810e11\":\"5606a0b77cc9020955c7efda33b7080e9c0e9fd374c4201b4324b3e6523b0407171141e8246d01292a34dc69331f7177d6b7238e16e0303e85741f9cea5698e42fc79217d9e141474068d6c192713c04b1ba3573e93480f69e4cbf72090d46d62d5b52e4a7613af8fcf0010d0024ea11c19cb04571c6d7045a1157cf81df18d1\":\"249119ace4e292ffdfebb433d5b57fa1518af3389eb832146c3adc2dc62fcc9121d7f6461a53ee107ce7edf362b365d8bc18e50cf9c328cb7c7aa7b4e8bfa07c34dc81c38fe0982bbc3b543485ea4b0ce5a76c988cdfcd241911cd66f5a5f9e0c97332bb0f3926117c0437470717c63957aeba1c55d96b1ff0f4d6045f908cd4\":64:\"70e986fced03ae67\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"a18240f6135e7b6eac071546ee58bb52394bc34ad4e91ee678b72e4514fddcf7\":\"02f288eea5588e7a011f4d91eca232af70f60ae3d9302cae5a8a58798c1b4e973e3b1d07695934ae871201682554ef6a5b94976c6a1aa73d354f1d65e3f025bb2a3f1e93009e822a87590dbfd1965904223049c5ac0da8596955199ff767b92df10d1f9c05c40bd8204846c719c5594000cabd87342f0447e4e466c3788723f8\":\"149da8186ca73941582532ede16edf3d\":\"4d46e1e87322ca84d5bb92d58670f644083db06bdffd99fab0055a62b64a30b5a5673a108f0b9f114d379d3fe63a1f63407881c5b5cb03142109c158af42a00eb24d3b1873edd2284a94a06b79d672bc8f13358f324af2622e9aa0da2b11e33567927e81aea24f3605168e602b532fa2cf9bde5f8cc0b51329e0930cf22e3752\":\"36cddac99e2673588ba783d3c085b9935626687a2dbac9ad10deb4867c577d6f80453266b2400afd773e4edeb743c32562e85f7f8f43dfd87b10a2dd79eddf6e580aeb4cea92ac21cf49ca97398cc23c02b0ca59257643fb2bc6462b9cf04658352d53c2ee50d87cc5ca2ecb722d950f0daecfa0b7c33aaa2c91dd8b093916cb\":64:\"73cbe40df3927e80\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"4b64bded6c658090a85b5d889679c6a00579498aa82be1e3a628a1cd001e52a6\":\"182cd59dc1934199d2d2a2712157438c347e286f66b5a2b8b5149aa41ff7ba82adc3751be379741124dfcf05c531416a64f25f0d28abb6f7bf98c80762f0fa363da679437621dcf61bce43ef4d63178779d1a3ebffb82044d427ef522cbd2643cf1f5617a0f23103cd2a164a59f182b151f47b303c4eb7387ee5cb97cabdf985\":\"99aa6f359534da409a18540d82fb3026\":\"f55fd6255d8a188ce9a4a2727699ce16c8bc5c6adba88d94106038b74deb79c9d43bfaa47375148d843a5ce248d70193c8017196941b2d9e2dfd4375a3390c19d2f833b0b265dab30f26adee07ab0aeeb930dc3a9fbcf719a707fac724deb28dee2a6788b17fa3505290c2797c6dbf930b41eca1f6d54d75b820e62ec7023e93\":\"5a1211218174e60690334856483a3066e2e8d996fe8ab86d0f8fef09aba9ef0acff9d3e1e5cc27efb5464bc23bea9c778fc74206ae3a16e5fdbf99694ab7096f23c4b395d7a7b8d6675e56b5505ff62f52bf183bcc4433298296e41662d6519d9c1f0a5fb3140376c8890547eae72afe75c338ba97fad9f0184dd311bbdaf3cc\":64:\"8dbdc0746074b486\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"cadef353122cec1fdbc236c0ab195fc4d732655cef444c00b6cba5c61e01c614\":\"a3d5e55fa3110a268cf1414a483adab6d58ec8762a6e6be81269c0369e8840333503bc3688c7be001cdb84d163fa1dfb05f3b01ffff31151f1af780c796822e3d564f785964a546bcc2a320d81a2bc61058652a8594ae9b9b0917400e08d4a99fa161376ac53cba54c92889fd3497e233aff4e12cd85d57375c7c89e92cdf5f5\":\"d765b5954e5b486885dc78ce6801516e\":\"ba0405745971eaec5d337fd22e0ad287551e7084f1c9c38231d675719e3980356e183a99a3c760ecf7a8ede5e0dac8d2bc13e135570ff6e91a854ea3b457263b0e77896fdf7bdf0b53c8276cfd1ea3e8e22450ff2665eacd24e5fb2be89373349fc9e2967763d43cbd7adc9a376b1b4ab956ddf8b1a56d9385fb7e861bc34df7\":\"9b99f984ae26f9cad5b3c8058757a0a5caef0fb86b8ecef0c1bca6b99bc72b0d5345a00ae75e37d4e651008bb733105d2172edaaf5bda4ad950a49de55a514e882a470dca7c7bbfddde40d38fef4e1f3864fd7e212bbc0383d0bc29ab2303c8935d49c35d7d73df2fba0daeb5f37f9ab0d541766da71b33da1018a3f287ba312\":32:\"c374cd77\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"0cfc42773fe2d16a59da52234af5015271332344448c214a2b4a0bb53b07a0a0\":\"dfbf9eaa46c368b28ef50227db97f29b5d9ed599760bb83f5d52f92ef5522815d6952ebb0d9b4efe8844216d37510746caf8c775d2c862bad8d67effe109a0cbcdd14ba8e31fa420a475e55ac6b02908346ad1b064d5b6b869503e08d057ae65e9dc2a2a26345917b18d1b715a2372e8e114a071eced0c29cc9966d7205ae010\":\"45afb3ba2db9287f06cf48405764a955\":\"16d3ad553cc0fde3f32112bdb478450c65c854927b198914649a2820a9e3d01131b693765d40bd2bb74a50eb4cd7bc8dd8dbac9c6a61acaf5e4cf81570814b30a6a11877a8f9c5df342f70008cbf0576bd27a50bfaf6e22a40bd77435da16b666a06d172aa981bdcae0d25b8ab002c6c1994a356d3c3b7e4dd7b99892b0784f6\":\"e29db2c4bccef2dda828ce652791d424a86cd5790e6ece67bc029ba9520bd8f35a214a73d8b86564df0eccdb60eafee4170da2694eb563e5a854b25d7ba0a4c53465fdc15c6e267be2e54263f97aa3edbe2358f3d9b8d28997388a57aa427a239a74534393593196253de1c2946b7a437a00480ecb2eb08dbe55ca2b3641c36f\":32:\"39e01fa0\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"2a840df4be22c70786c873058d2a6e16dd9895cbfb55b9c9e98f958cfe62e65d\":\"313eddc53f3986927a261f498283b6dc4a39d26f98c7428127237d79a11c5e626e2e9cdb68f72aa3168ab23dfa2f5e03bc65a68d781f23fb9e295909cd9f0f3e5648cf82f3f6b3b509b0a333cb7d9f2b6e444c351a318f8f200a921ccb409def21b87bc55ec211a76a518350e6ee21d7379edd004b3bfd1ce9086b9c66d80ec1\":\"ebf155f7cf55e6aabdc1171c95c45293\":\"8abb8843de1766cfb8d6474496acda2f7a14e78a5e4c787ac89e6bc06cfd42173c35b3a75ddff644f4a58aa7502fedada38a7156457365b4c3c07bc12a8f9061331139b9a2b8d840829b876beb84f27d5a64093c270fe6c310ca3afe987bbc5ec4dc06358d5bf77c7b4e4fe4078c6d3ec28e9a281318da88949c478094c0065b\":\"769869a55754eb5d6d42e22a2b5271b38533fc0c79642e250347d34566eeca732e0565f80672054bd10cbd3067730dbc567039c730d8bc32a2bdaad09885651533a4f03174d4e6510547c1e1dd51be6070ab0ca0cceeaccf64a46d0ef87c0311bd09973f3b588a4dfb39c85086ea5d67dc531c287b83c161dcb25e07b671343f\":32:\"c364c089\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"461566cac74f9220df97c1ab2f8bb74189a634bc752f7f04526923d30506949c\":\"\":\"546d821e437371061cf3207f3d866c15\":\"\":\"\":128:\"44193072791c435d6e8ea7756a0bd7bf\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"7736dbb38f1fe351a7fa101d91da62124c22ac02ee06b9413f56691067572f73\":\"\":\"5f01779e5e4471cd95a591f08445eb5b\":\"\":\"\":128:\"1a1f08c8f40b93e7b5a63008dff54777\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"eedcae924105c86190032650e2d66cf6927dd314de96a339db48e2081d19ad4a\":\"\":\"a39d400ee763a22d2a97c1983a8a06a6\":\"\":\"\":128:\"3b4294d34352743c4b48c40794047bea\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"714df4b69dc00067c4ab550f37ff72358b0a905dea2c01f00be28cec130313c2\":\"\":\"c46d63d6fead2cee03bd033fbc2e6478\":\"\":\"\":120:\"2a0271b0666889d2d0b34e82bf17d8\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"454021ece9a87a9543a1626820d39edd1eff3dca38a287d8fb68bd315a7a2677\":\"\":\"51de54b633a7c9f3b7b2c1e4b47d26a4\":\"\":\"\":120:\"114708102a434e3a30088b5944c272\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"d7e90b539c99e8c2187ed72823258c1149890a69a9c0081ff8c66e1cdea9f2f6\":\"\":\"6dba3273560f30f118a2e0251f7b7d76\":\"\":\"\":120:\"5f45e00181cd2d7feb4723e0cdca24\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"2948233eec9bf8adf7250b20d62df9219d30e314c5932383203805ff9f3dc5cf\":\"\":\"d6b8e723272e26922b78756d66e03432\":\"\":\"\":112:\"14c9a9a217a33d4c0b8e627641fe\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"c73fb5e732ebc1dc7c91ac25de0d01d427de12baf05ff251c04d3290d77c34d1\":\"\":\"c31220835b11d61920ae2c91e335907e\":\"\":\"\":112:\"9eb18097d3e6b6b7d5e161ae4e96\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"a46aff2121825814c603b258f71d47bd9c9d3db4c6fe0f900e0e99d36c8f8d66\":\"\":\"7cb5550a20d958490739be8a5c72440f\":\"\":\"\":112:\"8c76eebda0f1fd57f05a62c5f93d\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"61a612c76de551f794a146962d913f60fbd4431365b711217aaa4beaa115f726\":\"\":\"2d25462c90ad9a21073729e5efc99957\":\"\":\"\":104:\"e4d3b277dc9a107c0392ca1e5b\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"4b233480239fabd2035a7c9207a8e1ab2da45a90a472b30848fe4b4757c628db\":\"\":\"50d45096afd0571e171e1ab1ffb3720f\":\"\":\"\":104:\"5393bc06b8c5ecef1264fd6084\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"dc051ac63e6b051594158399291ed101a3efbb1701b98819c4835a4863734371\":\"\":\"1f304d4d7f84ab560366215649b0a064\":\"\":\"\":104:\"1081dda9e0a793916dc82f7848\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"75f76df772af8e3019a4c1588a7d59925f80ce0d5647030f29548374e7bcc9e8\":\"\":\"d407264e09fbc853b131c8a9f808f1de\":\"\":\"\":96:\"d515522db52bb872a4d3f9d1\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"608d7592c094322b31d4583a430986bdf6aa639cc4b4a0b3903e588b45c38d38\":\"\":\"6a631952e4990ae6bdd51052eb407168\":\"\":\"\":96:\"eb8851cfdd4fc841173c4985\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"86a90631e5341e67dfa55e68b07522507b437fbab7f3e2e26cfc6e89ef9d2410\":\"\":\"67763ee1890e4bb430ac3c0dbc2af997\":\"\":\"\":96:\"c6d11901b53cf6b13ac03cc5\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"b8d12783ba2548b499ea56e77491d2794057e05fd7af7da597241d91d832b33a\":\"\":\"0365436099fe57b4c027c7e58182e0b9\":\"\":\"\":64:\"41fc42d8c9999d8c\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"eb17c1bbcd356070ca58fc3899bb3751eea5b9f3663c8e51d32c1fc3060b7ac2\":\"\":\"aca76b23575d4ec1a52a3d7214a4da2f\":\"\":\"\":64:\"fbcfd13a2126b2af\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"916aea7c3283aadb60908ec747bcf82364c1827ec29bedcbadacbb9b935221c1\":\"\":\"e4aefe6f81872729ff5a3acf164922aa\":\"\":\"\":64:\"2035a7ce818b1eb4\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"47b4b7feb91582a2f6121d12fd465967352e58d9f3d1bf27478da39514510055\":\"\":\"137bc31639a8a5d6b3c410151078c662\":\"\":\"\":32:\"822955ba\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"8955cddce65978bd64ef5228308317a1ba6a9fbb5a80cf5905f3aed03058b797\":\"\":\"1370e72b56d97b9b9531ec02e2a5a937\":\"\":\"\":32:\"b2f779e8\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"7795d631f7e988bf53020d2b4607c04d1fab338a58b09484fe6659c500fd846b\":\"\":\"f3f5cc7c1ec0b7b113442269e478ed81\":\"\":\"\":32:\"e4e6dfcc\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"f9aab5d2ea01b9dc35c728ae24e07c54e6d1452e49d9644776f65878199bc5e4\":\"\":\"96ec2252e51ebfb731b680729be73297\":\"983a102a67359f4eecac465b0d65908a487c98c593be89494a39b721728edc991726e1fba49607eed1f8ba75ae9ab82a1a95b65ebdf48d7ee3c4a2b56832f21a483d48c8400dea71537f4c459d1cfcf9d2cc97b32eb7c5146cbf44d7e5ac779e9be0ae758eafff2138d4c5370b8cb62d70ebb713dfd2fd7772fa250590609844\":\"\":128:\"766b6dcf491a5836ef90f47ac6ab91ec\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"d713b33af57762f933d6abfecbac7fb0dc1e545dd7c01638b0e1510af719769a\":\"\":\"5da52833b6fc73c0e4b1403e1c3c10a2\":\"374dd4ebdfe74450abe26d9e53556092abe36f47bbb574e8184b4e0f64d16d99eaf0666fa3d9b0723c868cf6f77e641c47ac60f0ee13dd0c1046ef202e652b652f4b5de611989223b0acf1ead9b3537bba17ccf865a4a0fda1a20b00e3c828b9726bbd0b0e92fa8ed970eed50c885e6d69604278375af7b9ae47fbce4fed7d03\":\"\":128:\"6151956162348eb397e2b1077b61ee25\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"77a1e4ddfbe77a0ca3513fc654e7c41609cb974a306234add2fc77770a4a9e16\":\"\":\"30d6ec88433a6bdd7786dc4d3693bde8\":\"69beef4dbdcdf4e8eeb9bf8ae6caff8433949afc2ffef777e2b71a99fde974797dfed2254b959430ecc48db72cee16c7ef41fa4165ce4a0636ad4e40875d193a3c6c56a6bca5a55bce3a057a2d3ac223eba76e30e7415f00e6a7643fda9a1bf4d4b96ce597ffe30c3f780dd767cb5681bb7a3fd11668380e272bdd70e66f18b6\":\"\":128:\"d4a3c91e02a94fd183cb0c9de241c7d1\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"303930b8ba50f65a50c33eccd879990d5d87b569e46f1a59db54371fcbda7fd6\":\"\":\"2b2b28d8a5c94b6f7ee50e130268a078\":\"c2ff20441d96bae4d2d760dcbae636ca7e01d263c28db5faed201bdb39bcacc82ebdc943968aa0accd920d258709c270df65d46d3f09910d2ea701c018ec9a68af7fb3d76a9b360de266b2ac05e95c538417fec59cec1f07d47c03511751978baebd2e0e4f7483f7351b5e61c2a60138c97b751f6a8c8323970f6be05357aeb2\":\"\":120:\"b597491dfe599eaa414b71c54063ed\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"1e3b94f5883239c45ed4df6930c453c9ffd70b1c6cee845bbcfe6f29a762713b\":\"\":\"61155f27c629dcb6cf49b192b0b505d6\":\"5b7482e9b638cb23dba327cc08309bdb40d38100a407c36091457971bad3ab263efa8f36d8d04fdc4dea38369efe7ae5e8b9c190dad2688bda857e48dfd400748a359cfe1b2a3f3d5be7ae0f64a3f44738a7c7cf840a2e6b90ec43f8c9322c60dd91e4f27fa12197fab7ed092990879e964ce014f6be2a1ef70bfefe880a75d5\":\"\":120:\"7003f04d6b6d9dc794be27b9c5d5e5\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"9080effb27994ef831689da10600e7a219db93d690647457702c217b08057eb3\":\"\":\"f45514696ff5ee1e6e5797f7bcff05c0\":\"5251f800f7c7106c008c0122971f0070d6325b7343a82fc35f3853d25c878215e7a929bf63cc8996f0ffb817174a351b71d691f23021f58777f962fd1d45ff849e4612e3304ae3303ace7b8ca1a43f54e662071c183a1695873f5567397587283433d1e76cec1103ee76f8e0472814424b8981caea1f624131fb7353afcd2cd2\":\"\":120:\"cfb6d9bccf0378fabae08fd230edc1\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"8c291f0ad78908377039f59591d0e305bdc915a3e5bfb0b4364e1af9946339c0\":\"\":\"a9830d5663418add5f3c0b1140967b06\":\"e43c04e1f7304c1d83235120e24429af8dc29dc94399474d06047fd09d61ddc682684776c81ef08d97f06db6e4cfb02daea728ec6ac637e1ecfdb5d48f0440d8d8ffee43146f58a396e5151701b0d61d5f713b2816d3f56d6ee19f038ccc36493d9ad1809a49aa5798e181679d82cba22b0b4e064f56af5ec05c012b132bda87\":\"\":112:\"275480889efe55c4b9a08cef720b\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"96c77c11a3336a41b61ffdc1724a80735bbe91dd4c741fdbcc36e21c53335852\":\"\":\"655502d70119326405d8cc0a2c7a572c\":\"c01034fc6b7708128fbf4d6ffa4b4b280a1493b9e1dd07079f509479b365f55ae9290689f1c4bdfa439344e3abb17f3fd3d5e2f8b317517747714a82f0a9ace04938591d3ade6d6095491a440322d347e8634008cc4fd8add7c1c4764afdb2b098b3f5604e449e8049a46b6192647d19cf88fa5ed1abab7f313b4285560cba44\":\"\":112:\"b4d581464c4bb23433699c418ddc\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"e2a3957393669278f052ff2df4e658e17f2fe32811e32b3f62a31a3938930764\":\"\":\"a6f5a1f1f1ac77a1cb010d2dd4325cbe\":\"ce9c268429ca9c35c958ca3e81935ec60166aea0be15975baf69103251efafd54cbcc0bed76a8b44a5b947199cd3c2dee6878dd14a5a491a4a3d45788405d0129354e59c047b5367f1158bcf4e066a276951d2586bafc3c11f8a982ca7c3ba4677a938498bd51171552ea032fe1bd85cfeaeb87e87168f7a28e979b08358f841\":\"\":112:\"cd5986df8e9761d52cb578e96b1b\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"2b17652f7f04073afe9d9eb8b2615c7550968b9776b139fcc4f9b0300912cbdb\":\"\":\"9a8ac23ea74b292b7386138666a0fb60\":\"2732107241e6136f1dd28d233373079d75d6ac13828ae7afc751b6f9c57e77268c52ae91f4ab3016af2764597994573cd6b41f72e21b60ffbb3aafc9487ac19d0ffe8db2ae2c7505ae5963b032d1ee1bffb4c5bd88bb0c9a350ba26ee3eb8dc0a157955333e4f28c5ec7349c39229dff9f440da72909f2870aea873a76545ee8\":\"\":104:\"f7b94229439088142619a1a6bc\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"16fe502e20d6473ed9a27569b63a768ecd428738904cf0b337df510775804619\":\"\":\"431a8d78b91414737e7c6188328a6d37\":\"934bcacbac10ea4ff6ee94b17bd7379b88489fbf123bf496c78c9b6b02ee97dd62eedd05b8f44f4912764920129e711701628991a0009ebc7017a1a19b177ec9bc3b0f280eeefadfa310708dfe214428a184147b4523e66f2d62630d4a12fd3e366d27c3b7d1566553c9b434ed193db083160da1f241de190bcbd36f435e30f4\":\"\":104:\"1dd3e6d610f359cc4e98d36244\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"ccc545fd330cf17e27d75582db28807ec972b897f812d6ed4726d2a18daac76a\":\"\":\"caf2f56584a59c42a51fdbfe4ad78f3c\":\"e85ae6b27778893f36f130694af0b40f62a05aa386b30fc415e292761cab36fdc39bf5687a513e25ed149414f059e706d8a719b7165044fcbd48c773eae546380b8e667b56824e23685173ad9015a9449bc1cd0b767981efe09da43a07bf1aeee08ba05d387b8a00199e18c874fb3a91f77ba448c3bff971593f94747fce9cbd\":\"\":104:\"5cf5c7ca6fbfee63854f3bcd15\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"8340d604770c778ee83d0fdd5703b1fb304c3bffeb6f4c65e2dd0e12c19bddcc\":\"\":\"c0a580465b1b2e8344f795a6578a5151\":\"799f228962ef87865dfcfa0addde7366de2e4aa78029dbc8d57d7e50fa7c74343458df3465103556a3bfc5ce217fbbb5b2835c9f76b70240b40fd605bcfa6b790d5985a8ba54354e0625263c628e8746c451504fc58a179f90f77f2b293d8dbf5582b031082025c806e60143da9ebb6133ac8367376d0572b32569ee799540ae\":\"\":96:\"318f56bd0f3832d043ef700a\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"74de45262fe09e12c9ee7100030352112a6532d1874cc6792b4da6950677eb2a\":\"\":\"9f7fc7367f9afdb67fd1afffac058e2a\":\"289ac6f5beecbbcbde5cb3b0fdf4a27ba237fca33719f774ed33a5fd35d7e49f76d3e88c53fd35561655c35469f3eefb5b2f776ff2799aab346522d3f003154e53f4ef075f016aaa500c76870e6659a5f9af197c9a8f5b9e0416ed894e868463cc4386a7442bb0c089a9ab84981313c01fec4fc0ba35829b3cf49c6447f56a4b\":\"\":96:\"bc1b8b94ff478d9e197551cd\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"441ec8afce630805d0ce98b200e59f5656a5ce19e5ef58241e6ef16cac7646b9\":\"\":\"a1cbeffaf55708c375dcfeb496b21f4e\":\"5a6ba5d3f5a7a4b317c6c716564c648f0e6bc6b0f9a4c27affca6d5af04b7b13d989b7a2cb42ce8eedd710be70c04c0e40977ca1c2f536aa70677038e737064fb0e23d3dd48bc00ebdd7f988f57141e164e3c18db81e9565a62e28c73770666ff3bfd725eebd98946fed02f31d500b0b7ab4dafeb14e8cc85731a87f50d95fae\":\"\":96:\"aa4bb3d555dabaaeb4d81fcd\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"d643111c973ffb7f56bfbf394eedac54be2c556963b181cf661ba144f7893a62\":\"\":\"4575b00b9af2195a0cc75855d396e4e8\":\"b2c53efe59c84c651979bcc1bc76b0bbf5e52b5c3115849abdbc469a063e2b1699bd292e5fcb3476e849c9edbe6ea14c2ab948ed7d21a21f69406621d3d412b043eaf813be722d92739a33a361ed8081c0eb00400c3c7d4e329f5ba4f7b75d534500f42f178048cf2e95b768ffed79c350f2ff72cb355abdb30af0a1363c0b4a\":\"\":64:\"9d1d182630d7aeee\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"91301ee0ca694ae6971ee705f53c7ec467f4c88257d6466f6f8159a8970384b9\":\"\":\"345fb57e88124a414828730a85f57871\":\"c13623824a204385f352388098f5e2db23426f00a73c60c1bf1047ce2c7cdf7f7cc8475781fe7075d1226ad18871e12f0156f35e6ce7032efe3bade1c807f9eedc720fff7a27a2f4690f904be9c99b54a65509eab60e97c4283596eeefa2b2517e95de7620382e3f780efa1dbf5d3908373adfe784a4faf298681e171bade4b3\":\"\":64:\"325d08c5b96068c1\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"b6ba5c11daed7f868da9bfd7754d555a147a1ffd98c940c1cd5d136680e05c10\":\"\":\"b0c92b79d78547496d770678e1ce1552\":\"5b1ac8ff687f6fd2429dc90a8913f5826d143a16a372cca787845cea86d9b4778708bc0aa538f98e1031850f7c1d97fb64fe29adce6e1d51ca7f5203fc0358fe0bc54347e777dddfe04e3d7a66a1d1e2bdb8b8929e2100daf073845db5dc0b243819754c4c08f4fc3631d1cbd79ac7604746d677ff035930fcd6bd652e7864db\":\"\":64:\"b1819b6f2d788616\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"5fcae1759209e784dae5a8278b267c414a03ce7c803df1db7815b2910d10ce19\":\"\":\"24c5c349b3effebfd076c88a591b8301\":\"ca2778e39fffce7fbe8f912e69d55931848dd5ab0d1bd32e7b94af453251a47f5408ebacd7b50ddd1103fab1c72acc0a02f404c5661d8450746d781e2c0861b6974ade9ee2515da88b470f16d5f06007f35ce97cfc17fd015e438af39ca6127db240babe9c42ed5717715f14e72f0ef6ff4ce512de95a179e60d6393e73f216a\":\"\":32:\"8e59f30b\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"8d71a70fd58125b0da8dddf8d23ddbe0bc44743753bdf259448d58aae54775a6\":\"\":\"d15b02572dec98398ba9e68e1a463738\":\"81313be1eda9f27e01b30877ca90e825f55ef60b15548c45c786c44b024e7198f333be7ddd2c3f593a9b77b68e6a7ac4cfc015aeec66f4823d9be7152f02a533f375554309a4db0fea8e76255144458e488fd19106d9a9614e828ae306fe82af89e7981369b2259c49bae77f8ec2b1f169ef0449ad083d11907234b72ed2e464\":\"\":32:\"99df1b8d\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"b52398c7c75e1b146cc9998eb203159925cf6fc0b1c993ba46528e2f8e8087f0\":\"\":\"afc9a60ab8448b77fb05e8410d0a26e8\":\"770b3782f0e3a19d7d6bb98fa3eb0b916928a2970701c0f4a372a0ecd63499444ae02fd269ddb7d92e11a9e11d0e0b8bc60096a4be79a1e063174b710c5d739d8d05ab5c8ba119ff40843cf8c5dc4e1bd6fcad8389de3b606284c902422108d85eb3589524776641b175946c9ade1465e0d1064c5ae073be90e3261878a9af98\":\"\":32:\"32d6b756\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"6793869513ac886ed66e5897bcfa263877d8465fc762b1ed929ba3d08615fdd5\":\"cda45e29f487f21b820e1af2c8e6d34a8bdf3f72d564a4625a6e06f9bae1c2eac3bbd5c5958fd75cf389a1a31391211745029dcd4cb2575f40ab04710a909b88c2d430cdee279f54cf7c0ff6638d1e0e631f526ee198cfd6e5cdf73d1a11b69de01d640f385fd829616cd2c0e78f09b5f64012e42dee9eb0245b72aba1404e0c\":\"a43de15dae25c606da1e7a4152f0df71\":\"\":\"385834c853772af70675b6be2d5087df84f88b6a303ea594a170e6dd0398ae270fcec61661ca373f4653d8dcc9e71767568c0fb03023b163bdc9ae8a08ea858cbb03b8182b4674147cb35ffda14a2f50ed9eb48d5351f00eb2fa433fdfed6f94833bcf656a7e350eb978a0aaf7a91674145f28f64693197a116b21328e273dca\":128:\"159ffdb05615941e11f0db46ac8f23de\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"9f77c141b234907b38fb45f1b3602f3c29de1ed839bb7ba51f6192aa8baaa287\":\"96dcb74a78e99676a71673e3c9f94c34b34dad2748a6e42cc70ea50e41ef8b86b5992295d2cbc8d621fefce09e8948de7e696b9788377d598796afd002a82b628d9890db78359e1edc075cbc0d3f11d544bfdf5c8a838390cb856735942dff260189c00accfabf720e5fef1d9b7131a6b2b769f67374602d1a7ed9b899b2c398\":\"1b49005788148665cef20d8dcde41889\":\"\":\"b4ca59caaa94749317789b92257f2ef1dd3d9b1f4ee9540927a6ae7bf5bb0b348fcf25ba8ddda79a89d3174ac1713421291910c8926cfbb4ec1e59be7dd50e816ff586f165c605371ee6077ba4ac0ce10499f9a2a44866ce6319fce22652226164cc0a813c3147c4461dd0410e3701d4647d5a003090082e367cb9249cf1be47\":128:\"8048ae0c35a656fcaa2f4c1b6be250e2\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"2419fd9dbe58655122ac1022956a023446b7f4756163769fc1b99eaf8fba1474\":\"93bc33dc647c7321152b12303f38937bd191ab3ce3b3a43a29f6853b33e415667d97192fcab2d1baa017042b301d03bae2f657505cc58e3aa4bd849d1ce85ede0e192a373a3894c41c54edbae29a209e16c87c81445d43968595297b50b55659f8b92d7282a2b3ca85e4b5d4ac4ff5062635103f2c7806fcc7378d5c2013be72\":\"94ef13dbfe9f362da35209f6d62b38a4\":\"\":\"3db23c161cf352ba267dab6a55f611eb5fff78a75288779a167cd0e4db6e75d21f11f4ff2928abcb1b46d82c2a0b1f647c60da61f9a72565f629b06a7b3fe96e4141a6886436859f610724bbe43fb99fac9b78b1e0138e2d57ce5fcfac1599bdba5701cb424535fad9ac482ab381eadca074e7376101b4b436f9c43ed760a0a6\":128:\"ecd4a7370096dc781c3eb3f7e5985ef1\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"08e11a8b4b24e63060c5002713725bb5b4a412f1d76eac13989738ce94e19642\":\"d5598f4e37274f3b617aa4f9cf6b8547b4eb1e0eac79f6eedd6cd5364f8891f66b8d0cb09f54777d461bbf92d6fd74b3fac412b77f2c48e1024cf09b83c1e71bb86f0a20f82d296883ffee62a4a192b184bc6d7ba0448c1519310c83b18c00e71153137afad14f096b43d454f205ba6b6c2ec162aa992cebf50735dd9bb37c7c\":\"c6f1e6a39cabda1089048b536e39cf67\":\"\":\"1fdaf0156456b6b2a68d66091bf2260792748acf3e7bbb7906af8e0df3b569a7c03ee3a48bdfdff7ccd52433d0bbe8c5fe30d93633bb9d591dfad7d81bf8efd4d4a3c5c0bf2ac9832f0a8687f16be640fcf9b19169c251f46b97167d95115acdee3d4443df416275f5597a52c17a4b8c4b723d4b35a7fd0b380fdebd44df8bd5\":120:\"cb9f4d4610c67acfe612af5508bb8c\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"da2dae0107c284ec2aaf6e7306959df1e92d3932b88954f119ab677c6b9dcdb5\":\"277675044caf1713109d4d3abf50c6fb67dc67f7fa584fb1a41c833feead03177cf4b42edac139807ede16eb1d9bed27db741f9542d437781405608de18418c9f7269ab3fd88f6a922a31eab5a3b8b2aa75ee4315fcea80c4954ea6613b1360b1c7c6b6da815e3f6e50f72b7e69c3b6cb3d154855e3f83cbd1947eb54018155a\":\"2005f79d55b12e6dfbab7fedecc50e2d\":\"\":\"c2aaab524d1738b5244af642bbd16b32ba954e69ae51acc804a6b0f89f6cb77ba2db2b0e109cda6036786f9cec5587b01e306ee8b3d588748c61ad7fce1266165729d0153ee189746b107ce15ced667279a484294725e120dc1803d2c751784436ab8ff1d5a537628ee35742d1917dc51f8cb46c2d6b983bdec502e99b85e5b5\":120:\"52b4d7f2cc44f0725ee903551f681d\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"637807b3e472e2287b09d5a3ee62f791a416419ba35e11c49b24dbadc209f0ba\":\"e91a0a7320329dabb0d0fd7f099a4d313724aeeebcffe6fcea5b00af27d258cf9774845d29aaf5dad634c6f087c3311b1c92775fda8df8820c91186da30dc79747be6ec6230f2c261063143f4fc89d94c7efc145e68bfdbd58fb14e856578ed57ee5b3cba2cc67dd6497f05d1570efa496b46f5bcbf82ff9c6a414f76fcf3f5c\":\"46909d8dba6c82b86c7a2aca3c9e71e0\":\"\":\"13b4ad9c51063a7f697f3fc68030144aee0aeef0b5a52c9d4920a7185b0452159cf13e64ca216ff16637d0946a75fb5da283fcd263dd7ef2c8f14cf75537742d1f0e48846fcdbf03bc343203f7c31cf61b36374033462a7b813f4dbe9386e57874591fde606fbc150d4916c339f1950b09b1911b1b9119c3ff4053e05910ffb2\":120:\"6a5c83f807401d1a9a3a2688289f61\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"33613dc6e029df0f3ab9ca66fa96cdeaa84c1261dd586723b1ce873545565f7a\":\"775862b39c2a509afd3470a56891fbb79bdb7dacfdb9ac72ba4730cb936d364e1aed3c92c01a018cfcd7953f751003934c15bdfdf2826e9947ea8e521f55fd2a04c75156e4910f38932c9732eb3e60423e849d34c55e3fd00b48d83028e3b4f35686016126ff16c942ec859d3c3aa2ee6d322a92dc9fa9b0247423416f5a4b47\":\"59484fbc27cdbd917bb55f815f9faab6\":\"\":\"069f80826dbee03e6a3437e7c6d16eb6022bd14827b8e45bd440d9b1a8ddae09999388ba0b1be0a6bafdb96f26dad523a3592fa610d5091f68380f4c1c3fa9ef7a0796ab183e8a82c2bf1f76300f98ce983eab7a93ddb18f1c10534fdb61ace83cae37e225930ab870a46285e733788e907255ca391945d409d2e53dd8a28390\":112:\"9f31f8f8459eb03dc3654caba5c2\":0"}, 
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"75d8132f70ef3f2d8946d296c83014683eb2a4a58b555c0f48e4bfa5774d6672\":\"a5be88fd43dc761838f3a9c7d62923c38414fa61b3678313cbc8fa9c2e5effb6cad7d5be5f39a71a28ff327b68a69f7e6a6bcb90eccacaf3a8659aeb905dd3e38efe57f2bd0d19daacae238baa01a7051084da6598fc5a3783a18decefc8efc8d46c7b1887f87d6d70c909df49340bcc680832faac3dd23cab5bcd80553dd485\":\"5ff41f3e75c25cedda1b08a41b89c4b4\":\"\":\"959396b86913337f2b1fb19767b787c18f00661c5d601bc65e884e15ac8043081459e889453e906ee267cb5d04fbaf250144a56c820eca34469967c73daf50796184ecf74f3c054bfa63bdd0c32425a8e10546ac342bb8e38a186e42a403cb80110aefd5f2d0bcdd353daa4430b8e7ec2134925c454745e2f708cd0b90d9d672\":112:\"ca0889a0eb12995079cf9ba77019\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"8d44344d2ff9a02b1c75785bc84f16e4d23614bf43b2b9a87798b418e905c532\":\"e5689cef9f8258a748a615070fcbf40ed0b24c077e2f9a362cb536737ffbc5383bcafed278d4c5e0f3c83fdd5cde79483c2c178f6fef05ab50f2b8db680027a175bc6d702d249efcd6cbc425b736f1905307c9303a4bd8aca620b57e3bb4b68f2a515259b06cf5365b675edff3457e2e915d7da1e0802f7300b3d56c4644f4ad\":\"256a983cd6d6eb4e80b5c1d1cd2a9f21\":\"\":\"13eeadbecc4c9991e2aa0b1ca819572ef28517528320db970739a16994f82cd8b5bb53d889f298f65c63dcc07089dbf7e9d00612d2cc8220b5630ca0262a698836d906256896eea446f6de4506e558b4f20950528c8c397b6b5b04890204b77a163e46c80c96b3e268fd2754e0380e7330782d606c771d6085b34200a80335f0\":112:\"b33ab1e4029998e2566583dd550d\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"3999a6a394943be3d6e5732af5faf26caf483a3fd42c13b7f4f02132e93a990d\":\"8907e8832553264d7e92afa1595842ac661ddfec3f4294567faa0af61b3d0fdf76a922a2f3affb36b3b3b97f18d5172aec0b8f6f01239bb750c0fdd5da1e1244473cdfade83797037ca46d83123e6105c5c54071971f190da0c59821b0bf87242502bd19d19c7f463145bab0e687a18ffb2216c4a2ad2caf9488801c33c78c03\":\"76e2a5141d094b3a77765ba328f33576\":\"\":\"995189a396486b451db0167cf6990557287074def46eef872e6cfe1a297e256bdff2b71668ff0184eedf00ff1a3ec91358874718f0af88acf2bdb191e97332dc544d940412363840d4c03c7b2231852393c62d625093011ef314e4f755b1d0ee37690b4dfb55194a1465714cc3cbcdf93af39e666be0407508b8764f7ee95d3c\":104:\"87c8f61f459fd4a09d9ee8b331\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"4359a62d54c43770c3a0d51da25cc32fd985d9b41c282887299d2e348aa25a36\":\"f020c9cafba399009bd920c3ffc165d4db47a9ee15ca8c1f51c65e306ccccd3f1d694071a3c765b5255eba6ef6a280f6095f8c195ebdfbee6968b57366e62e16d05b1768825ab7fe66300941270aa121b4fc02ab970ca6e32170cdbccb46fc548620fa1777049343b1600bfb1bdecec6682f0aa7244a0852adbc7aacedfba446\":\"5fefa85c958417b6bc8a61b5496fea93\":\"\":\"3b8f829aa1cc1532a434bfbbd25f42480311657215946b9216846704fd5da5e886ca9d130df466c3b58f5259102ea6b9ad756e9f484a38dd0ed289fea083ab99fefbc2747100071744f10e362351d4ffac6c7c1f5a49ef3c78e2dc667f6b3bfd0fec454c4e3139443da71e514540d7a228db193a4c35d639ec13c1198ee7f81e\":104:\"591db861b9060869edb228a324\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"0d798a357de5a686d06c329e451d7384bfbd462063fb8ea7d77a13dfa1f2aac2\":\"d920785bd7d7b1a2c9c20139380a6ac5f27a11b614ae110da14203146c2615d81e97649e95edb0eda71a0fa1589244ed42fd9449962a92942e38001ac64b212c7e06c113129712a01556577ae02325a26eb92581c0a690a894225e83ff1e36776f22b600508d6d96a0d1c55316b518df8d09769df5e8340cbeabaa0bf7752870\":\"50a003c0cb50ae8a3183cd640ea4c6f6\":\"\":\"9af6a5341cde4b7e1b88346ec481024b40ad95a51533cdd8e09e4809a20684f18eaf243e1df56f02ace9667264cc1c6af6b0914f154b332234f6468cc471ecb2078a9f81c17f4ade83d326b670795458d110e4c4b4cd7fe7f9f5f4d4fb23a038969e4ff4f74839b1edc270fc81fcdc8a0b15b9c2f0561567c471b783b4322ebf\":104:\"6c2f01264f9dbf29962122daff\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"29b01b6d15f6e68fc2e7079429dde5363888a6410191d603941bed272daef7ed\":\"123b6da306978f745d1dd86d7df32d9421523a7f329dd29ad98d2c309145844010295ef443a18d37ffe093080682fb96ba9c2c92105d35d77897b589e2abc7269aba8752c2a48c843bebad2c0fa281015ba85f5f709f6aee9b1d49236d5695f7f7d01554b193c89adcd1a91749138952cb3f0ec8b5f046328b3113aaa0715ef4\":\"cb4ac8373bcbf1b14cf2a6a6a16a422a\":\"\":\"caf71e09395d596d5a7b091c9e87ba6d522e974451e41f33f3e7ded554f24daa9da719e87793424eca9a3eb3972983354041091ba4b16c5c8c14913e1f6cbda09779188e9b5512917a0adf4b4344f119736ba6328897726a317989cddc66f16bab64707564bb0064fe6ab7b2b5cce143e94d4b6d739f58c47b6d4850697f8101\":96:\"f635ff3d8bfbfb49694e05ec\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"f96d8cdcc21884e050f762c049930d78360b56cef5b99ae232c9a8c6e8fa89f7\":\"9cf05e5065531d2539d92ae76a43da1fa3614ffa4b1c73ddc2358f8d71345c01260060239edf629efc3650e0d13174af4294b6da0f39cc7fbecfa324afff89dd7d203416bd144c5e03df60a287fd4a8d54ef9b4b44b3d6de1d9de07418b8a34ec5c28cec3c5b2fb861583178a68ea0af89f2dfbfbd86f7cf1e572e1c8d4b0675\":\"5a7eb964b6bc9e75450b721b4d1f8f92\":\"\":\"566abaa23b8d464d6f107699453740e9e189254145c5132fe46989a6654de297398913daacb4083b29f7b31832079616e9a43c9c2878df1df451e49f1e629c8b9de2fb0e4ae9df48e3e8880f3f1ff5ace8842d2695e702dd1b7bfa7c25b0539b8c80d31ac91856796beced082c213e8be56efd646dae932f5bf503af46f491d8\":96:\"c049cce29c401d3d198773b6\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"253234c3dc9cb3d50a80598c5cde0e37b6b13bf834f3595a9458dee698a6d19b\":\"686ad2740bdad507ebe97aa5bdbef25b8b030c4cdcaccb0d3b675ca91279db3ea75aa222c0ae98f86c24b10038cbb4fe9f897e1145b2f58cd3e9120f9a5620f38aa1e1f63906f557ff4a4c3223f5bb13dca34f8a1c6419e24ea57d114c62fec6fb9eee58a16b9e6a6bd930aa6fedcfc591311250e7167d43cca5916d5beead27\":\"9d156414acb63d11cb34870b937c837d\":\"\":\"96abd56d2f8aefe6c687f035df46c3f952a9933b8a51698e47d973b7d47c65ca3ba2474cb419c84a4c3cefb49e78cee1443a8fbbdaaecf73e9059ef34ac5a0df3fc152ecde2286da8840ad4617fd6ebc1e126314204bdc0a17b958430eb9f727498ff1db17aabbdaf43acca0945342d2ba9346da5373b2372b3081605e895c99\":96:\"3d998e5be9df433da001a686\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"1054d48d52693d2797c80d3f10509d1c808f36a4d65e8fd968e5d56239f856bc\":\"a708e9d2d27ed4228e5b23d358561a77d684d855db9827be2bc102f2278f1961d3f056fb76f76204b2c96b916eb5e407f98e58edfed06de2388521832d97211d851d3e29658df738e3a15593b9db016d9e46fe9df98ce972d59f7058d484886ffaec7b9fd973c55644831241c1ce85bb478e83ccefd26b9718bfe910ac311ecc\":\"87611b936873b63abeaea990d6637a22\":\"\":\"94473e84659bc18eddcebe3112f55426f48ca4d670291fdedd42cc15a7415aa6795fb75b39434884eb266677e1fa7f530c6f3aaa733c0d9c06291bd7dff4c4e5857b2ee9e9f1f61a85571ad32dc9a3259017abe9eb5111e56df2913535669f3b2d722bd35fcdbd6541918885d9677cccaa902b9d3599cd4f0df1f35f4d11b8cf\":64:\"9bd7cfe1023448ac\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"a95dc5127b9cb1c82d558d5b24ae049e24447fd676a49350089951afe01dc797\":\"45f81fa4780a256c40a0efec9547310406904d8991bcf964aa35ec9af457e2a642c1343827839f1f4b42f2b226da351731f416a4b4151f07927c278b371404f027bb2058e1765b367f5433a43fa4153883351041db3f066ef284a3eabd584d1d0b1d594b4ce7b5bca1708fbc661d95a9ac0d77dc29547f022eedc582fc7158c3\":\"0b177d01993ec726fff082ec88c64a31\":\"\":\"16c77b7f541d2dc4e8d31da23e04f18f4254aa283e8cee5b776f3d9a27584f459d0747955efff8945f807209ddaa6421846647d4198534b244498fe13a9073d372171d1b2fc38af66204f3de04000c093ebe659173b8d78dcfb8ca9003d2cd44ed168e6aaf55a06f29e83ceb32b98bafb59f109599f88b5c0f0557bd2b28f03f\":64:\"19eb5f808d65989d\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"53d6393dd7ecc40f2d52460ecdb0607133ad843ef53f380cd3a2755bfa567abe\":\"72199c54dd5efb28c104e3b7210855506f6577d15c4eccdaa6a621a572e15f5845d648cf71b9fafef3411f6c1a664c7974fe71126a5cbab907e2caa342d8d7a05bc68a72c824896ec40e520e90b704dea441d22c5918f98803a88293384f64f92f11650c2cf4d3b062d30e14d149160742f59a473faf8fe00f4bdab9128c3281\":\"db7e93da21f0c9840c54c56e9c6ceba3\":\"\":\"5e83f559fa54926b731334f815783914530bbcc472d4bbd5e65908fb1c421442cb4c57329f2e4ba3d146a6499f34d8f1ec6d43e0cf98bdba923f404b914700edb235b08b0330097ea4162fd0baa1b7177ef0b29d5a6689bc56b8f975d6b6067ade4b8baf1d47a2eeb5b2ed28ebeded381d55d280cb2fb65ce4d82b69cce0594d\":64:\"4e65dde857a0f5c7\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"aa4a53c7764a254b06e1d8003810300b70f5729306effba9fb6210f97648a499\":\"19f3a8c298478d6868bf3b31785eb62e844c37200672e6ef1ecc05c616d981e02c333dbc3f86dbb7ab9ba40e9e57e133e6d1d595fcc6d8e9886a84517212669d5d7ce0f1383cb58681b92dc180c06caa1a7ac1ec974dcd7f2bca7ad2ab2789c9a3a487d64c484319bffa56d854a6d40c62b02d0c7898f641f106ff50d22a12e7\":\"c32288f97af9b6e31aa7e40d9ef8d016\":\"\":\"1fa6aec7a28767c8961363dc4264e6ab97014264f6fe1dda7e9db8646ce9a5463f69e91aad2fce696f9b641d75635bfb0f97ed2d7beaca944cf8bd9dbfffe77b5ae9fd032575e5333c7ce27538c609922843de87b960ebca7c2a2ef9702dd0c32f787b4d7df248fdf526d594a90bad0d6a8dffe212246c36db71e2d348326624\":32:\"1699444e\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"f420b6ef96d9bfe46dcf18246ee230790a6fc854e730f1dd2d1ffd0e8b5c4776\":\"658a954d6c61d0d6f0e81a3c1cc65684483fdc95f280b6d4c964358596c25ca41c389932d74a1a3a17d041e89b7110ea315fadb3128c2c469c350bf9b4723aa9c8abd9065ebbd12c317bfb7090f09633f8c1184f0c4fbe10f5486dbfb847536c886f7d144ed07272a7e62fb523a04111e5ea9e1ab415fd17e72143006db14e9e\":\"4982f502a37eea8bcf316ced466c9fb1\":\"\":\"8630aa78aabe35d9360a44bb2094209b6f70d46d71e3949803cf54e33dafd54c6e49eda9e26dc5c0c1e34908f5281c8cb2a1aeee81186cf45d3eb22f486320c7ee0fb7bf3c211b232a8426e7e82f3e05881bf7d9454cddec7f28e5358cd0e9ea2e9cff938be044c1b21911d50b2ae23ab1aef377511ea657adcb560c34209f8b\":32:\"3aa91b73\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"50f3b822dfc70382d8695811e6b0a2896ea2bcd4d5268778cd484053c8a19288\":\"15bfb3a562ced63c92561a78374af40c88a08ce02392419e03d7543365c5b6525951ef2dec5927474a0ef85f519e5ef795881db3eafa765ec38e6be7b565a878c13d90c02889dc50cbe87081d9225a515504c7be15bf97f5d72a4d81f218a148a46fbd42983ab002fce0a54719bfe301bb761753cb330dc25be517b87d0428d9\":\"980810c11abd3aff43408ec9a69abcb3\":\"\":\"12632296f27eb2439009f6032a3f648370303dcebaac311b684de2496f399b271347b19e045c1060802f3f742b6c780d20b9d589cc082d7d0d580dfb7231171cfb612227fcdee7feae4f8defd34c89fb0d68570e782192a7bdd9a5464f35dc6a4282cf9cc3fdfac988d129eddf8e0795ccc24a113f872ada88834c974df8bc69\":32:\"32c1c4c5\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"29072ab5bad2c1425ca8dd0ae56f27e93f8d26b320b08f77b8bd3fa9d03edc6c\":\"3c7afc5cfc5a1e141587e93fef8427d4f21d892b983b7c9b6e9de3ee168837a1533847c8a2e2ab0706ac1474e9aa54ab57e7860bca9ebb83bd6d3ae26ca5387abdb9a60c4a9928484742a91294b13ab8f51eb4f599a30e9cb1894aca32a62a4c2793ee6793df473f43234c9eafb44d585a7d92a50aebef80c73c86ef67f5b5a4\":\"0201edf80475d2f969a90848f639528c\":\"4c8ff3edeaa68e47bbc8724b37822216d42e2669ca127da14b7b488fde31a49c7d357fb9aecc1991b3c6f63a4ce43959a22de70545e6aee8674d812ecaaef93ad03b5d4c99bdef6d52f21fc7fdbeb1c5629a76df59620aaefda81a8e73cebe4c646beffd7f4a98a5283cc7bc5e78b2a70f43e0cab0b7772e03a5f048ec75081a\":\"f3755aae6813e4e4b84a089ca1496564676655ba3c94e59c5f682adbbfed21e76aed0db78390258cf5fbf15f06c6b6468414cb6493c8b9b953b4954ecaf07ecaf8586ae001710d4069da6d21810bcdcbb831f7041cdbb984b7c55878598a6658883178dcc0fa03394519b8b9c3bed0e5c073429f5dd071a9184b015cbbbc62e1\":128:\"0549dd9f2a123bd6d58e5cd16c0624a1\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"aa9999af53720d0c1288fd3fe307a471160635287eebf41dd77c82d1f9cc9d61\":\"6ce6f2dc202750219e15a24e1ff0678ffdde55b27cdcab6da188bd5235a3bdc677f72f106579d02c2970d4542e4e2372886e1a6d74c596ce735f51f2ee6aff4d62bd24112ec7cd1adc7c660561f163170cdf047c241c53b8a5b2e03fde48c249a319bb90c2693c468c9dd136e94e05f067cd1d68244ce50be318ae0464b79acd\":\"6299d651a032bdf3a7e6b25ace660e30\":\"afab0a3d1960ac973ee2f4461dacd10d189412b37e572cad7888bb4d2453f1eefbd6725aadd5f982393dfa59c3cf1ee342dd91e1fbfab10a802e3a0eda226fde2686e7db1015405a3d33c921e5aa857bfda53ca3aed3ff0e18c289406740a7c5d9f86ce43db40c9032e98ab126c7c0364e2efc008312b7641d36503d183fa5a5\":\"a8059fe6ff711616afb591b5e5de497b3b7813f9de658c7b47cc3e7b07d0805c1ba05856d98341869b8394f3b5df2876ae19837edb3931eebeb0f26eb6c4a2ea78003d82a98111305208ccaceaf77e5d71996cca4f9a5eb712dd916b71455f741ec2dde51f56828667b7a2da015e1886fba71e496a542d94a38efbcb5353fb89\":128:\"2ff4d8d00400ad63a6ae7842eefb16eb\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"31721e5e3a748a7f7369f3dffc1cbb570ceac868ef9d1f29b944b7e86a26d273\":\"6afc1d22233a60c3e6851447de89152a0dbadcd87e35fc947ca4bc886f1f87549ea106b097e2655136833d06dfb879a85732298860c149c5e5ff03bb2a95d9cd3deeb8ffdf951ea5f97e32c1ed75271d2ea58d158ae6d568bf197d69130977e330ebfef33f222bfd5b56bc6b0382dc99c4f0e42b0aa7a117b43f96d43f6e02dd\":\"523247d56cc67c752b20eab7a28f85fe\":\"11eb41aeae3611f0de77bfa1221ef5b7d254faf893dbdaead926a61605f8a86f20f1fb84e0c5acd195143bc5a4f297bf729129f898a2013175b3db7004115a6120134d8e354afe36699a6c6618d739c805b5b91739df67de7667729f1d6eae1a0609897999d474be4d8b826df901c6f39d522570d38d2d1aa828382932a177b1\":\"39e7f32bb3e8436d97a1d86a22750768001fe3a805516d3f800352323afd221991105d12da69ce7430402fa7923958ad5ed85506b968c4dd89516d6e3d02e722db3954ce098ec3299ef4f2ed4a89f383408dceca9dabc6f8eefe5a1f80093961c29a94b222d1a04d2c1e453d2e02977f3dd77a4659e2bde2fdbba8e2829db4f1\":128:\"506883db674fa0417e0832efc040227c\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"100bd2bf9c8b24cc2e8d57697cd131c846b55ad6ff0b214c0de14104b465b58b\":\"81c3370da989f774c1962f60c57299747481bea0e6b91df846e6ef93cada977bc742ee33ce085ae33eb9f7393a0943b647205a7e1ffb2a6a803a1ce7a88902456d66612362962b97c7152b57f1d54de94a39f07c1a8098da4ea5e498d426b7036c642fbeebefda50b8c421a7a33b1a8499dc35011d80a51d34285824d6f01722\":\"363e8af6f38307ec126e466e7056cc45\":\"471f7e9a0b505b12996747ec9e32731f11911ee95d70795bbd1bba34cf782d4100ce30a85b23f9f817f30e8f314e1a23e101201c920ce12ce732cc3fe01c74a9ee8d3e1599aa22f2398c3265d4dbda626a8ff4262889009e087fbef6babe33d7300e5cfc4c0056f3562a913d2594fee8e44959cf728599a9d3e7ee4a9ecd6694\":\"9494d01966ac887b8295bde61f0e7d006ea7b5c984a29cf5d849194f35d7b0f6ddb3bbd9646d7b9b961c515179901d2b04cb7cf7b6c8736d1d472ae8bb9a6dc9194b03b3f5373551a5ae0c0f023967669c873f0acfb02c0ae3a384e70f7a7ca05861f257f36a2ad5fbb591473dfc3ae1264dca0e889e0ddbf93dadf75db2059b\":120:\"5c78d914cac78c514e275a244d0ea4\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"614dd1762deb5c726eadf0e6587f9f38fa63d16bca1926955404f1b9f83e241a\":\"1ae828a1693d3c24651ab8ba59fb1185d08e6cc4a964f30dac59cd81ff4bdfce8023ab1b6dffb594a4250d25f611763efb4152cd35b937ca11373d237f1f8b3c0e21b942beb1f4ffe5014198c9ff59896ddfbb55e69963e3ef6b03d3fa134977870cd6f3ac10bbf59bdcc9f103cc2d58f294ef5f007a9f903c7bada08cb454e6\":\"10d079a86894b0c17bfcc8ffc4ecf7bc\":\"c4035f80b6d2ea288afd4ddaec1eb232b78be5a86583fa85f791d546102c97ace9716c2702483d762c8e4eda12f3dd10a9a49a2d72cd4694fa794477b54b4367be6b548675aee4c351e3f66c7e113aecfbcc57b8bbab4a039f28488237c75313e62612847b915ef9b582e146b2bfabbfce576a984f5ce4be0e6bff5480584fc3\":\"bf5fb0445aab46aba504801d5356455f28c98f300670a731bdd0c901a1d5564aa31f5d467e5f80dadbfeca61d2bf72b570f3935ba04c45a2ff7994bac6cabf84db2a42cd5db2a4f160c97c76817cc5cb62d4006d895fcdb218c1464b5caaadbd1f61779938e9a84440615eae050cd6f1713cfbd695d78818b2af78157339e9d9\":120:\"6d815ee12813875ce74e3aed3c7b73\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"12e97fafff7d397ea34efc0a8528afcd51c1b2ccda680ae9049edc8359b78ec0\":\"9fbf0141cd50bd1b3ccaf137b808b698570642ab20c32120901622b34173d7ad119abca3c61bbf1e6dd5cb182a079f3e01b0e5263d984c6186f01792125dd6c47c30033008ca2e0377f990285094f652c55a348242dfaa59f76989fcf86033c8d9c0b2a526bf46cca207e055e1dbc7cf3d0b7a840c8fb5f85784c9e4563f71de\":\"8eb11abfe350c0d5a6b02477b44867e9\":\"0a830029d450e20aaef484d4abee9dadeabbd6feaf800b3a693b4746db059efb7d110405b45e45a9e5acf90957c154674dfb2c1cd787af371e01bafc4e8475d0268b969d25756a1121a519afa61f3d6ecded4e0640f0ddd471f5b8e82029fd2887df4e65af9580390b6924022e39acfede7530e5f0e54f0285ba565ff49af542\":\"067cd6ff8461ac80217ef70a91dcf6edb2fbdd31856815cf356fffa63ba3f5cb293d7f1ed32ae40248693617f27839a34e871fdde635c04d1e66743f730a06e2be25cafe1d67d804879fe38e009268ec50a0294da445c795742ff1e924170e4c2e0e9ef3bdc26c251f5537218d295d93d57baccc4dee6185c235d7ec5c9926a6\":120:\"931f44f10993c836e534a59c1aeb98\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"c732da000262de558bd3ea65e66e20e11605170c90b67708bda43f40abed74fe\":\"7d6c981c30ef87a46f53aecb4c97124fb94b45057635d5bf1d4f3a3bdb534e9ab62b4a425de9dc52537575ed9ff406cfbf75403d3d9cdbd9fcd520d62065f81483427fa27964642cc1a07822da0f6234a689eb30e8425d7709abfd18666c76c963eecef20503ee77c96802c120abea1428cc64a08fc20860527854fecc571a6c\":\"523dd34ea263c31c2215053986626d02\":\"f170556ac5d38f0661bae33e0826356c8488218903eba1bfa49b16882537ef78283fd9351f37f44a7687049a608c3ddcc82817d4ba96a40d05807a38ee3f2d5cb8b1121db61318fe22bfd3afb319e84c4e2f94570a92433db29bd2193485449c719a2c6030696f53ac729df90678eb018783b25740d806d1ef6980e10d396595\":\"3470d4544f7bfa3ac0627a56e66c56fa062188440834b9238bd20e89dfc701fe6cfe0bf4ea2387014bd83c63ab7c912e1c0dce7c2d92eaea155f886b574bc94a8f4f275dffe2d84173a05b99d8029c36dd3c35c12709d33f55c3bcd96e9a815f77a4fe8e50639d8f195a526486f1209d7bf7e86ac3dfc4a1d2cbddb6d330e5db\":112:\"5924f3ceff0207fc8ba8179a9925\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"2684bccf2b845314a0c4b8b5a780f91aa7ed1177539122dc8717c14bb50e2dff\":\"1a4174d4e18ae0b6434f35dcd9c86cf158c42ce00ceb12f4356ec118d659820518c326a1b2ab92279d949f74c45219c660cb84fb6b10b14d56a501173fd3b129ac89db0de22874d92bec724e94751f91a817a42a28e8e15672172c0b0db4ead46b14d4bc21ad8f5ba1f9e7e0fcc867700681349b8102a208d76ae4ef7df5b56e\":\"8433b59b41fe0cdc5b30e4e87c5028ec\":\"280026eeebf05e26e84955e4a36352d4f97f3193dce0795d526d05645bf5d2eec4b92ee8dce54d78fd3fc3e36bc79d5bf9ee3b2699310a75dbc5007bdacb4dc88d06515995f8f5b1aa90cb8fc036b763a5e819db70c091802fb7f24b9c2a68ff194032fffc4ef798936aabccbb43f22a2bbd7e1ab9d0434d443dac4929b84193\":\"cc155e04472c0872d5ccf8910d34496f380954da7653a1e1d3c460fbbc791c9b82e35176e938b7e21eb4690ed9fca74ba45a03dac4abc4f625ffdfad02e1acccf18b5a1878f911fb6f6e09ce0d4c6a0bb87226e914879a1b3085c30e8328aa6e0d1c49c21b760b82e469981b40ea102f3998c81dd9799f484ab89b19396ab7e1\":112:\"5a80008e6da40c71b316b84ae284\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"484a33ba0b97c2887a86a1476f274e236eb37a72e05f9e74348248877ea99e98\":\"4d81cec14b398257a31ad1e3581c00d05e12b37b71260bdd95bc0b6981b614598ffbbb3ec4bb7deb5673a1020139877122f88504c9c53265706fe76623a9b488a3dfdd4cbc1b7b46c7fce9d7378e164964c0a377337a5c172e5e4de6206375164cd7beb0305d7a90f5c73e12f445326e1bc9ac5acd1bd4bcbe4662524891a2e9\":\"c3a5cc19aef6d64b656d66fad697b829\":\"30f276f96a50e17b452dcb5e1b4ab666dc7c4c72d0d9ab2abaf77eae2e3bab7dbe5ac005d7eac5480e1bae13646b59155528abdc148b3b71f06d017c4b12d64aa3990cc96941eaac14b60eb347e0be873de2b6fe2b86e2c2fc063b29511b70144ecd315b9491001b122701b9c8cc1d85427b6c60663ccd9d1fa84e1c2f609f36\":\"579fd8fb50d795b5b208c2d5b0a8b1804f754a30a1003025301655aebcda2d2ff30d29a16d0fb17a28401127750fc87c9e3aa08540817228b049c387253ea2359035b8063ab4bf54504ca5ad93b54b8ac5bd0c1ef3c6769fb1ed239bb76f3e0bc51d356aa91b494d22749c8e4cdb1629e93f7c6e46ff9145916c1275669ae5ba\":112:\"1c39aac1d5ffe7916a08ab2ce279\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"4a5f5321b515cfcde493148ee4c44c693b1979b3a3ba522a2a80e5d27c93fd1b\":\"962b8504feb57ae73e93c2e8962c9562f409c908e51f9904df1623eaa0c6b998db6ee8919d805b6ffcc37da51300c1ae16bca21f8f6f63af989a813ae8fe28c3fb012f003dab7e71b08d757799208806062d62b4ac937712409f9fafff3e3579a4d92d4437a6f0b263e1da7e4651e0a521be5f6f49ff5a0778f07bd5d3dac696\":\"c2cb0166046bad0cf0a107af83921d7a\":\"e48abfb657ab33f58eeda8c58a20e7e299bc3e7481f704c326529408580f9a5130cf6f7368502d20b03ba6c3b8f6f28c076a3ef7b8e987750dc972be953e712483e6f328da57e4b5c501fa7c720593eb89ff9644fbdc45478f80ee89f096694dcb44a9b3a6aca0904d4aa4e475b4b24771df9fd6ef9557f4f5c842ac241b212f\":\"11bd55d969603ff3d46355cb19c69557b99825a4c23eeafc8eed8422dab537c0fa9753191c49a6fd9e0d6760ed816a49e7f5704b5936a498544e2bbba7875c513c031f11527ca1b9b579960be6964fba9119dcece8205c174be07ebffada83375678de76fc012b0ee179787b4aa9fb6e2b459575260eb01f23786dc24d1d45ef\":104:\"36853a029b5163ca76c72d4fec\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"c8f7b7e6295fc8e33740bf2807caeaf4b90817cc3ef3d9f38f704d9f6164e41d\":\"4c26e489069b487ce9dc0e295d5e89760401185374041b0efca5bbf758e7d010ccbfe5999e2a817776aa8f49c1e5d43bcdade2989fe5be635dab54cb0e390a21b832b30f688857b9e09c346bcc5397e51cf71acbe1bfcaa1ecd7e87fe5dfde180d951922e60dd8203ff210c995eb54bb981f7e931f0b1f52dce0cf1b2eba503f\":\"903b2eeb9d0b3794acb7439d341cfe0d\":\"83e99497bfbe9393b065b0b18c13f99b67f1fdd724fd5d70cdccd2b8dd658499cb9f57e1a1fe39634ab0869182de085722a79eaabf057aac7b3f3230f51a2f9b48b49d592f02246dacbe915ff9d9a53f7e5332f7a9d89649050b075c07e5e74f281ca1a0dbe632c0aecf3b1911cd6ec4f8facc2777d0d14784bf5951a1c62c33\":\"63e2941bf4a13374627be66bdd4e57119149f81f4c1a8a321d27a4a79e7d61e2dcec9d7b13fcccf12f5b059cc209f8414ae81966462a266e92b4b3c25198ee240e0bc6f6197df1e24e8d4379fcae89e6240a7f9c7bab886e79990b846e98e4bacb8b3b17422249943e9973de42da5e38e4eb52830b1facce766b3389a5312476\":104:\"6e31c5db3146ae45ef5d50485e\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"dec062efc1bd2556b87a81143d025abbaa532c586d5ebb065859a2071f8f07e4\":\"02191bcb060e61827dbddac6c2961dbab8812cdc2ac77bf0275628e8e36bae18ad4deb77b2682ade0aef76afd4592173ba29dae4d0735963c803856eaa6f60a6c21785358e87f3c4a91e321c59e04c150297de873679194ba5ca857f7d91ffc358e73810d555ebd4dbd1fe4fbc4ffa4ff38e4b41db9af0a84fe9828708631469\":\"19abd0361443c3ac2a46f2606eeb1a69\":\"c3785e7c0095726fd1f3ca842057b0ea2baf9c3fe1119c2147609158a2039f26cedf8a44e046955ba7e7cad9f48cb49274fc53b109d7897e080af252e7dc64807c276bcf668d2cd505c9ce8e584609d293ebd2a4515bfbaf78c413d6e29dc90974db38b564ffe9a40d3955dba9f19b6f39bf942669cf80e4676d6c10df566ca1\":\"91a16c7fe029e3fddacf0809dde7d041c438977b89192e6fed7605d0133f3d9e810355d186432f6529bd2c4cb9dadb4fedf5128cb45e25a3a46bf74ed93f31349f64a69dbe86592d76e437947f1c1d7270d1cffe80afe10ae8523541961eacee1838c168a2ab76703ea4674a68a96b8a298a672ffc140e98e452d501fd57f000\":104:\"5b4071a4be0543aaa59b56de35\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"9b7b700d978e33ae9311b206347f488e2832fad5ce7e6026ad5e24fb47104fcb\":\"37aef6e4200c6abc3d161daaf9dd6ede002ce8c63d9ed54e8ac56bdc8d36906bea663d2857d8d543166ba150827735ec78e37f92e682275e268d377b1880970df232162e55c9311882f889e7d183e5cf4972691c85f81c47e1224b9c97ee3963d75c6a032270ad6d713c999913f0b58a2d4f42b85a3b0b40541a31398cdfb4b0\":\"d0bbc284af767af9a31b863d66cb6138\":\"dfb87a65ab2d99d7d753042aa47448ad830e546d298d6ad52b85207bbb0cbe8cf3cdb12b3544f1fc228fdae04a241abf9e71de8ae14f2de2c261469c383c682e13582e07cddb1ed9bff1fd2aa0be7978096a914676dfbe7bec6edd927362f656ce1de86229bc511cfec4cda77a1e761e7ab8664e4df08cb820ebdb604c2cdbb0\":\"dcd5575d94fffc647d4c081e3ce03928651419a32ada2af02de2f58d68fa98eb1fd5ef671875719a9c65b9ecc69513408a79a0a5d57cabd04f8e651f5b8fc1ff42ce58d8a212ac2bcb83c5c53c542c282553a62b4e3d7d4f049ab13172739a0f46e0a2fd9aec54eb0c84141c6b341783754372df69d39e48cc24eb3d9ddb21a9\":96:\"4a7ac79db94b27469b92343a\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"ce15e61edd9320ceacbf3984d87c707159caa738e7e76285be00b5a95954b523\":\"8af4a7d92441ce931815fa4e24d69f66256fec7e62f79a029b684b5db304a46b2a3d3a7ee8d6b7ae38caa7de526d5c0f28dc65a0913a383b7ee1640cbe24997ba95b9b12fa1e9ce9f9100d883c16b6286dce17e381af15113f56197c97fe6b45be00a3df05045f476829d7b303211ac97cf989a18c16e27fbf23570d9d18f04b\":\"b1269c8495ea1469ff41d8154ae6765e\":\"0ad26a08a5cc2ec825347d7ffd5aac795eb68aa7e22970d991c863fa6d1fa720137aa5cde4e382625a0038e6ed72da3b5003c1b2a953c2b2138e0cf870cca4afb595c0451aa793fb0a2bc43834a0aca1e760590cca765ad672ead975993f82ae6765c5afbddc6062d7c4babebf650ab097db1a1d9a2a99e8fd2e0eb8a7b916f6\":\"ad0ab4e77257866e4a57cf44fa4049428e56a6e8b8fd47b4cd00bfce84fa8f5a43f1df2061b0a37311b4a1436bad0d61d52ced5e262ed41a7eb125d61cec2e3fbaa95e533b43f318048096ebc8466f0cd609bb5e7c3fc6e5701aace546618a170f88c0b7ed76b63759ca4e4b931a86ac379dd12ad2cba7d47a19a3ae7c242fb0\":96:\"fb1e988f9c97358a17e35e6f\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"aef24b8205d4085d978505f04724293c2819ef9f3f03a6c758078690fc4bf7c8\":\"db26453170db2f984312e0cf961d1a7df1154f0525c31f166be5c9f516736501f9f2dd8096a69b6441888ce27aaceacb0b365a38e4e01e2e34027c023206e814f22d46fd2fa69f87509ddced4b8852a76b2532b92f069b8c922ac13b2b7f19cb7c524657a4ee6e989cf2598bef674aa31576776853fb7f9a2704d6b3ee7fbcbb\":\"81456baa337c3dfd162d9c5f72a2e216\":\"484a5f4772643cf74ccdced0e5d80862f9300f26ae3139968649d3d7bb761b313f2ba63798b2040d397c3d1569285fee8498fd9254851c15b98af5bd351fa72e7d574c62ede0d728e1279e8b4e4784fd63ea7851e99d1d2356bcbf868528f8d0a90fc3b884ece631648d916ec97abadca1b0dd7670e6ad42245021570582ec7c\":\"da95c61cd2bb88fea78c059c254d2b949d4fc291c73ac178ace44c1e6a339f64931c857d3a7cb276a04993620adb6918dfd3f9083edad384a8e6c1d4799d526a1c969d8deb0e2667d6d06f559baf914b49fc463244528aa6522d19699065438d939521d7d7bb149835298f2054bcaae6d786f6dde133b640697a3d37c697579a\":96:\"bc1c1cbcad2e1a66ace079a2\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"9685aea9aaebbd691e679779034729306d5887bee4c1f90f6ee3a397a0ff3ece\":\"ae3b2fa1e209f72c167eb16bc15b7669b87d4ab516e428157810b87a83e90d56e267bd4996522b5b22c2a349d3765ca27ea27057dd71f7c18ddd053033bd780b6cb689f48c383e9c717b9b265cb9e32c70c4a7d8fb933e986d996b5ad914cd645b74c47ac3a0de952ee3fc73ada83d896da7ca0b2a0b10e4f701fa13cba9ec50\":\"b1bc140531ae8c69e2ffc784e0988038\":\"294ff858fa6efc82ca3be4d05332bbb951a71a7ddfa4b78472e1582b445312eec11793d8d6e1e858d9cb078b5fc9083ac8a3e3bd82964cb07c08450567922299f68fd47663c7a77c29f2b5347f229301433d5a75263158a0d80095859e7e45476b99b23412046bfbe4eafff9f7820ba49919d2c987cf00c286c784e7669d8fe8\":\"6575128b576e68f7b3709e325b3d616783b42ff7f7631eb62b90cb0c8a86bd324756f43af53c33cbdaf9cf64ea94cf1b7fab5003f00c1d07f3fc8eb1931d759f9c43477ba22311a111488092c42b7786facf42b861a824cd1bcdc603a77d11253f15206a929a3e16e8737d080b8e5f0da8896226989a9964d72e491187250472\":64:\"f78c4dd37c06b197\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"3adf0da24394a98c7beae01d28f261a9cbd887aeeecc0c29e84540264d5a6bad\":\"8cf023d717b0f82f2b81750b53fb665c1c90f4740af4a3534b36b847df33ba5eec19eb24ead70a4b613a82572878216181d59b0c4c4df99be08d021cf182724d8ff5ec4e85884d0f69c16238fbbdbc5529ffcc4e418405e4e95139f79d3115a1ac56820cd39fc413ab72f7d447f947cb0541fc2be261f1246c0a786199013b22\":\"ad41288817577316df2d881ac93fcdef\":\"ad33ce922372fbe3531c0dece69f85f18eb1bbfb09a178403832308de0e54b1010db2636c4b7d9caa478138f61db5149c9fd7f3b45b7a1876729fe67622a37f0b322ef9cf6043b301a5d4c81e6f347d22bd3e40722059d3be945845c6b0629fbcfcaf885c7f393aa81f242c48c61a439574761ef6b671972cac664403250750e\":\"9d465e9c4228323946b1261892243d8455edb9eb8633d026d4033fa3965d20730979ba6952c0f6f2c5768f03c19256b64bc759d2e7b92424bbc668308504ba34384c2bb37baaf91a3a4f0952a050a3d69853141b49e86eda3bf0c4db4ebcd1c41e7f13eca20bf574a47ec45b8c98def17c0741805bf8f37923ba2b5221428578\":64:\"507618cec6d03964\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"9ef64b4132db54668568e2ae66ab61f62a820c7002a67a7e42006280a373feba\":\"4b96dce753273188c4cca3386a7415d5d9263757376e1f32797df47992e92e1bc0ab0833363b3acffde22602d4e47307bc8f252944414a15e1398693fd3b8bf4d8101cdcf70ce2c9de8cb7f5bb17cd83f09b1bc78ba07c34b9214e250c5940e9794199cb392309027d5ab4f32b51c533db6732024bd412f2cb0c5178d5296aa5\":\"07a86dbe2cce040eccdad79b3d211ecc\":\"af7a75748ee293015b600ca82ccc7718f4ecc20c3a2357ee02fb726330a0d79ca8bb97979bc0c89f4c60d7154f8bd29ba6ec5f2f4be286ea8a258cf6bd39b4f42d6db8e70c99ec3af26bb4d8003dc6fd0fdfbbc620d511d4d5f09ddf975a1663ac2979ae0978b0bc1e7bfcd660ae4ac7f1a8f6d8ee35752ed59a604f07dfda53\":\"e3e862146b6fb48b01ababc462dd560298eea7bfe5f3248e28a908d1de08c7e91fcf63922c394e7a51b64f4382225093e78598c050e588ff4ad38f3e83dc07b77ce569c6ab8f8a9cb0056b3155aa1503cebeb64c86d6d9cdbb178ea9a01a8ba33a1c48beb92ee4cf60e7dedf986019e19089cd186c98c229b0ff42c9e1aca571\":64:\"8614c216055c0660\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"f14ac79f35bc5a685433eea5bb7fd69fc959aabda24cbd8b7795fb2e41f90ab0\":\"8a20da14819079960b77ed5e548d0aa0bdcffb752817c1abe4195e612cfbb58c8e5a8af69f75bad10ee8afdf0b0d5c46c4dc11c32bff16d5e7e82e77fd80e475c6a5a0be36718af232697ab22314306b8ee32484b3461da657710c06170e80a6a8844f898c2be29366c8430f2392d100ffd419603cbce406dc7315577e6e9ee2\":\"353e1d08edce44c966430513cb7a0383\":\"cb1dde4ff5a6867038c170192fc2d292f5bb349d5b9a903cf3d88c09ce78fb1f4a776ff7588a25abb5e5f6a44791d7296afef3f32ed31db1def37dd25be0570a204955121f9c65b79a3ea88fc452dbcb82719243c11bc27e3408adf802b6e8b4e701ee4e9dfd140cb3277bf605bd5fb757d2325f7805fc6f0d1ea5a6207fac5f\":\"49b5e4ea0421034c074cde67dd39a0310c3f31e8138672ba2ecc0777be542f1c6529836d5206b79dac83d96aab56787a35c584b31228f007f11630328c3f40a57be37487689ee5babb576e7d14ff0f1f1ba6e4be11637352a4336327681058b99df2e44f9772de4e0e456d2e34dec5eeb335b238e862841d166e0612cc0f18f3\":32:\"88aed643\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"b55ac909e73989e310ae37d13c54bbd5a126f419a3b01a2ad8961d89bd247f81\":\"8a663e8b21a027c4a9545d145d42d9c67b4fcd5d0e39aa68822aedbd609e2c681f60e6315035321de739858b2b082bc05551fe9b8456c2e89c6151282c6068b915eae5762e4d6d765d667de58a315e061b3d60035ada50f59258eb6e2a1cd6b52eea7eb9d404fd96e71f19feff65b74a4b4f07061adf7c1b0e54e2ece7a2cd49\":\"9328abab0d3f63c75ddafd8559d96b4f\":\"cbae20aa1996abb62471aac91cd78080953fbe3b165d4c9435832ef1106e7e3424db8850f44a431c289ab4f2bbbea9e5c0c7aaf2e8de69c0ced176283662cadd280d8fda0c859551f0f90893ca57695c95803a1546826922ac78703d7ccae285b7ccd4bbab551756cccc6869dcf34b6af8d8b80c25c6fb1d2caa7f28161fb854\":\"457e13ff4eeaaae75d14bbf1bff91706c3168b9b146aed29dbe31b12ad90c1c158833be95701229ac6e4a13997e0a2d961d4a0021c4d8920ec54a9a935e5ea73b17e8fa60559df76bd07d966dfa7d86d1a77a313228b2ae7f66b5b696726c02af2c808bf75e0b9591a220e762f57c680ca68f20b2b5413b07731bbd49de039bf\":32:\"5de0434a\":0"},
+(char[]) {"gcm_encrypt_and_tag:POLARSSL_CIPHER_ID_AES:\"1477e189fb3546efac5cc144f25e132ffd0081be76e912e25cbce7ad63f1c2c4\":\"7bd3ea956f4b938ebe83ef9a75ddbda16717e924dd4e45202560bf5f0cffbffcdd23be3ae08ff30503d698ed08568ff6b3f6b9fdc9ea79c8e53a838cc8566a8b52ce7c21b2b067e778925a066c970a6c37b8a6cfc53145f24bf698c352078a7f0409b53196e00c619237454c190b970842bb6629c0def7f166d19565127cbce0\":\"c109f35893aff139db8ed51c85fee237\":\"8f7f9f71a4b2bb0aaf55fced4eb43c57415526162070919b5f8c08904942181820d5847dfd54d9ba707c5e893a888d5a38d0130f7f52c1f638b0119cf7bc5f2b68f51ff5168802e561dff2cf9c5310011c809eba002b2fa348718e8a5cb732056273cc7d01cce5f5837ab0b09b6c4c5321a7f30a3a3cd21f29da79fce3f3728b\":\"7841e3d78746f07e5614233df7175931e3c257e09ebd7b78545fae484d835ffe3db3825d3aa1e5cc1541fe6cac90769dc5aaeded0c148b5b4f397990eb34b39ee7881804e5a66ccc8d4afe907948780c4e646cc26479e1da874394cb3537a8f303e0aa13bd3cc36f6cc40438bcd41ef8b6a1cdee425175dcd17ee62611d09b02\":32:\"cb13ce59\":0"}};
+*/
+  for (int i=0; i<NR_TESTS; i++) {
+    fprintf( stdout, "Load Test #%d %s %d \n",i, tests[i], strlen(tests[i]));
+    cnt = parse_arguments( &tests[i][0], strlen(tests[i]), params );
+    fprintf(stdout, "# of params: %d\n",cnt);
+    ret = dispatch_test( cnt, params );
+
+    if( ret == 0 && test_errors == 0 )  {
+       fprintf( stdout, "Test #%d passed!\n",i);
+       fflush( stdout );
+       total_tests++;
+    } else if( ret == 2 ){
+       fprintf( stderr, "Failed to parse test #%d\n",i);
+       exit( 2 );
+    } else {
+        fprintf( stdout, "Test #%d failed!\n",i);
+        fflush( stdout );
+        total_errors++;
+    }
+  }
+#endif  // FILESYSTEM 
+
+    fprintf( stdout, "\n----------------------------------------------------------------------------\n\n");
+    if( total_errors == 0 )
+        fprintf( stdout, "PASSED" );
+    else
+        fprintf( stdout, "FAILED" );
+
+    fprintf( stdout, " (%d / %d tests (%d skipped))\n",
+             total_tests - total_errors, total_tests, total_skipped );
+
+#if defined(POLARSSL_MEMORY_BUFFER_ALLOC_C)
+#if defined(POLARSSL_MEMORY_DEBUG)
+    memory_buffer_alloc_status();
+#endif
+    memory_buffer_alloc_free();
+#endif
+
+    return( total_errors != 0 );
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Thu Sep 27 06:34:22 2018 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/024bf7f99721
\ No newline at end of file