mbed TLS library

Dependents:   HTTPClient-SSL WS_SERVER

Files at this revision

API Documentation at this revision

Comitter:
ansond
Date:
Thu Jun 11 03:27:03 2015 +0000
Commit message:
initial commit

Changed in this revision

README.md Show annotated file Show diff for this revision Revisions of this file
configs/config-ccm-psk-tls1_2.h Show annotated file Show diff for this revision Revisions of this file
configs/config-mini-tls1_1.h Show annotated file Show diff for this revision Revisions of this file
configs/config-picocoin.h Show annotated file Show diff for this revision Revisions of this file
configs/config-psk-rc4-tls1_0.h Show annotated file Show diff for this revision Revisions of this file
configs/config-suite-b.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/aes.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/aesni.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/arc4.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/asn1.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/asn1write.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/base64.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/bignum.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/blowfish.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/bn_mul.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/camellia.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/ccm.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/certs.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/check_config.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/cipher.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/cipher_wrap.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/compat-1.2.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/config.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/ctr_drbg.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/debug.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/des.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/dhm.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/ecdh.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/ecdsa.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/ecp.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/entropy.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/entropy_poll.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/error.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/gcm.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/havege.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/hmac_drbg.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/md.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/md2.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/md4.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/md5.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/md_wrap.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/memory.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/memory_buffer_alloc.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/net.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/oid.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/openssl.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/padlock.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/pbkdf2.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/pem.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/pk.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/pk_wrap.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/pkcs11.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/pkcs12.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/pkcs5.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/platform.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/ripemd160.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/rsa.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/sha1.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/sha256.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/sha512.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/ssl.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/ssl_cache.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/ssl_ciphersuites.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/threading.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/timing.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/version.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/x509.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/x509_crl.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/x509_crt.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/x509_csr.h Show annotated file Show diff for this revision Revisions of this file
include/polarssl/xtea.h Show annotated file Show diff for this revision Revisions of this file
polarssl/aes.c Show annotated file Show diff for this revision Revisions of this file
polarssl/aesni.c Show annotated file Show diff for this revision Revisions of this file
polarssl/arc4.c Show annotated file Show diff for this revision Revisions of this file
polarssl/asn1parse.c Show annotated file Show diff for this revision Revisions of this file
polarssl/asn1write.c Show annotated file Show diff for this revision Revisions of this file
polarssl/base64.c Show annotated file Show diff for this revision Revisions of this file
polarssl/bignum.c Show annotated file Show diff for this revision Revisions of this file
polarssl/blowfish.c Show annotated file Show diff for this revision Revisions of this file
polarssl/camellia.c Show annotated file Show diff for this revision Revisions of this file
polarssl/ccm.c Show annotated file Show diff for this revision Revisions of this file
polarssl/certs.c Show annotated file Show diff for this revision Revisions of this file
polarssl/cipher.c Show annotated file Show diff for this revision Revisions of this file
polarssl/cipher_wrap.c Show annotated file Show diff for this revision Revisions of this file
polarssl/ctr_drbg.c Show annotated file Show diff for this revision Revisions of this file
polarssl/debug.c Show annotated file Show diff for this revision Revisions of this file
polarssl/des.c Show annotated file Show diff for this revision Revisions of this file
polarssl/dhm.c Show annotated file Show diff for this revision Revisions of this file
polarssl/ecdh.c Show annotated file Show diff for this revision Revisions of this file
polarssl/ecdsa.c Show annotated file Show diff for this revision Revisions of this file
polarssl/ecp.c Show annotated file Show diff for this revision Revisions of this file
polarssl/ecp_curves.c Show annotated file Show diff for this revision Revisions of this file
polarssl/entropy.c Show annotated file Show diff for this revision Revisions of this file
polarssl/entropy_poll.c Show annotated file Show diff for this revision Revisions of this file
polarssl/error.c Show annotated file Show diff for this revision Revisions of this file
polarssl/gcm.c Show annotated file Show diff for this revision Revisions of this file
polarssl/havege.c Show annotated file Show diff for this revision Revisions of this file
polarssl/hmac_drbg.c Show annotated file Show diff for this revision Revisions of this file
polarssl/md.c Show annotated file Show diff for this revision Revisions of this file
polarssl/md2.c Show annotated file Show diff for this revision Revisions of this file
polarssl/md4.c Show annotated file Show diff for this revision Revisions of this file
polarssl/md5.c Show annotated file Show diff for this revision Revisions of this file
polarssl/md_wrap.c Show annotated file Show diff for this revision Revisions of this file
polarssl/memory_buffer_alloc.c Show annotated file Show diff for this revision Revisions of this file
polarssl/net.c Show annotated file Show diff for this revision Revisions of this file
polarssl/oid.c Show annotated file Show diff for this revision Revisions of this file
polarssl/padlock.c Show annotated file Show diff for this revision Revisions of this file
polarssl/pbkdf2.c Show annotated file Show diff for this revision Revisions of this file
polarssl/pem.c Show annotated file Show diff for this revision Revisions of this file
polarssl/pk.c Show annotated file Show diff for this revision Revisions of this file
polarssl/pk_wrap.c Show annotated file Show diff for this revision Revisions of this file
polarssl/pkcs11.c Show annotated file Show diff for this revision Revisions of this file
polarssl/pkcs12.c Show annotated file Show diff for this revision Revisions of this file
polarssl/pkcs5.c Show annotated file Show diff for this revision Revisions of this file
polarssl/pkparse.c Show annotated file Show diff for this revision Revisions of this file
polarssl/pkwrite.c Show annotated file Show diff for this revision Revisions of this file
polarssl/platform.c Show annotated file Show diff for this revision Revisions of this file
polarssl/ripemd160.c Show annotated file Show diff for this revision Revisions of this file
polarssl/rsa.c Show annotated file Show diff for this revision Revisions of this file
polarssl/sha1.c Show annotated file Show diff for this revision Revisions of this file
polarssl/sha256.c Show annotated file Show diff for this revision Revisions of this file
polarssl/sha512.c Show annotated file Show diff for this revision Revisions of this file
polarssl/ssl_cache.c Show annotated file Show diff for this revision Revisions of this file
polarssl/ssl_ciphersuites.c Show annotated file Show diff for this revision Revisions of this file
polarssl/ssl_cli.c Show annotated file Show diff for this revision Revisions of this file
polarssl/ssl_srv.c Show annotated file Show diff for this revision Revisions of this file
polarssl/ssl_tls.c Show annotated file Show diff for this revision Revisions of this file
polarssl/threading.c Show annotated file Show diff for this revision Revisions of this file
polarssl/timing.c Show annotated file Show diff for this revision Revisions of this file
polarssl/version.c Show annotated file Show diff for this revision Revisions of this file
polarssl/version_features.c Show annotated file Show diff for this revision Revisions of this file
polarssl/x509.c Show annotated file Show diff for this revision Revisions of this file
polarssl/x509_create.c Show annotated file Show diff for this revision Revisions of this file
polarssl/x509_crl.c Show annotated file Show diff for this revision Revisions of this file
polarssl/x509_crt.c Show annotated file Show diff for this revision Revisions of this file
polarssl/x509_csr.c Show annotated file Show diff for this revision Revisions of this file
polarssl/x509write_crt.c Show annotated file Show diff for this revision Revisions of this file
polarssl/x509write_csr.c Show annotated file Show diff for this revision Revisions of this file
polarssl/xtea.c Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README.md	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,1 @@
+June 5, 2015: mbed TLS library v1.3.11.gpl
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/configs/config-ccm-psk-tls1_2.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,68 @@
+/*
+ * Minimal configuration for TLS 1.2 with PSK and AES-CCM ciphersuites
+ * Distinguishing features:
+ * - no bignum, no PK, no X509
+ * - fully modern and secure (provided the pre-shared keys have high entropy)
+ * - very low record overhead with CCM-8
+ * - optimized for low RAM usage
+ *
+ * See README.txt for usage instructions.
+ */
+#ifndef POLARSSL_CONFIG_H
+#define POLARSSL_CONFIG_H
+
+/* System support */
+#define POLARSSL_HAVE_IPV6 /* Now mandatory for NET_C */
+//#define POLARSSL_HAVE_TIME /* Optionally used in Hello messages */
+/* Other POLARSSL_HAVE_XXX flags irrelevant for this configuration */
+
+/* mbed TLS feature support */
+#define POLARSSL_KEY_EXCHANGE_PSK_ENABLED
+#define POLARSSL_SSL_PROTO_TLS1_2
+#define POLARSSL_SSL_DISABLE_RENEGOTIATION
+
+/* mbed TLS modules */
+#define POLARSSL_AES_C
+#define POLARSSL_CCM_C
+#define POLARSSL_CIPHER_C
+#define POLARSSL_CTR_DRBG_C
+#define POLARSSL_ENTROPY_C
+#define POLARSSL_MD_C
+#define POLARSSL_NET_C
+#define POLARSSL_SHA256_C
+#define POLARSSL_SSL_CLI_C
+#define POLARSSL_SSL_SRV_C
+#define POLARSSL_SSL_TLS_C
+
+/* Save RAM at the expense of ROM */
+#define POLARSSL_AES_ROM_TABLES
+
+/* Save some RAM by adjusting to your exact needs */
+#define POLARSSL_PSK_MAX_LEN    16 /* 128-bits keys are generally enough */
+
+/*
+ * You should adjust this to the exact number of sources you're using: default
+ * is the "platform_entropy_poll" source, but you may want to add other ones
+ * Minimum is 2 for the entropy test suite.
+ */
+#define ENTROPY_MAX_SOURCES 2
+
+/*
+ * Use only CCM_8 ciphersuites, and
+ * save ROM and a few bytes of RAM by specifying our own ciphersuite list
+ */
+#define SSL_CIPHERSUITES                        \
+        TLS_PSK_WITH_AES_256_CCM_8,             \
+        TLS_PSK_WITH_AES_128_CCM_8
+
+/*
+ * Save RAM at the expense of interoperability: do this only if you control
+ * both ends of the connection!  (See comments in "polarssl/ssl.h".)
+ * The optimal size here depends on the typical size of records.
+ */
+#define SSL_MAX_CONTENT_LEN             512
+
+#include "check_config.h"
+
+#endif /* POLARSSL_CONFIG_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/configs/config-mini-tls1_1.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,58 @@
+/*
+ * Minimal configuration for TLS 1.1 (RFC 4346), implementing only the
+ * required ciphersuite: TLS_RSA_WITH_3DES_EDE_CBC_SHA
+ *
+ * See README.txt for usage instructions.
+ */
+
+#ifndef POLARSSL_CONFIG_H
+#define POLARSSL_CONFIG_H
+
+/* System support */
+#define POLARSSL_HAVE_ASM
+#define POLARSSL_HAVE_TIME
+#define POLARSSL_HAVE_IPV6
+
+/* mbed TLS feature support */
+#define POLARSSL_CIPHER_MODE_CBC
+#define POLARSSL_PKCS1_V15
+#define POLARSSL_KEY_EXCHANGE_RSA_ENABLED
+#define POLARSSL_SSL_PROTO_TLS1_1
+#define POLARSSL_SSL_DISABLE_RENEGOTIATION
+
+/* mbed TLS modules */
+#define POLARSSL_AES_C
+#define POLARSSL_ASN1_PARSE_C
+#define POLARSSL_ASN1_WRITE_C
+#define POLARSSL_BIGNUM_C
+#define POLARSSL_CIPHER_C
+#define POLARSSL_CTR_DRBG_C
+#define POLARSSL_DES_C
+#define POLARSSL_ENTROPY_C
+#define POLARSSL_MD_C
+#define POLARSSL_MD5_C
+#define POLARSSL_NET_C
+#define POLARSSL_OID_C
+#define POLARSSL_PK_C
+#define POLARSSL_PK_PARSE_C
+#define POLARSSL_RSA_C
+#define POLARSSL_SHA1_C
+#define POLARSSL_SHA256_C
+#define POLARSSL_SSL_CLI_C
+#define POLARSSL_SSL_SRV_C
+#define POLARSSL_SSL_TLS_C
+#define POLARSSL_X509_CRT_PARSE_C
+#define POLARSSL_X509_USE_C
+
+/* For test certificates */
+#define POLARSSL_BASE64_C
+#define POLARSSL_CERTS_C
+#define POLARSSL_PEM_PARSE_C
+
+/* For testing with compat.sh */
+#define POLARSSL_FS_IO
+
+#include "polarssl/check_config.h"
+
+#endif /* POLARSSL_CONFIG_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/configs/config-picocoin.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,54 @@
+/*
+ * Reduced configuration used by Picocoin.
+ *
+ * See README.txt for usage instructions.
+ *
+ * Distinguishing features:
+ * - no SSL/TLS;
+ * - no X.509;
+ * - ECDSA/PK and some other chosen crypto bits.
+ */
+
+#ifndef POLARSSL_CONFIG_H
+#define POLARSSL_CONFIG_H
+
+/* System support */
+#define POLARSSL_HAVE_LONGLONG
+#define POLARSSL_HAVE_ASM
+#define POLARSSL_HAVE_TIME
+#define POLARSSL_HAVE_IPV6
+
+/* mbed TLS feature support */
+#define POLARSSL_CIPHER_MODE_CBC
+#define POLARSSL_CIPHER_PADDING_PKCS7
+#define POLARSSL_ECP_DP_SECP256K1_ENABLED
+#define POLARSSL_ECDSA_DETERMINISTIC
+#define POLARSSL_PK_PARSE_EC_EXTENDED
+#define POLARSSL_ERROR_STRERROR_DUMMY
+#define POLARSSL_FS_IO
+
+/* mbed TLS modules */
+#define POLARSSL_AESNI_C
+#define POLARSSL_AES_C
+#define POLARSSL_ASN1_PARSE_C
+#define POLARSSL_ASN1_WRITE_C
+#define POLARSSL_BASE64_C
+#define POLARSSL_BIGNUM_C
+#define POLARSSL_ECDSA_C
+#define POLARSSL_ECP_C
+#define POLARSSL_ENTROPY_C
+#define POLARSSL_HMAC_DRBG_C
+#define POLARSSL_MD_C
+#define POLARSSL_OID_C
+#define POLARSSL_PADLOCK_C
+#define POLARSSL_PK_C
+#define POLARSSL_PK_PARSE_C
+#define POLARSSL_PK_WRITE_C
+#define POLARSSL_RIPEMD160_C
+#define POLARSSL_SHA1_C
+#define POLARSSL_SHA256_C
+
+#include "check_config.h"
+
+#endif /* POLARSSL_CONFIG_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/configs/config-psk-rc4-tls1_0.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,42 @@
+/*
+ * Custom compact configuration for TLS 1.0 with PSK and RC4
+ * Distinguishing features: no bignum, no PK, no X509.
+ *
+ * WARNING: RC4 is in the process of being deprecated!
+ * This configuration is kept for testing purposes only, DO NOT USE it!
+ * For a safe and lean PSK-based configuration, see config-ccm-psk-tls1_2.h
+ *
+ * See README.txt for usage instructions.
+ */
+#ifndef POLARSSL_CONFIG_H
+#define POLARSSL_CONFIG_H
+
+/* System support */
+#define POLARSSL_HAVE_IPV6 /* Now mandatory for NET_C */
+//#define POLARSSL_HAVE_TIME /* Optionnaly used in Hello messages */
+/* Other POLARSSL_HAVE_XXX flags irrelevant for this configuration */
+
+/* mbed TLS feature support */
+#define POLARSSL_KEY_EXCHANGE_PSK_ENABLED
+#define POLARSSL_SSL_PROTO_TLS1
+#define POLARSSL_SSL_DISABLE_RENEGOTIATION
+
+/* mbed TLS modules */
+#define POLARSSL_AES_C
+#define POLARSSL_ARC4_C
+#define POLARSSL_CIPHER_C
+#define POLARSSL_CTR_DRBG_C
+#define POLARSSL_ENTROPY_C
+#define POLARSSL_MD_C
+#define POLARSSL_MD5_C
+#define POLARSSL_NET_C
+#define POLARSSL_SHA1_C
+#define POLARSSL_SHA256_C
+#define POLARSSL_SSL_CLI_C
+#define POLARSSL_SSL_SRV_C
+#define POLARSSL_SSL_TLS_C
+
+#include "polarssl/check_config.h"
+
+#endif /* POLARSSL_CONFIG_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/configs/config-suite-b.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,97 @@
+/*
+ * Minimal configuration for TLS NSA Suite B Profile (RFC 6460)
+ *
+ * Distinguishing features:
+ * - no RSA or classic DH, fully based on ECC
+ * - optimized for low RAM usage
+ *
+ * Possible improvements:
+ * - if 128-bit security is enough, disable secp384r1 and SHA-512
+ * - use embedded certs in DER format and disable PEM_PARSE_C and BASE64_C
+ *
+ * See README.txt for usage instructions.
+ */
+
+#ifndef POLARSSL_CONFIG_H
+#define POLARSSL_CONFIG_H
+
+/* System support */
+#define POLARSSL_HAVE_ASM
+#define POLARSSL_HAVE_TIME
+#define POLARSSL_HAVE_IPV6
+
+/* mbed TLS feature support */
+#define POLARSSL_ECP_DP_SECP256R1_ENABLED
+#define POLARSSL_ECP_DP_SECP384R1_ENABLED
+#define POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+#define POLARSSL_SSL_PROTO_TLS1_2
+#define POLARSSL_SSL_DISABLE_RENEGOTIATION
+
+/* mbed TLS modules */
+#define POLARSSL_AES_C
+#define POLARSSL_ASN1_PARSE_C
+#define POLARSSL_ASN1_WRITE_C
+#define POLARSSL_BIGNUM_C
+#define POLARSSL_CIPHER_C
+#define POLARSSL_CTR_DRBG_C
+#define POLARSSL_ECDH_C
+#define POLARSSL_ECDSA_C
+#define POLARSSL_ECP_C
+#define POLARSSL_ENTROPY_C
+#define POLARSSL_GCM_C
+#define POLARSSL_MD_C
+#define POLARSSL_NET_C
+#define POLARSSL_OID_C
+#define POLARSSL_PK_C
+#define POLARSSL_PK_PARSE_C
+#define POLARSSL_SHA256_C
+#define POLARSSL_SHA512_C
+#define POLARSSL_SSL_CLI_C
+#define POLARSSL_SSL_SRV_C
+#define POLARSSL_SSL_TLS_C
+#define POLARSSL_X509_CRT_PARSE_C
+#define POLARSSL_X509_USE_C
+
+/* For test certificates */
+#define POLARSSL_BASE64_C
+#define POLARSSL_CERTS_C
+#define POLARSSL_PEM_PARSE_C
+
+/* Save RAM at the expense of ROM */
+#define POLARSSL_AES_ROM_TABLES
+
+/* Save RAM by adjusting to our exact needs */
+#define POLARSSL_ECP_MAX_BITS   384
+#define POLARSSL_MPI_MAX_SIZE    48 // 384 bits is 48 bytes
+
+/* Save RAM at the expense of speed, see ecp.h */
+#define POLARSSL_ECP_WINDOW_SIZE        2
+#define POLARSSL_ECP_FIXED_POINT_OPTIM  0
+
+/* Significant speed benefit at the expense of some ROM */
+#define POLARSSL_ECP_NIST_OPTIM
+
+/*
+ * You should adjust this to the exact number of sources you're using: default
+ * is the "platform_entropy_poll" source, but you may want to add other ones.
+ * Minimum is 2 for the entropy test suite.
+ */
+#define ENTROPY_MAX_SOURCES 2
+
+/* Save ROM and a few bytes of RAM by specifying our own ciphersuite list */
+#define SSL_CIPHERSUITES                        \
+    TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,    \
+    TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+
+/*
+ * Save RAM at the expense of interoperability: do this only if you control
+ * both ends of the connection!  (See coments in "polarssl/ssl.h".)
+ * The minimum size here depends on the certificate chain used as well as the
+ * typical size of records.
+ */
+#define SSL_MAX_CONTENT_LEN             1024
+
+#include "polarssl/check_config.h"
+
+#endif /* POLARSSL_CONFIG_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/polarssl/aes.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,279 @@
+/**
+ * \file aes.h
+ *
+ * \brief AES block cipher
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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 <stddef.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          Initialize AES context
+ *
+ * \param ctx      AES context to be initialized
+ */
+void aes_init( aes_context *ctx );
+
+/**
+ * \brief          Clear AES context
+ *
+ * \param ctx      AES context to be cleared
+ */
+void aes_free( aes_context *ctx );
+
+/**
+ * \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)
+ *
+ * \note           Upon exit, the content of the IV is updated so that you can
+ *                 call the function same function again on the following
+ *                 block(s) of data and get the same result as if it was
+ *                 encrypted in one call. This allows a "streaming" usage.
+ *                 If on the other hand you need to retain the contents of the
+ *                 IV, you should either save it manually or use the cipher
+ *                 module instead.
+ *
+ * \param ctx      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.
+ *
+ * \note           Upon exit, the content of the IV is updated so that you can
+ *                 call the function same function again on the following
+ *                 block(s) of data and get the same result as if it was
+ *                 encrypted in one call. This allows a "streaming" usage.
+ *                 If on the other hand you need to retain the contents of the
+ *                 IV, you should either save it manually or use the cipher
+ *                 module instead.
+ *
+ * \param ctx      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.
+ *
+ * \note           Upon exit, the content of the IV is updated so that you can
+ *                 call the function same function again on the following
+ *                 block(s) of data and get the same result as if it was
+ *                 encrypted in one call. This allows a "streaming" usage.
+ *                 If on the other hand you need to retain the contents of the
+ *                 IV, you should either save it manually or use the cipher
+ *                 module instead.
+ *
+ * \param ctx      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/include/polarssl/aesni.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,113 @@
+/**
+ * \file aesni.h
+ *
+ * \brief AES-NI for hardware AES acceleration on some Intel processors
+ *
+ *  Copyright (C) 2013, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \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 );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* POLARSSL_HAVE_X86_64 */
+
+#endif /* POLARSSL_AESNI_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/polarssl/arc4.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,115 @@
+/**
+ * \file arc4.h
+ *
+ * \brief The ARCFOUR stream cipher
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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 <stddef.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          Initialize ARC4 context
+ *
+ * \param ctx      ARC4 context to be initialized
+ */
+void arc4_init( arc4_context *ctx );
+
+/**
+ * \brief          Clear ARC4 context
+ *
+ * \param ctx      ARC4 context to be cleared
+ */
+void arc4_free( arc4_context *ctx );
+
+/**
+ * \brief          ARC4 key schedule
+ *
+ * \param ctx      ARC4 context to be setup
+ * \param key      the secret key
+ * \param keylen   length of the key, in bytes
+ */
+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/include/polarssl/asn1.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,346 @@
+/**
+ * \file asn1.h
+ *
+ * \brief Generic ASN.1 parsing
+ *
+ *  Copyright (C) 2006-2013, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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
+
+#include <stddef.h>
+
+#if defined(POLARSSL_BIGNUM_C)
+#include "bignum.h"
+#endif
+
+/**
+ * \addtogroup asn1_module
+ * \{
+ */
+
+/**
+ * \name ASN1 Error codes
+ * These error codes are OR'ed to X509 error codes for
+ * higher error granularity.
+ * ASN1 is a standard to specify data structures.
+ * \{
+ */
+#define 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 an asn1_buf structure to a reference OID.
+ *
+ * Only works for 'defined' oid_str values (OID_HMAC_SHA1), you cannot use a
+ * 'unsigned char *oid' here!
+ *
+ * Warning: returns true when the OIDs are equal (unlike memcmp)!
+ */
+#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. */
+    unsigned char next_merged;      /**< Merge next item into the current one? */
+}
+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/include/polarssl/asn1write.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,241 @@
+/**
+ * \file asn1write.h
+ *
+ * \brief ASN.1 buffer writing functionality
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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/include/polarssl/base64.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,85 @@
+/**
+ * \file base64.h
+ *
+ * \brief RFC 1521 base64 encoding/decoding
+ *
+ *  Copyright (C) 2006-2013, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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 <stddef.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/include/polarssl/bignum.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,755 @@
+/**
+ * \file bignum.h
+ *
+ * \brief  Multi-precision integer library
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+
+#if defined(POLARSSL_FS_IO)
+#include <stdio.h>
+#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_MPI_WINDOW_SIZE)
+/*
+ * 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. */
+#endif /* !POLARSSL_MPI_WINDOW_SIZE */
+
+#if !defined(POLARSSL_MPI_MAX_SIZE)
+/*
+ * Maximum size of MPIs allowed in bits and bytes for user-MPIs.
+ * ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits )
+ *
+ * Note: Calculations can results temporarily in larger MPIs. So the number
+ * of limbs required (POLARSSL_MPI_MAX_LIMBS) is higher.
+ */
+#define POLARSSL_MPI_MAX_SIZE                              1024     /**< Maximum number of bytes for usable MPIs. */
+#endif /* !POLARSSL_MPI_MAX_SIZE */
+
+#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 POLARSSL_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__) || defined(__mips64) ) )
+       #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 /* !POLARSSL_HAVE_INT32 && __GNUC__ && 64-bit platform */
+  #endif /* !POLARSSL_HAVE_INT32 && _MSC_VER && _M_AMD64 */
+#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 (make internal references valid)
+ *                  This just makes it ready to be set or freed,
+ *                  but does not define a value for the MPI.
+ *
+ * \param X         One MPI to initialize.
+ */
+void 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.
+ *                 Always fills the whole buffer, which will start with zeros
+ *                 if the number is smaller.
+ *
+ * \param X        Source MPI
+ * \param buf      Output buffer
+ * \param buflen   Output buffer size
+ *
+ * \return         0 if successful,
+ *                 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/include/polarssl/blowfish.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,211 @@
+/**
+ * \file blowfish.h
+ *
+ * \brief Blowfish block cipher
+ *
+ *  Copyright (C) 2012-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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 <stddef.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          Initialize Blowfish context
+ *
+ * \param ctx      Blowfish context to be initialized
+ */
+void blowfish_init( blowfish_context *ctx );
+
+/**
+ * \brief          Clear Blowfish context
+ *
+ * \param ctx      Blowfish context to be cleared
+ */
+void blowfish_free( blowfish_context *ctx );
+
+/**
+ * \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)
+ *
+ * \note           Upon exit, the content of the IV is updated so that you can
+ *                 call the function same function again on the following
+ *                 block(s) of data and get the same result as if it was
+ *                 encrypted in one call. This allows a "streaming" usage.
+ *                 If on the other hand you need to retain the contents of the
+ *                 IV, you should either save it manually or use the cipher
+ *                 module instead.
+ *
+ * \param ctx      Blowfish context
+ * \param mode     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.
+ *
+ * \note           Upon exit, the content of the IV is updated so that you can
+ *                 call the function same function again on the following
+ *                 block(s) of data and get the same result as if it was
+ *                 encrypted in one call. This allows a "streaming" usage.
+ *                 If on the other hand you need to retain the contents of the
+ *                 IV, you should either save it manually or use the cipher
+ *                 module instead.
+ *
+ * \param ctx      Blowfish context
+ * \param mode     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/include/polarssl/bn_mul.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,871 @@
+/**
+ * \file bn_mul.h
+ *
+ * \brief  Multi-precision integer library
+ *
+ *  Copyright (C) 2006-2010, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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           \n\t"   \
+        "movl   %5, %%esi           \n\t"   \
+        "movl   %6, %%edi           \n\t"   \
+        "movl   %7, %%ecx           \n\t"   \
+        "movl   %8, %%ebx           \n\t"
+
+#define MULADDC_CORE                        \
+        "lodsl                      \n\t"   \
+        "mull   %%ebx               \n\t"   \
+        "addl   %%ecx,   %%eax      \n\t"   \
+        "adcl   $0,      %%edx      \n\t"   \
+        "addl   (%%edi), %%eax      \n\t"   \
+        "adcl   $0,      %%edx      \n\t"   \
+        "movl   %%edx,   %%ecx      \n\t"   \
+        "stosl                      \n\t"
+
+#if defined(POLARSSL_HAVE_SSE2)
+
+#define MULADDC_HUIT                            \
+        "movd     %%ecx,     %%mm1      \n\t"   \
+        "movd     %%ebx,     %%mm0      \n\t"   \
+        "movd     (%%edi),   %%mm3      \n\t"   \
+        "paddq    %%mm3,     %%mm1      \n\t"   \
+        "movd     (%%esi),   %%mm2      \n\t"   \
+        "pmuludq  %%mm0,     %%mm2      \n\t"   \
+        "movd     4(%%esi),  %%mm4      \n\t"   \
+        "pmuludq  %%mm0,     %%mm4      \n\t"   \
+        "movd     8(%%esi),  %%mm6      \n\t"   \
+        "pmuludq  %%mm0,     %%mm6      \n\t"   \
+        "movd     12(%%esi), %%mm7      \n\t"   \
+        "pmuludq  %%mm0,     %%mm7      \n\t"   \
+        "paddq    %%mm2,     %%mm1      \n\t"   \
+        "movd     4(%%edi),  %%mm3      \n\t"   \
+        "paddq    %%mm4,     %%mm3      \n\t"   \
+        "movd     8(%%edi),  %%mm5      \n\t"   \
+        "paddq    %%mm6,     %%mm5      \n\t"   \
+        "movd     12(%%edi), %%mm4      \n\t"   \
+        "paddq    %%mm4,     %%mm7      \n\t"   \
+        "movd     %%mm1,     (%%edi)    \n\t"   \
+        "movd     16(%%esi), %%mm2      \n\t"   \
+        "pmuludq  %%mm0,     %%mm2      \n\t"   \
+        "psrlq    $32,       %%mm1      \n\t"   \
+        "movd     20(%%esi), %%mm4      \n\t"   \
+        "pmuludq  %%mm0,     %%mm4      \n\t"   \
+        "paddq    %%mm3,     %%mm1      \n\t"   \
+        "movd     24(%%esi), %%mm6      \n\t"   \
+        "pmuludq  %%mm0,     %%mm6      \n\t"   \
+        "movd     %%mm1,     4(%%edi)   \n\t"   \
+        "psrlq    $32,       %%mm1      \n\t"   \
+        "movd     28(%%esi), %%mm3      \n\t"   \
+        "pmuludq  %%mm0,     %%mm3      \n\t"   \
+        "paddq    %%mm5,     %%mm1      \n\t"   \
+        "movd     16(%%edi), %%mm5      \n\t"   \
+        "paddq    %%mm5,     %%mm2      \n\t"   \
+        "movd     %%mm1,     8(%%edi)   \n\t"   \
+        "psrlq    $32,       %%mm1      \n\t"   \
+        "paddq    %%mm7,     %%mm1      \n\t"   \
+        "movd     20(%%edi), %%mm5      \n\t"   \
+        "paddq    %%mm5,     %%mm4      \n\t"   \
+        "movd     %%mm1,     12(%%edi)  \n\t"   \
+        "psrlq    $32,       %%mm1      \n\t"   \
+        "paddq    %%mm2,     %%mm1      \n\t"   \
+        "movd     24(%%edi), %%mm5      \n\t"   \
+        "paddq    %%mm5,     %%mm6      \n\t"   \
+        "movd     %%mm1,     16(%%edi)  \n\t"   \
+        "psrlq    $32,       %%mm1      \n\t"   \
+        "paddq    %%mm4,     %%mm1      \n\t"   \
+        "movd     28(%%edi), %%mm5      \n\t"   \
+        "paddq    %%mm5,     %%mm3      \n\t"   \
+        "movd     %%mm1,     20(%%edi)  \n\t"   \
+        "psrlq    $32,       %%mm1      \n\t"   \
+        "paddq    %%mm6,     %%mm1      \n\t"   \
+        "movd     %%mm1,     24(%%edi)  \n\t"   \
+        "psrlq    $32,       %%mm1      \n\t"   \
+        "paddq    %%mm3,     %%mm1      \n\t"   \
+        "movd     %%mm1,     28(%%edi)  \n\t"   \
+        "addl     $32,       %%edi      \n\t"   \
+        "addl     $32,       %%esi      \n\t"   \
+        "psrlq    $32,       %%mm1      \n\t"   \
+        "movd     %%mm1,     %%ecx      \n\t"
+
+#define MULADDC_STOP                    \
+        "emms                   \n\t"   \
+        "movl   %4, %%ebx       \n\t"   \
+        "movl   %%ecx, %1       \n\t"   \
+        "movl   %%edi, %2       \n\t"   \
+        "movl   %%esi, %3       \n\t"   \
+        : "=m" (t), "=m" (c), "=m" (d), "=m" (s)        \
+        : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b)   \
+        : "eax", "ecx", "edx", "esi", "edi"             \
+    );
+
+#else
+
+#define MULADDC_STOP                    \
+        "movl   %4, %%ebx       \n\t"   \
+        "movl   %%ecx, %1       \n\t"   \
+        "movl   %%edi, %2       \n\t"   \
+        "movl   %%esi, %3       \n\t"   \
+        : "=m" (t), "=m" (c), "=m" (d), "=m" (s)        \
+        : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b)   \
+        : "eax", "ecx", "edx", "esi", "edi"             \
+    );
+#endif /* SSE2 */
+#endif /* i386 */
+
+#if defined(__amd64__) || defined (__x86_64__)
+
+#define MULADDC_INIT                        \
+    asm(                                    \
+        "movq   %3, %%rsi           \n\t"   \
+        "movq   %4, %%rdi           \n\t"   \
+        "movq   %5, %%rcx           \n\t"   \
+        "movq   %6, %%rbx           \n\t"   \
+        "xorq   %%r8, %%r8          \n\t"
+
+#define MULADDC_CORE                        \
+        "movq   (%%rsi), %%rax      \n\t"   \
+        "mulq   %%rbx               \n\t"   \
+        "addq   $8,      %%rsi      \n\t"   \
+        "addq   %%rcx,   %%rax      \n\t"   \
+        "movq   %%r8,    %%rcx      \n\t"   \
+        "adcq   $0,      %%rdx      \n\t"   \
+        "nop                        \n\t"   \
+        "addq   %%rax,   (%%rdi)    \n\t"   \
+        "adcq   %%rdx,   %%rcx      \n\t"   \
+        "addq   $8,      %%rdi      \n\t"
+
+#define MULADDC_STOP                        \
+        "movq   %%rcx, %0           \n\t"   \
+        "movq   %%rdi, %1           \n\t"   \
+        "movq   %%rsi, %2           \n\t"   \
+        : "=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        \n\t"   \
+        "movl   %4, %%a3        \n\t"   \
+        "movl   %5, %%d3        \n\t"   \
+        "movl   %6, %%d2        \n\t"   \
+        "moveq  #0, %%d0        \n\t"
+
+#define MULADDC_CORE                    \
+        "movel  %%a2@+, %%d1    \n\t"   \
+        "mulul  %%d2, %%d4:%%d1 \n\t"   \
+        "addl   %%d3, %%d1      \n\t"   \
+        "addxl  %%d0, %%d4      \n\t"   \
+        "moveq  #0,   %%d3      \n\t"   \
+        "addl   %%d1, %%a3@+    \n\t"   \
+        "addxl  %%d4, %%d3      \n\t"
+
+#define MULADDC_STOP                    \
+        "movl   %%d3, %0        \n\t"   \
+        "movl   %%a3, %1        \n\t"   \
+        "movl   %%a2, %2        \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)              \
+        : "m" (s), "m" (d), "m" (c), "m" (b)        \
+        : "d0", "d1", "d2", "d3", "d4", "a2", "a3"  \
+    );
+
+#define MULADDC_HUIT                        \
+        "movel  %%a2@+,  %%d1       \n\t"   \
+        "mulul  %%d2,    %%d4:%%d1  \n\t"   \
+        "addxl  %%d3,    %%d1       \n\t"   \
+        "addxl  %%d0,    %%d4       \n\t"   \
+        "addl   %%d1,    %%a3@+     \n\t"   \
+        "movel  %%a2@+,  %%d1       \n\t"   \
+        "mulul  %%d2,    %%d3:%%d1  \n\t"   \
+        "addxl  %%d4,    %%d1       \n\t"   \
+        "addxl  %%d0,    %%d3       \n\t"   \
+        "addl   %%d1,    %%a3@+     \n\t"   \
+        "movel  %%a2@+,  %%d1       \n\t"   \
+        "mulul  %%d2,    %%d4:%%d1  \n\t"   \
+        "addxl  %%d3,    %%d1       \n\t"   \
+        "addxl  %%d0,    %%d4       \n\t"   \
+        "addl   %%d1,    %%a3@+     \n\t"   \
+        "movel  %%a2@+,  %%d1       \n\t"   \
+        "mulul  %%d2,    %%d3:%%d1  \n\t"   \
+        "addxl  %%d4,    %%d1       \n\t"   \
+        "addxl  %%d0,    %%d3       \n\t"   \
+        "addl   %%d1,    %%a3@+     \n\t"   \
+        "movel  %%a2@+,  %%d1       \n\t"   \
+        "mulul  %%d2,    %%d4:%%d1  \n\t"   \
+        "addxl  %%d3,    %%d1       \n\t"   \
+        "addxl  %%d0,    %%d4       \n\t"   \
+        "addl   %%d1,    %%a3@+     \n\t"   \
+        "movel  %%a2@+,  %%d1       \n\t"   \
+        "mulul  %%d2,    %%d3:%%d1  \n\t"   \
+        "addxl  %%d4,    %%d1       \n\t"   \
+        "addxl  %%d0,    %%d3       \n\t"   \
+        "addl   %%d1,    %%a3@+     \n\t"   \
+        "movel  %%a2@+,  %%d1       \n\t"   \
+        "mulul  %%d2,    %%d4:%%d1  \n\t"   \
+        "addxl  %%d3,    %%d1       \n\t"   \
+        "addxl  %%d0,    %%d4       \n\t"   \
+        "addl   %%d1,    %%a3@+     \n\t"   \
+        "movel  %%a2@+,  %%d1       \n\t"   \
+        "mulul  %%d2,    %%d3:%%d1  \n\t"   \
+        "addxl  %%d4,    %%d1       \n\t"   \
+        "addxl  %%d0,    %%d3       \n\t"   \
+        "addl   %%d1,    %%a3@+     \n\t"   \
+        "addxl  %%d0,    %%d3       \n\t"
+
+#endif /* MC68000 */
+
+#if defined(__powerpc64__) || defined(__ppc64__)
+
+#if defined(__MACH__) && defined(__APPLE__)
+
+#define MULADDC_INIT                        \
+    asm(                                    \
+        "ld     r3, %3              \n\t"   \
+        "ld     r4, %4              \n\t"   \
+        "ld     r5, %5              \n\t"   \
+        "ld     r6, %6              \n\t"   \
+        "addi   r3, r3, -8          \n\t"   \
+        "addi   r4, r4, -8          \n\t"   \
+        "addic  r5, r5,  0          \n\t"
+
+#define MULADDC_CORE                        \
+        "ldu    r7, 8(r3)           \n\t"   \
+        "mulld  r8, r7, r6          \n\t"   \
+        "mulhdu r9, r7, r6          \n\t"   \
+        "adde   r8, r8, r5          \n\t"   \
+        "ld     r7, 8(r4)           \n\t"   \
+        "addze  r5, r9              \n\t"   \
+        "addc   r8, r8, r7          \n\t"   \
+        "stdu   r8, 8(r4)           \n\t"
+
+#define MULADDC_STOP                        \
+        "addze  r5, r5              \n\t"   \
+        "addi   r4, r4, 8           \n\t"   \
+        "addi   r3, r3, 8           \n\t"   \
+        "std    r5, %0              \n\t"   \
+        "std    r4, %1              \n\t"   \
+        "std    r3, %2              \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)              \
+        : "m" (s), "m" (d), "m" (c), "m" (b)        \
+        : "r3", "r4", "r5", "r6", "r7", "r8", "r9"  \
+    );
+
+
+#else /* __MACH__ && __APPLE__ */
+
+#define MULADDC_INIT                        \
+    asm(                                    \
+        "ld     %%r3, %3            \n\t"   \
+        "ld     %%r4, %4            \n\t"   \
+        "ld     %%r5, %5            \n\t"   \
+        "ld     %%r6, %6            \n\t"   \
+        "addi   %%r3, %%r3, -8      \n\t"   \
+        "addi   %%r4, %%r4, -8      \n\t"   \
+        "addic  %%r5, %%r5,  0      \n\t"
+
+#define MULADDC_CORE                        \
+        "ldu    %%r7, 8(%%r3)       \n\t"   \
+        "mulld  %%r8, %%r7, %%r6    \n\t"   \
+        "mulhdu %%r9, %%r7, %%r6    \n\t"   \
+        "adde   %%r8, %%r8, %%r5    \n\t"   \
+        "ld     %%r7, 8(%%r4)       \n\t"   \
+        "addze  %%r5, %%r9          \n\t"   \
+        "addc   %%r8, %%r8, %%r7    \n\t"   \
+        "stdu   %%r8, 8(%%r4)       \n\t"
+
+#define MULADDC_STOP                        \
+        "addze  %%r5, %%r5          \n\t"   \
+        "addi   %%r4, %%r4, 8       \n\t"   \
+        "addi   %%r3, %%r3, 8       \n\t"   \
+        "std    %%r5, %0            \n\t"   \
+        "std    %%r4, %1            \n\t"   \
+        "std    %%r3, %2            \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)              \
+        : "m" (s), "m" (d), "m" (c), "m" (b)        \
+        : "r3", "r4", "r5", "r6", "r7", "r8", "r9"  \
+    );
+
+#endif /* __MACH__ && __APPLE__ */
+
+#elif defined(__powerpc__) || defined(__ppc__) /* end PPC64/begin PPC32  */
+
+#if defined(__MACH__) && defined(__APPLE__)
+
+#define MULADDC_INIT                    \
+    asm(                                \
+        "lwz    r3, %3          \n\t"   \
+        "lwz    r4, %4          \n\t"   \
+        "lwz    r5, %5          \n\t"   \
+        "lwz    r6, %6          \n\t"   \
+        "addi   r3, r3, -4      \n\t"   \
+        "addi   r4, r4, -4      \n\t"   \
+        "addic  r5, r5,  0      \n\t"
+
+#define MULADDC_CORE                    \
+        "lwzu   r7, 4(r3)       \n\t"   \
+        "mullw  r8, r7, r6      \n\t"   \
+        "mulhwu r9, r7, r6      \n\t"   \
+        "adde   r8, r8, r5      \n\t"   \
+        "lwz    r7, 4(r4)       \n\t"   \
+        "addze  r5, r9          \n\t"   \
+        "addc   r8, r8, r7      \n\t"   \
+        "stwu   r8, 4(r4)       \n\t"
+
+#define MULADDC_STOP                    \
+        "addze  r5, r5          \n\t"   \
+        "addi   r4, r4, 4       \n\t"   \
+        "addi   r3, r3, 4       \n\t"   \
+        "stw    r5, %0          \n\t"   \
+        "stw    r4, %1          \n\t"   \
+        "stw    r3, %2          \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)              \
+        : "m" (s), "m" (d), "m" (c), "m" (b)        \
+        : "r3", "r4", "r5", "r6", "r7", "r8", "r9"  \
+    );
+
+#else /* __MACH__ && __APPLE__ */
+
+#define MULADDC_INIT                        \
+    asm(                                    \
+        "lwz    %%r3, %3            \n\t"   \
+        "lwz    %%r4, %4            \n\t"   \
+        "lwz    %%r5, %5            \n\t"   \
+        "lwz    %%r6, %6            \n\t"   \
+        "addi   %%r3, %%r3, -4      \n\t"   \
+        "addi   %%r4, %%r4, -4      \n\t"   \
+        "addic  %%r5, %%r5,  0      \n\t"
+
+#define MULADDC_CORE                        \
+        "lwzu   %%r7, 4(%%r3)       \n\t"   \
+        "mullw  %%r8, %%r7, %%r6    \n\t"   \
+        "mulhwu %%r9, %%r7, %%r6    \n\t"   \
+        "adde   %%r8, %%r8, %%r5    \n\t"   \
+        "lwz    %%r7, 4(%%r4)       \n\t"   \
+        "addze  %%r5, %%r9          \n\t"   \
+        "addc   %%r8, %%r8, %%r7    \n\t"   \
+        "stwu   %%r8, 4(%%r4)       \n\t"
+
+#define MULADDC_STOP                        \
+        "addze  %%r5, %%r5          \n\t"   \
+        "addi   %%r4, %%r4, 4       \n\t"   \
+        "addi   %%r3, %%r3, 4       \n\t"   \
+        "stw    %%r5, %0            \n\t"   \
+        "stw    %%r4, %1            \n\t"   \
+        "stw    %%r3, %2            \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)              \
+        : "m" (s), "m" (d), "m" (c), "m" (b)        \
+        : "r3", "r4", "r5", "r6", "r7", "r8", "r9"  \
+    );
+
+#endif /* __MACH__ && __APPLE__ */
+
+#endif /* PPC32 */
+
+/*
+ * The Sparc64 assembly is reported to be broken.
+ * Disable it for now, until we're able to fix it.
+ */
+#if 0 && defined(__sparc__) && defined(__sparc64__)
+
+#define MULADDC_INIT                                    \
+    asm(                                                \
+                "ldx     %3, %%o0               \n\t"   \
+                "ldx     %4, %%o1               \n\t"   \
+                "ld      %5, %%o2               \n\t"   \
+                "ld      %6, %%o3               \n\t"
+
+#define MULADDC_CORE                                    \
+                "ld      [%%o0], %%o4           \n\t"   \
+                "inc     4, %%o0                \n\t"   \
+                "ld      [%%o1], %%o5           \n\t"   \
+                "umul    %%o3, %%o4, %%o4       \n\t"   \
+                "addcc   %%o4, %%o2, %%o4       \n\t"   \
+                "rd      %%y, %%g1              \n\t"   \
+                "addx    %%g1, 0, %%g1          \n\t"   \
+                "addcc   %%o4, %%o5, %%o4       \n\t"   \
+                "st      %%o4, [%%o1]           \n\t"   \
+                "addx    %%g1, 0, %%o2          \n\t"   \
+                "inc     4, %%o1                \n\t"
+
+        #define MULADDC_STOP                            \
+                "st      %%o2, %0               \n\t"   \
+                "stx     %%o1, %1               \n\t"   \
+                "stx     %%o0, %2               \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)          \
+        : "m" (s), "m" (d), "m" (c), "m" (b)    \
+        : "g1", "o0", "o1", "o2", "o3", "o4",   \
+          "o5"                                  \
+        );
+#endif /* SPARCv9 */
+
+#if defined(__sparc__) && !defined(__sparc64__)
+
+#define MULADDC_INIT                                    \
+    asm(                                                \
+                "ld      %3, %%o0               \n\t"   \
+                "ld      %4, %%o1               \n\t"   \
+                "ld      %5, %%o2               \n\t"   \
+                "ld      %6, %%o3               \n\t"
+
+#define MULADDC_CORE                                    \
+                "ld      [%%o0], %%o4           \n\t"   \
+                "inc     4, %%o0                \n\t"   \
+                "ld      [%%o1], %%o5           \n\t"   \
+                "umul    %%o3, %%o4, %%o4       \n\t"   \
+                "addcc   %%o4, %%o2, %%o4       \n\t"   \
+                "rd      %%y, %%g1              \n\t"   \
+                "addx    %%g1, 0, %%g1          \n\t"   \
+                "addcc   %%o4, %%o5, %%o4       \n\t"   \
+                "st      %%o4, [%%o1]           \n\t"   \
+                "addx    %%g1, 0, %%o2          \n\t"   \
+                "inc     4, %%o1                \n\t"
+
+#define MULADDC_STOP                                    \
+                "st      %%o2, %0               \n\t"   \
+                "st      %%o1, %1               \n\t"   \
+                "st      %%o0, %2               \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)          \
+        : "m" (s), "m" (d), "m" (c), "m" (b)    \
+        : "g1", "o0", "o1", "o2", "o3", "o4",   \
+          "o5"                                  \
+        );
+
+#endif /* SPARCv8 */
+
+#if defined(__microblaze__) || defined(microblaze)
+
+#define MULADDC_INIT                    \
+    asm(                                \
+        "lwi   r3,   %3         \n\t"   \
+        "lwi   r4,   %4         \n\t"   \
+        "lwi   r5,   %5         \n\t"   \
+        "lwi   r6,   %6         \n\t"   \
+        "andi  r7,   r6, 0xffff \n\t"   \
+        "bsrli r6,   r6, 16     \n\t"
+
+#define MULADDC_CORE                    \
+        "lhui  r8,   r3,   0    \n\t"   \
+        "addi  r3,   r3,   2    \n\t"   \
+        "lhui  r9,   r3,   0    \n\t"   \
+        "addi  r3,   r3,   2    \n\t"   \
+        "mul   r10,  r9,  r6    \n\t"   \
+        "mul   r11,  r8,  r7    \n\t"   \
+        "mul   r12,  r9,  r7    \n\t"   \
+        "mul   r13,  r8,  r6    \n\t"   \
+        "bsrli  r8, r10,  16    \n\t"   \
+        "bsrli  r9, r11,  16    \n\t"   \
+        "add   r13, r13,  r8    \n\t"   \
+        "add   r13, r13,  r9    \n\t"   \
+        "bslli r10, r10,  16    \n\t"   \
+        "bslli r11, r11,  16    \n\t"   \
+        "add   r12, r12, r10    \n\t"   \
+        "addc  r13, r13,  r0    \n\t"   \
+        "add   r12, r12, r11    \n\t"   \
+        "addc  r13, r13,  r0    \n\t"   \
+        "lwi   r10,  r4,   0    \n\t"   \
+        "add   r12, r12, r10    \n\t"   \
+        "addc  r13, r13,  r0    \n\t"   \
+        "add   r12, r12,  r5    \n\t"   \
+        "addc   r5, r13,  r0    \n\t"   \
+        "swi   r12,  r4,   0    \n\t"   \
+        "addi   r4,  r4,   4    \n\t"
+
+#define MULADDC_STOP                    \
+        "swi   r5,   %0         \n\t"   \
+        "swi   r4,   %1         \n\t"   \
+        "swi   r3,   %2         \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)              \
+        : "m" (s), "m" (d), "m" (c), "m" (b)        \
+        : "r3", "r4"  "r5", "r6", "r7", "r8",       \
+          "r9", "r10", "r11", "r12", "r13"          \
+    );
+
+#endif /* MicroBlaze */
+
+#if defined(__tricore__)
+
+#define MULADDC_INIT                            \
+    asm(                                        \
+        "ld.a   %%a2, %3                \n\t"   \
+        "ld.a   %%a3, %4                \n\t"   \
+        "ld.w   %%d4, %5                \n\t"   \
+        "ld.w   %%d1, %6                \n\t"   \
+        "xor    %%d5, %%d5              \n\t"
+
+#define MULADDC_CORE                            \
+        "ld.w   %%d0,   [%%a2+]         \n\t"   \
+        "madd.u %%e2, %%e4, %%d0, %%d1  \n\t"   \
+        "ld.w   %%d0,   [%%a3]          \n\t"   \
+        "addx   %%d2,    %%d2,  %%d0    \n\t"   \
+        "addc   %%d3,    %%d3,    0     \n\t"   \
+        "mov    %%d4,    %%d3           \n\t"   \
+        "st.w  [%%a3+],  %%d2           \n\t"
+
+#define MULADDC_STOP                            \
+        "st.w   %0, %%d4                \n\t"   \
+        "st.a   %1, %%a3                \n\t"   \
+        "st.a   %2, %%a2                \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)          \
+        : "m" (s), "m" (d), "m" (c), "m" (b)    \
+        : "d0", "d1", "e2", "d4", "a2", "a3"    \
+    );
+
+#endif /* TriCore */
+
+#if defined(__arm__)
+
+#if defined(__thumb__) && !defined(__thumb2__)
+
+#define MULADDC_INIT                                    \
+    asm(                                                \
+            "ldr    r0, %3                      \n\t"   \
+            "ldr    r1, %4                      \n\t"   \
+            "ldr    r2, %5                      \n\t"   \
+            "ldr    r3, %6                      \n\t"   \
+            "lsr    r7, r3, #16                 \n\t"   \
+            "mov    r9, r7                      \n\t"   \
+            "lsl    r7, r3, #16                 \n\t"   \
+            "lsr    r7, r7, #16                 \n\t"   \
+            "mov    r8, r7                      \n\t"
+
+#define MULADDC_CORE                                    \
+            "ldmia  r0!, {r6}                   \n\t"   \
+            "lsr    r7, r6, #16                 \n\t"   \
+            "lsl    r6, r6, #16                 \n\t"   \
+            "lsr    r6, r6, #16                 \n\t"   \
+            "mov    r4, r8                      \n\t"   \
+            "mul    r4, r6                      \n\t"   \
+            "mov    r3, r9                      \n\t"   \
+            "mul    r6, r3                      \n\t"   \
+            "mov    r5, r9                      \n\t"   \
+            "mul    r5, r7                      \n\t"   \
+            "mov    r3, r8                      \n\t"   \
+            "mul    r7, r3                      \n\t"   \
+            "lsr    r3, r6, #16                 \n\t"   \
+            "add    r5, r5, r3                  \n\t"   \
+            "lsr    r3, r7, #16                 \n\t"   \
+            "add    r5, r5, r3                  \n\t"   \
+            "add    r4, r4, r2                  \n\t"   \
+            "mov    r2, #0                      \n\t"   \
+            "adc    r5, r2                      \n\t"   \
+            "lsl    r3, r6, #16                 \n\t"   \
+            "add    r4, r4, r3                  \n\t"   \
+            "adc    r5, r2                      \n\t"   \
+            "lsl    r3, r7, #16                 \n\t"   \
+            "add    r4, r4, r3                  \n\t"   \
+            "adc    r5, r2                      \n\t"   \
+            "ldr    r3, [r1]                    \n\t"   \
+            "add    r4, r4, r3                  \n\t"   \
+            "adc    r2, r5                      \n\t"   \
+            "stmia  r1!, {r4}                   \n\t"
+
+#define MULADDC_STOP                                    \
+            "str    r2, %0                      \n\t"   \
+            "str    r1, %1                      \n\t"   \
+            "str    r0, %2                      \n\t"   \
+         : "=m" (c),  "=m" (d), "=m" (s)        \
+         : "m" (s), "m" (d), "m" (c), "m" (b)   \
+         : "r0", "r1", "r2", "r3", "r4", "r5",  \
+           "r6", "r7", "r8", "r9", "cc"         \
+         );
+
+#else
+
+#define MULADDC_INIT                                    \
+    asm(                                                \
+            "ldr    r0, %3                      \n\t"   \
+            "ldr    r1, %4                      \n\t"   \
+            "ldr    r2, %5                      \n\t"   \
+            "ldr    r3, %6                      \n\t"
+
+#define MULADDC_CORE                                    \
+            "ldr    r4, [r0], #4                \n\t"   \
+            "mov    r5, #0                      \n\t"   \
+            "ldr    r6, [r1]                    \n\t"   \
+            "umlal  r2, r5, r3, r4              \n\t"   \
+            "adds   r7, r6, r2                  \n\t"   \
+            "adc    r2, r5, #0                  \n\t"   \
+            "str    r7, [r1], #4                \n\t"
+
+#define MULADDC_STOP                                    \
+            "str    r2, %0                      \n\t"   \
+            "str    r1, %1                      \n\t"   \
+            "str    r0, %2                      \n\t"   \
+         : "=m" (c),  "=m" (d), "=m" (s)        \
+         : "m" (s), "m" (d), "m" (c), "m" (b)   \
+         : "r0", "r1", "r2", "r3", "r4", "r5",  \
+           "r6", "r7", "cc"                     \
+         );
+
+#endif /* Thumb */
+
+#endif /* ARMv3 */
+
+#if defined(__alpha__)
+
+#define MULADDC_INIT                    \
+    asm(                                \
+        "ldq    $1, %3          \n\t"   \
+        "ldq    $2, %4          \n\t"   \
+        "ldq    $3, %5          \n\t"   \
+        "ldq    $4, %6          \n\t"
+
+#define MULADDC_CORE                    \
+        "ldq    $6,  0($1)      \n\t"   \
+        "addq   $1,  8, $1      \n\t"   \
+        "mulq   $6, $4, $7      \n\t"   \
+        "umulh  $6, $4, $6      \n\t"   \
+        "addq   $7, $3, $7      \n\t"   \
+        "cmpult $7, $3, $3      \n\t"   \
+        "ldq    $5,  0($2)      \n\t"   \
+        "addq   $7, $5, $7      \n\t"   \
+        "cmpult $7, $5, $5      \n\t"   \
+        "stq    $7,  0($2)      \n\t"   \
+        "addq   $2,  8, $2      \n\t"   \
+        "addq   $6, $3, $3      \n\t"   \
+        "addq   $5, $3, $3      \n\t"
+
+#define MULADDC_STOP                                    \
+        "stq    $3, %0          \n\t"   \
+        "stq    $2, %1          \n\t"   \
+        "stq    $1, %2          \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)              \
+        : "m" (s), "m" (d), "m" (c), "m" (b)        \
+        : "$1", "$2", "$3", "$4", "$5", "$6", "$7"  \
+    );
+#endif /* Alpha */
+
+#if defined(__mips__) && !defined(__mips64)
+
+#define MULADDC_INIT                    \
+    asm(                                \
+        "lw     $10, %3         \n\t"   \
+        "lw     $11, %4         \n\t"   \
+        "lw     $12, %5         \n\t"   \
+        "lw     $13, %6         \n\t"
+
+#define MULADDC_CORE                    \
+        "lw     $14, 0($10)     \n\t"   \
+        "multu  $13, $14        \n\t"   \
+        "addi   $10, $10, 4     \n\t"   \
+        "mflo   $14             \n\t"   \
+        "mfhi   $9              \n\t"   \
+        "addu   $14, $12, $14   \n\t"   \
+        "lw     $15, 0($11)     \n\t"   \
+        "sltu   $12, $14, $12   \n\t"   \
+        "addu   $15, $14, $15   \n\t"   \
+        "sltu   $14, $15, $14   \n\t"   \
+        "addu   $12, $12, $9    \n\t"   \
+        "sw     $15, 0($11)     \n\t"   \
+        "addu   $12, $12, $14   \n\t"   \
+        "addi   $11, $11, 4     \n\t"
+
+#define MULADDC_STOP                    \
+        "sw     $12, %0         \n\t"   \
+        "sw     $11, %1         \n\t"   \
+        "sw     $10, %2         \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)                      \
+        : "m" (s), "m" (d), "m" (c), "m" (b)                \
+        : "$9", "$10", "$11", "$12", "$13", "$14", "$15"    \
+    );
+
+#endif /* MIPS */
+#endif /* GNUC */
+
+#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
+
+#define MULADDC_INIT                            \
+    __asm   mov     esi, s                      \
+    __asm   mov     edi, d                      \
+    __asm   mov     ecx, c                      \
+    __asm   mov     ebx, b
+
+#define MULADDC_CORE                            \
+    __asm   lodsd                               \
+    __asm   mul     ebx                         \
+    __asm   add     eax, ecx                    \
+    __asm   adc     edx, 0                      \
+    __asm   add     eax, [edi]                  \
+    __asm   adc     edx, 0                      \
+    __asm   mov     ecx, edx                    \
+    __asm   stosd
+
+#if defined(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  = (t_uint) r;                   \
+    r1  = (t_uint)( 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/include/polarssl/camellia.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,243 @@
+/**
+ * \file camellia.h
+ *
+ * \brief Camellia block cipher
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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 <stddef.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          Initialize CAMELLIA context
+ *
+ * \param ctx      CAMELLIA context to be initialized
+ */
+void camellia_init( camellia_context *ctx );
+
+/**
+ * \brief          Clear CAMELLIA context
+ *
+ * \param ctx      CAMELLIA context to be cleared
+ */
+void camellia_free( camellia_context *ctx );
+
+/**
+ * \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)
+ *
+ * \note           Upon exit, the content of the IV is updated so that you can
+ *                 call the function same function again on the following
+ *                 block(s) of data and get the same result as if it was
+ *                 encrypted in one call. This allows a "streaming" usage.
+ *                 If on the other hand you need to retain the contents of the
+ *                 IV, you should either save it manually or use the cipher
+ *                 module instead.
+ *
+ * \param ctx      CAMELLIA context
+ * \param mode     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.
+ *
+ * \note           Upon exit, the content of the IV is updated so that you can
+ *                 call the function same function again on the following
+ *                 block(s) of data and get the same result as if it was
+ *                 encrypted in one call. This allows a "streaming" usage.
+ *                 If on the other hand you need to retain the contents of the
+ *                 IV, you should either save it manually or use the cipher
+ *                 module instead.
+ *
+ * \param ctx      CAMELLIA context
+ * \param mode     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/include/polarssl/ccm.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,132 @@
+/**
+ * \file ccm.h
+ *
+ * \brief Counter with CBC-MAC (CCM) for 128-bit block ciphers
+ *
+ *  Copyright (C) 2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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_CCM_H
+#define POLARSSL_CCM_H
+
+#include "cipher.h"
+
+#define POLARSSL_ERR_CCM_BAD_INPUT      -0x000D /**< Bad input parameters to function. */
+#define POLARSSL_ERR_CCM_AUTH_FAILED    -0x000F /**< Authenticated decryption failed. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          CCM context structure
+ */
+typedef struct {
+    cipher_context_t cipher_ctx;    /*!< cipher context used */
+}
+ccm_context;
+
+/**
+ * \brief           CCM initialization (encryption and decryption)
+ *
+ * \param ctx       CCM context to be initialized
+ * \param cipher    cipher to use (a 128-bit block cipher)
+ * \param key       encryption key
+ * \param keysize   key size in bits (must be acceptable by the cipher)
+ *
+ * \return          0 if successful, or a cipher specific error code
+ */
+int ccm_init( ccm_context *ctx, cipher_id_t cipher,
+              const unsigned char *key, unsigned int keysize );
+
+/**
+ * \brief           Free a CCM context and underlying cipher sub-context
+ *
+ * \param ctx       CCM context to free
+ */
+void ccm_free( ccm_context *ctx );
+
+/**
+ * \brief           CCM buffer encryption
+ *
+ * \param ctx       CCM context
+ * \param length    length of the input data in bytes
+ * \param iv        nonce (initialization vector)
+ * \param iv_len    length of IV in bytes
+ *                  must be 2, 3, 4, 5, 6, 7 or 8
+ * \param add       additional data
+ * \param add_len   length of additional data in bytes
+ *                  must be less than 2^16 - 2^8
+ * \param input     buffer holding the input data
+ * \param output    buffer for holding the output data
+ *                  must be at least 'length' bytes wide
+ * \param tag       buffer for holding the tag
+ * \param tag_len   length of the tag to generate in bytes
+ *                  must be 4, 6, 8, 10, 14 or 16
+ *
+ * \note            The tag is written to a separate buffer. To get the tag
+ *                  concatenated with the output as in the CCM spec, use
+ *                  tag = output + length and make sure the output buffer is
+ *                  at least length + tag_len wide.
+ *
+ * \return          0 if successful
+ */
+int ccm_encrypt_and_tag( ccm_context *ctx, size_t length,
+                         const unsigned char *iv, size_t iv_len,
+                         const unsigned char *add, size_t add_len,
+                         const unsigned char *input, unsigned char *output,
+                         unsigned char *tag, size_t tag_len );
+
+/**
+ * \brief           CCM buffer authenticated decryption
+ *
+ * \param ctx       CCM 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 input     buffer holding the input data
+ * \param output    buffer for holding the output data
+ * \param tag       buffer holding the tag
+ * \param tag_len   length of the tag
+ *
+ * \return         0 if successful and authenticated,
+ *                 POLARSSL_ERR_CCM_AUTH_FAILED if tag does not match
+ */
+int ccm_auth_decrypt( ccm_context *ctx, size_t length,
+                      const unsigned char *iv, size_t iv_len,
+                      const unsigned char *add, size_t add_len,
+                      const unsigned char *input, unsigned char *output,
+                      const unsigned char *tag, size_t tag_len );
+
+#if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_AES_C)
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int ccm_self_test( int verbose );
+#endif /* POLARSSL_SELF_TEST && POLARSSL_AES_C */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* POLARSSL_CGM_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/polarssl/certs.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,75 @@
+/**
+ * \file certs.h
+ *
+ * \brief Sample certificates and DHM parameters for testing
+ *
+ *  Copyright (C) 2006-2010, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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/include/polarssl/check_config.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,496 @@
+/**
+ * \file check_config.h
+ *
+ * \brief Consistency checks for configuration options
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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_DEPRECATED_WARNING) && \
+    !defined(__GNUC__) && !defined(__clang__)
+#error "POLARSSL_DEPRECATED_WARNING only works with GCC and Clang"
+#endif
+
+#if defined(POLARSSL_NET_C) && !defined(POLARSSL_HAVE_IPV6)
+#if defined(POLARSSL_DEPRECATED_WARNING)
+#warning "Using POLARSSL_NET_C without POLARSSL_HAVE_IPV6 is deprecated"
+#endif
+#if defined(POLARSSL_DEPRECATED_REMOVED)
+#define POLARSSL_HAVE_IPV6
+#endif
+#endif /* POLARSSL_NET_C && !POLARSSL_HAVE_IPV6 */
+
+#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(CTR_DRBG_ENTROPY_LEN) && (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(CTR_DRBG_ENTROPY_LEN) && (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_C) && !defined(POLARSSL_PLATFORM_C)
+#error "POLARSSL_MEMORY_C 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_C) && \
+    ( !defined(POLARSSL_RSA_C) && !defined(POLARSSL_ECP_C) )
+#error "POLARSSL_PK_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_PLATFORM_EXIT_ALT) && !defined(POLARSSL_PLATFORM_C)
+#error "POLARSSL_PLATFORM_EXIT_ALT defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PLATFORM_EXIT_MACRO) && !defined(POLARSSL_PLATFORM_C)
+#error "POLARSSL_PLATFORM_EXIT_MACRO defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PLATFORM_EXIT_MACRO) &&\
+    ( defined(POLARSSL_PLATFORM_STD_EXIT) ||\
+        defined(POLARSSL_PLATFORM_EXIT_ALT) )
+#error "POLARSSL_PLATFORM_EXIT_MACRO and POLARSSL_PLATFORM_STD_EXIT/POLARSSL_PLATFORM_EXIT_ALT cannot be defined simultaneously"
+#endif
+
+#if defined(POLARSSL_PLATFORM_FPRINTF_ALT) && !defined(POLARSSL_PLATFORM_C)
+#error "POLARSSL_PLATFORM_FPRINTF_ALT defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PLATFORM_FPRINTF_MACRO) && !defined(POLARSSL_PLATFORM_C)
+#error "POLARSSL_PLATFORM_FPRINTF_MACRO defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PLATFORM_FPRINTF_MACRO) &&\
+    ( defined(POLARSSL_PLATFORM_STD_FPRINTF) ||\
+        defined(POLARSSL_PLATFORM_FPRINTF_ALT) )
+#error "POLARSSL_PLATFORM_FPRINTF_MACRO and POLARSSL_PLATFORM_STD_FPRINTF/POLARSSL_PLATFORM_FPRINTF_ALT cannot be defined simultaneously"
+#endif
+
+#if defined(POLARSSL_PLATFORM_FREE_MACRO) &&\
+    ( !defined(POLARSSL_PLATFORM_C) || !defined(POLARSSL_PLATFORM_MEMORY) )
+#error "POLARSSL_PLATFORM_FREE_MACRO defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PLATFORM_FREE_MACRO) &&\
+    defined(POLARSSL_PLATFORM_STD_FREE)
+#error "POLARSSL_PLATFORM_FREE_MACRO and POLARSSL_PLATFORM_STD_FREE cannot be defined simultaneously"
+#endif
+
+#if defined(POLARSSL_PLATFORM_FREE_MACRO) && !defined(POLARSSL_PLATFORM_MALLOC_MACRO)
+#error "POLARSSL_PLATFORM_MALLOC_MACRO must be defined if POLARSSL_PLATFORM_FREE_MACRO is"
+#endif
+
+#if defined(POLARSSL_PLATFORM_MALLOC_MACRO) &&\
+    ( !defined(POLARSSL_PLATFORM_C) || !defined(POLARSSL_PLATFORM_MEMORY) )
+#error "POLARSSL_PLATFORM_MALLOC_MACRO defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PLATFORM_MALLOC_MACRO) &&\
+    defined(POLARSSL_PLATFORM_STD_MALLOC)
+#error "POLARSSL_PLATFORM_MALLOC_MACRO and POLARSSL_PLATFORM_STD_MALLOC cannot be defined simultaneously"
+#endif
+
+#if defined(POLARSSL_PLATFORM_MALLOC_MACRO) && !defined(POLARSSL_PLATFORM_FREE_MACRO)
+#error "POLARSSL_PLATFORM_FREE_MACRO must be defined if POLARSSL_PLATFORM_MALLOC_MACRO is"
+#endif
+
+#if defined(POLARSSL_PLATFORM_MEMORY) && !defined(POLARSSL_PLATFORM_C)
+#error "POLARSSL_PLATFORM_MEMORY defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PLATFORM_PRINTF_ALT) && !defined(POLARSSL_PLATFORM_C)
+#error "POLARSSL_PLATFORM_PRINTF_ALT defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PLATFORM_PRINTF_MACRO) && !defined(POLARSSL_PLATFORM_C)
+#error "POLARSSL_PLATFORM_PRINTF_MACRO defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PLATFORM_PRINTF_MACRO) &&\
+    ( defined(POLARSSL_PLATFORM_STD_PRINTF) ||\
+        defined(POLARSSL_PLATFORM_PRINTF_ALT) )
+#error "POLARSSL_PLATFORM_PRINTF_MACRO and POLARSSL_PLATFORM_STD_PRINTF/POLARSSL_PLATFORM_PRINTF_ALT cannot be defined simultaneously"
+#endif
+
+#if defined(POLARSSL_PLATFORM_SNPRINTF_ALT) && !defined(POLARSSL_PLATFORM_C)
+#error "POLARSSL_PLATFORM_SNPRINTF_ALT defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PLATFORM_SNPRINTF_ALT) && ( defined(_WIN32)\
+    && !defined(EFIX64) && !defined(EFI32) )
+#error "POLARSSL_PLATFORM_SNPRINTF_ALT defined but not available on Windows"
+#endif
+
+#if defined(POLARSSL_PLATFORM_SNPRINTF_MACRO) && !defined(POLARSSL_PLATFORM_C)
+#error "POLARSSL_PLATFORM_SNPRINTF_MACRO defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PLATFORM_SNPRINTF_MACRO) &&\
+    ( defined(POLARSSL_PLATFORM_STD_SNPRINTF) ||\
+        defined(POLARSSL_PLATFORM_SNPRINTF_ALT) )
+#error "POLARSSL_PLATFORM_SNPRINTF_MACRO and POLARSSL_PLATFORM_STD_SNPRINTF/POLARSSL_PLATFORM_SNPRINTF_ALT cannot be defined simultaneously"
+#endif
+
+#if defined(POLARSSL_PLATFORM_STD_MEM_HDR) &&\
+    !defined(POLARSSL_PLATFORM_NO_STD_FUNCTIONS)
+#error "POLARSSL_PLATFORM_STD_MEM_HDR defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PLATFORM_STD_MALLOC) && !defined(POLARSSL_PLATFORM_MEMORY)
+#error "POLARSSL_PLATFORM_STD_MALLOC defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PLATFORM_STD_MALLOC) && !defined(POLARSSL_PLATFORM_MEMORY)
+#error "POLARSSL_PLATFORM_STD_MALLOC defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PLATFORM_STD_FREE) && !defined(POLARSSL_PLATFORM_MEMORY)
+#error "POLARSSL_PLATFORM_STD_FREE defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PLATFORM_STD_EXIT) &&\
+    !defined(POLARSSL_PLATFORM_EXIT_ALT)
+#error "POLARSSL_PLATFORM_STD_EXIT defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PLATFORM_STD_FPRINTF) &&\
+    !defined(POLARSSL_PLATFORM_FPRINTF_ALT)
+#error "POLARSSL_PLATFORM_STD_FPRINTF defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PLATFORM_STD_PRINTF) &&\
+    !defined(POLARSSL_PLATFORM_PRINTF_ALT)
+#error "POLARSSL_PLATFORM_STD_PRINTF defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PLATFORM_STD_SNPRINTF) &&\
+    !defined(POLARSSL_PLATFORM_SNPRINTF_ALT)
+#error "POLARSSL_PLATFORM_STD_SNPRINTF 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_X509_RSASSA_PSS_SUPPORT) &&                        \
+    ( !defined(POLARSSL_RSA_C) || !defined(POLARSSL_PKCS1_V21) )
+#error "POLARSSL_X509_RSASSA_PSS_SUPPORT 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_ENCRYPT_THEN_MAC) &&   \
+    !defined(POLARSSL_SSL_PROTO_TLS1)   &&      \
+    !defined(POLARSSL_SSL_PROTO_TLS1_1) &&      \
+    !defined(POLARSSL_SSL_PROTO_TLS1_2)
+#error "POLARSSL_SSL_ENCRYPT_THEN_MAC defined, but not all prerequsites"
+#endif
+
+#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET) && \
+    !defined(POLARSSL_SSL_PROTO_TLS1)   &&          \
+    !defined(POLARSSL_SSL_PROTO_TLS1_1) &&          \
+    !defined(POLARSSL_SSL_PROTO_TLS1_2)
+#error "POLARSSL_SSL_EXTENDED_MASTER_SECRET defined, but not all prerequsites"
+#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_CBC_RECORD_SPLITTING) && \
+    !defined(POLARSSL_SSL_PROTO_SSL3) && !defined(POLARSSL_SSL_PROTO_TLS1)
+#error "POLARSSL_SSL_CBC_RECORD_SPLITTING 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/include/polarssl/cipher.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,780 @@
+/**
+ * \file cipher.h
+ *
+ * \brief Generic cipher wrapper.
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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
+
+#include <stddef.h>
+
+#if defined(POLARSSL_GCM_C) || defined(POLARSSL_CCM_C)
+#define POLARSSL_CIPHER_MODE_AEAD
+#endif
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+#define POLARSSL_CIPHER_MODE_WITH_PADDING
+#endif
+
+#if defined(POLARSSL_ARC4_C)
+#define POLARSSL_CIPHER_MODE_STREAM
+#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 */
+
+#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). */
+
+#define POLARSSL_CIPHER_VARIABLE_IV_LEN     0x01    /**< Cipher accepts IVs of variable length */
+#define POLARSSL_CIPHER_VARIABLE_KEY_LEN    0x02    /**< Cipher accepts keys of variable length */
+
+#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, /* Unused! */
+    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,
+    POLARSSL_CIPHER_AES_128_CCM,
+    POLARSSL_CIPHER_AES_192_CCM,
+    POLARSSL_CIPHER_AES_256_CCM,
+    POLARSSL_CIPHER_CAMELLIA_128_CCM,
+    POLARSSL_CIPHER_CAMELLIA_192_CCM,
+    POLARSSL_CIPHER_CAMELLIA_256_CCM,
+} cipher_type_t;
+
+typedef enum {
+    POLARSSL_MODE_NONE = 0,
+    POLARSSL_MODE_ECB,
+    POLARSSL_MODE_CBC,
+    POLARSSL_MODE_CFB,
+    POLARSSL_MODE_OFB, /* Unused! */
+    POLARSSL_MODE_CTR,
+    POLARSSL_MODE_GCM,
+    POLARSSL_MODE_STREAM,
+    POLARSSL_MODE_CCM,
+} 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 );
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    /** Encrypt using CBC */
+    int (*cbc_func)( void *ctx, operation_t mode, size_t length,
+                     unsigned char *iv, const unsigned char *input,
+                     unsigned char *output );
+#endif
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+    /** 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 );
+#endif
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+    /** Encrypt using CTR */
+    int (*ctr_func)( void *ctx, size_t length, size_t *nc_off,
+                     unsigned char *nonce_counter, unsigned char *stream_block,
+                     const unsigned char *input, unsigned char *output );
+#endif
+
+#if defined(POLARSSL_CIPHER_MODE_STREAM)
+    /** Encrypt using STREAM */
+    int (*stream_func)( void *ctx, size_t length,
+                        const unsigned char *input, unsigned char *output );
+#endif
+
+    /** Set key for encryption purposes */
+    int (*setkey_enc_func)( void *ctx, const unsigned char *key,
+                            unsigned int key_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;
+
+    /** Flags for variable IV size, variable key size, etc. */
+    int flags;
+
+    /** 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;
+
+#if defined(POLARSSL_CIPHER_MODE_WITH_PADDING)
+    /** 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 );
+#endif
+
+    /** 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               Initialize a cipher_context (as NONE)
+ */
+void cipher_init( cipher_context_t *ctx );
+
+/**
+ * \brief               Free and clear the cipher-specific context of ctx.
+ *                      Freeing ctx itself remains the responsibility of the
+ *                      caller.
+ */
+void cipher_free( cipher_context_t *ctx );
+
+/**
+ * \brief               Initialises and fills the cipher context structure with
+ *                      the appropriate values.
+ *
+ * \note                Currently also clears structure. In future versions you
+ *                      will be required to call cipher_init() on the structure
+ *                      first.
+ *
+ * \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 );
+
+#if ! defined(POLARSSL_DEPRECATED_REMOVED)
+#if defined(POLARSSL_DEPRECATED_WARNING)
+#define DEPRECATED    __attribute__((deprecated))
+#else
+#define DEPRECATED
+#endif
+/**
+ * \brief               Free the cipher-specific context of ctx. Freeing ctx
+ *                      itself remains the responsibility of the caller.
+ *
+ * \deprecated          Use cipher_free() instead
+ *
+ * \param ctx           Free the cipher-specific context
+ *
+ * \returns             0
+ */
+int cipher_free_ctx( cipher_context_t *ctx ) DEPRECATED;
+#undef DEPRECATED
+#endif /* POLARSSL_DEPRECATED_REMOVED */
+
+/**
+ * \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             0 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_GCM_C)
+/**
+ * \brief               Add additional data (for AEAD ciphers).
+ *                      Currently only supported with GCM.
+ *                      Must be called exactly once, after cipher_reset().
+ *
+ * \param ctx           generic cipher context
+ * \param ad            Additional data to use.
+ * \param ad_len        Length of ad.
+ *
+ * \return              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_GCM_C */
+
+/**
+ * \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_GCM_C)
+/**
+ * \brief               Write tag for AEAD ciphers.
+ *                      Currently only supported with GCM.
+ *                      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.
+ *                      Currently only supported with 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_GCM_C */
+
+/**
+ * \brief               Generic all-in-one encryption/decryption
+ *                      (for all ciphers except AEAD constructs).
+ *
+ * \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.
+ * \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.
+ *
+ * \note                Some ciphers don't use IVs nor NONCE. For these
+ *                      ciphers, use iv = NULL and iv_len = 0.
+ *
+ * \returns             0 on success, or
+ *                      POLARSSL_ERR_CIPHER_BAD_INPUT_DATA, or
+ *                      POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED if decryption
+ *                      expected a full block but was not provided one, or
+ *                      POLARSSL_ERR_CIPHER_INVALID_PADDING on invalid padding
+ *                      while decrypting, or
+ *                      a cipher specific error code.
+ */
+int cipher_crypt( cipher_context_t *ctx,
+                  const unsigned char *iv, size_t iv_len,
+                  const unsigned char *input, size_t ilen,
+                  unsigned char *output, size_t *olen );
+
+#if defined(POLARSSL_CIPHER_MODE_AEAD)
+/**
+ * \brief               Generic autenticated encryption (AEAD ciphers).
+ *
+ * \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.
+ * \param ad            Additional data to authenticate.
+ * \param ad_len        Length of ad.
+ * \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.
+ * \param olen          length of the output data, will be filled with the
+ *                      actual number of bytes written.
+ * \param tag           buffer for the authentication tag
+ * \param tag_len       desired tag length
+ *
+ * \returns             0 on success, or
+ *                      POLARSSL_ERR_CIPHER_BAD_INPUT_DATA, or
+ *                      a cipher specific error code.
+ */
+int cipher_auth_encrypt( cipher_context_t *ctx,
+                         const unsigned char *iv, size_t iv_len,
+                         const unsigned char *ad, size_t ad_len,
+                         const unsigned char *input, size_t ilen,
+                         unsigned char *output, size_t *olen,
+                         unsigned char *tag, size_t tag_len );
+
+/**
+ * \brief               Generic autenticated decryption (AEAD ciphers).
+ *
+ * \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.
+ * \param ad            Additional data to be authenticated.
+ * \param ad_len        Length of ad.
+ * \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.
+ * \param olen          length of the output data, will be filled with the
+ *                      actual number of bytes written.
+ * \param tag           buffer holding the authentication tag
+ * \param tag_len       length of the authentication tag
+ *
+ * \returns             0 on success, or
+ *                      POLARSSL_ERR_CIPHER_BAD_INPUT_DATA, or
+ *                      POLARSSL_ERR_CIPHER_AUTH_FAILED if data isn't authentic,
+ *                      or a cipher specific error code.
+ *
+ * \note                If the data is not authentic, then the output buffer
+ *                      is zeroed out to prevent the unauthentic plaintext to
+ *                      be used by mistake, making this interface safer.
+ */
+int cipher_auth_decrypt( cipher_context_t *ctx,
+                         const unsigned char *iv, size_t iv_len,
+                         const unsigned char *ad, size_t ad_len,
+                         const unsigned char *input, size_t ilen,
+                         unsigned char *output, size_t *olen,
+                         const unsigned char *tag, size_t tag_len );
+#endif /* 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/include/polarssl/cipher_wrap.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,56 @@
+/**
+ * \file cipher_wrap.h
+ *
+ * \brief Cipher wrappers.
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ *  Copyright (C) 2006-2013, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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/include/polarssl/compat-1.2.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,396 @@
+/**
+ * \file compat-1.2.h
+ *
+ * \brief Backwards compatibility header for PolarSSL-1.2 from PolarSSL-1.3
+ *
+ * \deprecated  Use native PolarSSL 1.3 functions instead.
+ *
+ *  Copyright (C) 2006-2013, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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_DEPRECATED_REMOVED)
+
+#if defined(POLARSSL_DEPRECATED_WARNING)
+#warning "Including compat-1.2.h is deprecated"
+#endif
+
+#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 */
+#endif /* POLARSSL_DEPRECATED_REMOVED */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/polarssl/config.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,2359 @@
+/**
+ * \file config.h
+ *
+ * \brief Configuration options (set of defines)
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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.
+ *
+ * \deprecated The compiler should be able to generate code for 32-bit
+ * arithmetic (required by C89). This code is likely to be at least as
+ * efficient as ours.
+ *
+ * Uncomment if native integers are 8-bit wide.
+ */
+//#define POLARSSL_HAVE_INT8
+
+/**
+ * \def POLARSSL_HAVE_INT16
+ *
+ * The system uses 16-bit wide native integers.
+ *
+ * \deprecated The compiler should be able to generate code for 32-bit
+ * arithmetic (required by C89). This code is likely to be at least as
+ * efficient as ours.
+ *
+ * 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.
+ *
+ * \warning As of 1.3.11, *not* using this flag when POLARSSL_NET_C is
+ * defined, is deprecated. The alternative legacy code will be removed in 2.0.
+ *
+ * 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 mbed TLS 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 without the
+ * POLARSSL_PLATFORM_{FREE,MALLOC}_MACROs will provide
+ * "platform_set_malloc_free()" allowing you to set an alternative malloc() and
+ * free() function pointer at runtime.
+ *
+ * Enabling POLARSSL_PLATFORM_MEMORY and specifying
+ * POLARSSL_PLATFORM_{MALLOC,FREE}_MACROs will allow you to specify the
+ * alternate function at compile time.
+ *
+ * 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, or enabling a
+ * POLARSSL_PLATFORM_XXX_MACRO.
+ *
+ * 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 mbed TLS support the function in the platform
+ * abstraction layer.
+ *
+ * Example: In case you uncomment POLARSSL_PLATFORM_PRINTF_ALT, mbed TLS 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!
+ *
+ * WARNING: POLARSSL_PLATFORM_SNPRINTF_ALT is not available on Windows
+ * for compatibility reasons.
+ *
+ * WARNING: POLARSSL_PLATFORM_XXX_ALT cannot be defined at the same time as
+ * POLARSSL_PLATFORM_XXX_MACRO!
+ *
+ * Uncomment a macro to enable alternate implementation of specific base
+ * platform function
+ */
+//#define POLARSSL_PLATFORM_EXIT_ALT
+//#define POLARSSL_PLATFORM_FPRINTF_ALT
+//#define POLARSSL_PLATFORM_PRINTF_ALT
+//#define POLARSSL_PLATFORM_SNPRINTF_ALT
+
+/**
+ * \def POLARSSL_DEPRECATED_WARNING
+ *
+ * Mark deprecated functions so that they generate a warning if used.
+ * Functions deprecated in one version will usually be removed in the next
+ * version. You can enable this to help you prepare the transition to a new
+ * major version by making sure your code is not using these functions.
+ *
+ * This only works with GCC and Clang. With other compilers, you may want to
+ * use POLARSSL_DEPRECATED_REMOVED
+ *
+ * Uncomment to get warnings on using deprecated functions.
+ */
+//#define POLARSSL_DEPRECATED_WARNING
+
+/**
+ * \def POLARSSL_DEPRECATED_REMOVED
+ *
+ * Remove deprecated functions so that they generate an error if used.
+ * Functions deprecated in one version will usually be removed in the next
+ * version. You can enable this to help you prepare the transition to a new
+ * major version by making sure your code is not using these functions.
+ *
+ * Uncomment to get errors on using deprecated functions.
+ */
+//#define POLARSSL_DEPRECATED_REMOVED
+
+/* \} name SECTION: System support */
+
+/**
+ * \name SECTION: mbed TLS 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 mbed TLS 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, mbed TLS 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_CAMELLIA_SMALL_MEMORY
+ *
+ * Use less ROM for the Camellia implementation (saves about 768 bytes).
+ *
+ * Uncomment this macro to use less memory for Camellia.
+ */
+//#define POLARSSL_CAMELLIA_SMALL_MEMORY
+
+/**
+ * \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_REMOVE_ARC4_CIPHERSUITES
+ *
+ * Remove RC4 ciphersuites by default in SSL / TLS.
+ * This flag removes the ciphersuites based on RC4 from the default list as
+ * returned by ssl_list_ciphersuites(). However, it is still possible to
+ * enable (some of) them with ssl_set_ciphersuites() by including them
+ * explicitly.
+ *
+ * Uncomment this macro to remove RC4 ciphersuites by default.
+ */
+//#define POLARSSL_REMOVE_ARC4_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().
+ *
+ * \deprecated Do not define this and use polarssl_strerror() instead
+ *
+ * Disable if you want to really remove the error_strerror() name
+ */
+#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 when POLARSSL_ERROR_C is disabled
+ * (no effect when POLARSSL_ERROR_C is enabled).
+ *
+ * You can safely disable this if POLARSSL_ERROR_C is enabled, or if you're
+ * not using polarssl_strerror() or error_strerror() in your application.
+ *
+ * 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_AEAD_RANDOM_IV
+ *
+ * Generate a random IV rather than using the record sequence number as a
+ * nonce for ciphersuites using and AEAD algorithm (GCM or CCM).
+ *
+ * Using the sequence number is generally recommended.
+ *
+ * Uncomment this macro to always use random IVs with AEAD ciphersuites.
+ */
+//#define POLARSSL_SSL_AEAD_RANDOM_IV
+
+/**
+ * \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, mbed TLS 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_ENCRYPT_THEN_MAC
+ *
+ * Enable support for Encrypt-then-MAC, RFC 7366.
+ *
+ * This allows peers that both support it to use a more robust protection for
+ * ciphersuites using CBC, providing deep resistance against timing attacks
+ * on the padding or underlying cipher.
+ *
+ * This only affects CBC ciphersuites, and is useless if none is defined.
+ *
+ * Requires: POLARSSL_SSL_PROTO_TLS1    or
+ *           POLARSSL_SSL_PROTO_TLS1_1  or
+ *           POLARSSL_SSL_PROTO_TLS1_2
+ *
+ * Comment this macro to disable support for Encrypt-then-MAC
+ */
+#define POLARSSL_SSL_ENCRYPT_THEN_MAC
+
+/** \def POLARSSL_SSL_EXTENDED_MASTER_SECRET
+ *
+ * Enable support for Extended Master Secret, aka Session Hash
+ * (draft-ietf-tls-session-hash-02).
+ *
+ * This was introduced as "the proper fix" to the Triple Handshake familiy of
+ * attacks, but it is recommended to always use it (even if you disable
+ * renegotiation), since it actually fixes a more fundamental issue in the
+ * original SSL/TLS design, and has implications beyond Triple Handshake.
+ *
+ * Requires: POLARSSL_SSL_PROTO_TLS1    or
+ *           POLARSSL_SSL_PROTO_TLS1_1  or
+ *           POLARSSL_SSL_PROTO_TLS1_2
+ *
+ * Comment this macro to disable support for Extended Master Secret.
+ */
+#define POLARSSL_SSL_EXTENDED_MASTER_SECRET
+
+/**
+ * \def POLARSSL_SSL_FALLBACK_SCSV
+ *
+ * Enable support for FALLBACK_SCSV (draft-ietf-tls-downgrade-scsv-00).
+ *
+ * For servers, it is recommended to always enable this, unless you support
+ * only one version of TLS, or know for sure that none of your clients
+ * implements a fallback strategy.
+ *
+ * For clients, you only need this if you're using a fallback strategy, which
+ * is not recommended in the first place, unless you absolutely need it to
+ * interoperate with buggy (version-intolerant) servers.
+ *
+ * Comment this macro to disable support for FALLBACK_SCSV
+ */
+#define POLARSSL_SSL_FALLBACK_SCSV
+
+/**
+ * \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_CBC_RECORD_SPLITTING
+ *
+ * Enable 1/n-1 record splitting for CBC mode in SSLv3 and TLS 1.0.
+ *
+ * This is a countermeasure to the BEAST attack, which also minimizes the risk
+ * of interoperability issues compared to sending 0-length records.
+ *
+ * Comment this macro to disable 1/n-1 record splitting.
+ */
+#define POLARSSL_SSL_CBC_RECORD_SPLITTING
+
+/**
+ * \def POLARSSL_SSL_DISABLE_RENEGOTIATION
+ *
+ * Disable support for TLS renegotiation.
+ *
+ * The two main uses of renegotiation are (1) refresh keys on long-lived
+ * connections and (2) client authentication after the initial handshake.
+ * If you don't need renegotiation, it's probably better to disable it, since
+ * it has been associated with security issues in the past and is easy to
+ * misuse/misunderstand.
+ *
+ * Warning: in the next stable branch, this switch will be replaced by
+ * POLARSSL_SSL_RENEGOTIATION to enable support for renegotiation.
+ *
+ * Uncomment this to disable support for renegotiation.
+ */
+//#define POLARSSL_SSL_DISABLE_RENEGOTIATION
+
+/**
+ * \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 RFC 7301 Application Layer Protocol Negotiation.
+ *
+ * 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.
+ *
+ * Requires: POLARSSL_X509_CRT_PARSE_C
+ *
+ * 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_X509_RSASSA_PSS_SUPPORT
+ *
+ * Enable parsing and verification of X.509 certificates, CRLs and CSRS
+ * signed with RSASSA-PSS (aka PKCS#1 v2.1).
+ *
+ * Comment this macro to disallow using RSASSA-PSS in certificates.
+ */
+#define POLARSSL_X509_RSASSA_PSS_SUPPORT
+
+/**
+ * \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: mbed TLS feature support */
+
+/**
+ * \name SECTION: mbed TLS modules
+ *
+ * This section enables or disables entire modules in mbed TLS
+ * \{
+ */
+
+/**
+ * \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/ecdsa.c
+ *          library/rsa.c
+ *          library/ssl_tls.c
+ *
+ * This module is required for RSA, DHM and ECC (ECDH, ECDSA) 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_CCM_C
+ *
+ * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher.
+ *
+ * Module:  library/ccm.c
+ *
+ * Requires: POLARSSL_AES_C or POLARSSL_CAMELLIA_C
+ *
+ * This module enables the AES-CCM ciphersuites, if other requisites are
+ * enabled as well.
+ */
+#define POLARSSL_CCM_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 Use POLARSSL_PLATFORM_MEMORY instead.
+ *
+ * Depends on: POLARSSL_PLATFORM_C
+ */
+//#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 mbed TLS)
+ *
+ * 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.
+ *
+ * \warning As of 1.3.11, it is deprecated to enable this module without
+ * POLARSSL_HAVE_IPV6. The alternative legacy code will be removed in 2.0.
+ *
+ * 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(), snprintf(), printf(), fprintf(), exit()
+ *
+ * Enabling POLARSSL_PLATFORM_C enables to use of POLARSSL_PLATFORM_XXX_ALT
+ * or POLARSSL_PLATFORM_XXX_MACRO directives, allowing the functions mentioned
+ * above to be specified at runtime or compile time respectively.
+ *
+ * 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 mbed TLS 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 mbed TLS
+ */
+//#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: mbed TLS 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            1024 /**< 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 POLARSSL_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_EXIT            exit /**< Default exit to use, can be undefined */
+//#define POLARSSL_PLATFORM_STD_FPRINTF      fprintf /**< Default fprintf to use, can be undefined */
+//#define POLARSSL_PLATFORM_STD_PRINTF        printf /**< Default printf to use, can be undefined */
+//#define POLARSSL_PLATFORM_STD_SNPRINTF    snprintf /**< Default snprintf to use, can be undefined */
+
+/* To Use Function Macros POLARSSL_PLATFORM_C must be enabled */
+/* POLARSSL_PLATFORM_XXX_MACRO and POLARSSL_PLATFORM_XXX_ALT cannot both be defined */
+//#define POLARSSL_PLATFORM_MALLOC_MACRO        malloc /**< Default allocator macro to use, can be undefined */
+//#define POLARSSL_PLATFORM_FREE_MACRO            free /**< Default free macro to use, can be undefined */
+//#define POLARSSL_PLATFORM_EXIT_MACRO            exit /**< Default exit macro to use, can be undefined */
+//#define POLARSSL_PLATFORM_FPRINTF_MACRO      fprintf /**< Default fprintf macro to use, can be undefined */
+//#define POLARSSL_PLATFORM_PRINTF_MACRO        printf /**< Default printf macro to use, can be undefined */
+//#define POLARSSL_PLATFORM_SNPRINTF_MACRO    snprintf /**< Default snprintf macro 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) */
+//#define POLARSSL_PSK_MAX_LEN               32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */
+
+/**
+ * Complete list of ciphersuites to use, in order of preference.
+ *
+ * \warning No dependency checking is done on that field! This option can only
+ * be used to restrict the set of available ciphersuites. It is your
+ * responsibility to make sure the needed modules are active.
+ *
+ * Use this to save a few hundred bytes of ROM (default ordering of all
+ * available ciphersuites) and a few to a few hundred bytes of RAM.
+ *
+ * The value below is only an example, not the default.
+ */
+//#define SSL_CIPHERSUITES TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+
+/* Debug options */
+//#define POLARSSL_DEBUG_DFL_MODE POLARSSL_DEBUG_LOG_FULL /**< Default log: Full or Raw */
+
+/* X509 options */
+//#define POLARSSL_X509_MAX_INTERMEDIATE_CA   8   /**< Maximum number of intermediate CAs in a verification chain. */
+
+/* \} name SECTION: Module configuration options */
+
+#include "check_config.h"
+
+#endif /* POLARSSL_CONFIG_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/polarssl/ctr_drbg.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,274 @@
+/**
+ * \file ctr_drbg.h
+ *
+ * \brief CTR_DRBG based on AES-256 (NIST SP 800-90)
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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 "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               Clear CTR_CRBG context data
+ *
+ * \param ctx           CTR_DRBG context to clear
+ */
+void ctr_drbg_free( ctr_drbg_context *ctx );
+
+/**
+ * \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
+ *
+ * \note                If add_len is greater than CTR_DRBG_MAX_SEED_INPUT,
+ *                      only the first CTR_DRBG_MAX_SEED_INPUT bytes are used,
+ *                      the remaining ones are silently discarded.
+ */
+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/include/polarssl/debug.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,152 @@
+/**
+ * \file debug.h
+ *
+ * \brief Debug functions
+ *
+ *  Copyright (C) 2006-2011, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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/include/polarssl/des.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,306 @@
+/**
+ * \file des.h
+ *
+ * \brief DES block cipher
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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 <stddef.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          Initialize DES context
+ *
+ * \param ctx      DES context to be initialized
+ */
+void des_init( des_context *ctx );
+
+/**
+ * \brief          Clear DES context
+ *
+ * \param ctx      DES context to be cleared
+ */
+void des_free( des_context *ctx );
+
+/**
+ * \brief          Initialize Triple-DES context
+ *
+ * \param ctx      DES3 context to be initialized
+ */
+void des3_init( des3_context *ctx );
+
+/**
+ * \brief          Clear Triple-DES context
+ *
+ * \param ctx      DES3 context to be cleared
+ */
+void des3_free( des3_context *ctx );
+
+/**
+ * \brief          Set key parity on the given key to odd.
+ *
+ *                 DES keys are 56 bits long, but each byte is padded with
+ *                 a parity bit to allow verification.
+ *
+ * \param key      8-byte secret key
+ */
+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
+ *
+ * \note           Upon exit, the content of the IV is updated so that you can
+ *                 call the function same function again on the following
+ *                 block(s) of data and get the same result as if it was
+ *                 encrypted in one call. This allows a "streaming" usage.
+ *                 If on the other hand you need to retain the contents of the
+ *                 IV, you should either save it manually or use the cipher
+ *                 module instead.
+ *
+ * \param ctx      DES context
+ * \param mode     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
+ *
+ * \note           Upon exit, the content of the IV is updated so that you can
+ *                 call the function same function again on the following
+ *                 block(s) of data and get the same result as if it was
+ *                 encrypted in one call. This allows a "streaming" usage.
+ *                 If on the other hand you need to retain the contents of the
+ *                 IV, you should either save it manually or use the cipher
+ *                 module instead.
+ *
+ * \param ctx      3DES context
+ * \param mode     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/include/polarssl/dhm.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,309 @@
+/**
+ * \file dhm.h
+ *
+ * \brief Diffie-Hellman-Merkle key exchange
+ *
+ *  Copyright (C) 2006-2013, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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 2409 defines a number of standardized Diffie-Hellman groups
+ * that can be used.
+ * 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 2409 6.2.  1024-bit MODP Group (Second Oakley Group)
+ *  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_RFC2409_MODP_1024_P               \
+    "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
+    "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
+    "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
+    "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
+    "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" \
+    "FFFFFFFFFFFFFFFF"
+
+#define POLARSSL_DHM_RFC2409_MODP_1024_G          "02"
+
+#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          Initialize DHM context
+ *
+ * \param ctx      DHM context to be initialized
+ */
+void dhm_init( dhm_context *ctx );
+
+/**
+ * \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     on entry, must hold the size of the destination buffer
+ *                 on exit, holds the actual number of bytes 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 and clear the components of a DHM key
+ *
+ * \param ctx      DHM context to free and clear
+ */
+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/include/polarssl/ecdh.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,223 @@
+/**
+ * \file ecdh.h
+ *
+ * \brief Elliptic curve Diffie-Hellman
+ *
+ *  Copyright (C) 2006-2013, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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;      /*!<  elliptic curve used                           */
+    mpi d;              /*!<  our secret value (private key)                */
+    ecp_point Q;        /*!<  our public value (public key)                 */
+    ecp_point Qp;       /*!<  peer's public value (public key)              */
+    mpi z;              /*!<  shared secret                                 */
+    int point_format;   /*!<  format for point export in TLS messages       */
+    ecp_point Vi;       /*!<  blinding value (for later)                    */
+    ecp_point Vf;       /*!<  un-blinding value (for later)                 */
+    mpi _d;             /*!<  previous d (for later)                        */
+}
+ecdh_context;
+
+/**
+ * \brief           Generate a public key.
+ *                  Raw function that only does the core computation.
+ *
+ * \param grp       ECP group
+ * \param d         Destination MPI (secret exponent, aka private key)
+ * \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
+ *                  Raw function that only does the core computation.
+ *
+ * \param grp       ECP group
+ * \param z         Destination MPI (shared secret)
+ * \param Q         Public key from other party
+ * \param d         Our secret exponent (private key)
+ * \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           Generate a public key and a TLS ServerKeyExchange payload.
+ *                  (First function used by a TLS server for ECDHE.)
+ *
+ * \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 and procress a TLS ServerKeyExhange payload.
+ *                  (First function used by a TLS client for ECDHE.)
+ *
+ * \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.
+ *                  (Used by clients and servers in place of the
+ *                  ServerKeyEchange for static ECDH: import ECDH parameters
+ *                  from a certificate's EC key information.)
+ *
+ * \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           Generate a public key and a TLS ClientKeyExchange payload.
+ *                  (Second function used by a TLS client for ECDH(E).)
+ *
+ * \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 process a TLS ClientKeyExchange payload.
+ *                  (Second function used by a TLS server for ECDH(E).)
+ *
+ * \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.
+ *                  (Last function used by both TLS client en servers.)
+ *
+ * \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/include/polarssl/ecdsa.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,231 @@
+/**
+ * \file ecdsa.h
+ *
+ * \brief Elliptic curve DSA
+ *
+ *  Copyright (C) 2006-2013, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+#include "md.h"
+
+/**
+ * \brief           ECDSA context structure
+ *
+ * \note Purposefully begins with the same members as struct ecp_keypair.
+ */
+typedef struct
+{
+    ecp_group grp;      /*!<  elliptic 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/include/polarssl/ecp.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,665 @@
+/**
+ * \file ecp.h
+ *
+ * \brief Elliptic curves over GF(p)
+ *
+ *  Copyright (C) 2006-2013, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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 /* POLARSSL_ECP_WINDOW_SIZE */
+
+#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 /* POLARSSL_ECP_FIXED_POINT_OPTIM */
+
+/* \} 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
+ *
+ * \note            buf is updated to point right after the ECPoint on exit
+ *
+ * \return          0 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          0 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
+ *
+ * \note            buf is updated to point right after ECParameters on exit
+ *
+ * \return          0 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 );
+
+/**
+ * \brief           Check a public-private key pair
+ *
+ * \param pub       Keypair structure holding a public key
+ * \param prv       Keypair structure holding a private (plus public) key
+ *
+ * \return          0 if successful (keys are valid and match), or
+ *                  POLARSSL_ERR_ECP_BAD_INPUT_DATA, or
+ *                  a POLARSSL_ERR_ECP_XXX or POLARSSL_ERR_MPI_XXX code.
+ */
+int ecp_check_pub_priv( const ecp_keypair *pub, const ecp_keypair *prv );
+
+#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/include/polarssl/entropy.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,244 @@
+/**
+ * \file entropy.h
+ *
+ * \brief Entropy accumulator implementation
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+
+#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       Number of bytes desired, must be at most ENTROPY_BLOCK_SIZE
+ *
+ * \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 */
+
+#if defined(POLARSSL_SELF_TEST)
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if a test failed
+ */
+int entropy_self_test( int verbose );
+#endif /* POLARSSL_SELF_TEST */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* entropy.h */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/polarssl/entropy_poll.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,77 @@
+/**
+ * \file entropy_poll.h
+ *
+ * \brief Platform-specific and custom entropy polling functions
+ *
+ *  Copyright (C) 2006-2011, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+
+#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/include/polarssl/error.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,121 @@
+/**
+ * \file error.h
+ *
+ * \brief Error to string translation
+ *
+ *  Copyright (C) 2006-2013, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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 <stddef.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
+ * CCM       2                  0x000D-0x000F
+ *
+ * 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   11 (Started from top)
+ * SSL       7   31
+ *
+ * Module dependent error code (5 bits 0x.00.-0x.F8.)
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Translate a mbed TLS error code into a string representation,
+ *        Result is truncated if necessary and always includes a terminating
+ *        null byte.
+ *
+ * \param errnum    error code
+ * \param buffer    buffer to place representation in
+ * \param buflen    length of the buffer
+ */
+void 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/include/polarssl/gcm.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,217 @@
+/**
+ * \file gcm.h
+ *
+ * \brief Galois/Counter mode for 128-bit block ciphers
+ *
+ *  Copyright (C) 2006-2013, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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/include/polarssl/havege.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,76 @@
+/**
+ * \file havege.h
+ *
+ * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion
+ *
+ *  Copyright (C) 2006-2013, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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 <stddef.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          Clear HAVEGE state
+ *
+ * \param hs       HAVEGE state to be cleared
+ */
+void havege_free( 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/include/polarssl/hmac_drbg.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,282 @@
+/**
+ * \file hmac_drbg.h
+ *
+ * \brief HMAC_DRBG (NIST SP 800-90A)
+ *
+ *  Copyright (C) 2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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/include/polarssl/md.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,401 @@
+/**
+ * \file md.h
+ *
+ * \brief Generic message digest wrapper
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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 <stddef.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               Initialize a md_context (as NONE)
+ */
+void md_init( md_context_t *ctx );
+
+/**
+ * \brief               Free and clear the message-specific context of ctx.
+ *                      Freeing ctx itself remains the responsibility of the
+ *                      caller.
+ */
+void md_free( md_context_t *ctx );
+
+/**
+ * \brief          Initialises and fills the message digest context structure
+ *                 with the appropriate values.
+ *
+ * \note           Currently also clears structure. In future versions you
+ *                 will be required to call md_init() on the structure
+ *                 first.
+ *
+ * \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 );
+
+#if ! defined(POLARSSL_DEPRECATED_REMOVED)
+#if defined(POLARSSL_DEPRECATED_WARNING)
+#define DEPRECATED    __attribute__((deprecated))
+#else
+#define DEPRECATED
+#endif
+/**
+ * \brief          Free the message-specific context of ctx. Freeing ctx itself
+ *                 remains the responsibility of the caller.
+ *
+ * \deprecated     Use md_free() instead
+ *
+ * \param ctx      Free the message-specific context
+ *
+ * \returns        0
+ */
+int md_free_ctx( md_context_t *ctx ) DEPRECATED;
+#undef DEPRECATED
+#endif /* POLARSSL_DEPRECATED_REMOVED */
+
+/**
+ * \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/include/polarssl/md2.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,192 @@
+/**
+ * \file md2.h
+ *
+ * \brief MD2 message digest algorithm (hash function)
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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 <stddef.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          Initialize MD2 context
+ *
+ * \param ctx      MD2 context to be initialized
+ */
+void md2_init( md2_context *ctx );
+
+/**
+ * \brief          Clear MD2 context
+ *
+ * \param ctx      MD2 context to be cleared
+ */
+void md2_free( md2_context *ctx );
+
+/**
+ * \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/include/polarssl/md4.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,198 @@
+/**
+ * \file md4.h
+ *
+ * \brief MD4 message digest algorithm (hash function)
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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 <stddef.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          Initialize MD4 context
+ *
+ * \param ctx      MD4 context to be initialized
+ */
+void md4_init( md4_context *ctx );
+
+/**
+ * \brief          Clear MD4 context
+ *
+ * \param ctx      MD4 context to be cleared
+ */
+void md4_free( md4_context *ctx );
+
+/**
+ * \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/include/polarssl/md5.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,198 @@
+/**
+ * \file md5.h
+ *
+ * \brief MD5 message digest algorithm (hash function)
+ *
+ *  Copyright (C) 2006-2013, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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 <stddef.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          Initialize MD5 context
+ *
+ * \param ctx      MD5 context to be initialized
+ */
+void md5_init( md5_context *ctx );
+
+/**
+ * \brief          Clear MD5 context
+ *
+ * \param ctx      MD5 context to be cleared
+ */
+void md5_free( md5_context *ctx );
+
+/**
+ * \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/include/polarssl/md_wrap.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,70 @@
+/**
+ * \file md_wrap.h
+ *
+ * \brief Message digest wrappers.
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ *  Copyright (C) 2006-2011, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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/include/polarssl/memory.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,63 @@
+/**
+ * \file memory.h
+ *
+ * \brief Memory allocation layer
+ *
+ * \deprecated Use the platform layer instead
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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>
+
+#include "platform.h"
+#include "memory_buffer_alloc.h"
+
+#if ! defined(POLARSSL_DEPRECATED_REMOVED)
+#if defined(POLARSSL_DEPRECATED_WARNING)
+#define DEPRECATED    __attribute__((deprecated))
+#else
+#define DEPRECATED
+#endif
+/**
+ * \brief   Set malloc() / free() callback
+ *
+ * \deprecated Use platform_set_malloc_free instead
+ */
+int memory_set_own( void * (*malloc_func)( size_t ),
+                    void (*free_func)( void * ) ) DEPRECATED;
+int memory_set_own( void * (*malloc_func)( size_t ),
+                    void (*free_func)( void * ) )
+{
+    return platform_set_malloc_free( malloc_func, free_func );
+}
+#undef DEPRECATED
+#endif /* POLARSSL_DEPRECATED_REMOVED */
+
+
+#endif /* memory.h */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/polarssl/memory_buffer_alloc.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,150 @@
+/**
+ * \file memory_buffer_alloc.h
+ *
+ * \brief Buffer-based memory allocator
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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 <stddef.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 );
+
+/**
+ * \brief   Get the peak heap usage so far
+ *
+ * \param max_used      Peak number of bytes reauested by the application
+ * \param max_blocks    Peak number of blocks reauested by the application
+ */
+void memory_buffer_alloc_max_get( size_t *max_used, size_t *max_blocks );
+
+/**
+ * \brief   Reset peak statistics
+ */
+void memory_buffer_alloc_max_reset( void );
+
+/**
+ * \brief   Get the current heap usage
+ *
+ * \param cur_used      Number of bytes reauested by the application
+ * \param cur_blocks    Number of blocks reauested by the application
+ */
+void memory_buffer_alloc_cur_get( size_t *cur_used, size_t *cur_blocks );
+#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 );
+
+#if defined(POLARSSL_SELF_TEST)
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if a test failed
+ */
+int memory_buffer_alloc_self_test( int verbose );
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* memory_buffer_alloc.h */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/polarssl/net.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,158 @@
+/**
+ * \file net.h
+ *
+ * \brief Network communication functions
+ *
+ *  Copyright (C) 2006-2011, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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_NET_H
+#define POLARSSL_NET_H
+
+#include <stddef.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. */
+
+#define POLARSSL_NET_LISTEN_BACKLOG         10 /**< The backlog that listen() should use. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          Initiate a TCP connection with host:port
+ *
+ * \param fd       Socket to use
+ * \param host     Host to connect to
+ * \param port     Port to connect to
+ *
+ * \return         0 if successful, or one of:
+ *                      POLARSSL_ERR_NET_SOCKET_FAILED,
+ *                      POLARSSL_ERR_NET_UNKNOWN_HOST,
+ *                      POLARSSL_ERR_NET_CONNECT_FAILED
+ */
+int net_connect( int *fd, const char *host, int port );
+
+/**
+ * \brief          Create a listening socket on bind_ip:port.
+ *                 If bind_ip == NULL, all interfaces are binded.
+ *
+ * \param fd       Socket to use
+ * \param bind_ip  IP to bind to, can be NULL
+ * \param port     Port number to use
+ *
+ * \return         0 if successful, or one of:
+ *                      POLARSSL_ERR_NET_SOCKET_FAILED,
+ *                      POLARSSL_ERR_NET_BIND_FAILED,
+ *                      POLARSSL_ERR_NET_LISTEN_FAILED
+ */
+int net_bind( int *fd, const char *bind_ip, int port );
+
+/**
+ * \brief           Accept a connection from a remote client
+ *
+ * \param bind_fd   Relevant socket
+ * \param client_fd Will contain the connected client socket
+ * \param client_ip Will contain the client IP address
+ *                  Must be at least 4 bytes, or 16 if IPv6 is supported
+ *
+ * \return          0 if successful, POLARSSL_ERR_NET_ACCEPT_FAILED, or
+ *                  POLARSSL_ERR_NET_WANT_READ is bind_fd was set to
+ *                  non-blocking and accept() is blocking.
+ */
+int net_accept( int bind_fd, int *client_fd, void *client_ip );
+
+/**
+ * \brief          Set the socket blocking
+ *
+ * \param fd       Socket to set
+ *
+ * \return         0 if successful, or a non-zero error code
+ */
+int net_set_block( int fd );
+
+/**
+ * \brief          Set the socket non-blocking
+ *
+ * \param fd       Socket to set
+ *
+ * \return         0 if successful, or a non-zero error code
+ */
+int net_set_nonblock( int fd );
+
+/**
+ * \brief          Portable usleep helper
+ *
+ * \param usec     Amount of microseconds to sleep
+ *
+ * \note           Real amount of time slept will not be less than
+ *                 select()'s timeout granularity (typically, 10ms).
+ */
+void net_usleep( unsigned long usec );
+
+/**
+ * \brief          Read at most 'len' characters. If no error occurs,
+ *                 the actual amount read is returned.
+ *
+ * \param ctx      Socket
+ * \param buf      The buffer to write to
+ * \param len      Maximum length of the buffer
+ *
+ * \return         This function returns the number of bytes received,
+ *                 or a non-zero error code; POLARSSL_ERR_NET_WANT_READ
+ *                 indicates read() is blocking.
+ */
+int net_recv( void *ctx, unsigned char *buf, size_t len );
+
+/**
+ * \brief          Write at most 'len' characters. If no error occurs,
+ *                 the actual amount read is returned.
+ *
+ * \param ctx      Socket
+ * \param buf      The buffer to read from
+ * \param len      The length of the buffer
+ *
+ * \return         This function returns the number of bytes sent,
+ *                 or a non-zero error code; POLARSSL_ERR_NET_WANT_WRITE
+ *                 indicates write() is blocking.
+ */
+int net_send( void *ctx, const unsigned char *buf, size_t len );
+
+/**
+ * \brief          Gracefully shutdown the connection
+ *
+ * \param fd       The socket to close
+ */
+void net_close( int fd );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* net.h */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/polarssl/oid.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,572 @@
+/**
+ * \file oid.h
+ *
+ * \brief Object Identifier (OID) database
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#include "asn1.h"
+#include "pk.h"
+
+#include <stddef.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_UNIQUE_IDENTIFIER        OID_AT "\x2D" /**< id-at-uniqueIdentifier AttributType:= {id-at 45} */
+#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 } */
+
+/* RFC 4055 */
+#define OID_RSASSA_PSS          OID_PKCS1 "\x0a" /**< id-RSASSA-PSS ::= { pkcs-1 10 } */
+#define OID_MGF1                OID_PKCS1 "\x08" /**< id-mgf1 ::= { pkcs-1 8 } */
+
+/*
+ * 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_TOO_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/include/polarssl/openssl.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,149 @@
+/**
+ * \file openssl.h
+ *
+ * \brief OpenSSL wrapper (definitions, inline functions).
+ *
+ * \deprecated Use native mbed TLS functions instead
+ *
+ *  Copyright (C) 2006-2010, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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
+ */
+
+#if ! defined(POLARSSL_DEPRECATED_REMOVED)
+
+#if defined(POLARSSL_DEPRECATED_WARNING)
+#warning "Including openssl.h is deprecated"
+#endif
+
+#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 */
+#endif /* POLARSSL_DEPRECATED_REMOVED */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/polarssl/padlock.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,106 @@
+/**
+ * \file padlock.h
+ *
+ * \brief VIA PadLock ACE for HW encryption/decryption supported by some
+ *        processors
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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/include/polarssl/pbkdf2.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,91 @@
+/**
+ * \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, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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 "md.h"
+
+#include <stddef.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
+
+#if ! defined(POLARSSL_DEPRECATED_REMOVED)
+#if defined(POLARSSL_DEPRECATED_WARNING)
+#define DEPRECATED    __attribute__((deprecated))
+#else
+#define DEPRECATED
+#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_ERR_xxx 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 ) DEPRECATED;
+
+/**
+ * \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 ) DEPRECATED;
+#undef DEPRECATED
+#endif /* POLARSSL_DEPRECATED_REMOVED */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* pbkdf2.h */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/polarssl/pem.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,131 @@
+/**
+ * \file pem.h
+ *
+ * \brief Privacy Enhanced Mail (PEM) decoding
+ *
+ *  Copyright (C) 2006-2013, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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 <stddef.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/include/polarssl/pk.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,651 @@
+/**
+ * \file pk.h
+ *
+ * \brief Public Key abstraction layer
+ *
+ *  Copyright (C) 2006-2013, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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,
+    POLARSSL_PK_RSASSA_PSS,
+} pk_type_t;
+
+/**
+ * \brief           Options for RSASSA-PSS signature verification.
+ *                  See \c rsa_rsassa_pss_verify_ext()
+ */
+typedef struct
+{
+    md_type_t mgf1_hash_id;
+    int expected_salt_len;
+
+} pk_rsassa_pss_options;
+
+/**
+ * \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 );
+
+    /** Check public-private key pair */
+    int (*check_pair_func)( const void *pub, const void *prv );
+
+    /** Allocate a new context */
+    void * (*ctx_alloc_func)( void );
+
+    /** Free the given context */
+    void (*ctx_free_func)( void *ctx );
+
+    /** Interface with the debug module */
+    void (*debug_func)( const void *ctx, 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 (including padding if relevant).
+ *
+ * \param ctx       PK context to use
+ * \param md_alg    Hash algorithm used (see notes)
+ * \param hash      Hash of the message to sign
+ * \param hash_len  Hash length or 0 (see notes)
+ * \param sig       Signature to verify
+ * \param sig_len   Signature length
+ *
+ * \return          0 on success (signature is valid),
+ *                  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            For RSA keys, the default padding type is PKCS#1 v1.5.
+ *                  Use \c pk_verify_ext( POLARSSL_PK_RSASSA_PSS, ... )
+ *                  to verify RSASSA_PSS signatures.
+ *
+ * \note            If hash_len is 0, then the length associated with md_alg
+ *                  is used instead, or an error returned if it is invalid.
+ *
+ * \note            md_alg may be 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           Verify signature, with options.
+ *                  (Includes verification of the padding depending on type.)
+ *
+ * \param type      Signature type (inc. possible padding type) to verify
+ * \param options   Pointer to type-specific options, or NULL
+ * \param ctx       PK context to use
+ * \param md_alg    Hash algorithm used (see notes)
+ * \param hash      Hash of the message to sign
+ * \param hash_len  Hash length or 0 (see notes)
+ * \param sig       Signature to verify
+ * \param sig_len   Signature length
+ *
+ * \return          0 on success (signature is valid),
+ *                  POLARSSL_ERR_PK_TYPE_MISMATCH if the PK context can't be
+ *                  used for this type of signatures,
+ *                  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
+ *
+ * \note            If type is POLARSSL_PK_RSASSA_PSS, then options must point
+ *                  to a pk_rsassa_pss_options structure,
+ *                  otherwise it must be NULL.
+ */
+int pk_verify_ext( pk_type_t type, const void *options,
+                   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, including padding if relevant.
+ *
+ * \param ctx       PK context to use
+ * \param md_alg    Hash algorithm used (see notes)
+ * \param hash      Hash of the message to sign
+ * \param hash_len  Hash length or 0 (see notes)
+ * \param sig       Place to write the signature
+ * \param sig_len   Number of bytes written
+ * \param f_rng     RNG function
+ * \param p_rng     RNG parameter
+ *
+ * \return          0 on success, or a specific error code.
+ *
+ * \note            For RSA keys, the default padding type is PKCS#1 v1.5.
+ *                  There is no interface in the PK module to make RSASSA-PSS
+ *                  signatures yet.
+ *
+ * \note            If hash_len is 0, then the length associated with md_alg
+ *                  is used instead, or an error returned if it is invalid.
+ *
+ * \note            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 (including padding if relevant).
+ *
+ * \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
+ *
+ * \note            For RSA keys, the default padding type is PKCS#1 v1.5.
+ *
+ * \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 (including padding if relevant).
+ *
+ * \param ctx       PK context to use
+ * \param input     Message to encrypt
+ * \param ilen      Message size
+ * \param output    Encrypted output
+ * \param olen      Encrypted output length
+ * \param osize     Size of the output buffer
+ * \param f_rng     RNG function
+ * \param p_rng     RNG parameter
+ *
+ * \note            For RSA keys, the default padding type is PKCS#1 v1.5.
+ *
+ * \return          0 on success, or a specific error code.
+ */
+int 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           Check if a public-private pair of keys matches.
+ *
+ * \param pub       Context holding a public key.
+ * \param prv       Context holding a private (and public) key.
+ *
+ * \return          0 on success or POLARSSL_ERR_PK_BAD_INPUT_DATA
+ */
+int pk_check_pair( const pk_context *pub, const pk_context *prv );
+
+/**
+ * \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 */
+
+/*
+ * Internal module functions. You probably do not want to use these unless you
+ * know you do.
+ */
+#if defined(POLARSSL_FS_IO)
+int pk_load_file( const char *path, unsigned char **buf, size_t *n );
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* POLARSSL_PK_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/polarssl/pk_wrap.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,61 @@
+/**
+ * \file pk.h
+ *
+ * \brief Public Key abstraction layer: wrapper functions
+ *
+ *  Copyright (C) 2006-2013, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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/include/polarssl/pkcs11.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,172 @@
+/**
+ * \file pkcs11.h
+ *
+ * \brief Wrapper for PKCS#11 library libpkcs11-helper
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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 mbed TLS 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/include/polarssl/pkcs12.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,121 @@
+/**
+ * \file pkcs12.h
+ *
+ * \brief PKCS#12 Personal Information Exchange Syntax
+ *
+ *  Copyright (C) 2006-2013, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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 "md.h"
+#include "cipher.h"
+#include "asn1.h"
+
+#include <stddef.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_ERR_xxx 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_ERR_xxx 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/include/polarssl/pkcs5.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,102 @@
+/**
+ * \file pkcs5.h
+ *
+ * \brief PKCS#5 functions
+ *
+ * \author Mathias Olsson <mathias@kompetensum.com>
+ *
+ *  Copyright (C) 2006-2013, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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 "asn1.h"
+#include "md.h"
+
+#include <stddef.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_ERR_xxx 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_ERR_xxx 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/include/polarssl/platform.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,206 @@
+/**
+ * \file platform.h
+ *
+ * \brief mbed TLS Platform abstraction layer
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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
+
+/* Temporary compatibility hack for to keep MEMORY_C working */
+#if defined(POLARSSL_MEMORY_C) && !defined(POLARSSL_PLATFORM_MEMORY)
+#define POLARSSL_PLATFORM_MEMORY
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \name SECTION: Module settings
+ *
+ * The configuration options you can set for this module are in this section.
+ * Either change them in config.h or define them on the compiler command line.
+ * \{
+ */
+
+#if !defined(POLARSSL_PLATFORM_NO_STD_FUNCTIONS)
+#include <stdio.h>
+#include <stdlib.h>
+#if !defined(POLARSSL_PLATFORM_STD_SNPRINTF)
+#define POLARSSL_PLATFORM_STD_SNPRINTF   snprintf /**< Default snprintf to use  */
+#endif
+#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
+#if !defined(POLARSSL_PLATFORM_STD_EXIT)
+#define POLARSSL_PLATFORM_STD_EXIT      exit /**< 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)
+#if defined(POLARSSL_PLATFORM_FREE_MACRO) && \
+    defined(POLARSSL_PLATFORM_MALLOC_MACRO)
+#define polarssl_free       POLARSSL_PLATFORM_FREE_MACRO
+#define polarssl_malloc     POLARSSL_PLATFORM_MALLOC_MACRO
+#else
+/* For size_t */
+#include <stddef.h>
+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 * ) );
+#endif /* POLARSSL_PLATFORM_FREE_MACRO && POLARSSL_PLATFORM_MALLOC_MACRO */
+#else /* !POLARSSL_PLATFORM_MEMORY */
+#define polarssl_free       free
+#define polarssl_malloc     malloc
+#endif /* POLARSSL_PLATFORM_MEMORY && !POLARSSL_PLATFORM_{FREE,MALLOC}_MACRO */
+
+/*
+ * The function pointers for fprintf
+ */
+#if defined(POLARSSL_PLATFORM_FPRINTF_ALT)
+/* We need FILE * */
+#include <stdio.h>
+extern int (*polarssl_fprintf)( FILE *stream, const char *format, ... );
+
+/**
+ * \brief   Set your own fprintf function pointer
+ *
+ * \param fprintf_func   the fprintf function implementation
+ *
+ * \return              0
+ */
+int platform_set_fprintf( int (*fprintf_func)( FILE *stream, const char *,
+                                               ... ) );
+#else
+#if defined(POLARSSL_PLATFORM_FPRINTF_MACRO)
+#define polarssl_fprintf    POLARSSL_PLATFORM_FPRINTF_MACRO
+#else
+#define polarssl_fprintf    fprintf
+#endif /* POLARSSL_PLATFORM_FPRINTF_MACRO */
+#endif /* POLARSSL_PLATFORM_FPRINTF_ALT */
+
+/*
+ * 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 */
+#if defined(POLARSSL_PLATFORM_PRINTF_MACRO)
+#define polarssl_printf     POLARSSL_PLATFORM_PRINTF_MACRO
+#else
+#define polarssl_printf     printf
+#endif /* POLARSSL_PLATFORM_PRINTF_MACRO */
+#endif /* POLARSSL_PLATFORM_PRINTF_ALT */
+
+/*
+ * The function pointers for snprintf
+ */
+#if defined(POLARSSL_PLATFORM_SNPRINTF_ALT)
+extern int (*polarssl_snprintf)( char * s, size_t n, const char * format, ... );
+
+/**
+ * \brief   Set your own snprintf function pointer
+ *
+ * \param snprintf_func   the snprintf function implementation
+ *
+ * \return              0
+ */
+int platform_set_snprintf( int (*snprintf_func)( char * s, size_t n,
+                                                 const char * format, ... ) );
+#else /* POLARSSL_PLATFORM_SNPRINTF_ALT */
+#if defined(POLARSSL_PLATFORM_SNPRINTF_MACRO)
+#define polarssl_snprintf   POLARSSL_PLATFORM_SNPRINTF_MACRO
+#else
+#define polarssl_snprintf   snprintf
+#endif /* POLARSSL_PLATFORM_SNPRINTF_MACRO */
+#endif /* POLARSSL_PLATFORM_SNPRINTF_ALT */
+
+/*
+ * The function pointers for exit
+ */
+#if defined(POLARSSL_PLATFORM_EXIT_ALT)
+extern void (*polarssl_exit)( int status );
+
+/**
+ * \brief   Set your own exit function pointer
+ *
+ * \param exit_func   the exit function implementation
+ *
+ * \return              0
+ */
+int platform_set_exit( void (*exit_func)( int status ) );
+#else
+#if defined(POLARSSL_PLATFORM_EXIT_MACRO)
+#define polarssl_exit   POLARSSL_PLATFORM_EXIT_MACRO
+#else
+#define polarssl_exit   exit
+#endif /* POLARSSL_PLATFORM_EXIT_MACRO */
+#endif /* POLARSSL_PLATFORM_EXIT_ALT */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* platform.h */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/polarssl/ripemd160.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,202 @@
+/**
+ * \file ripemd160.h
+ *
+ * \brief RIPE MD-160 message digest
+ *
+ *  Copyright (C) 2014-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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 <stddef.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          Initialize RIPEMD-160 context
+ *
+ * \param ctx      RIPEMD-160 context to be initialized
+ */
+void ripemd160_init( ripemd160_context *ctx );
+
+/**
+ * \brief          Clear RIPEMD-160 context
+ *
+ * \param ctx      RIPEMD-160 context to be cleared
+ */
+void ripemd160_free( ripemd160_context *ctx );
+
+/**
+ * \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/include/polarssl/rsa.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,654 @@
+/**
+ * \file rsa.h
+ *
+ * \brief The RSA public-key cryptosystem
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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 library's 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
+
+#define RSA_SALT_LEN_ANY    -1
+
+/*
+ * The above constants may be used even if the RSA module is compile out,
+ * eg for alternative (PKCS#11) RSA implemenations in the PK layers.
+ */
+#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  */
+
+    mpi Vi;                     /*!<  cached blinding value     */
+    mpi Vf;                     /*!<  cached un-blinding value  */
+
+    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.
+ *
+ * \note           Choice of padding mode is strictly enforced for private key
+ *                 operations, since there might be security concerns in
+ *                 mixing padding modes. For public key operations it's merely
+ *                 a default value, which can be overriden by calling specific
+ *                 rsa_rsaes_xxx or rsa_rsassa_xxx functions.
+ *
+ * \note           The chosen hash is always used for OEAP encryption.
+ *                 For PSS signatures, it's always used for making signatures,
+ *                 but can be overriden (and always is, if set to
+ *                 POLARSSL_MD_NONE) for verifying them.
+ */
+void rsa_init( rsa_context *ctx,
+               int padding,
+               int hash_id);
+
+/**
+ * \brief          Set padding for an already initialized RSA context
+ *                 See \c rsa_init() for details.
+ *
+ * \param ctx      RSA context to be set
+ * \param padding  RSA_PKCS_V15 or RSA_PKCS_V21
+ * \param hash_id  RSA_PKCS_V21 hash identifier
+ */
+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          Check a public-private RSA key pair.
+ *                 Check each of the contexts, and make sure they match.
+ *
+ * \param pub      RSA context holding the public key
+ * \param prv      RSA context holding the private key
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ */
+int rsa_check_pub_priv( const rsa_context *pub, const rsa_context *prv );
+
+/**
+ * \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, see comments on
+ * \note           \c rsa_rsassa_pss_sign() for details on md_alg and hash_id.
+ */
+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           The hash_id in the RSA context is the one used for the
+ *                 encoding. md_alg 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, see comments on
+ *                 \c rsa_rsassa_pss_verify() about md_alg and hash_id.
+ */
+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)
+ *                 (This is the "simple" version.)
+ *
+ * \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           The hash_id in the RSA context is the one used for the
+ *                 verification. md_alg 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. If hash_id in the RSA context is
+ *                 unset, the md_alg from the function call is used.
+ */
+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          Perform a PKCS#1 v2.1 PSS verification (RSASSA-PSS-VERIFY)
+ *                 (This is the version with "full" options.)
+ *
+ * \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 mgf1_hash_id message digest used for mask generation
+ * \param expected_salt_len Length of the salt used in padding, use
+ *                 RSA_SALT_LEN_ANY to accept any salt length
+ * \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           The hash_id in the RSA context is ignored.
+ */
+int rsa_rsassa_pss_verify_ext( 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,
+                               md_type_t mgf1_hash_id,
+                               int expected_salt_len,
+                               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/include/polarssl/sha1.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,198 @@
+/**
+ * \file sha1.h
+ *
+ * \brief SHA-1 cryptographic hash function
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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 <stddef.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          Initialize SHA-1 context
+ *
+ * \param ctx      SHA-1 context to be initialized
+ */
+void sha1_init( sha1_context *ctx );
+
+/**
+ * \brief          Clear SHA-1 context
+ *
+ * \param ctx      SHA-1 context to be cleared
+ */
+void sha1_free( sha1_context *ctx );
+
+/**
+ * \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/include/polarssl/sha256.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,206 @@
+/**
+ * \file sha256.h
+ *
+ * \brief SHA-224 and SHA-256 cryptographic hash function
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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 <stddef.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          Initialize SHA-256 context
+ *
+ * \param ctx      SHA-256 context to be initialized
+ */
+void sha256_init( sha256_context *ctx );
+
+/**
+ * \brief          Clear SHA-256 context
+ *
+ * \param ctx      SHA-256 context to be cleared
+ */
+void sha256_free( sha256_context *ctx );
+
+/**
+ * \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/include/polarssl/sha512.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,205 @@
+/**
+ * \file sha512.h
+ *
+ * \brief SHA-384 and SHA-512 cryptographic hash function
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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 <stddef.h>
+
+#if defined(_MSC_VER) || defined(__WATCOMC__)
+  typedef unsigned __int64 uint64_t;
+#else
+  #include <inttypes.h>
+#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          Initialize SHA-512 context
+ *
+ * \param ctx      SHA-512 context to be initialized
+ */
+void sha512_init( sha512_context *ctx );
+
+/**
+ * \brief          Clear SHA-512 context
+ *
+ * \param ctx      SHA-512 context to be cleared
+ */
+void sha512_free( sha512_context *ctx );
+
+/**
+ * \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/include/polarssl/ssl.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,2009 @@
+/**
+ * \file ssl.h
+ *
+ * \brief SSL/TLS functions.
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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
+
+/* Temporary compatibility trick for the current stable branch */
+#if !defined(POLARSSL_SSL_DISABLE_RENEGOTIATION)
+#define POLARSSL_SSL_RENEGOTIATION
+#endif
+
+#include "net.h"
+#include "bignum.h"
+#include "ecp.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). */
+#define POLARSSL_ERR_SSL_WAITING_SERVER_HELLO_RENEGO       -0x6B00  /**< Unexpected message at ServerHello in renegotiation. */
+#define POLARSSL_ERR_SSL_NO_USABLE_CIPHERSUITE             -0x6A80  /**< None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages). */
+
+/*
+ * 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_IS_NOT_FALLBACK             0
+#define SSL_IS_FALLBACK                 1
+
+#define SSL_EXTENDED_MS_DISABLED        0
+#define SSL_EXTENDED_MS_ENABLED         1
+
+#define SSL_ETM_DISABLED                0
+#define SSL_ETM_ENABLED                 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_RENEGOTIATION_NOT_ENFORCED  -1
+#define SSL_RENEGO_MAX_RECORDS_DEFAULT  16
+
+#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
+
+#define SSL_CBC_RECORD_SPLITTING_DISABLED   -1
+#define SSL_CBC_RECORD_SPLITTING_ENABLED     0
+
+#define SSL_ARC4_ENABLED                0
+#define SSL_ARC4_DISABLED               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, or
+ * if you're using the Max Fragment Length extension and you know all your
+ * peers are using it too!
+ */
+#if !defined(SSL_MAX_CONTENT_LEN)
+#define SSL_MAX_CONTENT_LEN         16384   /**< Size of the input / output buffer */
+#endif
+
+/* \} name SECTION: Module settings */
+
+/*
+ * Allow extra bytes for record, authentication and encryption overhead:
+ * counter (8) + header (5) + IV(16) + MAC (16-48) + padding (0-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
+
+#if defined(POLARSSL_RC4_C) || defined(POLARSSL_CIPHER_MODE_CBC)
+/* Ciphersuites using HMAC */
+#if defined(POLARSSL_SHA512_C)
+#define SSL_MAC_ADD                 48  /* SHA-384 used for HMAC */
+#elif defined(POLARSSL_SHA256_C)
+#define SSL_MAC_ADD                 32  /* SHA-256 used for HMAC */
+#else
+#define SSL_MAC_ADD                 20  /* SHA-1   used for HMAC */
+#endif
+#else
+/* AEAD ciphersuites: GCM and CCM use a 128 bits tag */
+#define SSL_MAC_ADD                 16
+#endif
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+#define SSL_PADDING_ADD            256
+#else
+#define SSL_PADDING_ADD              0
+#endif
+
+#define SSL_BUFFER_LEN  ( SSL_MAX_CONTENT_LEN               \
+                        + SSL_COMPRESSION_ADD               \
+                        + 29 /* counter + header + IV */    \
+                        + SSL_MAC_ADD                       \
+                        + SSL_PADDING_ADD                   \
+                        )
+
+/*
+ * Length of the verify data for secure renegotiation
+ */
+#if defined(POLARSSL_SSL_PROTO_SSL3)
+#define SSL_VERIFY_DATA_MAX_LEN 36
+#else
+#define SSL_VERIFY_DATA_MAX_LEN 12
+#endif
+
+/*
+ * Signaling ciphersuite values (SCSV)
+ */
+#define SSL_EMPTY_RENEGOTIATION_INFO    0xFF   /**< renegotiation info ext */
+#define SSL_FALLBACK_SCSV               0x5600 /**< draft-ietf-tls-downgrade-scsv-00 */
+
+/*
+ * 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_INAPROPRIATE_FALLBACK 86  /* 0x56 */
+#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_ENCRYPT_THEN_MAC            22 /* 0x16 */
+#define TLS_EXT_EXTENDED_MASTER_SECRET  0x0017 /* 23 */
+
+#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_PSK_MAX_LEN)
+#define POLARSSL_PSK_MAX_LEN            32 /* 256 bits */
+#endif
+
+/* Dummy type used only for its size */
+union _ssl_premaster_secret
+{
+#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED)
+    unsigned char _pms_rsa[48];                         /* RFC 5246 8.1.1 */
+#endif
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED)
+    unsigned char _pms_dhm[POLARSSL_MPI_MAX_SIZE];      /* RFC 5246 8.1.2 */
+#endif
+#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)
+    unsigned char _pms_ecdh[POLARSSL_ECP_MAX_BYTES];    /* RFC 4492 5.10 */
+#endif
+#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED)
+    unsigned char _pms_psk[4 + 2 * POLARSSL_PSK_MAX_LEN];       /* RFC 4279 2 */
+#endif
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED)
+    unsigned char _pms_dhe_psk[4 + POLARSSL_MPI_MAX_SIZE
+                                 + POLARSSL_PSK_MAX_LEN];       /* RFC 4279 3 */
+#endif
+#if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED)
+    unsigned char _pms_rsa_psk[52 + POLARSSL_PSK_MAX_LEN];      /* RFC 4279 4 */
+#endif
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
+    unsigned char _pms_ecdhe_psk[4 + POLARSSL_ECP_MAX_BYTES
+                                   + POLARSSL_PSK_MAX_LEN];     /* RFC 5489 2 */
+#endif
+};
+
+#define POLARSSL_PREMASTER_SIZE     sizeof( union _ssl_premaster_secret )
+
+#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 */
+
+#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
+    int encrypt_then_mac;       /*!< flag for EtM activation                */
+#endif
+};
+
+/*
+ * 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[20];          /*!<  SSL v3.0 secret (enc)   */
+    unsigned char mac_dec[20];          /*!<  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;                        /*!<  Hash algorithm for signature   */
+    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_EXTENDED_MASTER_SECRET)
+    int extended_ms;                    /*!< use Extended Master Secret? */
+#endif
+};
+
+#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         */
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+    int renego_records_seen;    /*!< Records since renego request     */
+#endif
+
+    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          */
+
+#if defined(POLARSSL_SSL_FALLBACK_SCSV) && defined(POLARSSL_SSL_CLI_C)
+    char fallback;              /*!< flag for fallback connections    */
+#endif
+#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
+    char encrypt_then_mac;      /*!< flag for encrypt-then-mac        */
+#endif
+#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET)
+    char extended_ms;           /*!< flag for extended master secret  */
+#endif
+    char arc4_disabled;         /*!< flag for disabling RC4           */
+
+    /*
+     * 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 */
+#if defined(POLARSSL_SSL_CBC_RECORD_SPLITTING)
+    signed char split_done;     /*!< flag for record splitting:
+                                     -1 disabled, 0 todo, 1 done      */
+#endif
+
+    /*
+     * 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     */
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+    int disable_renegotiation;          /*!<  enable/disable renegotiation   */
+    int renego_max_records;             /*!<  grace period for renegotiation */
+    unsigned char renego_period[8];     /*!<  value of the record counters
+                                              that triggers renegotiation    */
+#endif
+    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           */
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+    size_t verify_data_len;             /*!<  length of verify data stored   */
+    char own_verify_data[SSL_VERIFY_DATA_MAX_LEN]; /*!<  previous handshake verify data */
+    char peer_verify_data[SSL_VERIFY_DATA_MAX_LEN]; /*!<  previous handshake verify data */
+#endif
+};
+
+#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 );
+
+#if defined(POLARSSL_SSL_SRV_C)
+/**
+ * \brief          Set the session cache callbacks (server-side only)
+ *                 If not set, no session resuming is done (except if session
+ *                 tickets are enabled too).
+ *
+ *                 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 );
+#endif /* POLARSSL_SSL_SRV_C */
+
+#if defined(POLARSSL_SSL_CLI_C)
+/**
+ * \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 );
+#endif /* POLARSSL_SSL_CLI_C */
+
+/**
+ * \brief               Set the list of allowed ciphersuites and the preference
+ *                      order. First in the list has the highest preference.
+ *                      (Overrides all version specific lists)
+ *
+ *                      The ciphersuites array is not copied, and must remain
+ *                      valid for the lifetime of the ssl_context.
+ *
+ *                      Note: The server uses its own preferences
+ *                      over the preference of the 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_DEPRECATED_REMOVED)
+#if defined(POLARSSL_DEPRECATED_WARNING)
+#define DEPRECATED    __attribute__((deprecated))
+#else
+#define DEPRECATED
+#endif
+#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.
+ *
+ * \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 ) DEPRECATED;
+#endif /* POLARSSL_RSA_C */
+
+/**
+ * \brief          Set own certificate and external 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.
+ *
+ * \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 ) DEPRECATED;
+#undef DEPRECATED
+#endif /* POLARSSL_DEPRECATED_REMOVED */
+#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.
+ *
+ * \note           SSL_MINOR_VERSION_0 (SSL v3) should be avoided.
+ *
+ * \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_FALLBACK_SCSV) && defined(POLARSSL_SSL_CLI_C)
+/**
+ * \brief          Set the fallback flag (client-side only).
+ *                 (Default: SSL_IS_NOT_FALLBACK).
+ *
+ * \note           Set to SSL_IS_FALLBACK when preparing a fallback
+ *                 connection, that is a connection with max_version set to a
+ *                 lower value than the value you're willing to use. Such
+ *                 fallback connections are not recommended but are sometimes
+ *                 necessary to interoperate with buggy (version-intolerant)
+ *                 servers.
+ *
+ * \warning        You should NOT set this to SSL_IS_FALLBACK for
+ *                 non-fallback connections! This would appear to work for a
+ *                 while, then cause failures when the server is upgraded to
+ *                 support a newer TLS version.
+ *
+ * \param ssl      SSL context
+ * \param fallback SSL_IS_NOT_FALLBACK or SSL_IS_FALLBACK
+ */
+void ssl_set_fallback( ssl_context *ssl, char fallback );
+#endif /* POLARSSL_SSL_FALLBACK_SCSV && POLARSSL_SSL_CLI_C */
+
+#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
+/**
+ * \brief           Enable or disable Encrypt-then-MAC
+ *                  (Default: SSL_ETM_ENABLED)
+ *
+ * \note            This should always be enabled, it is a security
+ *                  improvement, and should not cause any interoperability
+ *                  issue (used only if the peer supports it too).
+ *
+ * \param ssl       SSL context
+ * \param etm       SSL_ETM_ENABLED or SSL_ETM_DISABLED
+ */
+void ssl_set_encrypt_then_mac( ssl_context *ssl, char etm );
+#endif /* POLARSSL_SSL_ENCRYPT_THEN_MAC */
+
+#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET)
+/**
+ * \brief           Enable or disable Extended Master Secret negotiation.
+ *                  (Default: SSL_EXTENDED_MS_ENABLED)
+ *
+ * \note            This should always be enabled, it is a security fix to the
+ *                  protocol, and should not cause any interoperability issue
+ *                  (used only if the peer supports it too).
+ *
+ * \param ssl       SSL context
+ * \param ems       SSL_EXTENDED_MS_ENABLED or SSL_EXTENDED_MS_DISABLED
+ */
+void ssl_set_extended_master_secret( ssl_context *ssl, char ems );
+#endif /* POLARSSL_SSL_EXTENDED_MASTER_SECRET */
+
+/**
+ * \brief          Disable or enable support for RC4
+ *                 (Default: SSL_ARC4_ENABLED)
+ *
+ * \note           Though the default is RC4 for compatibility reasons in the
+ *                 1.3 branch, the recommended value is SSL_ARC4_DISABLED.
+ *
+ * \note           This function will likely be removed in future versions as
+ *                 RC4 will then be disabled by default at compile time.
+ *
+ * \param ssl      SSL context
+ * \param arc4     SSL_ARC4_ENABLED or SSL_ARC4_DISABLED
+ */
+void ssl_set_arc4_support( ssl_context *ssl, char arc4 );
+
+#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         0 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
+ *                 (Default: SSL_TRUNC_HMAC_DISABLED on client,
+ *                           SSL_TRUNC_HMAC_ENABLED on server.)
+ *
+ * \param ssl      SSL context
+ * \param truncate Enable or disable (SSL_TRUNC_HMAC_ENABLED or
+ *                                    SSL_TRUNC_HMAC_DISABLED)
+ *
+ * \return         Always 0.
+ */
+int ssl_set_truncated_hmac( ssl_context *ssl, int truncate );
+#endif /* POLARSSL_SSL_TRUNCATED_HMAC */
+
+#if defined(POLARSSL_SSL_CBC_RECORD_SPLITTING)
+/**
+ * \brief          Enable / Disable 1/n-1 record splitting
+ *                 (Default: SSL_CBC_RECORD_SPLITTING_ENABLED)
+ *
+ * \note           Only affects SSLv3 and TLS 1.0, not higher versions.
+ *                 Does not affect non-CBC ciphersuites in any version.
+ *
+ * \param ssl      SSL context
+ * \param split    SSL_CBC_RECORD_SPLITTING_ENABLED or
+ *                 SSL_CBC_RECORD_SPLITTING_DISABLED
+ */
+void ssl_set_cbc_record_splitting( ssl_context *ssl, char split );
+#endif /* POLARSSL_SSL_CBC_RECORD_SPLITTING */
+
+#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         0 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 */
+
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+/**
+ * \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 );
+#endif /* POLARSSL_SSL_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 );
+
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+/**
+ * \brief          Enforce requested renegotiation.
+ *                 (Default: enforced, max_records = 16)
+ *
+ *                 When we request a renegotiation, the peer can comply or
+ *                 ignore the request. This function allows us to decide
+ *                 whether to enforce our renegotiation requests by closing
+ *                 the connection if the peer doesn't comply.
+ *
+ *                 However, records could already be in transit from the peer
+ *                 when the request is emitted. In order to increase
+ *                 reliability, we can accept a number of records before the
+ *                 expected handshake records.
+ *
+ *                 The optimal value is highly dependent on the specific usage
+ *                 scenario.
+ *
+ * \warning        On client, the grace period can only happen during
+ *                 ssl_read(), as opposed to ssl_write() and ssl_renegotiate()
+ *                 which always behave as if max_record was 0. The reason is,
+ *                 if we receive application data from the server, we need a
+ *                 place to write it, which only happens during ssl_read().
+ *
+ * \param ssl      SSL context
+ * \param max_records Use SSL_RENEGOTIATION_NOT_ENFORCED if you don't want to
+ *                 enforce renegotiation, or a non-negative value to enforce
+ *                 it but allow for a grace period of max_records records.
+ */
+void ssl_set_renegotiation_enforced( ssl_context *ssl, int max_records );
+
+/**
+ * \brief          Set record counter threshold for periodic renegotiation.
+ *                 (Default: 2^64 - 256.)
+ *
+ *                 Renegotiation is automatically triggered when a record
+ *                 counter (outgoing or ingoing) crosses the defined
+ *                 threshold. The default value is meant to prevent the
+ *                 connection from being closed when the counter is about to
+ *                 reached its maximal value (it is not allowed to wrap).
+ *
+ *                 Lower values can be used to enforce policies such as "keys
+ *                 must be refreshed every N packets with cipher X".
+ *
+ * \param ssl      SSL context
+ * \param period   The threshold value: a big-endian 64-bit number.
+ *                 Set to 2^64 - 1 to disable periodic renegotiation
+ */
+void ssl_set_renegotiation_period( ssl_context *ssl,
+                                   const unsigned char period[8] );
+#endif /* POLARSSL_SSL_RENEGOTIATION */
+
+/**
+ * \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,
+ *                 -1 if result is not available (eg because the handshake was
+ *                 aborted too early), or
+ *                 a combination of BADCERT_xxx and BADCRL_xxx flags, see
+ *                 x509.h
+ */
+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 */
+
+#if defined(POLARSSL_SSL_CLI_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 );
+#endif /* POLARSSL_SSL_CLI_C */
+
+/**
+ * \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 );
+
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+/**
+ * \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 );
+#endif /* POLARSSL_SSL_RENEGOTIATION */
+
+/**
+ * \brief          Read at most 'len' application data bytes
+ *
+ * \param ssl      SSL context
+ * \param buf      buffer that will hold the data
+ * \param len      maximum number of bytes to 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.
+ *
+ * \note           This function may write less than the number of bytes
+ *                 requested if len is greater than the maximum record length.
+ *                 For arbitrary-sized messages, it should be called in a loop.
+ */
+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          Initialize SSL session structure
+ *
+ * \param session  SSL session
+ */
+void ssl_session_init( ssl_session *session );
+
+/**
+ * \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,
+                          int *flags );
+#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/include/polarssl/ssl_cache.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,145 @@
+/**
+ * \file ssl_cache.h
+ *
+ * \brief SSL session cache implementation
+ *
+ *  Copyright (C) 2006-2013, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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/include/polarssl/ssl_ciphersuites.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,304 @@
+/**
+ * \file ssl_ciphersuites.h
+ *
+ * \brief SSL Ciphersuites for mbed TLS
+ *
+ *  Copyright (C) 2006-2013, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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! */
+
+#define TLS_RSA_WITH_AES_128_CCM                0xC09C  /**< TLS 1.2 */
+#define TLS_RSA_WITH_AES_256_CCM                0xC09D  /**< TLS 1.2 */
+#define TLS_DHE_RSA_WITH_AES_128_CCM            0xC09E  /**< TLS 1.2 */
+#define TLS_DHE_RSA_WITH_AES_256_CCM            0xC09F  /**< TLS 1.2 */
+#define TLS_RSA_WITH_AES_128_CCM_8              0xC0A0  /**< TLS 1.2 */
+#define TLS_RSA_WITH_AES_256_CCM_8              0xC0A1  /**< TLS 1.2 */
+#define TLS_DHE_RSA_WITH_AES_128_CCM_8          0xC0A2  /**< TLS 1.2 */
+#define TLS_DHE_RSA_WITH_AES_256_CCM_8          0xC0A3  /**< TLS 1.2 */
+#define TLS_PSK_WITH_AES_128_CCM                0xC0A4  /**< TLS 1.2 */
+#define TLS_PSK_WITH_AES_256_CCM                0xC0A5  /**< TLS 1.2 */
+#define TLS_DHE_PSK_WITH_AES_128_CCM            0xC0A6  /**< TLS 1.2 */
+#define TLS_DHE_PSK_WITH_AES_256_CCM            0xC0A7  /**< TLS 1.2 */
+#define TLS_PSK_WITH_AES_128_CCM_8              0xC0A8  /**< TLS 1.2 */
+#define TLS_PSK_WITH_AES_256_CCM_8              0xC0A9  /**< TLS 1.2 */
+#define TLS_DHE_PSK_WITH_AES_128_CCM_8          0xC0AA  /**< TLS 1.2 */
+#define TLS_DHE_PSK_WITH_AES_256_CCM_8          0xC0AB  /**< TLS 1.2 */
+/* The last two are named with PSK_DHE in the RFC, which looks like a typo */
+
+#define TLS_ECDHE_ECDSA_WITH_AES_128_CCM        0xC0AC  /**< TLS 1.2 */
+#define TLS_ECDHE_ECDSA_WITH_AES_256_CCM        0xC0AD  /**< TLS 1.2 */
+#define TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8      0xC0AE  /**< TLS 1.2 */
+#define TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8      0xC0AF  /**< TLS 1.2 */
+
+/* Reminder: update _ssl_premaster_secret when adding a new key exchange.
+ * Reminder: update POLARSSL_KEY_EXCHANGE__WITH_CERT__ENABLED below.
+ */
+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;
+
+#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)  || \
+    defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED)      || \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED)    || \
+    defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED)     || \
+    defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+#define POLARSSL_KEY_EXCHANGE__WITH_CERT__ENABLED
+#endif
+
+typedef struct _ssl_ciphersuite_t ssl_ciphersuite_t;
+
+#define POLARSSL_CIPHERSUITE_WEAK       0x01    /**< Weak ciphersuite flag  */
+#define POLARSSL_CIPHERSUITE_SHORT_TAG  0x02    /**< Short authentication tag,
+                                                     eg for CCM_8 */
+
+/**
+ * \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/include/polarssl/threading.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,84 @@
+/**
+ * \file threading.h
+ *
+ * \brief Threading abstraction layer
+ *
+ *  Copyright (C) 2006-2013, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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/include/polarssl/timing.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,100 @@
+/**
+ * \file timing.h
+ *
+ * \brief Portable interface to the CPU cycle counter
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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
+ *
+ * \warning        Only one alarm at a time  is supported. In a threaded
+ *                 context, this means one for the whole process, not one per
+ *                 thread.
+ */
+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/include/polarssl/version.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,112 @@
+/**
+ * \file version.h
+ *
+ * \brief Run-time version information
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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 mbed TLS 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  11
+
+/**
+ * The single version number has the following structure:
+ *    MMNNPP00
+ *    Major version | Minor version | Patch version
+ */
+#define POLARSSL_VERSION_NUMBER         0x01030B00
+#define POLARSSL_VERSION_STRING         "1.3.11"
+#define POLARSSL_VERSION_STRING_FULL    "mbed TLS 1.3.11"
+
+#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 ("mbed TLS x.y.z").
+ *
+ * \param string    The string that will receive the value. The mbed TLS 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
+ *                  mbed TLS 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", "mbed TLS modules" and "mbed TLS 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/include/polarssl/x509.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,343 @@
+/**
+ * \file x509.h
+ *
+ * \brief X.509 generic defines and structures
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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
+ * \{
+ */
+
+#if !defined(POLARSSL_X509_MAX_INTERMEDIATE_CA)
+/**
+ * Maximum number of intermediate CAs in a verification chain.
+ * That is, maximum length of the chain, excluding the end-entity certificate
+ * and the trusted root certificate.
+ *
+ * Set this to a low value to prevent an adversary from making you waste
+ * resources verifying an overlong certificate chain.
+ */
+#define POLARSSL_X509_MAX_INTERMEDIATE_CA   8
+#endif
+
+/**
+ * \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
+ * \{
+ */
+/* Reminder: update x509_crt_verify_strings[] in library/x509_crt.c */
+#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  /**< The CRL is not correctly signed by the trusted CA. */
+#define BADCRL_EXPIRED              0x20  /**< The 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 */
+#define BADCERT_KEY_USAGE         0x0800  /**< Usage does not match the keyUsage extension. */
+#define BADCERT_EXT_KEY_USAGE     0x1000  /**< Usage does not match the extendedKeyUsage extension. */
+#define BADCERT_NS_CERT_TYPE      0x2000  /**< Usage does not match the nsCertType extension. */
+/* \} 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
+
+#define X509_MAX_DN_NAME_SIZE         256 /**< Maximum value size of a DN entry */
+
+#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 );
+
+#if ! defined(POLARSSL_DEPRECATED_REMOVED)
+#if defined(POLARSSL_DEPRECATED_WARNING)
+#define DEPRECATED    __attribute__((deprecated))
+#else
+#define DEPRECATED
+#endif
+/**
+ * \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 ) DEPRECATED;
+
+/**
+ * \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 ) DEPRECATED;
+#undef DEPRECATED
+#endif /* POLARSSL_DEPRECATED_REMOVED */
+
+/**
+ * \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_alg( unsigned char **p, const unsigned char *end,
+                  x509_buf *alg, x509_buf *params );
+#if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT)
+int x509_get_rsassa_pss_params( const x509_buf *params,
+                                md_type_t *md_alg, md_type_t *mgf_md,
+                                int *salt_len );
+#endif
+int x509_get_sig( unsigned char **p, const unsigned char *end, x509_buf *sig );
+int x509_get_sig_alg( const x509_buf *sig_oid, const x509_buf *sig_params,
+                      md_type_t *md_alg, pk_type_t *pk_alg,
+                      void **sig_opts );
+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_sig_alg_gets( char *buf, size_t size, const x509_buf *sig_oid,
+                       pk_type_t pk_alg, md_type_t md_alg,
+                       const void *sig_opts );
+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/include/polarssl/x509_crl.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,173 @@
+/**
+ * \file x509_crl.h
+ *
+ * \brief X.509 certificate revocation list parsing
+ *
+ *  Copyright (C) 2006-2013, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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;            /**< CRL version (1=v1, 2=v2) */
+    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 */
+    void *sig_opts;             /**< Signature options to be passed to pk_verify_ext(), e.g. for RSASSA-PSS */
+
+    struct _x509_crl *next;
+}
+x509_crl;
+
+/**
+ * \brief          Parse a DER-encoded CRL and append it to the chained list
+ *
+ * \param chain    points to the start of the chain
+ * \param buf      buffer holding the CRL data in DER format
+ * \param buflen   size of the buffer
+ *
+ * \return         0 if successful, or a specific X509 or PEM error code
+ */
+int x509_crl_parse_der( x509_crl *chain,
+                        const unsigned char *buf, size_t buflen );
+/**
+ * \brief          Parse one or more CRLs and append them to the chained list
+ *
+ * \note           Mutliple CRLs are accepted only if using PEM format
+ *
+ * \param chain    points to the start of the chain
+ * \param buf      buffer holding the CRL data in PEM or DER format
+ * \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 append them to the chained list
+ *
+ * \note           Mutliple CRLs are accepted only if using PEM format
+ *
+ * \param chain    points to the start of the chain
+ * \param path     filename to read the CRLs from (in PEM or DER encoding)
+ *
+ * \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/include/polarssl/x509_crt.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,569 @@
+/**
+ * \file x509_crt.h
+ *
+ * \brief X.509 certificate parsing and writing
+ *
+ *  Copyright (C) 2006-2013, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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. (1=v1, 2=v2, 3=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 */
+    void *sig_opts;             /**< Signature options to be passed to pk_verify_ext(), e.g. for RSASSA-PSS */
+
+    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          Returns an informational string about the
+ *                 verification status of a certificate.
+ *
+ * \param buf      Buffer to write to
+ * \param size     Maximum size of buffer
+ * \param prefix   A line prefix
+ * \param flags    Verification flags created by x509_crt_verify()
+ *
+ * \return         The amount of data written to the buffer, or -1 in
+ *                 case of an error.
+ */
+int x509_crt_verify_info( char *buf, size_t size, const char *prefix,
+                          int flags );
+
+/**
+ * \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.
+ *
+ * \note           In case verification failed, the results can be displayed
+ *                 using \c x509_crt_verify_info()
+ *
+ * \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 BADCERT_XXX or
+ *                 BADCRL_XXX flags set,
+ *                 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=UK,O=ARM,CN=mbed TLS 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=UK,O=ARM,CN=mbed TLS 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/include/polarssl/x509_csr.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,293 @@
+/**
+ * \file x509_csr.h
+ *
+ * \brief X.509 certificate signing request parsing and writing
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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;            /**< CSR version (1=v1). */
+
+    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 */
+    void *sig_opts;         /**< Signature options to be passed to pk_verify_ext(), e.g. for RSASSA-PSS */
+}
+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) in DER format
+ *
+ * \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 error code
+ */
+int x509_csr_parse_der( x509_csr *csr,
+                        const unsigned char *buf, size_t buflen );
+
+/**
+ * \brief          Load a Certificate Signing Request (CSR), DER or PEM format
+ *
+ * \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 length of the string written (exluding the terminating
+ *                 null byte), or a negative value 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=UK,O=ARM,CN=mbed TLS 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/include/polarssl/xtea.h	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,147 @@
+/**
+ * \file xtea.h
+ *
+ * \brief XTEA block cipher (32-bit)
+ *
+ *  Copyright (C) 2006-2013, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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 <stddef.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          Initialize XTEA context
+ *
+ * \param ctx      XTEA context to be initialized
+ */
+void xtea_init( xtea_context *ctx );
+
+/**
+ * \brief          Clear XTEA context
+ *
+ * \param ctx      XTEA context to be cleared
+ */
+void xtea_free( xtea_context *ctx );
+
+/**
+ * \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/polarssl/aes.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,1453 @@
+/*
+ *  FIPS-197 compliant AES implementation
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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 <string.h>
+
+#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_SELF_TEST)
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdio.h>
+#define polarssl_printf printf
+#endif /* POLARSSL_PLATFORM_C */
+#endif /* POLARSSL_SELF_TEST */
+
+#if !defined(POLARSSL_AES_ALT)
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+/*
+ * 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)       ) & 0xFF );    \
+    (b)[(i) + 1] = (unsigned char) ( ( (n) >>  8 ) & 0xFF );    \
+    (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF );    \
+    (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF );    \
+}
+#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 */
+
+void aes_init( aes_context *ctx )
+{
+    memset( ctx, 0, sizeof( aes_context ) );
+}
+
+void aes_free( aes_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    polarssl_zeroize( ctx, sizeof( aes_context ) );
+}
+
+/*
+ * 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;
+    }
+
+    return( 0 );
+}
+
+/*
+ * AES key schedule (decryption)
+ */
+int aes_setkey_dec( aes_context *ctx, const unsigned char *key,
+                    unsigned int keysize )
+{
+    int i, j, ret;
+    aes_context cty;
+    uint32_t *RK;
+    uint32_t *SK;
+
+    aes_init( &cty );
+
+#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;
+
+    /* Also checks keysize */
+    if( ( ret = aes_setkey_enc( &cty, key, keysize ) ) != 0 )
+        goto exit;
+
+    ctx->nr = cty.nr;
+
+#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 exit;
+    }
+#endif
+
+    SK = cty.rk + cty.nr * 4;
+
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+
+    for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 )
+    {
+        for( j = 0; j < 4; j++, SK++ )
+        {
+            *RK++ = 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++;
+
+exit:
+    aes_free( &cty );
+
+    return( ret );
+}
+
+#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
+ */
+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)
+/*
+ * 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 ret = 0, 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 );
+    aes_init( &ctx );
+
+    /*
+     * 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" );
+
+                ret = 1;
+                goto exit;
+            }
+        }
+        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" );
+
+                ret = 1;
+                goto exit;
+            }
+        }
+
+        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" );
+
+                ret = 1;
+                goto exit;
+            }
+        }
+        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" );
+
+                ret = 1;
+                goto exit;
+            }
+        }
+
+        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" );
+
+                ret = 1;
+                goto exit;
+            }
+        }
+        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" );
+
+                ret = 1;
+                goto exit;
+            }
+        }
+
+        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" );
+
+                ret = 1;
+                goto exit;
+            }
+        }
+        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" );
+
+                ret = 1;
+                goto exit;
+            }
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+    ret = 0;
+
+exit:
+    aes_free( &ctx );
+
+    return( ret );
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_AES_C */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/polarssl/aesni.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,462 @@
+/*
+ *  AES-NI support functions
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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 <string.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\t"
+             "cpuid             \n\t"
+             : "=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\t" // load input
+         "movdqu    (%1), %%xmm1    \n\t" // load round key 0
+         "pxor      %%xmm1, %%xmm0  \n\t" // round 0
+         "addq      $16, %1         \n\t" // point to next round key
+         "subl      $1, %0          \n\t" // normal rounds = nr - 1
+         "test      %2, %2          \n\t" // mode?
+         "jz        2f              \n\t" // 0 = decrypt
+
+         "1:                        \n\t" // encryption loop
+         "movdqu    (%1), %%xmm1    \n\t" // load round key
+         AESENC     xmm1_xmm0      "\n\t" // do round
+         "addq      $16, %1         \n\t" // point to next round key
+         "subl      $1, %0          \n\t" // loop
+         "jnz       1b              \n\t"
+         "movdqu    (%1), %%xmm1    \n\t" // load round key
+         AESENCLAST xmm1_xmm0      "\n\t" // last round
+         "jmp       3f              \n\t"
+
+         "2:                        \n\t" // decryption loop
+         "movdqu    (%1), %%xmm1    \n\t"
+         AESDEC     xmm1_xmm0      "\n\t" // do round
+         "addq      $16, %1         \n\t"
+         "subl      $1, %0          \n\t"
+         "jnz       2b              \n\t"
+         "movdqu    (%1), %%xmm1    \n\t" // load round key
+         AESDECLAST xmm1_xmm0      "\n\t" // last round
+
+         "3:                        \n\t"
+         "movdqu    %%xmm0, (%4)    \n\t" // export output
+         :
+         : "r" (ctx->nr), "r" (ctx->rk), "r" (mode), "r" (input), "r" (output)
+         : "memory", "cc", "xmm0", "xmm1" );
+
+
+    return( 0 );
+}
+
+/*
+ * GCM multiplication: c = a times b in GF(2^128)
+ * Based on [CLMUL-WP] algorithms 1 (with equation 27) and 5.
+ */
+void aesni_gcm_mult( unsigned char c[16],
+                     const unsigned char a[16],
+                     const unsigned char b[16] )
+{
+    unsigned char aa[16], bb[16], cc[16];
+    size_t i;
+
+    /* The inputs are in big-endian order, so byte-reverse them */
+    for( i = 0; i < 16; i++ )
+    {
+        aa[i] = a[15 - i];
+        bb[i] = b[15 - i];
+    }
+
+    asm( "movdqu (%0), %%xmm0               \n\t" // a1:a0
+         "movdqu (%1), %%xmm1               \n\t" // b1:b0
+
+         /*
+          * Caryless multiplication xmm2:xmm1 = xmm0 * xmm1
+          * using [CLMUL-WP] algorithm 1 (p. 13).
+          */
+         "movdqa %%xmm1, %%xmm2             \n\t" // copy of b1:b0
+         "movdqa %%xmm1, %%xmm3             \n\t" // same
+         "movdqa %%xmm1, %%xmm4             \n\t" // same
+         PCLMULQDQ xmm0_xmm1 ",0x00         \n\t" // a0*b0 = c1:c0
+         PCLMULQDQ xmm0_xmm2 ",0x11         \n\t" // a1*b1 = d1:d0
+         PCLMULQDQ xmm0_xmm3 ",0x10         \n\t" // a0*b1 = e1:e0
+         PCLMULQDQ xmm0_xmm4 ",0x01         \n\t" // a1*b0 = f1:f0
+         "pxor %%xmm3, %%xmm4               \n\t" // e1+f1:e0+f0
+         "movdqa %%xmm4, %%xmm3             \n\t" // same
+         "psrldq $8, %%xmm4                 \n\t" // 0:e1+f1
+         "pslldq $8, %%xmm3                 \n\t" // e0+f0:0
+         "pxor %%xmm4, %%xmm2               \n\t" // d1:d0+e1+f1
+         "pxor %%xmm3, %%xmm1               \n\t" // c1+e0+f1:c0
+
+         /*
+          * Now shift the result one bit to the left,
+          * taking advantage of [CLMUL-WP] eq 27 (p. 20)
+          */
+         "movdqa %%xmm1, %%xmm3             \n\t" // r1:r0
+         "movdqa %%xmm2, %%xmm4             \n\t" // r3:r2
+         "psllq $1, %%xmm1                  \n\t" // r1<<1:r0<<1
+         "psllq $1, %%xmm2                  \n\t" // r3<<1:r2<<1
+         "psrlq $63, %%xmm3                 \n\t" // r1>>63:r0>>63
+         "psrlq $63, %%xmm4                 \n\t" // r3>>63:r2>>63
+         "movdqa %%xmm3, %%xmm5             \n\t" // r1>>63:r0>>63
+         "pslldq $8, %%xmm3                 \n\t" // r0>>63:0
+         "pslldq $8, %%xmm4                 \n\t" // r2>>63:0
+         "psrldq $8, %%xmm5                 \n\t" // 0:r1>>63
+         "por %%xmm3, %%xmm1                \n\t" // r1<<1|r0>>63:r0<<1
+         "por %%xmm4, %%xmm2                \n\t" // r3<<1|r2>>62:r2<<1
+         "por %%xmm5, %%xmm2                \n\t" // r3<<1|r2>>62:r2<<1|r1>>63
+
+         /*
+          * Now reduce modulo the GCM polynomial x^128 + x^7 + x^2 + x + 1
+          * using [CLMUL-WP] algorithm 5 (p. 20).
+          * Currently xmm2:xmm1 holds x3:x2:x1:x0 (already shifted).
+          */
+         /* Step 2 (1) */
+         "movdqa %%xmm1, %%xmm3             \n\t" // x1:x0
+         "movdqa %%xmm1, %%xmm4             \n\t" // same
+         "movdqa %%xmm1, %%xmm5             \n\t" // same
+         "psllq $63, %%xmm3                 \n\t" // x1<<63:x0<<63 = stuff:a
+         "psllq $62, %%xmm4                 \n\t" // x1<<62:x0<<62 = stuff:b
+         "psllq $57, %%xmm5                 \n\t" // x1<<57:x0<<57 = stuff:c
+
+         /* Step 2 (2) */
+         "pxor %%xmm4, %%xmm3               \n\t" // stuff:a+b
+         "pxor %%xmm5, %%xmm3               \n\t" // stuff:a+b+c
+         "pslldq $8, %%xmm3                 \n\t" // a+b+c:0
+         "pxor %%xmm3, %%xmm1               \n\t" // x1+a+b+c:x0 = d:x0
+
+         /* Steps 3 and 4 */
+         "movdqa %%xmm1,%%xmm0              \n\t" // d:x0
+         "movdqa %%xmm1,%%xmm4              \n\t" // same
+         "movdqa %%xmm1,%%xmm5              \n\t" // same
+         "psrlq $1, %%xmm0                  \n\t" // e1:x0>>1 = e1:e0'
+         "psrlq $2, %%xmm4                  \n\t" // f1:x0>>2 = f1:f0'
+         "psrlq $7, %%xmm5                  \n\t" // g1:x0>>7 = g1:g0'
+         "pxor %%xmm4, %%xmm0               \n\t" // e1+f1:e0'+f0'
+         "pxor %%xmm5, %%xmm0               \n\t" // e1+f1+g1:e0'+f0'+g0'
+         // e0'+f0'+g0' is almost e0+f0+g0, ex\tcept for some missing
+         // bits carried from d. Now get those\t bits back in.
+         "movdqa %%xmm1,%%xmm3              \n\t" // d:x0
+         "movdqa %%xmm1,%%xmm4              \n\t" // same
+         "movdqa %%xmm1,%%xmm5              \n\t" // same
+         "psllq $63, %%xmm3                 \n\t" // d<<63:stuff
+         "psllq $62, %%xmm4                 \n\t" // d<<62:stuff
+         "psllq $57, %%xmm5                 \n\t" // d<<57:stuff
+         "pxor %%xmm4, %%xmm3               \n\t" // d<<63+d<<62:stuff
+         "pxor %%xmm5, %%xmm3               \n\t" // missing bits of d:stuff
+         "psrldq $8, %%xmm3                 \n\t" // 0:missing bits of d
+         "pxor %%xmm3, %%xmm0               \n\t" // e1+f1+g1:e0+f0+g0
+         "pxor %%xmm1, %%xmm0               \n\t" // h1:h0
+         "pxor %%xmm2, %%xmm0               \n\t" // x3+h1:x2+h0
+
+         "movdqu %%xmm0, (%2)               \n\t" // done
+         :
+         : "r" (aa), "r" (bb), "r" (cc)
+         : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" );
+
+    /* Now byte-reverse the outputs */
+    for( i = 0; i < 16; i++ )
+        c[i] = cc[15 - i];
+
+    return;
+}
+
+/*
+ * Compute decryption round keys from encryption round keys
+ */
+void aesni_inverse_key( unsigned char *invkey,
+                        const unsigned char *fwdkey, int nr )
+{
+    unsigned char *ik = invkey;
+    const unsigned char *fk = fwdkey + 16 * nr;
+
+    memcpy( ik, fk, 16 );
+
+    for( fk -= 16, ik += 16; fk > fwdkey; fk -= 16, ik += 16 )
+        asm( "movdqu (%0), %%xmm0       \n\t"
+             AESIMC  xmm0_xmm0         "\n\t"
+             "movdqu %%xmm0, (%1)       \n\t"
+             :
+             : "r" (fk), "r" (ik)
+             : "memory", "xmm0" );
+
+    memcpy( ik, fk, 16 );
+}
+
+/*
+ * Key expansion, 128-bit case
+ */
+static void aesni_setkey_enc_128( unsigned char *rk,
+                                  const unsigned char *key )
+{
+    asm( "movdqu (%1), %%xmm0               \n\t" // copy the original key
+         "movdqu %%xmm0, (%0)               \n\t" // as round key 0
+         "jmp 2f                            \n\t" // skip auxiliary routine
+
+         /*
+          * Finish generating the next round key.
+          *
+          * On entry xmm0 is r3:r2:r1:r0 and xmm1 is X:stuff:stuff:stuff
+          * with X = rot( sub( r3 ) ) ^ RCON.
+          *
+          * On exit, xmm0 is r7:r6:r5:r4
+          * with r4 = X + r0, r5 = r4 + r1, r6 = r5 + r2, r7 = r6 + r3
+          * and those are written to the round key buffer.
+          */
+         "1:                                \n\t"
+         "pshufd $0xff, %%xmm1, %%xmm1      \n\t" // X:X:X:X
+         "pxor %%xmm0, %%xmm1               \n\t" // X+r3:X+r2:X+r1:r4
+         "pslldq $4, %%xmm0                 \n\t" // r2:r1:r0:0
+         "pxor %%xmm0, %%xmm1               \n\t" // X+r3+r2:X+r2+r1:r5:r4
+         "pslldq $4, %%xmm0                 \n\t" // etc
+         "pxor %%xmm0, %%xmm1               \n\t"
+         "pslldq $4, %%xmm0                 \n\t"
+         "pxor %%xmm1, %%xmm0               \n\t" // update xmm0 for next time!
+         "add $16, %0                       \n\t" // point to next round key
+         "movdqu %%xmm0, (%0)               \n\t" // write it
+         "ret                               \n\t"
+
+         /* Main "loop" */
+         "2:                                \n\t"
+         AESKEYGENA xmm0_xmm1 ",0x01        \n\tcall 1b \n\t"
+         AESKEYGENA xmm0_xmm1 ",0x02        \n\tcall 1b \n\t"
+         AESKEYGENA xmm0_xmm1 ",0x04        \n\tcall 1b \n\t"
+         AESKEYGENA xmm0_xmm1 ",0x08        \n\tcall 1b \n\t"
+         AESKEYGENA xmm0_xmm1 ",0x10        \n\tcall 1b \n\t"
+         AESKEYGENA xmm0_xmm1 ",0x20        \n\tcall 1b \n\t"
+         AESKEYGENA xmm0_xmm1 ",0x40        \n\tcall 1b \n\t"
+         AESKEYGENA xmm0_xmm1 ",0x80        \n\tcall 1b \n\t"
+         AESKEYGENA xmm0_xmm1 ",0x1B        \n\tcall 1b \n\t"
+         AESKEYGENA xmm0_xmm1 ",0x36        \n\tcall 1b \n\t"
+         :
+         : "r" (rk), "r" (key)
+         : "memory", "cc", "0" );
+}
+
+/*
+ * Key expansion, 192-bit case
+ */
+static void aesni_setkey_enc_192( unsigned char *rk,
+                                  const unsigned char *key )
+{
+    asm( "movdqu (%1), %%xmm0   \n\t" // copy original round key
+         "movdqu %%xmm0, (%0)   \n\t"
+         "add $16, %0           \n\t"
+         "movq 16(%1), %%xmm1   \n\t"
+         "movq %%xmm1, (%0)     \n\t"
+         "add $8, %0            \n\t"
+         "jmp 2f                \n\t" // skip auxiliary routine
+
+         /*
+          * Finish generating the next 6 quarter-keys.
+          *
+          * On entry xmm0 is r3:r2:r1:r0, xmm1 is stuff:stuff:r5:r4
+          * and xmm2 is stuff:stuff:X:stuff with X = rot( sub( r3 ) ) ^ RCON.
+          *
+          * On exit, xmm0 is r9:r8:r7:r6 and xmm1 is stuff:stuff:r11:r10
+          * and those are written to the round key buffer.
+          */
+         "1:                            \n\t"
+         "pshufd $0x55, %%xmm2, %%xmm2  \n\t" // X:X:X:X
+         "pxor %%xmm0, %%xmm2           \n\t" // X+r3:X+r2:X+r1:r4
+         "pslldq $4, %%xmm0             \n\t" // etc
+         "pxor %%xmm0, %%xmm2           \n\t"
+         "pslldq $4, %%xmm0             \n\t"
+         "pxor %%xmm0, %%xmm2           \n\t"
+         "pslldq $4, %%xmm0             \n\t"
+         "pxor %%xmm2, %%xmm0           \n\t" // update xmm0 = r9:r8:r7:r6
+         "movdqu %%xmm0, (%0)           \n\t"
+         "add $16, %0                   \n\t"
+         "pshufd $0xff, %%xmm0, %%xmm2  \n\t" // r9:r9:r9:r9
+         "pxor %%xmm1, %%xmm2           \n\t" // stuff:stuff:r9+r5:r10
+         "pslldq $4, %%xmm1             \n\t" // r2:r1:r0:0
+         "pxor %%xmm2, %%xmm1           \n\t" // xmm1 = stuff:stuff:r11:r10
+         "movq %%xmm1, (%0)             \n\t"
+         "add $8, %0                    \n\t"
+         "ret                           \n\t"
+
+         "2:                            \n\t"
+         AESKEYGENA xmm1_xmm2 ",0x01    \n\tcall 1b \n\t"
+         AESKEYGENA xmm1_xmm2 ",0x02    \n\tcall 1b \n\t"
+         AESKEYGENA xmm1_xmm2 ",0x04    \n\tcall 1b \n\t"
+         AESKEYGENA xmm1_xmm2 ",0x08    \n\tcall 1b \n\t"
+         AESKEYGENA xmm1_xmm2 ",0x10    \n\tcall 1b \n\t"
+         AESKEYGENA xmm1_xmm2 ",0x20    \n\tcall 1b \n\t"
+         AESKEYGENA xmm1_xmm2 ",0x40    \n\tcall 1b \n\t"
+         AESKEYGENA xmm1_xmm2 ",0x80    \n\tcall 1b \n\t"
+
+         :
+         : "r" (rk), "r" (key)
+         : "memory", "cc", "0" );
+}
+
+/*
+ * Key expansion, 256-bit case
+ */
+static void aesni_setkey_enc_256( unsigned char *rk,
+                                  const unsigned char *key )
+{
+    asm( "movdqu (%1), %%xmm0           \n\t"
+         "movdqu %%xmm0, (%0)           \n\t"
+         "add $16, %0                   \n\t"
+         "movdqu 16(%1), %%xmm1         \n\t"
+         "movdqu %%xmm1, (%0)           \n\t"
+         "jmp 2f                        \n\t" // skip auxiliary routine
+
+         /*
+          * Finish generating the next two round keys.
+          *
+          * On entry xmm0 is r3:r2:r1:r0, xmm1 is r7:r6:r5:r4 and
+          * xmm2 is X:stuff:stuff:stuff with X = rot( sub( r7 )) ^ RCON
+          *
+          * On exit, xmm0 is r11:r10:r9:r8 and xmm1 is r15:r14:r13:r12
+          * and those have been written to the output buffer.
+          */
+         "1:                                \n\t"
+         "pshufd $0xff, %%xmm2, %%xmm2      \n\t"
+         "pxor %%xmm0, %%xmm2               \n\t"
+         "pslldq $4, %%xmm0                 \n\t"
+         "pxor %%xmm0, %%xmm2               \n\t"
+         "pslldq $4, %%xmm0                 \n\t"
+         "pxor %%xmm0, %%xmm2               \n\t"
+         "pslldq $4, %%xmm0                 \n\t"
+         "pxor %%xmm2, %%xmm0               \n\t"
+         "add $16, %0                       \n\t"
+         "movdqu %%xmm0, (%0)               \n\t"
+
+         /* Set xmm2 to stuff:Y:stuff:stuff with Y = subword( r11 )
+          * and proceed to generate next round key from there */
+         AESKEYGENA xmm0_xmm2 ",0x00        \n\t"
+         "pshufd $0xaa, %%xmm2, %%xmm2      \n\t"
+         "pxor %%xmm1, %%xmm2               \n\t"
+         "pslldq $4, %%xmm1                 \n\t"
+         "pxor %%xmm1, %%xmm2               \n\t"
+         "pslldq $4, %%xmm1                 \n\t"
+         "pxor %%xmm1, %%xmm2               \n\t"
+         "pslldq $4, %%xmm1                 \n\t"
+         "pxor %%xmm2, %%xmm1               \n\t"
+         "add $16, %0                       \n\t"
+         "movdqu %%xmm1, (%0)               \n\t"
+         "ret                               \n\t"
+
+         /*
+          * Main "loop" - Generating one more key than necessary,
+          * see definition of aes_context.buf
+          */
+         "2:                                \n\t"
+         AESKEYGENA xmm1_xmm2 ",0x01        \n\tcall 1b \n\t"
+         AESKEYGENA xmm1_xmm2 ",0x02        \n\tcall 1b \n\t"
+         AESKEYGENA xmm1_xmm2 ",0x04        \n\tcall 1b \n\t"
+         AESKEYGENA xmm1_xmm2 ",0x08        \n\tcall 1b \n\t"
+         AESKEYGENA xmm1_xmm2 ",0x10        \n\tcall 1b \n\t"
+         AESKEYGENA xmm1_xmm2 ",0x20        \n\tcall 1b \n\t"
+         AESKEYGENA xmm1_xmm2 ",0x40        \n\tcall 1b \n\t"
+         :
+         : "r" (rk), "r" (key)
+         : "memory", "cc", "0" );
+}
+
+/*
+ * Key expansion, wrapper
+ */
+int 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/polarssl/arc4.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,207 @@
+/*
+ *  An implementation of the ARCFOUR algorithm
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.h>
+
+#if defined(POLARSSL_SELF_TEST)
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdio.h>
+#define polarssl_printf printf
+#endif /* POLARSSL_PLATFORM_C */
+#endif /* POLARSSL_SELF_TEST */
+
+#if !defined(POLARSSL_ARC4_ALT)
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+void arc4_init( arc4_context *ctx )
+{
+    memset( ctx, 0, sizeof( arc4_context ) );
+}
+
+void arc4_free( arc4_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    polarssl_zeroize( ctx, sizeof( arc4_context ) );
+}
+
+/*
+ * 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)
+/*
+ * 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, ret = 0;
+    unsigned char ibuf[8];
+    unsigned char obuf[8];
+    arc4_context ctx;
+
+    arc4_init( &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" );
+
+            ret = 1;
+            goto exit;
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+exit:
+    arc4_free( &ctx );
+
+    return( ret );
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_ARC4_C */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/polarssl/asn1parse.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,396 @@
+/*
+ *  Generic ASN.1 parsing
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.h>
+
+#if defined(POLARSSL_BIGNUM_C)
+#include "polarssl/bignum.h"
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdlib.h>
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+/*
+ * 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 = ( (size_t)(*p)[1] << 8 ) | (*p)[2];
+            (*p) += 3;
+            break;
+
+        case 3:
+            if( ( end - *p ) < 4 )
+                return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+            *len = ( (size_t)(*p)[1] << 16 ) |
+                   ( (size_t)(*p)[2] << 8  ) | (*p)[3];
+            (*p) += 4;
+            break;
+
+        case 4:
+            if( ( end - *p ) < 5 )
+                return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+            *len = ( (size_t)(*p)[1] << 24 ) | ( (size_t)(*p)[2] << 16 ) |
+                   ( (size_t)(*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 = polarssl_malloc( sizeof( asn1_sequence ) );
+
+            if( cur->next == NULL )
+                return( POLARSSL_ERR_ASN1_MALLOC_FAILED );
+
+            memset( cur->next, 0, sizeof( asn1_sequence ) );
+
+            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 )
+    {
+        polarssl_zeroize( params, 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 );
+
+    polarssl_zeroize( cur, 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/polarssl/asn1write.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,366 @@
+/*
+ * ASN.1 buffer writing functionality
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.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 );
+        }
+
+        memcpy( cur->oid.p, oid, oid_len );
+
+        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 );
+        }
+
+        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/polarssl/base64.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,292 @@
+/*
+ *  RFC 1521 base64 encoding/decoding
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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_SELF_TEST)
+#include <string.h>
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdio.h>
+#define polarssl_printf printf
+#endif /* POLARSSL_PLATFORM_C */
+#endif /* POLARSSL_SELF_TEST */
+
+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 )
+    {
+        *dlen = 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;
+
+    /* First pass: check for validity and get output length */
+    for( i = n = j = 0; i < slen; i++ )
+    {
+        /* Skip spaces before checking for EOL */
+        x = 0;
+        while( i < slen && src[i] == ' ' )
+        {
+            ++i;
+            ++x;
+        }
+
+        /* Spaces at end of buffer are OK */
+        if( i == slen )
+            break;
+
+        if( ( slen - i ) >= 2 &&
+            src[i] == '\r' && src[i + 1] == '\n' )
+            continue;
+
+        if( src[i] == '\n' )
+            continue;
+
+        /* Space inside a line is an error */
+        if( x != 0 )
+            return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
+
+        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;
+    n -= j;
+
+    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' || *src == ' ' )
+            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)
+
+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/polarssl/bignum.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,2354 @@
+/*
+ *  Multi-precision integer library
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.h>
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#define polarssl_printf     printf
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+#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 )
+    {
+        polarssl_zeroize( X->p, 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 = 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 );
+            polarssl_zeroize( X->p, 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 = 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 );
+        polarssl_zeroize( X->p, 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 in a time-constant manner */
+    assign = (assign | (unsigned char)-assign) >> 7;
+
+    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 in a time-constant manner */
+    swap = (swap | (unsigned char)-swap) >> 7;
+
+    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;
+
+    if( X->n == 0 )
+        return( 0 );
+
+    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 ) != 2 )
+                    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
+        {
+#if defined(POLARSSL_HAVE_UDBL)
+            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 /* POLARSSL_HAVE_UDBL && !64-bit Apple with Clang 5.0 */
+        }
+
+        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, count;
+    size_t i, j, k, 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
+         */
+
+        count = 0;
+        do {
+            MPI_CHK( mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
+
+            j = mpi_msb( &A );
+            k = mpi_msb( &W );
+            if (j > k) {
+                MPI_CHK( mpi_shift_r( &A, j - k ) );
+            }
+
+            if (count++ > 30) {
+                return POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
+            }
+
+        } while ( (mpi_cmp_mpi( &A, &W ) >= 0) ||
+                  (mpi_cmp_int( &A, 1 )  <= 0)    );
+
+        /*
+         * 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;
+    mpi XX;
+
+    XX.s = 1;
+    XX.n = X->n;
+    XX.p = X->p;
+
+    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_r( X, k - nbits + 1 ) );
+
+    mpi_set_bit( X, nbits-1, 1 );
+
+    X->p[0] |= 1;
+
+    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
+         */
+
+        X->p[0] |= 2;
+
+        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/polarssl/blowfish.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,658 @@
+/*
+ *  Blowfish implementation
+ *
+ *  Copyright (C) 2012-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.h>
+
+#if !defined(POLARSSL_BLOWFISH_ALT)
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+/*
+ * 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;
+}
+
+void blowfish_init( blowfish_context *ctx )
+{
+    memset( ctx, 0, sizeof( blowfish_context ) );
+}
+
+void blowfish_free( blowfish_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    polarssl_zeroize( ctx, sizeof( blowfish_context ) );
+}
+
+/*
+ * 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/polarssl/camellia.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,1073 @@
+/*
+ *  Camellia implementation
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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_SELF_TEST)
+#include <string.h>
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdio.h>
+#define polarssl_printf printf
+#endif /* POLARSSL_PLATFORM_C */
+#endif /* POLARSSL_SELF_TEST */
+
+#if !defined(POLARSSL_CAMELLIA_ALT)
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+/*
+ * 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 = ((uint32_t) SBOX1((I0 >> 24) & 0xFF) << 24) |
+         ((uint32_t) SBOX2((I0 >> 16) & 0xFF) << 16) |
+         ((uint32_t) SBOX3((I0 >>  8) & 0xFF) <<  8) |
+         ((uint32_t) SBOX4((I0      ) & 0xFF)      );
+    I1 = ((uint32_t) SBOX2((I1 >> 24) & 0xFF) << 24) |
+         ((uint32_t) SBOX3((I1 >> 16) & 0xFF) << 16) |
+         ((uint32_t) SBOX4((I1 >>  8) & 0xFF) <<  8) |
+         ((uint32_t) 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;
+}
+
+void camellia_init( camellia_context *ctx )
+{
+    memset( ctx, 0, sizeof( camellia_context ) );
+}
+
+void camellia_free( camellia_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    polarssl_zeroize( ctx, sizeof( camellia_context ) );
+}
+
+/*
+ * 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, ret;
+    size_t i;
+    camellia_context cty;
+    uint32_t *RK;
+    uint32_t *SK;
+
+    camellia_init( &cty );
+
+    /* Also checks keysize */
+    if( ( ret = camellia_setkey_enc( &cty, key, keysize ) ) != 0 )
+        goto exit;
+
+    ctx->nr = cty.nr;
+    idx = ( ctx->nr == 4 );
+
+    RK = ctx->rk;
+    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++;
+
+exit:
+    camellia_free( &cty );
+
+    return( ret );
+}
+
+/*
+ * 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)
+
+/*
+ * 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/polarssl/ccm.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,459 @@
+/*
+ *  NIST SP800-38C compliant CCM implementation
+ *
+ *  Copyright (C) 2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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.
+ */
+
+/*
+ * Definition of CCM:
+ * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf
+ * RFC 3610 "Counter with CBC-MAC (CCM)"
+ *
+ * Related:
+ * RFC 5116 "An Interface and Algorithms for Authenticated Encryption"
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_CCM_C)
+
+#include "polarssl/ccm.h"
+
+#include <string.h>
+
+#if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_AES_C)
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdio.h>
+#define polarssl_printf printf
+#endif /* POLARSSL_PLATFORM_C */
+#endif /* POLARSSL_SELF_TEST && POLARSSL_AES_C */
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+#define CCM_ENCRYPT 0
+#define CCM_DECRYPT 1
+
+/*
+ * Initialize context
+ */
+int ccm_init( ccm_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( ccm_context ) );
+
+    cipher_init( &ctx->cipher_ctx );
+
+    cipher_info = cipher_info_from_values( cipher, keysize, POLARSSL_MODE_ECB );
+    if( cipher_info == NULL )
+        return( POLARSSL_ERR_CCM_BAD_INPUT );
+
+    if( cipher_info->block_size != 16 )
+        return( POLARSSL_ERR_CCM_BAD_INPUT );
+
+    cipher_free( &ctx->cipher_ctx );
+
+    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 );
+    }
+
+    return( 0 );
+}
+
+/*
+ * Free context
+ */
+void ccm_free( ccm_context *ctx )
+{
+    cipher_free( &ctx->cipher_ctx );
+    polarssl_zeroize( ctx, sizeof( ccm_context ) );
+}
+
+/*
+ * Macros for common operations.
+ * Results in smaller compiled code than static inline functions.
+ */
+
+/*
+ * Update the CBC-MAC state in y using a block in b
+ * (Always using b as the source helps the compiler optimise a bit better.)
+ */
+#define UPDATE_CBC_MAC                                                      \
+    for( i = 0; i < 16; i++ )                                               \
+        y[i] ^= b[i];                                                       \
+                                                                            \
+    if( ( ret = cipher_update( &ctx->cipher_ctx, y, 16, y, &olen ) ) != 0 ) \
+        return( ret );
+
+/*
+ * Encrypt or decrypt a partial block with CTR
+ * Warning: using b for temporary storage! src and dst must not be b!
+ * This avoids allocating one more 16 bytes buffer while allowing src == dst.
+ */
+#define CTR_CRYPT( dst, src, len  )                                            \
+    if( ( ret = cipher_update( &ctx->cipher_ctx, ctr, 16, b, &olen ) ) != 0 )  \
+        return( ret );                                                         \
+                                                                               \
+    for( i = 0; i < len; i++ )                                                 \
+        dst[i] = src[i] ^ b[i];
+
+/*
+ * Authenticated encryption or decryption
+ */
+static int ccm_auth_crypt( ccm_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,
+                           unsigned char *tag, size_t tag_len )
+{
+    int ret;
+    unsigned char i;
+    unsigned char q = 16 - 1 - iv_len;
+    size_t len_left, olen;
+    unsigned char b[16];
+    unsigned char y[16];
+    unsigned char ctr[16];
+    const unsigned char *src;
+    unsigned char *dst;
+
+    /*
+     * Check length requirements: SP800-38C A.1
+     * Additional requirement: a < 2^16 - 2^8 to simplify the code.
+     * 'length' checked later (when writing it to the first block)
+     */
+    if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 )
+        return( POLARSSL_ERR_CCM_BAD_INPUT );
+
+    /* Also implies q is within bounds */
+    if( iv_len < 7 || iv_len > 13 )
+        return( POLARSSL_ERR_CCM_BAD_INPUT );
+
+    if( add_len > 0xFF00 )
+        return( POLARSSL_ERR_CCM_BAD_INPUT );
+
+    /*
+     * First block B_0:
+     * 0        .. 0        flags
+     * 1        .. iv_len   nonce (aka iv)
+     * iv_len+1 .. 15       length
+     *
+     * With flags as (bits):
+     * 7        0
+     * 6        add present?
+     * 5 .. 3   (t - 2) / 2
+     * 2 .. 0   q - 1
+     */
+    b[0] = 0;
+    b[0] |= ( add_len > 0 ) << 6;
+    b[0] |= ( ( tag_len - 2 ) / 2 ) << 3;
+    b[0] |= q - 1;
+
+    memcpy( b + 1, iv, iv_len );
+
+    for( i = 0, len_left = length; i < q; i++, len_left >>= 8 )
+        b[15-i] = (unsigned char)( len_left & 0xFF );
+
+    if( len_left > 0 )
+        return( POLARSSL_ERR_CCM_BAD_INPUT );
+
+
+    /* Start CBC-MAC with first block */
+    memset( y, 0, 16 );
+    UPDATE_CBC_MAC;
+
+    /*
+     * If there is additional data, update CBC-MAC with
+     * add_len, add, 0 (padding to a block boundary)
+     */
+    if( add_len > 0 )
+    {
+        size_t use_len;
+        len_left = add_len;
+        src = add;
+
+        memset( b, 0, 16 );
+        b[0] = (unsigned char)( ( add_len >> 8 ) & 0xFF );
+        b[1] = (unsigned char)( ( add_len      ) & 0xFF );
+
+        use_len = len_left < 16 - 2 ? len_left : 16 - 2;
+        memcpy( b + 2, src, use_len );
+        len_left -= use_len;
+        src += use_len;
+
+        UPDATE_CBC_MAC;
+
+        while( len_left > 0 )
+        {
+            use_len = len_left > 16 ? 16 : len_left;
+
+            memset( b, 0, 16 );
+            memcpy( b, src, use_len );
+            UPDATE_CBC_MAC;
+
+            len_left -= use_len;
+            src += use_len;
+        }
+    }
+
+    /*
+     * Prepare counter block for encryption:
+     * 0        .. 0        flags
+     * 1        .. iv_len   nonce (aka iv)
+     * iv_len+1 .. 15       counter (initially 1)
+     *
+     * With flags as (bits):
+     * 7 .. 3   0
+     * 2 .. 0   q - 1
+     */
+    ctr[0] = q - 1;
+    memcpy( ctr + 1, iv, iv_len );
+    memset( ctr + 1 + iv_len, 0, q );
+    ctr[15] = 1;
+
+    /*
+     * Authenticate and {en,de}crypt the message.
+     *
+     * The only difference between encryption and decryption is
+     * the respective order of authentication and {en,de}cryption.
+     */
+    len_left = length;
+    src = input;
+    dst = output;
+
+    while( len_left > 0 )
+    {
+        unsigned char use_len = len_left > 16 ? 16 : len_left;
+
+        if( mode == CCM_ENCRYPT )
+        {
+            memset( b, 0, 16 );
+            memcpy( b, src, use_len );
+            UPDATE_CBC_MAC;
+        }
+
+        CTR_CRYPT( dst, src, use_len );
+
+        if( mode == CCM_DECRYPT )
+        {
+            memset( b, 0, 16 );
+            memcpy( b, dst, use_len );
+            UPDATE_CBC_MAC;
+        }
+
+        dst += use_len;
+        src += use_len;
+        len_left -= use_len;
+
+        /*
+         * Increment counter.
+         * No need to check for overflow thanks to the length check above.
+         */
+        for( i = 0; i < q; i++ )
+            if( ++ctr[15-i] != 0 )
+                break;
+    }
+
+    /*
+     * Authentication: reset counter and crypt/mask internal tag
+     */
+    for( i = 0; i < q; i++ )
+        ctr[15-i] = 0;
+
+    CTR_CRYPT( y, y, 16 );
+    memcpy( tag, y, tag_len );
+
+    return( 0 );
+}
+
+/*
+ * Authenticated encryption
+ */
+int ccm_encrypt_and_tag( ccm_context *ctx, size_t length,
+                         const unsigned char *iv, size_t iv_len,
+                         const unsigned char *add, size_t add_len,
+                         const unsigned char *input, unsigned char *output,
+                         unsigned char *tag, size_t tag_len )
+{
+    return( ccm_auth_crypt( ctx, CCM_ENCRYPT, length, iv, iv_len,
+                            add, add_len, input, output, tag, tag_len ) );
+}
+
+/*
+ * Authenticated decryption
+ */
+int ccm_auth_decrypt( ccm_context *ctx, size_t length,
+                      const unsigned char *iv, size_t iv_len,
+                      const unsigned char *add, size_t add_len,
+                      const unsigned char *input, unsigned char *output,
+                      const unsigned char *tag, size_t tag_len )
+{
+    int ret;
+    unsigned char check_tag[16];
+    unsigned char i;
+    int diff;
+
+    if( ( ret = ccm_auth_crypt( ctx, CCM_DECRYPT, length,
+                                iv, iv_len, add, add_len,
+                                input, output, check_tag, tag_len ) ) != 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 )
+    {
+        polarssl_zeroize( output, length );
+        return( POLARSSL_ERR_CCM_AUTH_FAILED );
+    }
+
+    return( 0 );
+}
+
+
+#if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_AES_C)
+/*
+ * Examples 1 to 3 from SP800-38C Appendix C
+ */
+
+#define NB_TESTS 3
+
+/*
+ * The data is the same for all tests, only the used length changes
+ */
+static const unsigned char key[] = {
+    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+    0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f
+};
+
+static const unsigned char iv[] = {
+    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+    0x18, 0x19, 0x1a, 0x1b
+};
+
+static const unsigned char ad[] = {
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+    0x10, 0x11, 0x12, 0x13
+};
+
+static const unsigned char msg[] = {
+    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+};
+
+static const size_t iv_len [NB_TESTS] = { 7, 8,  12 };
+static const size_t add_len[NB_TESTS] = { 8, 16, 20 };
+static const size_t msg_len[NB_TESTS] = { 4, 16, 24 };
+static const size_t tag_len[NB_TESTS] = { 4, 6,  8  };
+
+static const unsigned char res[NB_TESTS][32] = {
+    {   0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d },
+    {   0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62,
+        0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d,
+        0x1f, 0xc6, 0x4f, 0xbf, 0xac, 0xcd },
+    {   0xe3, 0xb2, 0x01, 0xa9, 0xf5, 0xb7, 0x1a, 0x7a,
+        0x9b, 0x1c, 0xea, 0xec, 0xcd, 0x97, 0xe7, 0x0b,
+        0x61, 0x76, 0xaa, 0xd9, 0xa4, 0x42, 0x8a, 0xa5,
+        0x48, 0x43, 0x92, 0xfb, 0xc1, 0xb0, 0x99, 0x51 }
+};
+
+int ccm_self_test( int verbose )
+{
+    ccm_context ctx;
+    unsigned char out[32];
+    size_t i;
+    int ret;
+
+    if( ccm_init( &ctx, POLARSSL_CIPHER_ID_AES, key, 8 * sizeof key ) != 0 )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "  CCM: setup failed" );
+
+        return( 1 );
+    }
+
+    for( i = 0; i < NB_TESTS; i++ )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "  CCM-AES #%u: ", (unsigned int) i + 1 );
+
+        ret = ccm_encrypt_and_tag( &ctx, msg_len[i],
+                                   iv, iv_len[i], ad, add_len[i],
+                                   msg, out,
+                                   out + msg_len[i], tag_len[i] );
+
+        if( ret != 0 ||
+            memcmp( out, res[i], msg_len[i] + tag_len[i] ) != 0 )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        ret = ccm_auth_decrypt( &ctx, msg_len[i],
+                                iv, iv_len[i], ad, add_len[i],
+                                res[i], out,
+                                res[i] + msg_len[i], tag_len[i] );
+
+        if( ret != 0 ||
+            memcmp( out, msg, msg_len[i] ) != 0 )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "passed\n" );
+    }
+
+    ccm_free( &ctx );
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+    return( 0 );
+}
+
+#endif /* POLARSSL_SELF_TEST && POLARSSL_AES_C */
+
+#endif /* POLARSSL_CCM_C */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/polarssl/certs.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,308 @@
+/*
+ *  X.509 test certificates
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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/polarssl/cipher.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,917 @@
+/**
+ * \file cipher.c
+ *
+ * \brief Generic cipher wrapper for mbed TLS
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(POLARSSL_GCM_C)
+#include "polarssl/gcm.h"
+#endif
+
+#if defined(POLARSSL_CCM_C)
+#include "polarssl/ccm.h"
+#endif
+
+#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
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+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 );
+}
+
+void cipher_init( cipher_context_t *ctx )
+{
+    memset( ctx, 0, sizeof( cipher_context_t ) );
+}
+
+void cipher_free( cipher_context_t *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    if( ctx->cipher_ctx )
+        ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx );
+
+    polarssl_zeroize( ctx, sizeof(cipher_context_t) );
+}
+
+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 );
+}
+
+#if ! defined(POLARSSL_DEPRECATED_REMOVED)
+int cipher_free_ctx( cipher_context_t *ctx )
+{
+    cipher_free( ctx );
+
+    return( 0 );
+}
+#endif
+
+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( ( ctx->cipher_info->flags & POLARSSL_CIPHER_VARIABLE_KEY_LEN ) == 0 &&
+        (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->flags & POLARSSL_CIPHER_VARIABLE_IV_LEN ) != 0 )
+        actual_iv_size = iv_len;
+    else
+    {
+        actual_iv_size = ctx->cipher_info->iv_size;
+
+        /* avoid reading past the end of input buffer */
+        if( actual_iv_size > iv_len )
+            return( 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_GCM_C)
+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( 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 );
+    }
+
+    return( 0 );
+}
+#endif /* POLARSSL_GCM_C */
+
+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_GCM_C)
+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( POLARSSL_MODE_GCM == ctx->cipher_info->mode )
+        return gcm_finish( (gcm_context *) ctx->cipher_ctx, tag, tag_len );
+
+    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( 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 );
+    }
+
+    return( 0 );
+}
+#endif /* POLARSSL_GCM_C */
+
+/*
+ * Packet-oriented wrapper for non-AEAD modes
+ */
+int cipher_crypt( cipher_context_t *ctx,
+                  const unsigned char *iv, size_t iv_len,
+                  const unsigned char *input, size_t ilen,
+                  unsigned char *output, size_t *olen )
+{
+    int ret;
+    size_t finish_olen;
+
+    if( ( ret = cipher_set_iv( ctx, iv, iv_len ) ) != 0 )
+        return( ret );
+
+    if( ( ret = cipher_reset( ctx ) ) != 0 )
+        return( ret );
+
+    if( ( ret = cipher_update( ctx, input, ilen, output, olen ) ) != 0 )
+        return( ret );
+
+    if( ( ret = cipher_finish( ctx, output + *olen, &finish_olen ) ) != 0 )
+        return( ret );
+
+    *olen += finish_olen;
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_CIPHER_MODE_AEAD)
+/*
+ * Packet-oriented encryption for AEAD modes
+ */
+int cipher_auth_encrypt( cipher_context_t *ctx,
+                         const unsigned char *iv, size_t iv_len,
+                         const unsigned char *ad, size_t ad_len,
+                         const unsigned char *input, size_t ilen,
+                         unsigned char *output, size_t *olen,
+                         unsigned char *tag, size_t tag_len )
+{
+#if defined(POLARSSL_GCM_C)
+    if( POLARSSL_MODE_GCM == ctx->cipher_info->mode )
+    {
+        *olen = ilen;
+        return( gcm_crypt_and_tag( ctx->cipher_ctx, GCM_ENCRYPT, ilen,
+                                   iv, iv_len, ad, ad_len, input, output,
+                                   tag_len, tag ) );
+    }
+#endif /* POLARSSL_GCM_C */
+#if defined(POLARSSL_CCM_C)
+    if( POLARSSL_MODE_CCM == ctx->cipher_info->mode )
+    {
+        *olen = ilen;
+        return( ccm_encrypt_and_tag( ctx->cipher_ctx, ilen,
+                                     iv, iv_len, ad, ad_len, input, output,
+                                     tag, tag_len ) );
+    }
+#endif /* POLARSSL_CCM_C */
+
+    return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE );
+}
+
+/*
+ * Packet-oriented decryption for AEAD modes
+ */
+int cipher_auth_decrypt( cipher_context_t *ctx,
+                         const unsigned char *iv, size_t iv_len,
+                         const unsigned char *ad, size_t ad_len,
+                         const unsigned char *input, size_t ilen,
+                         unsigned char *output, size_t *olen,
+                         const unsigned char *tag, size_t tag_len )
+{
+#if defined(POLARSSL_GCM_C)
+    if( POLARSSL_MODE_GCM == ctx->cipher_info->mode )
+    {
+        int ret;
+
+        *olen = ilen;
+        ret = gcm_auth_decrypt( ctx->cipher_ctx, ilen,
+                                iv, iv_len, ad, ad_len,
+                                tag, tag_len, input, output );
+
+        if( ret == POLARSSL_ERR_GCM_AUTH_FAILED )
+            ret = POLARSSL_ERR_CIPHER_AUTH_FAILED;
+
+        return( ret );
+    }
+#endif /* POLARSSL_GCM_C */
+#if defined(POLARSSL_CCM_C)
+    if( POLARSSL_MODE_CCM == ctx->cipher_info->mode )
+    {
+        int ret;
+
+        *olen = ilen;
+        ret = ccm_auth_decrypt( ctx->cipher_ctx, ilen,
+                                iv, iv_len, ad, ad_len,
+                                input, output, tag, tag_len );
+
+        if( ret == POLARSSL_ERR_CCM_AUTH_FAILED )
+            ret = POLARSSL_ERR_CIPHER_AUTH_FAILED;
+
+        return( ret );
+    }
+#endif /* POLARSSL_CCM_C */
+
+    return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE );
+}
+#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/polarssl/cipher_wrap.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,1443 @@
+/**
+ * \file cipher_wrap.c
+ *
+ * \brief Generic cipher wrapper for mbed TLS
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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_CCM_C)
+#include "polarssl/ccm.h"
+#endif
+
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+#include <string.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_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_CCM_C)
+/* shared by all CCM ciphers */
+static void *ccm_ctx_alloc( void )
+{
+    return polarssl_malloc( sizeof( ccm_context ) );
+}
+
+static void ccm_ctx_free( void *ctx )
+{
+    ccm_free( ctx );
+    polarssl_free( ctx );
+}
+#endif /* POLARSSL_CCM_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 );
+}
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+static int aes_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length,
+        unsigned char *iv, const unsigned char *input, unsigned char *output )
+{
+    return aes_crypt_cbc( (aes_context *) ctx, operation, length, iv, input,
+                          output );
+}
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+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 )
+{
+    return aes_crypt_cfb128( (aes_context *) ctx, operation, length, iv_off, iv,
+                             input, output );
+}
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+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 )
+{
+    return aes_crypt_ctr( (aes_context *) ctx, length, nc_off, nonce_counter,
+                          stream_block, input, output );
+}
+#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 )
+{
+    aes_context *aes = polarssl_malloc( sizeof( aes_context ) );
+
+    if( aes == NULL )
+        return( NULL );
+
+    aes_init( aes );
+
+    return( aes );
+}
+
+static void aes_ctx_free( void *ctx )
+{
+    aes_free( (aes_context *) ctx );
+    polarssl_free( ctx );
+}
+
+static const cipher_base_t aes_info = {
+    POLARSSL_CIPHER_ID_AES,
+    aes_crypt_ecb_wrap,
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    aes_crypt_cbc_wrap,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+    aes_crypt_cfb128_wrap,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+    aes_crypt_ctr_wrap,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_STREAM)
+    NULL,
+#endif
+    aes_setkey_enc_wrap,
+    aes_setkey_dec_wrap,
+    aes_ctx_alloc,
+    aes_ctx_free
+};
+
+static 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
+};
+
+static 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
+};
+
+static 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)
+static 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
+};
+
+static 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
+};
+
+static 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)
+static 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
+};
+
+static 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
+};
+
+static 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)
+static 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
+};
+
+static 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
+};
+
+static 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 );
+}
+
+static const cipher_base_t gcm_aes_info = {
+    POLARSSL_CIPHER_ID_AES,
+    NULL,
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    NULL,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+    NULL,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+    NULL,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_STREAM)
+    NULL,
+#endif
+    gcm_aes_setkey_wrap,
+    gcm_aes_setkey_wrap,
+    gcm_ctx_alloc,
+    gcm_ctx_free,
+};
+
+static const cipher_info_t aes_128_gcm_info = {
+    POLARSSL_CIPHER_AES_128_GCM,
+    POLARSSL_MODE_GCM,
+    128,
+    "AES-128-GCM",
+    12,
+    POLARSSL_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &gcm_aes_info
+};
+
+static const cipher_info_t aes_192_gcm_info = {
+    POLARSSL_CIPHER_AES_192_GCM,
+    POLARSSL_MODE_GCM,
+    192,
+    "AES-192-GCM",
+    12,
+    POLARSSL_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &gcm_aes_info
+};
+
+static const cipher_info_t aes_256_gcm_info = {
+    POLARSSL_CIPHER_AES_256_GCM,
+    POLARSSL_MODE_GCM,
+    256,
+    "AES-256-GCM",
+    12,
+    POLARSSL_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &gcm_aes_info
+};
+#endif /* POLARSSL_GCM_C */
+
+#if defined(POLARSSL_CCM_C)
+static int ccm_aes_setkey_wrap( void *ctx, const unsigned char *key,
+                                unsigned int key_length )
+{
+    return ccm_init( (ccm_context *) ctx, POLARSSL_CIPHER_ID_AES,
+                     key, key_length );
+}
+
+static const cipher_base_t ccm_aes_info = {
+    POLARSSL_CIPHER_ID_AES,
+    NULL,
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    NULL,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+    NULL,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+    NULL,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_STREAM)
+    NULL,
+#endif
+    ccm_aes_setkey_wrap,
+    ccm_aes_setkey_wrap,
+    ccm_ctx_alloc,
+    ccm_ctx_free,
+};
+
+static const cipher_info_t aes_128_ccm_info = {
+    POLARSSL_CIPHER_AES_128_CCM,
+    POLARSSL_MODE_CCM,
+    128,
+    "AES-128-CCM",
+    12,
+    POLARSSL_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &ccm_aes_info
+};
+
+static const cipher_info_t aes_192_ccm_info = {
+    POLARSSL_CIPHER_AES_192_CCM,
+    POLARSSL_MODE_CCM,
+    192,
+    "AES-192-CCM",
+    12,
+    POLARSSL_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &ccm_aes_info
+};
+
+static const cipher_info_t aes_256_ccm_info = {
+    POLARSSL_CIPHER_AES_256_CCM,
+    POLARSSL_MODE_CCM,
+    256,
+    "AES-256-CCM",
+    12,
+    POLARSSL_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &ccm_aes_info
+};
+#endif /* POLARSSL_CCM_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 );
+}
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+static int camellia_crypt_cbc_wrap( void *ctx, operation_t operation,
+        size_t length, unsigned char *iv,
+        const unsigned char *input, unsigned char *output )
+{
+    return camellia_crypt_cbc( (camellia_context *) ctx, operation, length, iv,
+                               input, output );
+}
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+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 )
+{
+    return camellia_crypt_cfb128( (camellia_context *) ctx, operation, length,
+                                  iv_off, iv, input, output );
+}
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+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 )
+{
+    return camellia_crypt_ctr( (camellia_context *) ctx, length, nc_off,
+                               nonce_counter, stream_block, input, output );
+}
+#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 )
+{
+    camellia_context *ctx;
+    ctx = polarssl_malloc( sizeof( camellia_context ) );
+
+    if( ctx == NULL )
+        return( NULL );
+
+    camellia_init( ctx );
+
+    return( ctx );
+}
+
+static void camellia_ctx_free( void *ctx )
+{
+    camellia_free( (camellia_context *) ctx );
+    polarssl_free( ctx );
+}
+
+static const cipher_base_t camellia_info = {
+    POLARSSL_CIPHER_ID_CAMELLIA,
+    camellia_crypt_ecb_wrap,
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    camellia_crypt_cbc_wrap,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+    camellia_crypt_cfb128_wrap,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+    camellia_crypt_ctr_wrap,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_STREAM)
+    NULL,
+#endif
+    camellia_setkey_enc_wrap,
+    camellia_setkey_dec_wrap,
+    camellia_ctx_alloc,
+    camellia_ctx_free
+};
+
+static 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
+};
+
+static 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
+};
+
+static 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)
+static 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
+};
+
+static 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
+};
+
+static 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)
+static 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
+};
+
+static 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
+};
+
+static 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)
+static 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
+};
+
+static 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
+};
+
+static 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 );
+}
+
+static const cipher_base_t gcm_camellia_info = {
+    POLARSSL_CIPHER_ID_CAMELLIA,
+    NULL,
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    NULL,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+    NULL,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+    NULL,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_STREAM)
+    NULL,
+#endif
+    gcm_camellia_setkey_wrap,
+    gcm_camellia_setkey_wrap,
+    gcm_ctx_alloc,
+    gcm_ctx_free,
+};
+
+static const cipher_info_t camellia_128_gcm_info = {
+    POLARSSL_CIPHER_CAMELLIA_128_GCM,
+    POLARSSL_MODE_GCM,
+    128,
+    "CAMELLIA-128-GCM",
+    12,
+    POLARSSL_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &gcm_camellia_info
+};
+
+static const cipher_info_t camellia_192_gcm_info = {
+    POLARSSL_CIPHER_CAMELLIA_192_GCM,
+    POLARSSL_MODE_GCM,
+    192,
+    "CAMELLIA-192-GCM",
+    12,
+    POLARSSL_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &gcm_camellia_info
+};
+
+static const cipher_info_t camellia_256_gcm_info = {
+    POLARSSL_CIPHER_CAMELLIA_256_GCM,
+    POLARSSL_MODE_GCM,
+    256,
+    "CAMELLIA-256-GCM",
+    12,
+    POLARSSL_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &gcm_camellia_info
+};
+#endif /* POLARSSL_GCM_C */
+
+#if defined(POLARSSL_CCM_C)
+static int ccm_camellia_setkey_wrap( void *ctx, const unsigned char *key,
+                                     unsigned int key_length )
+{
+    return ccm_init( (ccm_context *) ctx, POLARSSL_CIPHER_ID_CAMELLIA,
+                     key, key_length );
+}
+
+static const cipher_base_t ccm_camellia_info = {
+    POLARSSL_CIPHER_ID_CAMELLIA,
+    NULL,
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    NULL,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+    NULL,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+    NULL,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_STREAM)
+    NULL,
+#endif
+    ccm_camellia_setkey_wrap,
+    ccm_camellia_setkey_wrap,
+    ccm_ctx_alloc,
+    ccm_ctx_free,
+};
+
+static const cipher_info_t camellia_128_ccm_info = {
+    POLARSSL_CIPHER_CAMELLIA_128_CCM,
+    POLARSSL_MODE_CCM,
+    128,
+    "CAMELLIA-128-CCM",
+    12,
+    POLARSSL_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &ccm_camellia_info
+};
+
+static const cipher_info_t camellia_192_ccm_info = {
+    POLARSSL_CIPHER_CAMELLIA_192_CCM,
+    POLARSSL_MODE_CCM,
+    192,
+    "CAMELLIA-192-CCM",
+    12,
+    POLARSSL_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &ccm_camellia_info
+};
+
+static const cipher_info_t camellia_256_ccm_info = {
+    POLARSSL_CIPHER_CAMELLIA_256_CCM,
+    POLARSSL_MODE_CCM,
+    256,
+    "CAMELLIA-256-CCM",
+    12,
+    POLARSSL_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &ccm_camellia_info
+};
+#endif /* POLARSSL_CCM_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 );
+}
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+static int des_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length,
+        unsigned char *iv, const unsigned char *input, unsigned char *output )
+{
+    return des_crypt_cbc( (des_context *) ctx, operation, length, iv, input,
+                          output );
+}
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+#if defined(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 )
+{
+    return des3_crypt_cbc( (des3_context *) ctx, operation, length, iv, input,
+                           output );
+}
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+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 )
+{
+    des_context *des = polarssl_malloc( sizeof( des_context ) );
+
+    if( des == NULL )
+        return( NULL );
+
+    des_init( des );
+
+    return( des );
+}
+
+static void des_ctx_free( void *ctx )
+{
+    des_free( (des_context *) ctx );
+    polarssl_free( ctx );
+}
+
+static void * des3_ctx_alloc( void )
+{
+    des3_context *des3;
+    des3 = polarssl_malloc( sizeof( des3_context ) );
+
+    if( des3 == NULL )
+        return( NULL );
+
+    des3_init( des3 );
+
+    return( des3 );
+}
+
+static void des3_ctx_free( void *ctx )
+{
+    des3_free( (des3_context *) ctx );
+    polarssl_free( ctx );
+}
+
+static const cipher_base_t des_info = {
+    POLARSSL_CIPHER_ID_DES,
+    des_crypt_ecb_wrap,
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    des_crypt_cbc_wrap,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+    NULL,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+    NULL,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_STREAM)
+    NULL,
+#endif
+    des_setkey_enc_wrap,
+    des_setkey_dec_wrap,
+    des_ctx_alloc,
+    des_ctx_free
+};
+
+static 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)
+static 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 */
+
+static const cipher_base_t des_ede_info = {
+    POLARSSL_CIPHER_ID_DES,
+    des3_crypt_ecb_wrap,
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    des3_crypt_cbc_wrap,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+    NULL,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+    NULL,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_STREAM)
+    NULL,
+#endif
+    des3_set2key_enc_wrap,
+    des3_set2key_dec_wrap,
+    des3_ctx_alloc,
+    des3_ctx_free
+};
+
+static 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)
+static 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 */
+
+static const cipher_base_t des_ede3_info = {
+    POLARSSL_CIPHER_ID_DES,
+    des3_crypt_ecb_wrap,
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    des3_crypt_cbc_wrap,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+    NULL,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+    NULL,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_STREAM)
+    NULL,
+#endif
+    des3_set3key_enc_wrap,
+    des3_set3key_dec_wrap,
+    des3_ctx_alloc,
+    des3_ctx_free
+};
+
+static 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)
+static 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 );
+}
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+static int blowfish_crypt_cbc_wrap( void *ctx, operation_t operation,
+        size_t length, unsigned char *iv, const unsigned char *input,
+        unsigned char *output )
+{
+    return blowfish_crypt_cbc( (blowfish_context *) ctx, operation, length, iv,
+                               input, output );
+}
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+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 )
+{
+    return blowfish_crypt_cfb64( (blowfish_context *) ctx, operation, length,
+                                 iv_off, iv, input, output );
+}
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+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 )
+{
+    return blowfish_crypt_ctr( (blowfish_context *) ctx, length, nc_off,
+                               nonce_counter, stream_block, input, output );
+}
+#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 )
+{
+    blowfish_context *ctx;
+    ctx = polarssl_malloc( sizeof( blowfish_context ) );
+
+    if( ctx == NULL )
+        return( NULL );
+
+    blowfish_init( ctx );
+
+    return( ctx );
+}
+
+static void blowfish_ctx_free( void *ctx )
+{
+    blowfish_free( (blowfish_context *) ctx );
+    polarssl_free( ctx );
+}
+
+static const cipher_base_t blowfish_info = {
+    POLARSSL_CIPHER_ID_BLOWFISH,
+    blowfish_crypt_ecb_wrap,
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    blowfish_crypt_cbc_wrap,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+    blowfish_crypt_cfb64_wrap,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+    blowfish_crypt_ctr_wrap,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_STREAM)
+    NULL,
+#endif
+    blowfish_setkey_wrap,
+    blowfish_setkey_wrap,
+    blowfish_ctx_alloc,
+    blowfish_ctx_free
+};
+
+static const cipher_info_t blowfish_ecb_info = {
+    POLARSSL_CIPHER_BLOWFISH_ECB,
+    POLARSSL_MODE_ECB,
+    128,
+    "BLOWFISH-ECB",
+    8,
+    POLARSSL_CIPHER_VARIABLE_KEY_LEN,
+    8,
+    &blowfish_info
+};
+
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+static const cipher_info_t blowfish_cbc_info = {
+    POLARSSL_CIPHER_BLOWFISH_CBC,
+    POLARSSL_MODE_CBC,
+    128,
+    "BLOWFISH-CBC",
+    8,
+    POLARSSL_CIPHER_VARIABLE_KEY_LEN,
+    8,
+    &blowfish_info
+};
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+static const cipher_info_t blowfish_cfb64_info = {
+    POLARSSL_CIPHER_BLOWFISH_CFB64,
+    POLARSSL_MODE_CFB,
+    128,
+    "BLOWFISH-CFB64",
+    8,
+    POLARSSL_CIPHER_VARIABLE_KEY_LEN,
+    8,
+    &blowfish_info
+};
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+static const cipher_info_t blowfish_ctr_info = {
+    POLARSSL_CIPHER_BLOWFISH_CTR,
+    POLARSSL_MODE_CTR,
+    128,
+    "BLOWFISH-CTR",
+    8,
+    POLARSSL_CIPHER_VARIABLE_KEY_LEN,
+    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 )
+{
+    arc4_context *ctx;
+    ctx = polarssl_malloc( sizeof( arc4_context ) );
+
+    if( ctx == NULL )
+        return( NULL );
+
+    arc4_init( ctx );
+
+    return( ctx );
+}
+
+static void arc4_ctx_free( void *ctx )
+{
+    arc4_free( (arc4_context *) ctx );
+    polarssl_free( ctx );
+}
+
+static const cipher_base_t arc4_base_info = {
+    POLARSSL_CIPHER_ID_ARC4,
+    NULL,
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    NULL,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+    NULL,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+    NULL,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_STREAM)
+    arc4_crypt_stream_wrap,
+#endif
+    arc4_setkey_wrap,
+    arc4_setkey_wrap,
+    arc4_ctx_alloc,
+    arc4_ctx_free
+};
+
+static 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);
+}
+
+static const cipher_base_t null_base_info = {
+    POLARSSL_CIPHER_ID_NULL,
+    NULL,
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    NULL,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+    NULL,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+    NULL,
+#endif
+#if defined(POLARSSL_CIPHER_MODE_STREAM)
+    null_crypt_stream,
+#endif
+    null_setkey,
+    null_setkey,
+    null_ctx_alloc,
+    null_ctx_free
+};
+
+static 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
+#if defined(POLARSSL_CCM_C)
+    { POLARSSL_CIPHER_AES_128_CCM,          &aes_128_ccm_info },
+    { POLARSSL_CIPHER_AES_192_CCM,          &aes_192_ccm_info },
+    { POLARSSL_CIPHER_AES_256_CCM,          &aes_256_ccm_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
+#if defined(POLARSSL_CCM_C)
+    { POLARSSL_CIPHER_CAMELLIA_128_CCM,     &camellia_128_ccm_info },
+    { POLARSSL_CIPHER_CAMELLIA_192_CCM,     &camellia_192_ccm_info },
+    { POLARSSL_CIPHER_CAMELLIA_256_CCM,     &camellia_256_ccm_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 */
+
+    { POLARSSL_CIPHER_NONE, 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/polarssl/ctr_drbg.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,558 @@
+/*
+ *  CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.h>
+
+#if defined(POLARSSL_FS_IO)
+#include <stdio.h>
+#endif
+
+#if defined(POLARSSL_SELF_TEST)
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdio.h>
+#define polarssl_printf printf
+#endif /* POLARSSL_PLATFORM_C */
+#endif /* POLARSSL_SELF_TEST */
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+/*
+ * 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 );
+
+    aes_init( &ctx->aes_ctx );
+
+    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_free( ctr_drbg_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    aes_free( &ctx->aes_ctx );
+    polarssl_zeroize( ctx, sizeof( ctr_drbg_context ) );
+}
+
+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;
+
+    if( data_len > CTR_DRBG_MAX_SEED_INPUT )
+        return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
+
+    memset( buf, 0, CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16 );
+    aes_init( &aes_ctx );
+
+    /*
+     * 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;
+    }
+
+    aes_free( &aes_ctx );
+
+    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 )
+    {
+        /* MAX_INPUT would be more logical here, but we have to match
+         * block_cipher_df()'s limits since we can't propagate errors */
+        if( add_len > CTR_DRBG_MAX_SEED_INPUT )
+            add_len = CTR_DRBG_MAX_SEED_INPUT;
+
+        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)
+
+static const 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 const 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,
+                                (void *) 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,
+                            (void *) 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/polarssl/debug.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,360 @@
+/*
+ *  Debugging routines
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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 <stdio.h>
+#include <string.h>
+
+#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 */
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_snprintf snprintf
+#endif
+
+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, text );
+        return;
+    }
+
+    polarssl_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 = polarssl_snprintf( str, maxlen, "%s(%04d): ", file, line );
+
+    polarssl_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];
+    char txt[17];
+    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 = polarssl_snprintf( str, maxlen, "%s(%04d): ", file, line );
+
+    polarssl_snprintf( str + idx, maxlen - idx, "dumping '%s' (%u bytes)\n",
+              text, (unsigned int) len );
+
+    str[maxlen] = '\0';
+    ssl->f_dbg( ssl->p_dbg, level, str );
+
+    idx = 0;
+    memset( txt, 0, sizeof( txt ) );
+    for( i = 0; i < len; i++ )
+    {
+        if( i >= 4096 )
+            break;
+
+        if( i % 16 == 0 )
+        {
+            if( i > 0 )
+            {
+                polarssl_snprintf( str + idx, maxlen - idx, "  %s\n", txt );
+                ssl->f_dbg( ssl->p_dbg, level, str );
+
+                idx = 0;
+                memset( txt, 0, sizeof( txt ) );
+            }
+
+            if( debug_log_mode == POLARSSL_DEBUG_LOG_FULL )
+                idx = polarssl_snprintf( str, maxlen, "%s(%04d): ", file, line );
+
+            idx += polarssl_snprintf( str + idx, maxlen - idx, "%04x: ",
+                             (unsigned int) i );
+
+        }
+
+        idx += polarssl_snprintf( str + idx, maxlen - idx, " %02x",
+                         (unsigned int) buf[i] );
+        txt[i % 16] = ( buf[i] > 31 && buf[i] < 127 ) ? buf[i] : '.' ;
+    }
+
+    if( len > 0 )
+    {
+        for( /* i = i */; i % 16 != 0; i++ )
+            idx += polarssl_snprintf( str + idx, maxlen - idx, "   " );
+
+        polarssl_snprintf( str + idx, maxlen - idx, "  %s\n", txt );
+        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;
+
+    polarssl_snprintf( str, maxlen, "%s(X)", text );
+    str[maxlen] = '\0';
+    debug_print_mpi( ssl, level, file, line, str, &X->X );
+
+    polarssl_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 = polarssl_snprintf( str, maxlen, "%s(%04d): ", file, line );
+
+    polarssl_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 )
+                {
+                    polarssl_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 = polarssl_snprintf( str, maxlen, "%s(%04d): ", file, line );
+            }
+
+            idx += polarssl_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 = polarssl_snprintf( str, maxlen, "%s(%04d): ", file, line );
+
+        }
+        idx += polarssl_snprintf( str + idx, maxlen - idx, " 00" );
+    }
+
+    polarssl_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;
+
+        polarssl_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 )
+    {
+        polarssl_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 = polarssl_snprintf( str, maxlen, "%s(%04d): ", file, line );
+
+        polarssl_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/polarssl/des.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,1057 @@
+/*
+ *  FIPS-46-3 compliant Triple-DES implementation
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.h>
+
+#if defined(POLARSSL_SELF_TEST)
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdio.h>
+#define polarssl_printf printf
+#endif /* POLARSSL_PLATFORM_C */
+#endif /* POLARSSL_SELF_TEST */
+
+#if !defined(POLARSSL_DES_ALT)
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+/*
+ * 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; }
+
+void des_init( des_context *ctx )
+{
+    memset( ctx, 0, sizeof( des_context ) );
+}
+
+void des_free( des_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    polarssl_zeroize( ctx, sizeof( des_context ) );
+}
+
+void des3_init( des3_context *ctx )
+{
+    memset( ctx, 0, sizeof( des3_context ) );
+}
+
+void des3_free( des3_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    polarssl_zeroize( ctx, sizeof( des3_context ) );
+}
+
+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 );
+    polarssl_zeroize( sk,  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 );
+    polarssl_zeroize( sk,  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 );
+    polarssl_zeroize( sk,  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 );
+    polarssl_zeroize( sk,  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)
+/*
+ * 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, ret = 0;
+    des_context ctx;
+    des3_context ctx3;
+    unsigned char buf[8];
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    unsigned char prv[8];
+    unsigned char iv[8];
+#endif
+
+    des_init( &ctx );
+    des3_init( &ctx3 );
+    /*
+     * 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" );
+
+            ret = 1;
+            goto exit;
+        }
+
+        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" );
+
+            ret = 1;
+            goto exit;
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "passed\n" );
+    }
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+exit:
+    des_free( &ctx );
+    des3_free( &ctx3 );
+
+    return( ret );
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_DES_C */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/polarssl/dhm.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,614 @@
+/*
+ *  Diffie-Hellman-Merkle key exchange
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.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>
+#include <stdio.h>
+#define polarssl_printf     printf
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+/*
+ * 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 );
+}
+
+void dhm_init( dhm_context *ctx )
+{
+    memset( ctx, 0, sizeof( dhm_context ) );
+}
+
+/*
+ * Parse the ServerKeyExchange parameters
+ */
+int dhm_read_params( dhm_context *ctx,
+                     unsigned char **p,
+                     const unsigned char *end )
+{
+    int ret;
+
+    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 );
+
+    polarssl_zeroize( ctx, 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 );
+
+    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
+     *      privateValueLength INTEGER OPTIONAL
+     *  }
+     */
+    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 )
+    {
+        /* this might be the optional privateValueLength; If so, we
+         can cleanly discard it; */
+        mpi rec;
+        mpi_init( &rec );
+        ret = asn1_get_mpi( &p, end, &rec );
+        mpi_free( &rec );
+        if ( ret != 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 = 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 );
+
+    polarssl_zeroize( buf, 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;
+
+    dhm_init( &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" );
+
+        ret = 1;
+        goto exit;
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n\n" );
+
+exit:
+    dhm_free( &dhm );
+
+    return( ret );
+#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/polarssl/ecdh.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,280 @@
+/*
+ *  Elliptic curve Diffie-Hellman
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.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 );
+    ecp_point_free( &ctx->Q   );
+    ecp_point_free( &ctx->Qp  );
+    ecp_point_free( &ctx->Vi  );
+    ecp_point_free( &ctx->Vf  );
+    mpi_free( &ctx->d  );
+    mpi_free( &ctx->z  );
+    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/polarssl/ecdsa.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,503 @@
+/*
+ *  Elliptic curve DSA
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.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_type_t) *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 * ( 3 + 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/polarssl/ecp.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,2089 @@
+/*
+ *  Elliptic curves over GF(p): generic functions
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.h>
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdlib.h>
+#include <stdio.h>
+#define polarssl_printf     printf
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+#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 */
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+#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[] =
+{
+#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                },
+};
+
+#define ECP_NB_CURVES   sizeof( ecp_supported_curves ) /    \
+                        sizeof( ecp_supported_curves[0] )
+
+static ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES];
+
+/*
+ * 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 );
+    }
+
+    polarssl_zeroize( grp, 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( ilen < 1 )
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+
+    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 one 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 = 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
+ *
+ * Based on http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-dbl-1998-cmo-2 .
+ *
+ * We follow the variable naming fairly closely. The formula variations that trade a MUL for a SQR
+ * (plus a few ADDs) aren't useful as our bignum implementation doesn't distinguish squaring.
+ *
+ * Standard optimizations are applied when curve parameter A is one of { 0, -3 }.
+ *
+ * Cost: 1D := 3M + 4S          (A ==  0)
+ *             4M + 4S          (A == -3)
+ *             3M + 6S + 1a     otherwise
+ */
+static int ecp_double_jac( const ecp_group *grp, ecp_point *R,
+                           const ecp_point *P )
+{
+    int ret;
+    mpi M, S, T, U;
+
+#if defined(POLARSSL_SELF_TEST)
+    dbl_count++;
+#endif
+
+    mpi_init( &M ); mpi_init( &S ); mpi_init( &T ); mpi_init( &U );
+
+    /* Special case for A = -3 */
+    if( grp->A.p == NULL )
+    {
+        /* M = 3(X + Z^2)(X - Z^2) */
+        MPI_CHK( mpi_mul_mpi( &S,  &P->Z,  &P->Z   ) ); MOD_MUL( S );
+        MPI_CHK( mpi_add_mpi( &T,  &P->X,  &S      ) ); MOD_ADD( T );
+        MPI_CHK( mpi_sub_mpi( &U,  &P->X,  &S      ) ); MOD_SUB( U );
+        MPI_CHK( mpi_mul_mpi( &S,  &T,     &U      ) ); MOD_MUL( S );
+        MPI_CHK( mpi_mul_int( &M,  &S,     3       ) ); MOD_ADD( M );
+    }
+    else
+    {
+        /* M = 3.X^2 */
+        MPI_CHK( mpi_mul_mpi( &S,  &P->X,  &P->X   ) ); MOD_MUL( S );
+        MPI_CHK( mpi_mul_int( &M,  &S,     3       ) ); MOD_ADD( M );
+
+        /* Optimize away for "koblitz" curves with A = 0 */
+        if( mpi_cmp_int( &grp->A, 0 ) != 0 )
+        {
+            /* M += A.Z^4 */
+            MPI_CHK( mpi_mul_mpi( &S,  &P->Z,  &P->Z   ) ); MOD_MUL( S );
+            MPI_CHK( mpi_mul_mpi( &T,  &S,     &S      ) ); MOD_MUL( T );
+            MPI_CHK( mpi_mul_mpi( &S,  &T,     &grp->A ) ); MOD_MUL( S );
+            MPI_CHK( mpi_add_mpi( &M,  &M,     &S      ) ); MOD_ADD( M );
+        }
+    }
+
+    /* S = 4.X.Y^2 */
+    MPI_CHK( mpi_mul_mpi( &T,  &P->Y,  &P->Y   ) ); MOD_MUL( T );
+    MPI_CHK( mpi_shift_l( &T,  1               ) ); MOD_ADD( T );
+    MPI_CHK( mpi_mul_mpi( &S,  &P->X,  &T      ) ); MOD_MUL( S );
+    MPI_CHK( mpi_shift_l( &S,  1               ) ); MOD_ADD( S );
+
+    /* U = 8.Y^4 */
+    MPI_CHK( mpi_mul_mpi( &U,  &T,     &T      ) ); MOD_MUL( U );
+    MPI_CHK( mpi_shift_l( &U,  1               ) ); MOD_ADD( U );
+
+    /* T = M^2 - 2.S */
+    MPI_CHK( mpi_mul_mpi( &T,  &M,     &M      ) ); MOD_MUL( T );
+    MPI_CHK( mpi_sub_mpi( &T,  &T,     &S      ) ); MOD_SUB( T );
+    MPI_CHK( mpi_sub_mpi( &T,  &T,     &S      ) ); MOD_SUB( T );
+
+    /* S = M(S - T) - U */
+    MPI_CHK( mpi_sub_mpi( &S,  &S,     &T      ) ); MOD_SUB( S );
+    MPI_CHK( mpi_mul_mpi( &S,  &S,     &M      ) ); MOD_MUL( S );
+    MPI_CHK( mpi_sub_mpi( &S,  &S,     &U      ) ); MOD_SUB( S );
+
+    /* U = 2.Y.Z */
+    MPI_CHK( mpi_mul_mpi( &U,  &P->Y,  &P->Z   ) ); MOD_MUL( U );
+    MPI_CHK( mpi_shift_l( &U,  1               ) ); MOD_ADD( U );
+
+    MPI_CHK( mpi_copy( &R->X, &T ) );
+    MPI_CHK( mpi_copy( &R->Y, &S ) );
+    MPI_CHK( mpi_copy( &R->Z, &U ) );
+
+cleanup:
+    mpi_free( &M ); mpi_free( &S ); mpi_free( &T ); mpi_free( &U );
+
+    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 = 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 ) );
+}
+
+/*
+ * Check a public-private key pair
+ */
+int ecp_check_pub_priv( const ecp_keypair *pub, const ecp_keypair *prv )
+{
+    int ret;
+    ecp_point Q;
+    ecp_group grp;
+
+    if( pub->grp.id == POLARSSL_ECP_DP_NONE ||
+        pub->grp.id != prv->grp.id ||
+        mpi_cmp_mpi( &pub->Q.X, &prv->Q.X ) ||
+        mpi_cmp_mpi( &pub->Q.Y, &prv->Q.Y ) ||
+        mpi_cmp_mpi( &pub->Q.Z, &prv->Q.Z ) )
+    {
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+    }
+
+    ecp_point_init( &Q );
+    ecp_group_init( &grp );
+
+    /* ecp_mul() needs a non-const group... */
+    ecp_group_copy( &grp, &prv->grp );
+
+    /* Also checks d is valid */
+    MPI_CHK( ecp_mul( &grp, &Q, &prv->d, &prv->grp.G, NULL, NULL ) );
+
+    if( mpi_cmp_mpi( &Q.X, &prv->Q.X ) ||
+        mpi_cmp_mpi( &Q.Y, &prv->Q.Y ) ||
+        mpi_cmp_mpi( &Q.Z, &prv->Q.Z ) )
+    {
+        ret = POLARSSL_ERR_ECP_BAD_INPUT_DATA;
+        goto cleanup;
+    }
+
+cleanup:
+    ecp_point_free( &Q );
+    ecp_group_free( &grp );
+
+    return( ret );
+}
+
+#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/polarssl/ecp_curves.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,1380 @@
+/*
+ *  Elliptic curves over GF(p): curve-specific data and functions
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#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 */
+
+/*
+ * 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/polarssl/entropy.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,478 @@
+/*
+ *  Entropy accumulator implementation
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.h>
+
+#if defined(POLARSSL_FS_IO)
+#include <stdio.h>
+#endif
+
+#if defined(POLARSSL_SELF_TEST)
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdio.h>
+#define polarssl_printf     printf
+#endif /* POLARSSL_PLATFORM_C */
+#endif /* POLARSSL_SELF_TEST */
+
+#if defined(POLARSSL_HAVEGE_C)
+#include "polarssl/havege.h"
+#endif
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+#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 )
+{
+#if defined(POLARSSL_HAVEGE_C)
+    havege_free( &ctx->havege_data );
+#endif
+#if defined(POLARSSL_THREADING_C)
+    polarssl_mutex_free( &ctx->mutex );
+#endif
+    polarssl_zeroize( ctx, sizeof( entropy_context ) );
+}
+
+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 */
+
+#if defined(POLARSSL_SELF_TEST)
+/*
+ * Dummy source function
+ */
+static int entropy_dummy_source( void *data, unsigned char *output,
+                                 size_t len, size_t *olen )
+{
+    ((void) data);
+
+    memset( output, 0x2a, len );
+    *olen = len;
+
+    return( 0 );
+}
+
+/*
+ * The actual entropy quality is hard to test, but we can at least
+ * test that the functions don't cause errors and write the correct
+ * amount of data to buffers.
+ */
+int entropy_self_test( int verbose )
+{
+    int ret = 0;
+    entropy_context ctx;
+    unsigned char buf[ENTROPY_BLOCK_SIZE] = { 0 };
+    unsigned char acc[ENTROPY_BLOCK_SIZE] = { 0 };
+    size_t i, j;
+
+    if( verbose != 0 )
+        polarssl_printf( "  ENTROPY test: " );
+
+    entropy_init( &ctx );
+
+    ret = entropy_add_source( &ctx, entropy_dummy_source, NULL, 16 );
+    if( ret != 0 )
+        goto cleanup;
+
+    if( ( ret = entropy_gather( &ctx ) ) != 0 )
+        goto cleanup;
+
+    if( ( ret = entropy_update_manual( &ctx, buf, sizeof buf ) ) != 0 )
+        goto cleanup;
+
+    /*
+     * To test that entropy_func writes correct number of bytes:
+     * - use the whole buffer and rely on ASan to detect overruns
+     * - collect entropy 8 times and OR the result in an accumulator:
+     *   any byte should then be 0 with probably 2^(-64), so requiring
+     *   each of the 32 or 64 bytes to be non-zero has a false failure rate
+     *   of at most 2^(-58) which is acceptable.
+     */
+    for( i = 0; i < 8; i++ )
+    {
+        if( ( ret = entropy_func( &ctx, buf, sizeof( buf ) ) ) != 0 )
+            goto cleanup;
+
+        for( j = 0; j < sizeof( buf ); j++ )
+            acc[j] |= buf[j];
+    }
+
+    for( j = 0; j < sizeof( buf ); j++ )
+    {
+        if( acc[j] == 0 )
+        {
+            ret = 1;
+            goto cleanup;
+        }
+    }
+
+cleanup:
+    entropy_free( &ctx );
+
+    if( verbose != 0 )
+    {
+        if( ret != 0 )
+            polarssl_printf( "failed\n" );
+        else
+            polarssl_printf( "passed\n" );
+
+        polarssl_printf( "\n" );
+    }
+
+    return( ret != 0 );
+}
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_ENTROPY_C */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/polarssl/entropy_poll.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,211 @@
+/*
+ *  Platform-specific and custom entropy polling functions
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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 <string.h>
+#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 */
+
+/*
+ * Test for Linux getrandom() support.
+ * Since there is no wrapper in the libc yet, use the generic syscall wrapper
+ * available in GNU libc and compatible libc's (eg uClibc).
+ */
+#if defined(__linux__) && defined(__GLIBC__)
+#include <linux/version.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+#if defined(SYS_getrandom)
+#define HAVE_GETRANDOM
+static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags )
+{
+    return( syscall( SYS_getrandom, buf, buflen, flags ) );
+}
+
+#include <sys/utsname.h>
+/* Check if version is at least 3.17.0 */
+static int check_version_3_17_plus( void )
+{
+    int minor;
+    struct utsname un;
+    const char *ver;
+
+    /* Get version information */
+    uname(&un);
+    ver = un.release;
+
+    /* Check major version; assume a single digit */
+    if( ver[0] < '3' || ver[0] > '9' || ver [1] != '.' )
+        return( -1 );
+
+    if( ver[0] - '0' > 3 )
+        return( 0 );
+
+    /* Ok, so now we know major == 3, check minor.
+     * Assume 1 or 2 digits. */
+    if( ver[2] < '0' || ver[2] > '9' )
+        return( -1 );
+
+    minor = ver[2] - '0';
+
+    if( ver[3] >= '0' && ver[3] <= '9' )
+        minor = 10 * minor + ver[3] - '0';
+    else if( ver [3] != '.' )
+        return( -1 );
+
+    if( minor < 17 )
+        return( -1 );
+
+    return( 0 );
+}
+static int has_getrandom = -1;
+#endif /* SYS_getrandom */
+#endif /* __linux__ */
+
+#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);
+
+#if defined(HAVE_GETRANDOM)
+    if( has_getrandom == -1 )
+        has_getrandom = ( check_version_3_17_plus() == 0 );
+
+    if( has_getrandom )
+    {
+        int ret;
+
+        if( ( ret = getrandom_wrapper( output, len, 0 ) ) < 0 )
+            return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
+
+        *olen = ret;
+        return( 0 );
+    }
+#endif /* HAVE_GETRANDOM */
+
+    *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/polarssl/error.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,775 @@
+/*
+ *  Error message information
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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) || defined(POLARSSL_ERROR_STRERROR_DUMMY)
+#include "polarssl/error.h"
+#include <string.h>
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_snprintf snprintf
+#endif
+
+#if defined(POLARSSL_ERROR_C)
+
+#include <stdio.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_CCM_C)
+#include "polarssl/ccm.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
+
+#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
+        //
+        // BEGIN generated code
+#if defined(POLARSSL_CIPHER_C)
+        if( use_ret == -(POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE) )
+            polarssl_snprintf( buf, buflen, "CIPHER - The selected feature is not available" );
+        if( use_ret == -(POLARSSL_ERR_CIPHER_BAD_INPUT_DATA) )
+            polarssl_snprintf( buf, buflen, "CIPHER - Bad input parameters to function" );
+        if( use_ret == -(POLARSSL_ERR_CIPHER_ALLOC_FAILED) )
+            polarssl_snprintf( buf, buflen, "CIPHER - Failed to allocate memory" );
+        if( use_ret == -(POLARSSL_ERR_CIPHER_INVALID_PADDING) )
+            polarssl_snprintf( buf, buflen, "CIPHER - Input data contains invalid padding and is rejected" );
+        if( use_ret == -(POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED) )
+            polarssl_snprintf( buf, buflen, "CIPHER - Decryption of block requires a full block" );
+        if( use_ret == -(POLARSSL_ERR_CIPHER_AUTH_FAILED) )
+            polarssl_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) )
+            polarssl_snprintf( buf, buflen, "DHM - Bad input parameters to function" );
+        if( use_ret == -(POLARSSL_ERR_DHM_READ_PARAMS_FAILED) )
+            polarssl_snprintf( buf, buflen, "DHM - Reading of the DHM parameters failed" );
+        if( use_ret == -(POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED) )
+            polarssl_snprintf( buf, buflen, "DHM - Making of the DHM parameters failed" );
+        if( use_ret == -(POLARSSL_ERR_DHM_READ_PUBLIC_FAILED) )
+            polarssl_snprintf( buf, buflen, "DHM - Reading of the public values failed" );
+        if( use_ret == -(POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED) )
+            polarssl_snprintf( buf, buflen, "DHM - Making of the public value failed" );
+        if( use_ret == -(POLARSSL_ERR_DHM_CALC_SECRET_FAILED) )
+            polarssl_snprintf( buf, buflen, "DHM - Calculation of the DHM secret failed" );
+        if( use_ret == -(POLARSSL_ERR_DHM_INVALID_FORMAT) )
+            polarssl_snprintf( buf, buflen, "DHM - The ASN.1 data is not formatted correctly" );
+        if( use_ret == -(POLARSSL_ERR_DHM_MALLOC_FAILED) )
+            polarssl_snprintf( buf, buflen, "DHM - Allocation of memory failed" );
+        if( use_ret == -(POLARSSL_ERR_DHM_FILE_IO_ERROR) )
+            polarssl_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) )
+            polarssl_snprintf( buf, buflen, "ECP - Bad input parameters to function" );
+        if( use_ret == -(POLARSSL_ERR_ECP_BUFFER_TOO_SMALL) )
+            polarssl_snprintf( buf, buflen, "ECP - The buffer is too small to write to" );
+        if( use_ret == -(POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE) )
+            polarssl_snprintf( buf, buflen, "ECP - Requested curve not available" );
+        if( use_ret == -(POLARSSL_ERR_ECP_VERIFY_FAILED) )
+            polarssl_snprintf( buf, buflen, "ECP - The signature is not valid" );
+        if( use_ret == -(POLARSSL_ERR_ECP_MALLOC_FAILED) )
+            polarssl_snprintf( buf, buflen, "ECP - Memory allocation failed" );
+        if( use_ret == -(POLARSSL_ERR_ECP_RANDOM_FAILED) )
+            polarssl_snprintf( buf, buflen, "ECP - Generation of random value, such as (ephemeral) key, failed" );
+        if( use_ret == -(POLARSSL_ERR_ECP_INVALID_KEY) )
+            polarssl_snprintf( buf, buflen, "ECP - Invalid private or public key" );
+        if( use_ret == -(POLARSSL_ERR_ECP_SIG_LEN_MISMATCH) )
+            polarssl_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) )
+            polarssl_snprintf( buf, buflen, "MD - The selected feature is not available" );
+        if( use_ret == -(POLARSSL_ERR_MD_BAD_INPUT_DATA) )
+            polarssl_snprintf( buf, buflen, "MD - Bad input parameters to function" );
+        if( use_ret == -(POLARSSL_ERR_MD_ALLOC_FAILED) )
+            polarssl_snprintf( buf, buflen, "MD - Failed to allocate memory" );
+        if( use_ret == -(POLARSSL_ERR_MD_FILE_IO_ERROR) )
+            polarssl_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) )
+            polarssl_snprintf( buf, buflen, "PEM - No PEM header or footer found" );
+        if( use_ret == -(POLARSSL_ERR_PEM_INVALID_DATA) )
+            polarssl_snprintf( buf, buflen, "PEM - PEM string is not as expected" );
+        if( use_ret == -(POLARSSL_ERR_PEM_MALLOC_FAILED) )
+            polarssl_snprintf( buf, buflen, "PEM - Failed to allocate memory" );
+        if( use_ret == -(POLARSSL_ERR_PEM_INVALID_ENC_IV) )
+            polarssl_snprintf( buf, buflen, "PEM - RSA IV is not in hex-format" );
+        if( use_ret == -(POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG) )
+            polarssl_snprintf( buf, buflen, "PEM - Unsupported key encryption algorithm" );
+        if( use_ret == -(POLARSSL_ERR_PEM_PASSWORD_REQUIRED) )
+            polarssl_snprintf( buf, buflen, "PEM - Private key password can't be empty" );
+        if( use_ret == -(POLARSSL_ERR_PEM_PASSWORD_MISMATCH) )
+            polarssl_snprintf( buf, buflen, "PEM - Given private key password does not allow for correct decryption" );
+        if( use_ret == -(POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE) )
+            polarssl_snprintf( buf, buflen, "PEM - Unavailable feature, e.g. hashing/encryption combination" );
+        if( use_ret == -(POLARSSL_ERR_PEM_BAD_INPUT_DATA) )
+            polarssl_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) )
+            polarssl_snprintf( buf, buflen, "PK - Memory alloation failed" );
+        if( use_ret == -(POLARSSL_ERR_PK_TYPE_MISMATCH) )
+            polarssl_snprintf( buf, buflen, "PK - Type mismatch, eg attempt to encrypt with an ECDSA key" );
+        if( use_ret == -(POLARSSL_ERR_PK_BAD_INPUT_DATA) )
+            polarssl_snprintf( buf, buflen, "PK - Bad input parameters to function" );
+        if( use_ret == -(POLARSSL_ERR_PK_FILE_IO_ERROR) )
+            polarssl_snprintf( buf, buflen, "PK - Read/write of file failed" );
+        if( use_ret == -(POLARSSL_ERR_PK_KEY_INVALID_VERSION) )
+            polarssl_snprintf( buf, buflen, "PK - Unsupported key version" );
+        if( use_ret == -(POLARSSL_ERR_PK_KEY_INVALID_FORMAT) )
+            polarssl_snprintf( buf, buflen, "PK - Invalid key tag or value" );
+        if( use_ret == -(POLARSSL_ERR_PK_UNKNOWN_PK_ALG) )
+            polarssl_snprintf( buf, buflen, "PK - Key algorithm is unsupported (only RSA and EC are supported)" );
+        if( use_ret == -(POLARSSL_ERR_PK_PASSWORD_REQUIRED) )
+            polarssl_snprintf( buf, buflen, "PK - Private key password can't be empty" );
+        if( use_ret == -(POLARSSL_ERR_PK_PASSWORD_MISMATCH) )
+            polarssl_snprintf( buf, buflen, "PK - Given private key password does not allow for correct decryption" );
+        if( use_ret == -(POLARSSL_ERR_PK_INVALID_PUBKEY) )
+            polarssl_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) )
+            polarssl_snprintf( buf, buflen, "PK - The algorithm tag or value is invalid" );
+        if( use_ret == -(POLARSSL_ERR_PK_UNKNOWN_NAMED_CURVE) )
+            polarssl_snprintf( buf, buflen, "PK - Elliptic curve is unsupported (only NIST curves are supported)" );
+        if( use_ret == -(POLARSSL_ERR_PK_FEATURE_UNAVAILABLE) )
+            polarssl_snprintf( buf, buflen, "PK - Unavailable feature, e.g. RSA disabled for RSA key" );
+        if( use_ret == -(POLARSSL_ERR_PK_SIG_LEN_MISMATCH) )
+            polarssl_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) )
+            polarssl_snprintf( buf, buflen, "PKCS12 - Bad input parameters to function" );
+        if( use_ret == -(POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE) )
+            polarssl_snprintf( buf, buflen, "PKCS12 - Feature not available, e.g. unsupported encryption scheme" );
+        if( use_ret == -(POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT) )
+            polarssl_snprintf( buf, buflen, "PKCS12 - PBE ASN.1 data not as expected" );
+        if( use_ret == -(POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH) )
+            polarssl_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) )
+            polarssl_snprintf( buf, buflen, "PKCS5 - Bad input parameters to function" );
+        if( use_ret == -(POLARSSL_ERR_PKCS5_INVALID_FORMAT) )
+            polarssl_snprintf( buf, buflen, "PKCS5 - Unexpected ASN.1 data" );
+        if( use_ret == -(POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE) )
+            polarssl_snprintf( buf, buflen, "PKCS5 - Requested encryption or digest alg not available" );
+        if( use_ret == -(POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH) )
+            polarssl_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) )
+            polarssl_snprintf( buf, buflen, "RSA - Bad input parameters to function" );
+        if( use_ret == -(POLARSSL_ERR_RSA_INVALID_PADDING) )
+            polarssl_snprintf( buf, buflen, "RSA - Input data contains invalid padding and is rejected" );
+        if( use_ret == -(POLARSSL_ERR_RSA_KEY_GEN_FAILED) )
+            polarssl_snprintf( buf, buflen, "RSA - Something failed during generation of a key" );
+        if( use_ret == -(POLARSSL_ERR_RSA_KEY_CHECK_FAILED) )
+            polarssl_snprintf( buf, buflen, "RSA - Key failed to pass the library's validity check" );
+        if( use_ret == -(POLARSSL_ERR_RSA_PUBLIC_FAILED) )
+            polarssl_snprintf( buf, buflen, "RSA - The public key operation failed" );
+        if( use_ret == -(POLARSSL_ERR_RSA_PRIVATE_FAILED) )
+            polarssl_snprintf( buf, buflen, "RSA - The private key operation failed" );
+        if( use_ret == -(POLARSSL_ERR_RSA_VERIFY_FAILED) )
+            polarssl_snprintf( buf, buflen, "RSA - The PKCS#1 verification failed" );
+        if( use_ret == -(POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE) )
+            polarssl_snprintf( buf, buflen, "RSA - The output buffer for decryption is not large enough" );
+        if( use_ret == -(POLARSSL_ERR_RSA_RNG_FAILED) )
+            polarssl_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) )
+            polarssl_snprintf( buf, buflen, "SSL - The requested feature is not available" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_INPUT_DATA) )
+            polarssl_snprintf( buf, buflen, "SSL - Bad input parameters to function" );
+        if( use_ret == -(POLARSSL_ERR_SSL_INVALID_MAC) )
+            polarssl_snprintf( buf, buflen, "SSL - Verification of the message MAC failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_INVALID_RECORD) )
+            polarssl_snprintf( buf, buflen, "SSL - An invalid SSL record was received" );
+        if( use_ret == -(POLARSSL_ERR_SSL_CONN_EOF) )
+            polarssl_snprintf( buf, buflen, "SSL - The connection indicated an EOF" );
+        if( use_ret == -(POLARSSL_ERR_SSL_UNKNOWN_CIPHER) )
+            polarssl_snprintf( buf, buflen, "SSL - An unknown cipher was received" );
+        if( use_ret == -(POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN) )
+            polarssl_snprintf( buf, buflen, "SSL - The server has no ciphersuites in common with the client" );
+        if( use_ret == -(POLARSSL_ERR_SSL_NO_RNG) )
+            polarssl_snprintf( buf, buflen, "SSL - No RNG was provided to the SSL module" );
+        if( use_ret == -(POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE) )
+            polarssl_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) )
+            polarssl_snprintf( buf, buflen, "SSL - Our own certificate(s) is/are too large to send in an SSL message" );
+        if( use_ret == -(POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED) )
+            polarssl_snprintf( buf, buflen, "SSL - The own certificate is not set, but needed by the server" );
+        if( use_ret == -(POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED) )
+            polarssl_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) )
+            polarssl_snprintf( buf, buflen, "SSL - No CA Chain is set, but required to operate" );
+        if( use_ret == -(POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE) )
+            polarssl_snprintf( buf, buflen, "SSL - An unexpected message was received from our peer" );
+        if( use_ret == -(POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE) )
+        {
+            polarssl_snprintf( buf, buflen, "SSL - A fatal alert message was received from our peer" );
+            return;
+        }
+        if( use_ret == -(POLARSSL_ERR_SSL_PEER_VERIFY_FAILED) )
+            polarssl_snprintf( buf, buflen, "SSL - Verification of our peer failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY) )
+            polarssl_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) )
+            polarssl_snprintf( buf, buflen, "SSL - Processing of the ClientHello handshake message failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO) )
+            polarssl_snprintf( buf, buflen, "SSL - Processing of the ServerHello handshake message failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE) )
+            polarssl_snprintf( buf, buflen, "SSL - Processing of the Certificate handshake message failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST) )
+            polarssl_snprintf( buf, buflen, "SSL - Processing of the CertificateRequest handshake message failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE) )
+            polarssl_snprintf( buf, buflen, "SSL - Processing of the ServerKeyExchange handshake message failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE) )
+            polarssl_snprintf( buf, buflen, "SSL - Processing of the ServerHelloDone handshake message failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE) )
+            polarssl_snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP) )
+            polarssl_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) )
+            polarssl_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) )
+            polarssl_snprintf( buf, buflen, "SSL - Processing of the CertificateVerify handshake message failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC) )
+            polarssl_snprintf( buf, buflen, "SSL - Processing of the ChangeCipherSpec handshake message failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_FINISHED) )
+            polarssl_snprintf( buf, buflen, "SSL - Processing of the Finished handshake message failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_MALLOC_FAILED) )
+            polarssl_snprintf( buf, buflen, "SSL - Memory allocation failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_HW_ACCEL_FAILED) )
+            polarssl_snprintf( buf, buflen, "SSL - Hardware acceleration function returned with error" );
+        if( use_ret == -(POLARSSL_ERR_SSL_HW_ACCEL_FALLTHROUGH) )
+            polarssl_snprintf( buf, buflen, "SSL - Hardware acceleration function skipped / left alone data" );
+        if( use_ret == -(POLARSSL_ERR_SSL_COMPRESSION_FAILED) )
+            polarssl_snprintf( buf, buflen, "SSL - Processing of the compression / decompression failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION) )
+            polarssl_snprintf( buf, buflen, "SSL - Handshake protocol not within min/max boundaries" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_NEW_SESSION_TICKET) )
+            polarssl_snprintf( buf, buflen, "SSL - Processing of the NewSessionTicket handshake message failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_SESSION_TICKET_EXPIRED) )
+            polarssl_snprintf( buf, buflen, "SSL - Session ticket has expired" );
+        if( use_ret == -(POLARSSL_ERR_SSL_PK_TYPE_MISMATCH) )
+            polarssl_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) )
+            polarssl_snprintf( buf, buflen, "SSL - Unknown identity received (eg, PSK identity)" );
+        if( use_ret == -(POLARSSL_ERR_SSL_INTERNAL_ERROR) )
+            polarssl_snprintf( buf, buflen, "SSL - Internal error (eg, unexpected failure in lower-level module)" );
+        if( use_ret == -(POLARSSL_ERR_SSL_COUNTER_WRAPPING) )
+            polarssl_snprintf( buf, buflen, "SSL - A counter would wrap (eg, too many messages exchanged)" );
+        if( use_ret == -(POLARSSL_ERR_SSL_WAITING_SERVER_HELLO_RENEGO) )
+            polarssl_snprintf( buf, buflen, "SSL - Unexpected message at ServerHello in renegotiation" );
+        if( use_ret == -(POLARSSL_ERR_SSL_NO_USABLE_CIPHERSUITE) )
+            polarssl_snprintf( buf, buflen, "SSL - None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages)" );
+#endif /* POLARSSL_SSL_TLS_C */
+
+#if defined(POLARSSL_X509_USE_C) || defined(POLARSSL_X509_CREATE_C)
+        if( use_ret == -(POLARSSL_ERR_X509_FEATURE_UNAVAILABLE) )
+            polarssl_snprintf( buf, buflen, "X509 - Unavailable feature, e.g. RSA hashing/encryption combination" );
+        if( use_ret == -(POLARSSL_ERR_X509_UNKNOWN_OID) )
+            polarssl_snprintf( buf, buflen, "X509 - Requested OID is unknown" );
+        if( use_ret == -(POLARSSL_ERR_X509_INVALID_FORMAT) )
+            polarssl_snprintf( buf, buflen, "X509 - The CRT/CRL/CSR format is invalid, e.g. different type expected" );
+        if( use_ret == -(POLARSSL_ERR_X509_INVALID_VERSION) )
+            polarssl_snprintf( buf, buflen, "X509 - The CRT/CRL/CSR version element is invalid" );
+        if( use_ret == -(POLARSSL_ERR_X509_INVALID_SERIAL) )
+            polarssl_snprintf( buf, buflen, "X509 - The serial tag or value is invalid" );
+        if( use_ret == -(POLARSSL_ERR_X509_INVALID_ALG) )
+            polarssl_snprintf( buf, buflen, "X509 - The algorithm tag or value is invalid" );
+        if( use_ret == -(POLARSSL_ERR_X509_INVALID_NAME) )
+            polarssl_snprintf( buf, buflen, "X509 - The name tag or value is invalid" );
+        if( use_ret == -(POLARSSL_ERR_X509_INVALID_DATE) )
+            polarssl_snprintf( buf, buflen, "X509 - The date tag or value is invalid" );
+        if( use_ret == -(POLARSSL_ERR_X509_INVALID_SIGNATURE) )
+            polarssl_snprintf( buf, buflen, "X509 - The signature tag or value invalid" );
+        if( use_ret == -(POLARSSL_ERR_X509_INVALID_EXTENSIONS) )
+            polarssl_snprintf( buf, buflen, "X509 - The extension tag or value is invalid" );
+        if( use_ret == -(POLARSSL_ERR_X509_UNKNOWN_VERSION) )
+            polarssl_snprintf( buf, buflen, "X509 - CRT/CRL/CSR has an unsupported version number" );
+        if( use_ret == -(POLARSSL_ERR_X509_UNKNOWN_SIG_ALG) )
+            polarssl_snprintf( buf, buflen, "X509 - Signature algorithm (oid) is unsupported" );
+        if( use_ret == -(POLARSSL_ERR_X509_SIG_MISMATCH) )
+            polarssl_snprintf( buf, buflen, "X509 - Signature algorithms do not match. (see \\c ::x509_crt sig_oid)" );
+        if( use_ret == -(POLARSSL_ERR_X509_CERT_VERIFY_FAILED) )
+            polarssl_snprintf( buf, buflen, "X509 - Certificate verification failed, e.g. CRL, CA or signature check failed" );
+        if( use_ret == -(POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT) )
+            polarssl_snprintf( buf, buflen, "X509 - Format not recognized as DER or PEM" );
+        if( use_ret == -(POLARSSL_ERR_X509_BAD_INPUT_DATA) )
+            polarssl_snprintf( buf, buflen, "X509 - Input invalid" );
+        if( use_ret == -(POLARSSL_ERR_X509_MALLOC_FAILED) )
+            polarssl_snprintf( buf, buflen, "X509 - Allocation of memory failed" );
+        if( use_ret == -(POLARSSL_ERR_X509_FILE_IO_ERROR) )
+            polarssl_snprintf( buf, buflen, "X509 - Read/write of file failed" );
+#endif /* POLARSSL_X509_USE,X509_CREATE_C */
+        // END generated code
+
+        if( strlen( buf ) == 0 )
+            polarssl_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;
+
+        polarssl_snprintf( buf + len, buflen - len, " : " );
+
+        buf += len + 3;
+        buflen -= len + 3;
+    }
+
+    // Low level error codes
+    //
+    // BEGIN generated code
+#if defined(POLARSSL_AES_C)
+    if( use_ret == -(POLARSSL_ERR_AES_INVALID_KEY_LENGTH) )
+        polarssl_snprintf( buf, buflen, "AES - Invalid key length" );
+    if( use_ret == -(POLARSSL_ERR_AES_INVALID_INPUT_LENGTH) )
+        polarssl_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) )
+        polarssl_snprintf( buf, buflen, "ASN1 - Out of data when parsing an ASN1 data structure" );
+    if( use_ret == -(POLARSSL_ERR_ASN1_UNEXPECTED_TAG) )
+        polarssl_snprintf( buf, buflen, "ASN1 - ASN1 tag was of an unexpected value" );
+    if( use_ret == -(POLARSSL_ERR_ASN1_INVALID_LENGTH) )
+        polarssl_snprintf( buf, buflen, "ASN1 - Error when trying to determine the length or invalid length" );
+    if( use_ret == -(POLARSSL_ERR_ASN1_LENGTH_MISMATCH) )
+        polarssl_snprintf( buf, buflen, "ASN1 - Actual length differs from expected length" );
+    if( use_ret == -(POLARSSL_ERR_ASN1_INVALID_DATA) )
+        polarssl_snprintf( buf, buflen, "ASN1 - Data is invalid. (not used)" );
+    if( use_ret == -(POLARSSL_ERR_ASN1_MALLOC_FAILED) )
+        polarssl_snprintf( buf, buflen, "ASN1 - Memory allocation failed" );
+    if( use_ret == -(POLARSSL_ERR_ASN1_BUF_TOO_SMALL) )
+        polarssl_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) )
+        polarssl_snprintf( buf, buflen, "BASE64 - Output buffer too small" );
+    if( use_ret == -(POLARSSL_ERR_BASE64_INVALID_CHARACTER) )
+        polarssl_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) )
+        polarssl_snprintf( buf, buflen, "BIGNUM - An error occurred while reading from or writing to a file" );
+    if( use_ret == -(POLARSSL_ERR_MPI_BAD_INPUT_DATA) )
+        polarssl_snprintf( buf, buflen, "BIGNUM - Bad input parameters to function" );
+    if( use_ret == -(POLARSSL_ERR_MPI_INVALID_CHARACTER) )
+        polarssl_snprintf( buf, buflen, "BIGNUM - There is an invalid character in the digit string" );
+    if( use_ret == -(POLARSSL_ERR_MPI_BUFFER_TOO_SMALL) )
+        polarssl_snprintf( buf, buflen, "BIGNUM - The buffer is too small to write to" );
+    if( use_ret == -(POLARSSL_ERR_MPI_NEGATIVE_VALUE) )
+        polarssl_snprintf( buf, buflen, "BIGNUM - The input arguments are negative or result in illegal output" );
+    if( use_ret == -(POLARSSL_ERR_MPI_DIVISION_BY_ZERO) )
+        polarssl_snprintf( buf, buflen, "BIGNUM - The input argument for division is zero, which is not allowed" );
+    if( use_ret == -(POLARSSL_ERR_MPI_NOT_ACCEPTABLE) )
+        polarssl_snprintf( buf, buflen, "BIGNUM - The input arguments are not acceptable" );
+    if( use_ret == -(POLARSSL_ERR_MPI_MALLOC_FAILED) )
+        polarssl_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) )
+        polarssl_snprintf( buf, buflen, "BLOWFISH - Invalid key length" );
+    if( use_ret == -(POLARSSL_ERR_BLOWFISH_INVALID_INPUT_LENGTH) )
+        polarssl_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) )
+        polarssl_snprintf( buf, buflen, "CAMELLIA - Invalid key length" );
+    if( use_ret == -(POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH) )
+        polarssl_snprintf( buf, buflen, "CAMELLIA - Invalid data input length" );
+#endif /* POLARSSL_CAMELLIA_C */
+
+#if defined(POLARSSL_CCM_C)
+    if( use_ret == -(POLARSSL_ERR_CCM_BAD_INPUT) )
+        polarssl_snprintf( buf, buflen, "CCM - Bad input parameters to function" );
+    if( use_ret == -(POLARSSL_ERR_CCM_AUTH_FAILED) )
+        polarssl_snprintf( buf, buflen, "CCM - Authenticated decryption failed" );
+#endif /* POLARSSL_CCM_C */
+
+#if defined(POLARSSL_CTR_DRBG_C)
+    if( use_ret == -(POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED) )
+        polarssl_snprintf( buf, buflen, "CTR_DRBG - The entropy source failed" );
+    if( use_ret == -(POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG) )
+        polarssl_snprintf( buf, buflen, "CTR_DRBG - Too many random requested in single call" );
+    if( use_ret == -(POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG) )
+        polarssl_snprintf( buf, buflen, "CTR_DRBG - Input too large (Entropy + additional)" );
+    if( use_ret == -(POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR) )
+        polarssl_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) )
+        polarssl_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) )
+        polarssl_snprintf( buf, buflen, "ENTROPY - Critical entropy source failure" );
+    if( use_ret == -(POLARSSL_ERR_ENTROPY_MAX_SOURCES) )
+        polarssl_snprintf( buf, buflen, "ENTROPY - No more sources can be added" );
+    if( use_ret == -(POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED) )
+        polarssl_snprintf( buf, buflen, "ENTROPY - No sources have been added to poll" );
+    if( use_ret == -(POLARSSL_ERR_ENTROPY_FILE_IO_ERROR) )
+        polarssl_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) )
+        polarssl_snprintf( buf, buflen, "GCM - Authenticated decryption failed" );
+    if( use_ret == -(POLARSSL_ERR_GCM_BAD_INPUT) )
+        polarssl_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) )
+        polarssl_snprintf( buf, buflen, "HMAC_DRBG - Too many random requested in single call" );
+    if( use_ret == -(POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG) )
+        polarssl_snprintf( buf, buflen, "HMAC_DRBG - Input too large (Entropy + additional)" );
+    if( use_ret == -(POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR) )
+        polarssl_snprintf( buf, buflen, "HMAC_DRBG - Read/write error in file" );
+    if( use_ret == -(POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED) )
+        polarssl_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) )
+        polarssl_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) )
+        polarssl_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) )
+        polarssl_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) )
+        polarssl_snprintf( buf, buflen, "NET - Failed to get an IP address for the given hostname" );
+    if( use_ret == -(POLARSSL_ERR_NET_SOCKET_FAILED) )
+        polarssl_snprintf( buf, buflen, "NET - Failed to open a socket" );
+    if( use_ret == -(POLARSSL_ERR_NET_CONNECT_FAILED) )
+        polarssl_snprintf( buf, buflen, "NET - The connection to the given server / port failed" );
+    if( use_ret == -(POLARSSL_ERR_NET_BIND_FAILED) )
+        polarssl_snprintf( buf, buflen, "NET - Binding of the socket failed" );
+    if( use_ret == -(POLARSSL_ERR_NET_LISTEN_FAILED) )
+        polarssl_snprintf( buf, buflen, "NET - Could not listen on the socket" );
+    if( use_ret == -(POLARSSL_ERR_NET_ACCEPT_FAILED) )
+        polarssl_snprintf( buf, buflen, "NET - Could not accept the incoming connection" );
+    if( use_ret == -(POLARSSL_ERR_NET_RECV_FAILED) )
+        polarssl_snprintf( buf, buflen, "NET - Reading information from the socket failed" );
+    if( use_ret == -(POLARSSL_ERR_NET_SEND_FAILED) )
+        polarssl_snprintf( buf, buflen, "NET - Sending information through the socket failed" );
+    if( use_ret == -(POLARSSL_ERR_NET_CONN_RESET) )
+        polarssl_snprintf( buf, buflen, "NET - Connection was reset by peer" );
+    if( use_ret == -(POLARSSL_ERR_NET_WANT_READ) )
+        polarssl_snprintf( buf, buflen, "NET - Connection requires a read call" );
+    if( use_ret == -(POLARSSL_ERR_NET_WANT_WRITE) )
+        polarssl_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) )
+        polarssl_snprintf( buf, buflen, "OID - OID is not found" );
+    if( use_ret == -(POLARSSL_ERR_OID_BUF_TOO_SMALL) )
+        polarssl_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) )
+        polarssl_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) )
+        polarssl_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) )
+        polarssl_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) )
+        polarssl_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) )
+        polarssl_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) )
+        polarssl_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) )
+        polarssl_snprintf( buf, buflen, "THREADING - The selected feature is not available" );
+    if( use_ret == -(POLARSSL_ERR_THREADING_BAD_INPUT_DATA) )
+        polarssl_snprintf( buf, buflen, "THREADING - Bad input parameters to function" );
+    if( use_ret == -(POLARSSL_ERR_THREADING_MUTEX_ERROR) )
+        polarssl_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) )
+        polarssl_snprintf( buf, buflen, "XTEA - The data input has an invalid length" );
+#endif /* POLARSSL_XTEA_C */
+    // END generated code
+
+    if( strlen( buf ) != 0 )
+        return;
+
+    polarssl_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)
+
+/*
+ * 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/polarssl/gcm.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,947 @@
+/*
+ *  NIST SP800-38D compliant GCM implementation
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.h>
+
+#if defined(POLARSSL_AESNI_C)
+#include "polarssl/aesni.h"
+#endif
+
+#if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_AES_C)
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdio.h>
+#define polarssl_printf printf
+#endif /* POLARSSL_PLATFORM_C */
+#endif /* POLARSSL_SELF_TEST && POLARSSL_AES_C */
+
+/*
+ * 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
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+/*
+ * 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 <= 8; i *= 2 )
+    {
+        uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
+        vh = *HiH;
+        vl = *HiL;
+        for( j = 1; j < i; j++ )
+        {
+            HiH[j] = vh ^ ctx->HH[j];
+            HiL[j] = vl ^ ctx->HL[j];
+        }
+    }
+
+    return( 0 );
+}
+
+int 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_init( &ctx->cipher_ctx );
+
+    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 );
+
+    cipher_free( &ctx->cipher_ctx );
+
+    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 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 */
+
+    lo = x[15] & 0xf;
+
+    zh = ctx->HH[lo];
+    zl = ctx->HL[lo];
+
+    for( i = 15; i >= 0; i-- )
+    {
+        lo = x[i] & 0xf;
+        hi = x[i] >> 4;
+
+        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;
+
+    /* IV and AD are limited to 2^64 bits, so 2^61 bytes */
+    if( ( (uint64_t) iv_len  ) >> 61 != 0 ||
+        ( (uint64_t) add_len ) >> 61 != 0 )
+    {
+        return( POLARSSL_ERR_GCM_BAD_INPUT );
+    }
+
+    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 );
+
+    /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
+     * Also check for possible overflow */
+    if( ctx->len + length < ctx->len ||
+        (uint64_t) ctx->len + length > 0x03FFFFE0ull )
+    {
+        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 || tag_len < 4 )
+        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 )
+    {
+        polarssl_zeroize( output, length );
+        return( POLARSSL_ERR_GCM_AUTH_FAILED );
+    }
+
+    return( 0 );
+}
+
+void gcm_free( gcm_context *ctx )
+{
+    cipher_free( &ctx->cipher_ctx );
+    polarssl_zeroize( ctx, sizeof( gcm_context ) );
+}
+
+#if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_AES_C)
+/*
+ * AES-GCM test vectors from:
+ *
+ * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
+ */
+#define MAX_TESTS   6
+
+static const int key_index[MAX_TESTS] =
+    { 0, 0, 1, 1, 1, 1 };
+
+static const 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 },
+};
+
+static const size_t iv_len[MAX_TESTS] =
+    { 12, 12, 12, 12, 8, 60 };
+
+static const int iv_index[MAX_TESTS] =
+    { 0, 0, 1, 1, 1, 2 };
+
+static const 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 },
+};
+
+static const size_t add_len[MAX_TESTS] =
+    { 0, 0, 0, 20, 20, 20 };
+
+static const int add_index[MAX_TESTS] =
+    { 0, 0, 0, 1, 1, 1 };
+
+static const 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 },
+};
+
+static const size_t pt_len[MAX_TESTS] =
+    { 0, 16, 64, 60, 60, 60 };
+
+static const int pt_index[MAX_TESTS] =
+    { 0, 0, 1, 1, 1, 1 };
+
+static const 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 },
+};
+
+static const 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 },
+};
+
+static const 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/polarssl/havege.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,245 @@
+/**
+ *  \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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>
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+/* ------------------------------------------------------------------------
+ * 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 );
+}
+
+void havege_free( havege_state *hs )
+{
+    if( hs == NULL )
+        return;
+
+    polarssl_zeroize( hs, sizeof( havege_state ) );
+}
+
+/*
+ * 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/polarssl/hmac_drbg.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,503 @@
+/*
+ *  HMAC_DRBG implementation (NIST SP 800-90)
+ *
+ *  Copyright (C) 2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.h>
+
+#if defined(POLARSSL_FS_IO)
+#include <stdio.h>
+#endif
+
+#if defined(POLARSSL_SELF_TEST)
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdio.h>
+#define polarssl_printf printf
+#endif /* POLARSSL_SELF_TEST */
+#endif /* POLARSSL_PLATFORM_C */
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+/*
+ * 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 ) );
+
+    md_init( &ctx->md_ctx );
+
+    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 ) );
+
+    md_init( &ctx->md_ctx );
+
+    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->md_ctx );
+
+    polarssl_zeroize( ctx, 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)
+
+#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 const 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 const 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, (void *) 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, (void *) 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/polarssl/md.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,342 @@
+/**
+ * \file md.c
+ *
+ * \brief Generic message digest wrapper for mbed TLS
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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>
+#include <string.h>
+
+#if defined(_MSC_VER) && !defined strcasecmp && !defined(EFIX64) && \
+    !defined(EFI32)
+#define strcasecmp  _stricmp
+#endif
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+static const int supported_digests[] = {
+
+#if defined(POLARSSL_SHA512_C)
+        POLARSSL_MD_SHA512,
+        POLARSSL_MD_SHA384,
+#endif
+
+#if defined(POLARSSL_SHA256_C)
+        POLARSSL_MD_SHA256,
+        POLARSSL_MD_SHA224,
+#endif
+
+#if defined(POLARSSL_SHA1_C)
+        POLARSSL_MD_SHA1,
+#endif
+
+#if defined(POLARSSL_RIPEMD160_C)
+        POLARSSL_MD_RIPEMD160,
+#endif
+
+#if defined(POLARSSL_MD5_C)
+        POLARSSL_MD_MD5,
+#endif
+
+#if defined(POLARSSL_MD4_C)
+        POLARSSL_MD_MD4,
+#endif
+
+#if defined(POLARSSL_MD2_C)
+        POLARSSL_MD_MD2,
+#endif
+
+        POLARSSL_MD_NONE
+};
+
+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 );
+    }
+}
+
+void md_init( md_context_t *ctx )
+{
+    memset( ctx, 0, sizeof( md_context_t ) );
+}
+
+void md_free( md_context_t *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    if( ctx->md_ctx )
+        ctx->md_info->ctx_free_func( ctx->md_ctx );
+
+    polarssl_zeroize( ctx, sizeof( md_context_t ) );
+}
+
+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 );
+}
+
+#if ! defined(POLARSSL_DEPRECATED_REMOVED)
+int md_free_ctx( md_context_t *ctx )
+{
+    md_free( ctx );
+
+    return( 0 );
+}
+#endif
+
+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/polarssl/md2.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,401 @@
+/*
+ *  RFC 1115/1319 compliant MD2 implementation
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.h>
+
+#if defined(POLARSSL_FS_IO)
+#include <stdio.h>
+#endif
+
+#if defined(POLARSSL_SELF_TEST)
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdio.h>
+#define polarssl_printf printf
+#endif /* POLARSSL_PLATFORM_C */
+#endif /* POLARSSL_SELF_TEST */
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+#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
+};
+
+void md2_init( md2_context *ctx )
+{
+    memset( ctx, 0, sizeof( md2_context ) );
+}
+
+void md2_free( md2_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    polarssl_zeroize( ctx, sizeof( md2_context ) );
+}
+
+/*
+ * 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_init( &ctx );
+    md2_starts( &ctx );
+    md2_update( &ctx, input, ilen );
+    md2_finish( &ctx, output );
+    md2_free( &ctx );
+}
+
+#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_init( &ctx );
+    md2_starts( &ctx );
+
+    while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+        md2_update( &ctx, buf, n );
+
+    md2_finish( &ctx, output );
+    md2_free( &ctx );
+
+    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 );
+
+    polarssl_zeroize( sum, 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 );
+
+    polarssl_zeroize( tmpbuf, 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_init( &ctx );
+    md2_hmac_starts( &ctx, key, keylen );
+    md2_hmac_update( &ctx, input, ilen );
+    md2_hmac_finish( &ctx, output );
+    md2_free( &ctx );
+}
+
+#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/polarssl/md4.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,497 @@
+/*
+ *  RFC 1186/1320 compliant MD4 implementation
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.h>
+
+#if defined(POLARSSL_FS_IO)
+#include <stdio.h>
+#endif
+
+#if defined(POLARSSL_SELF_TEST)
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdio.h>
+#define polarssl_printf printf
+#endif /* POLARSSL_PLATFORM_C */
+#endif /* POLARSSL_SELF_TEST */
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+#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)       ) & 0xFF );    \
+    (b)[(i) + 1] = (unsigned char) ( ( (n) >>  8 ) & 0xFF );    \
+    (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF );    \
+    (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF );    \
+}
+#endif
+
+void md4_init( md4_context *ctx )
+{
+    memset( ctx, 0, sizeof( md4_context ) );
+}
+
+void md4_free( md4_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    polarssl_zeroize( ctx, sizeof( md4_context ) );
+}
+
+/*
+ * 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_init( &ctx );
+    md4_starts( &ctx );
+    md4_update( &ctx, input, ilen );
+    md4_finish( &ctx, output );
+    md4_free( &ctx );
+}
+
+#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_init( &ctx );
+    md4_starts( &ctx );
+
+    while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+        md4_update( &ctx, buf, n );
+
+    md4_finish( &ctx, output );
+    md4_free( &ctx );
+
+    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 );
+
+    polarssl_zeroize( sum, 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 );
+
+    polarssl_zeroize( tmpbuf, 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_init( &ctx );
+    md4_hmac_starts( &ctx, key, keylen );
+    md4_hmac_update( &ctx, input, ilen );
+    md4_hmac_finish( &ctx, output );
+    md4_free( &ctx );
+}
+
+#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/polarssl/md5.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,618 @@
+/*
+ *  RFC 1321 compliant MD5 implementation
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.h>
+
+#if defined(POLARSSL_FS_IO)
+#include <stdio.h>
+#endif
+
+#if defined(POLARSSL_SELF_TEST)
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdio.h>
+#define polarssl_printf printf
+#endif /* POLARSSL_PLATFORM_C */
+#endif /* POLARSSL_SELF_TEST */
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+#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)       ) & 0xFF );    \
+    (b)[(i) + 1] = (unsigned char) ( ( (n) >>  8 ) & 0xFF );    \
+    (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF );    \
+    (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF );    \
+}
+#endif
+
+void md5_init( md5_context *ctx )
+{
+    memset( ctx, 0, sizeof( md5_context ) );
+}
+
+void md5_free( md5_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    polarssl_zeroize( ctx, sizeof( md5_context ) );
+}
+
+/*
+ * 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_init( &ctx );
+    md5_starts( &ctx );
+    md5_update( &ctx, input, ilen );
+    md5_finish( &ctx, output );
+    md5_free( &ctx );
+}
+
+#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_init( &ctx );
+    md5_starts( &ctx );
+
+    while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+        md5_update( &ctx, buf, n );
+
+    md5_finish( &ctx, output );
+    md5_free( &ctx );
+
+    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 );
+
+    polarssl_zeroize( sum, 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 );
+
+    polarssl_zeroize( tmpbuf, 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_init( &ctx );
+    md5_hmac_starts( &ctx, key, keylen );
+    md5_hmac_update( &ctx, input, ilen );
+    md5_hmac_finish( &ctx, output );
+    md5_free( &ctx );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+/*
+ * RFC 1321 test vectors
+ */
+static const 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 const 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 const 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, 0xAA, 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/polarssl/md_wrap.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,952 @@
+/**
+ * \file md_wrap.c
+
+ * \brief Generic message digest wrapper for mbed TLS
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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
+#include <stdlib.h>
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+#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_zeroize( ctx, sizeof( md2_context ) );
+    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_zeroize( ctx, sizeof( md4_context ) );
+    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_zeroize( ctx, sizeof( md5_context ) );
+    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 )
+{
+    ripemd160_context *ctx;
+    ctx = polarssl_malloc( sizeof( ripemd160_context ) );
+
+    if( ctx == NULL )
+        return( NULL );
+
+    ripemd160_init( ctx );
+
+    return( ctx );
+}
+
+static void ripemd160_ctx_free( void *ctx )
+{
+    ripemd160_free( (ripemd160_context *) 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 )
+{
+    sha1_context *ctx;
+    ctx = polarssl_malloc( sizeof( sha1_context ) );
+
+    if( ctx == NULL )
+        return( NULL );
+
+    sha1_init( ctx );
+
+    return( ctx );
+}
+
+static void sha1_ctx_free( void *ctx )
+{
+    sha1_free( (sha1_context *) 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_zeroize( ctx, sizeof( sha256_context ) );
+    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 )
+{
+    sha256_context *ctx;
+    ctx = polarssl_malloc( sizeof( sha256_context ) );
+
+    if( ctx == NULL )
+        return( NULL );
+
+    sha256_init( ctx );
+
+    return( ctx );
+}
+
+static void sha256_ctx_free( void *ctx )
+{
+    sha256_free( (sha256_context *) 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_zeroize( ctx, sizeof( sha512_context ) );
+    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 )
+{
+    sha512_context *ctx;
+    ctx = polarssl_malloc( sizeof( sha512_context ) );
+
+    if( ctx == NULL )
+        return( NULL );
+
+    sha512_init( ctx );
+
+    return( ctx );
+}
+
+static void sha512_ctx_free( void *ctx )
+{
+    sha512_free( (sha512_context *) 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/polarssl/memory_buffer_alloc.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,735 @@
+/*
+ *  Buffer-based memory allocator
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+/* No need for the header guard as POLARSSL_MEMORY_BUFFER_ALLOC_C
+   is dependent upon POLARSSL_PLATFORM_C */
+#include "polarssl/platform.h"
+
+#include <string.h>
+
+#if defined(POLARSSL_MEMORY_BACKTRACE)
+#include <execinfo.h>
+#endif
+
+#if defined(POLARSSL_THREADING_C)
+#include "polarssl/threading.h"
+#endif
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+#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;
+    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(%10zu), PREV(%10zu), NEXT(%10zu), "
+                              "ALLOC(%zu), SIZE(%10zu)\n",
+                      (size_t) hdr, (size_t) hdr->prev, (size_t) hdr->next,
+                      hdr->alloc, hdr->size );
+    polarssl_fprintf( stderr, "      FPREV(%10zu), FNEXT(%10zu)\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
+        polarssl_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 )
+            polarssl_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 )
+        polarssl_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
+        polarssl_exit( 1 );
+    }
+
+    p -= sizeof(memory_header);
+    hdr = (memory_header *) p;
+
+    if( verify_header( hdr ) != 0 )
+        polarssl_exit( 1 );
+
+    if( hdr->alloc != 1 )
+    {
+#if defined(POLARSSL_MEMORY_DEBUG)
+        polarssl_fprintf( stderr, "FATAL: polarssl_free() on unallocated "
+                                  "data\n" );
+#endif
+        polarssl_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;
+        if( heap.first_free != NULL )
+            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 )
+        polarssl_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: %zu blocks / %zu bytes, max: %zu blocks / "
+                      "%zu bytes (total %zu bytes), malloc / free: %zu / %zu\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();
+    }
+}
+
+void memory_buffer_alloc_max_get( size_t *max_used, size_t *max_blocks )
+{
+    *max_used   = heap.maximum_used;
+    *max_blocks = heap.maximum_header_count;
+}
+
+void memory_buffer_alloc_max_reset( void )
+{
+    heap.maximum_used = 0;
+    heap.maximum_header_count = 0;
+}
+
+void memory_buffer_alloc_cur_get( size_t *cur_used, size_t *cur_blocks )
+{
+    *cur_used   = heap.total_used;
+    *cur_blocks = heap.header_count;
+}
+#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
+
+    if( (size_t) buf % POLARSSL_MEMORY_ALIGN_MULTIPLE )
+    {
+        /* Adjust len first since buf is used in the computation */
+        len -= POLARSSL_MEMORY_ALIGN_MULTIPLE
+             - (size_t) buf % POLARSSL_MEMORY_ALIGN_MULTIPLE;
+        buf += POLARSSL_MEMORY_ALIGN_MULTIPLE
+             - (size_t) buf % POLARSSL_MEMORY_ALIGN_MULTIPLE;
+    }
+
+    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
+    polarssl_zeroize( &heap, sizeof(buffer_alloc_ctx) );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+static int check_pointer( void *p )
+{
+    if( p == NULL )
+        return( -1 );
+
+    if( (size_t) p % POLARSSL_MEMORY_ALIGN_MULTIPLE != 0 )
+        return( -1 );
+
+    return( 0 );
+}
+
+static int check_all_free( )
+{
+    if(
+#if defined(POLARSSL_MEMORY_DEBUG)
+        heap.total_used != 0 ||
+#endif
+        heap.first != heap.first_free ||
+        (void *) heap.first != (void *) heap.buf )
+    {
+        return( -1 );
+    }
+
+    return( 0 );
+}
+
+#define TEST_ASSERT( condition )            \
+    if( ! (condition) )                     \
+    {                                       \
+        if( verbose != 0 )                  \
+            polarssl_printf( "failed\n" );  \
+                                            \
+        ret = 1;                            \
+        goto cleanup;                       \
+    }
+
+int memory_buffer_alloc_self_test( int verbose )
+{
+    unsigned char buf[1024];
+    unsigned char *p, *q, *r, *end;
+    int ret = 0;
+
+    if( verbose != 0 )
+        polarssl_printf( "  MBA test #1 (basic alloc-free cycle): " );
+
+    memory_buffer_alloc_init( buf, sizeof( buf ) );
+
+    p = polarssl_malloc( 1 );
+    q = polarssl_malloc( 128 );
+    r = polarssl_malloc( 16 );
+
+    TEST_ASSERT( check_pointer( p ) == 0 &&
+                 check_pointer( q ) == 0 &&
+                 check_pointer( r ) == 0 );
+
+    polarssl_free( r );
+    polarssl_free( q );
+    polarssl_free( p );
+
+    TEST_ASSERT( check_all_free( ) == 0 );
+
+    /* Memorize end to compare with the next test */
+    end = heap.buf + heap.len;
+
+    memory_buffer_alloc_free( );
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n" );
+
+    if( verbose != 0 )
+        polarssl_printf( "  MBA test #2 (buf not aligned): " );
+
+    memory_buffer_alloc_init( buf + 1, sizeof( buf ) - 1 );
+
+    TEST_ASSERT( heap.buf + heap.len == end );
+
+    p = polarssl_malloc( 1 );
+    q = polarssl_malloc( 128 );
+    r = polarssl_malloc( 16 );
+
+    TEST_ASSERT( check_pointer( p ) == 0 &&
+                 check_pointer( q ) == 0 &&
+                 check_pointer( r ) == 0 );
+
+    polarssl_free( r );
+    polarssl_free( q );
+    polarssl_free( p );
+
+    TEST_ASSERT( check_all_free( ) == 0 );
+
+    memory_buffer_alloc_free( );
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n" );
+
+    if( verbose != 0 )
+        polarssl_printf( "  MBA test #3 (full): " );
+
+    memory_buffer_alloc_init( buf, sizeof( buf ) );
+
+    p = polarssl_malloc( sizeof( buf ) - sizeof( memory_header ) );
+
+    TEST_ASSERT( check_pointer( p ) == 0 );
+    TEST_ASSERT( polarssl_malloc( 1 ) == NULL );
+
+    polarssl_free( p );
+
+    p = polarssl_malloc( sizeof( buf ) - 2 * sizeof( memory_header ) - 16 );
+    q = polarssl_malloc( 16 );
+
+    TEST_ASSERT( check_pointer( p ) == 0 && check_pointer( q ) == 0 );
+    TEST_ASSERT( polarssl_malloc( 1 ) == NULL );
+
+    polarssl_free( q );
+
+    TEST_ASSERT( polarssl_malloc( 17 ) == NULL );
+
+    polarssl_free( p );
+
+    TEST_ASSERT( check_all_free( ) == 0 );
+
+    memory_buffer_alloc_free( );
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n" );
+
+cleanup:
+    memory_buffer_alloc_free( );
+
+    return( ret );
+}
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_MEMORY_BUFFER_ALLOC_C */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/polarssl/net.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,587 @@
+/*
+ *  TCP networking functions
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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_NET_C)
+
+#include "polarssl/net.h"
+
+#include <string.h>
+
+#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
+    !defined(EFI32)
+
+#if defined(POLARSSL_HAVE_IPV6)
+#ifdef _WIN32_WINNT
+#undef _WIN32_WINNT
+#endif
+/* Enables getaddrinfo() & Co */
+#define _WIN32_WINNT 0x0501
+#include <ws2tcpip.h>
+#endif
+
+#include <winsock2.h>
+#include <windows.h>
+
+#if defined(_MSC_VER)
+#if defined(_WIN32_WCE)
+#pragma comment( lib, "ws2.lib" )
+#else
+#pragma comment( lib, "ws2_32.lib" )
+#endif
+#endif /* _MSC_VER */
+
+#define read(fd,buf,len)        recv(fd,(char*)buf,(int) len,0)
+#define write(fd,buf,len)       send(fd,(char*)buf,(int) len,0)
+#define close(fd)               closesocket(fd)
+
+static int wsa_init_done = 0;
+
+#else /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#if defined(POLARSSL_HAVE_TIME)
+#include <sys/time.h>
+#endif
+#include <unistd.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <errno.h>
+
+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) ||  \
+    defined(__DragonFly__)
+#include <sys/endian.h>
+#elif defined(__APPLE__) || defined(HAVE_MACHINE_ENDIAN_H) ||   \
+      defined(EFIX64) || defined(EFI32)
+#include <machine/endian.h>
+#elif defined(sun)
+#include <sys/isa_defs.h>
+#elif defined(_AIX) || defined(HAVE_ARPA_NAMESER_COMPAT_H)
+#include <arpa/nameser_compat.h>
+#else
+#include <endian.h>
+#endif
+
+#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#if defined(_MSC_VER) && !defined  snprintf && !defined(EFIX64) && \
+    !defined(EFI32)
+#define  snprintf  _snprintf
+#endif
+
+#if defined(POLARSSL_HAVE_TIME)
+#include <time.h>
+#endif
+
+#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
+#include <basetsd.h>
+typedef UINT32 uint32_t;
+#else
+#include <inttypes.h>
+#endif
+
+/*
+ * htons() is not always available.
+ * By default go for LITTLE_ENDIAN variant. Otherwise hope for _BYTE_ORDER and
+ * __BIG_ENDIAN to help determine endianness.
+ */
+#if defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) &&                   \
+    __BYTE_ORDER == __BIG_ENDIAN
+#define POLARSSL_HTONS(n) (n)
+#define POLARSSL_HTONL(n) (n)
+#else
+#define POLARSSL_HTONS(n) ((((unsigned short)(n) & 0xFF      ) << 8 ) | \
+                           (((unsigned short)(n) & 0xFF00    ) >> 8 ))
+#define POLARSSL_HTONL(n) ((((unsigned long )(n) & 0xFF      ) << 24) | \
+                           (((unsigned long )(n) & 0xFF00    ) << 8 ) | \
+                           (((unsigned long )(n) & 0xFF0000  ) >> 8 ) | \
+                           (((unsigned long )(n) & 0xFF000000) >> 24))
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_snprintf snprintf
+#endif
+
+unsigned short net_htons( unsigned short n );
+unsigned long  net_htonl( unsigned long  n );
+#define net_htons(n) POLARSSL_HTONS(n)
+#define net_htonl(n) POLARSSL_HTONL(n)
+
+/*
+ * Prepare for using the sockets interface
+ */
+static int net_prepare( void )
+{
+#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
+    !defined(EFI32)
+    WSADATA wsaData;
+
+    if( wsa_init_done == 0 )
+    {
+        if( WSAStartup( MAKEWORD(2,0), &wsaData ) != 0 )
+            return( POLARSSL_ERR_NET_SOCKET_FAILED );
+
+        wsa_init_done = 1;
+    }
+#else
+#if !defined(EFIX64) && !defined(EFI32)
+    signal( SIGPIPE, SIG_IGN );
+#endif
+#endif
+    return( 0 );
+}
+
+/*
+ * Initiate a TCP connection with host:port
+ */
+int net_connect( int *fd, const char *host, int port )
+{
+#if defined(POLARSSL_HAVE_IPV6)
+    int ret;
+    struct addrinfo hints, *addr_list, *cur;
+    char port_str[6];
+
+    if( ( ret = net_prepare() ) != 0 )
+        return( ret );
+
+    /* getaddrinfo expects port as a string */
+    memset( port_str, 0, sizeof( port_str ) );
+    polarssl_snprintf( port_str, sizeof( port_str ), "%d", port );
+
+    /* Do name resolution with both IPv6 and IPv4, but only TCP */
+    memset( &hints, 0, sizeof( hints ) );
+    hints.ai_family = AF_UNSPEC;
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_protocol = IPPROTO_TCP;
+
+    if( getaddrinfo( host, port_str, &hints, &addr_list ) != 0 )
+        return( POLARSSL_ERR_NET_UNKNOWN_HOST );
+
+    /* Try the sockaddrs until a connection succeeds */
+    ret = POLARSSL_ERR_NET_UNKNOWN_HOST;
+    for( cur = addr_list; cur != NULL; cur = cur->ai_next )
+    {
+        *fd = (int) socket( cur->ai_family, cur->ai_socktype,
+                            cur->ai_protocol );
+        if( *fd < 0 )
+        {
+            ret = POLARSSL_ERR_NET_SOCKET_FAILED;
+            continue;
+        }
+
+        if( connect( *fd, cur->ai_addr, cur->ai_addrlen ) == 0 )
+        {
+            ret = 0;
+            break;
+        }
+
+        close( *fd );
+        ret = POLARSSL_ERR_NET_CONNECT_FAILED;
+    }
+
+    freeaddrinfo( addr_list );
+
+    return( ret );
+
+#else
+    /* Legacy IPv4-only version */
+
+    int ret;
+    struct sockaddr_in server_addr;
+    struct hostent *server_host;
+
+    if( ( ret = net_prepare() ) != 0 )
+        return( ret );
+
+    if( ( server_host = gethostbyname( host ) ) == NULL )
+        return( POLARSSL_ERR_NET_UNKNOWN_HOST );
+
+    if( ( *fd = (int) socket( AF_INET, SOCK_STREAM, IPPROTO_IP ) ) < 0 )
+        return( POLARSSL_ERR_NET_SOCKET_FAILED );
+
+    memcpy( (void *) &server_addr.sin_addr,
+            (void *) server_host->h_addr,
+                     server_host->h_length );
+
+    server_addr.sin_family = AF_INET;
+    server_addr.sin_port   = net_htons( port );
+
+    if( connect( *fd, (struct sockaddr *) &server_addr,
+                 sizeof( server_addr ) ) < 0 )
+    {
+        close( *fd );
+        return( POLARSSL_ERR_NET_CONNECT_FAILED );
+    }
+
+    return( 0 );
+#endif /* POLARSSL_HAVE_IPV6 */
+}
+
+/*
+ * Create a listening socket on bind_ip:port
+ */
+int net_bind( int *fd, const char *bind_ip, int port )
+{
+#if defined(POLARSSL_HAVE_IPV6)
+    int n, ret;
+    struct addrinfo hints, *addr_list, *cur;
+    char port_str[6];
+
+    if( ( ret = net_prepare() ) != 0 )
+        return( ret );
+
+    /* getaddrinfo expects port as a string */
+    memset( port_str, 0, sizeof( port_str ) );
+    polarssl_snprintf( port_str, sizeof( port_str ), "%d", port );
+
+    /* Bind to IPv6 and/or IPv4, but only in TCP */
+    memset( &hints, 0, sizeof( hints ) );
+    hints.ai_family = AF_UNSPEC;
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_protocol = IPPROTO_TCP;
+    if( bind_ip == NULL )
+        hints.ai_flags = AI_PASSIVE;
+
+    if( getaddrinfo( bind_ip, port_str, &hints, &addr_list ) != 0 )
+        return( POLARSSL_ERR_NET_UNKNOWN_HOST );
+
+    /* Try the sockaddrs until a binding succeeds */
+    ret = POLARSSL_ERR_NET_UNKNOWN_HOST;
+    for( cur = addr_list; cur != NULL; cur = cur->ai_next )
+    {
+        *fd = (int) socket( cur->ai_family, cur->ai_socktype,
+                            cur->ai_protocol );
+        if( *fd < 0 )
+        {
+            ret = POLARSSL_ERR_NET_SOCKET_FAILED;
+            continue;
+        }
+
+        n = 1;
+        if( setsockopt( *fd, SOL_SOCKET, SO_REUSEADDR,
+                        (const char *) &n, sizeof( n ) ) != 0 )
+        {
+            close( *fd );
+            ret = POLARSSL_ERR_NET_SOCKET_FAILED;
+            continue;
+        }
+
+        if( bind( *fd, cur->ai_addr, cur->ai_addrlen ) != 0 )
+        {
+            close( *fd );
+            ret = POLARSSL_ERR_NET_BIND_FAILED;
+            continue;
+        }
+
+        if( listen( *fd, POLARSSL_NET_LISTEN_BACKLOG ) != 0 )
+        {
+            close( *fd );
+            ret = POLARSSL_ERR_NET_LISTEN_FAILED;
+            continue;
+        }
+
+        /* I we ever get there, it's a success */
+        ret = 0;
+        break;
+    }
+
+    freeaddrinfo( addr_list );
+
+    return( ret );
+
+#else
+    /* Legacy IPv4-only version */
+
+    int ret, n, c[4];
+    struct sockaddr_in server_addr;
+
+    if( ( ret = net_prepare() ) != 0 )
+        return( ret );
+
+    if( ( *fd = (int) socket( AF_INET, SOCK_STREAM, IPPROTO_IP ) ) < 0 )
+        return( POLARSSL_ERR_NET_SOCKET_FAILED );
+
+    n = 1;
+    setsockopt( *fd, SOL_SOCKET, SO_REUSEADDR,
+                (const char *) &n, sizeof( n ) );
+
+    server_addr.sin_addr.s_addr = net_htonl( INADDR_ANY );
+    server_addr.sin_family      = AF_INET;
+    server_addr.sin_port        = net_htons( port );
+
+    if( bind_ip != NULL )
+    {
+        memset( c, 0, sizeof( c ) );
+        sscanf( bind_ip, "%d.%d.%d.%d", &c[0], &c[1], &c[2], &c[3] );
+
+        for( n = 0; n < 4; n++ )
+            if( c[n] < 0 || c[n] > 255 )
+                break;
+
+        if( n == 4 )
+            server_addr.sin_addr.s_addr = net_htonl(
+                ( (uint32_t) c[0] << 24 ) |
+                ( (uint32_t) c[1] << 16 ) |
+                ( (uint32_t) c[2] <<  8 ) |
+                ( (uint32_t) c[3]       ) );
+    }
+
+    if( bind( *fd, (struct sockaddr *) &server_addr,
+              sizeof( server_addr ) ) < 0 )
+    {
+        close( *fd );
+        return( POLARSSL_ERR_NET_BIND_FAILED );
+    }
+
+    if( listen( *fd, POLARSSL_NET_LISTEN_BACKLOG ) != 0 )
+    {
+        close( *fd );
+        return( POLARSSL_ERR_NET_LISTEN_FAILED );
+    }
+
+    return( 0 );
+#endif /* POLARSSL_HAVE_IPV6 */
+}
+
+#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
+    !defined(EFI32)
+/*
+ * Check if the requested operation would be blocking on a non-blocking socket
+ * and thus 'failed' with a negative return value.
+ */
+static int net_would_block( int fd )
+{
+    ((void) fd);
+    return( WSAGetLastError() == WSAEWOULDBLOCK );
+}
+#else
+/*
+ * Check if the requested operation would be blocking on a non-blocking socket
+ * and thus 'failed' with a negative return value.
+ *
+ * Note: on a blocking socket this function always returns 0!
+ */
+static int net_would_block( int fd )
+{
+    /*
+     * Never return 'WOULD BLOCK' on a non-blocking socket
+     */
+    if( ( fcntl( fd, F_GETFL ) & O_NONBLOCK ) != O_NONBLOCK )
+        return( 0 );
+
+    switch( errno )
+    {
+#if defined EAGAIN
+        case EAGAIN:
+#endif
+#if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN
+        case EWOULDBLOCK:
+#endif
+            return( 1 );
+    }
+    return( 0 );
+}
+#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
+
+/*
+ * Accept a connection from a remote client
+ */
+int net_accept( int bind_fd, int *client_fd, void *client_ip )
+{
+#if defined(POLARSSL_HAVE_IPV6)
+    struct sockaddr_storage client_addr;
+#else
+    struct sockaddr_in client_addr;
+#endif
+
+#if defined(__socklen_t_defined) || defined(_SOCKLEN_T) ||  \
+    defined(_SOCKLEN_T_DECLARED)
+    socklen_t n = (socklen_t) sizeof( client_addr );
+#else
+    int n = (int) sizeof( client_addr );
+#endif
+
+    *client_fd = (int) accept( bind_fd, (struct sockaddr *)
+                               &client_addr, &n );
+
+    if( *client_fd < 0 )
+    {
+        if( net_would_block( bind_fd ) != 0 )
+            return( POLARSSL_ERR_NET_WANT_READ );
+
+        return( POLARSSL_ERR_NET_ACCEPT_FAILED );
+    }
+
+    if( client_ip != NULL )
+    {
+#if defined(POLARSSL_HAVE_IPV6)
+        if( client_addr.ss_family == AF_INET )
+        {
+            struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr;
+            memcpy( client_ip, &addr4->sin_addr.s_addr,
+                        sizeof( addr4->sin_addr.s_addr ) );
+        }
+        else
+        {
+            struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr;
+            memcpy( client_ip, &addr6->sin6_addr.s6_addr,
+                        sizeof( addr6->sin6_addr.s6_addr ) );
+        }
+#else
+        memcpy( client_ip, &client_addr.sin_addr.s_addr,
+                    sizeof( client_addr.sin_addr.s_addr ) );
+#endif /* POLARSSL_HAVE_IPV6 */
+    }
+
+    return( 0 );
+}
+
+/*
+ * Set the socket blocking or non-blocking
+ */
+int net_set_block( int fd )
+{
+#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
+    !defined(EFI32)
+    u_long n = 0;
+    return( ioctlsocket( fd, FIONBIO, &n ) );
+#else
+    return( fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) & ~O_NONBLOCK ) );
+#endif
+}
+
+int net_set_nonblock( int fd )
+{
+#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
+    !defined(EFI32)
+    u_long n = 1;
+    return( ioctlsocket( fd, FIONBIO, &n ) );
+#else
+    return( fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) | O_NONBLOCK ) );
+#endif
+}
+
+#if defined(POLARSSL_HAVE_TIME)
+/*
+ * Portable usleep helper
+ */
+void net_usleep( unsigned long usec )
+{
+    struct timeval tv;
+    tv.tv_sec  = usec / 1000000;
+#if !defined(_WIN32) && ( defined(__unix__) || defined(__unix) || \
+    ( defined(__APPLE__) && defined(__MACH__) ) )
+    tv.tv_usec = (suseconds_t) usec % 1000000;
+#else
+    tv.tv_usec = usec % 1000000;
+#endif
+    select( 0, NULL, NULL, NULL, &tv );
+}
+#endif /* POLARSSL_HAVE_TIME */
+
+/*
+ * Read at most 'len' characters
+ */
+int net_recv( void *ctx, unsigned char *buf, size_t len )
+{
+    int fd = *((int *) ctx);
+    int ret = (int) read( fd, buf, len );
+
+    if( ret < 0 )
+    {
+        if( net_would_block( fd ) != 0 )
+            return( POLARSSL_ERR_NET_WANT_READ );
+
+#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
+    !defined(EFI32)
+        if( WSAGetLastError() == WSAECONNRESET )
+            return( POLARSSL_ERR_NET_CONN_RESET );
+#else
+        if( errno == EPIPE || errno == ECONNRESET )
+            return( POLARSSL_ERR_NET_CONN_RESET );
+
+        if( errno == EINTR )
+            return( POLARSSL_ERR_NET_WANT_READ );
+#endif
+
+        return( POLARSSL_ERR_NET_RECV_FAILED );
+    }
+
+    return( ret );
+}
+
+/*
+ * Write at most 'len' characters
+ */
+int net_send( void *ctx, const unsigned char *buf, size_t len )
+{
+    int fd = *((int *) ctx);
+    int ret = (int) write( fd, buf, len );
+
+    if( ret < 0 )
+    {
+        if( net_would_block( fd ) != 0 )
+            return( POLARSSL_ERR_NET_WANT_WRITE );
+
+#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
+    !defined(EFI32)
+        if( WSAGetLastError() == WSAECONNRESET )
+            return( POLARSSL_ERR_NET_CONN_RESET );
+#else
+        if( errno == EPIPE || errno == ECONNRESET )
+            return( POLARSSL_ERR_NET_CONN_RESET );
+
+        if( errno == EINTR )
+            return( POLARSSL_ERR_NET_WANT_WRITE );
+#endif
+
+        return( POLARSSL_ERR_NET_SEND_FAILED );
+    }
+
+    return( ret );
+}
+
+/*
+ * Gracefully close the connection
+ */
+void net_close( int fd )
+{
+    shutdown( fd, 2 );
+    close( fd );
+}
+
+#endif /* POLARSSL_NET_C */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/polarssl/oid.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,693 @@
+/**
+ * \file oid.c
+ *
+ * \brief Object Identifier (OID) database
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <stdio.h>
+#include <string.h>
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_snprintf snprintf
+#endif
+
+#if defined(POLARSSL_X509_USE_C) || defined(POLARSSL_X509_CREATE_C)
+#include "polarssl/x509.h"
+#endif
+
+/*
+ * 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",
+    },
+    {
+        { ADD_LEN( OID_AT_UNIQUE_IDENTIFIER ), "id-at-uniqueIdentifier",    "Unique Identifier" },
+        "uniqueIdentifier",
+    },
+    {
+        { 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,
+    },
+    {
+        { ADD_LEN( OID_RSASSA_PSS ),        "RSASSA-PSS",           "RSASSA-PSS" },
+        POLARSSL_MD_NONE,     POLARSSL_PK_RSASSA_PSS,
+    },
+    {
+        { NULL, 0, NULL, NULL },
+        POLARSSL_MD_NONE, POLARSSL_PK_NONE,
+    },
+};
+
+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 },
+        POLARSSL_PK_NONE,
+    },
+};
+
+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 },
+        POLARSSL_ECP_DP_NONE,
+    },
+};
+
+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 },
+        POLARSSL_CIPHER_NONE,
+    },
+};
+
+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_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 },
+        POLARSSL_MD_NONE,
+    },
+};
+
+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 },
+        POLARSSL_MD_NONE, POLARSSL_CIPHER_NONE,
+    },
+};
+
+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 = polarssl_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 = polarssl_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/polarssl/padlock.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,168 @@
+/*
+ *  VIA PadLock support functions
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.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\t"
+             "movl  $0xC0000000, %%eax  \n\t"
+             "cpuid                     \n\t"
+             "cmpl  $0xC0000001, %%eax  \n\t"
+             "movl  $0, %%edx           \n\t"
+             "jb    unsupported         \n\t"
+             "movl  $0xC0000001, %%eax  \n\t"
+             "cpuid                     \n\t"
+             "unsupported:              \n\t"
+             "movl  %%edx, %1           \n\t"
+             "movl  %2, %%ebx           \n\t"
+             : "=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                        \n\t"
+         "popfl                         \n\t"
+         "movl    %%ebx, %0             \n\t"
+         "movl    $1, %%ecx             \n\t"
+         "movl    %2, %%edx             \n\t"
+         "movl    %3, %%ebx             \n\t"
+         "movl    %4, %%esi             \n\t"
+         "movl    %4, %%edi             \n\t"
+         ".byte  0xf3,0x0f,0xa7,0xc8    \n\t"
+         "movl    %1, %%ebx             \n\t"
+         : "=m" (ebx)
+         :  "m" (ebx), "m" (ctrl), "m" (rk), "m" (blk)
+         : "memory", "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                        \n\t"
+         "popfl                         \n\t"
+         "movl    %%ebx, %0             \n\t"
+         "movl    %2, %%ecx             \n\t"
+         "movl    %3, %%edx             \n\t"
+         "movl    %4, %%ebx             \n\t"
+         "movl    %5, %%esi             \n\t"
+         "movl    %6, %%edi             \n\t"
+         "movl    %7, %%eax             \n\t"
+         ".byte  0xf3,0x0f,0xa7,0xd0    \n\t"
+         "movl    %1, %%ebx             \n\t"
+         : "=m" (ebx)
+         :  "m" (ebx), "m" (count), "m" (ctrl),
+            "m"  (rk), "m" (input), "m" (output), "m" (iw)
+         : "memory", "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/polarssl/pbkdf2.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,65 @@
+/**
+ * \file pbkdf2.c
+ *
+ * \brief Compatibility wrappers for pkcs5.c
+ *
+ * \author Mathias Olsson <mathias@kompetensum.com>
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#if ! defined(POLARSSL_DEPRECATED_REMOVED)
+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 );
+}
+#endif
+
+#if defined(POLARSSL_SELF_TEST)
+#if ! defined(POLARSSL_DEPRECATED_REMOVED)
+int pbkdf2_self_test( int verbose )
+{
+    return pkcs5_self_test( verbose );
+}
+#endif
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_PBKDF2_C */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/polarssl/pem.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,445 @@
+/*
+ *  Privacy Enhanced Mail (PEM) decoding
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.h>
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdlib.h>
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+#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;
+
+    md5_init( &md5_ctx );
+
+    /*
+     * 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 );
+
+        md5_free( &md5_ctx );
+        polarssl_zeroize( md5sum, 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 );
+
+    md5_free( &md5_ctx );
+    polarssl_zeroize( md5sum, 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];
+
+    des_init( &des_ctx );
+
+    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 );
+
+    des_free( &des_ctx );
+    polarssl_zeroize( des_key, 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];
+
+    des3_init( &des3_ctx );
+
+    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 );
+
+    des3_free( &des3_ctx );
+    polarssl_zeroize( des3_key, 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];
+
+    aes_init( &aes_ctx );
+
+    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 );
+
+    aes_free( &aes_ctx );
+    polarssl_zeroize( aes_key, 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 = 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 )
+{
+    polarssl_free( ctx->buf );
+    polarssl_free( ctx->info );
+
+    polarssl_zeroize( ctx, 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/polarssl/pk.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,374 @@
+/*
+ *  Public Key abstraction layer
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+/*
+ * 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 );
+
+    polarssl_zeroize( ctx, sizeof( pk_context ) );
+}
+
+/*
+ * 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 ) );
+}
+
+/*
+ * Verify a signature with options
+ */
+int pk_verify_ext( pk_type_t type, const void *options,
+                   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 )
+        return( POLARSSL_ERR_PK_BAD_INPUT_DATA );
+
+    if( ! pk_can_do( ctx, type ) )
+        return( POLARSSL_ERR_PK_TYPE_MISMATCH );
+
+    if( type == POLARSSL_PK_RSASSA_PSS )
+    {
+#if defined(POLARSSL_RSA_C) && defined(POLARSSL_PKCS1_V21)
+        int ret;
+        const pk_rsassa_pss_options *pss_opts;
+
+        if( options == NULL )
+            return( POLARSSL_ERR_PK_BAD_INPUT_DATA );
+
+        pss_opts = (const pk_rsassa_pss_options *) options;
+
+        if( sig_len < pk_get_len( ctx ) )
+            return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+
+        ret = rsa_rsassa_pss_verify_ext( pk_rsa( *ctx ),
+                NULL, NULL, RSA_PUBLIC,
+                md_alg, (unsigned int) hash_len, hash,
+                pss_opts->mgf1_hash_id,
+                pss_opts->expected_salt_len,
+                sig );
+        if( ret != 0 )
+            return( ret );
+
+        if( sig_len > pk_get_len( ctx ) )
+            return( POLARSSL_ERR_PK_SIG_LEN_MISMATCH );
+
+        return( 0 );
+#else
+        return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE );
+#endif
+    }
+
+    /* General case: no options */
+    if( options != NULL )
+        return( POLARSSL_ERR_PK_BAD_INPUT_DATA );
+
+    return( pk_verify( 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 ) );
+}
+
+/*
+ * Check public-private key pair
+ */
+int pk_check_pair( const pk_context *pub, const pk_context *prv )
+{
+    if( pub == NULL || pub->pk_info == NULL ||
+        prv == NULL || prv->pk_info == NULL ||
+        prv->pk_info->check_pair_func == NULL )
+    {
+        return( POLARSSL_ERR_PK_BAD_INPUT_DATA );
+    }
+
+    if( prv->pk_info->type == POLARSSL_PK_RSA_ALT )
+    {
+        if( pub->pk_info->type != POLARSSL_PK_RSA )
+            return( POLARSSL_ERR_PK_TYPE_MISMATCH );
+    }
+    else
+    {
+        if( pub->pk_info != prv->pk_info )
+            return( POLARSSL_ERR_PK_TYPE_MISMATCH );
+    }
+
+    return( prv->pk_info->check_pair_func( pub->pk_ctx, prv->pk_ctx ) );
+}
+
+/*
+ * 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/polarssl/pk_wrap.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,503 @@
+/*
+ *  Public Key abstraction layer: wrapper functions
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.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
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+#if defined(POLARSSL_RSA_C)
+static int rsa_can_do( pk_type_t type )
+{
+    return( type == POLARSSL_PK_RSA ||
+            type == POLARSSL_PK_RSASSA_PSS );
+}
+
+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 )
+{
+    *olen = ((rsa_context *) ctx)->len;
+
+    if( *olen > osize )
+        return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE );
+
+    return( rsa_pkcs1_encrypt( (rsa_context *) ctx,
+                f_rng, p_rng, RSA_PUBLIC, ilen, input, output ) );
+}
+
+static int rsa_check_pair_wrap( const void *pub, const void *prv )
+{
+    return( rsa_check_pub_priv( (const rsa_context *) pub,
+                                (const rsa_context *) prv ) );
+}
+
+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_check_pair_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 int eckey_check_pair( const void *pub, const void *prv )
+{
+    return( ecp_check_pub_priv( (const ecp_keypair *) pub,
+                                (const ecp_keypair *) prv ) );
+}
+
+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_check_pair,
+    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_check_pair,
+    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,
+    eckey_check_pair,   /* Compatible key structures */
+    ecdsa_alloc_wrap,
+    ecdsa_free_wrap,
+    eckey_debug,        /* Compatible key structures */
+};
+#endif /* POLARSSL_ECDSA_C */
+
+/*
+ * Support for alternative RSA-private implementations
+ */
+
+static int rsa_alt_can_do( pk_type_t type )
+{
+    return( type == POLARSSL_PK_RSA );
+}
+
+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 ) );
+}
+
+#if defined(POLARSSL_RSA_C)
+static int rsa_alt_check_pair( const void *pub, const void *prv )
+{
+    unsigned char sig[POLARSSL_MPI_MAX_SIZE];
+    unsigned char hash[32];
+    size_t sig_len = 0;
+    int ret;
+
+    if( rsa_alt_get_size( prv ) != rsa_get_size( pub ) )
+        return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+
+    memset( hash, 0x2a, sizeof( hash ) );
+
+    if( ( ret = rsa_alt_sign_wrap( (void *) prv, POLARSSL_MD_NONE,
+                                   hash, sizeof( hash ),
+                                   sig, &sig_len, NULL, NULL ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    if( rsa_verify_wrap( (void *) pub, POLARSSL_MD_NONE,
+                         hash, sizeof( hash ), sig, sig_len ) != 0 )
+    {
+        return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+    }
+
+    return( 0 );
+}
+#endif /* POLARSSL_RSA_C */
+
+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_zeroize( ctx, sizeof( rsa_alt_context ) );
+    polarssl_free( ctx );
+}
+
+const pk_info_t rsa_alt_info = {
+    POLARSSL_PK_RSA_ALT,
+    "RSA-alt",
+    rsa_alt_get_size,
+    rsa_alt_can_do,
+    NULL,
+    rsa_alt_sign_wrap,
+    rsa_alt_decrypt_wrap,
+    NULL,
+#if defined(POLARSSL_RSA_C)
+    rsa_alt_check_pair,
+#else
+    NULL,
+#endif
+    rsa_alt_alloc_wrap,
+    rsa_alt_free_wrap,
+    NULL,
+};
+
+#endif /* POLARSSL_PK_C */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/polarssl/pkcs11.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,235 @@
+/**
+ * \file pkcs11.c
+ *
+ * \brief Wrapper for PKCS#11 library libpkcs11-helper
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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/polarssl/pkcs12.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,360 @@
+/*
+ *  PKCS#12 Personal Information Exchange Syntax
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.h>
+
+#if defined(POLARSSL_ARC4_C)
+#include "polarssl/arc4.h"
+#endif
+
+#if defined(POLARSSL_DES_C)
+#include "polarssl/des.h"
+#endif
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+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);
+
+    arc4_init( &ctx );
+
+    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 )
+        goto exit;
+
+exit:
+    polarssl_zeroize( key, sizeof( key ) );
+    arc4_free( &ctx );
+
+    return( ret );
+#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 );
+    }
+
+    cipher_init( &cipher_ctx );
+
+    if( ( ret = cipher_init_ctx( &cipher_ctx, cipher_info ) ) != 0 )
+        goto exit;
+
+    if( ( ret = cipher_setkey( &cipher_ctx, key, 8 * keylen, (operation_t) 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:
+    polarssl_zeroize( key, sizeof( key ) );
+    polarssl_zeroize( iv,  sizeof( iv  ) );
+    cipher_free( &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 );
+
+    md_init( &md_ctx );
+
+    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:
+    polarssl_zeroize( salt_block, sizeof( salt_block ) );
+    polarssl_zeroize( pwd_block, sizeof( pwd_block ) );
+    polarssl_zeroize( hash_block, sizeof( hash_block ) );
+    polarssl_zeroize( hash_output, sizeof( hash_output ) );
+
+    md_free( &md_ctx );
+
+    return( ret );
+}
+
+#endif /* POLARSSL_PKCS12_C */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/polarssl/pkcs5.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,407 @@
+/**
+ * \file pkcs5.c
+ *
+ * \brief PKCS#5 functions
+ *
+ * \author Mathias Olsson <mathias@kompetensum.com>
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.h>
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdio.h>
+#define polarssl_printf printf
+#endif
+
+static int pkcs5_parse_pbkdf2_params( const 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;
+
+    /*
+     *  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 );
+
+    /*
+     * The value of keylen from pkcs5_parse_pbkdf2_params() is ignored
+     * since it is optional and we don't know if it was set or not
+     */
+    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 );
+    }
+
+    md_init( &md_ctx );
+    cipher_init( &cipher_ctx );
+
+    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, (operation_t) mode ) ) != 0 )
+        goto exit;
+
+    if( ( ret = cipher_crypt( &cipher_ctx, iv, enc_scheme_params.len,
+                              data, datalen, output, &olen ) ) != 0 )
+        ret = POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH;
+
+exit:
+    md_free( &md_ctx );
+    cipher_free( &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)
+
+#if !defined(POLARSSL_SHA1_C)
+int pkcs5_self_test( int verbose )
+{
+    if( verbose != 0 )
+        polarssl_printf( "  PBKDF2 (SHA1): skipped\n\n" );
+
+    return( 0 );
+}
+#else
+
+#define MAX_TESTS   6
+
+static const size_t plen[MAX_TESTS] =
+    { 8, 8, 8, 24, 9 };
+
+static const unsigned char password[MAX_TESTS][32] =
+{
+    "password",
+    "password",
+    "password",
+    "passwordPASSWORDpassword",
+    "pass\0word",
+};
+
+static const size_t slen[MAX_TESTS] =
+    { 4, 4, 4, 36, 5 };
+
+static const unsigned char salt[MAX_TESTS][40] =
+{
+    "salt",
+    "salt",
+    "salt",
+    "saltSALTsaltSALTsaltSALTsaltSALTsalt",
+    "sa\0lt",
+};
+
+static const uint32_t it_cnt[MAX_TESTS] =
+    { 1, 2, 4096, 4096, 4096 };
+
+static const uint32_t key_len[MAX_TESTS] =
+    { 20, 20, 20, 25, 16 };
+
+static const 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 },
+    { 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];
+
+    md_init( &sha1_ctx );
+
+    info_sha1 = md_info_from_type( POLARSSL_MD_SHA1 );
+    if( info_sha1 == NULL )
+    {
+        ret = 1;
+        goto exit;
+    }
+
+    if( ( ret = md_init_ctx( &sha1_ctx, info_sha1 ) ) != 0 )
+    {
+        ret = 1;
+        goto exit;
+    }
+
+    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" );
+
+            ret = 1;
+            goto exit;
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "passed\n" );
+    }
+
+    polarssl_printf( "\n" );
+
+exit:
+    md_free( &sha1_ctx );
+
+    return( ret );
+}
+#endif /* POLARSSL_SHA1_C */
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_PKCS5_C */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/polarssl/pkparse.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,1265 @@
+/*
+ *  Public Key layer for parsing key files and structures
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.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)
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+/*
+ * Load all data from a file into a given buffer.
+ */
+int pk_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 = 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 = pk_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 ) );
+
+    polarssl_zeroize( buf, 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 = pk_load_file( path, &buf, &n ) ) != 0 )
+        return( ret );
+
+    ret = pk_parse_public_key( ctx, buf, n );
+
+    polarssl_zeroize( buf, 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 ) ) != 0 )
+        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;
+
+    pubkey_done = 0;
+    if( p != end )
+    {
+        /*
+         * 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.
+         */
+        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
+ */
+#if defined(POLARSSL_PKCS12_C) || defined(POLARSSL_PKCS5_C)
+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 ) );
+}
+#endif /* POLARSSL_PKCS12_C || POLARSSL_PKCS5_C */
+
+/*
+ * 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 );
+
+#if defined(POLARSSL_PKCS12_C) || defined(POLARSSL_PKCS5_C)
+    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 );
+#endif /* POLARSSL_PKCS12_C || POLARSSL_PKCS5_C */
+#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 defined(POLARSSL_PKCS12_C) || defined(POLARSSL_PKCS5_C)
+    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 );
+    }
+#endif /* POLARSSL_PKCS12_C || POLARSSL_PKCS5_C */
+
+    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/polarssl/pkwrite.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,441 @@
+/*
+ *  Public Key layer for writing key files and structures
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.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"
+
+/*
+ * Max sizes of key per types. Shown as tag + len (+ content).
+ */
+
+#if defined(POLARSSL_RSA_C)
+/*
+ * RSA public keys:
+ *  SubjectPublicKeyInfo  ::=  SEQUENCE  {          1 + 3
+ *       algorithm            AlgorithmIdentifier,  1 + 1 (sequence)
+ *                                                + 1 + 1 + 9 (rsa oid)
+ *                                                + 1 + 1 (params null)
+ *       subjectPublicKey     BIT STRING }          1 + 3 + (1 + below)
+ *  RSAPublicKey ::= SEQUENCE {                     1 + 3
+ *      modulus           INTEGER,  -- n            1 + 3 + MPI_MAX + 1
+ *      publicExponent    INTEGER   -- e            1 + 3 + MPI_MAX + 1
+ *  }
+ */
+#define RSA_PUB_DER_MAX_BYTES   38 + 2 * POLARSSL_MPI_MAX_SIZE
+
+/*
+ * RSA private keys:
+ *  RSAPrivateKey ::= SEQUENCE {                    1 + 3
+ *      version           Version,                  1 + 1 + 1
+ *      modulus           INTEGER,                  1 + 3 + MPI_MAX + 1
+ *      publicExponent    INTEGER,                  1 + 3 + MPI_MAX + 1
+ *      privateExponent   INTEGER,                  1 + 3 + MPI_MAX + 1
+ *      prime1            INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
+ *      prime2            INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
+ *      exponent1         INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
+ *      exponent2         INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
+ *      coefficient       INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
+ *      otherPrimeInfos   OtherPrimeInfos OPTIONAL  0 (not supported)
+ *  }
+ */
+#define MPI_MAX_SIZE_2          POLARSSL_MPI_MAX_SIZE / 2 + \
+                                POLARSSL_MPI_MAX_SIZE % 2
+#define RSA_PRV_DER_MAX_BYTES   47 + 3 * POLARSSL_MPI_MAX_SIZE \
+                                   + 5 * MPI_MAX_SIZE_2
+
+#else /* POLARSSL_RSA_C */
+
+#define RSA_PUB_DER_MAX_BYTES   0
+#define RSA_PRV_DER_MAX_BYTES   0
+
+#endif /* POLARSSL_RSA_C */
+
+#if defined(POLARSSL_ECP_C)
+/*
+ * EC public keys:
+ *  SubjectPublicKeyInfo  ::=  SEQUENCE  {      1 + 2
+ *    algorithm         AlgorithmIdentifier,    1 + 1 (sequence)
+ *                                            + 1 + 1 + 7 (ec oid)
+ *                                            + 1 + 1 + 9 (namedCurve oid)
+ *    subjectPublicKey  BIT STRING              1 + 2 + 1               [1]
+ *                                            + 1 (point format)        [1]
+ *                                            + 2 * ECP_MAX (coords)    [1]
+ *  }
+ */
+#define ECP_PUB_DER_MAX_BYTES   30 + 2 * POLARSSL_ECP_MAX_BYTES
+
+/*
+ * EC private keys:
+ * ECPrivateKey ::= SEQUENCE {                  1 + 2
+ *      version        INTEGER ,                1 + 1 + 1
+ *      privateKey     OCTET STRING,            1 + 1 + ECP_MAX
+ *      parameters [0] ECParameters OPTIONAL,   1 + 1 + (1 + 1 + 9)
+ *      publicKey  [1] BIT STRING OPTIONAL      1 + 2 + [1] above
+ *    }
+ */
+#define ECP_PRV_DER_MAX_BYTES   29 + 3 * POLARSSL_ECP_MAX_BYTES
+
+#else /* POLARSSL_ECP_C */
+
+#define ECP_PUB_DER_MAX_BYTES   0
+#define ECP_PRV_DER_MAX_BYTES   0
+
+#endif /* POLARSSL_ECP_C */
+
+#define PUB_DER_MAX_BYTES   RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
+                            RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES
+#define PRV_DER_MAX_BYTES   RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \
+                            RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES
+
+int pk_write_pubkey_pem( pk_context *key, unsigned char *buf, size_t size )
+{
+    int ret;
+    unsigned char output_buf[PUB_DER_MAX_BYTES];
+    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[PRV_DER_MAX_BYTES];
+    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/polarssl/platform.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,166 @@
+/*
+ *  Platform abstraction layer
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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_SNPRINTF_ALT)
+#if !defined(POLARSSL_PLATFORM_STD_SNPRINTF)
+/*
+ * Make dummy function to prevent NULL pointer dereferences
+ */
+static int platform_snprintf_uninit( char * s, size_t n,
+                                     const char * format, ... )
+{
+    ((void) s);
+    ((void) n);
+    ((void) format);
+    return( 0 );
+}
+
+#define POLARSSL_PLATFORM_STD_SNPRINTF    platform_snprintf_uninit
+#endif /* !POLARSSL_PLATFORM_STD_SNPRINTF */
+
+int (*polarssl_snprintf)( char * s, size_t n,
+                          const char * format,
+                          ... ) = POLARSSL_PLATFORM_STD_SNPRINTF;
+
+int platform_set_snprintf( int (*snprintf_func)( char * s, size_t n,
+                                                 const char * format,
+                                                 ... ) )
+{
+    polarssl_snprintf = snprintf_func;
+    return( 0 );
+}
+#endif /* POLARSSL_PLATFORM_SNPRINTF_ALT */
+
+#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 */
+
+#if defined(POLARSSL_PLATFORM_EXIT_ALT)
+#if !defined(POLARSSL_PLATFORM_STD_EXIT)
+/*
+ * Make dummy function to prevent NULL pointer dereferences
+ */
+static void platform_exit_uninit( int status )
+{
+    ((void) status);
+}
+
+#define POLARSSL_PLATFORM_STD_EXIT   platform_exit_uninit
+#endif /* !POLARSSL_PLATFORM_STD_EXIT */
+
+void (*polarssl_exit)( int status ) = POLARSSL_PLATFORM_STD_EXIT;
+
+int platform_set_exit( void (*exit_func)( int status ) )
+{
+    polarssl_exit = exit_func;
+    return( 0 );
+}
+#endif /* POLARSSL_PLATFORM_EXIT_ALT */
+
+#endif /* POLARSSL_PLATFORM_C */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/polarssl/ripemd160.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,652 @@
+/*
+ *  RIPE MD-160 implementation
+ *
+ *  Copyright (C) 2014-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.h>
+
+#if defined(POLARSSL_FS_IO)
+#include <stdio.h>
+#endif
+
+#if defined(POLARSSL_SELF_TEST)
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdio.h>
+#define polarssl_printf printf
+#endif /* POLARSSL_PLATFORM_C */
+#endif /* POLARSSL_SELF_TEST */
+
+/*
+ * 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)       ) & 0xFF );    \
+    (b)[(i) + 1] = (unsigned char) ( ( (n) >>  8 ) & 0xFF );    \
+    (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF );    \
+    (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF );    \
+}
+#endif
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+void ripemd160_init( ripemd160_context *ctx )
+{
+    memset( ctx, 0, sizeof( ripemd160_context ) );
+}
+
+void ripemd160_free( ripemd160_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    polarssl_zeroize( ctx, sizeof( ripemd160_context ) );
+}
+
+/*
+ * 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_init( &ctx );
+    ripemd160_starts( &ctx );
+    ripemd160_update( &ctx, input, ilen );
+    ripemd160_finish( &ctx, output );
+    ripemd160_free( &ctx );
+}
+
+#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_init( &ctx );
+    ripemd160_starts( &ctx );
+
+    while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+        ripemd160_update( &ctx, buf, n );
+
+    ripemd160_finish( &ctx, output );
+    ripemd160_free( &ctx );
+
+    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 );
+
+    polarssl_zeroize( sum, 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 );
+
+    polarssl_zeroize( tmpbuf, 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_init( &ctx );
+    ripemd160_hmac_starts( &ctx, key, keylen );
+    ripemd160_hmac_update( &ctx, input, ilen );
+    ripemd160_hmac_finish( &ctx, output );
+    ripemd160_free( &ctx );
+}
+
+
+#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/polarssl/rsa.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,1681 @@
+/*
+ *  The RSA public-key cryptosystem
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.h>
+
+#if defined(POLARSSL_PKCS1_V21)
+#include "polarssl/md.h"
+#endif
+
+#if defined(POLARSSL_PKCS1_V15) && !defined(__OpenBSD__)
+#include <stdlib.h>
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdio.h>
+#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 );
+}
+
+/*
+ * Check if contexts holding a public and private key match
+ */
+int rsa_check_pub_priv( const rsa_context *pub, const rsa_context *prv )
+{
+    if( rsa_check_pubkey( pub ) != 0 ||
+        rsa_check_privkey( prv ) != 0 )
+    {
+        return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+    }
+
+    if( mpi_cmp_mpi( &pub->N, &prv->N ) != 0 ||
+        mpi_cmp_mpi( &pub->E, &prv->E ) != 0 )
+    {
+        return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+    }
+
+    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 );
+    }
+
+#if defined(POLARSSL_THREADING_C)
+    polarssl_mutex_lock( &ctx->mutex );
+#endif
+
+    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:
+#if defined(POLARSSL_THREADING_C)
+    polarssl_mutex_unlock( &ctx->mutex );
+#endif
+
+    mpi_free( &T );
+
+    if( ret != 0 )
+        return( POLARSSL_ERR_RSA_PUBLIC_FAILED + ret );
+
+    return( 0 );
+}
+
+/*
+ * 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 );
+}
+
+/*
+ * 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;
+    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
+
+    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( 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 ) );
+    }
+
+#if defined(POLARSSL_THREADING_C)
+    polarssl_mutex_lock( &ctx->mutex );
+#endif
+
+#if defined(POLARSSL_RSA_NO_CRT)
+    MPI_CHK( mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) );
+#else
+    /*
+     * 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 ) );
+#endif /* POLARSSL_RSA_NO_CRT */
+
+    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 ) );
+    }
+
+    olen = ctx->len;
+    MPI_CHK( mpi_write_binary( &T, output, olen ) );
+
+cleanup:
+#if defined(POLARSSL_THREADING_C)
+    polarssl_mutex_unlock( &ctx->mutex );
+    mpi_free( &Vi_copy ); mpi_free( &Vf_copy );
+#endif
+    mpi_free( &T ); mpi_free( &T1 ); mpi_free( &T2 );
+
+    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( mode == RSA_PRIVATE && ctx->padding != RSA_PKCS_V21 )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    if( f_rng == NULL )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    md_info = md_info_from_type( (md_type_t) 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 )
+        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( &md_ctx );
+    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( &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( mode == RSA_PRIVATE && ctx->padding != RSA_PKCS_V15 )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    if( 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( mode == RSA_PRIVATE && 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( (md_type_t) 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( &md_ctx );
+    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( &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 | (unsigned char)-pad_done) >> 7) ^ 1;
+    }
+
+    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( mode == RSA_PRIVATE && 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] | (unsigned char)-p[i]) >> 7) ^ 1;
+            pad_count += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1;
+        }
+
+        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( mode == RSA_PRIVATE && ctx->padding != RSA_PKCS_V21 )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    if( 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( (md_type_t) 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( &md_ctx );
+    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( &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 = NULL;
+
+    if( mode == RSA_PRIVATE && 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_ext( 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,
+                               md_type_t mgf1_hash_id,
+                               int expected_salt_len,
+                               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( mode == RSA_PRIVATE && 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( mgf1_hash_id );
+    if( md_info == NULL )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    hlen = md_get_size( md_info );
+    slen = siglen - hlen - 1; /* Currently length of salt + padding */
+
+    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( &md_ctx );
+    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( &md_ctx );
+        return( POLARSSL_ERR_RSA_INVALID_PADDING );
+    }
+
+    /* Actual salt len */
+    slen -= p - buf;
+
+    if( expected_salt_len != RSA_SALT_LEN_ANY &&
+        slen != (size_t) expected_salt_len )
+    {
+        md_free( &md_ctx );
+        return( POLARSSL_ERR_RSA_INVALID_PADDING );
+    }
+
+    // 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( &md_ctx );
+
+    if( memcmp( p + slen, result, hlen ) == 0 )
+        return( 0 );
+    else
+        return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+}
+
+/*
+ * Simplified 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 )
+{
+    md_type_t mgf1_hash_id = ( ctx->hash_id != POLARSSL_MD_NONE )
+                             ? (md_type_t) ctx->hash_id
+                             : md_alg;
+
+    return( rsa_rsassa_pss_verify_ext( ctx, f_rng, p_rng, mode,
+                                       md_alg, hashlen, hash,
+                                       mgf1_hash_id, RSA_SALT_LEN_ANY,
+                                       sig ) );
+
+}
+#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( mode == RSA_PRIVATE && 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 ) );
+
+    MPI_CHK( mpi_copy( &dst->Vi, &src->Vi ) );
+    MPI_CHK( mpi_copy( &dst->Vf, &src->Vf ) );
+
+    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 )
+{
+    mpi_free( &ctx->Vi ); mpi_free( &ctx->Vf );
+    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/polarssl/sha1.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,664 @@
+/*
+ *  FIPS-180-1 compliant SHA-1 implementation
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.h>
+
+#if defined(POLARSSL_FS_IO)
+#include <stdio.h>
+#endif
+
+#if defined(POLARSSL_SELF_TEST)
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdio.h>
+#define polarssl_printf printf
+#endif /* POLARSSL_PLATFORM_C */
+#endif /* POLARSSL_SELF_TEST */
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+#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
+
+void sha1_init( sha1_context *ctx )
+{
+    memset( ctx, 0, sizeof( sha1_context ) );
+}
+
+void sha1_free( sha1_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    polarssl_zeroize( ctx, sizeof( sha1_context ) );
+}
+
+/*
+ * 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_init( &ctx );
+    sha1_starts( &ctx );
+    sha1_update( &ctx, input, ilen );
+    sha1_finish( &ctx, output );
+    sha1_free( &ctx );
+}
+
+#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_init( &ctx );
+    sha1_starts( &ctx );
+
+    while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+        sha1_update( &ctx, buf, n );
+
+    sha1_finish( &ctx, output );
+    sha1_free( &ctx );
+
+    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 );
+
+    polarssl_zeroize( sum, 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 );
+
+    polarssl_zeroize( tmpbuf, 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_init( &ctx );
+    sha1_hmac_starts( &ctx, key, keylen );
+    sha1_hmac_update( &ctx, input, ilen );
+    sha1_hmac_finish( &ctx, output );
+    sha1_free( &ctx );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+/*
+ * FIPS-180-1 test vectors
+ */
+static const 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 const 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 const 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, ret = 0;
+    unsigned char buf[1024];
+    unsigned char sha1sum[20];
+    sha1_context ctx;
+
+    sha1_init( &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" );
+
+            ret = 1;
+            goto exit;
+        }
+
+        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, 0xAA, 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" );
+
+            ret = 1;
+            goto exit;
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+exit:
+    sha1_free( &ctx );
+
+    return( ret );
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_SHA1_C */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/polarssl/sha256.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,745 @@
+/*
+ *  FIPS-180-2 compliant SHA-256 implementation
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.h>
+
+#if defined(POLARSSL_FS_IO)
+#include <stdio.h>
+#endif
+
+#if defined(POLARSSL_SELF_TEST)
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdio.h>
+#define polarssl_printf printf
+#endif /* POLARSSL_PLATFORM_C */
+#endif /* POLARSSL_SELF_TEST */
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+#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
+
+void sha256_init( sha256_context *ctx )
+{
+    memset( ctx, 0, sizeof( sha256_context ) );
+}
+
+void sha256_free( sha256_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    polarssl_zeroize( ctx, sizeof( sha256_context ) );
+}
+
+/*
+ * 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_init( &ctx );
+    sha256_starts( &ctx, is224 );
+    sha256_update( &ctx, input, ilen );
+    sha256_finish( &ctx, output );
+    sha256_free( &ctx );
+}
+
+#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_init( &ctx );
+    sha256_starts( &ctx, is224 );
+
+    while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+        sha256_update( &ctx, buf, n );
+
+    sha256_finish( &ctx, output );
+    sha256_free( &ctx );
+
+    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 );
+
+    polarssl_zeroize( sum, 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 );
+
+    polarssl_zeroize( tmpbuf, 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_init( &ctx );
+    sha256_hmac_starts( &ctx, key, keylen, is224 );
+    sha256_hmac_update( &ctx, input, ilen );
+    sha256_hmac_finish( &ctx, output );
+    sha256_free( &ctx );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+/*
+ * FIPS-180-2 test vectors
+ */
+static const 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 const 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 const 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, ret = 0;
+    unsigned char buf[1024];
+    unsigned char sha256sum[32];
+    sha256_context ctx;
+
+    sha256_init( &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" );
+
+            ret = 1;
+            goto exit;
+        }
+
+        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, 0xAA, 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" );
+
+            ret = 1;
+            goto exit;
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+exit:
+    sha256_free( &ctx );
+
+    return( ret );
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_SHA256_C */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/polarssl/sha512.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,805 @@
+/*
+ *  FIPS-180-2 compliant SHA-384/512 implementation
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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(_MSC_VER) || defined(__WATCOMC__)
+  #define UL64(x) x##ui64
+#else
+  #define UL64(x) x##ULL
+#endif
+
+#include <string.h>
+
+#if defined(POLARSSL_FS_IO)
+#include <stdio.h>
+#endif
+
+#if defined(POLARSSL_SELF_TEST)
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdio.h>
+#define polarssl_printf printf
+#endif /* POLARSSL_PLATFORM_C */
+#endif /* POLARSSL_SELF_TEST */
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+#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)
+};
+
+void sha512_init( sha512_context *ctx )
+{
+    memset( ctx, 0, sizeof( sha512_context ) );
+}
+
+void sha512_free( sha512_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    polarssl_zeroize( ctx, sizeof( sha512_context ) );
+}
+
+/*
+ * 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_init( &ctx );
+    sha512_starts( &ctx, is384 );
+    sha512_update( &ctx, input, ilen );
+    sha512_finish( &ctx, output );
+    sha512_free( &ctx );
+}
+
+#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_init( &ctx );
+    sha512_starts( &ctx, is384 );
+
+    while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+        sha512_update( &ctx, buf, n );
+
+    sha512_finish( &ctx, output );
+    sha512_free( &ctx );
+
+    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 );
+
+    polarssl_zeroize( sum, 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 );
+
+    polarssl_zeroize( tmpbuf, 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_init( &ctx );
+    sha512_hmac_starts( &ctx, key, keylen, is384 );
+    sha512_hmac_update( &ctx, input, ilen );
+    sha512_hmac_finish( &ctx, output );
+    sha512_free( &ctx );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+/*
+ * FIPS-180-2 test vectors
+ */
+static const 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 const 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 const 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, ret = 0;
+    unsigned char buf[1024];
+    unsigned char sha512sum[64];
+    sha512_context ctx;
+
+    sha512_init( &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" );
+
+            ret = 1;
+            goto exit;
+        }
+
+        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, 0xAA, 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" );
+
+            ret = 1;
+            goto exit;
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+exit:
+    sha512_free( &ctx );
+
+    return( ret );
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_SHA512_C */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/polarssl/ssl_cache.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,330 @@
+/*
+ *  SSL session cache implementation
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.h>
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdlib.h>
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+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 )
+        {
+            if( ( session->peer_cert = polarssl_malloc(
+                                 sizeof(x509_crt) ) ) == 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 = 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 = 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)
+        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/polarssl/ssl_ciphersuites.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,1844 @@
+/**
+ * \file ssl_ciphersuites.c
+ *
+ * \brief SSL ciphersuites for mbed TLS
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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>
+#include <string.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 > CCM > CBC > CCM_8
+ * 4. By hash function used when relevant
+ * 5. By key exchange/auth again: EC > non-EC
+ */
+static const int ciphersuite_preference[] =
+{
+#if defined(SSL_CIPHERSUITES)
+    SSL_CIPHERSUITES,
+#else
+    /* 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_CCM,
+    TLS_DHE_RSA_WITH_AES_256_CCM,
+    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_256_CCM_8,
+    TLS_DHE_RSA_WITH_AES_256_CCM_8,
+
+    /* 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_CCM,
+    TLS_DHE_RSA_WITH_AES_128_CCM,
+    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_ECDHE_ECDSA_WITH_AES_128_CCM_8,
+    TLS_DHE_RSA_WITH_AES_128_CCM_8,
+
+    /* 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_DHE_PSK_WITH_AES_256_CCM,
+    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_256_CCM_8,
+
+    TLS_DHE_PSK_WITH_AES_128_GCM_SHA256,
+    TLS_DHE_PSK_WITH_AES_128_CCM,
+    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_DHE_PSK_WITH_AES_128_CCM_8,
+
+    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_CCM,
+    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,
+    TLS_RSA_WITH_AES_256_CCM_8,
+
+    /* 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_CCM,
+    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,
+    TLS_RSA_WITH_AES_128_CCM_8,
+
+    /* 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_CCM,
+    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_256_CCM_8,
+
+    TLS_PSK_WITH_AES_128_GCM_SHA256,
+    TLS_PSK_WITH_AES_128_CCM,
+    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_AES_128_CCM_8,
+
+    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,
+
+#endif /* SSL_CIPHERSUITES */
+    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 */
+#if defined(POLARSSL_CCM_C)
+    { TLS_ECDHE_ECDSA_WITH_AES_256_CCM, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM",
+      POLARSSL_CIPHER_AES_256_CCM, 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 },
+    { TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM-8",
+      POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_SHORT_TAG },
+    { TLS_ECDHE_ECDSA_WITH_AES_128_CCM, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM",
+      POLARSSL_CIPHER_AES_128_CCM, 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 },
+    { TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM-8",
+      POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_SHORT_TAG },
+#endif /* POLARSSL_CCM_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 */
+#if defined(POLARSSL_CCM_C)
+    { TLS_DHE_RSA_WITH_AES_256_CCM, "TLS-DHE-RSA-WITH-AES-256-CCM",
+      POLARSSL_CIPHER_AES_256_CCM, 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_CCM_8, "TLS-DHE-RSA-WITH-AES-256-CCM-8",
+      POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_SHORT_TAG },
+    { TLS_DHE_RSA_WITH_AES_128_CCM, "TLS-DHE-RSA-WITH-AES-128-CCM",
+      POLARSSL_CIPHER_AES_128_CCM, 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_128_CCM_8, "TLS-DHE-RSA-WITH-AES-128-CCM-8",
+      POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_SHORT_TAG },
+#endif /* POLARSSL_CCM_C */
+#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 */
+#if defined(POLARSSL_CCM_C)
+    { TLS_RSA_WITH_AES_256_CCM, "TLS-RSA-WITH-AES-256-CCM",
+      POLARSSL_CIPHER_AES_256_CCM, 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_CCM_8, "TLS-RSA-WITH-AES-256-CCM-8",
+      POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_SHORT_TAG },
+    { TLS_RSA_WITH_AES_128_CCM, "TLS-RSA-WITH-AES-128-CCM",
+      POLARSSL_CIPHER_AES_128_CCM, 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_128_CCM_8, "TLS-RSA-WITH-AES-128-CCM-8",
+      POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_SHORT_TAG },
+#endif /* POLARSSL_CCM_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_1,
+      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_1,
+      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 */
+#if defined(POLARSSL_CCM_C)
+    { TLS_PSK_WITH_AES_256_CCM, "TLS-PSK-WITH-AES-256-CCM",
+      POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+    { TLS_PSK_WITH_AES_256_CCM_8, "TLS-PSK-WITH-AES-256-CCM-8",
+      POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_SHORT_TAG },
+    { TLS_PSK_WITH_AES_128_CCM, "TLS-PSK-WITH-AES-128-CCM",
+      POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+    { TLS_PSK_WITH_AES_128_CCM_8, "TLS-PSK-WITH-AES-128-CCM-8",
+      POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_SHORT_TAG },
+#endif /* POLARSSL_CCM_C */
+#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_1,
+      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_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_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_1,
+      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_1,
+      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 */
+#if defined(POLARSSL_CCM_C)
+    { TLS_DHE_PSK_WITH_AES_256_CCM, "TLS-DHE-PSK-WITH-AES-256-CCM",
+      POLARSSL_CIPHER_AES_256_CCM, 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 },
+    { TLS_DHE_PSK_WITH_AES_256_CCM_8, "TLS-DHE-PSK-WITH-AES-256-CCM-8",
+      POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_SHORT_TAG },
+    { TLS_DHE_PSK_WITH_AES_128_CCM, "TLS-DHE-PSK-WITH-AES-128-CCM",
+      POLARSSL_CIPHER_AES_128_CCM, 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 },
+    { TLS_DHE_PSK_WITH_AES_128_CCM_8, "TLS-DHE-PSK-WITH-AES-128-CCM-8",
+      POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_SHORT_TAG },
+#endif /* POLARSSL_CCM_C */
+#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_1,
+      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_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_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_1,
+      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_1,
+      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_1,
+      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_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_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_1,
+      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_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_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_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_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_1,
+      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_1,
+      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_1,
+      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_1,
+      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_1,
+      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_1,
+      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_1,
+      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_1,
+      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_1,
+      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, "",
+      POLARSSL_CIPHER_NONE, POLARSSL_MD_NONE, POLARSSL_KEY_EXCHANGE_NONE,
+      0, 0, 0, 0, 0 }
+};
+
+#if defined(SSL_CIPHERSUITES)
+const int *ssl_list_ciphersuites( void )
+{
+    return( ciphersuite_preference );
+}
+#else
+#define MAX_CIPHERSUITES    sizeof( ciphersuite_definitions     ) /         \
+                            sizeof( ciphersuite_definitions[0]  )
+static int supported_ciphersuites[MAX_CIPHERSUITES];
+static int supported_init = 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;
+        int *q;
+
+        for( p = ciphersuite_preference, q = supported_ciphersuites;
+             *p != 0 && q < supported_ciphersuites + MAX_CIPHERSUITES - 1;
+             p++ )
+        {
+#if defined(POLARSSL_REMOVE_ARC4_CIPHERSUITES)
+            const ssl_ciphersuite_t *cs_info;
+            if( ( cs_info = ssl_ciphersuite_from_id( *p ) ) != NULL &&
+                cs_info->cipher != POLARSSL_CIPHER_ARC4_128 )
+#else
+            if( ssl_ciphersuite_from_id( *p ) != NULL )
+#endif
+                *(q++) = *p;
+        }
+        *q = 0;
+
+        supported_init = 1;
+    }
+
+    return( supported_ciphersuites );
+};
+#endif /* SSL_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/polarssl/ssl_cli.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,2855 @@
+/*
+ *  SSLv3/TLSv1 client-side functions
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.h>
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdlib.h>
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+#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_SESSION_TICKETS)
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+#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 */
+
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+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;
+}
+#endif /* POLARSSL_SSL_RENEGOTIATION */
+
+/*
+ * Only if we handle at least one key exchange that needs signatures.
+ */
+#if defined(POLARSSL_SSL_PROTO_TLS1_2) && \
+    defined(POLARSSL_KEY_EXCHANGE__WITH_CERT__ENABLED)
+static void ssl_write_signature_algorithms_ext( ssl_context *ssl,
+                                                unsigned char *buf,
+                                                size_t *olen )
+{
+    unsigned char *p = buf;
+    size_t sig_alg_len = 0;
+#if defined(POLARSSL_RSA_C) || defined(POLARSSL_ECDSA_C)
+    unsigned char *sig_alg_list = buf + 6;
+#endif
+
+    *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 &&
+          POLARSSL_KEY_EXCHANGE__WITH_CERT__ENABLED */
+
+#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_ENCRYPT_THEN_MAC)
+static void ssl_write_encrypt_then_mac_ext( ssl_context *ssl,
+                                       unsigned char *buf, size_t *olen )
+{
+    unsigned char *p = buf;
+
+    if( ssl->encrypt_then_mac == SSL_ETM_DISABLED ||
+        ssl->max_minor_ver == SSL_MINOR_VERSION_0 )
+    {
+        *olen = 0;
+        return;
+    }
+
+    SSL_DEBUG_MSG( 3, ( "client hello, adding encrypt_then_mac "
+                        "extension" ) );
+
+    *p++ = (unsigned char)( ( TLS_EXT_ENCRYPT_THEN_MAC >> 8 ) & 0xFF );
+    *p++ = (unsigned char)( ( TLS_EXT_ENCRYPT_THEN_MAC      ) & 0xFF );
+
+    *p++ = 0x00;
+    *p++ = 0x00;
+
+    *olen = 4;
+}
+#endif /* POLARSSL_SSL_ENCRYPT_THEN_MAC */
+
+#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET)
+static void ssl_write_extended_ms_ext( ssl_context *ssl,
+                                       unsigned char *buf, size_t *olen )
+{
+    unsigned char *p = buf;
+
+    if( ssl->extended_ms == SSL_EXTENDED_MS_DISABLED ||
+        ssl->max_minor_ver == SSL_MINOR_VERSION_0 )
+    {
+        *olen = 0;
+        return;
+    }
+
+    SSL_DEBUG_MSG( 3, ( "client hello, adding extended_master_secret "
+                        "extension" ) );
+
+    *p++ = (unsigned char)( ( TLS_EXT_EXTENDED_MASTER_SECRET >> 8 ) & 0xFF );
+    *p++ = (unsigned char)( ( TLS_EXT_EXTENDED_MASTER_SECRET      ) & 0xFF );
+
+    *p++ = 0x00;
+    *p++ = 0x00;
+
+    *olen = 4;
+}
+#endif /* POLARSSL_SSL_EXTENDED_MASTER_SECRET */
+
+#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 defined(POLARSSL_SSL_RENEGOTIATION)
+    if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE )
+#endif
+    {
+        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( n < 16 || n > 32 ||
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+        ssl->renegotiation != SSL_INITIAL_HANDSHAKE ||
+#endif
+        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 defined(POLARSSL_SSL_RENEGOTIATION)
+    if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE )
+#endif
+    {
+        if( 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;
+
+    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;
+
+        if( ssl->arc4_disabled == SSL_ARC4_DISABLED &&
+            ciphersuite_info->cipher == POLARSSL_CIPHER_ARC4_128 )
+            continue;
+
+        SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %2d",
+                       ciphersuites[i] ) );
+
+        n++;
+        *p++ = (unsigned char)( ciphersuites[i] >> 8 );
+        *p++ = (unsigned char)( ciphersuites[i]      );
+    }
+
+    /*
+     * Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV
+     */
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+    if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE )
+#endif
+    {
+        *p++ = (unsigned char)( SSL_EMPTY_RENEGOTIATION_INFO >> 8 );
+        *p++ = (unsigned char)( SSL_EMPTY_RENEGOTIATION_INFO      );
+        n++;
+    }
+
+    /* Some versions of OpenSSL don't handle it correctly if not at end */
+#if defined(POLARSSL_SSL_FALLBACK_SCSV)
+    if( ssl->fallback == SSL_IS_FALLBACK )
+    {
+        SSL_DEBUG_MSG( 3, ( "adding FALLBACK_SCSV" ) );
+        *p++ = (unsigned char)( SSL_FALLBACK_SCSV >> 8 );
+        *p++ = (unsigned char)( SSL_FALLBACK_SCSV      );
+        n++;
+    }
+#endif
+
+    *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
+
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+    ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen );
+    ext_len += olen;
+#endif
+
+#if defined(POLARSSL_SSL_PROTO_TLS1_2) && \
+    defined(POLARSSL_KEY_EXCHANGE__WITH_CERT__ENABLED)
+    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_ENCRYPT_THEN_MAC)
+    ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, &olen );
+    ext_len += olen;
+#endif
+
+#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET)
+    ssl_write_extended_ms_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
+
+    /* olen unused if all extensions are disabled */
+    ((void) olen);
+
+    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 defined(POLARSSL_SSL_RENEGOTIATION)
+    if( ssl->renegotiation != SSL_INITIAL_HANDSHAKE )
+    {
+        /* 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 renegotiation info" ) );
+
+            if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
+                return( ret );
+
+            return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+        }
+    }
+    else
+#endif /* POLARSSL_SSL_RENEGOTIATION */
+    {
+        if( len != 1 || buf[0] != 0x00 )
+        {
+            SSL_DEBUG_MSG( 1, ( "non-zero length renegotiation info" ) );
+
+            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;
+    }
+
+    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_ENCRYPT_THEN_MAC)
+static int ssl_parse_encrypt_then_mac_ext( ssl_context *ssl,
+                                         const unsigned char *buf,
+                                         size_t len )
+{
+    if( ssl->encrypt_then_mac == SSL_ETM_DISABLED ||
+        ssl->minor_ver == SSL_MINOR_VERSION_0 ||
+        len != 0 )
+    {
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+    }
+
+    ((void) buf);
+
+    ssl->session_negotiate->encrypt_then_mac = SSL_ETM_ENABLED;
+
+    return( 0 );
+}
+#endif /* POLARSSL_SSL_ENCRYPT_THEN_MAC */
+
+#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET)
+static int ssl_parse_extended_ms_ext( ssl_context *ssl,
+                                         const unsigned char *buf,
+                                         size_t len )
+{
+    if( ssl->extended_ms == SSL_EXTENDED_MS_DISABLED ||
+        ssl->minor_ver == SSL_MINOR_VERSION_0 ||
+        len != 0 )
+    {
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+    }
+
+    ((void) buf);
+
+    ssl->handshake->extended_ms = SSL_EXTENDED_MS_ENABLED;
+
+    return( 0 );
+}
+#endif /* POLARSSL_SSL_EXTENDED_MASTER_SECRET */
+
+#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 + 1;
+    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++;
+    }
+
+    SSL_DEBUG_MSG( 1, ( "no point format in common" ) );
+    return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+}
+#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;
+    unsigned char *buf, *ext;
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+    int renegotiation_info_seen = 0;
+#endif
+    int handshake_failure = 0;
+    const ssl_ciphersuite_t *suite_info;
+#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 )
+    {
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+        if( ssl->renegotiation == SSL_RENEGOTIATION )
+        {
+            ssl->renego_records_seen++;
+
+            if( ssl->renego_max_records >= 0 &&
+                ssl->renego_records_seen > ssl->renego_max_records )
+            {
+                SSL_DEBUG_MSG( 1, ( "renegotiation requested, "
+                                    "but not honored by server" ) );
+                return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+            }
+
+            SSL_DEBUG_MSG( 1, ( "non-handshake message during renego" ) );
+            return( POLARSSL_ERR_SSL_WAITING_SERVER_HELLO_RENEGO );
+        }
+#endif /* POLARSSL_SSL_RENEGOTIATION */
+
+        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 > 43 + 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 );
+        }
+    }
+    else if( ssl->in_hslen == 42 + n )
+    {
+        ext_len = 0;
+    }
+    else
+    {
+        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->handshake->resume == 0 || n == 0 ||
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+        ssl->renegotiation != SSL_INITIAL_HANDSHAKE ||
+#endif
+        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] ) );
+
+    suite_info = ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite );
+    if( suite_info == NULL ||
+        ( ssl->arc4_disabled &&
+          suite_info->cipher == POLARSSL_CIPHER_ARC4_128 ) )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+    }
+
+
+    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" ) );
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+            renegotiation_info_seen = 1;
+#endif
+
+            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_ENCRYPT_THEN_MAC)
+        case TLS_EXT_ENCRYPT_THEN_MAC:
+            SSL_DEBUG_MSG( 3, ( "found encrypt_then_mac extension" ) );
+
+            if( ( ret = ssl_parse_encrypt_then_mac_ext( ssl,
+                            ext + 4, ext_size ) ) != 0 )
+            {
+                return( ret );
+            }
+
+            break;
+#endif /* POLARSSL_SSL_ENCRYPT_THEN_MAC */
+
+#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET)
+        case TLS_EXT_EXTENDED_MASTER_SECRET:
+            SSL_DEBUG_MSG( 3, ( "found extended_master_secret extension" ) );
+
+            if( ( ret = ssl_parse_extended_ms_ext( ssl,
+                            ext + 4, ext_size ) ) != 0 )
+            {
+                return( ret );
+            }
+
+            break;
+#endif /* POLARSSL_SSL_EXTENDED_MASTER_SECRET */
+
+#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;
+    }
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+    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;
+    }
+#endif /* POLARSSL_SSL_RENEGOTIATION */
+
+    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( POLARSSL_ERR_SSL_INTERNAL_ERROR );
+    }
+
+    SSL_DEBUG_MSG( 2, ( "ECDH curve: %s", curve_info->name ) );
+
+#if defined(POLARSSL_SSL_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_INTERNAL_ERROR );
+    }
+
+#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_INTERNAL_ERROR );
+        }
+
+        /*
+         * 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;
+
+            md5_init(  &md5  );
+            sha1_init( &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 );
+
+            md5_free(  &md5  );
+            sha1_free( &sha1 );
+        }
+        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;
+
+            md_init( &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 );
+        }
+        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_INTERNAL_ERROR );
+        }
+
+        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 )
+{
+    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 never happen" ) );
+    return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
+}
+#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 = POLARSSL_PREMASTER_SIZE;
+
+        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_INTERNAL_ERROR );
+        }
+
+        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_INTERNAL_ERROR );
+    }
+
+    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 )
+{
+    const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
+    int ret;
+
+    SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) );
+
+    if( ( ret = ssl_derive_keys( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_derive_keys", ret );
+        return( ret );
+    }
+
+    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 never happen" ) );
+    return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
+}
+#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( ( ret = ssl_derive_keys( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_derive_keys", ret );
+        return( ret );
+    }
+
+    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_INTERNAL_ERROR );
+    }
+
+    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_zeroize( ssl->session_negotiate->ticket,
+                      ssl->session_negotiate->ticket_len );
+    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/polarssl/ssl_srv.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,3628 @@
+/*
+ *  SSLv3/TLSv1 server-side functions
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.h>
+
+#if defined(POLARSSL_ECP_C)
+#include "polarssl/ecp.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_HAVE_TIME)
+#include <time.h>
+#endif
+
+#if defined(POLARSSL_SSL_SESSION_TICKETS)
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+/*
+ * 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_der( 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 ) );
+
+    /* Zeroize instead of free as we copied the content */
+    polarssl_zeroize( &session, 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 defined(POLARSSL_SSL_RENEGOTIATION)
+    if( ssl->renegotiation != SSL_INITIAL_HANDSHAKE )
+    {
+        /* 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 renegotiation info" ) );
+
+            if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
+                return( ret );
+
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+        }
+    }
+    else
+#endif /* POLARSSL_SSL_RENEGOTIATION */
+    {
+        if( len != 1 || buf[0] != 0x0 )
+        {
+            SSL_DEBUG_MSG( 1, ( "non-zero length renegotiation info" ) );
+
+            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;
+    }
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_SSL_PROTO_TLS1_2) && \
+    defined(POLARSSL_KEY_EXCHANGE__WITH_CERT__ENABLED)
+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;
+    const unsigned char *end = buf + len;
+    const int *md_cur;
+
+
+    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 );
+    }
+
+    /*
+     * For now, ignore the SignatureAlgorithm part and rely on offered
+     * ciphersuites only for that part. To be fixed later.
+     *
+     * So, just look at the HashAlgorithm part.
+     */
+    for( md_cur = md_list(); *md_cur != POLARSSL_MD_NONE; md_cur++ ) {
+        for( p = buf + 2; p < end; p += 2 ) {
+            if( *md_cur == (int) ssl_md_alg_from_hash( p[0] ) ) {
+                ssl->handshake->sig_alg = p[0];
+                goto have_sig_alg;
+            }
+        }
+    }
+
+    /* Some key echanges do not need signatures at all */
+    SSL_DEBUG_MSG( 3, ( "no signature_algorithm in common" ) );
+    return( 0 );
+
+have_sig_alg:
+    SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: %d",
+                   ssl->handshake->sig_alg ) );
+
+    return( 0 );
+}
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 &&
+          POLARSSL_KEY_EXCHANGE__WITH_CERT__ENABLED */
+
+#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 );
+    }
+
+    /* Should never happen unless client duplicates the extension */
+    if( ssl->handshake->curves != NULL )
+    {
+        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);
+
+    if( ssl->trunc_hmac == SSL_TRUNC_HMAC_ENABLED )
+        ssl->session_negotiate->trunc_hmac = SSL_TRUNC_HMAC_ENABLED;
+
+    return( 0 );
+}
+#endif /* POLARSSL_SSL_TRUNCATED_HMAC */
+
+#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
+static int ssl_parse_encrypt_then_mac_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);
+
+    if( ssl->encrypt_then_mac == SSL_ETM_ENABLED &&
+        ssl->minor_ver != SSL_MINOR_VERSION_0 )
+    {
+        ssl->session_negotiate->encrypt_then_mac = SSL_ETM_ENABLED;
+    }
+
+    return( 0 );
+}
+#endif /* POLARSSL_SSL_ENCRYPT_THEN_MAC */
+
+#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET)
+static int ssl_parse_extended_ms_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);
+
+    if( ssl->extended_ms == SSL_EXTENDED_MS_ENABLED &&
+        ssl->minor_ver != SSL_MINOR_VERSION_0 )
+    {
+        ssl->handshake->extended_ms = SSL_EXTENDED_MS_ENABLED;
+    }
+
+    return( 0 );
+}
+#endif /* POLARSSL_SSL_EXTENDED_MASTER_SECRET */
+
+#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 defined(POLARSSL_SSL_RENEGOTIATION)
+    if( ssl->renegotiation != SSL_INITIAL_HANDSHAKE )
+    {
+        SSL_DEBUG_MSG( 3, ( "ticket rejected: renegotiating" ) );
+        return( 0 );
+    }
+#endif /* POLARSSL_SSL_RENEGOTIATION */
+
+    /*
+     * 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,
+                               const unsigned char *buf, size_t len )
+{
+    size_t list_len, cur_len, ours_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++ )
+    {
+        ours_len = strlen( *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 == ours_len &&
+                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 0 if the given key uses one of the acceptable curves, -1 otherwise
+ */
+#if defined(POLARSSL_ECDSA_C)
+static int ssl_check_key_curve( 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( 0 );
+        crv++;
+    }
+
+    return( -1 );
+}
+#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, *fallback = NULL;
+    pk_type_t pk_alg = ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info );
+    int flags;
+
+#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 );
+
+    SSL_DEBUG_MSG( 3, ( "ciphersuite requires certificate" ) );
+
+    for( cur = list; cur != NULL; cur = cur->next )
+    {
+        SSL_DEBUG_CRT( 3, "candidate certificate chain, certificate",
+                          cur->cert );
+
+        if( ! pk_can_do( cur->key, pk_alg ) )
+        {
+            SSL_DEBUG_MSG( 3, ( "certificate mismatch: key type" ) );
+            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, &flags ) != 0 )
+        {
+            SSL_DEBUG_MSG( 3, ( "certificate mismatch: "
+                                "(extended) key usage extension" ) );
+            continue;
+        }
+
+#if defined(POLARSSL_ECDSA_C)
+        if( pk_alg == POLARSSL_PK_ECDSA &&
+            ssl_check_key_curve( cur->key, ssl->handshake->curves ) != 0 )
+        {
+            SSL_DEBUG_MSG( 3, ( "certificate mismatch: elliptic curve" ) );
+            continue;
+        }
+#endif
+
+        /*
+         * Try to select a SHA-1 certificate for pre-1.2 clients, but still
+         * present them a SHA-higher cert rather than failing if it's the only
+         * one we got that satisfies the other conditions.
+         */
+        if( ssl->minor_ver < SSL_MINOR_VERSION_3 &&
+            cur->cert->sig_md != POLARSSL_MD_SHA1 )
+        {
+            if( fallback == NULL )
+                fallback = cur;
+            {
+                SSL_DEBUG_MSG( 3, ( "certificate not preferred: "
+                                    "sha-2 with pre-TLS 1.2 client" ) );
+            continue;
+            }
+        }
+
+        /* If we get there, we got a winner */
+        break;
+    }
+
+    if( cur == NULL )
+        cur = fallback;
+
+
+    /* Do not update ssl->handshake->key_cert unless the is a match */
+    if( cur != NULL )
+    {
+        ssl->handshake->key_cert = cur;
+        SSL_DEBUG_CRT( 3, "selected certificate chain, certificate",
+                          ssl->handshake->key_cert->cert );
+        return( 0 );
+    }
+
+    return( -1 );
+}
+#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, ( "should never happen" ) );
+        return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
+    }
+
+    SSL_DEBUG_MSG( 3, ( "trying ciphersuite: %s", suite_info->name ) );
+
+    if( suite_info->min_minor_ver > ssl->minor_ver ||
+        suite_info->max_minor_ver < ssl->minor_ver )
+    {
+        SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: version" ) );
+        return( 0 );
+    }
+
+    if( ssl->arc4_disabled == SSL_ARC4_DISABLED &&
+            suite_info->cipher == POLARSSL_CIPHER_ARC4_128 )
+    {
+        SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: rc4" ) );
+        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 ) )
+    {
+        SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: "
+                            "no common elliptic curve" ) );
+        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 ) )
+    {
+        SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: no pre-shared key" ) );
+        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 )
+    {
+        SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: "
+                            "no suitable certificate" ) );
+        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, got_common_suite;
+    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 defined(POLARSSL_SSL_RENEGOTIATION)
+    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 );
+    }
+#endif /* POLARSSL_SSL_RENEGOTIATION */
+
+    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 defined(POLARSSL_SSL_RENEGOTIATION)
+            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 );
+            }
+#endif /* POLARSSL_SSL_RENEGOTIATION */
+            ssl->secure_renegotiation = SSL_SECURE_RENEGOTIATION;
+            break;
+        }
+    }
+
+#if defined(POLARSSL_SSL_FALLBACK_SCSV)
+    for( i = 0, p = buf + 6; i < ciph_len; i += 3, p += 3 )
+    {
+        if( p[0] == 0 &&
+            p[1] == (unsigned char)( ( SSL_FALLBACK_SCSV >> 8 ) & 0xff ) &&
+            p[2] == (unsigned char)( ( SSL_FALLBACK_SCSV      ) & 0xff ) )
+        {
+            SSL_DEBUG_MSG( 3, ( "received FALLBACK_SCSV" ) );
+
+            if( ssl->minor_ver < ssl->max_minor_ver )
+            {
+                SSL_DEBUG_MSG( 1, ( "inapropriate fallback" ) );
+
+                ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL,
+                                        SSL_ALERT_MSG_INAPROPRIATE_FALLBACK );
+
+                return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+            }
+
+            break;
+        }
+    }
+#endif /* POLARSSL_SSL_FALLBACK_SCSV */
+
+    got_common_suite = 0;
+    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;
+
+            got_common_suite = 1;
+
+            if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i],
+                                               &ciphersuite_info ) ) != 0 )
+                return( ret );
+
+            if( ciphersuite_info != NULL )
+                goto have_ciphersuite_v2;
+        }
+    }
+
+    if( got_common_suite )
+    {
+        SSL_DEBUG_MSG( 1, ( "got ciphersuites in common, "
+                            "but none of them usable" ) );
+        return( POLARSSL_ERR_SSL_NO_USABLE_CIPHERSUITE );
+    }
+    else
+    {
+        SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) );
+        return( POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN );
+    }
+
+have_ciphersuite_v2:
+    SSL_DEBUG_MSG( 2, ( "selected ciphersuite: %s", ciphersuite_info->name ) );
+
+    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, got_common_suite;
+    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;
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+    int renegotiation_info_seen = 0;
+#endif
+    int handshake_failure = 0;
+    const int *ciphersuites;
+    const ssl_ciphersuite_t *ciphersuite_info;
+
+    SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) );
+
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+    if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE )
+#endif
+    {
+        if( ( 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 defined(POLARSSL_SSL_RENEGOTIATION)
+    if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE )
+#endif
+    {
+        if( ( ret = ssl_fetch_input( ssl, 5 + n ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_fetch_input", ret );
+            return( ret );
+        }
+    }
+
+    buf = ssl->in_msg;
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+    if( ssl->renegotiation != SSL_INITIAL_HANDSHAKE )
+        n = ssl->in_msglen;
+    else
+#endif
+        n = ssl->in_left - 5;
+
+    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 . 40+y  ciphersuitelist
+     *   41+y . 41+y  compression alg length
+     *   42+y . 41+z  compression algs
+     *    ..  .  ..   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 || sess_len > n - 42 )
+    {
+        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 || ciph_len > n - 42 - sess_len )
+    {
+        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 ||
+        comp_len > n - 42 - sess_len - ciph_len )
+    {
+        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 defined(POLARSSL_SSL_RENEGOTIATION)
+            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 );
+            }
+            renegotiation_info_seen = 1;
+#endif /* POLARSSL_SSL_RENEGOTIATION */
+            ssl->secure_renegotiation = SSL_SECURE_RENEGOTIATION;
+            break;
+        }
+    }
+
+#if defined(POLARSSL_SSL_FALLBACK_SCSV)
+    for( i = 0, p = buf + 41 + sess_len; i < ciph_len; i += 2, p += 2 )
+    {
+        if( p[0] == (unsigned char)( ( SSL_FALLBACK_SCSV >> 8 ) & 0xff ) &&
+            p[1] == (unsigned char)( ( SSL_FALLBACK_SCSV      ) & 0xff ) )
+        {
+            SSL_DEBUG_MSG( 0, ( "received FALLBACK_SCSV" ) );
+
+            if( ssl->minor_ver < ssl->max_minor_ver )
+            {
+                SSL_DEBUG_MSG( 0, ( "inapropriate fallback" ) );
+
+                ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL,
+                                        SSL_ALERT_MSG_INAPROPRIATE_FALLBACK );
+
+                return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+            }
+
+            break;
+        }
+    }
+#endif /* POLARSSL_SSL_FALLBACK_SCSV */
+
+    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" ) );
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+            renegotiation_info_seen = 1;
+#endif
+
+            ret = ssl_parse_renegotiation_info( ssl, ext + 4, ext_size );
+            if( ret != 0 )
+                return( ret );
+            break;
+
+#if defined(POLARSSL_SSL_PROTO_TLS1_2) && \
+    defined(POLARSSL_KEY_EXCHANGE__WITH_CERT__ENABLED)
+        case TLS_EXT_SIG_ALG:
+            SSL_DEBUG_MSG( 3, ( "found signature_algorithms extension" ) );
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+            if( ssl->renegotiation == SSL_RENEGOTIATION )
+                break;
+#endif
+
+            ret = ssl_parse_signature_algorithms_ext( ssl, ext + 4, ext_size );
+            if( ret != 0 )
+                return( ret );
+            break;
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 &&
+          POLARSSL_KEY_EXCHANGE__WITH_CERT__ENABLED */
+
+#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_ENCRYPT_THEN_MAC)
+        case TLS_EXT_ENCRYPT_THEN_MAC:
+            SSL_DEBUG_MSG( 3, ( "found encrypt then mac extension" ) );
+
+            ret = ssl_parse_encrypt_then_mac_ext( ssl, ext + 4, ext_size );
+            if( ret != 0 )
+                return( ret );
+            break;
+#endif /* POLARSSL_SSL_ENCRYPT_THEN_MAC */
+
+#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET)
+        case TLS_EXT_EXTENDED_MASTER_SECRET:
+            SSL_DEBUG_MSG( 3, ( "found extended master secret extension" ) );
+
+            ret = ssl_parse_extended_ms_ext( ssl, ext + 4, ext_size );
+            if( ret != 0 )
+                return( ret );
+            break;
+#endif /* POLARSSL_SSL_EXTENDED_MASTER_SECRET */
+
+#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_SECURE_RENEGOTIATION &&
+        ssl->allow_legacy_renegotiation == SSL_LEGACY_BREAK_HANDSHAKE )
+    {
+        SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) );
+        handshake_failure = 1;
+    }
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+    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;
+    }
+#endif /* POLARSSL_SSL_RENEGOTIATION */
+
+    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.)
+     */
+    got_common_suite = 0;
+    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;
+
+            got_common_suite = 1;
+
+            if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i],
+                                               &ciphersuite_info ) ) != 0 )
+                return( ret );
+
+            if( ciphersuite_info != NULL )
+                goto have_ciphersuite;
+        }
+    }
+
+    if( got_common_suite )
+    {
+        SSL_DEBUG_MSG( 1, ( "got ciphersuites in common, "
+                            "but none of them usable" ) );
+        ssl_send_fatal_handshake_failure( ssl );
+        return( POLARSSL_ERR_SSL_NO_USABLE_CIPHERSUITE );
+    }
+    else
+    {
+        SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) );
+        ssl_send_fatal_handshake_failure( ssl );
+        return( POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN );
+    }
+
+have_ciphersuite:
+    SSL_DEBUG_MSG( 2, ( "selected ciphersuite: %s", ciphersuite_info->name ) );
+
+    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_ENCRYPT_THEN_MAC)
+static void ssl_write_encrypt_then_mac_ext( ssl_context *ssl,
+                                            unsigned char *buf,
+                                            size_t *olen )
+{
+    unsigned char *p = buf;
+    const ssl_ciphersuite_t *suite = NULL;
+    const cipher_info_t *cipher = NULL;
+
+    if( ssl->session_negotiate->encrypt_then_mac == SSL_EXTENDED_MS_DISABLED ||
+        ssl->minor_ver == SSL_MINOR_VERSION_0 )
+    {
+        *olen = 0;
+        return;
+    }
+
+    /*
+     * RFC 7366: "If a server receives an encrypt-then-MAC request extension
+     * from a client and then selects a stream or Authenticated Encryption
+     * with Associated Data (AEAD) ciphersuite, it MUST NOT send an
+     * encrypt-then-MAC response extension back to the client."
+     */
+    if( ( suite = ssl_ciphersuite_from_id(
+                    ssl->session_negotiate->ciphersuite ) ) == NULL ||
+        ( cipher = cipher_info_from_type( suite->cipher ) ) == NULL ||
+        cipher->mode != POLARSSL_MODE_CBC )
+    {
+        *olen = 0;
+        return;
+    }
+
+    SSL_DEBUG_MSG( 3, ( "server hello, adding encrypt then mac extension" ) );
+
+    *p++ = (unsigned char)( ( TLS_EXT_ENCRYPT_THEN_MAC >> 8 ) & 0xFF );
+    *p++ = (unsigned char)( ( TLS_EXT_ENCRYPT_THEN_MAC      ) & 0xFF );
+
+    *p++ = 0x00;
+    *p++ = 0x00;
+
+    *olen = 4;
+}
+#endif /* POLARSSL_SSL_ENCRYPT_THEN_MAC */
+
+#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET)
+static void ssl_write_extended_ms_ext( ssl_context *ssl,
+                                       unsigned char *buf,
+                                       size_t *olen )
+{
+    unsigned char *p = buf;
+
+    if( ssl->handshake->extended_ms == SSL_EXTENDED_MS_DISABLED ||
+        ssl->minor_ver == SSL_MINOR_VERSION_0 )
+    {
+        *olen = 0;
+        return;
+    }
+
+    SSL_DEBUG_MSG( 3, ( "server hello, adding extended master secret "
+                        "extension" ) );
+
+    *p++ = (unsigned char)( ( TLS_EXT_EXTENDED_MASTER_SECRET >> 8 ) & 0xFF );
+    *p++ = (unsigned char)( ( TLS_EXT_EXTENDED_MASTER_SECRET      ) & 0xFF );
+
+    *p++ = 0x00;
+    *p++ = 0x00;
+
+    *olen = 4;
+}
+#endif /* POLARSSL_SSL_EXTENDED_MASTER_SECRET */
+
+#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 );
+
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+    if( ssl->renegotiation != SSL_INITIAL_HANDSHAKE )
+    {
+        *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;
+    }
+    else
+#endif /* POLARSSL_SSL_RENEGOTIATION */
+    {
+        *p++ = 0x00;
+        *p++ = 0x01;
+        *p++ = 0x00;
+
+        *olen = 5;
+    }
+}
+
+#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 &&
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+        ssl->renegotiation == SSL_INITIAL_HANDSHAKE &&
+#endif
+        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_ENCRYPT_THEN_MAC)
+    ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, &olen );
+    ext_len += olen;
+#endif
+
+#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET)
+    ssl_write_extended_ms_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 )
+{
+    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 never happen" ) );
+    return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
+}
+#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_INTERNAL_ERROR );
+            }
+        }
+        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( 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;
+
+            md5_init(  &md5  );
+            sha1_init( &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;
+
+            md5_free(  &md5  );
+            sha1_free( &sha1 );
+        }
+        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;
+            const md_info_t *md_info = md_info_from_type( md_alg );
+
+            md_init( &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 ) ) != 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 );
+            md_free( &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_INTERNAL_ERROR );
+        }
+
+        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;
+    unsigned char fake_pms[48], peer_pms[48];
+    unsigned char mask;
+    size_t i, diff, peer_pmslen;
+
+    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 );
+    }
+
+    /*
+     * 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.
+     * Also, avoid data-dependant branches here to protect against
+     * timing-based variants.
+     */
+    ret = ssl->f_rng( ssl->p_rng, fake_pms, sizeof( fake_pms ) );
+    if( ret != 0 )
+        return( ret );
+
+    ret = pk_decrypt( ssl_own_key( ssl ), p, len,
+                      peer_pms, &peer_pmslen,
+                      sizeof( peer_pms ),
+                      ssl->f_rng, ssl->p_rng );
+
+    diff  = (size_t) ret;
+    diff |= peer_pmslen ^ 48;
+    diff |= peer_pms[0] ^ ssl->handshake->max_major_ver;
+    diff |= peer_pms[1] ^ ssl->handshake->max_minor_ver;
+
+#if defined(POLARSSL_SSL_DEBUG_ALL)
+    if( diff != 0 )
+        SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
+#endif
+
+    if( sizeof( ssl->handshake->premaster ) < pms_offset ||
+        sizeof( ssl->handshake->premaster ) - pms_offset < 48 )
+    {
+        SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+        return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
+    }
+    ssl->handshake->pmslen = 48;
+
+    mask = ( diff | - diff ) >> ( sizeof( size_t ) * 8 - 1 );
+    mask = (unsigned char)( - ( ret != 0 ) ); /* mask = diff ? 0xff : 0x00 */
+    for( i = 0; i < ssl->handshake->pmslen; i++ )
+        pms[i] = ( mask & fake_pms[i] ) | ( (~mask) & peer_pms[i] );
+
+    return( 0 );
+}
+#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( ssl->f_psk( ssl->p_psk, ssl, *p, n ) != 0 )
+            ret = POLARSSL_ERR_SSL_UNKNOWN_IDENTITY;
+    }
+    else
+    {
+        /* 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;
+
+    return( 0 );
+}
+#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 = POLARSSL_PREMASTER_SIZE;
+
+        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_INTERNAL_ERROR );
+    }
+
+    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 )
+{
+    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 never happen" ) );
+    return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
+}
+#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_INTERNAL_ERROR );
+    }
+
+    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/polarssl/ssl_tls.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,5292 @@
+/*
+ *  SSLv3/TLSv1 shared functions
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.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
+#include <stdlib.h>
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+#if defined(_MSC_VER) && !defined strcasecmp && !defined(EFIX64) && \
+    !defined(EFI32)
+#define strcasecmp _stricmp
+#endif
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+#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 = 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_der( 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 = 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);
+
+    md5_init(  &md5  );
+    sha1_init( &sha1 );
+
+    /*
+     *  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 );
+    }
+
+    md5_free(  &md5  );
+    sha1_free( &sha1 );
+
+    polarssl_zeroize( padding, sizeof( padding ) );
+    polarssl_zeroize( sha1sum, 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] );
+    }
+
+    polarssl_zeroize( tmp, sizeof( tmp ) );
+    polarssl_zeroize( h_i, 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];
+    }
+
+    polarssl_zeroize( tmp, sizeof( tmp ) );
+    polarssl_zeroize( h_i, 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];
+    }
+
+    polarssl_zeroize( tmp, sizeof( tmp ) );
+    polarssl_zeroize( h_i, 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_INTERNAL_ERROR );
+    }
+
+    /*
+     * 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 );
+
+#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET)
+        if( ssl->handshake->extended_ms == SSL_EXTENDED_MS_ENABLED )
+        {
+            unsigned char session_hash[48];
+            size_t hash_len;
+
+            SSL_DEBUG_MSG( 3, ( "using extended master secret" ) );
+
+            ssl->handshake->calc_verify( ssl, session_hash );
+
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+            if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
+            {
+#if defined(POLARSSL_SHA512_C)
+                if( ssl->transform_negotiate->ciphersuite_info->mac ==
+                    POLARSSL_MD_SHA384 )
+                {
+                    hash_len = 48;
+                }
+                else
+#endif
+                    hash_len = 32;
+            }
+            else
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
+                hash_len = 36;
+
+            SSL_DEBUG_BUF( 3, "session hash", session_hash, hash_len );
+
+            handshake->tls_prf( handshake->premaster, handshake->pmslen,
+                                "extended master secret",
+                                session_hash, hash_len, session->master, 48 );
+
+        }
+        else
+#endif
+        handshake->tls_prf( handshake->premaster, handshake->pmslen,
+                            "master secret",
+                            handshake->randbytes, 64, session->master, 48 );
+
+
+        polarssl_zeroize( handshake->premaster, 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 );
+    polarssl_zeroize( tmp, 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 );
+
+    polarssl_zeroize( handshake->randbytes, sizeof( handshake->randbytes ) );
+
+    /*
+     * Determine the appropriate key, IV and MAC length.
+     */
+
+    transform->keylen = cipher_info->key_length / 8;
+
+    if( cipher_info->mode == POLARSSL_MODE_GCM ||
+        cipher_info->mode == POLARSSL_MODE_CCM )
+    {
+        transform->maclen = 0;
+
+        transform->ivlen = 12;
+        transform->fixed_ivlen = 4;
+
+        /* Minimum length is expicit IV + tag */
+        transform->minlen = transform->ivlen - transform->fixed_ivlen
+                            + ( transform->ciphersuite_info->flags &
+                                POLARSSL_CIPHERSUITE_SHORT_TAG ? 8 : 16 );
+    }
+    else
+    {
+        int ret;
+
+        /* Initialize HMAC contexts */
+        if( ( ret = md_init_ctx( &transform->md_ctx_enc, md_info ) ) != 0 ||
+            ( ret = md_init_ctx( &transform->md_ctx_dec, md_info ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "md_init_ctx", ret );
+            return( ret );
+        }
+
+        /* Get MAC length */
+        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 */
+
+        /* IV length */
+        transform->ivlen = cipher_info->iv_size;
+
+        /* Minimum length */
+        if( cipher_info->mode == POLARSSL_MODE_STREAM )
+            transform->minlen = transform->maclen;
+        else
+        {
+            /*
+             * GenericBlockCipher:
+             * 1. if EtM is in use: one block plus MAC
+             *    otherwise: * first multiple of blocklen greater than maclen
+             * 2. IV except for SSL3 and TLS 1.0
+             */
+#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
+            if( session->encrypt_then_mac == SSL_ETM_ENABLED )
+            {
+                transform->minlen = transform->maclen
+                                  + cipher_info->block_size;
+            }
+            else
+#endif
+            {
+                transform->minlen = transform->maclen
+                                  + cipher_info->block_size
+                                  - transform->maclen % cipher_info->block_size;
+            }
+
+#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1)
+            if( ssl->minor_ver == SSL_MINOR_VERSION_0 ||
+                ssl->minor_ver == SSL_MINOR_VERSION_1 )
+                ; /* No need to adjust minlen */
+            else
+#endif
+#if defined(POLARSSL_SSL_PROTO_TLS1_1) || defined(POLARSSL_SSL_PROTO_TLS1_2)
+            if( ssl->minor_ver == SSL_MINOR_VERSION_2 ||
+                ssl->minor_ver == SSL_MINOR_VERSION_3 )
+            {
+                transform->minlen += transform->ivlen;
+            }
+            else
+#endif
+            {
+                SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+                return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
+            }
+        }
+    }
+
+    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 defined(POLARSSL_SSL_CLI_C)
+    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
+#endif /* POLARSSL_SSL_CLI_C */
+#if defined(POLARSSL_SSL_SRV_C)
+    if( ssl->endpoint == SSL_IS_SERVER )
+    {
+        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 );
+    }
+    else
+#endif /* POLARSSL_SSL_SRV_C */
+    {
+        SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+        return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
+    }
+
+#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_INTERNAL_ERROR );
+        }
+
+        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_INTERNAL_ERROR );
+    }
+
+#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 */
+
+    polarssl_zeroize( keyblk, 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" ) );
+
+    md5_free(  &md5  );
+    sha1_free( &sha1 );
+
+    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" ) );
+
+    md5_free(  &md5  );
+    sha1_free( &sha1 );
+
+    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" ) );
+
+    sha256_free( &sha256 );
+
+    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" ) );
+
+    sha512_free( &sha512 );
+
+    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 = end - ( p + 2 );
+
+        /* Write length only when we know the actual value */
+        if( ( ret = dhm_calc_secret( &ssl->handshake->dhm_ctx,
+                                      p + 2, &len,
+                                      ssl->f_rng, ssl->p_rng ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "dhm_calc_secret", ret );
+            return( ret );
+        }
+        *(p++) = (unsigned char)( len >> 8 );
+        *(p++) = (unsigned char)( len );
+        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_INTERNAL_ERROR );
+    }
+
+    /* 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;
+    int md_size = md_get_size( md_ctx->md_info );
+    int md_type = md_get_type( md_ctx->md_info );
+
+    /* Only MD5 and SHA-1 supported */
+    if( md_type == POLARSSL_MD_MD5 )
+        padlen = 48;
+    else
+        padlen = 40;
+
+    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 */
+
+#if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER) ||     \
+    ( defined(POLARSSL_CIPHER_MODE_CBC) &&                                  \
+      ( defined(POLARSSL_AES_C) || defined(POLARSSL_CAMELLIA_C) ) )
+#define POLARSSL_SOME_MODES_USE_MAC
+#endif
+
+/*
+ * Encryption/decryption functions
+ */
+static int ssl_encrypt_buf( ssl_context *ssl )
+{
+    size_t i;
+    cipher_mode_t mode;
+    int auth_done = 0;
+
+    SSL_DEBUG_MSG( 2, ( "=> encrypt buf" ) );
+
+    if( ssl->session_out == NULL || ssl->transform_out == NULL )
+    {
+        SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+        return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
+    }
+
+    mode = cipher_get_cipher_mode( &ssl->transform_out->cipher_ctx_enc );
+
+    SSL_DEBUG_BUF( 4, "before encrypt: output payload",
+                      ssl->out_msg, ssl->out_msglen );
+
+    /*
+     * Add MAC before if needed
+     */
+#if defined(POLARSSL_SOME_MODES_USE_MAC)
+    if( mode == POLARSSL_MODE_STREAM ||
+        ( mode == POLARSSL_MODE_CBC
+#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
+          && ssl->session_out->encrypt_then_mac == SSL_ETM_DISABLED
+#endif
+        ) )
+    {
+#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_INTERNAL_ERROR );
+        }
+
+        SSL_DEBUG_BUF( 4, "computed mac",
+                       ssl->out_msg + ssl->out_msglen,
+                       ssl->transform_out->maclen );
+
+        ssl->out_msglen += ssl->transform_out->maclen;
+        auth_done++;
+    }
+#endif /* AEAD not the only option */
+
+    /*
+     * Encrypt
+     */
+#if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER)
+    if( 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 ) );
+
+        if( ( ret = cipher_crypt( &ssl->transform_out->cipher_ctx_enc,
+                                   ssl->transform_out->iv_enc,
+                                   ssl->transform_out->ivlen,
+                                   ssl->out_msg, ssl->out_msglen,
+                                   ssl->out_msg, &olen ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_crypt", ret );
+            return( ret );
+        }
+
+        if( ssl->out_msglen != olen )
+        {
+            SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+            return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
+        }
+    }
+    else
+#endif /* POLARSSL_ARC4_C || POLARSSL_CIPHER_NULL_CIPHER */
+#if defined(POLARSSL_GCM_C) || defined(POLARSSL_CCM_C)
+    if( mode == POLARSSL_MODE_GCM ||
+        mode == POLARSSL_MODE_CCM )
+    {
+        int ret;
+        size_t enc_msglen, olen;
+        unsigned char *enc_msg;
+        unsigned char add_data[13];
+        unsigned char taglen = ssl->transform_out->ciphersuite_info->flags &
+                               POLARSSL_CIPHERSUITE_SHORT_TAG ? 8 : 16;
+
+        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
+         */
+#if defined(POLARSSL_SSL_AEAD_RANDOM_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 );
+#else
+        if( ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen != 8 )
+        {
+            /* Reminder if we ever add an AEAD mode with a different size */
+            SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+            return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
+        }
+
+        memcpy( ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen,
+                             ssl->out_ctr, 8 );
+        memcpy( ssl->out_iv, ssl->out_ctr, 8 );
+#endif
+
+        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 ) );
+
+        /*
+         * Encrypt and authenticate
+         */
+        if( ( ret = cipher_auth_encrypt( &ssl->transform_out->cipher_ctx_enc,
+                                         ssl->transform_out->iv_enc,
+                                         ssl->transform_out->ivlen,
+                                         add_data, 13,
+                                         enc_msg, enc_msglen,
+                                         enc_msg, &olen,
+                                         enc_msg + enc_msglen, taglen ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_auth_encrypt", ret );
+            return( ret );
+        }
+
+        if( olen != enc_msglen )
+        {
+            SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+            return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
+        }
+
+        ssl->out_msglen += taglen;
+        auth_done++;
+
+        SSL_DEBUG_BUF( 4, "after encrypt: tag", enc_msg + enc_msglen, taglen );
+    }
+    else
+#endif /* POLARSSL_GCM_C || POLARSSL_CCM_C */
+#if defined(POLARSSL_CIPHER_MODE_CBC) &&                                    \
+    ( defined(POLARSSL_AES_C) || defined(POLARSSL_CAMELLIA_C) )
+    if( 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 ) );
+
+        if( ( ret = cipher_crypt( &ssl->transform_out->cipher_ctx_enc,
+                                   ssl->transform_out->iv_enc,
+                                   ssl->transform_out->ivlen,
+                                   enc_msg, enc_msglen,
+                                   enc_msg, &olen ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_crypt", ret );
+            return( ret );
+        }
+
+        if( enc_msglen != olen )
+        {
+            SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+            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
+
+#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
+        if( auth_done == 0 )
+        {
+            /*
+             * MAC(MAC_write_key, seq_num +
+             *     TLSCipherText.type +
+             *     TLSCipherText.version +
+             *     length_of( (IV +) ENC(...) ) +
+             *     IV + // except for TLS 1.0
+             *     ENC(content + padding + padding_length));
+             */
+            unsigned char pseudo_hdr[13];
+
+            SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) );
+
+            memcpy( pseudo_hdr +  0, ssl->out_ctr, 8 );
+            memcpy( pseudo_hdr +  8, ssl->out_hdr, 3 );
+            pseudo_hdr[11] = (unsigned char)( ( ssl->out_msglen >> 8 ) & 0xFF );
+            pseudo_hdr[12] = (unsigned char)( ( ssl->out_msglen      ) & 0xFF );
+
+            SSL_DEBUG_BUF( 4, "MAC'd meta-data", pseudo_hdr, 13 );
+
+            md_hmac_update( &ssl->transform_out->md_ctx_enc, pseudo_hdr, 13 );
+            md_hmac_update( &ssl->transform_out->md_ctx_enc,
+                             ssl->out_iv, ssl->out_msglen );
+            md_hmac_finish( &ssl->transform_out->md_ctx_enc,
+                             ssl->out_iv + ssl->out_msglen );
+            md_hmac_reset( &ssl->transform_out->md_ctx_enc );
+
+            ssl->out_msglen += ssl->transform_out->maclen;
+            auth_done++;
+        }
+#endif /* POLARSSL_SSL_ENCRYPT_THEN_MAC */
+    }
+    else
+#endif /* POLARSSL_CIPHER_MODE_CBC &&
+          ( POLARSSL_AES_C || POLARSSL_CAMELLIA_C ) */
+    {
+        SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+        return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
+    }
+
+    /* Make extra sure authentication was performed, exactly once */
+    if( auth_done != 1 )
+    {
+        SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+        return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
+    }
+
+    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;
+    cipher_mode_t mode;
+    int auth_done = 0;
+#if defined(POLARSSL_SOME_MODES_USE_MAC)
+    size_t padlen = 0, correct = 1;
+#endif
+
+    SSL_DEBUG_MSG( 2, ( "=> decrypt buf" ) );
+
+    if( ssl->session_in == NULL || ssl->transform_in == NULL )
+    {
+        SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+        return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
+    }
+
+    mode = cipher_get_cipher_mode( &ssl->transform_in->cipher_ctx_dec );
+
+    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( mode == POLARSSL_MODE_STREAM )
+    {
+        int ret;
+        size_t olen = 0;
+
+        padlen = 0;
+
+        if( ( ret = cipher_crypt( &ssl->transform_in->cipher_ctx_dec,
+                                   ssl->transform_in->iv_dec,
+                                   ssl->transform_in->ivlen,
+                                   ssl->in_msg, ssl->in_msglen,
+                                   ssl->in_msg, &olen ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_crypt", ret );
+            return( ret );
+        }
+
+        if( ssl->in_msglen != olen )
+        {
+            SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+            return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
+        }
+    }
+    else
+#endif /* POLARSSL_ARC4_C || POLARSSL_CIPHER_NULL_CIPHER */
+#if defined(POLARSSL_GCM_C) || defined(POLARSSL_CCM_C)
+    if( mode == POLARSSL_MODE_GCM ||
+        mode == POLARSSL_MODE_CCM )
+    {
+        int ret;
+        size_t dec_msglen, olen;
+        unsigned char *dec_msg;
+        unsigned char *dec_msg_result;
+        unsigned char add_data[13];
+        unsigned char taglen = ssl->transform_in->ciphersuite_info->flags &
+                               POLARSSL_CIPHERSUITE_SHORT_TAG ? 8 : 16;
+        unsigned char explicit_iv_len =  ssl->transform_in->ivlen -
+                                         ssl->transform_in->fixed_ivlen;
+
+        if( ssl->in_msglen < (size_t) explicit_iv_len + taglen )
+        {
+            SSL_DEBUG_MSG( 1, ( "msglen (%d) < explicit_iv_len (%d) "
+                                "+ taglen (%d)", ssl->in_msglen,
+                                explicit_iv_len, taglen ) );
+            return( POLARSSL_ERR_SSL_INVALID_MAC );
+        }
+        dec_msglen = ssl->in_msglen - explicit_iv_len - taglen;
+
+        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, taglen );
+
+        /*
+         * Decrypt and authenticate
+         */
+        if( ( ret = cipher_auth_decrypt( &ssl->transform_in->cipher_ctx_dec,
+                                         ssl->transform_in->iv_dec,
+                                         ssl->transform_in->ivlen,
+                                         add_data, 13,
+                                         dec_msg, dec_msglen,
+                                         dec_msg_result, &olen,
+                                         dec_msg + dec_msglen, taglen ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_auth_decrypt", ret );
+
+            if( ret == POLARSSL_ERR_CIPHER_AUTH_FAILED )
+                return( POLARSSL_ERR_SSL_INVALID_MAC );
+
+            return( ret );
+        }
+        auth_done++;
+
+        if( olen != dec_msglen )
+        {
+            SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+            return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
+        }
+    }
+    else
+#endif /* POLARSSL_GCM_C || POLARSSL_CCM_C */
+#if defined(POLARSSL_CIPHER_MODE_CBC) &&                                    \
+    ( defined(POLARSSL_AES_C) || defined(POLARSSL_CAMELLIA_C) )
+    if( 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 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;
+
+        /*
+         * Authenticate before decrypt if enabled
+         */
+#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
+        if( ssl->session_in->encrypt_then_mac == SSL_ETM_ENABLED )
+        {
+            unsigned char computed_mac[POLARSSL_SSL_MAX_MAC_SIZE];
+            unsigned char pseudo_hdr[13];
+
+            SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) );
+
+            dec_msglen -= ssl->transform_in->maclen;
+            ssl->in_msglen -= ssl->transform_in->maclen;
+
+            memcpy( pseudo_hdr +  0, ssl->in_ctr, 8 );
+            memcpy( pseudo_hdr +  8, ssl->in_hdr, 3 );
+            pseudo_hdr[11] = (unsigned char)( ( ssl->in_msglen >> 8 ) & 0xFF );
+            pseudo_hdr[12] = (unsigned char)( ( ssl->in_msglen      ) & 0xFF );
+
+            SSL_DEBUG_BUF( 4, "MAC'd meta-data", pseudo_hdr, 13 );
+
+            md_hmac_update( &ssl->transform_in->md_ctx_dec, pseudo_hdr, 13 );
+            md_hmac_update( &ssl->transform_in->md_ctx_dec,
+                             ssl->in_iv, ssl->in_msglen );
+            md_hmac_finish( &ssl->transform_in->md_ctx_dec, computed_mac );
+            md_hmac_reset( &ssl->transform_in->md_ctx_dec );
+
+            SSL_DEBUG_BUF( 4, "message  mac", ssl->in_iv + ssl->in_msglen,
+                                              ssl->transform_in->maclen );
+            SSL_DEBUG_BUF( 4, "computed mac", computed_mac,
+                                              ssl->transform_in->maclen );
+
+            if( safer_memcmp( ssl->in_iv + ssl->in_msglen, computed_mac,
+                              ssl->transform_in->maclen ) != 0 )
+            {
+                SSL_DEBUG_MSG( 1, ( "message mac does not match" ) );
+
+                return( POLARSSL_ERR_SSL_INVALID_MAC );
+            }
+            auth_done++;
+        }
+#endif /* POLARSSL_SSL_ENCRYPT_THEN_MAC */
+
+        /*
+         * Check length 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)
+        /*
+         * 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_crypt( &ssl->transform_in->cipher_ctx_dec,
+                                   ssl->transform_in->iv_dec,
+                                   ssl->transform_in->ivlen,
+                                   dec_msg, dec_msglen,
+                                   dec_msg_result, &olen ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_crypt", ret );
+            return( ret );
+        }
+
+        if( dec_msglen != olen )
+        {
+            SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+            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 &&
+            auth_done == 0 )
+        {
+#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_INTERNAL_ERROR );
+        }
+
+        ssl->in_msglen -= padlen;
+    }
+    else
+#endif /* POLARSSL_CIPHER_MODE_CBC &&
+          ( POLARSSL_AES_C || POLARSSL_CAMELLIA_C ) */
+    {
+        SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+        return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
+    }
+
+    SSL_DEBUG_BUF( 4, "raw buffer after decryption",
+                   ssl->in_msg, ssl->in_msglen );
+
+    /*
+     * Authenticate if not done yet.
+     * Compute the MAC regardless of the padding result (RFC4346, CBCTIME).
+     */
+#if defined(POLARSSL_SOME_MODES_USE_MAC)
+    if( auth_done == 0 )
+    {
+        unsigned char tmp[POLARSSL_SSL_MAX_MAC_SIZE];
+
+        ssl->in_msglen -= ssl->transform_in->maclen;
+
+        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 );
+            /* Call md_process at least once due to cache attacks */
+            for( j = 0; j < extra_run + 1; 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_INTERNAL_ERROR );
+        }
+
+        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;
+        }
+        auth_done++;
+
+        /*
+         * Finally check the correct flag
+         */
+        if( correct == 0 )
+            return( POLARSSL_ERR_SSL_INVALID_MAC );
+    }
+#endif /* POLARSSL_SOME_MODES_USE_MAC */
+
+    /* Make extra sure authentication was performed, exactly once */
+    if( auth_done != 1 )
+    {
+        SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+        return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
+    }
+
+    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 );
+}
+
+#undef MAC_NONE
+#undef MAC_PLAINTEXT
+#undef MAC_CIPHERTEXT
+
+#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" ) );
+
+    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] ) );
+            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 )
+{
+    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 never happen" ) );
+    return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
+}
+
+int ssl_parse_certificate( ssl_context *ssl )
+{
+    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 never happen" ) );
+    return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
+}
+#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 defined(POLARSSL_SSL_CLI_C)
+    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 */
+    }
+#endif /* POLARSSL_SSL_CLI_C */
+#if defined(POLARSSL_SSL_SRV_C)
+    if( ssl->endpoint == SSL_IS_SERVER )
+    {
+        if( ssl_own_cert( ssl ) == NULL )
+        {
+            SSL_DEBUG_MSG( 1, ( "got no certificate to send" ) );
+            return( POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED );
+        }
+    }
+#endif
+
+    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 defined(POLARSSL_SSL_SRV_C)
+    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 );
+    }
+#endif
+
+    if( ( ret = ssl_read_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+        return( ret );
+    }
+
+    ssl->state++;
+
+#if defined(POLARSSL_SSL_SRV_C)
+#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 */
+#endif /* POLARSSL_SSL_SRV_C */
+
+    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 = 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 defined(POLARSSL_SSL_RENEGOTIATION) && defined(POLARSSL_SSL_CLI_C)
+    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 );
+        }
+    }
+#endif /* POLARSSL_SSL_RENEGOTIATION && POLARSSL_SSL_CLI_C */
+
+    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,
+                                 &ssl->session_negotiate->verify_result ) != 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 */
+    {
+        SSL_DEBUG_MSG( 1, ( "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 );
+
+    md5_free(  &md5  );
+    sha1_free( &sha1 );
+
+    polarssl_zeroize(  padbuf, sizeof(  padbuf ) );
+    polarssl_zeroize(  md5sum, sizeof(  md5sum ) );
+    polarssl_zeroize( sha1sum, 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 );
+
+    md5_free(  &md5  );
+    sha1_free( &sha1 );
+
+    polarssl_zeroize(  padbuf, 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 );
+
+    sha256_free( &sha256 );
+
+    polarssl_zeroize(  padbuf, 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 );
+
+    sha512_free( &sha512 );
+
+    polarssl_zeroize(  padbuf, 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 defined(POLARSSL_SSL_RENEGOTIATION)
+    if( ssl->renegotiation == SSL_RENEGOTIATION )
+    {
+        ssl->renegotiation =  SSL_RENEGOTIATION_DONE;
+        ssl->renego_records_seen = 0;
+    }
+#endif
+
+    /*
+     * 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 )
+    {
+#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
+        /* RFC 7366 3.1: keep the EtM state */
+        ssl->session_negotiate->encrypt_then_mac =
+                  ssl->session->encrypt_then_mac;
+#endif
+
+        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;
+
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+    ssl->verify_data_len = hash_len;
+    memcpy( ssl->own_verify_data, ssl->out_msg + 4, hash_len );
+#endif
+
+    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 defined(POLARSSL_SSL_CLI_C)
+        if( ssl->endpoint == SSL_IS_CLIENT )
+            ssl->state = SSL_HANDSHAKE_WRAPUP;
+#endif
+#if defined(POLARSSL_SSL_SRV_C)
+        if( ssl->endpoint == SSL_IS_SERVER )
+            ssl->state = SSL_CLIENT_CHANGE_CIPHER_SPEC;
+#endif
+    }
+    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 );
+    }
+
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+    ssl->verify_data_len = hash_len;
+    memcpy( ssl->peer_verify_data, buf, hash_len );
+#endif
+
+    if( ssl->handshake->resume != 0 )
+    {
+#if defined(POLARSSL_SSL_CLI_C)
+        if( ssl->endpoint == SSL_IS_CLIENT )
+            ssl->state = SSL_CLIENT_CHANGE_CIPHER_SPEC;
+#endif
+#if defined(POLARSSL_SSL_SRV_C)
+        if( ssl->endpoint == SSL_IS_SERVER )
+            ssl->state = SSL_HANDSHAKE_WRAPUP;
+#endif
+    }
+    else
+        ssl->state++;
+
+    SSL_DEBUG_MSG( 2, ( "<= parse finished" ) );
+
+    return( 0 );
+}
+
+static void ssl_handshake_params_init( ssl_handshake_params *handshake )
+{
+    memset( handshake, 0, sizeof( ssl_handshake_params ) );
+
+#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_1)
+     md5_init(   &handshake->fin_md5  );
+    sha1_init(   &handshake->fin_sha1 );
+     md5_starts( &handshake->fin_md5  );
+    sha1_starts( &handshake->fin_sha1 );
+#endif
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+#if defined(POLARSSL_SHA256_C)
+    sha256_init(   &handshake->fin_sha256    );
+    sha256_starts( &handshake->fin_sha256, 0 );
+#endif
+#if defined(POLARSSL_SHA512_C)
+    sha512_init(   &handshake->fin_sha512    );
+    sha512_starts( &handshake->fin_sha512, 1 );
+#endif
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
+
+    handshake->update_checksum = ssl_update_checksum_start;
+    handshake->sig_alg = SSL_HASH_SHA1;
+
+#if defined(POLARSSL_DHM_C)
+    dhm_init( &handshake->dhm_ctx );
+#endif
+#if defined(POLARSSL_ECDH_C)
+    ecdh_init( &handshake->ecdh_ctx );
+#endif
+}
+
+static void ssl_transform_init( ssl_transform *transform )
+{
+    memset( transform, 0, sizeof(ssl_transform) );
+
+    cipher_init( &transform->cipher_ctx_enc );
+    cipher_init( &transform->cipher_ctx_dec );
+
+    md_init( &transform->md_ctx_enc );
+    md_init( &transform->md_ctx_dec );
+}
+
+void ssl_session_init( ssl_session *session )
+{
+    memset( session, 0, sizeof(ssl_session) );
+}
+
+static int ssl_handshake_init( ssl_context *ssl )
+{
+    /* Clear old handshake information if present */
+    if( ssl->transform_negotiate )
+        ssl_transform_free( ssl->transform_negotiate );
+    if( ssl->session_negotiate )
+        ssl_session_free( ssl->session_negotiate );
+    if( ssl->handshake )
+        ssl_handshake_free( ssl->handshake );
+
+    /*
+     * Either the pointers are now NULL or cleared properly and can be freed.
+     * Now allocate missing structures.
+     */
+    if( ssl->transform_negotiate == NULL )
+    {
+        ssl->transform_negotiate = polarssl_malloc( sizeof(ssl_transform) );
+    }
+
+    if( ssl->session_negotiate == NULL )
+    {
+        ssl->session_negotiate = polarssl_malloc( sizeof(ssl_session) );
+    }
+
+    if( ssl->handshake == NULL )
+    {
+        ssl->handshake = polarssl_malloc( sizeof(ssl_handshake_params) );
+    }
+
+    /* All pointers should exist and can be directly freed without issue */
+    if( ssl->handshake == NULL ||
+        ssl->transform_negotiate == NULL ||
+        ssl->session_negotiate == NULL )
+    {
+        SSL_DEBUG_MSG( 1, ( "malloc() of ssl sub-contexts failed" ) );
+
+        polarssl_free( ssl->handshake );
+        polarssl_free( ssl->transform_negotiate );
+        polarssl_free( ssl->session_negotiate );
+
+        ssl->handshake = NULL;
+        ssl->transform_negotiate = NULL;
+        ssl->session_negotiate = NULL;
+
+        return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+    }
+
+    /* Initialize structures */
+    ssl_session_init( ssl->session_negotiate );
+    ssl_transform_init( ssl->transform_negotiate );
+    ssl_handshake_params_init( ssl->handshake );
+
+#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;
+
+    memset( ssl, 0, sizeof( ssl_context ) );
+
+    /*
+     * 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_SSL_RENEGOTIATION)
+    ssl->renego_max_records = SSL_RENEGO_MAX_RECORDS_DEFAULT;
+    memset( ssl->renego_period, 0xFF, 7 );
+    ssl->renego_period[7] = 0x00;
+#endif
+
+#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
+     */
+    if( ( ssl->in_ctr = polarssl_malloc( len ) ) == NULL ||
+        ( ssl->out_ctr = polarssl_malloc( len ) ) == 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 );
+
+    ssl->in_hdr = ssl->in_ctr +  8;
+    ssl->in_iv  = ssl->in_ctr + 13;
+    ssl->in_msg = ssl->in_ctr + 13;
+
+    ssl->out_hdr = ssl->out_ctr +  8;
+    ssl->out_iv  = ssl->out_ctr + 13;
+    ssl->out_msg = ssl->out_ctr + 13;
+
+#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
+    ssl->encrypt_then_mac = SSL_ETM_ENABLED;
+#endif
+
+#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET)
+    ssl->extended_ms = SSL_EXTENDED_MS_ENABLED;
+#endif
+
+#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;
+
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+    ssl->renegotiation = SSL_INITIAL_HANDSHAKE;
+    ssl->renego_records_seen = 0;
+
+    ssl->verify_data_len = 0;
+    memset( ssl->own_verify_data, 0, SSL_VERIFY_DATA_MAX_LEN );
+    memset( ssl->peer_verify_data, 0, SSL_VERIFY_DATA_MAX_LEN );
+#endif
+    ssl->secure_renegotiation = SSL_LEGACY_RENEGOTIATION;
+
+    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;
+#if defined(POLARSSL_SSL_CBC_RECORD_SPLITTING)
+    if( ssl->split_done != SSL_CBC_RECORD_SPLITTING_DISABLED )
+        ssl->split_done = 0;
+#endif
+
+    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)
+static void ssl_ticket_keys_free( ssl_ticket_keys *tkeys )
+{
+    aes_free( &tkeys->enc );
+    aes_free( &tkeys->dec );
+
+    polarssl_zeroize( tkeys, sizeof(ssl_ticket_keys) );
+}
+
+/*
+ * 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 = polarssl_malloc( sizeof(ssl_ticket_keys) );
+    if( tkeys == NULL )
+        return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+
+    aes_init( &tkeys->enc );
+    aes_init( &tkeys->dec );
+
+    if( ( ret = ssl->f_rng( ssl->p_rng, tkeys->key_name, 16 ) ) != 0 )
+    {
+        ssl_ticket_keys_free( tkeys );
+        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 )
+    {
+        ssl_ticket_keys_free( tkeys );
+        polarssl_free( tkeys );
+        return( ret );
+    }
+
+    if( ( ret = ssl->f_rng( ssl->p_rng, tkeys->mac_key, 16 ) ) != 0 )
+    {
+        ssl_ticket_keys_free( tkeys );
+        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) && \
+    defined(POLARSSL_SSL_CLI_C)
+    if( endpoint == SSL_IS_CLIENT )
+        ssl->session_tickets = SSL_SESSION_TICKETS_ENABLED;
+#endif
+
+#if defined(POLARSSL_SSL_TRUNCATED_HMAC)
+    if( endpoint == SSL_IS_SERVER )
+        ssl->trunc_hmac = SSL_TRUNC_HMAC_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;
+}
+
+#if defined(POLARSSL_SSL_SRV_C)
+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;
+}
+#endif /* POLARSSL_SSL_SRV_C */
+
+#if defined(POLARSSL_SSL_CLI_C)
+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 );
+}
+#endif /* POLARSSL_SSL_CLI_C */
+
+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 = 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_DEPRECATED_REMOVED)
+#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 = 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 = 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_DEPRECATED_REMOVED */
+#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 );
+
+    if( psk_len > POLARSSL_PSK_MAX_LEN )
+        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+    if( ssl->psk != NULL || ssl->psk_identity != NULL )
+    {
+        polarssl_free( ssl->psk );
+        polarssl_free( ssl->psk_identity );
+    }
+
+    if( ( ssl->psk = polarssl_malloc( psk_len ) ) == NULL ||
+        ( ssl->psk_identity = polarssl_malloc( psk_identity_len ) ) == NULL )
+    {
+        polarssl_free( ssl->psk );
+        ssl->psk = NULL;
+        return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+    }
+
+    ssl->psk_len = psk_len;
+    ssl->psk_identity_len = psk_identity_len;
+
+    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 = 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_FALLBACK_SCSV) && defined(POLARSSL_SSL_CLI_C)
+void ssl_set_fallback( ssl_context *ssl, char fallback )
+{
+    ssl->fallback = fallback;
+}
+#endif
+
+#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
+void ssl_set_encrypt_then_mac( ssl_context *ssl, char etm )
+{
+    ssl->encrypt_then_mac = etm;
+}
+#endif
+
+#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET)
+void ssl_set_extended_master_secret( ssl_context *ssl, char ems )
+{
+    ssl->extended_ms = ems;
+}
+#endif
+
+void ssl_set_arc4_support( ssl_context *ssl, char arc4 )
+{
+    ssl->arc4_disabled = arc4;
+}
+
+#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 )
+{
+    ssl->trunc_hmac = truncate;
+
+    return( 0 );
+}
+#endif /* POLARSSL_SSL_TRUNCATED_HMAC */
+
+#if defined(POLARSSL_SSL_CBC_RECORD_SPLITTING)
+void ssl_set_cbc_record_splitting( ssl_context *ssl, char split )
+{
+    ssl->split_done = split;
+}
+#endif
+
+void ssl_legacy_renegotiation( ssl_context *ssl, int allow_legacy )
+{
+    ssl->allow_legacy_renegotiation = allow_legacy;
+}
+
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+void ssl_set_renegotiation( ssl_context *ssl, int renegotiation )
+{
+    ssl->disable_renegotiation = renegotiation;
+}
+
+void ssl_set_renegotiation_enforced( ssl_context *ssl, int max_records )
+{
+    ssl->renego_max_records = max_records;
+}
+
+void ssl_set_renegotiation_period( ssl_context *ssl,
+                                   const unsigned char period[8] )
+{
+    memcpy( ssl->renego_period, period, 8 );
+}
+#endif /* POLARSSL_SSL_RENEGOTIATION */
+
+#if defined(POLARSSL_SSL_SESSION_TICKETS)
+int ssl_set_session_tickets( ssl_context *ssl, int use_tickets )
+{
+    ssl->session_tickets = use_tickets;
+
+#if defined(POLARSSL_SSL_CLI_C)
+    if( ssl->endpoint == SSL_IS_CLIENT )
+        return( 0 );
+#endif
+
+    if( use_tickets == SSL_SESSION_TICKETS_DISABLED )
+        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 )
+{
+    if( ssl->session != NULL )
+        return( ssl->session->verify_result );
+
+    if( ssl->session_negotiate != NULL )
+        return( ssl->session_negotiate->verify_result );
+
+    return( -1 );
+}
+
+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 */
+
+#if defined(POLARSSL_SSL_CLI_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 ) );
+}
+#endif /* POLARSSL_SSL_CLI_C */
+
+/*
+ * 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_RENEGOTIATION)
+#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_DEBUG_MSG( 2, ( "<= write hello request" ) );
+
+    return( 0 );
+}
+#endif /* POLARSSL_SSL_SRV_C */
+
+/*
+ * Actually renegotiate current connection, triggered by either:
+ * - any side: calling ssl_renegotiate(),
+ * - client: receiving a HelloRequest during ssl_read(),
+ * - server: 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 );
+
+        ssl->renegotiation = SSL_RENEGOTIATION_PENDING;
+
+        /* Did we already try/start sending HelloRequest? */
+        if( ssl->out_left != 0 )
+            return( ssl_flush_output( ssl ) );
+
+        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 );
+}
+
+/*
+ * Check record counters and renegotiate if they're above the limit.
+ */
+static int ssl_check_ctr_renegotiate( ssl_context *ssl )
+{
+    if( ssl->state != SSL_HANDSHAKE_OVER ||
+        ssl->renegotiation == SSL_RENEGOTIATION_PENDING ||
+        ssl->disable_renegotiation == SSL_RENEGOTIATION_DISABLED )
+    {
+        return( 0 );
+    }
+
+    // TODO: adapt for DTLS
+    if( memcmp( ssl->in_ctr,  ssl->renego_period, 8 ) <= 0 &&
+        memcmp( ssl->out_ctr, ssl->renego_period, 8 ) <= 0 )
+    {
+        return( 0 );
+    }
+
+    SSL_DEBUG_MSG( 0, ( "record counter limit reached: renegotiate" ) );
+    return( ssl_renegotiate( ssl ) );
+}
+#endif /* POLARSSL_SSL_RENEGOTIATION */
+
+/*
+ * Receive application data decrypted from the SSL layer
+ */
+int ssl_read( ssl_context *ssl, unsigned char *buf, size_t len )
+{
+    int ret, record_read = 0;
+    size_t n;
+
+    SSL_DEBUG_MSG( 2, ( "=> read" ) );
+
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+    if( ( ret = ssl_check_ctr_renegotiate( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret );
+        return( ret );
+    }
+#endif
+
+    if( ssl->state != SSL_HANDSHAKE_OVER )
+    {
+        ret = ssl_handshake( ssl );
+        if( ret == POLARSSL_ERR_SSL_WAITING_SERVER_HELLO_RENEGO )
+        {
+            record_read = 1;
+        }
+        else if( ret != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_handshake", ret );
+            return( ret );
+        }
+    }
+
+    if( ssl->in_offt == NULL )
+    {
+        if( ! record_read )
+        {
+            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 defined(POLARSSL_SSL_RENEGOTIATION)
+        if( ssl->in_msgtype == SSL_MSG_HANDSHAKE )
+        {
+            SSL_DEBUG_MSG( 1, ( "received handshake message" ) );
+
+#if defined(POLARSSL_SSL_CLI_C)
+            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 );
+            }
+#endif
+
+            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_INTERNAL_ERROR );
+                }
+            }
+            else
+            {
+                ret = ssl_start_renegotiation( ssl );
+                if( ret == POLARSSL_ERR_SSL_WAITING_SERVER_HELLO_RENEGO )
+                {
+                    record_read = 1;
+                }
+                else if( ret != 0 )
+                {
+                    SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret );
+                    return( ret );
+                }
+            }
+
+            /* If a non-handshake record was read during renego, fallthrough,
+             * else tell the user they should call ssl_read() again */
+            if( ! record_read )
+                return( POLARSSL_ERR_NET_WANT_READ );
+        }
+        else if( ssl->renegotiation == SSL_RENEGOTIATION_PENDING )
+        {
+            ssl->renego_records_seen++;
+
+            if( ssl->renego_max_records >= 0 &&
+                ssl->renego_records_seen > ssl->renego_max_records )
+            {
+                SSL_DEBUG_MSG( 1, ( "renegotiation requested, "
+                                    "but not honored by client" ) );
+                return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+            }
+        }
+#endif /* POLARSSL_SSL_RENEGOTIATION */
+
+        /* Fatal and closure alerts handled by ssl_read_record() */
+        if( ssl->in_msgtype == SSL_MSG_ALERT )
+        {
+            SSL_DEBUG_MSG( 2, ( "ignoring non-fatal non-closure alert" ) );
+            return( POLARSSL_ERR_NET_WANT_READ );
+        }
+
+        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,
+ * taking care of max fragment length and buffer size
+ */
+static int ssl_write_real( ssl_context *ssl,
+                           const unsigned char *buf, size_t len )
+{
+    int ret;
+    size_t n;
+    unsigned int max_len = SSL_MAX_CONTENT_LEN;
+
+#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 );
+        }
+    }
+
+    return( (int) n );
+}
+
+/*
+ * Write application data, doing 1/n-1 splitting if necessary.
+ *
+ * With non-blocking I/O, ssl_write_real() may return WANT_WRITE,
+ * then the caller will call us again with the same arguments, so
+ * remember wether we already did the split or not.
+ */
+#if defined(POLARSSL_SSL_CBC_RECORD_SPLITTING)
+static int ssl_write_split( ssl_context *ssl,
+                            const unsigned char *buf, size_t len )
+{
+    int ret;
+
+    if( ssl->split_done == SSL_CBC_RECORD_SPLITTING_DISABLED ||
+        len <= 1 ||
+        ssl->minor_ver > SSL_MINOR_VERSION_1 ||
+        cipher_get_cipher_mode( &ssl->transform_out->cipher_ctx_enc )
+                                != POLARSSL_MODE_CBC )
+    {
+        return( ssl_write_real( ssl, buf, len ) );
+    }
+
+    if( ssl->split_done == 0 )
+    {
+        if( ( ret = ssl_write_real( ssl, buf, 1 ) ) <= 0 )
+            return( ret );
+        ssl->split_done = 1;
+    }
+
+    if( ( ret = ssl_write_real( ssl, buf + 1, len - 1 ) ) <= 0 )
+        return( ret );
+    ssl->split_done = 0;
+
+    return( ret + 1 );
+}
+#endif /* POLARSSL_SSL_CBC_RECORD_SPLITTING */
+
+/*
+ * Write application data (public-facing wrapper)
+ */
+int ssl_write( ssl_context *ssl, const unsigned char *buf, size_t len )
+{
+    int ret;
+
+    SSL_DEBUG_MSG( 2, ( "=> write" ) );
+
+#if defined(POLARSSL_SSL_RENEGOTIATION)
+    if( ( ret = ssl_check_ctr_renegotiate( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret );
+        return( ret );
+    }
+#endif
+
+    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_CBC_RECORD_SPLITTING)
+    ret = ssl_write_split( ssl, buf, len );
+#else
+    ret = ssl_write_real( ssl, buf, len );
+#endif
+
+    SSL_DEBUG_MSG( 2, ( "<= write" ) );
+
+    return( ret );
+}
+
+/*
+ * 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( ssl->out_left != 0 )
+        return( ssl_flush_output( ssl ) );
+
+    if( ssl->state == SSL_HANDSHAKE_OVER )
+    {
+        if( ( ret = ssl_send_alert_message( ssl,
+                        SSL_ALERT_LEVEL_WARNING,
+                        SSL_ALERT_MSG_CLOSE_NOTIFY ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_send_alert_message", ret );
+            return( ret );
+        }
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= write close notify" ) );
+
+    return( 0 );
+}
+
+void ssl_transform_free( ssl_transform *transform )
+{
+    if( transform == NULL )
+        return;
+
+#if defined(POLARSSL_ZLIB_SUPPORT)
+    deflateEnd( &transform->ctx_deflate );
+    inflateEnd( &transform->ctx_inflate );
+#endif
+
+    cipher_free( &transform->cipher_ctx_enc );
+    cipher_free( &transform->cipher_ctx_dec );
+
+    md_free( &transform->md_ctx_enc );
+    md_free( &transform->md_ctx_dec );
+
+    polarssl_zeroize( transform, 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( handshake == NULL )
+        return;
+
+#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 */
+
+    polarssl_zeroize( handshake, sizeof( ssl_handshake_params ) );
+}
+
+void ssl_session_free( ssl_session *session )
+{
+    if( session == NULL )
+        return;
+
+#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
+
+    polarssl_zeroize( session, sizeof( ssl_session ) );
+}
+
+/*
+ * Free an SSL context
+ */
+void ssl_free( ssl_context *ssl )
+{
+    if( ssl == NULL )
+        return;
+
+    SSL_DEBUG_MSG( 2, ( "=> free" ) );
+
+    if( ssl->out_ctr != NULL )
+    {
+        polarssl_zeroize( ssl->out_ctr, SSL_BUFFER_LEN );
+        polarssl_free( ssl->out_ctr );
+    }
+
+    if( ssl->in_ctr != NULL )
+    {
+        polarssl_zeroize( ssl->in_ctr, SSL_BUFFER_LEN );
+        polarssl_free( ssl->in_ctr );
+    }
+
+#if defined(POLARSSL_ZLIB_SUPPORT)
+    if( ssl->compress_buf != NULL )
+    {
+        polarssl_zeroize( ssl->compress_buf, 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)
+    if( ssl->ticket_keys )
+    {
+        ssl_ticket_keys_free( ssl->ticket_keys );
+        polarssl_free( ssl->ticket_keys );
+    }
+#endif
+
+#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
+    if( ssl->hostname != NULL )
+    {
+        polarssl_zeroize( ssl->hostname, ssl->hostname_len );
+        polarssl_free( ssl->hostname );
+        ssl->hostname_len = 0;
+    }
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
+    if( ssl->psk != NULL )
+    {
+        polarssl_zeroize( ssl->psk, ssl->psk_len );
+        polarssl_zeroize( ssl->psk_identity, 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 */
+    polarssl_zeroize( ssl, 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,
+                          int *flags )
+{
+    int ret = 0;
+#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);
+    ((void) flags);
+#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 )
+    {
+        *flags |= BADCERT_KEY_USAGE;
+        ret = -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 )
+    {
+        *flags |= BADCERT_EXT_KEY_USAGE;
+        ret = -1;
+    }
+#endif /* POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE */
+
+    return( ret );
+}
+#endif /* POLARSSL_X509_CRT_PARSE_C */
+
+#endif /* POLARSSL_SSL_TLS_C */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/polarssl/threading.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,111 @@
+/*
+ *  Threading abstraction layer
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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/polarssl/timing.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,505 @@
+/*
+ *  Portable interface to the CPU cycle counter
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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__ */
+
+/* some versions of mingw-64 have 32-bit longs even on x84_64 */
+#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) &&  \
+    defined(__GNUC__) && ( defined(__i386__) || (                       \
+    ( defined(__amd64__) || defined( __x86_64__) ) && __SIZEOF_LONG__ == 4 ) )
+
+#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 );
+}
+
+/* It's OK to use a global because alarm() is supposed to be global anyway */
+static DWORD alarmMs;
+
+static DWORD WINAPI TimerProc( LPVOID TimerContext )
+{
+    ((void) TimerContext);
+    Sleep( alarmMs );
+    alarmed = 1;
+    return( TRUE );
+}
+
+void set_alarm( int seconds )
+{
+    DWORD ThreadId;
+
+    alarmed = 0;
+    alarmMs = seconds * 1000;
+    CloseHandle( CreateThread( NULL, 0, TimerProc, NULL, 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 );
+
+    if( reset )
+    {
+        t->start.tv_sec  = offset.tv_sec;
+        t->start.tv_usec = offset.tv_usec;
+        return( 0 );
+    }
+
+    delta = ( offset.tv_sec  - t->start.tv_sec  ) * 1000
+          + ( offset.tv_usec - t->start.tv_usec ) / 1000;
+
+    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) && defined(POLARSSL_HAVE_TIME)
+#include "polarssl/net.h"
+#endif
+
+/*
+ * Busy-waits for the given number of milliseconds.
+ * Used for testing hardclock.
+ */
+static void busy_msleep( unsigned long msec )
+{
+    struct hr_time hires;
+    unsigned long i = 0; /* for busy-waiting */
+    volatile unsigned long j; /* to prevent optimisation */
+
+    (void) get_timer( &hires, 1 );
+
+    while( get_timer( &hires, 0 ) < msec )
+        i++;
+
+    j = i;
+    (void) j;
+}
+
+/*
+ * 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 note: 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( (int)( 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( (int) 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 / get_timer): " );
+
+    /*
+     * 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 */
+    millisecs = 1;
+    cycles = hardclock();
+    busy_msleep( millisecs );
+    cycles = hardclock() - cycles;
+    ratio = cycles / millisecs;
+
+    /* Check that the ratio is mostly constant */
+    for( millisecs = 2; millisecs <= 4; millisecs++ )
+    {
+        cycles = hardclock();
+        busy_msleep( 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 defined(POLARSSL_NET_C) && defined(POLARSSL_HAVE_TIME)
+    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 */
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+    return( 0 );
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_TIMING_C && !POLARSSL_TIMING_ALT */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/polarssl/version.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,52 @@
+/*
+ *  Version information
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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>
+
+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/polarssl/version_features.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,591 @@
+/*
+ *  Version feature information
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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
+
+static 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_EXIT_ALT)
+    "POLARSSL_PLATFORM_EXIT_ALT",
+#endif /* POLARSSL_PLATFORM_EXIT_ALT */
+#if defined(POLARSSL_PLATFORM_FPRINTF_ALT)
+    "POLARSSL_PLATFORM_FPRINTF_ALT",
+#endif /* POLARSSL_PLATFORM_FPRINTF_ALT */
+#if defined(POLARSSL_PLATFORM_PRINTF_ALT)
+    "POLARSSL_PLATFORM_PRINTF_ALT",
+#endif /* POLARSSL_PLATFORM_PRINTF_ALT */
+#if defined(POLARSSL_PLATFORM_SNPRINTF_ALT)
+    "POLARSSL_PLATFORM_SNPRINTF_ALT",
+#endif /* POLARSSL_PLATFORM_SNPRINTF_ALT */
+#if defined(POLARSSL_DEPRECATED_WARNING)
+    "POLARSSL_DEPRECATED_WARNING",
+#endif /* POLARSSL_DEPRECATED_WARNING */
+#if defined(POLARSSL_DEPRECATED_REMOVED)
+    "POLARSSL_DEPRECATED_REMOVED",
+#endif /* POLARSSL_DEPRECATED_REMOVED */
+#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_CAMELLIA_SMALL_MEMORY)
+    "POLARSSL_CAMELLIA_SMALL_MEMORY",
+#endif /* POLARSSL_CAMELLIA_SMALL_MEMORY */
+#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_REMOVE_ARC4_CIPHERSUITES)
+    "POLARSSL_REMOVE_ARC4_CIPHERSUITES",
+#endif /* POLARSSL_REMOVE_ARC4_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_AEAD_RANDOM_IV)
+    "POLARSSL_SSL_AEAD_RANDOM_IV",
+#endif /* POLARSSL_SSL_AEAD_RANDOM_IV */
+#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_ENCRYPT_THEN_MAC)
+    "POLARSSL_SSL_ENCRYPT_THEN_MAC",
+#endif /* POLARSSL_SSL_ENCRYPT_THEN_MAC */
+#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET)
+    "POLARSSL_SSL_EXTENDED_MASTER_SECRET",
+#endif /* POLARSSL_SSL_EXTENDED_MASTER_SECRET */
+#if defined(POLARSSL_SSL_FALLBACK_SCSV)
+    "POLARSSL_SSL_FALLBACK_SCSV",
+#endif /* POLARSSL_SSL_FALLBACK_SCSV */
+#if defined(POLARSSL_SSL_HW_RECORD_ACCEL)
+    "POLARSSL_SSL_HW_RECORD_ACCEL",
+#endif /* POLARSSL_SSL_HW_RECORD_ACCEL */
+#if defined(POLARSSL_SSL_CBC_RECORD_SPLITTING)
+    "POLARSSL_SSL_CBC_RECORD_SPLITTING",
+#endif /* POLARSSL_SSL_CBC_RECORD_SPLITTING */
+#if defined(POLARSSL_SSL_DISABLE_RENEGOTIATION)
+    "POLARSSL_SSL_DISABLE_RENEGOTIATION",
+#endif /* POLARSSL_SSL_DISABLE_RENEGOTIATION */
+#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_X509_RSASSA_PSS_SUPPORT)
+    "POLARSSL_X509_RSASSA_PSS_SUPPORT",
+#endif /* POLARSSL_X509_RSASSA_PSS_SUPPORT */
+#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_CCM_C)
+    "POLARSSL_CCM_C",
+#endif /* POLARSSL_CCM_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/polarssl/x509.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,1088 @@
+/*
+ *  X.509 common functions for parsing and verification
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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/rfc5280.txt (Certificates and CRLs)
+ *  http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs)
+ *  http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10)
+ *
+ *  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"
+
+#include <stdio.h>
+#include <string.h>
+
+#if defined(POLARSSL_PEM_PARSE_C)
+#include "polarssl/pem.h"
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#define polarssl_free       free
+#define polarssl_malloc     malloc
+#define polarssl_printf     printf
+#define polarssl_snprintf   snprintf
+#endif
+
+#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
+#include <windows.h>
+#else
+#include <time.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
+
+#define CHECK(code) if( ( ret = code ) != 0 ){ return( ret ); }
+
+/*
+ *  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 );
+}
+
+/*
+ * Parse an algorithm identifier with (optional) paramaters
+ */
+int x509_get_alg( unsigned char **p, const unsigned char *end,
+                  x509_buf *alg, x509_buf *params )
+{
+    int ret;
+
+    if( ( ret = asn1_get_alg( p, end, alg, params ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_ALG + ret );
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT)
+/*
+ * HashAlgorithm ::= AlgorithmIdentifier
+ *
+ * AlgorithmIdentifier  ::=  SEQUENCE  {
+ *      algorithm               OBJECT IDENTIFIER,
+ *      parameters              ANY DEFINED BY algorithm OPTIONAL  }
+ *
+ * For HashAlgorithm, parameters MUST be NULL or absent.
+ */
+static int x509_get_hash_alg( const x509_buf *alg, md_type_t *md_alg )
+{
+    int ret;
+    unsigned char *p;
+    const unsigned char *end;
+    x509_buf md_oid;
+    size_t len;
+
+    /* Make sure we got a SEQUENCE and setup bounds */
+    if( alg->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) )
+        return( POLARSSL_ERR_X509_INVALID_ALG +
+                POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
+
+    p = (unsigned char *) alg->p;
+    end = p + alg->len;
+
+    if( p >= end )
+        return( POLARSSL_ERR_X509_INVALID_ALG +
+                POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+    /* Parse md_oid */
+    md_oid.tag = *p;
+
+    if( ( ret = asn1_get_tag( &p, end, &md_oid.len, ASN1_OID ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_ALG + ret );
+
+    md_oid.p = p;
+    p += md_oid.len;
+
+    /* Get md_alg from md_oid */
+    if( ( ret = oid_get_md_alg( &md_oid, md_alg ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_ALG + ret );
+
+    /* Make sure params is absent of NULL */
+    if( p == end )
+        return( 0 );
+
+    if( ( ret = asn1_get_tag( &p, end, &len, ASN1_NULL ) ) != 0 || len != 0 )
+        return( POLARSSL_ERR_X509_INVALID_ALG + ret );
+
+    if( p != end )
+        return( POLARSSL_ERR_X509_INVALID_ALG +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    return( 0 );
+}
+
+/*
+ *    RSASSA-PSS-params  ::=  SEQUENCE  {
+ *       hashAlgorithm     [0] HashAlgorithm DEFAULT sha1Identifier,
+ *       maskGenAlgorithm  [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier,
+ *       saltLength        [2] INTEGER DEFAULT 20,
+ *       trailerField      [3] INTEGER DEFAULT 1  }
+ *    -- Note that the tags in this Sequence are explicit.
+ *
+ * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value
+ * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other
+ * option. Enfore this at parsing time.
+ */
+int x509_get_rsassa_pss_params( const x509_buf *params,
+                                md_type_t *md_alg, md_type_t *mgf_md,
+                                int *salt_len )
+{
+    int ret;
+    unsigned char *p;
+    const unsigned char *end, *end2;
+    size_t len;
+    x509_buf alg_id, alg_params;
+
+    /* First set everything to defaults */
+    *md_alg = POLARSSL_MD_SHA1;
+    *mgf_md = POLARSSL_MD_SHA1;
+    *salt_len = 20;
+
+    /* Make sure params is a SEQUENCE and setup bounds */
+    if( params->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) )
+        return( POLARSSL_ERR_X509_INVALID_ALG +
+                POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
+
+    p = (unsigned char *) params->p;
+    end = p + params->len;
+
+    if( p == end )
+        return( 0 );
+
+    /*
+     * HashAlgorithm
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len,
+                    ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) == 0 )
+    {
+        end2 = p + len;
+
+        /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */
+        if( ( ret = x509_get_alg_null( &p, end2, &alg_id ) ) != 0 )
+            return( ret );
+
+        if( ( ret = oid_get_md_alg( &alg_id, md_alg ) ) != 0 )
+            return( POLARSSL_ERR_X509_INVALID_ALG + ret );
+
+        if( p != end2 )
+            return( POLARSSL_ERR_X509_INVALID_ALG +
+                    POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+    }
+    else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+        return( POLARSSL_ERR_X509_INVALID_ALG + ret );
+
+    if( p == end )
+        return( 0 );
+
+    /*
+     * MaskGenAlgorithm
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len,
+                    ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1 ) ) == 0 )
+    {
+        end2 = p + len;
+
+        /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */
+        if( ( ret = x509_get_alg( &p, end2, &alg_id, &alg_params ) ) != 0 )
+            return( ret );
+
+        /* Only MFG1 is recognised for now */
+        if( ! OID_CMP( OID_MGF1, &alg_id ) )
+            return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE +
+                    POLARSSL_ERR_OID_NOT_FOUND );
+
+        /* Parse HashAlgorithm */
+        if( ( ret = x509_get_hash_alg( &alg_params, mgf_md ) ) != 0 )
+            return( ret );
+
+        if( p != end2 )
+            return( POLARSSL_ERR_X509_INVALID_ALG +
+                    POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+    }
+    else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+        return( POLARSSL_ERR_X509_INVALID_ALG + ret );
+
+    if( p == end )
+        return( 0 );
+
+    /*
+     * salt_len
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len,
+                    ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 2 ) ) == 0 )
+    {
+        end2 = p + len;
+
+        if( ( ret = asn1_get_int( &p, end2, salt_len ) ) != 0 )
+            return( POLARSSL_ERR_X509_INVALID_ALG + ret );
+
+        if( p != end2 )
+            return( POLARSSL_ERR_X509_INVALID_ALG +
+                    POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+    }
+    else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+        return( POLARSSL_ERR_X509_INVALID_ALG + ret );
+
+    if( p == end )
+        return( 0 );
+
+    /*
+     * trailer_field (if present, must be 1)
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len,
+                    ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) ) == 0 )
+    {
+        int trailer_field;
+
+        end2 = p + len;
+
+        if( ( ret = asn1_get_int( &p, end2, &trailer_field ) ) != 0 )
+            return( POLARSSL_ERR_X509_INVALID_ALG + ret );
+
+        if( p != end2 )
+            return( POLARSSL_ERR_X509_INVALID_ALG +
+                    POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+        if( trailer_field != 1 )
+            return( POLARSSL_ERR_X509_INVALID_ALG );
+    }
+    else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+        return( POLARSSL_ERR_X509_INVALID_ALG + ret );
+
+    if( p != end )
+        return( POLARSSL_ERR_X509_INVALID_ALG +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    return( 0 );
+}
+#endif /* POLARSSL_X509_RSASSA_PSS_SUPPORT */
+
+/*
+ *  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 &&
+        **p != ASN1_BIT_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 );
+}
+
+/*
+ *  Name ::= CHOICE { -- only one possibility for now --
+ *       rdnSequence  RDNSequence }
+ *
+ *  RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+ *
+ *  RelativeDistinguishedName ::=
+ *    SET OF AttributeTypeAndValue
+ *
+ *  AttributeTypeAndValue ::= SEQUENCE {
+ *    type     AttributeType,
+ *    value    AttributeValue }
+ *
+ *  AttributeType ::= OBJECT IDENTIFIER
+ *
+ *  AttributeValue ::= ANY DEFINED BY AttributeType
+ *
+ * The data structure is optimized for the common case where each RDN has only
+ * one element, which is represented as a list of AttributeTypeAndValue.
+ * For the general case we still use a flat list, but we mark elements of the
+ * same set so that they are "merged" together in the functions that consume
+ * this list, eg x509_dn_gets().
+ */
+int x509_get_name( unsigned char **p, const unsigned char *end,
+                   x509_name *cur )
+{
+    int ret;
+    size_t set_len;
+    const unsigned char *end_set;
+
+    /* don't use recursion, we'd risk stack overflow if not optimized */
+    while( 1 )
+    {
+        /*
+         * parse SET
+         */
+        if( ( ret = asn1_get_tag( p, end, &set_len,
+                ASN1_CONSTRUCTED | ASN1_SET ) ) != 0 )
+            return( POLARSSL_ERR_X509_INVALID_NAME + ret );
+
+        end_set  = *p + set_len;
+
+        while( 1 )
+        {
+            if( ( ret = x509_get_attr_type_value( p, end_set, cur ) ) != 0 )
+                return( ret );
+
+            if( *p == end_set )
+                break;
+
+            /* Mark this item as being not the only one in a set */
+            cur->next_merged = 1;
+
+            cur->next = polarssl_malloc( sizeof( x509_name ) );
+
+            if( cur->next == NULL )
+                return( POLARSSL_ERR_X509_MALLOC_FAILED );
+
+            memset( cur->next, 0, sizeof( x509_name ) );
+
+            cur = cur->next;
+        }
+
+        /*
+         * continue until end of SEQUENCE is reached
+         */
+        if( *p == end )
+            return( 0 );
+
+        cur->next = polarssl_malloc( sizeof( x509_name ) );
+
+        if( cur->next == NULL )
+            return( POLARSSL_ERR_X509_MALLOC_FAILED );
+
+        memset( cur->next, 0, sizeof( x509_name ) );
+
+        cur = cur->next;
+    }
+}
+
+static int x509_parse_int(unsigned char **p, unsigned n, int *res){
+    *res = 0;
+    for( ; n > 0; --n ){
+        if( ( **p < '0') || ( **p > '9' ) ) return POLARSSL_ERR_X509_INVALID_DATE;
+        *res *= 10;
+        *res += (*(*p)++ - '0');
+    }
+    return 0;
+}
+
+/*
+ *  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;
+    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 );
+
+        CHECK( x509_parse_int( p, 2, &time->year ) );
+        CHECK( x509_parse_int( p, 2, &time->mon ) );
+        CHECK( x509_parse_int( p, 2, &time->day ) );
+        CHECK( x509_parse_int( p, 2, &time->hour ) );
+        CHECK( x509_parse_int( p, 2, &time->min ) );
+        if( len > 10 )
+            CHECK( x509_parse_int( p, 2, &time->sec ) );
+        if( len > 12 && *(*p)++ != 'Z' )
+            return( POLARSSL_ERR_X509_INVALID_DATE );
+
+        time->year +=  100 * ( time->year < 50 );
+        time->year += 1900;
+
+        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 );
+
+        CHECK( x509_parse_int( p, 4, &time->year ) );
+        CHECK( x509_parse_int( p, 2, &time->mon ) );
+        CHECK( x509_parse_int( p, 2, &time->day ) );
+        CHECK( x509_parse_int( p, 2, &time->hour ) );
+        CHECK( x509_parse_int( p, 2, &time->min ) );
+        if( len > 12 )
+            CHECK( x509_parse_int( p, 2, &time->sec ) );
+        if( len > 14 && *(*p)++ != 'Z' )
+            return( POLARSSL_ERR_X509_INVALID_DATE );
+
+        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 );
+}
+
+/*
+ * Get signature algorithm from alg OID and optional parameters
+ */
+int x509_get_sig_alg( const x509_buf *sig_oid, const x509_buf *sig_params,
+                      md_type_t *md_alg, pk_type_t *pk_alg,
+                      void **sig_opts )
+{
+    int ret;
+
+    if( *sig_opts != NULL )
+        return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
+
+    if( ( ret = oid_get_sig_alg( sig_oid, md_alg, pk_alg ) ) != 0 )
+        return( POLARSSL_ERR_X509_UNKNOWN_SIG_ALG + ret );
+
+#if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT)
+    if( *pk_alg == POLARSSL_PK_RSASSA_PSS )
+    {
+        pk_rsassa_pss_options *pss_opts;
+
+        pss_opts = polarssl_malloc( sizeof( pk_rsassa_pss_options ) );
+        if( pss_opts == NULL )
+            return( POLARSSL_ERR_X509_MALLOC_FAILED );
+
+        ret = x509_get_rsassa_pss_params( sig_params,
+                                          md_alg,
+                                          &pss_opts->mgf1_hash_id,
+                                          &pss_opts->expected_salt_len );
+        if( ret != 0 )
+        {
+            polarssl_free( pss_opts );
+            return( ret );
+        }
+
+        *sig_opts = (void *) pss_opts;
+    }
+    else
+#endif /* POLARSSL_X509_RSASSA_PSS_SUPPORT */
+    {
+        /* Make sure parameters are absent or NULL */
+        if( ( sig_params->tag != ASN1_NULL && sig_params->tag != 0 ) ||
+              sig_params->len != 0 )
+        return( POLARSSL_ERR_X509_INVALID_ALG );
+    }
+
+    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(_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, merge = 0;
+    const x509_name *name;
+    const char *short_name = NULL;
+    char s[X509_MAX_DN_NAME_SIZE], *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 = polarssl_snprintf( p, n, merge ? " + " : ", " );
+            SAFE_SNPRINTF();
+        }
+
+        ret = oid_get_attr_short_name( &name->oid, &short_name );
+
+        if( ret == 0 )
+            ret = polarssl_snprintf( p, n, "%s=", short_name );
+        else
+            ret = polarssl_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 = polarssl_snprintf( p, n, "%s", s );
+        SAFE_SNPRINTF();
+
+        merge = name->next_merged;
+        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 = polarssl_snprintf( p, n, "%02X%s",
+                serial->p[i], ( i < nr - 1 ) ? ":" : "" );
+        SAFE_SNPRINTF();
+    }
+
+    if( nr != serial->len )
+    {
+        ret = polarssl_snprintf( p, n, "...." );
+        SAFE_SNPRINTF();
+    }
+
+    return( (int) ( size - n ) );
+}
+
+/*
+ * Helper for writing signature algorithms
+ */
+int x509_sig_alg_gets( char *buf, size_t size, const x509_buf *sig_oid,
+                       pk_type_t pk_alg, md_type_t md_alg,
+                       const void *sig_opts )
+{
+    int ret;
+    char *p = buf;
+    size_t n = size;
+    const char *desc = NULL;
+
+    ret = oid_get_sig_alg_desc( sig_oid, &desc );
+    if( ret != 0 )
+        ret = polarssl_snprintf( p, n, "???"  );
+    else
+        ret = polarssl_snprintf( p, n, "%s", desc );
+    SAFE_SNPRINTF();
+
+#if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT)
+    if( pk_alg == POLARSSL_PK_RSASSA_PSS )
+    {
+        const pk_rsassa_pss_options *pss_opts;
+        const md_info_t *md_info, *mgf_md_info;
+
+        pss_opts = (const pk_rsassa_pss_options *) sig_opts;
+
+        md_info = md_info_from_type( md_alg );
+        mgf_md_info = md_info_from_type( pss_opts->mgf1_hash_id );
+
+        ret = polarssl_snprintf( p, n, " (%s, MGF1-%s, 0x%02X)",
+                              md_info ? md_info->name : "???",
+                              mgf_md_info ? mgf_md_info->name : "???",
+                              pss_opts->expected_salt_len );
+        SAFE_SNPRINTF();
+    }
+#else
+    ((void) pk_alg);
+    ((void) md_alg);
+    ((void) sig_opts);
+#endif /* POLARSSL_X509_RSASSA_PSS_SUPPORT */
+
+    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 = polarssl_snprintf( p, n, "%s key size", name );
+    SAFE_SNPRINTF();
+
+    return( 0 );
+}
+
+/*
+ * Return an informational string describing the given OID
+ */
+#if ! defined(POLARSSL_DEPRECATED_REMOVED)
+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 );
+}
+#endif
+
+/* Return the x.y.z.... style numeric string for the given OID */
+#if ! defined(POLARSSL_DEPRECATED_REMOVED)
+int x509_oid_get_numeric_string( char *buf, size_t size, x509_buf *oid )
+{
+    return oid_get_numeric_string( buf, size, oid );
+}
+#endif
+
+/*
+ * 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/polarssl/x509_create.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,344 @@
+/*
+ *  X.509 base functions for creating certificates / CSRs
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.h>
+
+#if defined(_MSC_VER) && !defined strncasecmp && !defined(EFIX64) && \
+    !defined(EFI32)
+#define strncasecmp _strnicmp
+#endif
+
+typedef struct {
+    const char *name;
+    size_t name_len;
+    const char*oid;
+} x509_attr_descriptor_t;
+
+#define ADD_STRLEN( s )     s, sizeof( s ) - 1
+
+static const x509_attr_descriptor_t x509_attrs[] =
+{
+    { ADD_STRLEN( "CN" ),                       OID_AT_CN },
+    { ADD_STRLEN( "commonName" ),               OID_AT_CN },
+    { ADD_STRLEN( "C" ),                        OID_AT_COUNTRY },
+    { ADD_STRLEN( "countryName" ),              OID_AT_COUNTRY },
+    { ADD_STRLEN( "O" ),                        OID_AT_ORGANIZATION },
+    { ADD_STRLEN( "organizationName" ),         OID_AT_ORGANIZATION },
+    { ADD_STRLEN( "L" ),                        OID_AT_LOCALITY },
+    { ADD_STRLEN( "locality" ),                 OID_AT_LOCALITY },
+    { ADD_STRLEN( "R" ),                        OID_PKCS9_EMAIL },
+    { ADD_STRLEN( "OU" ),                       OID_AT_ORG_UNIT },
+    { ADD_STRLEN( "organizationalUnitName" ),   OID_AT_ORG_UNIT },
+    { ADD_STRLEN( "ST" ),                       OID_AT_STATE },
+    { ADD_STRLEN( "stateOrProvinceName" ),      OID_AT_STATE },
+    { ADD_STRLEN( "emailAddress" ),             OID_PKCS9_EMAIL },
+    { ADD_STRLEN( "serialNumber" ),             OID_AT_SERIAL_NUMBER },
+    { ADD_STRLEN( "postalAddress" ),            OID_AT_POSTAL_ADDRESS },
+    { ADD_STRLEN( "postalCode" ),               OID_AT_POSTAL_CODE },
+    { ADD_STRLEN( "dnQualifier" ),              OID_AT_DN_QUALIFIER },
+    { ADD_STRLEN( "title" ),                    OID_AT_TITLE },
+    { ADD_STRLEN( "surName" ),                  OID_AT_SUR_NAME },
+    { ADD_STRLEN( "SN" ),                       OID_AT_SUR_NAME },
+    { ADD_STRLEN( "givenName" ),                OID_AT_GIVEN_NAME },
+    { ADD_STRLEN( "GN" ),                       OID_AT_GIVEN_NAME },
+    { ADD_STRLEN( "initials" ),                 OID_AT_INITIALS },
+    { ADD_STRLEN( "pseudonym" ),                OID_AT_PSEUDONYM },
+    { ADD_STRLEN( "generationQualifier" ),      OID_AT_GENERATION_QUALIFIER },
+    { ADD_STRLEN( "domainComponent" ),          OID_DOMAIN_COMPONENT },
+    { ADD_STRLEN( "DC" ),                       OID_DOMAIN_COMPONENT },
+    { NULL, 0, NULL }
+};
+
+static const char *x509_at_oid_from_name( const char *name, size_t name_len )
+{
+    const x509_attr_descriptor_t *cur;
+
+    for( cur = x509_attrs; cur->name != NULL; cur++ )
+        if( cur->name_len == name_len &&
+            strncasecmp( cur->name, name, name_len ) == 0 )
+            break;
+
+    return( cur->oid );
+}
+
+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;
+    char data[X509_MAX_DN_NAME_SIZE];
+    char *d = data;
+
+    /* Clear existing chain if present */
+    asn1_free_named_data_list( head );
+
+    while( c <= end )
+    {
+        if( in_tag && *c == '=' )
+        {
+            if( ( oid = x509_at_oid_from_name( s, c - s ) ) == NULL )
+            {
+                ret = POLARSSL_ERR_X509_UNKNOWN_OID;
+                goto exit;
+            }
+
+            s = c + 1;
+            in_tag = 0;
+            d = data;
+        }
+
+        if( !in_tag && *c == '\\' && c != end )
+        {
+            c++;
+
+            /* Check for valid escaped characters */
+            if( c == end || *c != ',' )
+            {
+                ret = POLARSSL_ERR_X509_INVALID_NAME;
+                goto exit;
+            }
+        }
+        else if( !in_tag && ( *c == ',' || c == end ) )
+        {
+            if( asn1_store_named_data( head, oid, strlen( oid ),
+                                       (unsigned char *) data,
+                                       d - data ) == NULL )
+            {
+                return( POLARSSL_ERR_X509_MALLOC_FAILED );
+            }
+
+            while( c < end && *(c + 1) == ' ' )
+                c++;
+
+            s = c + 1;
+            in_tag = 1;
+        }
+
+        if( !in_tag && s != c + 1 )
+        {
+            *(d++) = *c;
+
+            if( d - data == X509_MAX_DN_NAME_SIZE )
+            {
+                ret = POLARSSL_ERR_X509_INVALID_NAME;
+                goto exit;
+            }
+        }
+
+        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/polarssl/x509_crl.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,768 @@
+/*
+ *  X.509 Certidicate Revocation List (CRL) parsing
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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/rfc5280.txt (Certificates and CRLs)
+ *  http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs)
+ *  http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10)
+ *
+ *  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"
+
+#include <string.h>
+
+#if defined(POLARSSL_PEM_PARSE_C)
+#include "polarssl/pem.h"
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdlib.h>
+#include <stdio.h>
+#define polarssl_free       free
+#define polarssl_malloc     malloc
+#define polarssl_snprintf   snprintf
+#endif
+
+#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
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+/*
+ *  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 );
+
+            memset( cur_entry->next, 0, sizeof( x509_crl_entry ) );
+            cur_entry = cur_entry->next;
+        }
+    }
+
+    return( 0 );
+}
+
+/*
+ * Parse one  CRLs in DER format and append it to the chained list
+ */
+int x509_crl_parse_der( x509_crl *chain,
+                        const unsigned char *buf, size_t buflen )
+{
+    int ret;
+    size_t len;
+    unsigned char *p, *end;
+    x509_buf sig_params1, sig_params2;
+    x509_crl *crl = chain;
+
+    /*
+     * Check for valid input
+     */
+    if( crl == NULL || buf == NULL )
+        return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
+
+    memset( &sig_params1, 0, sizeof( x509_buf ) );
+    memset( &sig_params2, 0, sizeof( x509_buf ) );
+
+    /*
+     * Add new CRL on the end of the chain if needed.
+     */
+    while( crl->version != 0 && crl->next != NULL )
+        crl = crl->next;
+
+    if( crl->version != 0 && crl->next == NULL )
+    {
+        crl->next = polarssl_malloc( sizeof( x509_crl ) );
+
+        if( crl->next == NULL )
+        {
+            x509_crl_free( crl );
+            return( POLARSSL_ERR_X509_MALLOC_FAILED );
+        }
+
+        x509_crl_init( crl->next );
+        crl = crl->next;
+    }
+
+    /*
+     * Copy raw DER-encoded CRL
+     */
+    if( ( p = polarssl_malloc( buflen ) ) == NULL )
+        return( POLARSSL_ERR_X509_MALLOC_FAILED );
+
+    memcpy( p, buf, buflen );
+
+    crl->raw.p = p;
+    crl->raw.len = buflen;
+
+    end = p + buflen;
+
+    /*
+     * 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( &p, end, &crl->sig_oid1, &sig_params1 ) ) != 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, &sig_params1,
+                                  &crl->sig_md, &crl->sig_pk,
+                                  &crl->sig_opts ) ) != 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( &p, end, &crl->sig_oid2, &sig_params2 ) ) != 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 ||
+        sig_params1.len != sig_params2.len ||
+        ( sig_params1.len != 0 &&
+          memcmp( sig_params1.p, sig_params2.p, sig_params1.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 );
+    }
+
+    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 )
+{
+#if defined(POLARSSL_PEM_PARSE_C)
+    int ret;
+    size_t use_len;
+    pem_context pem;
+    int is_pem = 0;
+
+    if( chain == NULL || buf == NULL )
+        return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
+
+    do
+    {
+        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
+             */
+            is_pem = 1;
+
+            buflen -= use_len;
+            buf += use_len;
+
+            if( ( ret = x509_crl_parse_der( chain,
+                                            pem.buf, pem.buflen ) ) != 0 )
+            {
+                return( ret );
+            }
+
+            pem_free( &pem );
+        }
+        else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
+        {
+            pem_free( &pem );
+            return( ret );
+        }
+    }
+    while( is_pem && buflen > 0 );
+
+    if( is_pem )
+        return( 0 );
+    else
+#endif /* POLARSSL_PEM_PARSE_C */
+        return( x509_crl_parse_der( chain, buf, buflen ) );
+}
+
+#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 = pk_load_file( path, &buf, &n ) ) != 0 )
+        return( ret );
+
+    ret = x509_crl_parse( chain, buf, n );
+
+    polarssl_zeroize( buf, 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 x509_crl_entry *entry;
+
+    p = buf;
+    n = size;
+
+    ret = polarssl_snprintf( p, n, "%sCRL version   : %d",
+                               prefix, crl->version );
+    SAFE_SNPRINTF();
+
+    ret = polarssl_snprintf( p, n, "\n%sissuer name   : ", prefix );
+    SAFE_SNPRINTF();
+    ret = x509_dn_gets( p, n, &crl->issuer );
+    SAFE_SNPRINTF();
+
+    ret = polarssl_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 = polarssl_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 = polarssl_snprintf( p, n, "\n%sRevoked certificates:",
+                               prefix );
+    SAFE_SNPRINTF();
+
+    while( entry != NULL && entry->raw.len != 0 )
+    {
+        ret = polarssl_snprintf( p, n, "\n%sserial number: ",
+                               prefix );
+        SAFE_SNPRINTF();
+
+        ret = x509_serial_gets( p, n, &entry->serial );
+        SAFE_SNPRINTF();
+
+        ret = polarssl_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 = polarssl_snprintf( p, n, "\n%ssigned using  : ", prefix );
+    SAFE_SNPRINTF();
+
+    ret = x509_sig_alg_gets( p, n, &crl->sig_oid1, crl->sig_pk, crl->sig_md,
+                             crl->sig_opts );
+    SAFE_SNPRINTF();
+
+    ret = polarssl_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
+    {
+#if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT)
+        polarssl_free( crl_cur->sig_opts );
+#endif
+
+        name_cur = crl_cur->issuer.next;
+        while( name_cur != NULL )
+        {
+            name_prv = name_cur;
+            name_cur = name_cur->next;
+            polarssl_zeroize( name_prv, 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;
+            polarssl_zeroize( entry_prv, sizeof( x509_crl_entry ) );
+            polarssl_free( entry_prv );
+        }
+
+        if( crl_cur->raw.p != NULL )
+        {
+            polarssl_zeroize( crl_cur->raw.p, 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;
+
+        polarssl_zeroize( crl_prv, 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/polarssl/x509_crt.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,2158 @@
+/*
+ *  X.509 certificate parsing and verification
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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/rfc5280.txt (Certificates and CRLs)
+ *  http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs)
+ *  http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10)
+ *
+ *  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"
+
+#include <stdio.h>
+#include <string.h>
+
+#if defined(POLARSSL_PEM_PARSE_C)
+#include "polarssl/pem.h"
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdlib.h>
+#define polarssl_free       free
+#define polarssl_malloc     malloc
+#define polarssl_snprintf   snprintf
+#endif
+
+#if defined(POLARSSL_THREADING_C)
+#include "polarssl/threading.h"
+#endif
+
+#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
+#include <windows.h>
+#else
+#include <time.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 /* !_WIN32 || EFIX64 || EFI32 */
+#endif
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+/*
+ *  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: we only parse and use 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 )
+        {
+            if( cur->next != NULL )
+                return( POLARSSL_ERR_X509_INVALID_EXTENSIONS );
+
+            cur->next = 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;
+        }
+
+        /* Forbid repeated extensions */
+        if( ( crt->ext_types & ext_type ) != 0 )
+            return( POLARSSL_ERR_X509_INVALID_EXTENSIONS );
+
+        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;
+    x509_buf sig_params1, sig_params2;
+
+    memset( &sig_params1, 0, sizeof( x509_buf ) );
+    memset( &sig_params2, 0, sizeof( x509_buf ) );
+
+    /*
+     * Check for valid input
+     */
+    if( crt == NULL || buf == NULL )
+        return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
+
+    p = 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(      &p, end, &crt->sig_oid1,
+                                            &sig_params1 ) ) != 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, &sig_params1,
+                                  &crt->sig_md, &crt->sig_pk,
+                                  &crt->sig_opts ) ) != 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( &p, end, &crt->sig_oid2, &sig_params2 ) ) != 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 ||
+        sig_params1.len != sig_params2.len ||
+        ( sig_params1.len != 0 &&
+          memcmp( sig_params1.p, sig_params2.p, sig_params1.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 = polarssl_malloc( sizeof( x509_crt ) );
+
+        if( crt->next == NULL )
+            return( POLARSSL_ERR_X509_MALLOC_FAILED );
+
+        prev = crt;
+        x509_crt_init( crt->next );
+        crt = crt->next;
+    }
+
+    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;
+
+                total_failed++;
+                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 = pk_load_file( path, &buf, &n ) ) != 0 )
+        return( ret );
+
+    ret = x509_crt_parse( chain, buf, n );
+
+    polarssl_zeroize( buf, 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 );
+    if( w_ret == 0 )
+        return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
+
+    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 );
+        if( w_ret == 0 )
+            return( POLARSSL_ERR_X509_FILE_IO_ERROR );
+
+        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 )
+    {
+        polarssl_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 = polarssl_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 = polarssl_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;
+    char key_size_str[BEFORE_COLON];
+
+    p = buf;
+    n = size;
+
+    ret = polarssl_snprintf( p, n, "%scert. version     : %d\n",
+                               prefix, crt->version );
+    SAFE_SNPRINTF();
+    ret = polarssl_snprintf( p, n, "%sserial number     : ",
+                               prefix );
+    SAFE_SNPRINTF();
+
+    ret = x509_serial_gets( p, n, &crt->serial );
+    SAFE_SNPRINTF();
+
+    ret = polarssl_snprintf( p, n, "\n%sissuer name       : ", prefix );
+    SAFE_SNPRINTF();
+    ret = x509_dn_gets( p, n, &crt->issuer  );
+    SAFE_SNPRINTF();
+
+    ret = polarssl_snprintf( p, n, "\n%ssubject name      : ", prefix );
+    SAFE_SNPRINTF();
+    ret = x509_dn_gets( p, n, &crt->subject );
+    SAFE_SNPRINTF();
+
+    ret = polarssl_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 = polarssl_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 = polarssl_snprintf( p, n, "\n%ssigned using      : ", prefix );
+    SAFE_SNPRINTF();
+
+    ret = x509_sig_alg_gets( p, n, &crt->sig_oid1, crt->sig_pk,
+                             crt->sig_md, crt->sig_opts );
+    SAFE_SNPRINTF();
+
+    /* Key size */
+    if( ( ret = x509_key_size_helper( key_size_str, BEFORE_COLON,
+                                      pk_get_name( &crt->pk ) ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    ret = polarssl_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 = polarssl_snprintf( p, n, "\n%sbasic constraints : CA=%s", prefix,
+                        crt->ca_istrue ? "true" : "false" );
+        SAFE_SNPRINTF();
+
+        if( crt->max_pathlen > 0 )
+        {
+            ret = polarssl_snprintf( p, n, ", max_pathlen=%d", crt->max_pathlen - 1 );
+            SAFE_SNPRINTF();
+        }
+    }
+
+    if( crt->ext_types & EXT_SUBJECT_ALT_NAME )
+    {
+        ret = polarssl_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 = polarssl_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 = polarssl_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 = polarssl_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 = polarssl_snprintf( p, n, "\n" );
+    SAFE_SNPRINTF();
+
+    return( (int) ( size - n ) );
+}
+
+struct x509_crt_verify_string {
+    int code;
+    const char *string;
+};
+
+static const struct x509_crt_verify_string x509_crt_verify_strings[] = {
+    { BADCERT_EXPIRED,       "The certificate validity has expired" },
+    { BADCERT_REVOKED,       "The certificate has been revoked (is on a CRL)" },
+    { BADCERT_CN_MISMATCH,   "The certificate Common Name (CN) does not match with the expected CN" },
+    { BADCERT_NOT_TRUSTED,   "The certificate is not correctly signed by the trusted CA" },
+    { BADCRL_NOT_TRUSTED,    "The CRL is not correctly signed by the trusted CA" },
+    { BADCRL_EXPIRED,        "The CRL is expired" },
+    { BADCERT_MISSING,       "Certificate was missing" },
+    { BADCERT_SKIP_VERIFY,   "Certificate verification was skipped" },
+    { BADCERT_OTHER,         "Other reason (can be used by verify callback)" },
+    { BADCERT_FUTURE,        "The certificate validity starts in the future" },
+    { BADCRL_FUTURE,         "The CRL is from the future" },
+    { BADCERT_KEY_USAGE,     "Usage does not match the keyUsage extension" },
+    { BADCERT_EXT_KEY_USAGE, "Usage does not match the extendedKeyUsage extension" },
+    { BADCERT_NS_CERT_TYPE,  "Usage does not match the nsCertType extension" },
+    { 0, NULL }
+};
+
+int x509_crt_verify_info( char *buf, size_t size, const char *prefix,
+                          int flags )
+{
+    int ret;
+    const struct x509_crt_verify_string *cur;
+    char *p = buf;
+    size_t n = size;
+
+    for( cur = x509_crt_verify_strings; cur->string != NULL ; cur++ )
+    {
+        if( ( flags & cur->code ) == 0 )
+            continue;
+
+        ret = polarssl_snprintf( p, n, "%s%s\n", prefix, cur->string );
+        SAFE_SNPRINTF();
+        flags ^= cur->code;
+    }
+
+    if( flags != 0 )
+    {
+        ret = polarssl_snprintf( p, n, "%sUnknown reason "
+                                       "(this should not happen)\n", prefix );
+        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_verify_ext( crl_list->sig_pk, crl_list->sig_opts, &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 */
+
+/*
+ * Like memcmp, but case-insensitive and always returns -1 if different
+ */
+static int x509_memcasecmp( 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 );
+}
+
+/*
+ * Return 1 if match, 0 if not
+ * TODO: inverted return value!
+ */
+static int x509_wildcard_verify( const char *cn, x509_buf *name )
+{
+    size_t i;
+    size_t cn_idx = 0, cn_len = strlen( cn );
+
+    if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' )
+        return( 0 );
+
+    for( i = 0; i < cn_len; ++i )
+    {
+        if( cn[i] == '.' )
+        {
+            cn_idx = i;
+            break;
+        }
+    }
+
+    if( cn_idx == 0 )
+        return( 0 );
+
+    if( cn_len - cn_idx == name->len - 1 &&
+        x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 )
+    {
+        return( 1 );
+    }
+
+    return( 0 );
+}
+
+/*
+ * Compare two X.509 strings, case-insensitive, and allowing for some encoding
+ * variations (but not all).
+ *
+ * Return 0 if equal, -1 otherwise.
+ */
+static int x509_string_cmp( const x509_buf *a, const x509_buf *b )
+{
+    if( a->tag == b->tag &&
+        a->len == b->len &&
+        memcmp( a->p, b->p, b->len ) == 0 )
+    {
+        return( 0 );
+    }
+
+    if( ( a->tag == ASN1_UTF8_STRING || a->tag == ASN1_PRINTABLE_STRING ) &&
+        ( b->tag == ASN1_UTF8_STRING || b->tag == ASN1_PRINTABLE_STRING ) &&
+        a->len == b->len &&
+        x509_memcasecmp( a->p, b->p, b->len ) == 0 )
+    {
+        return( 0 );
+    }
+
+    return( -1 );
+}
+
+/*
+ * Compare two X.509 Names (aka rdnSequence).
+ *
+ * See RFC 5280 section 7.1, though we don't implement the whole algorithm:
+ * we sometimes return unequal when the full algorithm would return equal,
+ * but never the other way. (In particular, we don't do Unicode normalisation
+ * or space folding.)
+ *
+ * Return 0 if equal, -1 otherwise.
+ */
+static int x509_name_cmp( const x509_name *a, const x509_name *b )
+{
+    /* Avoid recursion, it might not be optimised by the compiler */
+    while( a != NULL || b != NULL )
+    {
+        if( a == NULL || b == NULL )
+            return( -1 );
+
+        /* type */
+        if( a->oid.tag != b->oid.tag ||
+            a->oid.len != b->oid.len ||
+            memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 )
+        {
+            return( -1 );
+        }
+
+        /* value */
+        if( x509_string_cmp( &a->val, &b->val ) != 0 )
+            return( -1 );
+
+        /* structure of the list of sets */
+        if( a->next_merged != b->next_merged )
+            return( -1 );
+
+        a = a->next;
+        b = b->next;
+    }
+
+    /* a == NULL == b */
+    return( 0 );
+}
+
+/*
+ * Check if 'parent' is a suitable parent (signing CA) for 'child'.
+ * Return 0 if yes, -1 if not.
+ *
+ * top means parent is a locally-trusted certificate
+ * bottom means child is the end entity cert
+ */
+static int x509_crt_check_parent( const x509_crt *child,
+                                  const x509_crt *parent,
+                                  int top, int bottom )
+{
+    int need_ca_bit;
+
+    /* Parent must be the issuer */
+    if( x509_name_cmp( &child->issuer, &parent->subject ) != 0 )
+        return( -1 );
+
+    /* Parent must have the basicConstraints CA bit set as a general rule */
+    need_ca_bit = 1;
+
+    /* Exception: v1/v2 certificates that are locally trusted. */
+    if( top && parent->version < 3 )
+        need_ca_bit = 0;
+
+    /* Exception: self-signed end-entity certs that are locally trusted. */
+    if( top && bottom &&
+        child->raw.len == parent->raw.len &&
+        memcmp( child->raw.p, parent->raw.p, child->raw.len ) == 0 )
+    {
+        need_ca_bit = 0;
+    }
+
+    if( need_ca_bit && ! parent->ca_istrue )
+        return( -1 );
+
+#if defined(POLARSSL_X509_CHECK_KEY_USAGE)
+    if( need_ca_bit &&
+        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;
+    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, 1, path_cnt == 0 ) != 0 )
+            continue;
+
+        check_path_cnt = path_cnt + 1;
+
+        /*
+         * Reduce check_path_cnt 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_verify_ext( child->sig_pk, child->sig_opts, &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;
+
+    /* path_cnt is 0 for the first intermediate CA */
+    if( 1 + path_cnt > POLARSSL_X509_MAX_INTERMEDIATE_CA )
+    {
+        *flags |= BADCERT_NOT_TRUSTED;
+        return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
+    }
+
+    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_verify_ext( child->sig_pk, child->sig_opts, &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, path_cnt == 0 ) == 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_memcasecmp( 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_memcasecmp( 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, pathlen == 0 ) == 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 );
+
+#if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT)
+        polarssl_free( cert_cur->sig_opts );
+#endif
+
+        name_cur = cert_cur->issuer.next;
+        while( name_cur != NULL )
+        {
+            name_prv = name_cur;
+            name_cur = name_cur->next;
+            polarssl_zeroize( name_prv, 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;
+            polarssl_zeroize( name_prv, 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;
+            polarssl_zeroize( seq_prv, 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;
+            polarssl_zeroize( seq_prv, sizeof( x509_sequence ) );
+            polarssl_free( seq_prv );
+        }
+
+        if( cert_cur->raw.p != NULL )
+        {
+            polarssl_zeroize( cert_cur->raw.p, 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;
+
+        polarssl_zeroize( cert_prv, 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/polarssl/x509_csr.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,466 @@
+/*
+ *  X.509 Certificate Signing Request (CSR) parsing
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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/rfc5280.txt (Certificates and CRLs)
+ *  http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs)
+ *  http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10)
+ *
+ *  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"
+
+#include <string.h>
+
+#if defined(POLARSSL_PEM_PARSE_C)
+#include "polarssl/pem.h"
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdlib.h>
+#include <stdio.h>
+#define polarssl_free       free
+#define polarssl_malloc     malloc
+#define polarssl_snprintf   snprintf
+#endif
+
+#if defined(POLARSSL_FS_IO) || defined(EFIX64) || defined(EFI32)
+#include <stdio.h>
+#endif
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+/*
+ *  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 in DER format
+ */
+int x509_csr_parse_der( x509_csr *csr,
+                        const unsigned char *buf, size_t buflen )
+{
+    int ret;
+    size_t len;
+    unsigned char *p, *end;
+    x509_buf sig_params;
+
+    memset( &sig_params, 0, sizeof( x509_buf ) );
+
+    /*
+     * Check for valid input
+     */
+    if( csr == NULL || buf == NULL )
+        return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
+
+    x509_csr_init( csr );
+
+    /*
+     * first copy the raw DER data
+     */
+    p = 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( &p, end, &csr->sig_oid, &sig_params ) ) != 0 )
+    {
+        x509_csr_free( csr );
+        return( ret );
+    }
+
+    if( ( ret = x509_get_sig_alg( &csr->sig_oid, &sig_params,
+                                  &csr->sig_md, &csr->sig_pk,
+                                  &csr->sig_opts ) ) != 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 );
+}
+
+/*
+ * Parse a CSR, allowing for PEM or raw DER encoding
+ */
+int x509_csr_parse( x509_csr *csr, const unsigned char *buf, size_t buflen )
+{
+    int ret;
+#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 );
+
+#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, parse the result
+         */
+        if( ( ret = x509_csr_parse_der( csr, pem.buf, pem.buflen ) ) != 0 )
+            return( ret );
+
+        pem_free( &pem );
+        return( 0 );
+    }
+    else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
+    {
+        pem_free( &pem );
+        return( ret );
+    }
+    else
+#endif /* POLARSSL_PEM_PARSE_C */
+    return( x509_csr_parse_der( csr, buf, buflen ) );
+}
+
+#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 = pk_load_file( path, &buf, &n ) ) != 0 )
+        return( ret );
+
+    ret = x509_csr_parse( csr, buf, n );
+
+    polarssl_zeroize( buf, 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;
+    char key_size_str[BEFORE_COLON];
+
+    p = buf;
+    n = size;
+
+    ret = polarssl_snprintf( p, n, "%sCSR version   : %d",
+                               prefix, csr->version );
+    SAFE_SNPRINTF();
+
+    ret = polarssl_snprintf( p, n, "\n%ssubject name  : ", prefix );
+    SAFE_SNPRINTF();
+    ret = x509_dn_gets( p, n, &csr->subject );
+    SAFE_SNPRINTF();
+
+    ret = polarssl_snprintf( p, n, "\n%ssigned using  : ", prefix );
+    SAFE_SNPRINTF();
+
+    ret = x509_sig_alg_gets( p, n, &csr->sig_oid, csr->sig_pk, csr->sig_md,
+                             csr->sig_opts );
+    SAFE_SNPRINTF();
+
+    if( ( ret = x509_key_size_helper( key_size_str, BEFORE_COLON,
+                                      pk_get_name( &csr->pk ) ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    ret = polarssl_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 );
+
+#if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT)
+    polarssl_free( csr->sig_opts );
+#endif
+
+    name_cur = csr->subject.next;
+    while( name_cur != NULL )
+    {
+        name_prv = name_cur;
+        name_cur = name_cur->next;
+        polarssl_zeroize( name_prv, sizeof( x509_name ) );
+        polarssl_free( name_prv );
+    }
+
+    if( csr->raw.p != NULL )
+    {
+        polarssl_zeroize( csr->raw.p, csr->raw.len );
+        polarssl_free( csr->raw.p );
+    }
+
+    polarssl_zeroize( csr, sizeof( x509_csr ) );
+}
+
+#endif /* POLARSSL_X509_CSR_PARSE_C */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/polarssl/x509write_crt.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,452 @@
+/*
+ *  X.509 certificate writing
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.h>
+
+#if defined(POLARSSL_PEM_WRITE_C)
+#include "polarssl/pem.h"
+#endif /* POLARSSL_PEM_WRITE_C */
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+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 );
+
+    polarssl_zeroize( ctx, 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/polarssl/x509write_csr.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,258 @@
+/*
+ *  X.509 Certificate Signing Request writing
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.h>
+#include <stdlib.h>
+
+#if defined(POLARSSL_PEM_WRITE_C)
+#include "polarssl/pem.h"
+#endif
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+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 );
+
+    polarssl_zeroize( ctx, 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/polarssl/xtea.c	Thu Jun 11 03:27:03 2015 +0000
@@ -0,0 +1,283 @@
+/*
+ *  An 32-bit implementation of the XTEA algorithm
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  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"
+
+#include <string.h>
+
+#if defined(POLARSSL_SELF_TEST)
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdio.h>
+#define polarssl_printf printf
+#endif /* POLARSSL_PLATFORM_C */
+#endif /* POLARSSL_SELF_TEST */
+
+#if !defined(POLARSSL_XTEA_ALT)
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+/*
+ * 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
+
+void xtea_init( xtea_context *ctx )
+{
+    memset( ctx, 0, sizeof( xtea_context ) );
+}
+
+void xtea_free( xtea_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    polarssl_zeroize( ctx, sizeof( xtea_context ) );
+}
+
+/*
+ * 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)
+
+/*
+ * 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, ret = 0;
+    unsigned char buf[8];
+    xtea_context ctx;
+
+    xtea_init( &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" );
+
+            ret = 1;
+            goto exit;
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+exit:
+    xtea_free( &ctx );
+
+    return( ret );
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_XTEA_C */
+